diff options
author | Luiz Augusto von Dentz <luiz.von.dentz@intel.com> | 2014-09-17 15:49:45 +0300 |
---|---|---|
committer | Johan Hedberg <johan.hedberg@intel.com> | 2014-09-18 08:04:23 +0300 |
commit | 3d51328b6c8bbf9ef687a962c8bc1127a5873138 (patch) | |
tree | 467e4a0f8fcfaed144cda4d58b5d1437511cd42b /emulator/bthost.c | |
parent | a7b600b45b369961d53e33455ea30628f6ee0bea (diff) | |
download | bluez-3d51328b6c8bbf9ef687a962c8bc1127a5873138.tar.gz |
emulator/bthost: Add iovec support
This convert bthost_set_send_handler to take struct iovec for doing
scatter io.
Diffstat (limited to 'emulator/bthost.c')
-rw-r--r-- | emulator/bthost.c | 96 |
1 files changed, 51 insertions, 45 deletions
diff --git a/emulator/bthost.c b/emulator/bthost.c index 1fae58079..766f14c79 100644 --- a/emulator/bthost.c +++ b/emulator/bthost.c @@ -448,11 +448,12 @@ void bthost_set_send_handler(struct bthost *bthost, bthost_send_func handler, bthost->send_data = user_data; } -static void queue_command(struct bthost *bthost, const void *data, - uint16_t len) +static void queue_command(struct bthost *bthost, const struct iovec *iov, + int iovlen) { struct cmd_queue *cmd_q = &bthost->cmd_q; struct cmd *cmd; + int i; cmd = malloc(sizeof(*cmd)); if (!cmd) @@ -460,8 +461,10 @@ static void queue_command(struct bthost *bthost, const void *data, memset(cmd, 0, sizeof(*cmd)); - memcpy(cmd->data, data, len); - cmd->len = len; + for (i = 0; i < iovlen; i++) { + memcpy(cmd->data + cmd->len, iov[i].iov_base, iov[i].iov_len); + cmd->len += iov[i].iov_len; + } if (cmd_q->tail) cmd_q->tail->next = cmd; @@ -472,45 +475,47 @@ static void queue_command(struct bthost *bthost, const void *data, cmd_q->tail = cmd; } -static void send_packet(struct bthost *bthost, const void *data, uint16_t len) +static void send_packet(struct bthost *bthost, const struct iovec *iov, + int iovlen) { if (!bthost->send_handler) return; - bthost->send_handler(data, len, bthost->send_data); + bthost->send_handler(iov, iovlen, bthost->send_data); } static void send_acl(struct bthost *bthost, uint16_t handle, uint16_t cid, const void *data, uint16_t len) { - struct bt_hci_acl_hdr *acl_hdr; - struct bt_l2cap_hdr *l2_hdr; - uint16_t pkt_len; - void *pkt_data; + struct bt_hci_acl_hdr acl_hdr; + struct bt_l2cap_hdr l2_hdr; + uint8_t pkt = BT_H4_ACL_PKT; + struct iovec iov[4]; - pkt_len = 1 + sizeof(*acl_hdr) + sizeof(*l2_hdr) + len; + iov[0].iov_base = &pkt; + iov[0].iov_len = sizeof(pkt); - pkt_data = malloc(pkt_len); - if (!pkt_data) - return; + acl_hdr.handle = acl_handle_pack(handle, 0); + acl_hdr.dlen = cpu_to_le16(len + sizeof(l2_hdr)); - ((uint8_t *) pkt_data)[0] = BT_H4_ACL_PKT; + iov[1].iov_base = &acl_hdr; + iov[1].iov_len = sizeof(acl_hdr); - acl_hdr = pkt_data + 1; - acl_hdr->handle = acl_handle_pack(handle, 0); - acl_hdr->dlen = cpu_to_le16(len + sizeof(*l2_hdr)); + l2_hdr.cid = cpu_to_le16(cid); + l2_hdr.len = cpu_to_le16(len); - l2_hdr = pkt_data + 1 + sizeof(*acl_hdr); - l2_hdr->cid = cpu_to_le16(cid); - l2_hdr->len = cpu_to_le16(len); + iov[2].iov_base = &l2_hdr; + iov[2].iov_len = sizeof(l2_hdr); - if (len > 0) - memcpy(pkt_data + 1 + sizeof(*acl_hdr) + sizeof(*l2_hdr), - data, len); + if (len == 0) { + send_packet(bthost, iov, 3); + return; + } - send_packet(bthost, pkt_data, pkt_len); + iov[3].iov_base = (void *) data; + iov[3].iov_len = len; - free(pkt_data); + send_packet(bthost, iov, 4); } static uint8_t l2cap_sig_send(struct bthost *bthost, struct btconn *conn, @@ -636,33 +641,30 @@ bool bthost_l2cap_req(struct bthost *bthost, uint16_t handle, uint8_t code, static void send_command(struct bthost *bthost, uint16_t opcode, const void *data, uint8_t len) { - struct bt_hci_cmd_hdr *hdr; - uint16_t pkt_len; - void *pkt_data; + struct bt_hci_cmd_hdr hdr; + uint8_t pkt = BT_H4_CMD_PKT; + struct iovec iov[3]; - pkt_len = 1 + sizeof(*hdr) + len; + iov[0].iov_base = &pkt; + iov[0].iov_len = sizeof(pkt); - pkt_data = malloc(pkt_len); - if (!pkt_data) - return; + hdr.opcode = cpu_to_le16(opcode); + hdr.plen = len; - ((uint8_t *) pkt_data)[0] = BT_H4_CMD_PKT; + iov[1].iov_base = &hdr; + iov[1].iov_len = sizeof(hdr); - hdr = pkt_data + 1; - hdr->opcode = cpu_to_le16(opcode); - hdr->plen = len; - - if (len > 0) - memcpy(pkt_data + 1 + sizeof(*hdr), data, len); + if (len > 0) { + iov[2].iov_base = (void *) data; + iov[2].iov_len = len; + } if (bthost->ncmd) { - send_packet(bthost, pkt_data, pkt_len); + send_packet(bthost, iov, len > 0 ? 3 : 2); bthost->ncmd--; } else { - queue_command(bthost, pkt_data, pkt_len); + queue_command(bthost, iov, len > 0 ? 3 : 2); } - - free(pkt_data); } static void next_cmd(struct bthost *bthost) @@ -670,6 +672,7 @@ static void next_cmd(struct bthost *bthost) struct cmd_queue *cmd_q = &bthost->cmd_q; struct cmd *cmd = cmd_q->head; struct cmd *next; + struct iovec iov; if (!cmd) return; @@ -679,7 +682,10 @@ static void next_cmd(struct bthost *bthost) if (!bthost->ncmd) return; - send_packet(bthost, cmd->data, cmd->len); + iov.iov_base = cmd->data; + iov.iov_len = cmd->len; + + send_packet(bthost, &iov, 1); bthost->ncmd--; if (next) |