hci_packet_parser.cc revision f2af1c42ccb2f642b241c2261b42d0be61d45438
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 */);
117dbcb1b58baeac019fafd4b43df751ff8f6c3d5d4Andre Eisenbach  if (stream != NULL) {
118dbcb1b58baeac019fafd4b43df751ff8f6c3d5d4Andre Eisenbach    STREAM_TO_UINT8(*page_number_ptr, stream);
119dbcb1b58baeac019fafd4b43df751ff8f6c3d5d4Andre Eisenbach    STREAM_TO_UINT8(*max_page_number_ptr, stream);
120dbcb1b58baeac019fafd4b43df751ff8f6c3d5d4Andre Eisenbach
121f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He    CHECK(*page_number_ptr < feature_pages_count);
1225ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson    STREAM_TO_ARRAY(feature_pages[*page_number_ptr].as_array, stream,
1235ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson                    (int)sizeof(bt_device_features_t));
124dbcb1b58baeac019fafd4b43df751ff8f6c3d5d4Andre Eisenbach  } else {
1255ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson    LOG_ERROR(LOG_TAG,
1265ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson              "%s() - WARNING: READING EXTENDED FEATURES FAILED. "
1275ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson              "THIS MAY INDICATE A FIRMWARE/CONTROLLER ISSUE.",
1285ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson              __func__);
129dbcb1b58baeac019fafd4b43df751ff8f6c3d5d4Andre Eisenbach  }
13030e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
13130e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  buffer_allocator->free(response);
13230e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson}
133bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson
13430e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnsonstatic void parse_ble_read_white_list_size_response(
1355ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson    BT_HDR* response, uint8_t* white_list_size_ptr) {
1365ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson  uint8_t* stream = read_command_complete_header(
1375ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson      response, HCI_BLE_READ_WHITE_LIST_SIZE, 1 /* byte after */);
138f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He  CHECK(stream != NULL);
13930e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  STREAM_TO_UINT8(*white_list_size_ptr, stream);
14030e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
14130e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  buffer_allocator->free(response);
142bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson}
143bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson
1445ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watsonstatic void parse_ble_read_buffer_size_response(BT_HDR* response,
1455ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson                                                uint16_t* data_size_ptr,
1465ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson                                                uint8_t* acl_buffer_count_ptr) {
1475ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson  uint8_t* stream = read_command_complete_header(
1485ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson      response, HCI_BLE_READ_BUFFER_SIZE, 3 /* bytes after */);
149f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He  CHECK(stream != NULL);
15030e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  STREAM_TO_UINT16(*data_size_ptr, stream);
15130e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  STREAM_TO_UINT8(*acl_buffer_count_ptr, stream);
15230e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
15330e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  buffer_allocator->free(response);
15430e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson}
15530e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
15630e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnsonstatic void parse_ble_read_supported_states_response(
1575ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson    BT_HDR* response, uint8_t* supported_states, size_t supported_states_size) {
1585ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson  uint8_t* stream =
1595ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson      read_command_complete_header(response, HCI_BLE_READ_SUPPORTED_STATES,
1605ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson                                   supported_states_size /* bytes after */);
161f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He  CHECK(stream != NULL);
16230e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  STREAM_TO_ARRAY(supported_states, stream, (int)supported_states_size);
16330e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
16430e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  buffer_allocator->free(response);
16530e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson}
16630e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
16730e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnsonstatic void parse_ble_read_local_supported_features_response(
1685ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson    BT_HDR* response, bt_device_features_t* supported_features) {
1695ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson  uint8_t* stream = read_command_complete_header(
1705ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson      response, HCI_BLE_READ_LOCAL_SPT_FEAT,
1715ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson      sizeof(bt_device_features_t) /* bytes after */);
172f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He  CHECK(stream != NULL);
1735ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson  STREAM_TO_ARRAY(supported_features->as_array, stream,
1745ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson                  (int)sizeof(bt_device_features_t));
17530e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
17630e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  buffer_allocator->free(response);
17730e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson}
17830e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
179444a8da807abaf5f9e813ce70c56a79160495fb3Satya Callojistatic void parse_ble_read_resolving_list_size_response(
1805ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson    BT_HDR* response, uint8_t* resolving_list_size_ptr) {
1815ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson  uint8_t* stream = read_command_complete_header(
1825ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson      response, HCI_BLE_READ_RESOLVING_LIST_SIZE, 1 /* bytes after */);
183444a8da807abaf5f9e813ce70c56a79160495fb3Satya Calloji  STREAM_TO_UINT8(*resolving_list_size_ptr, stream);
184444a8da807abaf5f9e813ce70c56a79160495fb3Satya Calloji
185444a8da807abaf5f9e813ce70c56a79160495fb3Satya Calloji  buffer_allocator->free(response);
186444a8da807abaf5f9e813ce70c56a79160495fb3Satya Calloji}
187444a8da807abaf5f9e813ce70c56a79160495fb3Satya Calloji
188636d6714a4c08dd99d2147dcce05dc3892e804b4Priti Agherastatic void parse_ble_read_suggested_default_data_length_response(
1895ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson    BT_HDR* response, uint16_t* ble_default_packet_length_ptr) {
1905ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson  uint8_t* stream = read_command_complete_header(
1915ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson      response, HCI_BLE_READ_DEFAULT_DATA_LENGTH, 2 /* bytes after */);
192636d6714a4c08dd99d2147dcce05dc3892e804b4Priti Aghera  STREAM_TO_UINT8(*ble_default_packet_length_ptr, stream);
1931f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowski}
1941f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowski
1951f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowskistatic void parse_ble_read_maximum_advertising_data_length(
1961f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowski    BT_HDR* response, uint16_t* ble_maximum_advertising_data_length_ptr) {
1971f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowski  uint8_t* stream = read_command_complete_header(
1981f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowski      response, HCI_LE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH,
1991f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowski      2 /* bytes after */);
2001f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowski  STREAM_TO_UINT8(*ble_maximum_advertising_data_length_ptr, stream);
2011f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowski
2021f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowski  buffer_allocator->free(response);
2031f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowski}
2041f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowski
2051f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowskistatic void parse_ble_read_number_of_supported_advertising_sets(
2061f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowski    BT_HDR* response, uint8_t* ble_number_of_supported_advertising_sets_ptr) {
2071f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowski  uint8_t* stream = read_command_complete_header(
2081f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowski      response, HCI_LE_READ_NUMBER_OF_SUPPORTED_ADVERTISING_SETS,
2091f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowski      1 /* bytes after */);
2101f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowski  STREAM_TO_UINT8(*ble_number_of_supported_advertising_sets_ptr, stream);
211636d6714a4c08dd99d2147dcce05dc3892e804b4Priti Aghera
212636d6714a4c08dd99d2147dcce05dc3892e804b4Priti Aghera  buffer_allocator->free(response);
213636d6714a4c08dd99d2147dcce05dc3892e804b4Priti Aghera}
214636d6714a4c08dd99d2147dcce05dc3892e804b4Priti Aghera
21530e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson// Internal functions
21630e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
2175ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watsonstatic uint8_t* read_command_complete_header(BT_HDR* response,
2185ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson                                             command_opcode_t expected_opcode,
2195ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson                                             size_t minimum_bytes_after) {
2205ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson  uint8_t* stream = response->data + response->offset;
221bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson
22230e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  // Read the event header
22330e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  uint8_t event_code;
22430e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  uint8_t parameter_length;
22530e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  STREAM_TO_UINT8(event_code, stream);
22630e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  STREAM_TO_UINT8(parameter_length, stream);
22730e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
22830e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  const size_t parameter_bytes_we_read_here = 4;
22930e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
23030e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  // Check the event header values against what we expect
231f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He  CHECK(event_code == HCI_COMMAND_COMPLETE_EVT);
232f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He  CHECK(parameter_length >=
233f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He        (parameter_bytes_we_read_here + minimum_bytes_after));
23430e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
23530e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  // Read the command complete header
23630e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  command_opcode_t opcode;
23730e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  uint8_t status;
2385ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson  STREAM_SKIP_UINT8(stream);  // skip the number of hci command packets field
239bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson  STREAM_TO_UINT16(opcode, stream);
240bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson
24130e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  // Check the command complete header values against what we expect
24230e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  if (expected_opcode != NO_OPCODE_CHECKING) {
243f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He    CHECK(opcode == expected_opcode);
24430e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  }
24530e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
24630e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  // Assume the next field is the status field
24730e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  STREAM_TO_UINT8(status, stream);
248dbcb1b58baeac019fafd4b43df751ff8f6c3d5d4Andre Eisenbach
2495ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson  if (status != HCI_SUCCESS) {
25085e22b32ec3482a09dc019ee6fd096a31fd1bf64Jakub Pawlowski    LOG_ERROR(LOG_TAG, "%s: return status - 0x%x", __func__, status);
251dbcb1b58baeac019fafd4b43df751ff8f6c3d5d4Andre Eisenbach    return NULL;
252f6dcf79f62880e716e127b19c70ea328e07c6051Srinu Jella  }
25330e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
25430e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  return stream;
255bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson}
256bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson
257bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnsonstatic const hci_packet_parser_t interface = {
2585ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson    parse_generic_command_complete,
2595ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson    parse_read_buffer_size_response,
2605ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson    parse_read_local_version_info_response,
2615ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson    parse_read_bd_addr_response,
2625ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson    parse_read_local_supported_commands_response,
2635ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson    parse_read_local_extended_features_response,
2645ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson    parse_ble_read_white_list_size_response,
2655ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson    parse_ble_read_buffer_size_response,
2665ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson    parse_ble_read_supported_states_response,
2675ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson    parse_ble_read_local_supported_features_response,
2685ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson    parse_ble_read_resolving_list_size_response,
2695ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson    parse_ble_read_suggested_default_data_length_response,
2701f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowski    parse_ble_read_maximum_advertising_data_length,
2711f4cc6dc61ad5863c3fe31dafd364e064b1e64adJakub Pawlowski    parse_ble_read_number_of_supported_advertising_sets,
2725ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson    parse_read_local_supported_codecs_response};
2735ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson
2745ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watsonconst hci_packet_parser_t* hci_packet_parser_get_interface() {
27530e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  buffer_allocator = buffer_allocator_get_interface();
27630e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  return &interface;
27730e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson}
27830e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
2795ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watsonconst hci_packet_parser_t* hci_packet_parser_get_test_interface(
2805ff20a23661695abb1cff6d01d71a8cad4cc7890Myles Watson    allocator_t* buffer_allocator_interface) {
28130e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  buffer_allocator = buffer_allocator_interface;
282bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson  return &interface;
283bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson}
284