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 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 */ 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); 124*7741b155SMatthias 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; 1367d902a1fSMatthias Ringwald hci_event_buffer[pos++] = 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 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