xref: /btstack/src/hci_event.c (revision c69c1cf86b3b19124e0e92019ae55fc41bfe9a4e)
17d902a1fSMatthias Ringwald /*
27d902a1fSMatthias Ringwald  * Copyright (C) 2020 BlueKitchen GmbH
37d902a1fSMatthias Ringwald  *
47d902a1fSMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
57d902a1fSMatthias Ringwald  * modification, are permitted provided that the following conditions
67d902a1fSMatthias Ringwald  * are met:
77d902a1fSMatthias Ringwald  *
87d902a1fSMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
97d902a1fSMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
107d902a1fSMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
117d902a1fSMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
127d902a1fSMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
137d902a1fSMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
147d902a1fSMatthias Ringwald  *    contributors may be used to endorse or promote products derived
157d902a1fSMatthias Ringwald  *    from this software without specific prior written permission.
167d902a1fSMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
177d902a1fSMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
187d902a1fSMatthias Ringwald  *    monetary gain.
197d902a1fSMatthias Ringwald  *
207d902a1fSMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
217d902a1fSMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
227d902a1fSMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
237d902a1fSMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
247d902a1fSMatthias Ringwald  * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
257d902a1fSMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
267d902a1fSMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
277d902a1fSMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
287d902a1fSMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
297d902a1fSMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
307d902a1fSMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
317d902a1fSMatthias Ringwald  * SUCH DAMAGE.
327d902a1fSMatthias Ringwald  *
337d902a1fSMatthias Ringwald  * Please inquire about commercial licensing options at
347d902a1fSMatthias Ringwald  * [email protected]
357d902a1fSMatthias Ringwald  *
367d902a1fSMatthias Ringwald  */
377d902a1fSMatthias Ringwald 
387d902a1fSMatthias Ringwald #define BTSTACK_FILE__ "hci_event.c"
397d902a1fSMatthias Ringwald 
407d902a1fSMatthias Ringwald /*
417d902a1fSMatthias Ringwald  *  hci_event.c
427d902a1fSMatthias Ringwald  */
437d902a1fSMatthias Ringwald 
447d902a1fSMatthias Ringwald #include "btstack_config.h"
457d902a1fSMatthias Ringwald 
467d902a1fSMatthias Ringwald #include "hci.h"
477d902a1fSMatthias Ringwald #include "hci_event.h"
487d902a1fSMatthias Ringwald #include "btstack_defines.h"
497d902a1fSMatthias Ringwald #include "btstack_debug.h"
507d902a1fSMatthias Ringwald 
517d902a1fSMatthias Ringwald #include <string.h>
527d902a1fSMatthias Ringwald 
hci_event_can_store(uint16_t pos,uint16_t size,uint16_t to_store,bool * overrun)53fe70ee48SMatthias Ringwald static inline bool hci_event_can_store(uint16_t pos, uint16_t size, uint16_t to_store, bool *overrun) {
54fe70ee48SMatthias Ringwald     if ((pos + to_store) > size) {
55fe70ee48SMatthias Ringwald         *overrun = true;
56fe70ee48SMatthias Ringwald         return false;
57fe70ee48SMatthias Ringwald     } else {
58fe70ee48SMatthias Ringwald         return true;
59fe70ee48SMatthias Ringwald     }
60fe70ee48SMatthias Ringwald }
61fe70ee48SMatthias Ringwald 
627d902a1fSMatthias Ringwald /**
637d902a1fSMatthias Ringwald  * construct HCI Event based on template
647d902a1fSMatthias Ringwald  *
657d902a1fSMatthias Ringwald  * Format:
667d902a1fSMatthias Ringwald  *   1,2,3,4: one to four byte value
677d902a1fSMatthias Ringwald  *   H: HCI connection handle
687d902a1fSMatthias Ringwald  *   B: Bluetooth Baseband Address (BD_ADDR)
697d902a1fSMatthias Ringwald  *   D: 8 byte data block
707d902a1fSMatthias Ringwald  *   P: 16 byte data block.
717d902a1fSMatthias Ringwald  *   Q: 32 byte data block, e.g. for X and Y coordinates of P-256 public key
727d902a1fSMatthias Ringwald  *   J: 1-byte lenght of following variable-length data blob 'V'
737d902a1fSMatthias Ringwald  *   K: 1-byte length of following variable-length data blob 'V', length is not included in packet
747d902a1fSMatthias Ringwald  *   V: variable-length data blob of len provided in 'J' field
757d902a1fSMatthias Ringwald  */
hci_event_create_from_template_and_arglist(uint8_t * hci_event_buffer,uint16_t buffer_size,const hci_event_t * event,va_list argptr)76c70b3b48SMatthias Ringwald 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){
77c70b3b48SMatthias Ringwald 
787d902a1fSMatthias Ringwald     hci_event_buffer[0] = event->event_code;
79fe70ee48SMatthias Ringwald     hci_event_buffer[1] = 0;
80fe70ee48SMatthias Ringwald 
817d902a1fSMatthias Ringwald     uint16_t pos = 2;
827d902a1fSMatthias Ringwald 
837d902a1fSMatthias Ringwald     // store subevent code if set
847d902a1fSMatthias Ringwald     if (event->subevent_code != 0){
857d902a1fSMatthias Ringwald         hci_event_buffer[pos++] = event->subevent_code;
867d902a1fSMatthias Ringwald     }
877d902a1fSMatthias Ringwald 
887d902a1fSMatthias Ringwald     const char *format = event->format;
897d902a1fSMatthias Ringwald     uint16_t word;
907d902a1fSMatthias Ringwald     uint32_t longword;
917d902a1fSMatthias Ringwald     uint8_t * ptr;
927d902a1fSMatthias Ringwald     uint16_t length_j = 0xffff;
93fe70ee48SMatthias Ringwald     bool overrun = false;
94fe70ee48SMatthias Ringwald     while (*format != 0) {
957d902a1fSMatthias Ringwald         switch(*format) {
967d902a1fSMatthias Ringwald             case '1': //  8 bit value
97fe70ee48SMatthias Ringwald                 if (!hci_event_can_store(pos, buffer_size, 1, &overrun)) break;
987d902a1fSMatthias Ringwald                 word = va_arg(argptr, int);  // minimal va_arg is int: 2 bytes on 8+16 bit CPUs
997d902a1fSMatthias Ringwald                 hci_event_buffer[pos++] = word & 0xff;
100fe70ee48SMatthias Ringwald                 break;
101fe70ee48SMatthias Ringwald             case '2': // 16 bit value
102fe70ee48SMatthias Ringwald             case 'H': // hci_handle
103fe70ee48SMatthias Ringwald                 if (!hci_event_can_store(pos, buffer_size, 2, &overrun)) break;
104fe70ee48SMatthias Ringwald                 word = va_arg(argptr, int);  // minimal va_arg is int: 2 bytes on 8+16 bit CPUs
105fe70ee48SMatthias Ringwald                 little_endian_store_16(hci_event_buffer, pos, word);
106fe70ee48SMatthias Ringwald                 pos += 2;
1077d902a1fSMatthias Ringwald                 break;
1087d902a1fSMatthias Ringwald             case '3':
109fe70ee48SMatthias Ringwald                 if (!hci_event_can_store(pos, buffer_size, 3, &overrun)) break;
1107d902a1fSMatthias Ringwald                 longword = va_arg(argptr, uint32_t);
111fe70ee48SMatthias Ringwald                 little_endian_store_24(hci_event_buffer, pos, longword);
112fe70ee48SMatthias Ringwald                 pos += 3;
113fe70ee48SMatthias Ringwald                 break;
114fe70ee48SMatthias Ringwald             case '4':
115fe70ee48SMatthias Ringwald                 if (!hci_event_can_store(pos, buffer_size, 4, &overrun)) break;
116fe70ee48SMatthias Ringwald                 longword = va_arg(argptr, uint32_t);
117fe70ee48SMatthias Ringwald                 little_endian_store_32(hci_event_buffer, pos, longword);
118fe70ee48SMatthias Ringwald                 pos += 4;
1197d902a1fSMatthias Ringwald                 break;
1207d902a1fSMatthias Ringwald             case 'B': // bt-addr
121fe70ee48SMatthias Ringwald                 if (!hci_event_can_store(pos, buffer_size, 6, &overrun)) break;
1227d902a1fSMatthias Ringwald                 ptr = va_arg(argptr, uint8_t *);
123fe70ee48SMatthias Ringwald                 reverse_bytes(ptr, &hci_event_buffer[pos], 6);
1247741b155SMatthias Ringwald                 pos += 6;
1257d902a1fSMatthias Ringwald                 break;
1267d902a1fSMatthias Ringwald             case 'Q':
127fe70ee48SMatthias Ringwald                 if (!hci_event_can_store(pos, buffer_size, 32, &overrun)) break;
1287d902a1fSMatthias Ringwald                 ptr = va_arg(argptr, uint8_t *);
1297d902a1fSMatthias Ringwald                 reverse_bytes(ptr, &hci_event_buffer[pos], 32);
1307d902a1fSMatthias Ringwald                 pos += 32;
1317d902a1fSMatthias Ringwald                 break;
1327d902a1fSMatthias Ringwald             case 'J':
133fe70ee48SMatthias Ringwald                 if (!hci_event_can_store(pos, buffer_size, 1, &overrun)) break;
1347d902a1fSMatthias Ringwald                 word = va_arg(argptr, int);  // minimal va_arg is int: 2 bytes on 8+16 bit CPUs
1357d902a1fSMatthias Ringwald                 length_j = word & 0xff;
136*c69c1cf8SMatthias Ringwald                 hci_event_buffer[pos++] = (uint8_t) length_j;
1377d902a1fSMatthias Ringwald                 break;
1387d902a1fSMatthias Ringwald             case 'K':
1397d902a1fSMatthias Ringwald                 word = va_arg(argptr, int);  // minimal va_arg is int: 2 bytes on 8+16 bit CPUs
1407d902a1fSMatthias Ringwald                 length_j = word & 0xff;
1417d902a1fSMatthias Ringwald                 break;
1427d902a1fSMatthias Ringwald             case 'V':
1437d902a1fSMatthias Ringwald                 btstack_assert(length_j < 0x100);
144fe70ee48SMatthias Ringwald                 if (!hci_event_can_store(pos, buffer_size, length_j, &overrun)) break;
1457d902a1fSMatthias Ringwald                 ptr = va_arg(argptr, uint8_t *);
1467d902a1fSMatthias Ringwald                 (void)memcpy(&hci_event_buffer[pos], ptr, length_j);
1477d902a1fSMatthias Ringwald                 pos += length_j;
1487d902a1fSMatthias Ringwald                 break;
1497d902a1fSMatthias Ringwald             default:
1507d902a1fSMatthias Ringwald                 btstack_assert(false);
1517d902a1fSMatthias Ringwald                 break;
1527d902a1fSMatthias Ringwald         }
153fe70ee48SMatthias Ringwald         if (overrun){
154fe70ee48SMatthias Ringwald             return 0;
155fe70ee48SMatthias Ringwald         }
1567d902a1fSMatthias Ringwald         format++;
1577d902a1fSMatthias Ringwald     };
158fe70ee48SMatthias Ringwald 
159fe70ee48SMatthias Ringwald     // store final event len
1607d902a1fSMatthias Ringwald     hci_event_buffer[1] = pos - 2;
1617d902a1fSMatthias Ringwald     return pos;
1627d902a1fSMatthias Ringwald }
1637d902a1fSMatthias Ringwald 
hci_event_create_from_template_and_arguments(uint8_t * hci_buffer,uint16_t buffer_size,const hci_event_t * event,...)164c70b3b48SMatthias Ringwald uint16_t hci_event_create_from_template_and_arguments(uint8_t *hci_buffer, uint16_t buffer_size, const hci_event_t *event, ...){
1657d902a1fSMatthias Ringwald     va_list argptr;
1667d902a1fSMatthias Ringwald     va_start(argptr, event);
167c70b3b48SMatthias Ringwald     uint16_t length = hci_event_create_from_template_and_arglist(hci_buffer, buffer_size, event, argptr);
1687d902a1fSMatthias Ringwald     va_end(argptr);
1697d902a1fSMatthias Ringwald     return length;
1707d902a1fSMatthias Ringwald }
1717d902a1fSMatthias Ringwald 
1727d902a1fSMatthias Ringwald /* HCI Events */
1737d902a1fSMatthias Ringwald 
1747d902a1fSMatthias Ringwald const hci_event_t hci_event_hardware_error = {
1757d902a1fSMatthias Ringwald     HCI_EVENT_HARDWARE_ERROR, 0, "1"
1767d902a1fSMatthias Ringwald };
1777d902a1fSMatthias Ringwald 
1787d902a1fSMatthias Ringwald const hci_event_t hci_event_transport_packet_sent = {
1797d902a1fSMatthias Ringwald         HCI_EVENT_TRANSPORT_PACKET_SENT, 0, ""
1807d902a1fSMatthias Ringwald };
1817d902a1fSMatthias Ringwald 
1827d902a1fSMatthias Ringwald const hci_event_t hci_event_command_complete = {
1837d902a1fSMatthias Ringwald     HCI_EVENT_COMMAND_COMPLETE, 0, "121KV"
1847d902a1fSMatthias Ringwald };
1857d902a1fSMatthias Ringwald 
1867d902a1fSMatthias Ringwald const hci_event_t hci_event_disconnection_complete = {
1877d902a1fSMatthias Ringwald     HCI_EVENT_DISCONNECTION_COMPLETE, 0, "1H1"
1887d902a1fSMatthias Ringwald };
1897d902a1fSMatthias Ringwald 
1907d902a1fSMatthias Ringwald const hci_event_t hci_event_number_of_completed_packets_1 = {
1917d902a1fSMatthias Ringwald     HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS, 0, "1H2"
1927d902a1fSMatthias Ringwald };
1937d902a1fSMatthias Ringwald 
1947d902a1fSMatthias Ringwald /* LE Subevents */
1957d902a1fSMatthias Ringwald 
1967d902a1fSMatthias Ringwald const hci_event_t hci_subevent_le_connection_complete = {
1977d902a1fSMatthias Ringwald     HCI_EVENT_LE_META, HCI_SUBEVENT_LE_CONNECTION_COMPLETE, "1H11B2221"
1987d902a1fSMatthias Ringwald };
199