diff --git a/CHANGELOG.md b/CHANGELOG.md index a7fb2e33d..c94429f2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,8 +23,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - GATT Client: HID-over-GATT (HOG) Client, Report and Boot Host - GATT Client: Scan Parameters Service Client - GATT Server: Scan Parameters Service Server -- GAP: add `gap_set_page_scan_activity` and `gap_set_page_scan_type` -- GAP: support sniff subrating with `gap_sniff_subrating_configure` +- GAP: support scan page configuration with `gap_set_page_scan_activity` and `gap_set_page_scan_type` +- GAP: support sniff subrating with `gap_sniff_subrating_configure +- GAP: support QoS setup with `gap_qos_set` - AVRCP: new field `button_pressed` in `AVRCP_SUBEVENT_OPERATION` - AVRCP: `AVRCP_SUBEVENT_OPERATION` emitted for button release - AVRCP Controller: avrcp_controller_start_press_and_hold_cmd helps to support device buttons diff --git a/src/bluetooth.h b/src/bluetooth.h index c03a999ae..e38cf0f8b 100644 --- a/src/bluetooth.h +++ b/src/bluetooth.h @@ -142,6 +142,16 @@ typedef enum { */ #define HCI_LINK_SUPERVISION_TIMEOUT_DEFAULT 0x7D00 +/** + * Service Type used for QoS Setup and Flow Specification + */ +typedef enum { + HCI_SERVICE_TYPE_NO_TRAFFIC = 0, + HCI_SERVICE_TYPE_BEST_EFFORT, + HCI_SERVICE_TYPE_GUARANTEED, + HCI_SERVICE_TyPE_INVALID, +} hci_service_type_t; + /** * HCI Transport */ diff --git a/src/gap.h b/src/gap.h index 36173a6ab..16abd06dc 100644 --- a/src/gap.h +++ b/src/gap.h @@ -807,9 +807,22 @@ uint8_t gap_sniff_mode_exit(hci_con_handle_t con_handle); * @param max_latency range: 0x0002 to 0xFFFE; Time = N * 0.625 ms * @param min_remote_timeout range: 0x0002 to 0xFFFE; Time = N * 0.625 ms * @param min_local_timeout range: 0x0002 to 0xFFFE; Time = N * 0.625 ms + @ @return 0 if ok */ uint8_t gap_sniff_subrating_configure(hci_con_handle_t con_handle, uint16_t max_latency, uint16_t min_remote_timeout, uint16_t min_local_timeout); +/** + * @Brief Set QoS + * @param con_handle + * @param service_type + * @param token_rate + * @param peak_bandwidth + * @param latency + * @param delay_variation + @ @return 0 if ok + */ +uint8_t gap_qos_set(hci_con_handle_t con_handle, hci_service_type_t service_type, uint32_t token_rate, uint32_t peak_bandwidth, uint32_t latency, uint32_t delay_variation); + // LE /** diff --git a/src/hci.c b/src/hci.c index 8fa01d94f..7128d3d0b 100644 --- a/src/hci.c +++ b/src/hci.c @@ -213,6 +213,7 @@ static hci_connection_t * create_connection_for_bd_addr_and_type(const bd_addr_t #ifdef ENABLE_CLASSIC conn->request_role = HCI_ROLE_INVALID; conn->sniff_subrating_max_latency = 0xffff; + conn->qos_service_type = HCI_SERVICE_TyPE_INVALID; btstack_run_loop_set_timer_handler(&conn->timeout, hci_connection_timeout_handler); btstack_run_loop_set_timer_context(&conn->timeout, conn); hci_connection_timestamp(conn); @@ -4501,6 +4502,13 @@ static bool hci_run_general_pending_commands(void){ return true; } + if (connection->qos_service_type != HCI_SERVICE_TyPE_INVALID){ + uint8_t service_type = (uint8_t) connection->qos_service_type; + connection->qos_service_type = HCI_SERVICE_TyPE_INVALID; + hci_send_cmd(&hci_qos_setup, connection->con_handle, 0, service_type, connection->qos_token_rate, connection->qos_peak_bandwidth, connection->qos_latency, connection->qos_delay_variation); + return true; + } + if (connection->request_role != HCI_ROLE_INVALID){ hci_role_t role = connection->request_role; connection->request_role = HCI_ROLE_INVALID; @@ -6375,6 +6383,18 @@ uint8_t gap_sniff_subrating_configure(hci_con_handle_t con_handle, uint16_t max_ return ERROR_CODE_SUCCESS; } +uint8_t gap_qos_set(hci_con_handle_t con_handle, hci_service_type_t service_type, uint32_t token_rate, uint32_t peak_bandwidth, uint32_t latency, uint32_t delay_variation){ + hci_connection_t * conn = hci_connection_for_handle(con_handle); + if (!conn) return GAP_CONNECTION_INVALID; + conn->qos_service_type = service_type; + conn->qos_token_rate = token_rate; + conn->qos_peak_bandwidth = peak_bandwidth; + conn->qos_latency = latency; + conn->qos_delay_variation = delay_variation; + hci_run(); + return ERROR_CODE_SUCCESS; +} + void gap_set_page_scan_activity(uint16_t page_scan_interval, uint16_t page_scan_window){ hci_stack->new_page_scan_interval = page_scan_interval; hci_stack->new_page_scan_window = page_scan_window; diff --git a/src/hci.h b/src/hci.h index 9abbe6873..d07f88dce 100644 --- a/src/hci.h +++ b/src/hci.h @@ -546,6 +546,13 @@ typedef struct { uint16_t sniff_subrating_min_remote_timeout; uint16_t sniff_subrating_min_local_timeout; + // QoS + hci_service_type_t qos_service_type; + uint32_t qos_token_rate; + uint32_t qos_peak_bandwidth; + uint32_t qos_latency; + uint32_t qos_delay_variation; + #ifdef ENABLE_SCO_OVER_HCI // track SCO rx event uint32_t sco_rx_ms;