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