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     if (stream) {
190         STREAM_TO_UINT8(*resolving_list_size_ptr, stream);
191     }
192 
193     osi_free(response);
194 }
195 
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)196 static void parse_ble_read_suggested_default_data_length_response(
197     BT_HDR *response,
198     uint16_t *ble_default_packet_length_ptr,
199     uint16_t *ble_default_packet_txtime_ptr)
200 {
201 
202     uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_DEFAULT_DATA_LENGTH, 2 /* bytes after */);
203     if (stream) {
204         STREAM_TO_UINT16(*ble_default_packet_length_ptr, stream);
205         STREAM_TO_UINT16(*ble_default_packet_txtime_ptr, stream);
206     }
207 
208     osi_free(response);
209 }
210 
211 #if (BLE_50_FEATURE_SUPPORT == TRUE)
parse_ble_read_adv_max_len_response(BT_HDR * response,uint16_t * adv_max_len_ptr)212 static void parse_ble_read_adv_max_len_response(
213     BT_HDR *response,
214     uint16_t *adv_max_len_ptr)
215 {
216 
217     uint8_t *stream = read_command_complete_header(response, HCI_BLE_RD_MAX_ADV_DATA_LEN, 1 /* bytes after */);
218     if (stream) {
219         // Size: 2 Octets ; Value: 0x001F – 0x0672 ; Maximum supported advertising data length
220         STREAM_TO_UINT16(*adv_max_len_ptr, stream);
221     }
222     osi_free(response);
223 }
224 #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
225 
226 
227 // Internal functions
228 
read_command_complete_header(BT_HDR * response,command_opcode_t expected_opcode,size_t minimum_bytes_after)229 static uint8_t *read_command_complete_header(
230     BT_HDR *response,
231     command_opcode_t expected_opcode,
232     size_t minimum_bytes_after)
233 {
234 
235     uint8_t *stream = response->data + response->offset;
236 
237     // Read the event header
238     uint8_t event_code __attribute__((unused));
239     uint8_t parameter_length __attribute__((unused));
240     STREAM_TO_UINT8(event_code, stream);
241     STREAM_TO_UINT8(parameter_length, stream);
242 
243     const size_t parameter_bytes_we_read_here  __attribute__((unused)) = 4;
244 
245     // Check the event header values against what we expect
246     assert(event_code == HCI_COMMAND_COMPLETE_EVT);
247     assert(parameter_length >= (parameter_bytes_we_read_here + minimum_bytes_after));
248 
249     // Read the command complete header
250     command_opcode_t opcode __attribute__((unused));
251     uint8_t status;
252     STREAM_SKIP_UINT8(stream); // skip the number of hci command packets field
253     STREAM_TO_UINT16(opcode, stream);
254 
255     // Check the command complete header values against what we expect
256     if (expected_opcode != NO_OPCODE_CHECKING) {
257         assert(opcode == expected_opcode);
258     }
259 
260     // Assume the next field is the status field
261     STREAM_TO_UINT8(status, stream);
262 
263     if (status != HCI_SUCCESS) {
264         HCI_TRACE_ERROR("%s failed: opcode 0x%04x, status 0x%02x", __func__, opcode, status);
265         return NULL;
266     }
267 
268     return stream;
269 }
270 
271 static const hci_packet_parser_t interface = {
272     parse_generic_command_complete,
273     parse_read_buffer_size_response,
274     parse_read_local_version_info_response,
275     parse_read_bd_addr_response,
276     parse_read_local_supported_commands_response,
277     parse_read_local_supported_features_response,
278     parse_read_local_extended_features_response,
279     parse_ble_read_white_list_size_response,
280     parse_ble_read_buffer_size_response,
281     parse_ble_read_supported_states_response,
282     parse_ble_read_local_supported_features_response,
283     parse_ble_read_resolving_list_size_response,
284 #if (BLE_50_FEATURE_SUPPORT == TRUE)
285     parse_ble_read_adv_max_len_response,
286 #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
287     parse_ble_read_suggested_default_data_length_response
288 };
289 
hci_packet_parser_get_interface(void)290 const hci_packet_parser_t *hci_packet_parser_get_interface(void)
291 {
292     return &interface;
293 }
294