1 /* 2 * hci_h4_transport.c 3 * 4 * HCI Transport API implementation for basic H4 protocol 5 * 6 * Created by Matthias Ringwald on 4/29/09. 7 */ 8 #include <termios.h> /* POSIX terminal control definitions */ 9 #include <fcntl.h> /* File control definitions */ 10 #include <unistd.h> /* UNIX standard function definitions */ 11 #include <stdio.h> 12 13 #include "hci.h" 14 #include "hci_transport_h4.h" 15 16 typedef enum { 17 H4_W4_PACKET_TYPE, 18 H4_W4_EVENT_HEADER, 19 H4_W4_EVENT_PAYLOAD, 20 H4_W4_ACL_HEADER, 21 H4_W4_ACL_PAYLOAD 22 } H4_STATE; 23 24 static void dummy_handler(uint8_t *packet, int size); 25 static hci_uart_config_t *hci_uart_config; 26 27 static int fd; 28 static void (*event_packet_handler)(uint8_t *packet, int size) = dummy_handler; 29 static void (*acl_packet_handler) (uint8_t *packet, int size) = dummy_handler; 30 31 // packet reader state machine 32 static H4_STATE h4_state; 33 static int bytes_to_read; 34 static int read_pos; 35 // static uint8_t hci_event_buffer[255+2]; // maximal payload + 2 bytes header 36 static uint8_t hci_packet[400]; // bigger than largest packet 37 38 39 40 // prototypes 41 static int h4_open(void *transport_config){ 42 hci_uart_config = (hci_uart_config_t*) transport_config; 43 struct termios toptions; 44 fd = open(hci_uart_config->device_name, O_RDWR | O_NOCTTY | O_NDELAY); 45 if (fd == -1) { 46 perror("init_serialport: Unable to open port "); 47 perror(hci_uart_config->device_name); 48 return -1; 49 } 50 51 if (tcgetattr(fd, &toptions) < 0) { 52 perror("init_serialport: Couldn't get term attributes"); 53 return -1; 54 } 55 speed_t brate = hci_uart_config->baudrate; // let you override switch below if needed 56 switch(hci_uart_config->baudrate) { 57 case 57600: brate=B57600; break; 58 case 115200: brate=B115200; break; 59 #ifdef B230400 60 case 230400: brate=B230400; break; 61 #endif 62 #ifdef B460800 63 case 460800: brate=B460800; break; 64 #endif 65 #ifdef B921600 66 case 921600: brate=B921600; break; 67 #endif 68 } 69 cfsetispeed(&toptions, brate); 70 cfsetospeed(&toptions, brate); 71 72 // 8N1 73 toptions.c_cflag &= ~PARENB; 74 toptions.c_cflag &= ~CSTOPB; 75 toptions.c_cflag &= ~CSIZE; 76 toptions.c_cflag |= CS8; 77 78 if (hci_uart_config->flowcontrol) { 79 // with flow control 80 toptions.c_cflag |= CRTSCTS; 81 } else { 82 // no flow control 83 toptions.c_cflag &= ~CRTSCTS; 84 } 85 86 toptions.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines 87 toptions.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl 88 89 toptions.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make raw 90 toptions.c_oflag &= ~OPOST; // make raw 91 92 // see: http://unixwiz.net/techtips/termios-vmin-vtime.html 93 toptions.c_cc[VMIN] = 1; 94 toptions.c_cc[VTIME] = 0; 95 96 if( tcsetattr(fd, TCSANOW, &toptions) < 0) { 97 perror("init_serialport: Couldn't set term attributes"); 98 return -1; 99 } 100 101 // init state machine 102 bytes_to_read = 1; 103 h4_state = H4_W4_PACKET_TYPE; 104 read_pos = 0; 105 106 return 0; 107 } 108 109 static int h4_close(){ 110 return 0; 111 } 112 113 static int h4_send_cmd_packet(uint8_t *packet, int size){ 114 printf("CMD: "); 115 hexdump(packet, size); 116 117 char *data = (char*) packet; 118 char packet_type = HCI_COMMAND_DATA_PACKET; 119 write(fd, &packet_type, 1); 120 while (size > 0) { 121 int bytes_written = write(fd, data, size); 122 if (bytes_written < 0) { 123 return bytes_written; 124 } 125 data += bytes_written; 126 size -= bytes_written; 127 } 128 return 0; 129 } 130 131 static int h4_send_acl_packet(uint8_t *packet, int size){ 132 printf("ACL> "); 133 hexdump(packet, size); 134 135 char *data = (char*) packet; 136 char packet_type = HCI_ACL_DATA_PACKET; 137 write(fd, &packet_type, 1); 138 while (size > 0) { 139 int bytes_written = write(fd, data, size); 140 if (bytes_written < 0) { 141 return bytes_written; 142 } 143 data += bytes_written; 144 size -= bytes_written; 145 } 146 return 0; 147 } 148 149 static void h4_register_event_packet_handler(void (*handler)(uint8_t *packet, int size)){ 150 event_packet_handler = handler; 151 } 152 153 static void h4_register_acl_packet_handler (void (*handler)(uint8_t *packet, int size)){ 154 acl_packet_handler = handler; 155 } 156 157 static int h4_get_fd() { 158 return fd; 159 } 160 161 static int h4_handle_data() { 162 // read up to bytes_to_read data in 163 int bytes_read = read(fd, &hci_packet[read_pos], bytes_to_read); 164 if (bytes_read < 0) { 165 return bytes_read; 166 } 167 // printf("Bytes read: %u\n", bytes_read); 168 bytes_to_read -= bytes_read; 169 read_pos += bytes_read; 170 if (bytes_to_read > 0) { 171 return 0; 172 } 173 174 // act 175 switch (h4_state) { 176 case H4_W4_PACKET_TYPE: 177 if (hci_packet[0] == HCI_EVENT_PACKET){ 178 read_pos = 0; 179 bytes_to_read = HCI_EVENT_PKT_HDR; 180 h4_state = H4_W4_EVENT_HEADER; 181 } else if (hci_packet[0] == HCI_ACL_DATA_PACKET){ 182 read_pos = 0; 183 bytes_to_read = HCI_ACL_DATA_PKT_HDR; 184 h4_state = H4_W4_ACL_HEADER; 185 } else { 186 } 187 break; 188 case H4_W4_EVENT_HEADER: 189 bytes_to_read = hci_packet[1]; 190 h4_state = H4_W4_EVENT_PAYLOAD; 191 break; 192 case H4_W4_EVENT_PAYLOAD: 193 printf("EVT: "); 194 hexdump(hci_packet, read_pos); 195 event_packet_handler(hci_packet, read_pos); 196 h4_state = H4_W4_PACKET_TYPE; 197 read_pos = 0; 198 bytes_to_read = 1; 199 break; 200 case H4_W4_ACL_HEADER: 201 bytes_to_read = READ_BT_16( hci_packet, 2); 202 h4_state = H4_W4_ACL_PAYLOAD; 203 break; 204 case H4_W4_ACL_PAYLOAD: 205 printf("<ACL "); 206 hexdump(hci_packet, read_pos); 207 acl_packet_handler(hci_packet, read_pos); 208 h4_state = H4_W4_PACKET_TYPE; 209 read_pos = 0; 210 bytes_to_read = 1; 211 break; 212 } 213 return 0; 214 } 215 216 static const char * h4_get_transport_name(){ 217 return "H4"; 218 } 219 220 static void dummy_handler(uint8_t *packet, int size){ 221 } 222 223 // single instance 224 hci_transport_t hci_transport_h4 = { 225 h4_open, 226 h4_close, 227 h4_send_cmd_packet, 228 h4_send_acl_packet, 229 h4_register_event_packet_handler, 230 h4_register_acl_packet_handler, 231 h4_get_fd, 232 h4_handle_data, 233 h4_get_transport_name 234 }; 235