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