1 /* 2 * Copyright (C) 2014 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 /* 39 * hci_transport_usb.c 40 * 41 * HCI Transport API implementation for USB 42 * 43 * Created by Matthias Ringwald on 7/5/09. 44 */ 45 46 // Interface Number - Alternate Setting - suggested Endpoint Address - Endpoint Type - Suggested Max Packet Size 47 // HCI Commands 0 0 0x00 Control 8/16/32/64 48 // HCI Events 0 0 0x81 Interrupt (IN) 16 49 // ACL Data 0 0 0x82 Bulk (IN) 32/64 50 // ACL Data 0 0 0x02 Bulk (OUT) 32/64 51 // SCO Data 0 0 0x83 Isochronous (IN) 52 // SCO Data 0 0 0x03 Isochronous (Out) 53 54 #include <stdio.h> 55 #include <strings.h> 56 #include <string.h> 57 #include <unistd.h> /* UNIX standard function definitions */ 58 #include <sys/types.h> 59 #include <inttypes.h> // to print long long int (aka 64 bit ints) 60 61 #include "btstack_config.h" 62 63 #include "btstack_debug.h" 64 #include "hci.h" 65 #include "hci_transport.h" 66 67 #include <Windows.h> 68 #include <SetupAPI.h> 69 #include <Winusb.h> 70 71 #ifdef ENABLE_SCO_OVER_HCI 72 73 // Isochronous Add-On 74 75 // Function signatures frome https://abi-laboratory.pro/compatibility/Windows_7.0_to_Windows_8.1/x86_64/info/winusb.dll/symbols.html 76 // MSDN documentation has multiple errors (Jan 2017), annotated below 77 78 typedef PVOID WINUSB_ISOCH_BUFFER_HANDLE, *PWINUSB_ISOCH_BUFFER_HANDLE; 79 80 typedef struct _WINUSB_PIPE_INFORMATION_EX { 81 USBD_PIPE_TYPE PipeType; 82 UCHAR PipeId; 83 USHORT MaximumPacketSize; 84 UCHAR Interval; 85 ULONG MaximumBytesPerInterval; 86 } WINUSB_PIPE_INFORMATION_EX, *PWINUSB_PIPE_INFORMATION_EX; 87 88 typedef WINBOOL (WINAPI * WinUsb_QueryPipeEx_t) ( 89 WINUSB_INTERFACE_HANDLE InterfaceHandle, 90 UCHAR AlternateInterfaceNumber, 91 UCHAR PipeIndex, 92 PWINUSB_PIPE_INFORMATION_EX PipeInformationEx 93 ); 94 typedef WINBOOL (WINAPI * WinUsb_RegisterIsochBuffer_t)( 95 WINUSB_INTERFACE_HANDLE InterfaceHandle, 96 UCHAR PipeID, 97 PVOID Buffer, 98 ULONG BufferLength, 99 PWINUSB_ISOCH_BUFFER_HANDLE BufferHandle 100 ); 101 typedef WINBOOL (WINAPI * WinUsb_ReadIsochPipe_t)( 102 PWINUSB_ISOCH_BUFFER_HANDLE BufferHandle, 103 ULONG Offset, 104 ULONG Length, 105 PULONG FrameNumber, 106 ULONG NumberOfPackets, // MSDN lists PULONG 107 PUSBD_ISO_PACKET_DESCRIPTOR IsoPacketDescriptors, // MSDN lists PULONG 108 LPOVERLAPPED Overlapped 109 ); 110 typedef WINBOOL (WINAPI * WinUsb_ReadIsochPipeAsap_t)( 111 PWINUSB_ISOCH_BUFFER_HANDLE BufferHandle, 112 ULONG Offset, 113 ULONG Length, 114 BOOL ContinueStream, 115 ULONG NumberOfPackets, // MSDN lists PULONG 116 PUSBD_ISO_PACKET_DESCRIPTOR IsoPacketDescriptors, 117 LPOVERLAPPED Overlapped 118 ); 119 typedef WINBOOL (WINAPI * WinUsb_WriteIsochPipe_t)( 120 PWINUSB_ISOCH_BUFFER_HANDLE BufferHandle, 121 ULONG Offset, 122 ULONG Length, 123 PULONG FrameNumber, 124 LPOVERLAPPED Overlapped 125 ); 126 typedef WINBOOL (WINAPI * WinUsb_WriteIsochPipeAsap_t)( 127 PWINUSB_ISOCH_BUFFER_HANDLE BufferHandle, 128 ULONG Offset, 129 ULONG Length, 130 BOOL ContinueStream, 131 LPOVERLAPPED Overlapped 132 ); 133 typedef WINBOOL (WINAPI * WinUsb_UnregisterIsochBuffer_t)( 134 PWINUSB_ISOCH_BUFFER_HANDLE BufferHandle 135 ); 136 typedef WINBOOL (WINAPI * WinUsb_GetCurrentFrameNumber_t)( 137 WINUSB_INTERFACE_HANDLE InterfaceHandle, // MSDN lists 'Device handle returned from CreateFile' 138 PULONG CurrentFrameNumber, 139 LARGE_INTEGER *TimeStamp 140 ); 141 142 static WinUsb_QueryPipeEx_t WinUsb_QueryPipeEx; 143 static WinUsb_RegisterIsochBuffer_t WinUsb_RegisterIsochBuffer; 144 static WinUsb_ReadIsochPipe_t WinUsb_ReadIsochPipe; 145 static WinUsb_ReadIsochPipeAsap_t WinUsb_ReadIsochPipeAsap; 146 static WinUsb_WriteIsochPipe_t WinUsb_WriteIsochPipe; 147 static WinUsb_WriteIsochPipeAsap_t WinUsb_WriteIsochPipeAsap; 148 static WinUsb_UnregisterIsochBuffer_t WinUsb_UnregisterIsochBuffer; 149 static WinUsb_GetCurrentFrameNumber_t WinUsb_GetCurrentFrameNumber; 150 #endif 151 152 // Doesn't work as expected 153 // #define SCHEDULE_SCO_IN_TRANSFERS_MANUALLY 154 155 // Not tested yet 156 // #define SCHEDULE_SCO_OUT_TRANSFERS_MANUALLY 157 158 // 159 // Bluetooth USB Transport Alternate Settings: 160 // 161 // 0: No active voice channels (for USB compliance) 162 // 1: One 8 kHz voice channel with 8-bit encoding 163 // 2: Two 8 kHz voice channels with 8-bit encoding or one 8 kHz voice channel with 16-bit encoding 164 // 3: Three 8 kHz voice channels with 8-bit encoding 165 // 4: Two 8 kHz voice channels with 16-bit encoding or one 16 kHz voice channel with 16-bit encoding 166 // 5: Three 8 kHz voice channels with 16-bit encoding or one 8 kHz voice channel with 16-bit encoding and one 16 kHz voice channel with 16-bit encoding 167 // --> support only a single SCO connection 168 #define ALT_SETTING (1) 169 170 // for ALT_SETTING >= 1 and 8-bit channel, we need the following isochronous packets 171 // One complete SCO packet with 24 frames every 3 frames (== 3 ms) 172 #define NUM_ISO_PACKETS (3) 173 174 // results in 9 bytes per frame 175 #define ISO_PACKET_SIZE (9) 176 177 // 49 bytes is the max usb packet size for alternate setting 5 (Three 8 kHz 16-bit channels or one 8 kHz 16-bit channel and one 16 kHz 16-bit channel) 178 // note: alt setting 6 has max packet size of 63 every 7.5 ms = 472.5 bytes / HCI packet, while max SCO packet has 255 byte payload 179 #define SCO_PACKET_SIZE (NUM_ISO_PACKETS * ISO_PACKET_SIZE) 180 181 #define ISOC_BUFFERS 8 182 183 // Outgoing SCO packet queue 184 // simplified ring buffer implementation 185 #define SCO_RING_BUFFER_COUNT (20) 186 #define SCO_RING_BUFFER_SIZE (SCO_RING_BUFFER_COUNT * SCO_PACKET_SIZE) 187 188 /** Request type bits of the "bmRequestType" field in control transfers. */ 189 enum usb_request_type { 190 USB_REQUEST_TYPE_STANDARD = (0x00 << 5), 191 USB_REQUEST_TYPE_CLASS = (0x01 << 5), 192 USB_REQUEST_TYPE_VENDOR = (0x02 << 5), 193 }; 194 195 /** Recipient bits of the "bmRequestType" field in control transfers. Values 4 through 31 are reserved. */ 196 enum usb_request_recipient { 197 USB_RECIPIENT_DEVICE = 0x00, 198 USB_RECIPIENT_INTERFACE = 0x01, 199 USB_RECIPIENT_ENDPOINT = 0x02, 200 USB_RECIPIENT_OTHER = 0x03, 201 }; 202 203 // This is the GUID for the USB device class 204 static GUID GUID_DEVINTERFACE_USB_DEVICE = 205 { 0xA5DCBF10L, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } }; 206 207 static void usb_dummy_handler(uint8_t packet_type, uint8_t *packet, uint16_t size); 208 209 static void (*packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size) = &usb_dummy_handler; 210 211 // endpoint addresses 212 static int event_in_addr; 213 static int acl_in_addr; 214 static int acl_out_addr; 215 static int sco_in_addr; 216 static int sco_out_addr; 217 218 // 219 static HANDLE usb_device_handle; 220 static WINUSB_INTERFACE_HANDLE usb_interface_0_handle; 221 static WINUSB_INTERFACE_HANDLE usb_interface_1_handle; 222 static OVERLAPPED usb_overlapped_event_in; 223 static OVERLAPPED usb_overlapped_command_out; 224 static OVERLAPPED usb_overlapped_acl_in; 225 static OVERLAPPED usb_overlapped_acl_out; 226 static btstack_data_source_t usb_data_source_event_in; 227 static btstack_data_source_t usb_data_source_command_out; 228 static btstack_data_source_t usb_data_source_acl_in; 229 static btstack_data_source_t usb_data_source_acl_out; 230 231 // 232 static int usb_command_out_active; 233 static int usb_acl_out_active; 234 235 // buffer for HCI Events and ACL Packets 236 static uint8_t hci_event_in_buffer[2 + 255]; 237 static uint8_t hci_acl_in_buffer[HCI_INCOMING_PRE_BUFFER_SIZE + HCI_ACL_BUFFER_SIZE]; 238 239 240 #ifdef ENABLE_SCO_OVER_HCI 241 242 typedef enum { 243 H2_W4_SCO_HEADER = 1, 244 H2_W4_PAYLOAD, 245 } H2_SCO_STATE; 246 247 // SCO Incoming Windows 248 static uint8_t hci_sco_in_buffer[ISOC_BUFFERS * SCO_PACKET_SIZE]; 249 static WINUSB_ISOCH_BUFFER_HANDLE hci_sco_in_buffer_handle; 250 static USBD_ISO_PACKET_DESCRIPTOR hci_sco_packet_descriptors[ISOC_BUFFERS * NUM_ISO_PACKETS]; 251 static OVERLAPPED usb_overlapped_sco_in[ISOC_BUFFERS]; 252 static int usb_sco_in_expected_transfer; 253 254 // SCO Incoming Run Loop 255 static btstack_data_source_t usb_data_source_sco_in[ISOC_BUFFERS]; 256 257 // SCO Incoming HCI 258 static H2_SCO_STATE sco_state; 259 static uint8_t sco_buffer[SCO_PACKET_SIZE]; 260 static uint16_t sco_read_pos; 261 static uint16_t sco_bytes_to_read; 262 263 // SCO Outgoing Windows 264 static WINUSB_ISOCH_BUFFER_HANDLE hci_sco_out_buffer_handle; 265 static OVERLAPPED usb_overlapped_sco_out[SCO_RING_BUFFER_COUNT]; 266 static int sco_ring_transfers_active; 267 static int usb_sco_out_expected_transfer; 268 269 #ifdef SCHEDULE_SCO_IN_TRANSFERS_MANUALLY 270 // next tranfer 271 static ULONG sco_next_transfer_at_frame; 272 #endif 273 274 // SCO Outgoing Run Loop 275 static btstack_data_source_t usb_data_source_sco_out[SCO_RING_BUFFER_COUNT]; 276 277 // SCO Outgoing HCI 278 static uint8_t sco_ring_buffer[SCO_RING_BUFFER_SIZE]; 279 static int sco_ring_write; // packet idx 280 281 #endif 282 283 #if 0 284 // list of known devices, using VendorID/ProductID tuples 285 static const uint16_t known_bluetooth_devices[] = { 286 // DeLOCK Bluetooth 4.0 287 0x0a5c, 0x21e8, 288 // Asus BT400 289 0x0b05, 0x17cb, 290 }; 291 292 static int num_known_devices = sizeof(known_bluetooth_devices) / sizeof(uint16_t) / 2; 293 294 static int usb_is_known_bluetooth_device(uint16_t vendor_id, uint16_t product_id){ 295 int i; 296 for (i=0; i<num_known_devices; i++){ 297 if (known_bluetooth_devices[i*2] == vendor_id && known_bluetooth_devices[i*2+1] == product_id){ 298 return 1; 299 } 300 } 301 return 0; 302 } 303 #endif 304 305 #ifdef ENABLE_SCO_OVER_HCI 306 static void sco_ring_init(void){ 307 sco_ring_write = 0; 308 sco_ring_transfers_active = 0; 309 } 310 static int sco_ring_have_space(void){ 311 return sco_ring_transfers_active < SCO_RING_BUFFER_COUNT; 312 } 313 #endif 314 315 static void usb_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)){ 316 log_info("registering packet handler"); 317 packet_handler = handler; 318 } 319 320 static void usb_dummy_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){ 321 } 322 323 static void usb_init(const void *transport_config){ 324 } 325 326 static void usb_free_resources(void){ 327 if (usb_interface_1_handle){ 328 WinUsb_Free(usb_interface_1_handle); 329 usb_interface_1_handle = NULL; 330 } 331 332 if (usb_interface_0_handle){ 333 WinUsb_Free(usb_interface_0_handle); 334 usb_interface_0_handle = NULL; 335 } 336 337 if (usb_device_handle) { 338 CloseHandle(usb_device_handle); 339 usb_device_handle = NULL; 340 } 341 342 #ifdef ENABLE_SCO_OVER_HCI 343 if (hci_sco_in_buffer_handle){ 344 WinUsb_UnregisterIsochBuffer(hci_sco_in_buffer_handle); 345 hci_sco_in_buffer_handle = NULL; 346 } 347 if (hci_sco_out_buffer_handle){ 348 WinUsb_UnregisterIsochBuffer(hci_sco_out_buffer_handle); 349 hci_sco_out_buffer_handle = NULL; 350 } 351 #endif 352 } 353 354 static void usb_submit_event_in_transfer(void){ 355 // submit transfer 356 BOOL result = WinUsb_ReadPipe(usb_interface_0_handle, event_in_addr, hci_event_in_buffer, sizeof(hci_event_in_buffer), NULL, &usb_overlapped_event_in); 357 if (!result) { 358 if (GetLastError() != ERROR_IO_PENDING) goto exit_on_error; 359 } 360 361 // IO_PENDING -> wait for completed 362 btstack_run_loop_enable_data_source_callbacks(&usb_data_source_event_in, DATA_SOURCE_CALLBACK_READ); 363 return; 364 365 exit_on_error: 366 log_error("usb_submit_event_in_transfer: winusb last error %lu", GetLastError()); 367 } 368 369 static void usb_submit_acl_in_transfer(void){ 370 // submit transfer 371 BOOL result = WinUsb_ReadPipe(usb_interface_0_handle, acl_in_addr, hci_acl_in_buffer, sizeof(hci_acl_in_buffer), NULL, &usb_overlapped_acl_in); 372 if (!result) { 373 if (GetLastError() != ERROR_IO_PENDING) goto exit_on_error; 374 } 375 376 // IO_PENDING -> wait for completed 377 btstack_run_loop_enable_data_source_callbacks(&usb_data_source_acl_in, DATA_SOURCE_CALLBACK_READ); 378 return; 379 380 exit_on_error: 381 log_error("usb_submit_acl_in_transfer: winusb last error %lu", GetLastError()); 382 } 383 384 #ifdef ENABLE_SCO_OVER_HCI 385 #ifdef SCHEDULE_SCO_IN_TRANSFERS_MANUALLY 386 387 // frame number gets updated 388 static void usb_submit_sco_in_transfer_at_frame(int i, ULONG * frame_number){ 389 390 LARGE_INTEGER timestamp; 391 ULONG current_frame_number; 392 WinUsb_GetCurrentFrameNumber(usb_interface_0_handle, ¤t_frame_number, ×tamp); 393 394 ULONG frame_before = *frame_number; 395 396 BOOL result = WinUsb_ReadIsochPipe(hci_sco_in_buffer_handle, i * SCO_PACKET_SIZE, SCO_PACKET_SIZE, 397 frame_number, NUM_ISO_PACKETS, &hci_sco_packet_descriptors[i * NUM_ISO_PACKETS], &usb_overlapped_sco_in[i]); 398 399 log_info("WinUsb_ReadIsochPipe #%02u: current %lu, planned %lu - buffer %lu", i, current_frame_number, frame_before, frame_before - current_frame_number); 400 401 if (!result) { 402 if (GetLastError() == ERROR_IO_PENDING) { 403 } else { 404 goto exit_on_error; 405 } 406 } 407 408 return; 409 410 exit_on_error: 411 log_error("usb_submit_sco_in_transfer: winusb last error %lu", GetLastError()); 412 } 413 414 #else 415 416 static void usb_submit_sco_in_transfer_asap(int i, int continue_stream){ 417 418 LARGE_INTEGER timestamp; 419 ULONG current_frame_number; 420 WinUsb_GetCurrentFrameNumber(usb_interface_0_handle, ¤t_frame_number, ×tamp); 421 422 // log_info("usb_submit_sco_in_transfer[%02u]: current frame %lu", i, current_frame_number); 423 424 BOOL result = WinUsb_ReadIsochPipeAsap(hci_sco_in_buffer_handle, i * SCO_PACKET_SIZE, SCO_PACKET_SIZE, 425 continue_stream, NUM_ISO_PACKETS, &hci_sco_packet_descriptors[i * NUM_ISO_PACKETS], &usb_overlapped_sco_in[i]); 426 427 if (!result) { 428 if (GetLastError() != ERROR_IO_PENDING) goto exit_on_error; 429 } 430 431 return; 432 433 exit_on_error: 434 log_error("usb_submit_sco_in_transfer: winusb last error %lu", GetLastError()); 435 } 436 #endif 437 #endif 438 439 static void usb_process_event_in(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type) { 440 441 btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ); 442 443 DWORD bytes_read; 444 BOOL ok = WinUsb_GetOverlappedResult(usb_interface_0_handle, &usb_overlapped_event_in, &bytes_read, FALSE); 445 if(!ok){ 446 DWORD err = GetLastError(); 447 if (err == ERROR_IO_INCOMPLETE){ 448 // IO_INCOMPLETE -> wait for completed 449 btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ); 450 } else { 451 log_error("usb_process_event_in: error reading"); 452 } 453 return; 454 } 455 456 // notify uppper 457 packet_handler(HCI_EVENT_PACKET, hci_event_in_buffer, bytes_read); 458 459 // re-submit transfer 460 usb_submit_event_in_transfer(); 461 } 462 463 static void usb_process_acl_in(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type) { 464 465 btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ); 466 467 DWORD bytes_read; 468 BOOL ok = WinUsb_GetOverlappedResult(usb_interface_0_handle, &usb_overlapped_acl_in, &bytes_read, FALSE); 469 if(!ok){ 470 DWORD err = GetLastError(); 471 if (err == ERROR_IO_INCOMPLETE){ 472 // IO_INCOMPLETE -> wait for completed 473 btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ); 474 } else { 475 log_error("usb_process_acl_in: error writing"); 476 } 477 return; 478 } 479 480 // notify uppper 481 packet_handler(HCI_ACL_DATA_PACKET, hci_acl_in_buffer, bytes_read); 482 483 // re-submit transfer 484 usb_submit_acl_in_transfer(); 485 } 486 487 #ifdef ENABLE_SCO_OVER_HCI 488 static void sco_state_machine_init(void){ 489 sco_state = H2_W4_SCO_HEADER; 490 sco_read_pos = 0; 491 sco_bytes_to_read = 3; 492 } 493 494 static void sco_handle_data(uint8_t * buffer, uint16_t size){ 495 // printf("sco_handle_data: state %u, pos %u, to read %u, size %u", sco_state, sco_read_pos, sco_bytes_to_read, size); 496 while (size){ 497 if (size < sco_bytes_to_read){ 498 // just store incomplete data 499 memcpy(&sco_buffer[sco_read_pos], buffer, size); 500 sco_read_pos += size; 501 sco_bytes_to_read -= size; 502 return; 503 } 504 // copy requested data 505 memcpy(&sco_buffer[sco_read_pos], buffer, sco_bytes_to_read); 506 sco_read_pos += sco_bytes_to_read; 507 buffer += sco_bytes_to_read; 508 size -= sco_bytes_to_read; 509 510 // chunk read successfully, next action 511 switch (sco_state){ 512 case H2_W4_SCO_HEADER: 513 sco_state = H2_W4_PAYLOAD; 514 sco_bytes_to_read = sco_buffer[2]; 515 if (sco_bytes_to_read > (sizeof(sco_buffer)-3)){ 516 log_error("sco_handle_data: sco packet len > packet size"); 517 sco_state_machine_init(); 518 } 519 break; 520 case H2_W4_PAYLOAD: 521 // packet complete 522 packet_handler(HCI_SCO_DATA_PACKET, sco_buffer, sco_read_pos); 523 sco_state_machine_init(); 524 break; 525 } 526 } 527 } 528 529 static void usb_process_sco_out(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type){ 530 531 btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE); 532 533 // get current frame number 534 ULONG current_frame_number; 535 LARGE_INTEGER timestamp; 536 WinUsb_GetCurrentFrameNumber(usb_interface_0_handle, ¤t_frame_number, ×tamp); 537 538 // find index 539 int transfer_index; 540 for (transfer_index=0;transfer_index<SCO_RING_BUFFER_COUNT;transfer_index++){ 541 if (ds == &usb_data_source_sco_out[transfer_index]) break; 542 } 543 544 log_info("usb_process_sco_out[%02u] -- current frame %lu", transfer_index, current_frame_number); 545 546 DWORD bytes_transferred; 547 BOOL ok = WinUsb_GetOverlappedResult(usb_interface_0_handle, &usb_overlapped_sco_out[transfer_index], &bytes_transferred, FALSE); 548 log_info("usb_process_sco_out_done: #%u result %u, bytes %u, state %u", transfer_index, ok, (int) bytes_transferred, sco_state); 549 if(!ok){ 550 DWORD err = GetLastError(); 551 if (err == ERROR_IO_INCOMPLETE){ 552 // IO_INCOMPLETE -> wait for completed 553 btstack_run_loop_enable_data_source_callbacks(&usb_data_source_sco_out[transfer_index], DATA_SOURCE_CALLBACK_WRITE); 554 return; 555 } 556 log_error("usb_process_sco_out_done[%02u]: error writing %u, Internal %x", transfer_index, (int) err, (int) usb_overlapped_sco_out[transfer_index].Internal); 557 } 558 559 // decrease tab 560 sco_ring_transfers_active--; 561 562 // enable next data source callback 563 if (sco_ring_transfers_active){ 564 // update expected and wait for completion 565 usb_sco_out_expected_transfer = (transfer_index+ 1) % SCO_RING_BUFFER_COUNT; 566 log_info("usb_process_sco_out_done[%02u]: wait for transfer %02u", transfer_index, usb_sco_out_expected_transfer); 567 btstack_run_loop_enable_data_source_callbacks(&usb_data_source_sco_out[usb_sco_out_expected_transfer], DATA_SOURCE_CALLBACK_WRITE); 568 } 569 570 log_info("usb_process_sco_out_done: transfers active %u", sco_ring_transfers_active); 571 572 // mark free 573 if (sco_ring_have_space()) { 574 uint8_t event[] = { HCI_EVENT_SCO_CAN_SEND_NOW, 0}; 575 packet_handler(HCI_EVENT_PACKET, &event[0], sizeof(event)); 576 } 577 } 578 579 static void usb_process_sco_in(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type){ 580 581 btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ); 582 583 584 // find index 585 int i; 586 for (i=0;i<ISOC_BUFFERS;i++){ 587 if (ds == &usb_data_source_sco_in[i]) break; 588 } 589 int transfer_index = i; 590 591 // ULONG current_frame_number; 592 // LARGE_INTEGER timestamp; 593 // WinUsb_GetCurrentFrameNumber(usb_interface_0_handle, ¤t_frame_number, ×tamp); 594 595 // log_info("usb_process_sco_in[%02u] -- current frame %lu", transfer_index, current_frame_number); 596 597 DWORD bytes_transferred; 598 BOOL ok = WinUsb_GetOverlappedResult(usb_interface_0_handle, &usb_overlapped_sco_in[transfer_index], &bytes_transferred, FALSE); 599 600 if(!ok) { 601 DWORD err = GetLastError(); 602 if (err == ERROR_IO_INCOMPLETE) { 603 // IO_INCOMPLETE -> wait for completed 604 btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ); 605 return; 606 } 607 log_error("usb_process_sco_in[%02u]: error reading %u, Internal %x", transfer_index, (int) err, (int) usb_overlapped_sco_out[i].Internal); 608 } 609 610 if (ok){ 611 for (i=0;i<NUM_ISO_PACKETS;i++){ 612 USBD_ISO_PACKET_DESCRIPTOR * packet_descriptor = &hci_sco_packet_descriptors[transfer_index * NUM_ISO_PACKETS + i]; 613 if (packet_descriptor->Length){ 614 uint8_t * iso_data = &hci_sco_in_buffer[transfer_index * SCO_PACKET_SIZE + packet_descriptor->Offset]; 615 uint16_t iso_len = packet_descriptor->Length; 616 sco_handle_data(iso_data, iso_len); 617 } 618 } 619 } 620 621 #ifdef SCHEDULE_SCO_IN_TRANSFERS_MANUALLY 622 usb_submit_sco_in_transfer_at_frame(i, &sco_next_transfer_at_frame); 623 #else 624 usb_submit_sco_in_transfer_asap(transfer_index, 1); 625 #endif 626 // update expected and wait for completion 627 usb_sco_in_expected_transfer = (transfer_index+ 1) % ISOC_BUFFERS; 628 629 // log_info("usb_process_sco_in[%02u]: enable data source %02u", transfer_index, usb_sco_in_expected_transfer); 630 btstack_run_loop_enable_data_source_callbacks(&usb_data_source_sco_in[usb_sco_in_expected_transfer], DATA_SOURCE_CALLBACK_READ); 631 } 632 #endif 633 634 static void usb_process_command_out(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type){ 635 636 btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE); 637 638 // update stata before submitting transfer 639 usb_command_out_active = 0; 640 641 // notify upper stack that provided buffer can be used again 642 uint8_t event[] = { HCI_EVENT_TRANSPORT_PACKET_SENT, 0}; 643 packet_handler(HCI_EVENT_PACKET, &event[0], sizeof(event)); 644 } 645 646 static void usb_process_acl_out(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type){ 647 648 btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE); 649 650 // update stata before submitting transfer 651 usb_acl_out_active = 0; 652 653 // notify upper stack that provided buffer can be used again 654 uint8_t event[] = { HCI_EVENT_TRANSPORT_PACKET_SENT, 0}; 655 packet_handler(HCI_EVENT_PACKET, &event[0], sizeof(event)); 656 } 657 658 static BOOL usb_scan_for_bluetooth_endpoints(void) { 659 int i; 660 USB_INTERFACE_DESCRIPTOR usb_interface_descriptor; 661 662 // reset 663 event_in_addr = 0; 664 acl_in_addr = 0; 665 acl_out_addr = 0; 666 667 log_info("Scanning USB Entpoints:"); 668 669 // look for Event and ACL pipes on Interface #0 670 BOOL result = WinUsb_QueryInterfaceSettings(usb_interface_0_handle, 0, &usb_interface_descriptor); 671 if (!result) goto exit_on_error; 672 for (i=0;i<usb_interface_descriptor.bNumEndpoints;i++){ 673 WINUSB_PIPE_INFORMATION pipe; 674 result = WinUsb_QueryPipe( 675 usb_interface_0_handle, 676 0, 677 (UCHAR) i, 678 &pipe); 679 if (!result) goto exit_on_error; 680 log_info("Interface #0, Alt #0, Pipe idx #%u: type %u, id 0x%02x, max packet size %u,", 681 i, pipe.PipeType, pipe.PipeId, pipe.MaximumPacketSize); 682 switch (pipe.PipeType){ 683 case USB_ENDPOINT_TYPE_INTERRUPT: 684 if (event_in_addr) continue; 685 event_in_addr = pipe.PipeId; 686 log_info("-> using 0x%2.2X for HCI Events", event_in_addr); 687 break; 688 case USB_ENDPOINT_TYPE_BULK: 689 if (pipe.PipeId & 0x80) { 690 if (acl_in_addr) continue; 691 acl_in_addr = pipe.PipeId; 692 log_info("-> using 0x%2.2X for ACL Data In", acl_in_addr); 693 } else { 694 if (acl_out_addr) continue; 695 acl_out_addr = pipe.PipeId; 696 log_info("-> using 0x%2.2X for ACL Data Out", acl_out_addr); 697 } 698 break; 699 default: 700 break; 701 } 702 } 703 704 #ifdef ENABLE_SCO_OVER_HCI 705 sco_out_addr = 0; 706 sco_in_addr = 0; 707 708 // look for SCO pipes on Interface #1, Alt Setting ALT_SETTING 709 result = WinUsb_QueryInterfaceSettings(usb_interface_1_handle, ALT_SETTING, &usb_interface_descriptor); 710 if (!result) goto exit_on_error; 711 for (i=0;i<usb_interface_descriptor.bNumEndpoints;i++){ 712 WINUSB_PIPE_INFORMATION_EX pipe; 713 result = WinUsb_QueryPipeEx( 714 usb_interface_1_handle, 715 ALT_SETTING, 716 (UCHAR) i, 717 &pipe); 718 if (!result) goto exit_on_error; 719 log_info("Interface #1, Alt #%u, Pipe idx #%u: type %u, id 0x%02x, max packet size %u, interval %u, max bytes per interval %u", 720 ALT_SETTING, i, pipe.PipeType, pipe.PipeId, pipe.MaximumPacketSize, pipe.Interval, (int) pipe.MaximumBytesPerInterval); 721 switch (pipe.PipeType){ 722 case USB_ENDPOINT_TYPE_ISOCHRONOUS: 723 if (pipe.PipeId & 0x80) { 724 if (sco_in_addr) continue; 725 sco_in_addr = pipe.PipeId; 726 log_info("-> using 0x%2.2X for SCO Data In", sco_in_addr); 727 } else { 728 if (sco_out_addr) continue; 729 sco_out_addr = pipe.PipeId; 730 log_info("-> using 0x%2.2X for SCO Data Out", sco_out_addr); 731 } 732 break; 733 default: 734 break; 735 } 736 } 737 if (!sco_in_addr){ 738 log_error("Couldn't find pipe for SCO IN!"); 739 return FALSE; 740 } 741 if (!sco_out_addr){ 742 log_error("Couldn't find pipe for SCO IN!"); 743 return FALSE; 744 } 745 #endif 746 747 // check if all found 748 if (!event_in_addr){ 749 log_error("Couldn't find pipe for Event IN!"); 750 return FALSE; 751 } 752 if (!acl_in_addr){ 753 log_error("Couldn't find pipe for ACL IN!"); 754 return FALSE; 755 } 756 if (!acl_out_addr){ 757 log_error("Couldn't find pipe for ACL OUT!"); 758 return FALSE; 759 } 760 761 // all clear 762 return TRUE; 763 764 exit_on_error: 765 log_error("usb_scan_for_bluetooth_endpoints: last error %lu", GetLastError()); 766 return FALSE; 767 } 768 769 // returns 0 if successful, -1 otherwise 770 static int usb_try_open_device(const char * device_path){ 771 772 // open file 773 usb_device_handle = CreateFile(device_path, 774 GENERIC_WRITE | GENERIC_READ, 775 FILE_SHARE_WRITE | FILE_SHARE_READ, 776 NULL, 777 OPEN_EXISTING, 778 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 779 NULL); 780 log_info("Opening USB device: %p", usb_device_handle); 781 if (!usb_device_handle) goto exit_on_error; 782 783 // WinUsb_Initialize returns TRUE if the operation succeed 784 BOOL result = WinUsb_Initialize(usb_device_handle, &usb_interface_0_handle); 785 if (!result) goto exit_on_error; 786 787 // Detect USB Dongle based Class, Subclass, and Protocol 788 // The class code (bDeviceClass) is 0xE0 – Wireless Controller. 789 // The SubClass code (bDeviceSubClass) is 0x01 – RF Controller. 790 // The Protocol code (bDeviceProtocol) is 0x01 – Bluetooth programming. 791 USB_INTERFACE_DESCRIPTOR usb_interface_descriptor; 792 result = WinUsb_QueryInterfaceSettings(usb_interface_0_handle, 0, &usb_interface_descriptor); 793 if (!result) goto exit_on_error; 794 // 795 if (usb_interface_descriptor.bInterfaceClass != 0xe0 || 796 usb_interface_descriptor.bInterfaceSubClass != 0x01 || 797 usb_interface_descriptor.bInterfaceProtocol != 0x01){ 798 799 // TODO: fallback to whitelist 800 log_info("Class, Subclass, Protocol does not match Bluetooth device"); 801 usb_free_resources(); 802 return 0; 803 } 804 805 #ifdef ENABLE_SCO_OVER_HCI 806 log_info("Claiming interface 1..."); 807 // WinUsb_GetAssociatedInterface returns TRUE if the operation succeeds. 808 // We use index 1 - assuming it refers to interface #1 with libusb 809 // A value of 0 indicates the first associated interface, a value of 1 indicates the second associated interface, and so on. 810 result = WinUsb_GetAssociatedInterface(usb_interface_0_handle, 0, &usb_interface_1_handle); 811 if (!result) goto exit_on_error; 812 log_info("Claiming interface 1: success"); 813 814 log_info("Switching to setting %u on interface 1..", ALT_SETTING); 815 // WinUsb_SetCurrentAlternateSetting returns TRUE if the operation succeeds. 816 result = WinUsb_SetCurrentAlternateSetting(usb_interface_1_handle, ALT_SETTING); 817 if (!result) goto exit_on_error; 818 #endif 819 820 result = usb_scan_for_bluetooth_endpoints(); 821 if (!result) { 822 log_error("Could not find all Bluetooth Endpoints!"); 823 usb_free_resources(); 824 return 0; 825 } 826 827 #ifdef ENABLE_SCO_OVER_HCI 828 int i; 829 830 memset(hci_sco_packet_descriptors, 0, sizeof(hci_sco_packet_descriptors)); 831 log_info("Size of packet descriptors for SCO IN%u", (int) sizeof(hci_sco_packet_descriptors)); 832 833 result = WinUsb_RegisterIsochBuffer(usb_interface_1_handle, sco_in_addr, hci_sco_in_buffer, ISOC_BUFFERS * SCO_PACKET_SIZE, &hci_sco_in_buffer_handle); 834 if (!result) goto exit_on_error; 835 log_info("hci_sco_in_buffer_handle %p", hci_sco_in_buffer_handle); 836 837 result = WinUsb_RegisterIsochBuffer(usb_interface_1_handle, sco_out_addr, sco_ring_buffer, sizeof(sco_ring_buffer), &hci_sco_out_buffer_handle); 838 if (!result) goto exit_on_error; 839 log_info("hci_sco_out_buffer_handle %p", hci_sco_out_buffer_handle); 840 841 // setup async io && btstack handler 842 memset(&usb_overlapped_sco_in, 0, sizeof(usb_overlapped_sco_in)); 843 for (i=0;i<ISOC_BUFFERS;i++){ 844 usb_overlapped_sco_in[i].hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 845 // log_info_hexdump(&usb_overlapped_sco_in[i], sizeof(OVERLAPPED)); 846 // log_info("data source SCO in %u, handle %p", i, usb_overlapped_sco_in[i].hEvent); 847 usb_data_source_sco_in[i].handle = usb_overlapped_sco_in[i].hEvent; 848 btstack_run_loop_set_data_source_handler(&usb_data_source_sco_in[i], &usb_process_sco_in); 849 btstack_run_loop_add_data_source(&usb_data_source_sco_in[i]); 850 } 851 852 memset(&usb_overlapped_sco_out, 0, sizeof(usb_overlapped_sco_out)); 853 for (i=0;i<SCO_RING_BUFFER_COUNT;i++){ 854 usb_overlapped_sco_out[i].hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 855 // log_info("data source SCO out %u, handle %p", i, usb_overlapped_sco_out[i].hEvent); 856 usb_data_source_sco_out[i].handle = usb_overlapped_sco_out[i].hEvent; 857 btstack_run_loop_set_data_source_handler(&usb_data_source_sco_out[i], &usb_process_sco_out); 858 btstack_run_loop_add_data_source(&usb_data_source_sco_out[i]); 859 } 860 #endif 861 862 // setup async io 863 memset(&usb_overlapped_event_in, 0, sizeof(usb_overlapped_event_in)); 864 memset(&usb_overlapped_command_out, 0, sizeof(usb_overlapped_command_out)); 865 memset(&usb_overlapped_acl_out, 0, sizeof(usb_overlapped_acl_out)); 866 memset(&usb_overlapped_acl_in, 0, sizeof(usb_overlapped_acl_in)); 867 usb_overlapped_event_in.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 868 usb_overlapped_command_out.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 869 usb_overlapped_acl_in.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 870 usb_overlapped_acl_out.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 871 872 // setup btstack data soures 873 usb_data_source_event_in.handle = usb_overlapped_event_in.hEvent; 874 btstack_run_loop_set_data_source_handler(&usb_data_source_event_in, &usb_process_event_in); 875 btstack_run_loop_add_data_source(&usb_data_source_event_in); 876 877 usb_data_source_command_out.handle = usb_overlapped_command_out.hEvent; 878 btstack_run_loop_set_data_source_handler(&usb_data_source_command_out, &usb_process_command_out); 879 btstack_run_loop_add_data_source(&usb_data_source_command_out); 880 881 usb_data_source_acl_in.handle = usb_overlapped_acl_in.hEvent; 882 btstack_run_loop_set_data_source_handler(&usb_data_source_acl_in, &usb_process_acl_in); 883 btstack_run_loop_add_data_source(&usb_data_source_acl_in); 884 885 usb_data_source_acl_out.handle = usb_overlapped_acl_out.hEvent; 886 btstack_run_loop_set_data_source_handler(&usb_data_source_acl_out, &usb_process_acl_out); 887 btstack_run_loop_add_data_source(&usb_data_source_acl_out); 888 889 // submit all incoming transfers 890 usb_submit_event_in_transfer(); 891 usb_submit_acl_in_transfer(); 892 893 #ifdef ENABLE_SCO_OVER_HCI 894 895 #ifdef SCHEDULE_SCO_IN_TRANSFERS_MANUALLY 896 // get current frame number 897 ULONG current_frame_number; 898 LARGE_INTEGER timestamp; 899 WinUsb_GetCurrentFrameNumber(usb_interface_0_handle, ¤t_frame_number, ×tamp); 900 901 // plan for next tranfer 902 sco_next_transfer_at_frame = current_frame_number + ISOC_BUFFERS * NUM_ISO_PACKETS; 903 #endif 904 905 for (i=0;i<ISOC_BUFFERS;i++){ 906 #ifdef SCHEDULE_SCO_IN_TRANSFERS_MANUALLY 907 usb_submit_sco_in_transfer_at_frame(i, &sco_next_transfer_at_frame); 908 #else 909 usb_submit_sco_in_transfer_asap(i, 0); 910 #endif 911 } 912 913 usb_sco_in_expected_transfer = 0; 914 915 // only await first transfer to return 916 btstack_run_loop_enable_data_source_callbacks(&usb_data_source_sco_in[usb_sco_in_expected_transfer], DATA_SOURCE_CALLBACK_READ); 917 918 #if 0 919 // AUTO_CLEAR_STALL, RAW_IO, IGNORE_SHORT_PACKETS is not callable for ISO EP 920 uint8_t value = 0; 921 ULONG value_len = 1; 922 result = WinUsb_GetPipePolicy(usb_interface_0_handle, event_in_addr, IGNORE_SHORT_PACKETS, &value_len, &value); 923 if (!result) goto exit_on_error; 924 log_info("IGNORE_SHORT_PACKETS = %u", value); 925 926 uint8_t value_on = 0; 927 result = WinUsb_SetPipePolicy(usb_interface_1_handle, sco_in_addr, IGNORE_SHORT_PACKETS, sizeof(value_on), &value_on); 928 if (!result) goto exit_on_error; 929 #endif 930 931 #if 0 932 while (1){ 933 // 934 DWORD bytes_transferred; 935 BOOL ok = WinUsb_GetOverlappedResult(usb_interface_0_handle, &usb_overlapped_sco_in[usb_sco_in_expected_transfer], &bytes_transferred, TRUE); 936 937 // WinUsb_GetCurrentFrameNumber(usb_interface_0_handle, ¤t_frame_number, ×tamp); 938 939 // log_info("WinUsb_GetOverlappedResult[%02u]: ok = %u, current frame %lu", usb_sco_in_expected_transfer, ok, current_frame_number); 940 if (!ok){ 941 log_error("WinUsb_GetOverlappedResult res %x", (int) GetLastError()); 942 // return 0; 943 } 944 // update expected and wait for completion 945 usb_sco_in_expected_transfer = (usb_sco_in_expected_transfer + 1) % ISOC_BUFFERS; 946 947 usb_submit_sco_in_transfer_at_frame(usb_sco_in_expected_transfer, &sco_next_transfer_at_frame); 948 } 949 #endif 950 951 #endif 952 953 return 1; 954 955 exit_on_error: 956 log_error("usb_try_open_device: last error %lu", GetLastError()); 957 usb_free_resources(); 958 return 0; 959 } 960 961 #ifdef ENABLE_SCO_OVER_HCI 962 963 #define WinUSB_Lookup(fn) do { fn = (fn##_t) GetProcAddress(h, #fn); log_info("%-30s %p", #fn, fn); if (!fn) return FALSE; } while(0) 964 965 static BOOL usb_lookup_symbols(void){ 966 // lookup runtime symbols missing in current mingw64 distribution 967 HMODULE h = GetModuleHandleA("WinUSB"); 968 log_info("%-30s %p", "WinUSB", h); 969 WinUSB_Lookup(WinUsb_QueryPipeEx); 970 WinUSB_Lookup(WinUsb_RegisterIsochBuffer); 971 WinUSB_Lookup(WinUsb_ReadIsochPipe); 972 WinUSB_Lookup(WinUsb_ReadIsochPipeAsap); 973 WinUSB_Lookup(WinUsb_WriteIsochPipe); 974 WinUSB_Lookup(WinUsb_WriteIsochPipeAsap); 975 WinUSB_Lookup(WinUsb_UnregisterIsochBuffer); 976 WinUSB_Lookup(WinUsb_GetCurrentFrameNumber); 977 return TRUE; 978 } 979 #endif 980 981 // returns 0 on success, -1 otherwise 982 static int usb_open(void){ 983 984 int r = -1; 985 986 #ifdef ENABLE_SCO_OVER_HCI 987 BOOL ok = usb_lookup_symbols(); 988 if (!ok){ 989 log_error("usb_open: Failed to lookup WinSUB ISOCHRONOUS functions. Please disable ENABLE_SCO_OVER_HCI or use Windows 8.1 or higher"); 990 return r; 991 } 992 sco_state_machine_init(); 993 sco_ring_init(); 994 #endif 995 996 HDEVINFO hDevInfo; 997 SP_DEVICE_INTERFACE_DATA DevIntfData; 998 PSP_DEVICE_INTERFACE_DETAIL_DATA DevIntfDetailData; 999 SP_DEVINFO_DATA DevData; 1000 1001 DWORD dwSize; 1002 DWORD dwMemberIdx; 1003 1004 // default endpoint addresses 1005 event_in_addr = 0x81; // EP1, IN interrupt 1006 acl_in_addr = 0x82; // EP2, IN bulk 1007 acl_out_addr = 0x02; // EP2, OUT bulk 1008 sco_in_addr = 0x83; // EP3, IN isochronous 1009 sco_out_addr = 0x03; // EP3, OUT isochronous 1010 1011 // We will try to get device information set for all USB devices that have a 1012 // device interface and are currently present on the system (plugged in). 1013 hDevInfo = SetupDiGetClassDevs(&GUID_DEVINTERFACE_USB_DEVICE, NULL, 0, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); 1014 1015 log_info("usb_open: SetupDiGetClassDevs -> %p", hDevInfo); 1016 if (hDevInfo == INVALID_HANDLE_VALUE) return -1; 1017 1018 // Prepare to enumerate all device interfaces for the device information 1019 // set that we retrieved with SetupDiGetClassDevs(..) 1020 DevIntfData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); 1021 dwMemberIdx = 0; 1022 1023 // Next, we will keep calling this SetupDiEnumDeviceInterfaces(..) until this 1024 // function causes GetLastError() to return ERROR_NO_MORE_ITEMS. With each 1025 // call the dwMemberIdx value needs to be incremented to retrieve the next 1026 // device interface information. 1027 1028 SetupDiEnumDeviceInterfaces(hDevInfo, NULL, (LPGUID) &GUID_DEVINTERFACE_USB_DEVICE, 1029 dwMemberIdx, &DevIntfData); 1030 1031 while(GetLastError() != ERROR_NO_MORE_ITEMS){ 1032 1033 // As a last step we will need to get some more details for each 1034 // of device interface information we are able to retrieve. This 1035 // device interface detail gives us the information we need to identify 1036 // the device (VID/PID), and decide if it's useful to us. It will also 1037 // provide a DEVINFO_DATA structure which we can use to know the serial 1038 // port name for a virtual com port. 1039 1040 DevData.cbSize = sizeof(DevData); 1041 1042 // Get the required buffer size. Call SetupDiGetDeviceInterfaceDetail with 1043 // a NULL DevIntfDetailData pointer, a DevIntfDetailDataSize 1044 // of zero, and a valid RequiredSize variable. In response to such a call, 1045 // this function returns the required buffer size at dwSize. 1046 1047 SetupDiGetDeviceInterfaceDetail( 1048 hDevInfo, &DevIntfData, NULL, 0, &dwSize, NULL); 1049 1050 // Allocate memory for the DeviceInterfaceDetail struct. Don't forget to 1051 // deallocate it later! 1052 DevIntfDetailData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize); 1053 DevIntfDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); 1054 1055 if (SetupDiGetDeviceInterfaceDetail(hDevInfo, &DevIntfData, 1056 DevIntfDetailData, dwSize, &dwSize, &DevData)) 1057 { 1058 // Finally we can start checking if we've found a useable device, 1059 // by inspecting the DevIntfDetailData->DevicePath variable. 1060 // The DevicePath looks something like this: 1061 // 1062 // \\?\usb#vid_04d8&pid_0033#5&19f2438f&0&2#{a5dcbf10-6530-11d2-901f-00c04fb951ed} 1063 // 1064 1065 log_info("usb_open: Device Path: %s", DevIntfDetailData->DevicePath); 1066 1067 #if 0 1068 // check for hard-coded vendor/product ids 1069 char vid_pid_match[30]; 1070 uint16_t vid = 0x0a12; 1071 uint16_t pid = 0x0001; 1072 sprintf(vid_pid_match, "\\\\?\\usb#vid_%04x&pid_%04x", vid, pid); 1073 if (strncmp(DevIntfDetailData->DevicePath, &vid_pid_match[0], strlen(vid_pid_match)) == 0 ){ 1074 log_info("Matched search string %s", vid_pid_match); 1075 1076 BOOL result = usb_try_open_device(DevIntfDetailData->DevicePath); 1077 if (result){ 1078 log_info("usb_open: Device opened, stop scanning"); 1079 r = 0; 1080 } else { 1081 log_error("usb_open: Device open failed"); 1082 } 1083 } 1084 #endif 1085 1086 // try all devices 1087 BOOL result = usb_try_open_device(DevIntfDetailData->DevicePath); 1088 if (result){ 1089 log_info("usb_open: Device opened, stop scanning"); 1090 r = 0; 1091 } else { 1092 log_error("usb_open: Device open failed"); 1093 } 1094 } 1095 HeapFree(GetProcessHeap(), 0, DevIntfDetailData); 1096 1097 if (r == 0) break; 1098 1099 // Continue looping 1100 SetupDiEnumDeviceInterfaces( 1101 hDevInfo, NULL, &GUID_DEVINTERFACE_USB_DEVICE, ++dwMemberIdx, &DevIntfData); 1102 } 1103 1104 SetupDiDestroyDeviceInfoList(hDevInfo); 1105 1106 log_info("usb_open: done"); 1107 1108 return r; 1109 } 1110 1111 static int usb_close(void){ 1112 1113 // remove data sources 1114 btstack_run_loop_remove_data_source(&usb_data_source_command_out); 1115 btstack_run_loop_remove_data_source(&usb_data_source_event_in); 1116 btstack_run_loop_remove_data_source(&usb_data_source_acl_in); 1117 btstack_run_loop_remove_data_source(&usb_data_source_acl_out); 1118 1119 #ifdef ENABLE_SCO_OVER_HCI 1120 int i; 1121 for (i=0;i<ISOC_BUFFERS;i++){ 1122 btstack_run_loop_remove_data_source(&usb_data_source_sco_in[i]); 1123 } 1124 for (i=0;i<SCO_RING_BUFFER_COUNT;i++){ 1125 btstack_run_loop_remove_data_source(&usb_data_source_sco_out[i]); 1126 } 1127 #endif 1128 1129 // stop transfers 1130 WinUsb_AbortPipe(usb_interface_0_handle, event_in_addr); 1131 WinUsb_AbortPipe(usb_interface_0_handle, acl_in_addr); 1132 WinUsb_AbortPipe(usb_interface_0_handle, acl_out_addr); 1133 #ifdef ENABLE_SCO_OVER_HCI 1134 WinUsb_AbortPipe(usb_interface_0_handle, sco_in_addr); 1135 WinUsb_AbortPipe(usb_interface_0_handle, sco_out_addr); 1136 #endif 1137 usb_acl_out_active = 0; 1138 1139 // control transfer cannot be stopped, just wait for completion 1140 if (usb_command_out_active){ 1141 DWORD bytes_transferred; 1142 WinUsb_GetOverlappedResult(usb_interface_0_handle, &usb_overlapped_command_out, &bytes_transferred, TRUE); 1143 usb_command_out_active = 0; 1144 } 1145 1146 // free everything 1147 usb_free_resources(); 1148 return 0; 1149 } 1150 1151 static int usb_can_send_packet_now(uint8_t packet_type){ 1152 // return 0; 1153 switch (packet_type){ 1154 case HCI_COMMAND_DATA_PACKET: 1155 return !usb_command_out_active; 1156 case HCI_ACL_DATA_PACKET: 1157 return !usb_acl_out_active; 1158 #ifdef ENABLE_SCO_OVER_HCI 1159 case HCI_SCO_DATA_PACKET: 1160 // return 0; 1161 return sco_ring_have_space(); 1162 #endif 1163 default: 1164 return 0; 1165 } 1166 } 1167 1168 static int usb_send_cmd_packet(uint8_t *packet, int size){ 1169 1170 // update stata before submitting transfer 1171 usb_command_out_active = 1; 1172 1173 // Start trasnsfer 1174 WINUSB_SETUP_PACKET setup_packet; 1175 memset(&setup_packet, 0, sizeof(setup_packet)); 1176 setup_packet.RequestType = USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE; 1177 setup_packet.Length = sizeof(size); 1178 BOOL result = WinUsb_ControlTransfer(usb_interface_0_handle, setup_packet, packet, size, NULL, &usb_overlapped_command_out); 1179 if (!result) { 1180 if (GetLastError() != ERROR_IO_PENDING) goto exit_on_error; 1181 } 1182 1183 // IO_PENDING -> wait for completed 1184 btstack_run_loop_enable_data_source_callbacks(&usb_data_source_command_out, DATA_SOURCE_CALLBACK_WRITE); 1185 1186 return 0; 1187 1188 exit_on_error: 1189 log_error("winusb: last error %lu", GetLastError()); 1190 return -1; 1191 } 1192 1193 static int usb_send_acl_packet(uint8_t *packet, int size){ 1194 1195 // update stata before submitting transfer 1196 usb_acl_out_active = 1; 1197 1198 // Start trasnsfer 1199 BOOL ok = WinUsb_WritePipe(usb_interface_0_handle, acl_out_addr, packet, size, NULL, &usb_overlapped_acl_out); 1200 if (!ok) { 1201 if (GetLastError() != ERROR_IO_PENDING) goto exit_on_error; 1202 } 1203 1204 // IO_PENDING -> wait for completed 1205 btstack_run_loop_enable_data_source_callbacks(&usb_data_source_acl_out, DATA_SOURCE_CALLBACK_WRITE); 1206 return 0; 1207 1208 exit_on_error: 1209 log_error("winusb: last error %lu", GetLastError()); 1210 return -1; 1211 } 1212 1213 #ifdef ENABLE_SCO_OVER_HCI 1214 static int usb_send_sco_packet(uint8_t *packet, int size){ 1215 1216 if (size > SCO_PACKET_SIZE){ 1217 log_error("usb_send_sco_packet: size %u > SCO_PACKET_SIZE %u", size, SCO_PACKET_SIZE); 1218 return -1; 1219 } 1220 1221 // get current frame number 1222 ULONG current_frame_number; 1223 LARGE_INTEGER timestamp; 1224 WinUsb_GetCurrentFrameNumber(usb_interface_0_handle, ¤t_frame_number, ×tamp); 1225 1226 // store packet in free slot 1227 int transfer_index = sco_ring_write; 1228 uint8_t * data = &sco_ring_buffer[transfer_index * SCO_PACKET_SIZE]; 1229 memcpy(data, packet, size); 1230 1231 1232 // setup transfer 1233 int continue_stream = sco_ring_transfers_active > 0; 1234 BOOL ok = WinUsb_WriteIsochPipeAsap(hci_sco_out_buffer_handle, transfer_index * SCO_PACKET_SIZE, size, continue_stream, &usb_overlapped_sco_out[transfer_index]); 1235 log_info("usb_send_sco_packet: using slot #%02u, current frame %lu, continue stream %u, ok %u", transfer_index, current_frame_number, continue_stream, ok); 1236 if (!ok) { 1237 if (GetLastError() != ERROR_IO_PENDING) goto exit_on_error; 1238 } 1239 1240 // successful started transfer, enable data source callback if first active transfer 1241 if (sco_ring_transfers_active == 0){ 1242 usb_sco_out_expected_transfer = transfer_index; 1243 btstack_run_loop_enable_data_source_callbacks(&usb_data_source_sco_out[transfer_index], DATA_SOURCE_CALLBACK_WRITE); 1244 } 1245 1246 // mark slot as full 1247 sco_ring_write = (sco_ring_write + 1) % SCO_RING_BUFFER_COUNT; 1248 sco_ring_transfers_active++; 1249 1250 // notify upper stack that provided buffer can be used again 1251 uint8_t event[] = { HCI_EVENT_TRANSPORT_PACKET_SENT, 0}; 1252 packet_handler(HCI_EVENT_PACKET, &event[0], sizeof(event)); 1253 1254 log_info("usb_send_sco_packet: transfers active %u", sco_ring_transfers_active); 1255 1256 // and if we have more space for SCO packets 1257 if (sco_ring_have_space()) { 1258 uint8_t event_sco[] = { HCI_EVENT_SCO_CAN_SEND_NOW, 0}; 1259 packet_handler(HCI_EVENT_PACKET, &event_sco[0], sizeof(event_sco)); 1260 } 1261 return 0; 1262 1263 exit_on_error: 1264 log_error("usb_send_sco_packet: last error %lu", GetLastError()); 1265 return -1; 1266 } 1267 #endif 1268 1269 static int usb_send_packet(uint8_t packet_type, uint8_t * packet, int size){ 1270 switch (packet_type){ 1271 case HCI_COMMAND_DATA_PACKET: 1272 return usb_send_cmd_packet(packet, size); 1273 case HCI_ACL_DATA_PACKET: 1274 return usb_send_acl_packet(packet, size); 1275 #ifdef ENABLE_SCO_OVER_HCI 1276 case HCI_SCO_DATA_PACKET: 1277 return usb_send_sco_packet(packet, size); 1278 #endif 1279 default: 1280 return -1; 1281 } 1282 } 1283 1284 // get usb singleton 1285 static const hci_transport_t hci_transport_usb = { 1286 /* const char * name; */ "H2_WINUSB", 1287 /* void (*init) (const void *transport_config); */ &usb_init, 1288 /* int (*open)(void); */ &usb_open, 1289 /* int (*close)(void); */ &usb_close, 1290 /* void (*register_packet_handler)(void (*handler)(...); */ &usb_register_packet_handler, 1291 /* int (*can_send_packet_now)(uint8_t packet_type); */ &usb_can_send_packet_now, 1292 /* int (*send_packet)(...); */ &usb_send_packet, 1293 /* int (*set_baudrate)(uint32_t baudrate); */ NULL, 1294 /* void (*reset_link)(void); */ NULL, 1295 /* void (*set_sco_config)(uint16_t voice_setting, int num_connections); */ NULL, 1296 }; 1297 1298 const hci_transport_t * hci_transport_usb_instance(void) { 1299 return &hci_transport_usb; 1300 } 1301