mirror of
https://git.kernel.org/pub/scm/bluetooth/bluez.git
synced 2024-11-16 16:54:38 +08:00
emulator: Add HCI command queuing support
This commit is contained in:
parent
1fdd76c7cb
commit
5e7eea6767
@ -39,9 +39,22 @@
|
||||
#define cpu_to_le16(val) (val)
|
||||
#define cpu_to_le32(val) (val)
|
||||
|
||||
struct cmd {
|
||||
struct cmd *next;
|
||||
struct cmd *prev;
|
||||
uint8_t data[256 + sizeof(struct bt_hci_cmd_hdr)];
|
||||
uint16_t len;
|
||||
};
|
||||
|
||||
struct cmd_queue {
|
||||
struct cmd *head;
|
||||
struct cmd *tail;
|
||||
};
|
||||
|
||||
struct bthost {
|
||||
bthost_send_func send_handler;
|
||||
void *send_data;
|
||||
struct cmd_queue cmd_q;
|
||||
uint8_t ncmd;
|
||||
};
|
||||
|
||||
@ -60,9 +73,14 @@ struct bthost *bthost_create(void)
|
||||
|
||||
void bthost_destroy(struct bthost *bthost)
|
||||
{
|
||||
struct cmd *cmd;
|
||||
|
||||
if (!bthost)
|
||||
return;
|
||||
|
||||
for (cmd = bthost->cmd_q.tail; cmd != NULL; cmd = cmd->next)
|
||||
free(cmd);
|
||||
|
||||
free(bthost);
|
||||
}
|
||||
|
||||
@ -76,6 +94,28 @@ 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)
|
||||
{
|
||||
struct cmd_queue *cmd_q = &bthost->cmd_q;
|
||||
struct cmd *cmd;
|
||||
|
||||
cmd = malloc(sizeof(*cmd));
|
||||
if (!cmd)
|
||||
return;
|
||||
|
||||
memset(cmd, 0, sizeof(*cmd));
|
||||
|
||||
memcpy(cmd->data, data, len);
|
||||
cmd->len = len;
|
||||
|
||||
if (cmd_q->tail)
|
||||
cmd_q->tail->next = cmd;
|
||||
|
||||
cmd->prev = cmd_q->tail;
|
||||
cmd_q->tail = cmd;
|
||||
}
|
||||
|
||||
static void send_packet(struct bthost *bthost, const void *data, uint16_t len)
|
||||
{
|
||||
if (!bthost->send_handler)
|
||||
@ -106,11 +146,41 @@ static void send_command(struct bthost *bthost, uint16_t opcode,
|
||||
if (len > 0)
|
||||
memcpy(pkt_data + 1 + sizeof(*hdr), data, len);
|
||||
|
||||
send_packet(bthost, pkt_data, pkt_len);
|
||||
if (bthost->ncmd) {
|
||||
send_packet(bthost, pkt_data, pkt_len);
|
||||
bthost->ncmd--;
|
||||
} else {
|
||||
queue_command(bthost, pkt_data, pkt_len);
|
||||
}
|
||||
|
||||
free(pkt_data);
|
||||
}
|
||||
|
||||
static void next_cmd(struct bthost *bthost)
|
||||
{
|
||||
struct cmd_queue *cmd_q = &bthost->cmd_q;
|
||||
struct cmd *cmd = cmd_q->tail;
|
||||
struct cmd *next;
|
||||
|
||||
if (!cmd)
|
||||
return;
|
||||
|
||||
next = cmd->next;
|
||||
|
||||
if (!bthost->ncmd)
|
||||
return;
|
||||
|
||||
send_packet(bthost, cmd->data, cmd->len);
|
||||
bthost->ncmd--;
|
||||
|
||||
if (next)
|
||||
next->prev = NULL;
|
||||
|
||||
cmd_q->tail = next;
|
||||
|
||||
free(cmd);
|
||||
}
|
||||
|
||||
static void evt_cmd_complete(struct bthost *bthost, const void *data,
|
||||
uint8_t len)
|
||||
{
|
||||
@ -120,6 +190,8 @@ static void evt_cmd_complete(struct bthost *bthost, const void *data,
|
||||
return;
|
||||
|
||||
bthost->ncmd = ev->ncmd;
|
||||
|
||||
next_cmd(bthost);
|
||||
}
|
||||
|
||||
static void evt_cmd_status(struct bthost *bthost, const void *data,
|
||||
@ -131,6 +203,8 @@ static void evt_cmd_status(struct bthost *bthost, const void *data,
|
||||
return;
|
||||
|
||||
bthost->ncmd = ev->ncmd;
|
||||
|
||||
next_cmd(bthost);
|
||||
}
|
||||
|
||||
static void process_evt(struct bthost *bthost, const void *data, uint16_t len)
|
||||
|
Loading…
Reference in New Issue
Block a user