hci_packet_parser.cc revision 30e58068c1adaac7c5ccb3aa9cfb045d41d2a10e
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
19bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson#include <assert.h>
20bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson
2130e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson#include "buffer_allocator.h"
22bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson#include "bt_types.h"
23bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson#include "hcimsgs.h"
24bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson#include "hci_layer.h"
25bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson#include "hci_packet_parser.h"
26bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson
2730e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnsonstatic const command_opcode_t NO_OPCODE_CHECKING = 0;
2830e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
2930e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnsonstatic const allocator_t *buffer_allocator;
3030e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
3130e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnsonstatic uint8_t *read_command_complete_header(
3230e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  BT_HDR *response,
3330e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  command_opcode_t expected_opcode,
3430e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  size_t minimum_bytes_after);
3530e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
3630e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnsonstatic void parse_generic_command_complete(BT_HDR *response) {
3730e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  read_command_complete_header(response, NO_OPCODE_CHECKING, 0 /* bytes after */);
3830e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
3930e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  buffer_allocator->free(response);
4030e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson}
4130e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
42bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnsonstatic void parse_read_buffer_size_response(
43bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson    BT_HDR *response,
4430e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson    uint16_t *data_size_ptr,
4530e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson    uint16_t *acl_buffer_count_ptr) {
46bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson
4730e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  uint8_t *stream = read_command_complete_header(response, HCI_READ_BUFFER_SIZE, 5 /* bytes after */);
48bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson  STREAM_TO_UINT16(*data_size_ptr, stream);
4930e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  STREAM_SKIP_UINT8(stream); // skip the sco packet length
5030e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  STREAM_TO_UINT16(*acl_buffer_count_ptr, stream);
5130e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
5230e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  buffer_allocator->free(response);
5330e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson}
5430e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
5530e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnsonstatic void parse_read_local_version_info_response(
5630e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson    BT_HDR *response,
5730e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson    bt_version_t *bt_version) {
5830e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
5930e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  uint8_t *stream = read_command_complete_header(response, HCI_READ_LOCAL_VERSION_INFO, 8 /* bytes after */);
6030e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  STREAM_TO_UINT8(bt_version->hci_version, stream);
6130e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  STREAM_TO_UINT16(bt_version->hci_revision, stream);
6230e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  STREAM_TO_UINT8(bt_version->lmp_version, stream);
6330e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  STREAM_TO_UINT16(bt_version->manufacturer, stream);
6430e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  STREAM_TO_UINT16(bt_version->lmp_subversion, stream);
6530e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
6630e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  buffer_allocator->free(response);
6730e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson}
6830e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
6930e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnsonstatic void parse_read_bd_addr_response(
7030e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson    BT_HDR *response,
7130e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson    bt_bdaddr_t *address_ptr) {
7230e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
7330e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  uint8_t *stream = read_command_complete_header(response, HCI_READ_BD_ADDR, sizeof(bt_bdaddr_t) /* bytes after */);
7430e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  STREAM_TO_BDADDR(address_ptr->address, stream);
7530e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
7630e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  buffer_allocator->free(response);
7730e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson}
7830e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
7930e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnsonstatic void parse_read_local_supported_commands_response(
8030e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson    BT_HDR *response,
8130e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson    uint8_t *supported_commands_ptr,
8230e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson    size_t supported_commands_length) {
8330e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
8430e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  uint8_t *stream = read_command_complete_header(response, HCI_READ_LOCAL_SUPPORTED_CMDS, supported_commands_length /* bytes after */);
8530e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  STREAM_TO_ARRAY(supported_commands_ptr, stream, (int)supported_commands_length);
8630e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
8730e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  buffer_allocator->free(response);
8830e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson}
8930e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
9030e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnsonstatic void parse_read_local_extended_features_response(
9130e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson    BT_HDR *response,
9230e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson    uint8_t *page_number_ptr,
9330e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson    uint8_t *max_page_number_ptr,
9430e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson    bt_device_features_t *feature_pages,
9530e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson    size_t feature_pages_count) {
9630e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
9730e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  uint8_t *stream = read_command_complete_header(response, HCI_READ_LOCAL_EXT_FEATURES, 2 + sizeof(bt_device_features_t) /* bytes after */);
9830e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  STREAM_TO_UINT8(*page_number_ptr, stream);
9930e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  STREAM_TO_UINT8(*max_page_number_ptr, stream);
10030e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
10130e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  assert(*page_number_ptr < feature_pages_count);
10230e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  STREAM_TO_ARRAY(feature_pages[*page_number_ptr].as_array, stream, (int)sizeof(bt_device_features_t));
10330e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
10430e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  buffer_allocator->free(response);
10530e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson}
106bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson
10730e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnsonstatic void parse_ble_read_white_list_size_response(
10830e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson    BT_HDR *response,
10930e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson    uint8_t *white_list_size_ptr) {
11030e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
11130e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_WHITE_LIST_SIZE, 1 /* byte after */);
11230e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  STREAM_TO_UINT8(*white_list_size_ptr, stream);
11330e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
11430e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  buffer_allocator->free(response);
115bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson}
116bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson
117bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnsonstatic void parse_ble_read_buffer_size_response(
118bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson    BT_HDR *response,
11930e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson    uint16_t *data_size_ptr,
12030e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson    uint8_t *acl_buffer_count_ptr) {
12130e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
12230e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_BUFFER_SIZE, 3 /* bytes after */);
12330e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  STREAM_TO_UINT16(*data_size_ptr, stream);
12430e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  STREAM_TO_UINT8(*acl_buffer_count_ptr, stream);
12530e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
12630e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  buffer_allocator->free(response);
12730e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson}
12830e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
12930e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnsonstatic void parse_ble_read_supported_states_response(
13030e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson    BT_HDR *response,
13130e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson    uint8_t *supported_states,
13230e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson    size_t supported_states_size) {
13330e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
13430e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_SUPPORTED_STATES, supported_states_size /* bytes after */);
13530e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  STREAM_TO_ARRAY(supported_states, stream, (int)supported_states_size);
13630e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
13730e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  buffer_allocator->free(response);
13830e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson}
13930e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
14030e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnsonstatic void parse_ble_read_local_supported_features_response(
14130e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson    BT_HDR *response,
14230e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson    bt_device_features_t *supported_features) {
14330e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
14430e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_LOCAL_SPT_FEAT, sizeof(bt_device_features_t) /* bytes after */);
14530e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  STREAM_TO_ARRAY(supported_features->as_array, stream, (int)sizeof(bt_device_features_t));
14630e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
14730e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  buffer_allocator->free(response);
14830e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson}
14930e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
15030e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson// Internal functions
15130e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
15230e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnsonstatic uint8_t *read_command_complete_header(
15330e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson    BT_HDR *response,
15430e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson    command_opcode_t expected_opcode,
15530e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson    size_t minimum_bytes_after) {
15630e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
157bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson  uint8_t *stream = response->data + response->offset;
158bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson
15930e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  // Read the event header
16030e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  uint8_t event_code;
16130e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  uint8_t parameter_length;
16230e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  STREAM_TO_UINT8(event_code, stream);
16330e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  STREAM_TO_UINT8(parameter_length, stream);
16430e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
16530e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  const size_t parameter_bytes_we_read_here = 4;
16630e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
16730e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  // Check the event header values against what we expect
16830e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  assert(event_code == HCI_COMMAND_COMPLETE_EVT);
16930e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  assert(parameter_length >= (parameter_bytes_we_read_here + minimum_bytes_after));
17030e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
17130e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  // Read the command complete header
17230e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  command_opcode_t opcode;
17330e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  uint8_t status;
17430e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  STREAM_SKIP_UINT8(stream); // skip the number of hci command packets field
175bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson  STREAM_TO_UINT16(opcode, stream);
176bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson
17730e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  // Check the command complete header values against what we expect
17830e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  if (expected_opcode != NO_OPCODE_CHECKING) {
17930e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson    assert(opcode == expected_opcode);
18030e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  }
18130e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
18230e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  // Assume the next field is the status field
18330e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  STREAM_TO_UINT8(status, stream);
18430e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  // Make sure it was successful
18530e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  assert(status == HCI_SUCCESS);
18630e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
18730e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  return stream;
188bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson}
189bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson
190bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnsonstatic const hci_packet_parser_t interface = {
19130e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  parse_generic_command_complete,
192bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson  parse_read_buffer_size_response,
19330e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  parse_read_local_version_info_response,
19430e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  parse_read_bd_addr_response,
19530e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  parse_read_local_supported_commands_response,
19630e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  parse_read_local_extended_features_response,
19730e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  parse_ble_read_white_list_size_response,
19830e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  parse_ble_read_buffer_size_response,
19930e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  parse_ble_read_supported_states_response,
20030e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  parse_ble_read_local_supported_features_response
201bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson};
202bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson
203bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnsonconst hci_packet_parser_t *hci_packet_parser_get_interface() {
20430e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  buffer_allocator = buffer_allocator_get_interface();
20530e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  return &interface;
20630e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson}
20730e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson
20830e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnsonconst hci_packet_parser_t *hci_packet_parser_get_test_interface(
20930e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson    allocator_t *buffer_allocator_interface) {
21030e58068c1adaac7c5ccb3aa9cfb045d41d2a10eZach Johnson  buffer_allocator = buffer_allocator_interface;
211bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson  return &interface;
212bf8193bc81cc077e3acd245cacbe8e3789c4b9ffZach Johnson}
213