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