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