hci_packet_parser.cc revision 85e22b32ec3482a09dc019ee6fd096a31fd1bf64
1/******************************************************************************
2 *
3 *  Copyright (C) 2014 Google, Inc.
4 *
5 *  Licensed under the Apache License, Version 2.0 (the "License");
6 *  you may not use this file except in compliance with the License.
7 *  You may obtain a copy of the License at:
8 *
9 *  http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 *
17 ******************************************************************************/
18
19#define LOG_TAG "bt_hci"
20
21#include "hci_packet_parser.h"
22
23#include <assert.h>
24
25#include "buffer_allocator.h"
26#include "hci_layer.h"
27#include "hcimsgs.h"
28#include "osi/include/log.h"
29
30static const command_opcode_t NO_OPCODE_CHECKING = 0;
31
32static const allocator_t *buffer_allocator;
33
34static uint8_t *read_command_complete_header(
35  BT_HDR *response,
36  command_opcode_t expected_opcode,
37  size_t minimum_bytes_after);
38
39static void parse_generic_command_complete(BT_HDR *response) {
40  read_command_complete_header(response, NO_OPCODE_CHECKING, 0 /* bytes after */);
41
42  buffer_allocator->free(response);
43}
44
45static void parse_read_buffer_size_response(
46    BT_HDR *response,
47    uint16_t *data_size_ptr,
48    uint16_t *acl_buffer_count_ptr) {
49
50  uint8_t *stream = read_command_complete_header(response, HCI_READ_BUFFER_SIZE, 5 /* bytes after */);
51  assert(stream != NULL);
52  STREAM_TO_UINT16(*data_size_ptr, stream);
53  STREAM_SKIP_UINT8(stream); // skip the sco packet length
54  STREAM_TO_UINT16(*acl_buffer_count_ptr, stream);
55
56  buffer_allocator->free(response);
57}
58
59static void parse_read_local_version_info_response(
60    BT_HDR *response,
61    bt_version_t *bt_version) {
62
63  uint8_t *stream = read_command_complete_header(response, HCI_READ_LOCAL_VERSION_INFO, 8 /* bytes after */);
64  assert(stream != NULL);
65  STREAM_TO_UINT8(bt_version->hci_version, stream);
66  STREAM_TO_UINT16(bt_version->hci_revision, stream);
67  STREAM_TO_UINT8(bt_version->lmp_version, stream);
68  STREAM_TO_UINT16(bt_version->manufacturer, stream);
69  STREAM_TO_UINT16(bt_version->lmp_subversion, stream);
70
71  buffer_allocator->free(response);
72}
73
74static void parse_read_local_supported_codecs_response(
75    BT_HDR *response,
76    uint8_t *number_of_local_supported_codecs, uint8_t *local_supported_codecs) {
77
78  uint8_t *stream = read_command_complete_header(response, HCI_READ_LOCAL_SUPPORTED_CODECS, 0 /* bytes after */);
79  if(stream) {
80    STREAM_TO_UINT8(*number_of_local_supported_codecs, stream);
81    for ( uint8_t i = 0; i < *number_of_local_supported_codecs; i++)
82    {
83      STREAM_TO_UINT8(*local_supported_codecs, stream);
84      local_supported_codecs++;
85    }
86  }
87
88  buffer_allocator->free(response);
89}
90
91static void parse_read_bd_addr_response(
92    BT_HDR *response,
93    bt_bdaddr_t *address_ptr) {
94
95  uint8_t *stream = read_command_complete_header(response, HCI_READ_BD_ADDR, sizeof(bt_bdaddr_t) /* bytes after */);
96  assert(stream != NULL);
97  STREAM_TO_BDADDR(address_ptr->address, stream);
98
99  buffer_allocator->free(response);
100}
101
102static void parse_read_local_supported_commands_response(
103    BT_HDR *response,
104    uint8_t *supported_commands_ptr,
105    size_t supported_commands_length) {
106
107  uint8_t *stream = read_command_complete_header(response, HCI_READ_LOCAL_SUPPORTED_CMDS, supported_commands_length /* bytes after */);
108  assert(stream != NULL);
109  STREAM_TO_ARRAY(supported_commands_ptr, stream, (int)supported_commands_length);
110
111  buffer_allocator->free(response);
112}
113
114static void parse_read_local_extended_features_response(
115    BT_HDR *response,
116    uint8_t *page_number_ptr,
117    uint8_t *max_page_number_ptr,
118    bt_device_features_t *feature_pages,
119    size_t feature_pages_count) {
120
121  uint8_t *stream = read_command_complete_header(response, HCI_READ_LOCAL_EXT_FEATURES, 2 + sizeof(bt_device_features_t) /* bytes after */);
122  if (stream != NULL) {
123    STREAM_TO_UINT8(*page_number_ptr, stream);
124    STREAM_TO_UINT8(*max_page_number_ptr, stream);
125
126    assert(*page_number_ptr < feature_pages_count);
127    STREAM_TO_ARRAY(feature_pages[*page_number_ptr].as_array, stream, (int)sizeof(bt_device_features_t));
128  } else {
129    LOG_ERROR(LOG_TAG, "%s() - WARNING: READING EXTENDED FEATURES FAILED. "
130                "THIS MAY INDICATE A FIRMWARE/CONTROLLER ISSUE.", __func__);
131  }
132
133  buffer_allocator->free(response);
134}
135
136static void parse_ble_read_white_list_size_response(
137    BT_HDR *response,
138    uint8_t *white_list_size_ptr) {
139
140  uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_WHITE_LIST_SIZE, 1 /* byte after */);
141  assert(stream != NULL);
142  STREAM_TO_UINT8(*white_list_size_ptr, stream);
143
144  buffer_allocator->free(response);
145}
146
147static void parse_ble_read_buffer_size_response(
148    BT_HDR *response,
149    uint16_t *data_size_ptr,
150    uint8_t *acl_buffer_count_ptr) {
151
152  uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_BUFFER_SIZE, 3 /* bytes after */);
153  assert(stream != NULL);
154  STREAM_TO_UINT16(*data_size_ptr, stream);
155  STREAM_TO_UINT8(*acl_buffer_count_ptr, stream);
156
157  buffer_allocator->free(response);
158}
159
160static void parse_ble_read_supported_states_response(
161    BT_HDR *response,
162    uint8_t *supported_states,
163    size_t supported_states_size) {
164
165  uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_SUPPORTED_STATES, supported_states_size /* bytes after */);
166  assert(stream != NULL);
167  STREAM_TO_ARRAY(supported_states, stream, (int)supported_states_size);
168
169  buffer_allocator->free(response);
170}
171
172static void parse_ble_read_local_supported_features_response(
173    BT_HDR *response,
174    bt_device_features_t *supported_features) {
175
176  uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_LOCAL_SPT_FEAT, sizeof(bt_device_features_t) /* bytes after */);
177  assert(stream != NULL);
178  STREAM_TO_ARRAY(supported_features->as_array, stream, (int)sizeof(bt_device_features_t));
179
180  buffer_allocator->free(response);
181}
182
183static void parse_ble_read_resolving_list_size_response(
184    BT_HDR *response,
185    uint8_t *resolving_list_size_ptr) {
186
187  uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_RESOLVING_LIST_SIZE, 1 /* bytes after */);
188  STREAM_TO_UINT8(*resolving_list_size_ptr, stream);
189
190  buffer_allocator->free(response);
191}
192
193static void parse_ble_read_suggested_default_data_length_response(
194    BT_HDR *response,
195    uint16_t *ble_default_packet_length_ptr) {
196
197  uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_DEFAULT_DATA_LENGTH, 2 /* bytes after */);
198  STREAM_TO_UINT8(*ble_default_packet_length_ptr, stream);
199
200  buffer_allocator->free(response);
201}
202
203// Internal functions
204
205static uint8_t *read_command_complete_header(
206    BT_HDR *response,
207    command_opcode_t expected_opcode,
208    size_t minimum_bytes_after) {
209
210  uint8_t *stream = response->data + response->offset;
211
212  // Read the event header
213  uint8_t event_code;
214  uint8_t parameter_length;
215  STREAM_TO_UINT8(event_code, stream);
216  STREAM_TO_UINT8(parameter_length, stream);
217
218  const size_t parameter_bytes_we_read_here = 4;
219
220  // Check the event header values against what we expect
221  assert(event_code == HCI_COMMAND_COMPLETE_EVT);
222  assert(parameter_length >= (parameter_bytes_we_read_here + minimum_bytes_after));
223
224  // Read the command complete header
225  command_opcode_t opcode;
226  uint8_t status;
227  STREAM_SKIP_UINT8(stream); // skip the number of hci command packets field
228  STREAM_TO_UINT16(opcode, stream);
229
230  // Check the command complete header values against what we expect
231  if (expected_opcode != NO_OPCODE_CHECKING) {
232    assert(opcode == expected_opcode);
233  }
234
235  // Assume the next field is the status field
236  STREAM_TO_UINT8(status, stream);
237
238  if (status != HCI_SUCCESS){
239    LOG_ERROR(LOG_TAG, "%s: return status - 0x%x", __func__, status);
240    return NULL;
241  }
242
243  return stream;
244}
245
246static const hci_packet_parser_t interface = {
247  parse_generic_command_complete,
248  parse_read_buffer_size_response,
249  parse_read_local_version_info_response,
250  parse_read_bd_addr_response,
251  parse_read_local_supported_commands_response,
252  parse_read_local_extended_features_response,
253  parse_ble_read_white_list_size_response,
254  parse_ble_read_buffer_size_response,
255  parse_ble_read_supported_states_response,
256  parse_ble_read_local_supported_features_response,
257  parse_ble_read_resolving_list_size_response,
258  parse_ble_read_suggested_default_data_length_response,
259  parse_read_local_supported_codecs_response
260};
261
262const hci_packet_parser_t *hci_packet_parser_get_interface() {
263  buffer_allocator = buffer_allocator_get_interface();
264  return &interface;
265}
266
267const hci_packet_parser_t *hci_packet_parser_get_test_interface(
268    allocator_t *buffer_allocator_interface) {
269  buffer_allocator = buffer_allocator_interface;
270  return &interface;
271}
272