xref: /btstack/chipset/cinnamon/controller.c (revision cf1c3df9398526785393a3a67e68370020c31f13)
12c4f9bbbSMatthias Ringwald /*
22c4f9bbbSMatthias Ringwald  * Copyright (C) 2020 BlueKitchen GmbH
32c4f9bbbSMatthias Ringwald  *
42c4f9bbbSMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
52c4f9bbbSMatthias Ringwald  * modification, are permitted provided that the following conditions
62c4f9bbbSMatthias Ringwald  * are met:
72c4f9bbbSMatthias Ringwald  *
82c4f9bbbSMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
92c4f9bbbSMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
102c4f9bbbSMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
112c4f9bbbSMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
122c4f9bbbSMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
132c4f9bbbSMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
142c4f9bbbSMatthias Ringwald  *    contributors may be used to endorse or promote products derived
152c4f9bbbSMatthias Ringwald  *    from this software without specific prior written permission.
162c4f9bbbSMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
172c4f9bbbSMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
182c4f9bbbSMatthias Ringwald  *    monetary gain.
192c4f9bbbSMatthias Ringwald  *
202c4f9bbbSMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
212c4f9bbbSMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
222c4f9bbbSMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
232fca4dadSMilanka Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
242fca4dadSMilanka Ringwald  * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
252c4f9bbbSMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
262c4f9bbbSMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
272c4f9bbbSMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
282c4f9bbbSMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
292c4f9bbbSMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
302c4f9bbbSMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
312c4f9bbbSMatthias Ringwald  * SUCH DAMAGE.
322c4f9bbbSMatthias Ringwald  *
332c4f9bbbSMatthias Ringwald  * Please inquire about commercial licensing options at
342c4f9bbbSMatthias Ringwald  * [email protected]
352c4f9bbbSMatthias Ringwald  *
362c4f9bbbSMatthias Ringwald  */
372c4f9bbbSMatthias Ringwald 
382c4f9bbbSMatthias Ringwald #define BTSTACK_FILE__ "controller.c"
392c4f9bbbSMatthias Ringwald 
402c4f9bbbSMatthias Ringwald #define DEBUG
412c4f9bbbSMatthias Ringwald 
422c4f9bbbSMatthias Ringwald #include <string.h>
432c4f9bbbSMatthias Ringwald 
442c4f9bbbSMatthias Ringwald #include "controller.h"
452c4f9bbbSMatthias Ringwald 
462c4f9bbbSMatthias Ringwald #include "ll.h"
472c4f9bbbSMatthias Ringwald 
482c4f9bbbSMatthias Ringwald #include "btstack_config.h"
492c4f9bbbSMatthias Ringwald #include "btstack_debug.h"
502c4f9bbbSMatthias Ringwald #include "btstack_util.h"
512c4f9bbbSMatthias Ringwald #include "btstack_run_loop.h"
522c4f9bbbSMatthias Ringwald #include "btstack_run_loop_embedded.h"
532c4f9bbbSMatthias Ringwald #include "bluetooth_company_id.h"
542c4f9bbbSMatthias Ringwald #include "hci_event.h"
552c4f9bbbSMatthias Ringwald #include "hci_transport.h"
562c4f9bbbSMatthias Ringwald #include "btstack_tlv.h"
572c4f9bbbSMatthias Ringwald #include "btstack_tlv_none.h"
582c4f9bbbSMatthias Ringwald #include "ble/le_device_db_tlv.h"
592c4f9bbbSMatthias Ringwald #include "hci_cmd.h"
602c4f9bbbSMatthias Ringwald 
612c4f9bbbSMatthias Ringwald // HCI Connection Handle used for all HCI events/connections
622c4f9bbbSMatthias Ringwald #define HCI_CON_HANDLE 0x0001
632c4f9bbbSMatthias Ringwald 
642c4f9bbbSMatthias Ringwald //
652c4f9bbbSMatthias Ringwald // Controller
662c4f9bbbSMatthias Ringwald //
672c4f9bbbSMatthias Ringwald static uint8_t send_hardware_error;
682c4f9bbbSMatthias Ringwald static bool send_transport_sent;
692c4f9bbbSMatthias Ringwald 
702c4f9bbbSMatthias Ringwald static btstack_data_source_t hci_transport_data_source;
712c4f9bbbSMatthias Ringwald 
722c4f9bbbSMatthias Ringwald static uint8_t hci_outgoing_event[258];
732c4f9bbbSMatthias Ringwald static bool    hci_outgoing_event_ready;
742c4f9bbbSMatthias Ringwald 
752c4f9bbbSMatthias Ringwald static void (*hci_packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size);
762c4f9bbbSMatthias Ringwald 
772c4f9bbbSMatthias Ringwald /** BTstack Controller Implementation */
782c4f9bbbSMatthias Ringwald 
792c4f9bbbSMatthias Ringwald // Controller State
802c4f9bbbSMatthias Ringwald static bool controller_ll_acl_reserved;
812c4f9bbbSMatthias Ringwald 
send_command_complete(uint16_t opcode,uint8_t status,const uint8_t * result,uint16_t len)822c4f9bbbSMatthias Ringwald static void send_command_complete(uint16_t opcode, uint8_t status, const uint8_t * result, uint16_t len){
83478f65a4SMatthias Ringwald     hci_event_create_from_template_and_arguments(hci_outgoing_event, sizeof(hci_outgoing_event),
84478f65a4SMatthias Ringwald          &hci_event_command_complete, /* num commands */ 1, opcode, status, len, result);
852c4f9bbbSMatthias Ringwald     hci_outgoing_event_ready = true;
86fb5f22f2SMatthias Ringwald     btstack_run_loop_poll_data_sources_from_irq();
872c4f9bbbSMatthias Ringwald }
882c4f9bbbSMatthias Ringwald 
fake_command_complete(uint16_t opcode)892c4f9bbbSMatthias Ringwald static void fake_command_complete(uint16_t opcode){
90478f65a4SMatthias Ringwald     hci_event_create_from_template_and_arguments(hci_outgoing_event, sizeof(hci_outgoing_event),
91478f65a4SMatthias Ringwald          &hci_event_command_complete, /* num commands */ 1, opcode, ERROR_CODE_SUCCESS, 0, NULL);
922c4f9bbbSMatthias Ringwald     hci_outgoing_event_ready = true;
93fb5f22f2SMatthias Ringwald     btstack_run_loop_poll_data_sources_from_irq();
942c4f9bbbSMatthias Ringwald }
952c4f9bbbSMatthias Ringwald 
controller_handle_hci_command(uint8_t * packet,uint16_t size)962c4f9bbbSMatthias Ringwald static void controller_handle_hci_command(uint8_t * packet, uint16_t size){
972c4f9bbbSMatthias Ringwald 
982c4f9bbbSMatthias Ringwald     btstack_assert(hci_outgoing_event_ready == false);
992c4f9bbbSMatthias Ringwald 
1002c4f9bbbSMatthias Ringwald     const uint8_t local_supported_features[] = { 0, 0, 0, 0, 0x40, 0, 0, 0};
1012c4f9bbbSMatthias Ringwald     const uint8_t read_buffer_size_result[] = { 0x1b, 0, HCI_NUM_TX_BUFFERS_STACK };
1022c4f9bbbSMatthias Ringwald     uint8_t status;
1032c4f9bbbSMatthias Ringwald 
1042c4f9bbbSMatthias Ringwald     uint16_t opcode = little_endian_read_16(packet, 0);
1052c4f9bbbSMatthias Ringwald     switch (opcode){
1062c4f9bbbSMatthias Ringwald         case HCI_OPCODE_HCI_RESET:
1072c4f9bbbSMatthias Ringwald             fake_command_complete(opcode);
1082c4f9bbbSMatthias Ringwald             break;
1092c4f9bbbSMatthias Ringwald         case HCI_OPCODE_HCI_READ_LOCAL_SUPPORTED_FEATURES:
1102c4f9bbbSMatthias Ringwald             // No. 37, byte 4, bit 6 = LE Supported (Controller)
1112c4f9bbbSMatthias Ringwald             send_command_complete(opcode, 0, local_supported_features, 8);
1122c4f9bbbSMatthias Ringwald             break;
1132c4f9bbbSMatthias Ringwald         case HCI_OPCODE_HCI_LE_READ_BUFFER_SIZE:
1142c4f9bbbSMatthias Ringwald             send_command_complete(opcode, 0, read_buffer_size_result, 8);
1152c4f9bbbSMatthias Ringwald             break;
1162c4f9bbbSMatthias Ringwald         case HCI_OPCODE_HCI_LE_SET_ADVERTISING_PARAMETERS:
1172c4f9bbbSMatthias Ringwald             status = ll_set_advertising_parameters(
1182c4f9bbbSMatthias Ringwald                     little_endian_read_16(packet,3),
1192c4f9bbbSMatthias Ringwald                     little_endian_read_16(packet,5),
1202c4f9bbbSMatthias Ringwald                     packet[7],
1212c4f9bbbSMatthias Ringwald                     packet[8],
1222c4f9bbbSMatthias Ringwald                     packet[9],
1232c4f9bbbSMatthias Ringwald                     &packet[10],
1242c4f9bbbSMatthias Ringwald                     packet[16],
1252c4f9bbbSMatthias Ringwald                     packet[17]);
1262c4f9bbbSMatthias Ringwald             send_command_complete(opcode, status, NULL, 0);
1272c4f9bbbSMatthias Ringwald             break;
1282c4f9bbbSMatthias Ringwald         case HCI_OPCODE_HCI_LE_SET_ADVERTISING_DATA:
1292c4f9bbbSMatthias Ringwald             status = ll_set_advertising_data(packet[3], &packet[4]);
1302c4f9bbbSMatthias Ringwald             send_command_complete(opcode, status, NULL, 0);
1312c4f9bbbSMatthias Ringwald             break;
1322c4f9bbbSMatthias Ringwald         case HCI_OPCODE_HCI_LE_SET_ADVERTISE_ENABLE:
1332c4f9bbbSMatthias Ringwald             status = ll_set_advertise_enable(packet[3]);
1342c4f9bbbSMatthias Ringwald             send_command_complete(opcode, status, NULL, 0);
1352c4f9bbbSMatthias Ringwald             break;
1362c4f9bbbSMatthias Ringwald         case HCI_OPCODE_HCI_LE_SET_SCAN_ENABLE:
1372c4f9bbbSMatthias Ringwald             ll_set_scan_enable(packet[3], packet[4]);
1382c4f9bbbSMatthias Ringwald             fake_command_complete(opcode);
1392c4f9bbbSMatthias Ringwald             break;
1402c4f9bbbSMatthias Ringwald         case HCI_OPCODE_HCI_LE_SET_SCAN_PARAMETERS:
1412c4f9bbbSMatthias Ringwald             ll_set_scan_parameters(packet[3], little_endian_read_16(packet, 4), little_endian_read_16(packet, 6), packet[8], packet[9]);
1422c4f9bbbSMatthias Ringwald             fake_command_complete(opcode);
1432c4f9bbbSMatthias Ringwald             break;
1442c4f9bbbSMatthias Ringwald         default:
1452c4f9bbbSMatthias Ringwald             log_debug("CMD opcode %02x not handled yet", opcode);
1462c4f9bbbSMatthias Ringwald             // try with "OK"
1472c4f9bbbSMatthias Ringwald             fake_command_complete(opcode);
1482c4f9bbbSMatthias Ringwald             break;
1492c4f9bbbSMatthias Ringwald     }
1502c4f9bbbSMatthias Ringwald }
1512c4f9bbbSMatthias Ringwald 
1522c4f9bbbSMatthias Ringwald // ACL handler
controller_handle_acl_data(uint8_t * packet,uint16_t size)1532c4f9bbbSMatthias Ringwald static void controller_handle_acl_data(uint8_t * packet, uint16_t size){
1542c4f9bbbSMatthias Ringwald     // so far, only single connection supported with fixed con handle
1552c4f9bbbSMatthias Ringwald     hci_con_handle_t con_handle = little_endian_read_16(packet, 0) & 0xfff;
1562c4f9bbbSMatthias Ringwald     btstack_assert(con_handle == HCI_CON_HANDLE);
1572c4f9bbbSMatthias Ringwald     btstack_assert( size > 4);
1582c4f9bbbSMatthias Ringwald 
1592c4f9bbbSMatthias Ringwald     // just queue up
1602c4f9bbbSMatthias Ringwald     btstack_assert(controller_ll_acl_reserved);
1612c4f9bbbSMatthias Ringwald     controller_ll_acl_reserved = false;
1622c4f9bbbSMatthias Ringwald     ll_queue_acl_packet(packet, size);
1632c4f9bbbSMatthias Ringwald }
1642c4f9bbbSMatthias Ringwald 
transport_emit_hci_event(const hci_event_t * event,...)1652c4f9bbbSMatthias Ringwald static void transport_emit_hci_event(const hci_event_t * event, ...){
1662c4f9bbbSMatthias Ringwald     va_list argptr;
1672c4f9bbbSMatthias Ringwald     va_start(argptr, event);
168*cf1c3df9SMatthias Ringwald     uint16_t length = hci_event_create_from_template_and_arglist(hci_outgoing_event, sizeof(hci_outgoing_event), event, argptr);
1692c4f9bbbSMatthias Ringwald     va_end(argptr);
1702c4f9bbbSMatthias Ringwald     hci_packet_handler(HCI_EVENT_PACKET, hci_outgoing_event, length);
1712c4f9bbbSMatthias Ringwald }
1722c4f9bbbSMatthias Ringwald 
transport_run(btstack_data_source_t * ds,btstack_data_source_callback_type_t callback_type)1732c4f9bbbSMatthias Ringwald static void transport_run(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type){
1742c4f9bbbSMatthias Ringwald 
1752c4f9bbbSMatthias Ringwald     // deliver command complete events caused by command processor
1762c4f9bbbSMatthias Ringwald     if (hci_outgoing_event_ready){
1772c4f9bbbSMatthias Ringwald         hci_outgoing_event_ready = false;
1782c4f9bbbSMatthias Ringwald         hci_packet_handler(HCI_EVENT_PACKET, hci_outgoing_event, hci_outgoing_event[1]+2);
1792c4f9bbbSMatthias Ringwald     }
1802c4f9bbbSMatthias Ringwald 
1812c4f9bbbSMatthias Ringwald     if (send_hardware_error != 0){
1822c4f9bbbSMatthias Ringwald         uint8_t error_code = send_hardware_error;
1832c4f9bbbSMatthias Ringwald         send_hardware_error = 0;
1842c4f9bbbSMatthias Ringwald         transport_emit_hci_event(&hci_event_hardware_error, error_code);
1852c4f9bbbSMatthias Ringwald     }
1862c4f9bbbSMatthias Ringwald 
1872c4f9bbbSMatthias Ringwald     if (send_transport_sent){
1882c4f9bbbSMatthias Ringwald         send_transport_sent = false;
1892c4f9bbbSMatthias Ringwald         // notify upper stack that it might be possible to send again
1902c4f9bbbSMatthias Ringwald         transport_emit_hci_event(&hci_event_transport_packet_sent);
1912c4f9bbbSMatthias Ringwald     }
1922c4f9bbbSMatthias Ringwald 
1932c4f9bbbSMatthias Ringwald     ll_execute_once();
1942c4f9bbbSMatthias Ringwald }
1952c4f9bbbSMatthias Ringwald 
transport_packet_handler(uint8_t packet_type,uint8_t * packet,uint16_t size)1962c4f9bbbSMatthias Ringwald static void transport_packet_handler(uint8_t packet_type, uint8_t * packet, uint16_t size){
1972c4f9bbbSMatthias Ringwald     // just forward to hci
1982c4f9bbbSMatthias Ringwald     (*hci_packet_handler)(packet_type, packet, size);
1992c4f9bbbSMatthias Ringwald }
2002c4f9bbbSMatthias Ringwald 
2012c4f9bbbSMatthias Ringwald /**
2022c4f9bbbSMatthias Ringwald  * init transport
2032c4f9bbbSMatthias Ringwald  * @param transport_config
2042c4f9bbbSMatthias Ringwald  */
transport_init(const void * transport_config)2052c4f9bbbSMatthias Ringwald static void transport_init(const void *transport_config){
2062c4f9bbbSMatthias Ringwald     UNUSED(transport_config);
2072c4f9bbbSMatthias Ringwald     ll_register_packet_handler(&transport_packet_handler);
2082c4f9bbbSMatthias Ringwald }
2092c4f9bbbSMatthias Ringwald 
2102c4f9bbbSMatthias Ringwald /**
2112c4f9bbbSMatthias Ringwald  * open transport connection
2122c4f9bbbSMatthias Ringwald  */
transport_open(void)2132c4f9bbbSMatthias Ringwald static int transport_open(void){
2142c4f9bbbSMatthias Ringwald     btstack_run_loop_set_data_source_handler(&hci_transport_data_source, &transport_run);
2152c4f9bbbSMatthias Ringwald     btstack_run_loop_enable_data_source_callbacks(&hci_transport_data_source, DATA_SOURCE_CALLBACK_POLL);
2162c4f9bbbSMatthias Ringwald     btstack_run_loop_add_data_source(&hci_transport_data_source);
2172c4f9bbbSMatthias Ringwald 
2182c4f9bbbSMatthias Ringwald     ll_init();
2192c4f9bbbSMatthias Ringwald     ll_radio_on();
2202c4f9bbbSMatthias Ringwald 
2212c4f9bbbSMatthias Ringwald     return 0;
2222c4f9bbbSMatthias Ringwald }
2232c4f9bbbSMatthias Ringwald 
2242c4f9bbbSMatthias Ringwald /**
2252c4f9bbbSMatthias Ringwald  * close transport connection
2262c4f9bbbSMatthias Ringwald  */
transport_close(void)2272c4f9bbbSMatthias Ringwald static int transport_close(void){
2282c4f9bbbSMatthias Ringwald     btstack_run_loop_remove_data_source(&hci_transport_data_source);
2292c4f9bbbSMatthias Ringwald 
2302c4f9bbbSMatthias Ringwald     // TODO
2312c4f9bbbSMatthias Ringwald 
2322c4f9bbbSMatthias Ringwald     return 0;
2332c4f9bbbSMatthias Ringwald }
2342c4f9bbbSMatthias Ringwald 
2352c4f9bbbSMatthias Ringwald /**
2362c4f9bbbSMatthias Ringwald  * register packet handler for HCI packets: ACL, SCO, and Events
2372c4f9bbbSMatthias Ringwald  */
transport_register_packet_handler(void (* handler)(uint8_t packet_type,uint8_t * packet,uint16_t size))2382c4f9bbbSMatthias Ringwald static void transport_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)){
2392c4f9bbbSMatthias Ringwald     hci_packet_handler = handler;
2402c4f9bbbSMatthias Ringwald }
2412c4f9bbbSMatthias Ringwald 
transport_can_send_packet_now(uint8_t packet_type)2422c4f9bbbSMatthias Ringwald static int transport_can_send_packet_now(uint8_t packet_type){
2432c4f9bbbSMatthias Ringwald     if (send_transport_sent) return 0;
2442c4f9bbbSMatthias Ringwald     switch (packet_type){
2452c4f9bbbSMatthias Ringwald         case HCI_COMMAND_DATA_PACKET:
2462c4f9bbbSMatthias Ringwald             return hci_outgoing_event_ready ? 0 : 1;
2472c4f9bbbSMatthias Ringwald         case HCI_ACL_DATA_PACKET:
2482c4f9bbbSMatthias Ringwald             if (controller_ll_acl_reserved == false){
2492c4f9bbbSMatthias Ringwald                 controller_ll_acl_reserved = ll_reserve_acl_packet();
2502c4f9bbbSMatthias Ringwald             }
2512c4f9bbbSMatthias Ringwald             return controller_ll_acl_reserved ? 1 : 0;
2522c4f9bbbSMatthias Ringwald         default:
2532c4f9bbbSMatthias Ringwald             btstack_assert(false);
2542c4f9bbbSMatthias Ringwald             break;
2552c4f9bbbSMatthias Ringwald     }
2562c4f9bbbSMatthias Ringwald     return 0;
2572c4f9bbbSMatthias Ringwald }
2582c4f9bbbSMatthias Ringwald 
transport_send_packet(uint8_t packet_type,uint8_t * packet,int size)2592c4f9bbbSMatthias Ringwald static int transport_send_packet(uint8_t packet_type, uint8_t *packet, int size){
2602c4f9bbbSMatthias Ringwald     switch (packet_type){
2612c4f9bbbSMatthias Ringwald         case HCI_COMMAND_DATA_PACKET:
2622c4f9bbbSMatthias Ringwald             controller_handle_hci_command(packet, size);
2632c4f9bbbSMatthias Ringwald             send_transport_sent = true;
2642c4f9bbbSMatthias Ringwald             break;
2652c4f9bbbSMatthias Ringwald         case HCI_ACL_DATA_PACKET:
2662c4f9bbbSMatthias Ringwald             controller_handle_acl_data(packet, size);
2672c4f9bbbSMatthias Ringwald             send_transport_sent = true;
2682c4f9bbbSMatthias Ringwald             break;
2692c4f9bbbSMatthias Ringwald         default:
2702c4f9bbbSMatthias Ringwald             send_hardware_error = 0x01; // invalid HCI packet
2712c4f9bbbSMatthias Ringwald             break;
2722c4f9bbbSMatthias Ringwald     }
2732c4f9bbbSMatthias Ringwald     return 0;
2742c4f9bbbSMatthias Ringwald }
2752c4f9bbbSMatthias Ringwald 
controller_init(void)2762c4f9bbbSMatthias Ringwald void controller_init(void){
2772c4f9bbbSMatthias Ringwald }
2782c4f9bbbSMatthias Ringwald 
2792c4f9bbbSMatthias Ringwald static const hci_transport_t controller_transport = {
2802c4f9bbbSMatthias Ringwald         "sx1280-vhci",
2812c4f9bbbSMatthias Ringwald         &transport_init,
2822c4f9bbbSMatthias Ringwald         &transport_open,
2832c4f9bbbSMatthias Ringwald         &transport_close,
2842c4f9bbbSMatthias Ringwald         &transport_register_packet_handler,
2852c4f9bbbSMatthias Ringwald         &transport_can_send_packet_now,
2862c4f9bbbSMatthias Ringwald         &transport_send_packet,
2872c4f9bbbSMatthias Ringwald         NULL, // set baud rate
2882c4f9bbbSMatthias Ringwald         NULL, // reset link
2892c4f9bbbSMatthias Ringwald         NULL, // set SCO config
2902c4f9bbbSMatthias Ringwald };
2912c4f9bbbSMatthias Ringwald 
controller_get_hci_transport(void)2922c4f9bbbSMatthias Ringwald const hci_transport_t * controller_get_hci_transport(void){
2932c4f9bbbSMatthias Ringwald     return &controller_transport;
2942c4f9bbbSMatthias Ringwald }
295