@@ -203,6 +203,7 @@ struct btdev {
uint8_t ssp_debug_mode;
uint8_t secure_conn_support;
uint8_t host_flow_control;
+ uint8_t sco_flowctl;
uint8_t le_supported;
uint8_t le_simultaneous;
uint8_t le_event_mask[8];
@@ -2398,6 +2399,20 @@ static int cmd_read_tx_power_level(struct btdev *dev, const void *data,
return 0;
}
+static int cmd_write_sync_flowctl(struct btdev *dev, const void *data,
+ uint8_t len)
+{
+ const struct bt_hci_cmd_write_sync_flow_control *cmd = data;
+ uint8_t status = BT_HCI_ERR_SUCCESS;
+
+ dev->sco_flowctl = cmd->enable;
+
+ cmd_complete(dev, BT_HCI_CMD_WRITE_SYNC_FLOW_CONTROL, &status,
+ sizeof(status));
+
+ return 0;
+}
+
static int cmd_read_num_iac(struct btdev *dev, const void *data, uint8_t len)
{
struct bt_hci_rsp_read_num_supported_iac rsp;
@@ -2676,6 +2691,7 @@ static int cmd_enable_dut_mode(struct btdev *dev, const void *data,
CMD(BT_HCI_CMD_READ_VOICE_SETTING, cmd_read_voice, NULL), \
CMD(BT_HCI_CMD_WRITE_VOICE_SETTING, cmd_write_voice, NULL), \
CMD(BT_HCI_CMD_READ_TX_POWER, cmd_read_tx_power_level, NULL), \
+ CMD(BT_HCI_CMD_WRITE_SYNC_FLOW_CONTROL, cmd_write_sync_flowctl, NULL), \
CMD(BT_HCI_CMD_READ_NUM_SUPPORTED_IAC, cmd_read_num_iac, NULL), \
CMD(BT_HCI_CMD_READ_CURRENT_IAC_LAP, cmd_read_current_iac_lap, \
NULL), \
@@ -2739,6 +2755,7 @@ static void set_common_commands_bredr20(struct btdev *btdev)
btdev->commands[9] |= 0x04; /* Read Voice Setting */
btdev->commands[9] |= 0x08; /* Write Voice Setting */
btdev->commands[10] |= 0x04; /* Read TX Power Level */
+ btdev->commands[10] |= BIT(4); /* Write Sync Flow Control */
btdev->commands[11] |= 0x04; /* Read Number of Supported IAC */
btdev->commands[11] |= 0x08; /* Read Current IAC LAP */
btdev->commands[11] |= 0x10; /* Write Current IAC LAP */
@@ -7655,6 +7672,31 @@ static void send_acl(struct btdev *dev, const void *data, uint16_t len)
send_packet(conn->link->dev, iov, 3);
}
+static void send_sco(struct btdev *dev, const void *data, uint16_t len)
+{
+ struct bt_hci_acl_hdr *hdr;
+ struct iovec iov[2];
+ struct btdev_conn *conn;
+ uint8_t pkt_type = BT_H4_SCO_PKT;
+
+ /* Packet type */
+ iov[0].iov_base = &pkt_type;
+ iov[0].iov_len = sizeof(pkt_type);
+
+ iov[1].iov_base = hdr = (void *) (data);
+ iov[1].iov_len = len;
+
+ conn = queue_find(dev->conns, match_handle,
+ UINT_TO_PTR(acl_handle(hdr->handle)));
+ if (!conn)
+ return;
+
+ if (dev->sco_flowctl)
+ num_completed_packets(dev, conn->handle);
+
+ send_packet(conn->link->dev, iov, 2);
+}
+
static void send_iso(struct btdev *dev, const void *data, uint16_t len)
{
struct bt_hci_acl_hdr *hdr;
@@ -7702,6 +7744,9 @@ void btdev_receive_h4(struct btdev *btdev, const void *data, uint16_t len)
case BT_H4_ACL_PKT:
send_acl(btdev, data + 1, len - 1);
break;
+ case BT_H4_SCO_PKT:
+ send_sco(btdev, data + 1, len - 1);
+ break;
case BT_H4_ISO_PKT:
send_iso(btdev, data + 1, len - 1);
break;