1bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson/****************************************************************************** 2bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson * 3bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson * Copyright (C) 2014 Google, Inc. 4bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson * 5bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson * Licensed under the Apache License, Version 2.0 (the "License"); 6bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson * you may not use this file except in compliance with the License. 7bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson * You may obtain a copy of the License at: 8bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson * 9bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson * http://www.apache.org/licenses/LICENSE-2.0 10bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson * 11bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson * Unless required by applicable law or agreed to in writing, software 12bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson * distributed under the License is distributed on an "AS IS" BASIS, 13bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson * See the License for the specific language governing permissions and 15bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson * limitations under the License. 16bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson * 17bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson ******************************************************************************/ 18bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson 1949120dc867c7818511b5afec461dfc97d17eef58Marie Janssen#define LOG_TAG "bt_hci" 2049120dc867c7818511b5afec461dfc97d17eef58Marie Janssen 21db554581079863974af8e1289646f5deea6fc044Marie Janssen#include "hci_packet_parser.h" 22dbcb1b58baeac019fafd4b43df751ff8f6c3d5d4Andre Eisenbach 23f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He#include <base/logging.h> 24bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson 2530e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson#include "buffer_allocator.h" 26bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson#include "hci_layer.h" 27db554581079863974af8e1289646f5deea6fc044Marie Janssen#include "hcimsgs.h" 28dbcb1b58baeac019fafd4b43df751ff8f6c3d5d4Andre Eisenbach#include "osi/include/log.h" 29bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson 3030e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnsonstatic const command_opcode_t NO_OPCODE_CHECKING = 0; 3130e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson 325ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watsonstatic const allocator_t* buffer_allocator; 3330e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson 345ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watsonstatic uint8_t* read_command_complete_header(BT_HDR* response, 355ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson command_opcode_t expected_opcode, 365ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson size_t minimum_bytes_after); 3730e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson 385ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watsonstatic void parse_generic_command_complete(BT_HDR* response) { 395ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson read_command_complete_header(response, NO_OPCODE_CHECKING, 405ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson 0 /* bytes after */); 4130e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson 4230e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson buffer_allocator->free(response); 4330e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson} 4430e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson 455ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watsonstatic void parse_read_buffer_size_response(BT_HDR* response, 465ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson uint16_t* data_size_ptr, 475ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson uint16_t* acl_buffer_count_ptr) { 485ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson uint8_t* stream = read_command_complete_header(response, HCI_READ_BUFFER_SIZE, 495ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson 5 /* bytes after */); 50f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(stream != NULL); 51bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson STREAM_TO_UINT16(*data_size_ptr, stream); 525ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson STREAM_SKIP_UINT8(stream); // skip the sco packet length 5330e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson STREAM_TO_UINT16(*acl_buffer_count_ptr, stream); 5430e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson 5530e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson buffer_allocator->free(response); 5630e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson} 5730e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson 585ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watsonstatic void parse_read_local_version_info_response(BT_HDR* response, 595ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson bt_version_t* bt_version) { 605ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson uint8_t* stream = read_command_complete_header( 615ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson response, HCI_READ_LOCAL_VERSION_INFO, 8 /* bytes after */); 62f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(stream != NULL); 6330e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson STREAM_TO_UINT8(bt_version->hci_version, stream); 6430e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson STREAM_TO_UINT16(bt_version->hci_revision, stream); 6530e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson STREAM_TO_UINT8(bt_version->lmp_version, stream); 6630e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson STREAM_TO_UINT16(bt_version->manufacturer, stream); 6730e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson STREAM_TO_UINT16(bt_version->lmp_subversion, stream); 6830e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson 6930e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson buffer_allocator->free(response); 7030e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson} 7130e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson 72f6dcf79f62880e716e127b19c70ea328e07c6051Srinu Jellastatic void parse_read_local_supported_codecs_response( 735ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson BT_HDR* response, uint8_t* number_of_local_supported_codecs, 745ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson uint8_t* local_supported_codecs) { 755ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson uint8_t* stream = read_command_complete_header( 765ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson response, HCI_READ_LOCAL_SUPPORTED_CODECS, 0 /* bytes after */); 775ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson if (stream) { 78f6dcf79f62880e716e127b19c70ea328e07c6051Srinu Jella STREAM_TO_UINT8(*number_of_local_supported_codecs, stream); 795ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson for (uint8_t i = 0; i < *number_of_local_supported_codecs; i++) { 80f6dcf79f62880e716e127b19c70ea328e07c6051Srinu Jella STREAM_TO_UINT8(*local_supported_codecs, stream); 81f6dcf79f62880e716e127b19c70ea328e07c6051Srinu Jella local_supported_codecs++; 82f6dcf79f62880e716e127b19c70ea328e07c6051Srinu Jella } 83f6dcf79f62880e716e127b19c70ea328e07c6051Srinu Jella } 84f6dcf79f62880e716e127b19c70ea328e07c6051Srinu Jella 85f6dcf79f62880e716e127b19c70ea328e07c6051Srinu Jella buffer_allocator->free(response); 86f6dcf79f62880e716e127b19c70ea328e07c6051Srinu Jella} 87f6dcf79f62880e716e127b19c70ea328e07c6051Srinu Jella 885ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watsonstatic void parse_read_bd_addr_response(BT_HDR* response, 895ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson bt_bdaddr_t* address_ptr) { 905ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson uint8_t* stream = read_command_complete_header( 915ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson response, HCI_READ_BD_ADDR, sizeof(bt_bdaddr_t) /* bytes after */); 92f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(stream != NULL); 9330e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson STREAM_TO_BDADDR(address_ptr->address, stream); 9430e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson 9530e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson buffer_allocator->free(response); 9630e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson} 9730e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson 9830e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnsonstatic void parse_read_local_supported_commands_response( 995ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson BT_HDR* response, uint8_t* supported_commands_ptr, 10030e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson size_t supported_commands_length) { 1015ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson uint8_t* stream = 1025ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson read_command_complete_header(response, HCI_READ_LOCAL_SUPPORTED_CMDS, 1035ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson supported_commands_length /* bytes after */); 104f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(stream != NULL); 1055ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson STREAM_TO_ARRAY(supported_commands_ptr, stream, 1065ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson (int)supported_commands_length); 10730e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson 10830e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson buffer_allocator->free(response); 10930e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson} 11030e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson 11130e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnsonstatic void parse_read_local_extended_features_response( 1125ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson BT_HDR* response, uint8_t* page_number_ptr, uint8_t* max_page_number_ptr, 1135ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson bt_device_features_t* feature_pages, size_t feature_pages_count) { 1145ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson uint8_t* stream = read_command_complete_header( 1155ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson response, HCI_READ_LOCAL_EXT_FEATURES, 1165ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson 2 + sizeof(bt_device_features_t) /* bytes after */); 11709173e75bb92d6fedfe010fa306cc0783e061c86Myles Watson CHECK(stream != NULL); 11809173e75bb92d6fedfe010fa306cc0783e061c86Myles Watson 11909173e75bb92d6fedfe010fa306cc0783e061c86Myles Watson STREAM_TO_UINT8(*page_number_ptr, stream); 12009173e75bb92d6fedfe010fa306cc0783e061c86Myles Watson STREAM_TO_UINT8(*max_page_number_ptr, stream); 12109173e75bb92d6fedfe010fa306cc0783e061c86Myles Watson 12209173e75bb92d6fedfe010fa306cc0783e061c86Myles Watson CHECK(*page_number_ptr < feature_pages_count); 12309173e75bb92d6fedfe010fa306cc0783e061c86Myles Watson STREAM_TO_ARRAY(feature_pages[*page_number_ptr].as_array, stream, 12409173e75bb92d6fedfe010fa306cc0783e061c86Myles Watson (int)sizeof(bt_device_features_t)); 12530e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson 12630e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson buffer_allocator->free(response); 12730e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson} 128bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson 12930e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnsonstatic void parse_ble_read_white_list_size_response( 1305ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson BT_HDR* response, uint8_t* white_list_size_ptr) { 1315ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson uint8_t* stream = read_command_complete_header( 1325ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson response, HCI_BLE_READ_WHITE_LIST_SIZE, 1 /* byte after */); 133f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(stream != NULL); 13430e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson STREAM_TO_UINT8(*white_list_size_ptr, stream); 13530e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson 13630e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson buffer_allocator->free(response); 137bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson} 138bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson 1395ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watsonstatic void parse_ble_read_buffer_size_response(BT_HDR* response, 1405ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson uint16_t* data_size_ptr, 1415ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson uint8_t* acl_buffer_count_ptr) { 1425ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson uint8_t* stream = read_command_complete_header( 1435ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson response, HCI_BLE_READ_BUFFER_SIZE, 3 /* bytes after */); 144f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(stream != NULL); 14530e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson STREAM_TO_UINT16(*data_size_ptr, stream); 14630e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson STREAM_TO_UINT8(*acl_buffer_count_ptr, stream); 14730e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson 14830e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson buffer_allocator->free(response); 14930e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson} 15030e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson 15130e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnsonstatic void parse_ble_read_supported_states_response( 1525ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson BT_HDR* response, uint8_t* supported_states, size_t supported_states_size) { 1535ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson uint8_t* stream = 1545ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson read_command_complete_header(response, HCI_BLE_READ_SUPPORTED_STATES, 1555ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson supported_states_size /* bytes after */); 156f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(stream != NULL); 15730e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson STREAM_TO_ARRAY(supported_states, stream, (int)supported_states_size); 15830e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson 15930e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson buffer_allocator->free(response); 16030e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson} 16130e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson 16230e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnsonstatic void parse_ble_read_local_supported_features_response( 1635ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson BT_HDR* response, bt_device_features_t* supported_features) { 1645ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson uint8_t* stream = read_command_complete_header( 1655ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson response, HCI_BLE_READ_LOCAL_SPT_FEAT, 1665ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson sizeof(bt_device_features_t) /* bytes after */); 167f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(stream != NULL); 1685ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson STREAM_TO_ARRAY(supported_features->as_array, stream, 1695ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson (int)sizeof(bt_device_features_t)); 17030e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson 17130e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson buffer_allocator->free(response); 17230e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson} 17330e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson 174444a8da807abaf5f9e813ce70c56a79160495fb3Satya Callojistatic void parse_ble_read_resolving_list_size_response( 1755ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson BT_HDR* response, uint8_t* resolving_list_size_ptr) { 1765ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson uint8_t* stream = read_command_complete_header( 1775ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson response, HCI_BLE_READ_RESOLVING_LIST_SIZE, 1 /* bytes after */); 178444a8da807abaf5f9e813ce70c56a79160495fb3Satya Calloji STREAM_TO_UINT8(*resolving_list_size_ptr, stream); 179444a8da807abaf5f9e813ce70c56a79160495fb3Satya Calloji 180444a8da807abaf5f9e813ce70c56a79160495fb3Satya Calloji buffer_allocator->free(response); 181444a8da807abaf5f9e813ce70c56a79160495fb3Satya Calloji} 182444a8da807abaf5f9e813ce70c56a79160495fb3Satya Calloji 183636d6714a4c08dd99d2147dcce05dc3892e804b4Priti Agherastatic void parse_ble_read_suggested_default_data_length_response( 1845ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson BT_HDR* response, uint16_t* ble_default_packet_length_ptr) { 1855ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson uint8_t* stream = read_command_complete_header( 1865ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson response, HCI_BLE_READ_DEFAULT_DATA_LENGTH, 2 /* bytes after */); 187636d6714a4c08dd99d2147dcce05dc3892e804b4Priti Aghera STREAM_TO_UINT8(*ble_default_packet_length_ptr, stream); 1881f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowski} 1891f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowski 1901f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowskistatic void parse_ble_read_maximum_advertising_data_length( 1911f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowski BT_HDR* response, uint16_t* ble_maximum_advertising_data_length_ptr) { 1921f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowski uint8_t* stream = read_command_complete_header( 1931f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowski response, HCI_LE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH, 1941f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowski 2 /* bytes after */); 195910f8b64397a5da6872c2f223c7f9cb6f0316062Jakub Pawlowski STREAM_TO_UINT16(*ble_maximum_advertising_data_length_ptr, stream); 1961f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowski 1971f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowski buffer_allocator->free(response); 1981f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowski} 1991f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowski 2001f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowskistatic void parse_ble_read_number_of_supported_advertising_sets( 2011f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowski BT_HDR* response, uint8_t* ble_number_of_supported_advertising_sets_ptr) { 2021f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowski uint8_t* stream = read_command_complete_header( 2031f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowski response, HCI_LE_READ_NUMBER_OF_SUPPORTED_ADVERTISING_SETS, 2041f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowski 1 /* bytes after */); 2051f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowski STREAM_TO_UINT8(*ble_number_of_supported_advertising_sets_ptr, stream); 206636d6714a4c08dd99d2147dcce05dc3892e804b4Priti Aghera 207636d6714a4c08dd99d2147dcce05dc3892e804b4Priti Aghera buffer_allocator->free(response); 208636d6714a4c08dd99d2147dcce05dc3892e804b4Priti Aghera} 209636d6714a4c08dd99d2147dcce05dc3892e804b4Priti Aghera 21030e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson// Internal functions 21130e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson 2125ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watsonstatic uint8_t* read_command_complete_header(BT_HDR* response, 2135ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson command_opcode_t expected_opcode, 2145ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson size_t minimum_bytes_after) { 2155ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson uint8_t* stream = response->data + response->offset; 216bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson 21730e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson // Read the event header 21830e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson uint8_t event_code; 21930e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson uint8_t parameter_length; 22030e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson STREAM_TO_UINT8(event_code, stream); 22130e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson STREAM_TO_UINT8(parameter_length, stream); 22230e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson 22330e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson const size_t parameter_bytes_we_read_here = 4; 22430e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson 22530e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson // Check the event header values against what we expect 226f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(event_code == HCI_COMMAND_COMPLETE_EVT); 227f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(parameter_length >= 228f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He (parameter_bytes_we_read_here + minimum_bytes_after)); 22930e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson 23030e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson // Read the command complete header 23130e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson command_opcode_t opcode; 23230e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson uint8_t status; 2335ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson STREAM_SKIP_UINT8(stream); // skip the number of hci command packets field 234bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson STREAM_TO_UINT16(opcode, stream); 235bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson 23630e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson // Check the command complete header values against what we expect 23730e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson if (expected_opcode != NO_OPCODE_CHECKING) { 238f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He CHECK(opcode == expected_opcode); 23930e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson } 24030e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson 24130e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson // Assume the next field is the status field 24230e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson STREAM_TO_UINT8(status, stream); 243dbcb1b58baeac019fafd4b43df751ff8f6c3d5d4Andre Eisenbach 2445ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson if (status != HCI_SUCCESS) { 24585e22b32ec3482a09dc019ee6fd096a31fd1bf64Jakub Pawlowski LOG_ERROR(LOG_TAG, "%s: return status - 0x%x", __func__, status); 246dbcb1b58baeac019fafd4b43df751ff8f6c3d5d4Andre Eisenbach return NULL; 247f6dcf79f62880e716e127b19c70ea328e07c6051Srinu Jella } 24830e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson 24930e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson return stream; 250bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson} 251bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson 252bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnsonstatic const hci_packet_parser_t interface = { 2535ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson parse_generic_command_complete, 2545ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson parse_read_buffer_size_response, 2555ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson parse_read_local_version_info_response, 2565ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson parse_read_bd_addr_response, 2575ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson parse_read_local_supported_commands_response, 2585ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson parse_read_local_extended_features_response, 2595ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson parse_ble_read_white_list_size_response, 2605ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson parse_ble_read_buffer_size_response, 2615ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson parse_ble_read_supported_states_response, 2625ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson parse_ble_read_local_supported_features_response, 2635ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson parse_ble_read_resolving_list_size_response, 2645ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson parse_ble_read_suggested_default_data_length_response, 2651f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowski parse_ble_read_maximum_advertising_data_length, 2661f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowski parse_ble_read_number_of_supported_advertising_sets, 2675ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson parse_read_local_supported_codecs_response}; 2685ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson 2695ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watsonconst hci_packet_parser_t* hci_packet_parser_get_interface() { 27030e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson buffer_allocator = buffer_allocator_get_interface(); 27130e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson return &interface; 27230e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson} 27330e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson 2745ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watsonconst hci_packet_parser_t* hci_packet_parser_get_test_interface( 2755ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson allocator_t* buffer_allocator_interface) { 27630e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson buffer_allocator = buffer_allocator_interface; 277bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson return &interface; 278bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson} 279