summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2014-01-12 15:31:42 -0800
committerMarcel Holtmann <marcel@holtmann.org>2014-01-12 15:31:42 -0800
commit9d34d000b8f225eb2bf0993fb7b0c907e910e6ed (patch)
treee7de56c9adc34e64db7e7afd00bc1ca382b02cf2
parentc2e705d2e033ca0224f8dcc3262c04324f95c107 (diff)
shared: Integrate HCI userspace handling with IO abstraction
-rw-r--r--src/shared/hci.c116
1 files changed, 61 insertions, 55 deletions
diff --git a/src/shared/hci.c b/src/shared/hci.c
index d33320b37..1e4b58fa2 100644
--- a/src/shared/hci.c
+++ b/src/shared/hci.c
@@ -30,10 +30,11 @@
#include <string.h>
#include <sys/socket.h>
+#include "monitor/bt.h"
+#include "src/shared/io.h"
#include "src/shared/util.h"
#include "src/shared/queue.h"
#include "monitor/mainloop.h"
-#include "monitor/bt.h"
#include "hci.h"
@@ -56,8 +57,7 @@ struct hci_filter {
struct bt_hci {
int ref_count;
- int fd;
- bool close_on_unref;
+ struct io *io;
bool writer_active;
uint8_t num_cmds;
unsigned int next_cmd_id;
@@ -112,7 +112,7 @@ static void send_command(struct bt_hci *hci, uint16_t opcode,
uint8_t type = BT_H4_CMD_PKT;
struct bt_hci_cmd_hdr hdr;
struct iovec iov[3];
- int iovcnt;
+ int fd, iovcnt;
if (hci->num_cmds < 1)
return;
@@ -132,12 +132,32 @@ static void send_command(struct bt_hci *hci, uint16_t opcode,
} else
iovcnt = 2;
- if (writev(hci->fd, iov, iovcnt) < 0)
+ fd = io_get_fd(hci->io);
+ if (fd < 0)
+ return;
+
+ if (writev(fd, iov, iovcnt) < 0)
return;
hci->num_cmds--;
}
+static bool io_write_callback(struct io *io, void *user_data)
+{
+ struct bt_hci *hci = user_data;
+ struct cmd *cmd;
+
+ cmd = queue_pop_head(hci->cmd_queue);
+ if (cmd) {
+ send_command(hci, cmd->opcode, cmd->data, cmd->size);
+ queue_push_tail(hci->rsp_queue, cmd);
+ }
+
+ hci->writer_active = false;
+
+ return false;
+}
+
static void wakeup_writer(struct bt_hci *hci)
{
if (hci->writer_active)
@@ -149,23 +169,12 @@ static void wakeup_writer(struct bt_hci *hci)
if (queue_isempty(hci->cmd_queue))
return;
- if (mainloop_modify_fd(hci->fd, EPOLLIN | EPOLLOUT) < 0)
+ if (!io_set_write_handler(hci->io, io_write_callback, hci, NULL))
return;
hci->writer_active = true;
}
-static void suspend_writer(struct bt_hci *hci)
-{
- if (!hci->writer_active)
- return;
-
- if (mainloop_modify_fd(hci->fd, EPOLLIN) < 0)
- return;
-
- hci->writer_active = false;
-}
-
static bool match_cmd_opcode(const void *a, const void *b)
{
const struct cmd *cmd = a;
@@ -246,40 +255,31 @@ static void process_event(struct bt_hci *hci, const void *data, size_t size)
}
}
-static void io_callback(int fd, uint32_t events, void *user_data)
+static bool io_read_callback(struct io *io, void *user_data)
{
struct bt_hci *hci = user_data;
+ uint8_t buf[512];
+ ssize_t len;
+ int fd;
- if (events & (EPOLLERR | EPOLLHUP))
- return;
-
- if (events & EPOLLIN) {
- uint8_t buf[512];
- ssize_t len;
-
- len = read(hci->fd, buf, sizeof(buf));
- if (len < 0)
- return;
-
- if (len < 1)
- return;
+ fd = io_get_fd(hci->io);
+ if (fd < 0)
+ return false;
- switch (buf[0]) {
- case BT_H4_EVT_PKT:
- process_event(hci, buf + 1, len - 1);
- break;
- }
- } else if (events & EPOLLOUT) {
- struct cmd *cmd;
+ len = read(fd, buf, sizeof(buf));
+ if (len < 0)
+ return false;
- cmd = queue_pop_head(hci->cmd_queue);
- if (cmd) {
- send_command(hci, cmd->opcode, cmd->data, cmd->size);
- queue_push_tail(hci->rsp_queue, cmd);
- }
+ if (len < 1)
+ return true;
- suspend_writer(hci);
+ switch (buf[0]) {
+ case BT_H4_EVT_PKT:
+ process_event(hci, buf + 1, len - 1);
+ break;
}
+
+ return true;
}
struct bt_hci *bt_hci_new(int fd)
@@ -293,8 +293,12 @@ struct bt_hci *bt_hci_new(int fd)
if (!hci)
return NULL;
- hci->fd = fd;
- hci->close_on_unref = false;
+ hci->io = io_new(fd);
+ if (!hci->io) {
+ free(hci);
+ return NULL;
+ }
+
hci->writer_active = false;
hci->num_cmds = 1;
hci->next_cmd_id = 1;
@@ -302,6 +306,7 @@ struct bt_hci *bt_hci_new(int fd)
hci->cmd_queue = queue_new();
if (!hci->cmd_queue) {
+ io_destroy(hci->io);
free(hci);
return NULL;
}
@@ -309,6 +314,7 @@ struct bt_hci *bt_hci_new(int fd)
hci->rsp_queue = queue_new();
if (!hci->rsp_queue) {
queue_destroy(hci->cmd_queue, NULL);
+ io_destroy(hci->io);
free(hci);
return NULL;
}
@@ -317,14 +323,16 @@ struct bt_hci *bt_hci_new(int fd)
if (!hci->evt_list) {
queue_destroy(hci->rsp_queue, NULL);
queue_destroy(hci->cmd_queue, NULL);
+ io_destroy(hci->io);
free(hci);
return NULL;
}
- if (mainloop_add_fd(hci->fd, EPOLLIN, io_callback, hci, NULL) < 0) {
+ if (!io_set_read_handler(hci->io, io_read_callback, hci, NULL)) {
queue_destroy(hci->evt_list, NULL);
queue_destroy(hci->rsp_queue, NULL);
queue_destroy(hci->cmd_queue, NULL);
+ io_destroy(hci->io);
free(hci);
return NULL;
}
@@ -428,10 +436,7 @@ void bt_hci_unref(struct bt_hci *hci)
queue_destroy(hci->cmd_queue, cmd_free);
queue_destroy(hci->rsp_queue, cmd_free);
- mainloop_remove_fd(hci->fd);
-
- if (hci->close_on_unref)
- close(hci->fd);
+ io_destroy(hci->io);
free(hci);
}
@@ -441,9 +446,7 @@ bool bt_hci_set_close_on_unref(struct bt_hci *hci, bool do_close)
if (!hci)
return false;
- hci->close_on_unref = do_close;
-
- return true;
+ return io_set_close_on_destroy(hci->io, do_close);
}
unsigned int bt_hci_send(struct bt_hci *hci, uint16_t opcode,
@@ -528,7 +531,10 @@ bool bt_hci_flush(struct bt_hci *hci)
if (!hci)
return false;
- suspend_writer(hci);
+ if (hci->writer_active) {
+ io_set_write_handler(hci->io, NULL, NULL, NULL);
+ hci->writer_active = false;
+ }
queue_remove_all(hci->cmd_queue, NULL, NULL, cmd_free);
queue_remove_all(hci->rsp_queue, NULL, NULL, cmd_free);