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