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