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