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