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