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 #include "common/bt_defs.h"
20
21 #include "stack/bt_types.h"
22 #include "stack/hcimsgs.h"
23 #include "hci/hci_layer.h"
24 #include "hci/hci_packet_parser.h"
25
26 static const command_opcode_t NO_OPCODE_CHECKING = 0;
27
28 static uint8_t *read_command_complete_header(
29 BT_HDR *response,
30 command_opcode_t expected_opcode,
31 size_t minimum_bytes_after);
32
parse_generic_command_complete(BT_HDR * response)33 static void parse_generic_command_complete(BT_HDR *response)
34 {
35 read_command_complete_header(response, NO_OPCODE_CHECKING, 0 /* bytes after */);
36
37 osi_free(response);
38 }
39
parse_read_buffer_size_response(BT_HDR * response,uint16_t * acl_data_size_ptr,uint16_t * acl_buffer_count_ptr,uint8_t * sco_data_size_ptr,uint16_t * sco_buffer_count_ptr)40 static void parse_read_buffer_size_response(
41 BT_HDR *response,
42 uint16_t *acl_data_size_ptr,
43 uint16_t *acl_buffer_count_ptr,
44 uint8_t *sco_data_size_ptr,
45 uint16_t *sco_buffer_count_ptr)
46 {
47
48 uint8_t *stream = read_command_complete_header(response, HCI_READ_BUFFER_SIZE, 7 /* bytes after */);
49 assert(stream != NULL);
50 STREAM_TO_UINT16(*acl_data_size_ptr, stream);
51 STREAM_TO_UINT8(*sco_data_size_ptr, stream);
52 STREAM_TO_UINT16(*acl_buffer_count_ptr, stream);
53 STREAM_TO_UINT16(*sco_buffer_count_ptr, stream);
54 osi_free(response);
55 }
56
parse_read_local_version_info_response(BT_HDR * response,bt_version_t * bt_version)57 static void parse_read_local_version_info_response(
58 BT_HDR *response,
59 bt_version_t *bt_version)
60 {
61
62 uint8_t *stream = read_command_complete_header(response, HCI_READ_LOCAL_VERSION_INFO, 8 /* bytes after */);
63 assert(stream != NULL);
64 STREAM_TO_UINT8(bt_version->hci_version, stream);
65 STREAM_TO_UINT16(bt_version->hci_revision, stream);
66 STREAM_TO_UINT8(bt_version->lmp_version, stream);
67 STREAM_TO_UINT16(bt_version->manufacturer, stream);
68 STREAM_TO_UINT16(bt_version->lmp_subversion, stream);
69
70 osi_free(response);
71 }
72
parse_read_bd_addr_response(BT_HDR * response,bt_bdaddr_t * address_ptr)73 static void parse_read_bd_addr_response(
74 BT_HDR *response,
75 bt_bdaddr_t *address_ptr)
76 {
77
78 uint8_t *stream = read_command_complete_header(response, HCI_READ_BD_ADDR, sizeof(bt_bdaddr_t) /* bytes after */);
79 assert(stream != NULL);
80 STREAM_TO_BDADDR(address_ptr->address, stream);
81
82 osi_free(response);
83 }
84
parse_read_local_supported_commands_response(BT_HDR * response,uint8_t * supported_commands_ptr,size_t supported_commands_length)85 static void parse_read_local_supported_commands_response(
86 BT_HDR *response,
87 uint8_t *supported_commands_ptr,
88 size_t supported_commands_length)
89 {
90
91 uint8_t *stream = read_command_complete_header(response, HCI_READ_LOCAL_SUPPORTED_CMDS, supported_commands_length /* bytes after */);
92 assert(stream != NULL);
93 STREAM_TO_ARRAY(supported_commands_ptr, stream, (int)supported_commands_length);
94
95 osi_free(response);
96 }
97
parse_read_local_supported_features_response(BT_HDR * response,bt_device_features_t * feature_pages)98 static void parse_read_local_supported_features_response(
99 BT_HDR *response,
100 bt_device_features_t *feature_pages)
101 {
102 uint8_t *stream = read_command_complete_header(response, HCI_READ_LOCAL_FEATURES, sizeof(bt_device_features_t) /* bytes after */);
103 if (stream != NULL) {
104 STREAM_TO_ARRAY(feature_pages->as_array, stream, (int)sizeof(bt_device_features_t));
105 }
106 osi_free(response);
107 }
108
parse_read_local_extended_features_response(BT_HDR * response,uint8_t * page_number_ptr,uint8_t * max_page_number_ptr,bt_device_features_t * feature_pages,size_t feature_pages_count)109 static void parse_read_local_extended_features_response(
110 BT_HDR *response,
111 uint8_t *page_number_ptr,
112 uint8_t *max_page_number_ptr,
113 bt_device_features_t *feature_pages,
114 size_t feature_pages_count)
115 {
116
117 uint8_t *stream = read_command_complete_header(response, HCI_READ_LOCAL_EXT_FEATURES, 2 + sizeof(bt_device_features_t) /* bytes after */);
118 if (stream != NULL) {
119 STREAM_TO_UINT8(*page_number_ptr, stream);
120 STREAM_TO_UINT8(*max_page_number_ptr, stream);
121
122 assert(*page_number_ptr < feature_pages_count);
123 STREAM_TO_ARRAY(feature_pages[*page_number_ptr].as_array, stream, (int)sizeof(bt_device_features_t));
124 } else {
125 HCI_TRACE_ERROR("%s() - WARNING: READING EXTENDED FEATURES FAILED. "
126 "THIS MAY INDICATE A FIRMWARE/CONTROLLER ISSUE.", __func__);
127 }
128
129 osi_free(response);
130 }
131
parse_ble_read_white_list_size_response(BT_HDR * response,uint8_t * white_list_size_ptr)132 static void parse_ble_read_white_list_size_response(
133 BT_HDR *response,
134 uint8_t *white_list_size_ptr)
135 {
136
137 uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_WHITE_LIST_SIZE, 1 /* byte after */);
138 assert(stream != NULL);
139 STREAM_TO_UINT8(*white_list_size_ptr, stream);
140
141 osi_free(response);
142 }
143
parse_ble_read_buffer_size_response(BT_HDR * response,uint16_t * data_size_ptr,uint8_t * acl_buffer_count_ptr)144 static void parse_ble_read_buffer_size_response(
145 BT_HDR *response,
146 uint16_t *data_size_ptr,
147 uint8_t *acl_buffer_count_ptr)
148 {
149
150 uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_BUFFER_SIZE, 3 /* bytes after */);
151 assert(stream != NULL);
152 STREAM_TO_UINT16(*data_size_ptr, stream);
153 STREAM_TO_UINT8(*acl_buffer_count_ptr, stream);
154
155 osi_free(response);
156 }
157
parse_ble_read_supported_states_response(BT_HDR * response,uint8_t * supported_states,size_t supported_states_size)158 static void parse_ble_read_supported_states_response(
159 BT_HDR *response,
160 uint8_t *supported_states,
161 size_t supported_states_size)
162 {
163
164 uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_SUPPORTED_STATES, supported_states_size /* bytes after */);
165 assert(stream != NULL);
166 STREAM_TO_ARRAY(supported_states, stream, (int)supported_states_size);
167
168 osi_free(response);
169 }
170
parse_ble_read_local_supported_features_response(BT_HDR * response,bt_device_features_t * supported_features)171 static void parse_ble_read_local_supported_features_response(
172 BT_HDR *response,
173 bt_device_features_t *supported_features)
174 {
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 osi_free(response);
181 }
182
parse_ble_read_resolving_list_size_response(BT_HDR * response,uint8_t * resolving_list_size_ptr)183 static void parse_ble_read_resolving_list_size_response(
184 BT_HDR *response,
185 uint8_t *resolving_list_size_ptr)
186 {
187
188 uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_RESOLVING_LIST_SIZE, 1 /* bytes after */);
189 STREAM_TO_UINT8(*resolving_list_size_ptr, stream);
190
191 osi_free(response);
192 }
193
parse_ble_read_suggested_default_data_length_response(BT_HDR * response,uint16_t * ble_default_packet_length_ptr,uint16_t * ble_default_packet_txtime_ptr)194 static void parse_ble_read_suggested_default_data_length_response(
195 BT_HDR *response,
196 uint16_t *ble_default_packet_length_ptr,
197 uint16_t *ble_default_packet_txtime_ptr)
198 {
199
200 uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_DEFAULT_DATA_LENGTH, 2 /* bytes after */);
201 STREAM_TO_UINT16(*ble_default_packet_length_ptr, stream);
202 STREAM_TO_UINT16(*ble_default_packet_txtime_ptr, stream);
203 osi_free(response);
204 }
205 #if (BLE_50_FEATURE_SUPPORT == TRUE)
parse_ble_read_adv_max_len_response(BT_HDR * response,uint16_t * adv_max_len_ptr)206 static void parse_ble_read_adv_max_len_response(
207 BT_HDR *response,
208 uint16_t *adv_max_len_ptr)
209 {
210
211 uint8_t *stream = read_command_complete_header(response, HCI_BLE_RD_MAX_ADV_DATA_LEN, 1 /* bytes after */);
212 STREAM_TO_UINT8(*adv_max_len_ptr, stream);
213
214 osi_free(response);
215 }
216 #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
217
218
219 // Internal functions
220
read_command_complete_header(BT_HDR * response,command_opcode_t expected_opcode,size_t minimum_bytes_after)221 static uint8_t *read_command_complete_header(
222 BT_HDR *response,
223 command_opcode_t expected_opcode,
224 size_t minimum_bytes_after)
225 {
226
227 uint8_t *stream = response->data + response->offset;
228
229 // Read the event header
230 uint8_t event_code;
231 uint8_t parameter_length;
232 STREAM_TO_UINT8(event_code, stream);
233 STREAM_TO_UINT8(parameter_length, stream);
234
235 const size_t parameter_bytes_we_read_here = 4;
236
237 // Check the event header values against what we expect
238 assert(event_code == HCI_COMMAND_COMPLETE_EVT);
239 assert(parameter_length >= (parameter_bytes_we_read_here + minimum_bytes_after));
240
241 // Read the command complete header
242 command_opcode_t opcode;
243 uint8_t status;
244 STREAM_SKIP_UINT8(stream); // skip the number of hci command packets field
245 STREAM_TO_UINT16(opcode, stream);
246
247 // Check the command complete header values against what we expect
248 if (expected_opcode != NO_OPCODE_CHECKING) {
249 assert(opcode == expected_opcode);
250 }
251
252 // Assume the next field is the status field
253 STREAM_TO_UINT8(status, stream);
254
255 if (status != HCI_SUCCESS) {
256 return NULL;
257 }
258
259 return stream;
260 }
261
262 static const hci_packet_parser_t interface = {
263 parse_generic_command_complete,
264 parse_read_buffer_size_response,
265 parse_read_local_version_info_response,
266 parse_read_bd_addr_response,
267 parse_read_local_supported_commands_response,
268 parse_read_local_supported_features_response,
269 parse_read_local_extended_features_response,
270 parse_ble_read_white_list_size_response,
271 parse_ble_read_buffer_size_response,
272 parse_ble_read_supported_states_response,
273 parse_ble_read_local_supported_features_response,
274 parse_ble_read_resolving_list_size_response,
275 #if (BLE_50_FEATURE_SUPPORT == TRUE)
276 parse_ble_read_adv_max_len_response,
277 #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
278 parse_ble_read_suggested_default_data_length_response
279 };
280
hci_packet_parser_get_interface(void)281 const hci_packet_parser_t *hci_packet_parser_get_interface(void)
282 {
283 return &interface;
284 }
285