1*bd021c4eSMatthias Ringwald /* 2*bd021c4eSMatthias Ringwald * Copyright (C) 2014 BlueKitchen GmbH 3*bd021c4eSMatthias Ringwald * 4*bd021c4eSMatthias Ringwald * Redistribution and use in source and binary forms, with or without 5*bd021c4eSMatthias Ringwald * modification, are permitted provided that the following conditions 6*bd021c4eSMatthias Ringwald * are met: 7*bd021c4eSMatthias Ringwald * 8*bd021c4eSMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 9*bd021c4eSMatthias Ringwald * notice, this list of conditions and the following disclaimer. 10*bd021c4eSMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 11*bd021c4eSMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 12*bd021c4eSMatthias Ringwald * documentation and/or other materials provided with the distribution. 13*bd021c4eSMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 14*bd021c4eSMatthias Ringwald * contributors may be used to endorse or promote products derived 15*bd021c4eSMatthias Ringwald * from this software without specific prior written permission. 16*bd021c4eSMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for 17*bd021c4eSMatthias Ringwald * personal benefit and not for any commercial purpose or for 18*bd021c4eSMatthias Ringwald * monetary gain. 19*bd021c4eSMatthias Ringwald * 20*bd021c4eSMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21*bd021c4eSMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22*bd021c4eSMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23*bd021c4eSMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24*bd021c4eSMatthias Ringwald * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25*bd021c4eSMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26*bd021c4eSMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27*bd021c4eSMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28*bd021c4eSMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29*bd021c4eSMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30*bd021c4eSMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31*bd021c4eSMatthias Ringwald * SUCH DAMAGE. 32*bd021c4eSMatthias Ringwald * 33*bd021c4eSMatthias Ringwald * Please inquire about commercial licensing options at 34*bd021c4eSMatthias Ringwald * [email protected] 35*bd021c4eSMatthias Ringwald * 36*bd021c4eSMatthias Ringwald */ 37*bd021c4eSMatthias Ringwald 38*bd021c4eSMatthias Ringwald /* 39*bd021c4eSMatthias Ringwald * hci_h4_transport.c 40*bd021c4eSMatthias Ringwald * 41*bd021c4eSMatthias Ringwald * HCI Transport API implementation for basic H4 protocol over POSIX 42*bd021c4eSMatthias Ringwald * 43*bd021c4eSMatthias Ringwald * Created by Matthias Ringwald on 4/29/09. 44*bd021c4eSMatthias Ringwald */ 45*bd021c4eSMatthias Ringwald 46*bd021c4eSMatthias Ringwald #include "btstack_config.h" 47*bd021c4eSMatthias Ringwald 48*bd021c4eSMatthias Ringwald #include "btstack_debug.h" 49*bd021c4eSMatthias Ringwald #include "hci.h" 50*bd021c4eSMatthias Ringwald #include "hci_transport.h" 51*bd021c4eSMatthias Ringwald #include "btstack_uart_block.h" 52*bd021c4eSMatthias Ringwald 53*bd021c4eSMatthias Ringwald #ifdef HAVE_EHCILL 54*bd021c4eSMatthias Ringwald #error "HCI Transport H4 POSIX does not support eHCILL yet. Please remove HAVE_EHCILL from your btstack-config.h" 55*bd021c4eSMatthias Ringwald #endif 56*bd021c4eSMatthias Ringwald 57*bd021c4eSMatthias Ringwald // assert pre-buffer for packet type is available 58*bd021c4eSMatthias Ringwald #if !defined(HCI_OUTGOING_PRE_BUFFER_SIZE) || (HCI_OUTGOING_PRE_BUFFER_SIZE == 0) 59*bd021c4eSMatthias Ringwald #error HCI_OUTGOING_PRE_BUFFER_SIZE not defined. Please update hci.h 60*bd021c4eSMatthias Ringwald #endif 61*bd021c4eSMatthias Ringwald 62*bd021c4eSMatthias Ringwald static void dummy_handler(uint8_t packet_type, uint8_t *packet, uint16_t size); 63*bd021c4eSMatthias Ringwald 64*bd021c4eSMatthias Ringwald typedef enum { 65*bd021c4eSMatthias Ringwald H4_W4_PACKET_TYPE, 66*bd021c4eSMatthias Ringwald H4_W4_EVENT_HEADER, 67*bd021c4eSMatthias Ringwald H4_W4_ACL_HEADER, 68*bd021c4eSMatthias Ringwald H4_W4_SCO_HEADER, 69*bd021c4eSMatthias Ringwald H4_W4_PAYLOAD, 70*bd021c4eSMatthias Ringwald } H4_STATE; 71*bd021c4eSMatthias Ringwald 72*bd021c4eSMatthias Ringwald // UART Driver + Config 73*bd021c4eSMatthias Ringwald static const btstack_uart_block_t * btstack_uart; 74*bd021c4eSMatthias Ringwald static btstack_uart_config_t uart_config; 75*bd021c4eSMatthias Ringwald 76*bd021c4eSMatthias Ringwald // write mutex 77*bd021c4eSMatthias Ringwald static int uart_write_active; 78*bd021c4eSMatthias Ringwald 79*bd021c4eSMatthias Ringwald static void (*packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size) = dummy_handler; 80*bd021c4eSMatthias Ringwald 81*bd021c4eSMatthias Ringwald // packet reader state machine 82*bd021c4eSMatthias Ringwald static H4_STATE h4_state; 83*bd021c4eSMatthias Ringwald static int bytes_to_read; 84*bd021c4eSMatthias Ringwald static int read_pos; 85*bd021c4eSMatthias Ringwald 86*bd021c4eSMatthias Ringwald // incoming packet buffer 87*bd021c4eSMatthias Ringwald static uint8_t hci_packet_with_pre_buffer[HCI_INCOMING_PRE_BUFFER_SIZE + 1 + HCI_PACKET_BUFFER_SIZE]; // packet type + max(acl header + acl payload, event header + event data) 88*bd021c4eSMatthias Ringwald static uint8_t * hci_packet = &hci_packet_with_pre_buffer[HCI_INCOMING_PRE_BUFFER_SIZE]; 89*bd021c4eSMatthias Ringwald 90*bd021c4eSMatthias Ringwald static int hci_transport_h4_set_baudrate(uint32_t baudrate){ 91*bd021c4eSMatthias Ringwald log_info("hci_transport_h4_set_baudrate %u", baudrate); 92*bd021c4eSMatthias Ringwald return btstack_uart->set_baudrate(baudrate); 93*bd021c4eSMatthias Ringwald } 94*bd021c4eSMatthias Ringwald 95*bd021c4eSMatthias Ringwald static void hci_transport_h4_reset_statemachine(void){ 96*bd021c4eSMatthias Ringwald h4_state = H4_W4_PACKET_TYPE; 97*bd021c4eSMatthias Ringwald read_pos = 0; 98*bd021c4eSMatthias Ringwald bytes_to_read = 1; 99*bd021c4eSMatthias Ringwald } 100*bd021c4eSMatthias Ringwald 101*bd021c4eSMatthias Ringwald static void hci_transport_h4_trigger_next_read(void){ 102*bd021c4eSMatthias Ringwald // trigger next read 103*bd021c4eSMatthias Ringwald btstack_uart->receive_block(&hci_packet[read_pos], bytes_to_read); 104*bd021c4eSMatthias Ringwald } 105*bd021c4eSMatthias Ringwald 106*bd021c4eSMatthias Ringwald static void hci_transport_h4_block_sent(void){ 107*bd021c4eSMatthias Ringwald // free mutex 108*bd021c4eSMatthias Ringwald uart_write_active = 0; 109*bd021c4eSMatthias Ringwald 110*bd021c4eSMatthias Ringwald // notify upper stack that it can send again 111*bd021c4eSMatthias Ringwald uint8_t event[] = { HCI_EVENT_TRANSPORT_PACKET_SENT, 0}; 112*bd021c4eSMatthias Ringwald packet_handler(HCI_EVENT_PACKET, &event[0], sizeof(event)); 113*bd021c4eSMatthias Ringwald } 114*bd021c4eSMatthias Ringwald 115*bd021c4eSMatthias Ringwald static void hci_transport_h4_block_read(void){ 116*bd021c4eSMatthias Ringwald 117*bd021c4eSMatthias Ringwald read_pos += bytes_to_read; 118*bd021c4eSMatthias Ringwald 119*bd021c4eSMatthias Ringwald switch (h4_state) { 120*bd021c4eSMatthias Ringwald case H4_W4_PACKET_TYPE: 121*bd021c4eSMatthias Ringwald switch (hci_packet[0]){ 122*bd021c4eSMatthias Ringwald case HCI_EVENT_PACKET: 123*bd021c4eSMatthias Ringwald bytes_to_read = HCI_EVENT_HEADER_SIZE; 124*bd021c4eSMatthias Ringwald h4_state = H4_W4_EVENT_HEADER; 125*bd021c4eSMatthias Ringwald break; 126*bd021c4eSMatthias Ringwald case HCI_ACL_DATA_PACKET: 127*bd021c4eSMatthias Ringwald bytes_to_read = HCI_ACL_HEADER_SIZE; 128*bd021c4eSMatthias Ringwald h4_state = H4_W4_ACL_HEADER; 129*bd021c4eSMatthias Ringwald break; 130*bd021c4eSMatthias Ringwald case HCI_SCO_DATA_PACKET: 131*bd021c4eSMatthias Ringwald bytes_to_read = HCI_SCO_HEADER_SIZE; 132*bd021c4eSMatthias Ringwald h4_state = H4_W4_SCO_HEADER; 133*bd021c4eSMatthias Ringwald break; 134*bd021c4eSMatthias Ringwald default: 135*bd021c4eSMatthias Ringwald log_error("h4_process: invalid packet type 0x%02x", hci_packet[0]); 136*bd021c4eSMatthias Ringwald hci_transport_h4_reset_statemachine(); 137*bd021c4eSMatthias Ringwald break; 138*bd021c4eSMatthias Ringwald } 139*bd021c4eSMatthias Ringwald break; 140*bd021c4eSMatthias Ringwald 141*bd021c4eSMatthias Ringwald case H4_W4_EVENT_HEADER: 142*bd021c4eSMatthias Ringwald bytes_to_read = hci_packet[2]; 143*bd021c4eSMatthias Ringwald h4_state = H4_W4_PAYLOAD; 144*bd021c4eSMatthias Ringwald break; 145*bd021c4eSMatthias Ringwald 146*bd021c4eSMatthias Ringwald case H4_W4_ACL_HEADER: 147*bd021c4eSMatthias Ringwald bytes_to_read = little_endian_read_16( hci_packet, 3); 148*bd021c4eSMatthias Ringwald // check ACL length 149*bd021c4eSMatthias Ringwald if (HCI_ACL_HEADER_SIZE + bytes_to_read > HCI_PACKET_BUFFER_SIZE){ 150*bd021c4eSMatthias Ringwald log_error("h4_process: invalid ACL payload len %u - only space for %u", bytes_to_read, HCI_PACKET_BUFFER_SIZE - HCI_ACL_HEADER_SIZE); 151*bd021c4eSMatthias Ringwald hci_transport_h4_reset_statemachine(); 152*bd021c4eSMatthias Ringwald break; 153*bd021c4eSMatthias Ringwald } 154*bd021c4eSMatthias Ringwald h4_state = H4_W4_PAYLOAD; 155*bd021c4eSMatthias Ringwald break; 156*bd021c4eSMatthias Ringwald 157*bd021c4eSMatthias Ringwald case H4_W4_SCO_HEADER: 158*bd021c4eSMatthias Ringwald bytes_to_read = hci_packet[3]; 159*bd021c4eSMatthias Ringwald h4_state = H4_W4_PAYLOAD; 160*bd021c4eSMatthias Ringwald break; 161*bd021c4eSMatthias Ringwald 162*bd021c4eSMatthias Ringwald case H4_W4_PAYLOAD: 163*bd021c4eSMatthias Ringwald packet_handler(hci_packet[0], &hci_packet[1], read_pos-1); 164*bd021c4eSMatthias Ringwald hci_transport_h4_reset_statemachine(); 165*bd021c4eSMatthias Ringwald break; 166*bd021c4eSMatthias Ringwald default: 167*bd021c4eSMatthias Ringwald break; 168*bd021c4eSMatthias Ringwald } 169*bd021c4eSMatthias Ringwald hci_transport_h4_trigger_next_read(); 170*bd021c4eSMatthias Ringwald } 171*bd021c4eSMatthias Ringwald 172*bd021c4eSMatthias Ringwald static void hci_transport_h4_init(const void * transport_config){ 173*bd021c4eSMatthias Ringwald // check for hci_transport_config_uart_t 174*bd021c4eSMatthias Ringwald if (!transport_config) { 175*bd021c4eSMatthias Ringwald log_error("hci_transport_h4: no config!"); 176*bd021c4eSMatthias Ringwald return; 177*bd021c4eSMatthias Ringwald } 178*bd021c4eSMatthias Ringwald if (((hci_transport_config_t*)transport_config)->type != HCI_TRANSPORT_CONFIG_UART) { 179*bd021c4eSMatthias Ringwald log_error("hci_transport_h4: config not of type != HCI_TRANSPORT_CONFIG_UART!"); 180*bd021c4eSMatthias Ringwald return; 181*bd021c4eSMatthias Ringwald } 182*bd021c4eSMatthias Ringwald 183*bd021c4eSMatthias Ringwald // extract UART config from transport config 184*bd021c4eSMatthias Ringwald hci_transport_config_uart_t * hci_transport_config_uart = (hci_transport_config_uart_t*) transport_config; 185*bd021c4eSMatthias Ringwald uart_config.baudrate = hci_transport_config_uart->baudrate_init; 186*bd021c4eSMatthias Ringwald uart_config.flowcontrol = hci_transport_config_uart->flowcontrol; 187*bd021c4eSMatthias Ringwald uart_config.device_name = hci_transport_config_uart->device_name; 188*bd021c4eSMatthias Ringwald 189*bd021c4eSMatthias Ringwald // setup UART driver 190*bd021c4eSMatthias Ringwald btstack_uart->init(&uart_config); 191*bd021c4eSMatthias Ringwald btstack_uart->set_block_received(&hci_transport_h4_block_read); 192*bd021c4eSMatthias Ringwald btstack_uart->set_block_sent(&hci_transport_h4_block_sent); 193*bd021c4eSMatthias Ringwald } 194*bd021c4eSMatthias Ringwald 195*bd021c4eSMatthias Ringwald static int hci_transport_h4_open(void){ 196*bd021c4eSMatthias Ringwald int res = btstack_uart->open(); 197*bd021c4eSMatthias Ringwald if (res){ 198*bd021c4eSMatthias Ringwald return res; 199*bd021c4eSMatthias Ringwald } 200*bd021c4eSMatthias Ringwald hci_transport_h4_reset_statemachine(); 201*bd021c4eSMatthias Ringwald hci_transport_h4_trigger_next_read(); 202*bd021c4eSMatthias Ringwald return 0; 203*bd021c4eSMatthias Ringwald } 204*bd021c4eSMatthias Ringwald 205*bd021c4eSMatthias Ringwald static int hci_transport_h4_close(void){ 206*bd021c4eSMatthias Ringwald return btstack_uart->close(); 207*bd021c4eSMatthias Ringwald } 208*bd021c4eSMatthias Ringwald 209*bd021c4eSMatthias Ringwald static void hci_transport_h4_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)){ 210*bd021c4eSMatthias Ringwald packet_handler = handler; 211*bd021c4eSMatthias Ringwald } 212*bd021c4eSMatthias Ringwald 213*bd021c4eSMatthias Ringwald static int hci_transport_h4_can_send_now(uint8_t packet_type){ 214*bd021c4eSMatthias Ringwald return uart_write_active == 0; 215*bd021c4eSMatthias Ringwald } 216*bd021c4eSMatthias Ringwald 217*bd021c4eSMatthias Ringwald static int hci_transport_h4_send_packet(uint8_t packet_type, uint8_t * packet, int size){ 218*bd021c4eSMatthias Ringwald // store packet type before actual data and increase size 219*bd021c4eSMatthias Ringwald size++; 220*bd021c4eSMatthias Ringwald packet--; 221*bd021c4eSMatthias Ringwald *packet = packet_type; 222*bd021c4eSMatthias Ringwald 223*bd021c4eSMatthias Ringwald // lock mutex 224*bd021c4eSMatthias Ringwald uart_write_active = 1; 225*bd021c4eSMatthias Ringwald 226*bd021c4eSMatthias Ringwald // 227*bd021c4eSMatthias Ringwald btstack_uart->send_block(packet, size); 228*bd021c4eSMatthias Ringwald return 0; 229*bd021c4eSMatthias Ringwald } 230*bd021c4eSMatthias Ringwald 231*bd021c4eSMatthias Ringwald static void dummy_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){ 232*bd021c4eSMatthias Ringwald } 233*bd021c4eSMatthias Ringwald 234*bd021c4eSMatthias Ringwald static const hci_transport_t hci_transport_h4 = { 235*bd021c4eSMatthias Ringwald /* const char * name; */ "H4", 236*bd021c4eSMatthias Ringwald /* void (*init) (const void *transport_config); */ &hci_transport_h4_init, 237*bd021c4eSMatthias Ringwald /* int (*open)(void); */ &hci_transport_h4_open, 238*bd021c4eSMatthias Ringwald /* int (*close)(void); */ &hci_transport_h4_close, 239*bd021c4eSMatthias Ringwald /* void (*register_packet_handler)(void (*handler)(...); */ &hci_transport_h4_register_packet_handler, 240*bd021c4eSMatthias Ringwald /* int (*can_send_packet_now)(uint8_t packet_type); */ &hci_transport_h4_can_send_now, 241*bd021c4eSMatthias Ringwald /* int (*send_packet)(...); */ &hci_transport_h4_send_packet, 242*bd021c4eSMatthias Ringwald /* int (*set_baudrate)(uint32_t baudrate); */ &hci_transport_h4_set_baudrate, 243*bd021c4eSMatthias Ringwald /* void (*reset_link)(void); */ NULL, 244*bd021c4eSMatthias Ringwald }; 245*bd021c4eSMatthias Ringwald 246*bd021c4eSMatthias Ringwald // configure and return h4 singleton 247*bd021c4eSMatthias Ringwald const hci_transport_t * hci_transport_h4_instance(const btstack_uart_block_t * uart_driver) { 248*bd021c4eSMatthias Ringwald btstack_uart = uart_driver; 249*bd021c4eSMatthias Ringwald return &hci_transport_h4; 250*bd021c4eSMatthias Ringwald } 251