1 /* 2 * Copyright (C) 2016 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 #define BTSTACK_FILE__ "btstack_uart_block_windows.c" 39 40 /* 41 * btstack_uart_block_windows.c 42 * 43 * Common code to access serial port via asynchronous block read/write commands 44 * 45 */ 46 47 #include "btstack_uart_block.h" 48 #include "btstack_run_loop.h" 49 #include "btstack_debug.h" 50 51 #include <fcntl.h> /* File control definitions */ 52 #include <unistd.h> /* UNIX standard function definitions */ 53 #include <string.h> 54 #include <errno.h> 55 56 #include <Windows.h> 57 58 // uart config 59 static const btstack_uart_config_t * uart_config; 60 61 // data source for integration with BTstack Runloop 62 static btstack_data_source_t transport_data_source_read; 63 static btstack_data_source_t transport_data_source_write; 64 65 // block write 66 static int write_bytes_len; 67 static const uint8_t * write_bytes_data; 68 69 // block read 70 static uint16_t read_bytes_len; 71 static uint8_t * read_bytes_data; 72 73 // callbacks 74 static void (*block_sent)(void); 75 static void (*block_received)(void); 76 77 // port and async control structure 78 static HANDLE serial_port_handle; 79 static OVERLAPPED overlapped_read; 80 static OVERLAPPED overlapped_write; 81 82 // -- engine that retries send/receive if not all bytes have been transferred 83 84 static void btstack_uart_windows_send_engine(void){ 85 // start write 86 DWORD bytes_written; 87 BOOL ok = WriteFile(serial_port_handle, // handle 88 write_bytes_data, // (LPCSTR) 8-bit data 89 write_bytes_len, // length 90 &bytes_written, // amount written 91 &overlapped_write); // overlapped structure 92 93 if (ok){ 94 // assert all bytes written 95 if (bytes_written != write_bytes_len){ 96 log_error("btstack_uart_windows_send_block: requested write %u but %u were written", (int) write_bytes_len, (int) bytes_written); 97 return; 98 } 99 100 // 101 // TODO: to defer sending done event by enabling POLL Callback for Write 102 // 103 104 // notify done 105 if (block_sent){ 106 block_sent(); 107 } 108 return; 109 } 110 111 DWORD err = GetLastError(); 112 if (err != ERROR_IO_PENDING){ 113 log_error("btstack_uart_windows_send_block: error writing"); 114 return; 115 } 116 117 // IO_PENDING -> wait for completed 118 btstack_run_loop_enable_data_source_callbacks(&transport_data_source_write, DATA_SOURCE_CALLBACK_WRITE); 119 } 120 121 static void btstack_uart_windows_receive_engine(void){ 122 DWORD bytes_read; 123 BOOL ok = ReadFile(serial_port_handle, // handle 124 read_bytes_data, // (LPCSTR) 8-bit data 125 read_bytes_len, // length 126 &bytes_read, // amount read 127 &overlapped_read); // overlapped structure 128 129 if (ok){ 130 // assert all bytes read 131 if (bytes_read != read_bytes_len){ 132 log_error("btstack_uart_windows_receive_block: requested read %u but %u were read", (int) read_bytes_len, (int) bytes_read); 133 return; 134 } 135 136 // 137 // TODO: to defer sending done event by enabling POLL Callback 138 // 139 140 // notify done 141 if (block_received){ 142 block_received(); 143 } 144 return; 145 } 146 147 DWORD err = GetLastError(); 148 if (err != ERROR_IO_PENDING){ 149 log_error("error reading"); 150 return; 151 } 152 153 // IO_PENDING -> wait for completed 154 btstack_run_loop_enable_data_source_callbacks(&transport_data_source_read, DATA_SOURCE_CALLBACK_READ); 155 } 156 157 158 // -- overlapped IO handlers for read & write 159 160 static void btstack_uart_windows_process_write(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type) { 161 162 btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE); 163 164 DWORD bytes_written; 165 BOOL ok = GetOverlappedResult(serial_port_handle, &overlapped_write, &bytes_written, FALSE); 166 if(!ok){ 167 DWORD err = GetLastError(); 168 if (err == ERROR_IO_INCOMPLETE){ 169 // IO_INCOMPLETE -> wait for completed 170 btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE); 171 } else { 172 log_error("write: error writing"); 173 } 174 return; 175 } 176 177 // assert all bytes written 178 if (bytes_written != write_bytes_len){ 179 log_debug("write: requested to write %u but %u were written, try again", (int) write_bytes_len, (int) bytes_written); 180 btstack_uart_windows_send_engine(); 181 write_bytes_data += bytes_written; 182 write_bytes_len -= bytes_written; 183 return; 184 } 185 186 // notify done 187 if (block_sent){ 188 block_sent(); 189 } 190 } 191 192 193 static void btstack_uart_windows_process_read(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type) { 194 195 btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ); 196 197 DWORD bytes_read; 198 BOOL ok = GetOverlappedResult(serial_port_handle, &overlapped_read, &bytes_read, FALSE); 199 if(!ok){ 200 DWORD err = GetLastError(); 201 if (err == ERROR_IO_INCOMPLETE){ 202 // IO_INCOMPLETE -> wait for completed 203 btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ); 204 } else { 205 log_error("error reading"); 206 } 207 return; 208 } 209 210 211 // assert all bytes read 212 if (bytes_read != read_bytes_len){ 213 log_debug("read: requested read %u but %u were read, try again", (int) read_bytes_len, (int) bytes_read); 214 read_bytes_data += bytes_read; 215 read_bytes_len -= bytes_read; 216 btstack_uart_windows_receive_engine(); 217 return; 218 } 219 220 // notify done 221 if (block_received){ 222 block_received(); 223 } 224 } 225 226 // -- API implementation 227 228 static int btstack_uart_windows_init(const btstack_uart_config_t * config){ 229 uart_config = config; 230 return 0; 231 } 232 233 static void btstack_uart_windows_send_block(const uint8_t *data, uint16_t size){ 234 // setup async write 235 write_bytes_data = data; 236 write_bytes_len = size; 237 238 // go 239 btstack_uart_windows_send_engine(); 240 } 241 242 static void btstack_uart_windows_receive_block(uint8_t *buffer, uint16_t len){ 243 // setup async read 244 read_bytes_data = buffer; 245 read_bytes_len = len; 246 247 // go 248 btstack_uart_windows_receive_engine(); 249 } 250 251 static void btstack_uart_windows_set_baudrate_option(DCB * serial_params, uint32_t baudrate){ 252 serial_params->BaudRate = baudrate; 253 } 254 255 static void btstack_uart_windows_set_parity_option(DCB * serial_params, uint32_t parity){ 256 serial_params->Parity = parity; 257 } 258 259 static void btstack_uart_windows_set_flowcontrol_option(DCB * serial_params, uint32_t flowcontrol){ 260 // Flowcontrol 261 serial_params->fOutxCtsFlow = flowcontrol; 262 serial_params->fRtsControl = flowcontrol ? RTS_CONTROL_HANDSHAKE : 0; 263 } 264 265 static int btstack_uart_windows_set_baudrate(uint32_t baudrate){ 266 DCB serial_params; 267 memset(&serial_params, 0, sizeof(DCB)); 268 serial_params.DCBlength = sizeof(DCB); 269 270 int ok = GetCommState(serial_port_handle, &serial_params); 271 if (!ok){ 272 log_error("windows_set_baudrate: Couldn't get serial parameters"); 273 return -1; 274 } 275 btstack_uart_windows_set_baudrate_option(&serial_params, baudrate); 276 ok = SetCommState(serial_port_handle, &serial_params); 277 if (!ok){ 278 log_error("windows_set_baudrate: Couldn't serial parameters"); 279 return -1; 280 } 281 282 return 0; 283 } 284 285 static int btstack_uart_windows_set_parity(int parity){ 286 DCB serial_params; 287 memset(&serial_params, 0, sizeof(DCB)); 288 serial_params.DCBlength = sizeof(DCB); 289 290 int ok = GetCommState(serial_port_handle, &serial_params); 291 if (!ok){ 292 log_error("windows_set_parity: Couldn't get serial parameters"); 293 return -1; 294 } 295 btstack_uart_windows_set_parity_option(&serial_params, parity); 296 ok = SetCommState(serial_port_handle, &serial_params); 297 if (!ok){ 298 log_error("windows_set_parity: Couldn't serial parameters"); 299 return -1; 300 } 301 return 0; 302 } 303 304 static int btstack_uart_windows_set_flowcontrol(int flowcontrol){ 305 DCB serial_params; 306 memset(&serial_params, 0, sizeof(DCB)); 307 serial_params.DCBlength = sizeof(DCB); 308 309 int ok = GetCommState(serial_port_handle, &serial_params); 310 if (!ok){ 311 log_error("windows_set_parity: Couldn't get serial parameters"); 312 return -1; 313 } 314 btstack_uart_windows_set_flowcontrol_option(&serial_params, flowcontrol); 315 ok = SetCommState(serial_port_handle, &serial_params); 316 if (!ok){ 317 log_error("windows_set_flowcontrol: Couldn't serial parameters"); 318 return -1; 319 } 320 return 0; 321 } 322 323 static int btstack_uart_windows_open(void){ 324 325 const char * device_name = uart_config->device_name; 326 const uint32_t baudrate = uart_config->baudrate; 327 const int flowcontrol = uart_config->flowcontrol; 328 329 serial_port_handle = CreateFile( device_name, 330 GENERIC_READ | GENERIC_WRITE, 331 0, 332 0, 333 OPEN_EXISTING, 334 FILE_FLAG_OVERLAPPED, 335 0); 336 337 if (device_name == INVALID_HANDLE_VALUE){ 338 log_error("windows_open: Unable to open port %s", device_name); 339 return -1; 340 } 341 342 DCB serial_params; 343 memset(&serial_params, 0, sizeof(DCB)); 344 serial_params.DCBlength = sizeof(DCB); 345 346 int ok; 347 348 #if 0 349 // test - try to set internal buffer 350 ok = SetupComm(serial_port_handle, 64, 64); 351 printf("SetupCommL ok %u\n", ok); 352 #endif 353 354 #if 0 355 // test - read internal buffer sizes 356 COMMPROP comm_prop; 357 GetCommProperties(serial_port_handle, &comm_prop); 358 printf("dwMaxTxQueue %ld\n", comm_prop.dwMaxTxQueue); 359 printf("dwMaxRxQueue %ld\n", comm_prop.dwMaxRxQueue); 360 printf("dwCurrentTxQueue %ld\n", comm_prop.dwCurrentTxQueue); 361 printf("dwCurrentRxQueue %ld\n", comm_prop.dwCurrentRxQueue); 362 #endif 363 364 // Caveat: with the default FTDI driver and a FT232R on Windows 10, the default USB RX/TX buffer sizes are 4096 365 // this causes a problem when data is received back to back, like with SCO audio data 366 367 // Workaround: manually set these values in the Device Manager to 64 bytes 368 369 ok = GetCommState(serial_port_handle, &serial_params); 370 371 if (!ok){ 372 log_error("windows_open: Couldn't get serial parameters"); 373 return -1; 374 } 375 376 // 8-N-1 377 serial_params.ByteSize = 8; 378 serial_params.StopBits = ONESTOPBIT; 379 serial_params.Parity = NOPARITY; 380 381 // baudrate 382 btstack_uart_windows_set_baudrate_option(&serial_params, baudrate); 383 384 // flow control 385 btstack_uart_windows_set_flowcontrol_option(&serial_params, flowcontrol); 386 387 // parity none 388 btstack_uart_windows_set_parity_option(&serial_params, 0); 389 390 // commit changes 391 ok = SetCommState(serial_port_handle, &serial_params); 392 if (!ok){ 393 log_error("windows_open: Couldn't serial parameters"); 394 return -1; 395 } 396 397 // setup overlapped structures for async io 398 memset(&overlapped_read, 0, sizeof(overlapped_read)); 399 memset(&overlapped_write, 0, sizeof(overlapped_write)); 400 overlapped_read.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 401 overlapped_write.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 402 403 // setup read + write data sources 404 transport_data_source_read.source.handle = overlapped_read.hEvent; 405 transport_data_source_write.source.handle = overlapped_write.hEvent; 406 btstack_run_loop_set_data_source_handler(&transport_data_source_read, &btstack_uart_windows_process_read); 407 btstack_run_loop_set_data_source_handler(&transport_data_source_write, &btstack_uart_windows_process_write); 408 btstack_run_loop_add_data_source(&transport_data_source_read); 409 btstack_run_loop_add_data_source(&transport_data_source_write); 410 411 return 0; 412 } 413 414 static int btstack_uart_windows_close_new(void){ 415 416 // first remove run loop handler 417 btstack_run_loop_remove_data_source(&transport_data_source_read); 418 btstack_run_loop_remove_data_source(&transport_data_source_write); 419 420 // note: an event cannot be freed while a kernel function is waiting. 421 // in our single-threaded environment, this cannot happen. 422 423 // free events 424 CloseHandle(overlapped_read.hEvent); 425 CloseHandle(overlapped_write.hEvent); 426 CloseHandle(serial_port_handle); 427 428 // set pointers to zero 429 overlapped_read.hEvent = NULL; 430 overlapped_write.hEvent = NULL; 431 serial_port_handle = NULL; 432 return 0; 433 } 434 435 static void btstack_uart_windows_set_block_received( void (*block_handler)(void)){ 436 block_received = block_handler; 437 } 438 439 static void btstack_uart_windows_set_block_sent( void (*block_handler)(void)){ 440 block_sent = block_handler; 441 } 442 443 // static void btstack_uart_windows_set_sleep(uint8_t sleep){ 444 // } 445 // static void btstack_uart_windows_set_csr_irq_handler( void (*csr_irq_handler)(void)){ 446 // } 447 448 static const btstack_uart_block_t btstack_uart_windows = { 449 /* int (*init)(hci_transport_config_uart_t * config); */ &btstack_uart_windows_init, 450 /* int (*open)(void); */ &btstack_uart_windows_open, 451 /* int (*close)(void); */ &btstack_uart_windows_close_new, 452 /* void (*set_block_received)(void (*handler)(void)); */ &btstack_uart_windows_set_block_received, 453 /* void (*set_block_sent)(void (*handler)(void)); */ &btstack_uart_windows_set_block_sent, 454 /* int (*set_baudrate)(uint32_t baudrate); */ &btstack_uart_windows_set_baudrate, 455 /* int (*set_parity)(int parity); */ &btstack_uart_windows_set_parity, 456 /* int (*set_flowcontrol)(int flowcontrol); */ &btstack_uart_windows_set_flowcontrol, 457 /* void (*receive_block)(uint8_t *buffer, uint16_t len); */ &btstack_uart_windows_receive_block, 458 /* void (*send_block)(const uint8_t *buffer, uint16_t length); */ &btstack_uart_windows_send_block, 459 /* int (*get_supported_sleep_modes); */ NULL, 460 /* void (*set_sleep)(btstack_uart_sleep_mode_t sleep_mode); */ NULL, 461 /* void (*set_wakeup_handler)(void (*handler)(void)); */ NULL, 462 }; 463 464 const btstack_uart_block_t * btstack_uart_block_windows_instance(void){ 465 return &btstack_uart_windows; 466 } 467