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