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