1 /*
2 * Copyright (C) 2020 BlueKitchen GmbH
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the copyright holders nor the names of
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * 4. Any redistribution, use, or modification is done solely for
17 * personal benefit and not for any commercial purpose or for
18 * monetary gain.
19 *
20 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
24 * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * Please inquire about commercial licensing options at
34 * [email protected]
35 *
36 */
37
38 #define BTSTACK_FILE__ "hci_event.c"
39
40 /*
41 * hci_event.c
42 */
43
44 #include "btstack_config.h"
45
46 #include "hci.h"
47 #include "hci_event.h"
48 #include "btstack_defines.h"
49 #include "btstack_debug.h"
50
51 #include <string.h>
52
hci_event_can_store(uint16_t pos,uint16_t size,uint16_t to_store,bool * overrun)53 static inline bool hci_event_can_store(uint16_t pos, uint16_t size, uint16_t to_store, bool *overrun) {
54 if ((pos + to_store) > size) {
55 *overrun = true;
56 return false;
57 } else {
58 return true;
59 }
60 }
61
62 /**
63 * construct HCI Event based on template
64 *
65 * Format:
66 * 1,2,3,4: one to four byte value
67 * H: HCI connection handle
68 * B: Bluetooth Baseband Address (BD_ADDR)
69 * D: 8 byte data block
70 * P: 16 byte data block.
71 * Q: 32 byte data block, e.g. for X and Y coordinates of P-256 public key
72 * J: 1-byte lenght of following variable-length data blob 'V'
73 * K: 1-byte length of following variable-length data blob 'V', length is not included in packet
74 * V: variable-length data blob of len provided in 'J' field
75 */
hci_event_create_from_template_and_arglist(uint8_t * hci_event_buffer,uint16_t buffer_size,const hci_event_t * event,va_list argptr)76 uint16_t hci_event_create_from_template_and_arglist(uint8_t *hci_event_buffer, uint16_t buffer_size, const hci_event_t *event, va_list argptr){
77
78 hci_event_buffer[0] = event->event_code;
79 hci_event_buffer[1] = 0;
80
81 uint16_t pos = 2;
82
83 // store subevent code if set
84 if (event->subevent_code != 0){
85 hci_event_buffer[pos++] = event->subevent_code;
86 }
87
88 const char *format = event->format;
89 uint16_t word;
90 uint32_t longword;
91 uint8_t * ptr;
92 uint16_t length_j = 0xffff;
93 bool overrun = false;
94 while (*format != 0) {
95 switch(*format) {
96 case '1': // 8 bit value
97 if (!hci_event_can_store(pos, buffer_size, 1, &overrun)) break;
98 word = va_arg(argptr, int); // minimal va_arg is int: 2 bytes on 8+16 bit CPUs
99 hci_event_buffer[pos++] = word & 0xff;
100 break;
101 case '2': // 16 bit value
102 case 'H': // hci_handle
103 if (!hci_event_can_store(pos, buffer_size, 2, &overrun)) break;
104 word = va_arg(argptr, int); // minimal va_arg is int: 2 bytes on 8+16 bit CPUs
105 little_endian_store_16(hci_event_buffer, pos, word);
106 pos += 2;
107 break;
108 case '3':
109 if (!hci_event_can_store(pos, buffer_size, 3, &overrun)) break;
110 longword = va_arg(argptr, uint32_t);
111 little_endian_store_24(hci_event_buffer, pos, longword);
112 pos += 3;
113 break;
114 case '4':
115 if (!hci_event_can_store(pos, buffer_size, 4, &overrun)) break;
116 longword = va_arg(argptr, uint32_t);
117 little_endian_store_32(hci_event_buffer, pos, longword);
118 pos += 4;
119 break;
120 case 'B': // bt-addr
121 if (!hci_event_can_store(pos, buffer_size, 6, &overrun)) break;
122 ptr = va_arg(argptr, uint8_t *);
123 reverse_bytes(ptr, &hci_event_buffer[pos], 6);
124 pos += 6;
125 break;
126 case 'Q':
127 if (!hci_event_can_store(pos, buffer_size, 32, &overrun)) break;
128 ptr = va_arg(argptr, uint8_t *);
129 reverse_bytes(ptr, &hci_event_buffer[pos], 32);
130 pos += 32;
131 break;
132 case 'J':
133 if (!hci_event_can_store(pos, buffer_size, 1, &overrun)) break;
134 word = va_arg(argptr, int); // minimal va_arg is int: 2 bytes on 8+16 bit CPUs
135 length_j = word & 0xff;
136 hci_event_buffer[pos++] = (uint8_t) length_j;
137 break;
138 case 'K':
139 word = va_arg(argptr, int); // minimal va_arg is int: 2 bytes on 8+16 bit CPUs
140 length_j = word & 0xff;
141 break;
142 case 'V':
143 btstack_assert(length_j < 0x100);
144 if (!hci_event_can_store(pos, buffer_size, length_j, &overrun)) break;
145 ptr = va_arg(argptr, uint8_t *);
146 (void)memcpy(&hci_event_buffer[pos], ptr, length_j);
147 pos += length_j;
148 break;
149 default:
150 btstack_assert(false);
151 break;
152 }
153 if (overrun){
154 return 0;
155 }
156 format++;
157 };
158
159 // store final event len
160 hci_event_buffer[1] = pos - 2;
161 return pos;
162 }
163
hci_event_create_from_template_and_arguments(uint8_t * hci_buffer,uint16_t buffer_size,const hci_event_t * event,...)164 uint16_t hci_event_create_from_template_and_arguments(uint8_t *hci_buffer, uint16_t buffer_size, const hci_event_t *event, ...){
165 va_list argptr;
166 va_start(argptr, event);
167 uint16_t length = hci_event_create_from_template_and_arglist(hci_buffer, buffer_size, event, argptr);
168 va_end(argptr);
169 return length;
170 }
171
172 /* HCI Events */
173
174 const hci_event_t hci_event_hardware_error = {
175 HCI_EVENT_HARDWARE_ERROR, 0, "1"
176 };
177
178 const hci_event_t hci_event_transport_packet_sent = {
179 HCI_EVENT_TRANSPORT_PACKET_SENT, 0, ""
180 };
181
182 const hci_event_t hci_event_command_complete = {
183 HCI_EVENT_COMMAND_COMPLETE, 0, "121KV"
184 };
185
186 const hci_event_t hci_event_disconnection_complete = {
187 HCI_EVENT_DISCONNECTION_COMPLETE, 0, "1H1"
188 };
189
190 const hci_event_t hci_event_number_of_completed_packets_1 = {
191 HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS, 0, "1H2"
192 };
193
194 /* LE Subevents */
195
196 const hci_event_t hci_subevent_le_connection_complete = {
197 HCI_EVENT_LE_META, HCI_SUBEVENT_LE_CONNECTION_COMPLETE, "1H11B2221"
198 };
199