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 53*fe70ee48SMatthias Ringwald static inline bool hci_event_can_store(uint16_t pos, uint16_t size, uint16_t to_store, bool *overrun) { 54*fe70ee48SMatthias Ringwald if ((pos + to_store) > size) { 55*fe70ee48SMatthias Ringwald *overrun = true; 56*fe70ee48SMatthias Ringwald return false; 57*fe70ee48SMatthias Ringwald } else { 58*fe70ee48SMatthias Ringwald return true; 59*fe70ee48SMatthias Ringwald } 60*fe70ee48SMatthias Ringwald } 61*fe70ee48SMatthias 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 */ 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; 79*fe70ee48SMatthias Ringwald hci_event_buffer[1] = 0; 80*fe70ee48SMatthias 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; 93*fe70ee48SMatthias Ringwald bool overrun = false; 94*fe70ee48SMatthias Ringwald while (*format != 0) { 957d902a1fSMatthias Ringwald switch(*format) { 967d902a1fSMatthias Ringwald case '1': // 8 bit value 97*fe70ee48SMatthias 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; 100*fe70ee48SMatthias Ringwald break; 101*fe70ee48SMatthias Ringwald case '2': // 16 bit value 102*fe70ee48SMatthias Ringwald case 'H': // hci_handle 103*fe70ee48SMatthias Ringwald if (!hci_event_can_store(pos, buffer_size, 2, &overrun)) break; 104*fe70ee48SMatthias Ringwald word = va_arg(argptr, int); // minimal va_arg is int: 2 bytes on 8+16 bit CPUs 105*fe70ee48SMatthias Ringwald little_endian_store_16(hci_event_buffer, pos, word); 106*fe70ee48SMatthias Ringwald pos += 2; 1077d902a1fSMatthias Ringwald break; 1087d902a1fSMatthias Ringwald case '3': 109*fe70ee48SMatthias Ringwald if (!hci_event_can_store(pos, buffer_size, 3, &overrun)) break; 1107d902a1fSMatthias Ringwald longword = va_arg(argptr, uint32_t); 111*fe70ee48SMatthias Ringwald little_endian_store_24(hci_event_buffer, pos, longword); 112*fe70ee48SMatthias Ringwald pos += 3; 113*fe70ee48SMatthias Ringwald break; 114*fe70ee48SMatthias Ringwald case '4': 115*fe70ee48SMatthias Ringwald if (!hci_event_can_store(pos, buffer_size, 4, &overrun)) break; 116*fe70ee48SMatthias Ringwald longword = va_arg(argptr, uint32_t); 117*fe70ee48SMatthias Ringwald little_endian_store_32(hci_event_buffer, pos, longword); 118*fe70ee48SMatthias Ringwald pos += 4; 1197d902a1fSMatthias Ringwald break; 1207d902a1fSMatthias Ringwald case 'B': // bt-addr 121*fe70ee48SMatthias Ringwald if (!hci_event_can_store(pos, buffer_size, 6, &overrun)) break; 1227d902a1fSMatthias Ringwald ptr = va_arg(argptr, uint8_t *); 123*fe70ee48SMatthias Ringwald reverse_bytes(ptr, &hci_event_buffer[pos], 6); 1247d902a1fSMatthias Ringwald break; 1257d902a1fSMatthias Ringwald case 'Q': 126*fe70ee48SMatthias Ringwald if (!hci_event_can_store(pos, buffer_size, 32, &overrun)) break; 1277d902a1fSMatthias Ringwald ptr = va_arg(argptr, uint8_t *); 1287d902a1fSMatthias Ringwald reverse_bytes(ptr, &hci_event_buffer[pos], 32); 1297d902a1fSMatthias Ringwald pos += 32; 1307d902a1fSMatthias Ringwald break; 1317d902a1fSMatthias Ringwald case 'J': 132*fe70ee48SMatthias Ringwald if (!hci_event_can_store(pos, buffer_size, 1, &overrun)) break; 1337d902a1fSMatthias Ringwald word = va_arg(argptr, int); // minimal va_arg is int: 2 bytes on 8+16 bit CPUs 1347d902a1fSMatthias Ringwald length_j = word & 0xff; 1357d902a1fSMatthias Ringwald hci_event_buffer[pos++] = length_j; 1367d902a1fSMatthias Ringwald break; 1377d902a1fSMatthias Ringwald case 'K': 1387d902a1fSMatthias Ringwald word = va_arg(argptr, int); // minimal va_arg is int: 2 bytes on 8+16 bit CPUs 1397d902a1fSMatthias Ringwald length_j = word & 0xff; 1407d902a1fSMatthias Ringwald break; 1417d902a1fSMatthias Ringwald case 'V': 1427d902a1fSMatthias Ringwald btstack_assert(length_j < 0x100); 143*fe70ee48SMatthias Ringwald if (!hci_event_can_store(pos, buffer_size, length_j, &overrun)) break; 1447d902a1fSMatthias Ringwald ptr = va_arg(argptr, uint8_t *); 1457d902a1fSMatthias Ringwald (void)memcpy(&hci_event_buffer[pos], ptr, length_j); 1467d902a1fSMatthias Ringwald pos += length_j; 1477d902a1fSMatthias Ringwald break; 1487d902a1fSMatthias Ringwald default: 1497d902a1fSMatthias Ringwald btstack_assert(false); 1507d902a1fSMatthias Ringwald break; 1517d902a1fSMatthias Ringwald } 152*fe70ee48SMatthias Ringwald if (overrun){ 153*fe70ee48SMatthias Ringwald return 0; 154*fe70ee48SMatthias Ringwald } 1557d902a1fSMatthias Ringwald format++; 1567d902a1fSMatthias Ringwald }; 157*fe70ee48SMatthias Ringwald 158*fe70ee48SMatthias Ringwald // store final event len 1597d902a1fSMatthias Ringwald hci_event_buffer[1] = pos - 2; 1607d902a1fSMatthias Ringwald return pos; 1617d902a1fSMatthias Ringwald } 1627d902a1fSMatthias Ringwald 163c70b3b48SMatthias Ringwald uint16_t hci_event_create_from_template_and_arguments(uint8_t *hci_buffer, uint16_t buffer_size, const hci_event_t *event, ...){ 1647d902a1fSMatthias Ringwald va_list argptr; 1657d902a1fSMatthias Ringwald va_start(argptr, event); 166c70b3b48SMatthias Ringwald uint16_t length = hci_event_create_from_template_and_arglist(hci_buffer, buffer_size, event, argptr); 1677d902a1fSMatthias Ringwald va_end(argptr); 1687d902a1fSMatthias Ringwald return length; 1697d902a1fSMatthias Ringwald } 1707d902a1fSMatthias Ringwald 1717d902a1fSMatthias Ringwald /* HCI Events */ 1727d902a1fSMatthias Ringwald 1737d902a1fSMatthias Ringwald const hci_event_t hci_event_hardware_error = { 1747d902a1fSMatthias Ringwald HCI_EVENT_HARDWARE_ERROR, 0, "1" 1757d902a1fSMatthias Ringwald }; 1767d902a1fSMatthias Ringwald 1777d902a1fSMatthias Ringwald const hci_event_t hci_event_transport_packet_sent = { 1787d902a1fSMatthias Ringwald HCI_EVENT_TRANSPORT_PACKET_SENT, 0, "" 1797d902a1fSMatthias Ringwald }; 1807d902a1fSMatthias Ringwald 1817d902a1fSMatthias Ringwald const hci_event_t hci_event_command_complete = { 1827d902a1fSMatthias Ringwald HCI_EVENT_COMMAND_COMPLETE, 0, "121KV" 1837d902a1fSMatthias Ringwald }; 1847d902a1fSMatthias Ringwald 1857d902a1fSMatthias Ringwald const hci_event_t hci_event_disconnection_complete = { 1867d902a1fSMatthias Ringwald HCI_EVENT_DISCONNECTION_COMPLETE, 0, "1H1" 1877d902a1fSMatthias Ringwald }; 1887d902a1fSMatthias Ringwald 1897d902a1fSMatthias Ringwald const hci_event_t hci_event_number_of_completed_packets_1 = { 1907d902a1fSMatthias Ringwald HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS, 0, "1H2" 1917d902a1fSMatthias Ringwald }; 1927d902a1fSMatthias Ringwald 1937d902a1fSMatthias Ringwald /* LE Subevents */ 1947d902a1fSMatthias Ringwald 1957d902a1fSMatthias Ringwald const hci_event_t hci_subevent_le_connection_complete = { 1967d902a1fSMatthias Ringwald HCI_EVENT_LE_META, HCI_SUBEVENT_LE_CONNECTION_COMPLETE, "1H11B2221" 1977d902a1fSMatthias Ringwald }; 198