xref: /btstack/src/hci_event.c (revision c70b3b486dde2b96829c110a442a90c62ebfbd82)
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 
537d902a1fSMatthias Ringwald /**
547d902a1fSMatthias Ringwald  * construct HCI Event based on template
557d902a1fSMatthias Ringwald  *
567d902a1fSMatthias Ringwald  * Format:
577d902a1fSMatthias Ringwald  *   1,2,3,4: one to four byte value
587d902a1fSMatthias Ringwald  *   H: HCI connection handle
597d902a1fSMatthias Ringwald  *   B: Bluetooth Baseband Address (BD_ADDR)
607d902a1fSMatthias Ringwald  *   D: 8 byte data block
617d902a1fSMatthias Ringwald  *   P: 16 byte data block.
627d902a1fSMatthias Ringwald  *   Q: 32 byte data block, e.g. for X and Y coordinates of P-256 public key
637d902a1fSMatthias Ringwald  *   J: 1-byte lenght of following variable-length data blob 'V'
647d902a1fSMatthias Ringwald  *   K: 1-byte length of following variable-length data blob 'V', length is not included in packet
657d902a1fSMatthias Ringwald  *   V: variable-length data blob of len provided in 'J' field
667d902a1fSMatthias Ringwald  */
67*c70b3b48SMatthias 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){
68*c70b3b48SMatthias Ringwald 
69*c70b3b48SMatthias Ringwald     UNUSED(buffer_size);
707d902a1fSMatthias Ringwald 
717d902a1fSMatthias Ringwald     hci_event_buffer[0] = event->event_code;
727d902a1fSMatthias Ringwald     uint16_t pos = 2;
737d902a1fSMatthias Ringwald 
747d902a1fSMatthias Ringwald     // store subevent code if set
757d902a1fSMatthias Ringwald     if (event->subevent_code != 0){
767d902a1fSMatthias Ringwald         hci_event_buffer[pos++] = event->subevent_code;
777d902a1fSMatthias Ringwald     }
787d902a1fSMatthias Ringwald 
797d902a1fSMatthias Ringwald     const char *format = event->format;
807d902a1fSMatthias Ringwald     uint16_t word;
817d902a1fSMatthias Ringwald     uint32_t longword;
827d902a1fSMatthias Ringwald     uint8_t * ptr;
837d902a1fSMatthias Ringwald     uint16_t length_j = 0xffff;
847d902a1fSMatthias Ringwald     while (*format) {
857d902a1fSMatthias Ringwald         switch(*format) {
867d902a1fSMatthias Ringwald             case '1': //  8 bit value
877d902a1fSMatthias Ringwald             case '2': // 16 bit value
887d902a1fSMatthias Ringwald             case 'H': // hci_handle
897d902a1fSMatthias Ringwald                 word = va_arg(argptr, int);  // minimal va_arg is int: 2 bytes on 8+16 bit CPUs
907d902a1fSMatthias Ringwald                 hci_event_buffer[pos++] = word & 0xff;
917d902a1fSMatthias Ringwald                 if (*format != '1') {
927d902a1fSMatthias Ringwald                     hci_event_buffer[pos++] = word >> 8;
937d902a1fSMatthias Ringwald                 }
947d902a1fSMatthias Ringwald                 break;
957d902a1fSMatthias Ringwald             case '3':
967d902a1fSMatthias Ringwald             case '4':
977d902a1fSMatthias Ringwald                 longword = va_arg(argptr, uint32_t);
987d902a1fSMatthias Ringwald                 // longword = va_arg(argptr, int);
997d902a1fSMatthias Ringwald                 hci_event_buffer[pos++] = longword;
1007d902a1fSMatthias Ringwald                 hci_event_buffer[pos++] = longword >> 8;
1017d902a1fSMatthias Ringwald                 hci_event_buffer[pos++] = longword >> 16;
1027d902a1fSMatthias Ringwald                 if (*format == '4'){
1037d902a1fSMatthias Ringwald                     hci_event_buffer[pos++] = longword >> 24;
1047d902a1fSMatthias Ringwald                 }
1057d902a1fSMatthias Ringwald                 break;
1067d902a1fSMatthias Ringwald             case 'B': // bt-addr
1077d902a1fSMatthias Ringwald                 ptr = va_arg(argptr, uint8_t *);
1087d902a1fSMatthias Ringwald                 hci_event_buffer[pos++] = ptr[5];
1097d902a1fSMatthias Ringwald                 hci_event_buffer[pos++] = ptr[4];
1107d902a1fSMatthias Ringwald                 hci_event_buffer[pos++] = ptr[3];
1117d902a1fSMatthias Ringwald                 hci_event_buffer[pos++] = ptr[2];
1127d902a1fSMatthias Ringwald                 hci_event_buffer[pos++] = ptr[1];
1137d902a1fSMatthias Ringwald                 hci_event_buffer[pos++] = ptr[0];
1147d902a1fSMatthias Ringwald                 break;
1157d902a1fSMatthias Ringwald             case 'D': // 8 byte data block
1167d902a1fSMatthias Ringwald                 ptr = va_arg(argptr, uint8_t *);
1177d902a1fSMatthias Ringwald                 (void)memcpy(&hci_event_buffer[pos], ptr, 8);
1187d902a1fSMatthias Ringwald                 pos += 8;
1197d902a1fSMatthias Ringwald                 break;
1207d902a1fSMatthias Ringwald             case 'P': // 16 byte block
1217d902a1fSMatthias Ringwald                 ptr = va_arg(argptr, uint8_t *);
1227d902a1fSMatthias Ringwald                 (void)memcpy(&hci_event_buffer[pos], ptr, 16);
1237d902a1fSMatthias Ringwald                 pos += 16;
1247d902a1fSMatthias Ringwald                 break;
1257d902a1fSMatthias Ringwald             case 'Q':
1267d902a1fSMatthias Ringwald                 ptr = va_arg(argptr, uint8_t *);
1277d902a1fSMatthias Ringwald                 reverse_bytes(ptr, &hci_event_buffer[pos], 32);
1287d902a1fSMatthias Ringwald                 pos += 32;
1297d902a1fSMatthias Ringwald                 break;
1307d902a1fSMatthias Ringwald             case 'J':
1317d902a1fSMatthias Ringwald                 word = va_arg(argptr, int);  // minimal va_arg is int: 2 bytes on 8+16 bit CPUs
1327d902a1fSMatthias Ringwald                 length_j = word &  0xff;
1337d902a1fSMatthias Ringwald                 hci_event_buffer[pos++] = length_j;
1347d902a1fSMatthias Ringwald                 break;
1357d902a1fSMatthias Ringwald             case 'K':
1367d902a1fSMatthias Ringwald                 word = va_arg(argptr, int);  // minimal va_arg is int: 2 bytes on 8+16 bit CPUs
1377d902a1fSMatthias Ringwald                 length_j = word &  0xff;
1387d902a1fSMatthias Ringwald                 break;
1397d902a1fSMatthias Ringwald             case 'V':
1407d902a1fSMatthias Ringwald                 btstack_assert(length_j < 0x100);
1417d902a1fSMatthias Ringwald                 ptr = va_arg(argptr, uint8_t *);
1427d902a1fSMatthias Ringwald                 (void)memcpy(&hci_event_buffer[pos], ptr, length_j);
1437d902a1fSMatthias Ringwald                 pos += length_j;
1447d902a1fSMatthias Ringwald                 break;
1457d902a1fSMatthias Ringwald             default:
1467d902a1fSMatthias Ringwald                 btstack_assert(false);
1477d902a1fSMatthias Ringwald                 break;
1487d902a1fSMatthias Ringwald         }
1497d902a1fSMatthias Ringwald         format++;
1507d902a1fSMatthias Ringwald     };
1517d902a1fSMatthias Ringwald     hci_event_buffer[1] = pos - 2;
1527d902a1fSMatthias Ringwald     return pos;
1537d902a1fSMatthias Ringwald }
1547d902a1fSMatthias Ringwald 
155*c70b3b48SMatthias Ringwald uint16_t hci_event_create_from_template_and_arguments(uint8_t *hci_buffer, uint16_t buffer_size, const hci_event_t *event, ...){
1567d902a1fSMatthias Ringwald     va_list argptr;
1577d902a1fSMatthias Ringwald     va_start(argptr, event);
158*c70b3b48SMatthias Ringwald     uint16_t length = hci_event_create_from_template_and_arglist(hci_buffer, buffer_size, event, argptr);
1597d902a1fSMatthias Ringwald     va_end(argptr);
1607d902a1fSMatthias Ringwald     return length;
1617d902a1fSMatthias Ringwald }
1627d902a1fSMatthias Ringwald 
1637d902a1fSMatthias Ringwald /* HCI Events */
1647d902a1fSMatthias Ringwald 
1657d902a1fSMatthias Ringwald const hci_event_t hci_event_hardware_error = {
1667d902a1fSMatthias Ringwald     HCI_EVENT_HARDWARE_ERROR, 0, "1"
1677d902a1fSMatthias Ringwald };
1687d902a1fSMatthias Ringwald 
1697d902a1fSMatthias Ringwald const hci_event_t hci_event_transport_packet_sent = {
1707d902a1fSMatthias Ringwald         HCI_EVENT_TRANSPORT_PACKET_SENT, 0, ""
1717d902a1fSMatthias Ringwald };
1727d902a1fSMatthias Ringwald 
1737d902a1fSMatthias Ringwald const hci_event_t hci_event_command_complete = {
1747d902a1fSMatthias Ringwald     HCI_EVENT_COMMAND_COMPLETE, 0, "121KV"
1757d902a1fSMatthias Ringwald };
1767d902a1fSMatthias Ringwald 
1777d902a1fSMatthias Ringwald const hci_event_t hci_event_disconnection_complete = {
1787d902a1fSMatthias Ringwald     HCI_EVENT_DISCONNECTION_COMPLETE, 0, "1H1"
1797d902a1fSMatthias Ringwald };
1807d902a1fSMatthias Ringwald 
1817d902a1fSMatthias Ringwald const hci_event_t hci_event_number_of_completed_packets_1 = {
1827d902a1fSMatthias Ringwald     HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS, 0, "1H2"
1837d902a1fSMatthias Ringwald };
1847d902a1fSMatthias Ringwald 
1857d902a1fSMatthias Ringwald /* LE Subevents */
1867d902a1fSMatthias Ringwald 
1877d902a1fSMatthias Ringwald const hci_event_t hci_subevent_le_connection_complete = {
1887d902a1fSMatthias Ringwald     HCI_EVENT_LE_META, HCI_SUBEVENT_LE_CONNECTION_COMPLETE, "1H11B2221"
1897d902a1fSMatthias Ringwald };
190