1 /* 2 * Copyright (C) 2009 by Matthias Ringwald 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 * 17 * THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 21 * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 24 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 27 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 */ 31 32 /* 33 * hci_h4_transport.c 34 * 35 * HCI Transport API implementation for basic H4 protocol 36 * with extension for "enforced wake device" used e.g. in iOS 37 * 38 * Created by Matthias Ringwald on 4/29/09. 39 */ 40 41 #include "config.h" 42 43 #undef USE_NETGRAPH 44 45 // don't enforce wake after 3s idle 46 #define HCI_WAKE_TIMER_MS 3000 47 #define HCI_WAKE_DURATION 10000 48 49 #include <termios.h> /* POSIX terminal control definitions */ 50 #include <fcntl.h> /* File control definitions */ 51 #include <unistd.h> /* UNIX standard function definitions */ 52 #include <stdio.h> 53 #include <string.h> 54 #include <pthread.h> 55 56 #include "debug.h" 57 #include "hci.h" 58 #include "hci_transport.h" 59 #include "hci_dump.h" 60 61 static int h4_process(struct data_source *ds); 62 static void dummy_handler(uint8_t packet_type, uint8_t *packet, uint16_t size); 63 static hci_uart_config_t *hci_uart_config; 64 65 static void h4_enforce_wake_on(void); 66 static void h4_enforce_wake_off(void); 67 static void h4_enforce_wake_timeout(struct timer *ts); 68 69 typedef enum { 70 H4_W4_PACKET_TYPE, 71 H4_W4_EVENT_HEADER, 72 H4_W4_ACL_HEADER, 73 H4_W4_PAYLOAD, 74 } H4_STATE; 75 76 typedef struct hci_transport_h4 { 77 hci_transport_t transport; 78 data_source_t *ds; 79 int uart_fd; // different from ds->fd for HCI reader thread 80 /* power management support, e.g. used by iOS */ 81 timer_source_t sleep_timer; 82 } hci_transport_h4_t; 83 84 85 // single instance 86 static hci_transport_h4_t * hci_transport_h4 = NULL; 87 88 // enforced wake support 89 static char * enforce_wake_device = NULL; 90 static int enforce_wake_fd = 0; 91 92 static void (*packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size) = dummy_handler; 93 94 // packet reader state machine 95 static H4_STATE h4_state; 96 static int bytes_to_read; 97 static int read_pos; 98 99 static uint8_t hci_packet[1+HCI_PACKET_BUFFER_SIZE]; // packet type + max(acl header + acl payload, event header + event data) 100 101 102 static int h4_open(void *transport_config){ 103 hci_uart_config = (hci_uart_config_t*) transport_config; 104 struct termios toptions; 105 int flags = O_RDWR | O_NOCTTY; 106 int fd = open(hci_uart_config->device_name, flags); 107 if (fd == -1) { 108 perror("init_serialport: Unable to open port "); 109 perror(hci_uart_config->device_name); 110 return -1; 111 } 112 113 if (tcgetattr(fd, &toptions) < 0) { 114 perror("init_serialport: Couldn't get term attributes"); 115 return -1; 116 } 117 speed_t brate = hci_uart_config->baudrate_init; // let you override switch below if needed 118 switch(hci_uart_config->baudrate_init) { 119 case 57600: brate=B57600; break; 120 case 115200: brate=B115200; break; 121 #ifdef B230400 122 case 230400: brate=B230400; break; 123 #endif 124 #ifdef B460800 125 case 460800: brate=B460800; break; 126 #endif 127 #ifdef B921600 128 case 921600: brate=B921600; break; 129 #endif 130 } 131 cfsetispeed(&toptions, brate); 132 cfsetospeed(&toptions, brate); 133 134 // 8N1 135 toptions.c_cflag &= ~PARENB; 136 toptions.c_cflag &= ~CSTOPB; 137 toptions.c_cflag &= ~CSIZE; 138 toptions.c_cflag |= CS8; 139 140 if (hci_uart_config->flowcontrol) { 141 // with flow control 142 toptions.c_cflag |= CRTSCTS; 143 } else { 144 // no flow control 145 toptions.c_cflag &= ~CRTSCTS; 146 } 147 148 toptions.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines 149 toptions.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl 150 151 toptions.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make raw 152 toptions.c_oflag &= ~OPOST; // make raw 153 154 // see: http://unixwiz.net/techtips/termios-vmin-vtime.html 155 toptions.c_cc[VMIN] = 1; 156 toptions.c_cc[VTIME] = 0; 157 158 if( tcsetattr(fd, TCSANOW, &toptions) < 0) { 159 perror("init_serialport: Couldn't set term attributes"); 160 return -1; 161 } 162 163 // set up data_source 164 hci_transport_h4->ds = malloc(sizeof(data_source_t)); 165 if (!hci_transport_h4->ds) return -1; 166 hci_transport_h4->uart_fd = fd; 167 hci_transport_h4->ds->fd = fd; 168 hci_transport_h4->ds->process = h4_process; 169 run_loop_add_data_source(hci_transport_h4->ds); 170 171 // init state machine 172 bytes_to_read = 1; 173 h4_state = H4_W4_PACKET_TYPE; 174 read_pos = 0; 175 176 return 0; 177 } 178 179 static int h4_close(void *transport_config){ 180 // first remove run loop handler 181 run_loop_remove_data_source(hci_transport_h4->ds); 182 183 // close device 184 close(hci_transport_h4->ds->fd); 185 186 // let module sleep 187 h4_enforce_wake_off(); 188 189 // free struct 190 free(hci_transport_h4->ds); 191 hci_transport_h4->ds = NULL; 192 return 0; 193 } 194 195 static int h4_send_packet(uint8_t packet_type, uint8_t * packet, int size){ 196 if (hci_transport_h4->ds == NULL) return -1; 197 if (hci_transport_h4->uart_fd == 0) return -1; 198 199 // wake Bluetooth module 200 h4_enforce_wake_on(); 201 202 hci_dump_packet( (uint8_t) packet_type, 0, packet, size); 203 char *data = (char*) packet; 204 int bytes_written = write(hci_transport_h4->uart_fd, &packet_type, 1); 205 while (bytes_written < 1) { 206 usleep(5000); 207 bytes_written = write(hci_transport_h4->uart_fd, &packet_type, 1); 208 }; 209 while (size > 0) { 210 int bytes_written = write(hci_transport_h4->uart_fd, data, size); 211 if (bytes_written < 0) { 212 usleep(5000); 213 continue; 214 } 215 data += bytes_written; 216 size -= bytes_written; 217 } 218 return 0; 219 } 220 221 static void h4_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)){ 222 packet_handler = handler; 223 } 224 225 static void h4_deliver_packet(void){ 226 if (read_pos < 3) return; // sanity check 227 hci_dump_packet( hci_packet[0], 1, &hci_packet[1], read_pos-1); 228 packet_handler(hci_packet[0], &hci_packet[1], read_pos-1); 229 230 h4_state = H4_W4_PACKET_TYPE; 231 read_pos = 0; 232 bytes_to_read = 1; 233 } 234 235 static void h4_statemachine(void){ 236 switch (h4_state) { 237 238 case H4_W4_PACKET_TYPE: 239 if (hci_packet[0] == HCI_EVENT_PACKET){ 240 bytes_to_read = HCI_EVENT_HEADER_SIZE; 241 h4_state = H4_W4_EVENT_HEADER; 242 } else if (hci_packet[0] == HCI_ACL_DATA_PACKET){ 243 bytes_to_read = HCI_ACL_HEADER_SIZE; 244 h4_state = H4_W4_ACL_HEADER; 245 } else { 246 log_error("h4_process: invalid packet type 0x%02x\n", hci_packet[0]); 247 read_pos = 0; 248 bytes_to_read = 1; 249 } 250 break; 251 252 case H4_W4_EVENT_HEADER: 253 bytes_to_read = hci_packet[2]; 254 h4_state = H4_W4_PAYLOAD; 255 break; 256 257 case H4_W4_ACL_HEADER: 258 bytes_to_read = READ_BT_16( hci_packet, 3); 259 h4_state = H4_W4_PAYLOAD; 260 break; 261 262 case H4_W4_PAYLOAD: 263 h4_deliver_packet(); 264 break; 265 default: 266 break; 267 } 268 } 269 270 static int h4_process(struct data_source *ds) { 271 if (hci_transport_h4->uart_fd == 0) return -1; 272 273 int read_now = bytes_to_read; 274 // if (read_now > 100) { 275 // read_now = 100; 276 // } 277 278 // read up to bytes_to_read data in 279 ssize_t bytes_read = read(hci_transport_h4->uart_fd, &hci_packet[read_pos], read_now); 280 // printf("h4_process: bytes read %u\n", bytes_read); 281 if (bytes_read < 0) { 282 return bytes_read; 283 } 284 285 // hexdump(&hci_packet[read_pos], bytes_read); 286 287 bytes_to_read -= bytes_read; 288 read_pos += bytes_read; 289 if (bytes_to_read > 0) { 290 return 0; 291 } 292 293 h4_statemachine(); 294 return 0; 295 } 296 297 static void h4_enforce_wake_on(void) 298 { 299 if (!enforce_wake_device) return; 300 301 if (!enforce_wake_fd) { 302 enforce_wake_fd = open(enforce_wake_device, O_RDWR); 303 usleep(HCI_WAKE_DURATION); // wait until device is ready 304 } 305 run_loop_remove_timer(&hci_transport_h4->sleep_timer); 306 run_loop_set_timer(&hci_transport_h4->sleep_timer, HCI_WAKE_TIMER_MS); 307 hci_transport_h4->sleep_timer.process = h4_enforce_wake_timeout; 308 run_loop_add_timer(&hci_transport_h4->sleep_timer); 309 } 310 311 static void h4_enforce_wake_off(void) 312 { 313 run_loop_remove_timer(&hci_transport_h4->sleep_timer); 314 315 if (enforce_wake_fd) { 316 close(enforce_wake_fd); 317 enforce_wake_fd = 0; 318 } 319 } 320 321 static void h4_enforce_wake_timeout(struct timer *ts) 322 { 323 h4_enforce_wake_off(); 324 } 325 326 static const char * h4_get_transport_name(void){ 327 return "H4"; 328 } 329 330 static void dummy_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){ 331 } 332 333 // get h4 singleton 334 hci_transport_t * hci_transport_h4_instance() { 335 if (hci_transport_h4 == NULL) { 336 hci_transport_h4 = malloc( sizeof(hci_transport_h4_t)); 337 hci_transport_h4->ds = NULL; 338 hci_transport_h4->transport.open = h4_open; 339 hci_transport_h4->transport.close = h4_close; 340 hci_transport_h4->transport.send_packet = h4_send_packet; 341 hci_transport_h4->transport.register_packet_handler = h4_register_packet_handler; 342 hci_transport_h4->transport.get_transport_name = h4_get_transport_name; 343 hci_transport_h4->transport.set_baudrate = NULL; 344 hci_transport_h4->transport.can_send_packet_now = NULL; 345 } 346 return (hci_transport_t *) hci_transport_h4; 347 } 348 349 void hci_transport_h4_set_enforce_wake_device(char *path){ 350 enforce_wake_device = path; 351 }