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