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