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