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
hci_transport_usb_add_device(uint16_t vendor_id,uint16_t product_id)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
usb_is_vmware_bluetooth_adapter(const char * device_path)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
usb_device_path_match(const char * device_path,uint16_t vendor_id,uint16_t product_id)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
usb_is_known_bluetooth_device(const char * device_path)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
sco_ring_init(void)373 static void sco_ring_init(void){
374 sco_ring_write = 0;
375 sco_ring_transfers_active = 0;
376 }
sco_ring_have_space(void)377 static int sco_ring_have_space(void){
378 return sco_ring_transfers_active < SCO_RING_BUFFER_COUNT;
379 }
usb_sco_register_buffers(void)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 }
usb_sco_unregister_buffers(void)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
usb_register_packet_handler(void (* handler)(uint8_t packet_type,uint8_t * packet,uint16_t size))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
usb_dummy_handler(uint8_t packet_type,uint8_t * packet,uint16_t size)411 static void usb_dummy_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){
412 }
413
usb_init(const void * transport_config)414 static void usb_init(const void *transport_config){
415 }
416
usb_free_resources(void)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
usb_submit_event_in_transfer(void)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
usb_submit_acl_in_transfer(void)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
usb_submit_sco_in_transfer_at_frame(int i,ULONG * frame_number)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, ¤t_frame_number, ×tamp);
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
usb_submit_sco_in_transfer_asap(int i,int continue_stream)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, ¤t_frame_number, ×tamp);
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
usb_process_event_in(btstack_data_source_t * ds,btstack_data_source_callback_type_t callback_type)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
usb_process_acl_in(btstack_data_source_t * ds,btstack_data_source_callback_type_t callback_type)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
sco_state_machine_init(void)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
sco_handle_data(uint8_t * buffer,uint16_t size)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
usb_process_sco_out(btstack_data_source_t * ds,btstack_data_source_callback_type_t callback_type)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, ¤t_frame_number, ×tamp);
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
usb_process_sco_in(btstack_data_source_t * ds,btstack_data_source_callback_type_t callback_type)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, ¤t_frame_number, ×tamp);
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
usb_process_command_out(btstack_data_source_t * ds,btstack_data_source_callback_type_t callback_type)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
usb_process_acl_out(btstack_data_source_t * ds,btstack_data_source_callback_type_t callback_type)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
usb_scan_for_bluetooth_endpoints(void)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
usb_sco_start(void)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, ¤t_frame_number, ×tamp);
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
usb_sco_stop(void)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
usb_try_open_device(const char * device_path)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
usb_lookup_symbols(void)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
usb_open(void)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
usb_close(void)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
usb_can_send_packet_now(uint8_t packet_type)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
usb_send_cmd_packet(uint8_t * packet,int size)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
usb_send_acl_packet(uint8_t * packet,int size)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
usb_send_sco_packet(uint8_t * packet,int size)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, ¤t_frame_number, ×tamp);
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
usb_send_packet(uint8_t packet_type,uint8_t * packet,int size)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
usb_set_sco_config(uint16_t voice_setting,int num_connections)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
hci_transport_usb_instance(void)1471 const hci_transport_t * hci_transport_usb_instance(void) {
1472 return &hci_transport_usb;
1473 }
1474