1ff964d8eSMatthias Ringwald /*
2ff964d8eSMatthias Ringwald * Copyright (C) 2014 BlueKitchen GmbH
3ff964d8eSMatthias Ringwald *
4ff964d8eSMatthias Ringwald * Redistribution and use in source and binary forms, with or without
5ff964d8eSMatthias Ringwald * modification, are permitted provided that the following conditions
6ff964d8eSMatthias Ringwald * are met:
7ff964d8eSMatthias Ringwald *
8ff964d8eSMatthias Ringwald * 1. Redistributions of source code must retain the above copyright
9ff964d8eSMatthias Ringwald * notice, this list of conditions and the following disclaimer.
10ff964d8eSMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright
11ff964d8eSMatthias Ringwald * notice, this list of conditions and the following disclaimer in the
12ff964d8eSMatthias Ringwald * documentation and/or other materials provided with the distribution.
13ff964d8eSMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of
14ff964d8eSMatthias Ringwald * contributors may be used to endorse or promote products derived
15ff964d8eSMatthias Ringwald * from this software without specific prior written permission.
16ff964d8eSMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for
17ff964d8eSMatthias Ringwald * personal benefit and not for any commercial purpose or for
18ff964d8eSMatthias Ringwald * monetary gain.
19ff964d8eSMatthias Ringwald *
20ff964d8eSMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21ff964d8eSMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22ff964d8eSMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
232fca4dadSMilanka Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
242fca4dadSMilanka Ringwald * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25ff964d8eSMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26ff964d8eSMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27ff964d8eSMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28ff964d8eSMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29ff964d8eSMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30ff964d8eSMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31ff964d8eSMatthias Ringwald * SUCH DAMAGE.
32ff964d8eSMatthias Ringwald *
33ff964d8eSMatthias Ringwald * Please inquire about commercial licensing options at
34ff964d8eSMatthias Ringwald * [email protected]
35ff964d8eSMatthias Ringwald *
36ff964d8eSMatthias Ringwald */
37ff964d8eSMatthias Ringwald
38e501bae0SMatthias Ringwald #define BTSTACK_FILE__ "hci_transport_h2_libusb.c"
39ab2c6ae4SMatthias Ringwald
40ff964d8eSMatthias Ringwald /*
41ff964d8eSMatthias Ringwald * hci_transport_usb.c
42ff964d8eSMatthias Ringwald *
43ff964d8eSMatthias Ringwald * HCI Transport API implementation for USB
44ff964d8eSMatthias Ringwald *
45ff964d8eSMatthias Ringwald * Created by Matthias Ringwald on 7/5/09.
46ff964d8eSMatthias Ringwald */
47ff964d8eSMatthias Ringwald
48ff964d8eSMatthias Ringwald // Interface Number - Alternate Setting - suggested Endpoint Address - Endpoint Type - Suggested Max Packet Size
49ff964d8eSMatthias Ringwald // HCI Commands 0 0 0x00 Control 8/16/32/64
50ff964d8eSMatthias Ringwald // HCI Events 0 0 0x81 Interrupt (IN) 16
51ff964d8eSMatthias Ringwald // ACL Data 0 0 0x82 Bulk (IN) 32/64
52ff964d8eSMatthias Ringwald // ACL Data 0 0 0x02 Bulk (OUT) 32/64
53ff964d8eSMatthias Ringwald // SCO Data 0 0 0x83 Isochronous (IN)
54ff964d8eSMatthias Ringwald // SCO Data 0 0 0x03 Isochronous (Out)
55ff964d8eSMatthias Ringwald
56ff964d8eSMatthias Ringwald #include <strings.h>
57ff964d8eSMatthias Ringwald #include <string.h>
58ff964d8eSMatthias Ringwald #include <unistd.h> /* UNIX standard function definitions */
59ff964d8eSMatthias Ringwald #include <sys/types.h>
60ff964d8eSMatthias Ringwald
61ff964d8eSMatthias Ringwald #include <libusb.h>
62ff964d8eSMatthias Ringwald
633faa160fSDirk Helbig // bail out if seen libusb is apperently to old
643faa160fSDirk Helbig #if !defined(LIBUSB_API_VERSION) || (LIBUSB_API_VERSION < 0x01000104)
653faa160fSDirk Helbig #error libusb api version to old!
663faa160fSDirk Helbig #endif
673faa160fSDirk Helbig
683faa160fSDirk Helbig #include <poll.h>
693faa160fSDirk Helbig
70ff964d8eSMatthias Ringwald #include "btstack_config.h"
71ff964d8eSMatthias Ringwald
72ff964d8eSMatthias Ringwald #include "btstack_debug.h"
73ff964d8eSMatthias Ringwald #include "hci.h"
74ff964d8eSMatthias Ringwald #include "hci_transport.h"
75c8dfe071SMatthias Ringwald #include "hci_transport_usb.h"
76ff964d8eSMatthias Ringwald
775728804aSDirk Helbig #define DEBUG
785728804aSDirk Helbig
7964831607SMatthias Ringwald // deal with changes in libusb API:
8064831607SMatthias Ringwald #ifdef LIBUSB_API_VERSION
8164831607SMatthias Ringwald #if LIBUSB_API_VERSION >= 0x01000106
8264831607SMatthias Ringwald // since 1.0.22, libusb_set_option replaces libusb_set_debug
8364831607SMatthias Ringwald #define libusb_set_debug(context,level) libusb_set_option(context, LIBUSB_OPTION_LOG_LEVEL, level)
8464831607SMatthias Ringwald #endif
8564831607SMatthias Ringwald #endif
8664831607SMatthias Ringwald
87ff964d8eSMatthias Ringwald #if (USB_VENDOR_ID != 0) && (USB_PRODUCT_ID != 0)
88ff964d8eSMatthias Ringwald #define HAVE_USB_VENDOR_ID_AND_PRODUCT_ID
89ff964d8eSMatthias Ringwald #endif
90ff964d8eSMatthias Ringwald
91ee73ad13SMatthias Ringwald #define ACL_IN_BUFFER_COUNT 3
92ee73ad13SMatthias Ringwald #define EVENT_IN_BUFFER_COUNT 3
933faa160fSDirk Helbig #define EVENT_OUT_BUFFER_COUNT 4
94ee73ad13SMatthias Ringwald #define SCO_IN_BUFFER_COUNT 10
95ff964d8eSMatthias Ringwald
96ff964d8eSMatthias Ringwald #define ASYNC_POLLING_INTERVAL_MS 1
97ff964d8eSMatthias Ringwald
98ff964d8eSMatthias Ringwald //
99ff964d8eSMatthias Ringwald // Bluetooth USB Transport Alternate Settings:
100ff964d8eSMatthias Ringwald //
101ff964d8eSMatthias Ringwald // 0: No active voice channels (for USB compliance)
102ff964d8eSMatthias Ringwald // 1: One 8 kHz voice channel with 8-bit encoding
103ff964d8eSMatthias Ringwald // 2: Two 8 kHz voice channels with 8-bit encoding or one 8 kHz voice channel with 16-bit encoding
104ff964d8eSMatthias Ringwald // 3: Three 8 kHz voice channels with 8-bit encoding
105ff964d8eSMatthias Ringwald // 4: Two 8 kHz voice channels with 16-bit encoding or one 16 kHz voice channel with 16-bit encoding
106ff964d8eSMatthias Ringwald // 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
107ff964d8eSMatthias Ringwald // --> support only a single SCO connection
108f64229a0SMatthias Ringwald // #define ALT_SETTING (1)
109ff964d8eSMatthias Ringwald
110ee6b1613SMatthias Ringwald #ifdef ENABLE_SCO_OVER_HCI
111c6f9dc91SMatthias Ringwald // alt setting for 1-3 connections and 8/16 bit
112c6f9dc91SMatthias Ringwald static const int alt_setting_8_bit[] = {1,2,3};
113c6f9dc91SMatthias Ringwald static const int alt_setting_16_bit[] = {2,4,5};
114c6f9dc91SMatthias Ringwald
115ff964d8eSMatthias Ringwald // for ALT_SETTING >= 1 and 8-bit channel, we need the following isochronous packets
116ff964d8eSMatthias Ringwald // One complete SCO packet with 24 frames every 3 frames (== 3 ms)
117ff964d8eSMatthias Ringwald #define NUM_ISO_PACKETS (3)
118f34d119bSMatthias Ringwald
1199786b3a9SMatthias Ringwald static const uint16_t iso_packet_size_for_alt_setting[] = {
120f34d119bSMatthias Ringwald 0,
121f34d119bSMatthias Ringwald 9,
122f34d119bSMatthias Ringwald 17,
123f34d119bSMatthias Ringwald 25,
124f34d119bSMatthias Ringwald 33,
125f34d119bSMatthias Ringwald 49,
126f34d119bSMatthias Ringwald 63,
127f34d119bSMatthias Ringwald };
128ee6b1613SMatthias Ringwald #endif
129f34d119bSMatthias Ringwald
130ff964d8eSMatthias Ringwald // 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)
131ff964d8eSMatthias Ringwald // 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
132f64229a0SMatthias Ringwald #define SCO_PACKET_SIZE (49 * NUM_ISO_PACKETS)
133ff964d8eSMatthias Ringwald
134ff964d8eSMatthias Ringwald // Outgoing SCO packet queue
135ff964d8eSMatthias Ringwald // simplified ring buffer implementation
1365728804aSDirk Helbig #define SCO_OUT_BUFFER_COUNT (20)
137ee73ad13SMatthias Ringwald #define SCO_OUT_BUFFER_SIZE (SCO_OUT_BUFFER_COUNT * SCO_PACKET_SIZE)
138ff964d8eSMatthias Ringwald
139ff964d8eSMatthias Ringwald // seems to be the max depth for USB 3
140ff964d8eSMatthias Ringwald #define USB_MAX_PATH_LEN 7
141ff964d8eSMatthias Ringwald
142ff964d8eSMatthias Ringwald // prototypes
143ff964d8eSMatthias Ringwald static void dummy_handler(uint8_t packet_type, uint8_t *packet, uint16_t size);
144ff964d8eSMatthias Ringwald static int usb_close(void);
145ff964d8eSMatthias Ringwald
146ff964d8eSMatthias Ringwald typedef enum {
147ff964d8eSMatthias Ringwald LIB_USB_CLOSED = 0,
148ff964d8eSMatthias Ringwald LIB_USB_OPENED,
149ff964d8eSMatthias Ringwald LIB_USB_DEVICE_OPENDED,
150ff964d8eSMatthias Ringwald LIB_USB_INTERFACE_CLAIMED,
151ff964d8eSMatthias Ringwald LIB_USB_TRANSFERS_ALLOCATED
152ff964d8eSMatthias Ringwald } libusb_state_t;
153ff964d8eSMatthias Ringwald
154ff964d8eSMatthias Ringwald // SCO packet state machine
155ff964d8eSMatthias Ringwald typedef enum {
156ff964d8eSMatthias Ringwald H2_W4_SCO_HEADER = 1,
157ff964d8eSMatthias Ringwald H2_W4_PAYLOAD,
158ff964d8eSMatthias Ringwald } H2_SCO_STATE;
159ff964d8eSMatthias Ringwald
160ff964d8eSMatthias Ringwald static libusb_state_t libusb_state = LIB_USB_CLOSED;
161ff964d8eSMatthias Ringwald
162ff964d8eSMatthias Ringwald // single instance
163ff964d8eSMatthias Ringwald static hci_transport_t * hci_transport_usb = NULL;
164ff964d8eSMatthias Ringwald
165ff964d8eSMatthias Ringwald static void (*packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size) = dummy_handler;
166ff964d8eSMatthias Ringwald
167ff964d8eSMatthias Ringwald // libusb
168ff964d8eSMatthias Ringwald #ifndef HAVE_USB_VENDOR_ID_AND_PRODUCT_ID
169ff964d8eSMatthias Ringwald static struct libusb_device_descriptor desc;
170ff964d8eSMatthias Ringwald #endif
171ff964d8eSMatthias Ringwald static libusb_device_handle * handle;
172ff964d8eSMatthias Ringwald
17362ec5f72SMatthias Ringwald // known devices
17462ec5f72SMatthias Ringwald typedef struct {
17562ec5f72SMatthias Ringwald btstack_linked_item_t next;
17662ec5f72SMatthias Ringwald uint16_t vendor_id;
17762ec5f72SMatthias Ringwald uint16_t product_id;
17862ec5f72SMatthias Ringwald } usb_known_device_t;
17962ec5f72SMatthias Ringwald
18062ec5f72SMatthias Ringwald static btstack_linked_list_t usb_knwon_devices;
18162ec5f72SMatthias Ringwald
1823faa160fSDirk Helbig typedef struct list_head {
1833faa160fSDirk Helbig struct list_head *next, *prev;
1843faa160fSDirk Helbig } list_head_t;
1853faa160fSDirk Helbig
__list_add(list_head_t * new,list_head_t * prev,list_head_t * next)1863faa160fSDirk Helbig static inline void __list_add( list_head_t *new, list_head_t *prev, list_head_t *next ) {
1873faa160fSDirk Helbig next->prev = new;
1883faa160fSDirk Helbig new->next = next;
1893faa160fSDirk Helbig new->prev = prev;
1903faa160fSDirk Helbig prev->next = new;
1913faa160fSDirk Helbig }
1923faa160fSDirk Helbig
1933faa160fSDirk Helbig #define LIST_HEAD_INIT(name) { &(name), &(name) }
1943faa160fSDirk Helbig
init_list_head(list_head_t * list)1953faa160fSDirk Helbig static inline void init_list_head( list_head_t *list ) {
1963faa160fSDirk Helbig list->next = list;
1973faa160fSDirk Helbig list->prev = list;
1983faa160fSDirk Helbig }
1993faa160fSDirk Helbig
list_add(list_head_t * new,list_head_t * head)2003faa160fSDirk Helbig static inline void list_add( list_head_t *new, list_head_t *head ) {
2013faa160fSDirk Helbig __list_add( new, head, head->next );
2023faa160fSDirk Helbig }
2033faa160fSDirk Helbig
list_add_tail(list_head_t * new,list_head_t * head)2043faa160fSDirk Helbig static inline void list_add_tail( list_head_t *new, list_head_t *head ) {
2053faa160fSDirk Helbig __list_add( new, head->prev, head );
2063faa160fSDirk Helbig }
2073faa160fSDirk Helbig
list_del(list_head_t * entry)2083faa160fSDirk Helbig static inline void list_del( list_head_t *entry ) {
2093faa160fSDirk Helbig entry->next->prev = entry->prev;
2103faa160fSDirk Helbig entry->prev->next = entry->next;
2113faa160fSDirk Helbig
2123faa160fSDirk Helbig entry->prev = NULL;
2133faa160fSDirk Helbig entry->next = NULL;
2143faa160fSDirk Helbig }
2153faa160fSDirk Helbig
list_empty(list_head_t * head)2163faa160fSDirk Helbig static inline bool list_empty( list_head_t *head ) {
2173faa160fSDirk Helbig return head->next == head;
2183faa160fSDirk Helbig }
2193faa160fSDirk Helbig
list_pop_front(list_head_t * head)2203faa160fSDirk Helbig static inline list_head_t *list_pop_front( list_head_t *head ) {
2213faa160fSDirk Helbig list_head_t *front = head->next;
2223faa160fSDirk Helbig list_del( front );
2233faa160fSDirk Helbig return front;
2243faa160fSDirk Helbig }
2253faa160fSDirk Helbig
2263faa160fSDirk Helbig
2273faa160fSDirk Helbig typedef struct {
2283faa160fSDirk Helbig list_head_t list;
2293faa160fSDirk Helbig struct libusb_transfer *t;
2303faa160fSDirk Helbig uint8_t *data;
2313faa160fSDirk Helbig bool in_flight;
2323faa160fSDirk Helbig } usb_transfer_list_entry_t;
2333faa160fSDirk Helbig
2343faa160fSDirk Helbig typedef struct {
2353faa160fSDirk Helbig list_head_t transfers;
2363faa160fSDirk Helbig int nbr;
2373faa160fSDirk Helbig usb_transfer_list_entry_t entries[0];
2383faa160fSDirk Helbig } usb_transfer_list_t;
2393faa160fSDirk Helbig
usb_transfer_list_acquire(usb_transfer_list_t * list)2403faa160fSDirk Helbig static struct libusb_transfer *usb_transfer_list_acquire( usb_transfer_list_t *list ) {
2413faa160fSDirk Helbig usb_transfer_list_entry_t *current = (usb_transfer_list_entry_t*)list_pop_front( &list->transfers );
2423faa160fSDirk Helbig struct libusb_transfer *transfer = current->t;
2433faa160fSDirk Helbig current->in_flight = true;
2443faa160fSDirk Helbig return transfer;
2453faa160fSDirk Helbig }
2465728804aSDirk Helbig void usb_transfer_list_free( usb_transfer_list_t *list );
2473faa160fSDirk Helbig
usb_transfer_list_release(usb_transfer_list_t * list,struct libusb_transfer * transfer)2483faa160fSDirk Helbig static void usb_transfer_list_release( usb_transfer_list_t *list, struct libusb_transfer *transfer ) {
2493faa160fSDirk Helbig usb_transfer_list_entry_t *current = (usb_transfer_list_entry_t*)transfer->user_data;
250dd7eda92SDirk Helbig btstack_assert( current != NULL );
2513faa160fSDirk Helbig current->in_flight = false;
2523faa160fSDirk Helbig list_add( ¤t->list, &list->transfers );
2533faa160fSDirk Helbig }
2543faa160fSDirk Helbig
usb_transfer_list_empty(usb_transfer_list_t * list)2553faa160fSDirk Helbig static bool usb_transfer_list_empty( usb_transfer_list_t *list ) {
2563faa160fSDirk Helbig return list_empty( &list->transfers );
2573faa160fSDirk Helbig }
2583faa160fSDirk Helbig
usb_transfer_list_alloc(int nbr,int iso_packets,int length)2593faa160fSDirk Helbig static usb_transfer_list_t *usb_transfer_list_alloc( int nbr, int iso_packets, int length ) {
2603faa160fSDirk Helbig usb_transfer_list_t *list = malloc( sizeof(usb_transfer_list_t) + nbr*sizeof(usb_transfer_list_entry_t) );
2613faa160fSDirk Helbig init_list_head( &list->transfers );
2623faa160fSDirk Helbig list->nbr = nbr;
2633faa160fSDirk Helbig for( int i=0; i<nbr; ++i )
2643faa160fSDirk Helbig {
2653faa160fSDirk Helbig usb_transfer_list_entry_t *entry = &list->entries[i];
2663faa160fSDirk Helbig struct libusb_transfer *transfer = libusb_alloc_transfer(iso_packets);
2673faa160fSDirk Helbig entry->data = malloc( length );
2683faa160fSDirk Helbig transfer->buffer = entry->data;
2693faa160fSDirk Helbig transfer->user_data = entry;
2703faa160fSDirk Helbig entry->t = transfer;
2713faa160fSDirk Helbig usb_transfer_list_release( list, transfer );
272dd7eda92SDirk Helbig btstack_assert( entry->t->user_data != NULL );
2733faa160fSDirk Helbig }
2743faa160fSDirk Helbig return list;
2753faa160fSDirk Helbig }
2763faa160fSDirk Helbig
usb_transfer_list_cancel(usb_transfer_list_t * list)2773faa160fSDirk Helbig static void usb_transfer_list_cancel( usb_transfer_list_t *list ) {
27834de5f8bSDirk Helbig #ifdef __APPLE__
27934de5f8bSDirk Helbig // for darwin ignore all warnings
28034de5f8bSDirk Helbig libusb_set_debug(NULL, LIBUSB_LOG_LEVEL_ERROR);
28134de5f8bSDirk Helbig #endif
2823faa160fSDirk Helbig for( int i=0; i<list->nbr; ++i ) {
2833faa160fSDirk Helbig usb_transfer_list_entry_t *current = &list->entries[i];
2843faa160fSDirk Helbig if( current->in_flight ) {
2853faa160fSDirk Helbig libusb_cancel_transfer( current->t );
2863faa160fSDirk Helbig }
2873faa160fSDirk Helbig }
28834de5f8bSDirk Helbig #ifdef __APPLE__
28934de5f8bSDirk Helbig libusb_set_debug(NULL, LIBUSB_LOG_LEVEL_WARNING);
29034de5f8bSDirk Helbig #endif
2913faa160fSDirk Helbig }
2923faa160fSDirk Helbig
usb_transfer_list_in_flight(usb_transfer_list_t * list)2933faa160fSDirk Helbig static int usb_transfer_list_in_flight( usb_transfer_list_t *list ) {
2943faa160fSDirk Helbig int cnt = 0;
2953faa160fSDirk Helbig for(int i=0; i<list->nbr; ++i) {
2963faa160fSDirk Helbig usb_transfer_list_entry_t *entry = &list->entries[i];
2973faa160fSDirk Helbig if( entry->in_flight ) {
2983faa160fSDirk Helbig ++cnt;
2993faa160fSDirk Helbig }
3003faa160fSDirk Helbig }
3013faa160fSDirk Helbig return cnt;
3023faa160fSDirk Helbig }
3033faa160fSDirk Helbig
3043faa160fSDirk Helbig
usb_transfer_list_free_entry(struct libusb_transfer * transfer)3053faa160fSDirk Helbig static void usb_transfer_list_free_entry( struct libusb_transfer *transfer ) {
3063faa160fSDirk Helbig usb_transfer_list_entry_t *current = (usb_transfer_list_entry_t*)transfer->user_data;
3073faa160fSDirk Helbig free( current->data );
3083faa160fSDirk Helbig libusb_free_transfer( transfer );
3093faa160fSDirk Helbig current->in_flight = false;
3103faa160fSDirk Helbig current->t = NULL;
3113faa160fSDirk Helbig current->data = NULL;
3123faa160fSDirk Helbig }
3133faa160fSDirk Helbig
usb_transfer_list_free(usb_transfer_list_t * list)3143faa160fSDirk Helbig void usb_transfer_list_free( usb_transfer_list_t *list ) {
3153faa160fSDirk Helbig for( int i=0; i<list->nbr; ++i ) {
3163faa160fSDirk Helbig usb_transfer_list_entry_t *entry = &list->entries[i];
317dd7eda92SDirk Helbig btstack_assert( entry->in_flight == false );
3183faa160fSDirk Helbig if( entry->t ) {
3193faa160fSDirk Helbig usb_transfer_list_free_entry( entry->t );
3203faa160fSDirk Helbig }
3213faa160fSDirk Helbig }
3223faa160fSDirk Helbig free( list );
3233faa160fSDirk Helbig }
3243faa160fSDirk Helbig
3253faa160fSDirk Helbig static usb_transfer_list_t *default_transfer_list = NULL;
3263faa160fSDirk Helbig
3273faa160fSDirk Helbig // For (ab)use as a linked list of received packets
3283faa160fSDirk Helbig static list_head_t handle_packet_list = LIST_HEAD_INIT(handle_packet_list);
3293faa160fSDirk Helbig
enqueue_transfer(struct libusb_transfer * transfer)3303faa160fSDirk Helbig static void enqueue_transfer(struct libusb_transfer *transfer) {
3313faa160fSDirk Helbig usb_transfer_list_entry_t *current = (usb_transfer_list_entry_t*)transfer->user_data;
332dd7eda92SDirk Helbig btstack_assert( current != NULL );
3333faa160fSDirk Helbig list_add_tail( ¤t->list, &handle_packet_list );
3343faa160fSDirk Helbig }
3353faa160fSDirk Helbig
3365728804aSDirk Helbig static void signal_acknowledge(void);
3373faa160fSDirk Helbig
338be531a89SMatthias Ringwald #ifdef ENABLE_SCO_OVER_HCI
3397d6cb61eSMatthias Ringwald static void signal_sco_can_send_now(void);
340be531a89SMatthias Ringwald
341be531a89SMatthias Ringwald #ifdef _WIN32
342be531a89SMatthias Ringwald #error "SCO not working on Win32 (Windows 8, libusb 1.0.19, Zadic WinUSB), please uncomment ENABLE_SCO_OVER_HCI in btstack-config.h for now"
343be531a89SMatthias Ringwald #endif
344be531a89SMatthias Ringwald
345ff964d8eSMatthias Ringwald // incoming SCO
346ff964d8eSMatthias Ringwald static H2_SCO_STATE sco_state;
347ff964d8eSMatthias Ringwald static uint8_t sco_buffer[255+3 + SCO_PACKET_SIZE];
348ff964d8eSMatthias Ringwald static uint16_t sco_read_pos;
349ff964d8eSMatthias Ringwald static uint16_t sco_bytes_to_read;
35056e558dbSMatthias Ringwald
35156e558dbSMatthias Ringwald // pause/resume
35256e558dbSMatthias Ringwald static uint16_t sco_voice_setting;
35356e558dbSMatthias Ringwald static int sco_num_connections;
3545728804aSDirk Helbig static bool sco_activated;
35556e558dbSMatthias Ringwald
356f64229a0SMatthias Ringwald // dynamic SCO configuration
357f64229a0SMatthias Ringwald static uint16_t iso_packet_size;
3582bdb9b6dSMatthias Ringwald static int sco_enabled;
359f64229a0SMatthias Ringwald
3603faa160fSDirk Helbig usb_transfer_list_t *sco_transfer_list = NULL;
3613faa160fSDirk Helbig
362ff964d8eSMatthias Ringwald #endif
363ff964d8eSMatthias Ringwald
364ff964d8eSMatthias Ringwald
365ff964d8eSMatthias Ringwald static int doing_pollfds;
366ff964d8eSMatthias Ringwald static int num_pollfds;
367ff964d8eSMatthias Ringwald static btstack_data_source_t * pollfd_data_sources;
3683faa160fSDirk Helbig
3693faa160fSDirk Helbig static void usb_transport_response_ds(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type);
3703faa160fSDirk Helbig static btstack_data_source_t transport_response;
3713faa160fSDirk Helbig
372ff964d8eSMatthias Ringwald static btstack_timer_source_t usb_timer;
373ff964d8eSMatthias Ringwald static int usb_timer_active;
374ff964d8eSMatthias Ringwald
375ff964d8eSMatthias Ringwald // endpoint addresses
376ff964d8eSMatthias Ringwald static int event_in_addr;
377ff964d8eSMatthias Ringwald static int acl_in_addr;
378ff964d8eSMatthias Ringwald static int acl_out_addr;
379ff964d8eSMatthias Ringwald static int sco_in_addr;
380ff964d8eSMatthias Ringwald static int sco_out_addr;
381ff964d8eSMatthias Ringwald
382dd5fa345SMatthias Ringwald // device info
383ff964d8eSMatthias Ringwald static int usb_path_len;
384ff964d8eSMatthias Ringwald static uint8_t usb_path[USB_MAX_PATH_LEN];
385dd5fa345SMatthias Ringwald static uint16_t usb_vendor_id;
386dd5fa345SMatthias Ringwald static uint16_t usb_product_id;
387ff964d8eSMatthias Ringwald
388d2b52257SMatthias Ringwald // transport interface state
389d2b52257SMatthias Ringwald static int usb_transport_open;
390d2b52257SMatthias Ringwald
hci_transport_h2_libusb_emit_usb_info(void)391f85342b4SMatthias Ringwald static void hci_transport_h2_libusb_emit_usb_info(void) {
392f85342b4SMatthias Ringwald uint8_t event[7 + USB_MAX_PATH_LEN];
393f85342b4SMatthias Ringwald uint16_t pos = 0;
394f85342b4SMatthias Ringwald event[pos++] = HCI_EVENT_TRANSPORT_USB_INFO;
395f85342b4SMatthias Ringwald event[pos++] = 5 + usb_path_len;
396f85342b4SMatthias Ringwald little_endian_store_16(event, pos, usb_vendor_id);
397f85342b4SMatthias Ringwald pos+=2;
398f85342b4SMatthias Ringwald little_endian_store_16(event, pos, usb_product_id);
399f85342b4SMatthias Ringwald pos+=2;
400f85342b4SMatthias Ringwald event[pos++] = usb_path_len;
401f85342b4SMatthias Ringwald memcpy(&event[pos], usb_path, usb_path_len);
402f85342b4SMatthias Ringwald pos += usb_path_len;
403f85342b4SMatthias Ringwald (*packet_handler)(HCI_EVENT_PACKET, event, pos);
404f85342b4SMatthias Ringwald }
405ff964d8eSMatthias Ringwald
hci_transport_usb_add_device(uint16_t vendor_id,uint16_t product_id)40662ec5f72SMatthias Ringwald void hci_transport_usb_add_device(uint16_t vendor_id, uint16_t product_id) {
40762ec5f72SMatthias Ringwald usb_known_device_t * device = malloc(sizeof(usb_known_device_t));
40862ec5f72SMatthias Ringwald if (device != NULL) {
40962ec5f72SMatthias Ringwald device->vendor_id = vendor_id;
41062ec5f72SMatthias Ringwald device->product_id = product_id;
41162ec5f72SMatthias Ringwald btstack_linked_list_add(&usb_knwon_devices, (btstack_linked_item_t *) device);
41262ec5f72SMatthias Ringwald }
41362ec5f72SMatthias Ringwald }
41462ec5f72SMatthias Ringwald
hci_transport_usb_set_path(int len,uint8_t * port_numbers)415ff964d8eSMatthias Ringwald void hci_transport_usb_set_path(int len, uint8_t * port_numbers){
416ff964d8eSMatthias Ringwald if (len > USB_MAX_PATH_LEN || !port_numbers){
417ff964d8eSMatthias Ringwald log_error("hci_transport_usb_set_path: len or port numbers invalid");
418ff964d8eSMatthias Ringwald return;
419ff964d8eSMatthias Ringwald }
420ff964d8eSMatthias Ringwald usb_path_len = len;
421ff964d8eSMatthias Ringwald memcpy(usb_path, port_numbers, len);
422ff964d8eSMatthias Ringwald }
423ff964d8eSMatthias Ringwald
async_callback(struct libusb_transfer * transfer)424fd9ea8fdSMatthias Ringwald LIBUSB_CALL static void async_callback(struct libusb_transfer *transfer) {
4258644aff0SMatthias Ringwald if (libusb_state != LIB_USB_TRANSFERS_ALLOCATED) {
4268644aff0SMatthias Ringwald log_info("shutdown, transfer %p", transfer);
4273faa160fSDirk Helbig usb_transfer_list_free_entry( transfer );
4283faa160fSDirk Helbig return;
4298644aff0SMatthias Ringwald }
4303faa160fSDirk Helbig
431ff964d8eSMatthias Ringwald int r;
432ff964d8eSMatthias Ringwald // log_info("begin async_callback endpoint %x, status %x, actual length %u", transfer->endpoint, transfer->status, transfer->actual_length );
433ff964d8eSMatthias Ringwald
434ff964d8eSMatthias Ringwald if (transfer->status == LIBUSB_TRANSFER_COMPLETED) {
4353faa160fSDirk Helbig enqueue_transfer(transfer);
436ff964d8eSMatthias Ringwald } else if (transfer->status == LIBUSB_TRANSFER_STALL){
437ff964d8eSMatthias Ringwald log_info("-> Transfer stalled, trying again");
438ff964d8eSMatthias Ringwald r = libusb_clear_halt(handle, transfer->endpoint);
439ff964d8eSMatthias Ringwald if (r) {
440ff964d8eSMatthias Ringwald log_error("Error rclearing halt %d", r);
441ff964d8eSMatthias Ringwald }
442ff964d8eSMatthias Ringwald r = libusb_submit_transfer(transfer);
443ff964d8eSMatthias Ringwald if (r) {
444ff964d8eSMatthias Ringwald log_error("Error re-submitting transfer %d", r);
445ff964d8eSMatthias Ringwald }
446883fce10SDirk Helbig } else if ( transfer->status == LIBUSB_TRANSFER_CANCELLED ) {
447abe9af1aSDirk Helbig #ifdef ENABLE_SCO_OVER_HCI
448883fce10SDirk Helbig if(( transfer->endpoint == sco_in_addr) || (transfer->endpoint == sco_out_addr)) {
449883fce10SDirk Helbig usb_transfer_list_release( sco_transfer_list, transfer );
450dd7eda92SDirk Helbig } else
451abe9af1aSDirk Helbig #endif
452dd7eda92SDirk Helbig {
453883fce10SDirk Helbig usb_transfer_list_release( default_transfer_list, transfer );
454883fce10SDirk Helbig }
455ff964d8eSMatthias Ringwald } else {
456ff964d8eSMatthias Ringwald log_info("async_callback. not data -> resubmit transfer, endpoint %x, status %x, length %u", transfer->endpoint, transfer->status, transfer->actual_length);
457ff964d8eSMatthias Ringwald // No usable data, just resubmit packet
458ff964d8eSMatthias Ringwald r = libusb_submit_transfer(transfer);
459ff964d8eSMatthias Ringwald if (r) {
460ff964d8eSMatthias Ringwald log_error("Error re-submitting transfer %d", r);
461ff964d8eSMatthias Ringwald }
462ff964d8eSMatthias Ringwald }
463ff964d8eSMatthias Ringwald // log_info("end async_callback");
464ff964d8eSMatthias Ringwald }
465ff964d8eSMatthias Ringwald
466ff964d8eSMatthias Ringwald
467ff964d8eSMatthias Ringwald #ifdef ENABLE_SCO_OVER_HCI
usb_send_sco_packet(uint8_t * packet,int size)468ff964d8eSMatthias Ringwald static int usb_send_sco_packet(uint8_t *packet, int size){
469ff964d8eSMatthias Ringwald int r;
470ff964d8eSMatthias Ringwald
4715728804aSDirk Helbig if( !sco_activated ) {
4725728804aSDirk Helbig log_error("sco send without beeing active!");
4735728804aSDirk Helbig return -1;
4745728804aSDirk Helbig }
4755728804aSDirk Helbig
476ff964d8eSMatthias Ringwald if (libusb_state != LIB_USB_TRANSFERS_ALLOCATED) return -1;
477ff964d8eSMatthias Ringwald
4783faa160fSDirk Helbig struct libusb_transfer *transfer = usb_transfer_list_acquire( sco_transfer_list );
4793faa160fSDirk Helbig uint8_t *data = transfer->buffer;
4803faa160fSDirk Helbig void *user_data = transfer->user_data;
4813faa160fSDirk Helbig
482ff964d8eSMatthias Ringwald // log_info("usb_send_acl_packet enter, size %u", size);
483ff964d8eSMatthias Ringwald
484ff964d8eSMatthias Ringwald // store packet in free slot
485ff964d8eSMatthias Ringwald memcpy(data, packet, size);
486ff964d8eSMatthias Ringwald
487ff964d8eSMatthias Ringwald // setup transfer
488f64229a0SMatthias Ringwald // log_info("usb_send_sco_packet: size %u, max size %u, iso packet size %u", size, NUM_ISO_PACKETS * iso_packet_size, iso_packet_size);
4893faa160fSDirk Helbig libusb_fill_iso_transfer(transfer, handle, sco_out_addr, data, NUM_ISO_PACKETS * iso_packet_size, NUM_ISO_PACKETS, async_callback, user_data, 0);
4903faa160fSDirk Helbig libusb_set_iso_packet_lengths(transfer, iso_packet_size);
4913faa160fSDirk Helbig r = libusb_submit_transfer(transfer);
492ff964d8eSMatthias Ringwald if (r < 0) {
493ff964d8eSMatthias Ringwald log_error("Error submitting sco transfer, %d", r);
494ff964d8eSMatthias Ringwald return -1;
495ff964d8eSMatthias Ringwald }
496ff964d8eSMatthias Ringwald
497ee73ad13SMatthias Ringwald // log_info("H2: queued packet at index %u, num active %u", tranfer_index, sco_out_transfers_active);
4983faa160fSDirk Helbig signal_acknowledge();
499ff964d8eSMatthias Ringwald
5003faa160fSDirk Helbig if( !usb_transfer_list_empty( sco_transfer_list ) ) {
5013faa160fSDirk Helbig signal_sco_can_send_now();
502ff964d8eSMatthias Ringwald }
5033faa160fSDirk Helbig
504ff964d8eSMatthias Ringwald return 0;
505ff964d8eSMatthias Ringwald }
506ff964d8eSMatthias Ringwald
sco_state_machine_init(void)507ff964d8eSMatthias Ringwald static void sco_state_machine_init(void){
508ff964d8eSMatthias Ringwald sco_state = H2_W4_SCO_HEADER;
509ff964d8eSMatthias Ringwald sco_read_pos = 0;
510ff964d8eSMatthias Ringwald sco_bytes_to_read = 3;
511ff964d8eSMatthias Ringwald }
512ff964d8eSMatthias Ringwald
handle_isochronous_data(uint8_t * buffer,uint16_t size)513ff964d8eSMatthias Ringwald static void handle_isochronous_data(uint8_t * buffer, uint16_t size){
514ff964d8eSMatthias Ringwald while (size){
515ff964d8eSMatthias Ringwald if (size < sco_bytes_to_read){
516ff964d8eSMatthias Ringwald // just store incomplete data
517ff964d8eSMatthias Ringwald memcpy(&sco_buffer[sco_read_pos], buffer, size);
518ff964d8eSMatthias Ringwald sco_read_pos += size;
519ff964d8eSMatthias Ringwald sco_bytes_to_read -= size;
520ff964d8eSMatthias Ringwald return;
521ff964d8eSMatthias Ringwald }
522ff964d8eSMatthias Ringwald // copy requested data
523ff964d8eSMatthias Ringwald memcpy(&sco_buffer[sco_read_pos], buffer, sco_bytes_to_read);
524ff964d8eSMatthias Ringwald sco_read_pos += sco_bytes_to_read;
525ff964d8eSMatthias Ringwald buffer += sco_bytes_to_read;
526ff964d8eSMatthias Ringwald size -= sco_bytes_to_read;
527ff964d8eSMatthias Ringwald
528ff964d8eSMatthias Ringwald // chunk read successfully, next action
529ff964d8eSMatthias Ringwald switch (sco_state){
530ff964d8eSMatthias Ringwald case H2_W4_SCO_HEADER:
531ff964d8eSMatthias Ringwald sco_state = H2_W4_PAYLOAD;
532ff964d8eSMatthias Ringwald sco_bytes_to_read = sco_buffer[2];
533ff964d8eSMatthias Ringwald break;
534ff964d8eSMatthias Ringwald case H2_W4_PAYLOAD:
535ff964d8eSMatthias Ringwald // packet complete
536ff964d8eSMatthias Ringwald packet_handler(HCI_SCO_DATA_PACKET, sco_buffer, sco_read_pos);
537ff964d8eSMatthias Ringwald sco_state_machine_init();
538ff964d8eSMatthias Ringwald break;
539a8d51f09SMatthias Ringwald default:
540a8d51f09SMatthias Ringwald btstack_assert(false);
541a8d51f09SMatthias Ringwald break;
542ff964d8eSMatthias Ringwald }
543ff964d8eSMatthias Ringwald }
544ff964d8eSMatthias Ringwald }
545ff964d8eSMatthias Ringwald #endif
546ff964d8eSMatthias Ringwald
handle_completed_transfer(struct libusb_transfer * transfer)547ff964d8eSMatthias Ringwald static void handle_completed_transfer(struct libusb_transfer *transfer){
548ff964d8eSMatthias Ringwald
549ff964d8eSMatthias Ringwald int resubmit = 0;
550ff964d8eSMatthias Ringwald if (transfer->endpoint == event_in_addr) {
551ff964d8eSMatthias Ringwald packet_handler(HCI_EVENT_PACKET, transfer->buffer, transfer->actual_length);
552ff964d8eSMatthias Ringwald resubmit = 1;
553ff964d8eSMatthias Ringwald } else if (transfer->endpoint == acl_in_addr) {
554ff964d8eSMatthias Ringwald // log_info("-> acl");
555ff964d8eSMatthias Ringwald packet_handler(HCI_ACL_DATA_PACKET, transfer->buffer, transfer->actual_length);
556ff964d8eSMatthias Ringwald resubmit = 1;
557ff964d8eSMatthias Ringwald } else if (transfer->endpoint == 0){
558ff964d8eSMatthias Ringwald // log_info("command done, size %u", transfer->actual_length);
5593faa160fSDirk Helbig // printf("%s cmd release\n", __FUNCTION__ );
5603faa160fSDirk Helbig usb_transfer_list_release( default_transfer_list, transfer );
561ff964d8eSMatthias Ringwald } else if (transfer->endpoint == acl_out_addr){
562ff964d8eSMatthias Ringwald // log_info("acl out done, size %u", transfer->actual_length);
5633faa160fSDirk Helbig // printf("%s acl release\n", __FUNCTION__ );
5643faa160fSDirk Helbig usb_transfer_list_release( default_transfer_list, transfer );
565ff964d8eSMatthias Ringwald #ifdef ENABLE_SCO_OVER_HCI
566ff964d8eSMatthias Ringwald } else if (transfer->endpoint == sco_in_addr) {
567ff964d8eSMatthias Ringwald // log_info("handle_completed_transfer for SCO IN! num packets %u", transfer->NUM_ISO_PACKETS);
5683faa160fSDirk Helbig
5693faa160fSDirk Helbig // give the transfer back to the pool, without resubmiting
5705728804aSDirk Helbig if( !sco_activated ) {
5713faa160fSDirk Helbig usb_transfer_list_release( sco_transfer_list, transfer );
5723faa160fSDirk Helbig return;
5733faa160fSDirk Helbig }
5743faa160fSDirk Helbig
575ff964d8eSMatthias Ringwald int i;
576ff964d8eSMatthias Ringwald for (i = 0; i < transfer->num_iso_packets; i++) {
577ff964d8eSMatthias Ringwald struct libusb_iso_packet_descriptor *pack = &transfer->iso_packet_desc[i];
578ff964d8eSMatthias Ringwald if (pack->status != LIBUSB_TRANSFER_COMPLETED) {
579ff964d8eSMatthias Ringwald log_error("Error: pack %u status %d\n", i, pack->status);
580ff964d8eSMatthias Ringwald continue;
581ff964d8eSMatthias Ringwald }
582ff964d8eSMatthias Ringwald if (!pack->actual_length) continue;
583ff964d8eSMatthias Ringwald uint8_t * data = libusb_get_iso_packet_buffer_simple(transfer, i);
584ff964d8eSMatthias Ringwald handle_isochronous_data(data, pack->actual_length);
585ff964d8eSMatthias Ringwald }
586ff964d8eSMatthias Ringwald resubmit = 1;
587ff964d8eSMatthias Ringwald } else if (transfer->endpoint == sco_out_addr){
5881f4116c1SMatthias Ringwald int i;
5891f4116c1SMatthias Ringwald for (i = 0; i < transfer->num_iso_packets; i++) {
590a09e374cSJoep Moritz struct libusb_iso_packet_descriptor *pack = &transfer->iso_packet_desc[i];
591a09e374cSJoep Moritz if (pack->status != LIBUSB_TRANSFER_COMPLETED) {
592a09e374cSJoep Moritz log_error("Error: pack %u status %d\n", i, pack->status);
593a09e374cSJoep Moritz }
594a09e374cSJoep Moritz }
5953faa160fSDirk Helbig usb_transfer_list_release( sco_transfer_list, transfer );
5965728804aSDirk Helbig if( !sco_activated ) {
5973faa160fSDirk Helbig return;
5983faa160fSDirk Helbig }
599a09e374cSJoep Moritz // log_info("sco out done, {{ %u/%u (%x)}, { %u/%u (%x)}, { %u/%u (%x)}}",
600a09e374cSJoep Moritz // transfer->iso_packet_desc[0].actual_length, transfer->iso_packet_desc[0].length, transfer->iso_packet_desc[0].status,
601a09e374cSJoep Moritz // transfer->iso_packet_desc[1].actual_length, transfer->iso_packet_desc[1].length, transfer->iso_packet_desc[1].status,
602a09e374cSJoep Moritz // transfer->iso_packet_desc[2].actual_length, transfer->iso_packet_desc[2].length, transfer->iso_packet_desc[2].status);
603ff964d8eSMatthias Ringwald // notify upper layer if there's space for new SCO packets
604a09e374cSJoep Moritz
6053faa160fSDirk Helbig if (!usb_transfer_list_empty(sco_transfer_list)) {
6063faa160fSDirk Helbig signal_sco_can_send_now();
607ff964d8eSMatthias Ringwald }
608ee73ad13SMatthias Ringwald // log_info("H2: sco out complete, num active num active %u", sco_out_transfers_active);
609ff964d8eSMatthias Ringwald #endif
610ff964d8eSMatthias Ringwald } else {
611ff964d8eSMatthias Ringwald log_info("usb_process_ds endpoint unknown %x", transfer->endpoint);
612ff964d8eSMatthias Ringwald }
613ff964d8eSMatthias Ringwald
614ff964d8eSMatthias Ringwald if (libusb_state != LIB_USB_TRANSFERS_ALLOCATED) return;
615ff964d8eSMatthias Ringwald
616ff964d8eSMatthias Ringwald if (resubmit){
617ff964d8eSMatthias Ringwald // Re-submit transfer
618ff964d8eSMatthias Ringwald int r = libusb_submit_transfer(transfer);
619ff964d8eSMatthias Ringwald if (r) {
620ff964d8eSMatthias Ringwald log_error("Error re-submitting transfer %d", r);
621ff964d8eSMatthias Ringwald }
622ff964d8eSMatthias Ringwald }
623ff964d8eSMatthias Ringwald }
624ff964d8eSMatthias Ringwald
6255728804aSDirk Helbig void usb_handle_pending_events(void);
usb_handle_pending_events(void)6265728804aSDirk Helbig void usb_handle_pending_events(void) {
6273faa160fSDirk Helbig struct timeval tv = { 0 };
6283faa160fSDirk Helbig libusb_handle_events_timeout_completed(NULL, &tv, NULL);
6293faa160fSDirk Helbig }
6303faa160fSDirk Helbig
usb_process_ds(btstack_data_source_t * ds,btstack_data_source_callback_type_t callback_type)631ff964d8eSMatthias Ringwald static void usb_process_ds(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type) {
6329ec2630cSMatthias Ringwald
6339ec2630cSMatthias Ringwald UNUSED(ds);
6349ec2630cSMatthias Ringwald UNUSED(callback_type);
6359ec2630cSMatthias Ringwald
636ff964d8eSMatthias Ringwald if (libusb_state != LIB_USB_TRANSFERS_ALLOCATED) return;
637ff964d8eSMatthias Ringwald
638ff964d8eSMatthias Ringwald // log_info("begin usb_process_ds");
639ff964d8eSMatthias Ringwald // always handling an event as we're called when data is ready
6403faa160fSDirk Helbig usb_handle_pending_events();
641ff964d8eSMatthias Ringwald
642ff964d8eSMatthias Ringwald // Handle any packet in the order that they were received
6433faa160fSDirk Helbig while (!list_empty(&handle_packet_list)) {
644ff964d8eSMatthias Ringwald // log_info("handle packet %p, endpoint %x, status %x", handle_packet, handle_packet->endpoint, handle_packet->status);
64506c6f94cSMatthias Ringwald
64606c6f94cSMatthias Ringwald // pop next transfer
6473faa160fSDirk Helbig usb_transfer_list_entry_t *current = (usb_transfer_list_entry_t*)list_pop_front( &handle_packet_list );
64806c6f94cSMatthias Ringwald
64906c6f94cSMatthias Ringwald // handle transfer
6503faa160fSDirk Helbig handle_completed_transfer(current->t);
65106c6f94cSMatthias Ringwald
652ff964d8eSMatthias Ringwald // handle case where libusb_close might be called by hci packet handler
653ff964d8eSMatthias Ringwald if (libusb_state != LIB_USB_TRANSFERS_ALLOCATED) return;
654ff964d8eSMatthias Ringwald }
655ff964d8eSMatthias Ringwald // log_info("end usb_process_ds");
656ff964d8eSMatthias Ringwald }
657ff964d8eSMatthias Ringwald
usb_process_ts(btstack_timer_source_t * timer)658ff964d8eSMatthias Ringwald static void usb_process_ts(btstack_timer_source_t *timer) {
6599ec2630cSMatthias Ringwald
6609ec2630cSMatthias Ringwald UNUSED(timer);
6619ec2630cSMatthias Ringwald
662ff964d8eSMatthias Ringwald // log_info("in usb_process_ts");
663ff964d8eSMatthias Ringwald
664ff964d8eSMatthias Ringwald // timer is deactive, when timer callback gets called
665ff964d8eSMatthias Ringwald usb_timer_active = 0;
666ff964d8eSMatthias Ringwald
667ff964d8eSMatthias Ringwald if (libusb_state != LIB_USB_TRANSFERS_ALLOCATED) return;
668ff964d8eSMatthias Ringwald
669ff964d8eSMatthias Ringwald // actually handled the packet in the pollfds function
670ff964d8eSMatthias Ringwald usb_process_ds((struct btstack_data_source *) NULL, DATA_SOURCE_CALLBACK_READ);
671ff964d8eSMatthias Ringwald
672ff964d8eSMatthias Ringwald // Get the amount of time until next event is due
673ff964d8eSMatthias Ringwald long msec = ASYNC_POLLING_INTERVAL_MS;
674ff964d8eSMatthias Ringwald
675ff964d8eSMatthias Ringwald // Activate timer
676ff964d8eSMatthias Ringwald btstack_run_loop_set_timer(&usb_timer, msec);
677ff964d8eSMatthias Ringwald btstack_run_loop_add_timer(&usb_timer);
678ff964d8eSMatthias Ringwald usb_timer_active = 1;
679ff964d8eSMatthias Ringwald
680ff964d8eSMatthias Ringwald return;
681ff964d8eSMatthias Ringwald }
682ff964d8eSMatthias Ringwald
683ff964d8eSMatthias Ringwald
scan_for_bt_endpoints(libusb_device * dev)684696b00c8SMilanka Ringwald static int scan_for_bt_endpoints(libusb_device *dev) {
685ff964d8eSMatthias Ringwald int r;
686ff964d8eSMatthias Ringwald
687ff964d8eSMatthias Ringwald event_in_addr = 0;
688ff964d8eSMatthias Ringwald acl_in_addr = 0;
689ff964d8eSMatthias Ringwald acl_out_addr = 0;
690ff964d8eSMatthias Ringwald sco_out_addr = 0;
691ff964d8eSMatthias Ringwald sco_in_addr = 0;
692ff964d8eSMatthias Ringwald
693ff964d8eSMatthias Ringwald // get endpoints from interface descriptor
694ff964d8eSMatthias Ringwald struct libusb_config_descriptor *config_descriptor;
695ff964d8eSMatthias Ringwald r = libusb_get_active_config_descriptor(dev, &config_descriptor);
696696b00c8SMilanka Ringwald if (r < 0) return r;
697ff964d8eSMatthias Ringwald
698ff964d8eSMatthias Ringwald int num_interfaces = config_descriptor->bNumInterfaces;
699ff964d8eSMatthias Ringwald log_info("active configuration has %u interfaces", num_interfaces);
700ff964d8eSMatthias Ringwald
701ff964d8eSMatthias Ringwald int i;
702ff964d8eSMatthias Ringwald for (i = 0; i < num_interfaces ; i++){
703ff964d8eSMatthias Ringwald const struct libusb_interface *interface = &config_descriptor->interface[i];
704ff964d8eSMatthias Ringwald const struct libusb_interface_descriptor * interface_descriptor = interface->altsetting;
705ff964d8eSMatthias Ringwald log_info("interface %u: %u endpoints", i, interface_descriptor->bNumEndpoints);
706ff964d8eSMatthias Ringwald
707ff964d8eSMatthias Ringwald const struct libusb_endpoint_descriptor *endpoint = interface_descriptor->endpoint;
708ff964d8eSMatthias Ringwald
709ff964d8eSMatthias Ringwald for (r=0;r<interface_descriptor->bNumEndpoints;r++,endpoint++){
710ff964d8eSMatthias Ringwald log_info("- endpoint %x, attributes %x", endpoint->bEndpointAddress, endpoint->bmAttributes);
711ff964d8eSMatthias Ringwald
712ff964d8eSMatthias Ringwald switch (endpoint->bmAttributes & 0x3){
713ff964d8eSMatthias Ringwald case LIBUSB_TRANSFER_TYPE_INTERRUPT:
714ff964d8eSMatthias Ringwald if (event_in_addr) continue;
715ff964d8eSMatthias Ringwald event_in_addr = endpoint->bEndpointAddress;
716ff964d8eSMatthias Ringwald log_info("-> using 0x%2.2X for HCI Events", event_in_addr);
717ff964d8eSMatthias Ringwald break;
718ff964d8eSMatthias Ringwald case LIBUSB_TRANSFER_TYPE_BULK:
719ff964d8eSMatthias Ringwald if (endpoint->bEndpointAddress & 0x80) {
720ff964d8eSMatthias Ringwald if (acl_in_addr) continue;
721ff964d8eSMatthias Ringwald acl_in_addr = endpoint->bEndpointAddress;
722ff964d8eSMatthias Ringwald log_info("-> using 0x%2.2X for ACL Data In", acl_in_addr);
723ff964d8eSMatthias Ringwald } else {
724ff964d8eSMatthias Ringwald if (acl_out_addr) continue;
725ff964d8eSMatthias Ringwald acl_out_addr = endpoint->bEndpointAddress;
726ff964d8eSMatthias Ringwald log_info("-> using 0x%2.2X for ACL Data Out", acl_out_addr);
727ff964d8eSMatthias Ringwald }
728ff964d8eSMatthias Ringwald break;
729ff964d8eSMatthias Ringwald case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
730ff964d8eSMatthias Ringwald if (endpoint->bEndpointAddress & 0x80) {
731ff964d8eSMatthias Ringwald if (sco_in_addr) continue;
732ff964d8eSMatthias Ringwald sco_in_addr = endpoint->bEndpointAddress;
733ff964d8eSMatthias Ringwald log_info("-> using 0x%2.2X for SCO Data In", sco_in_addr);
734ff964d8eSMatthias Ringwald } else {
735ff964d8eSMatthias Ringwald if (sco_out_addr) continue;
736ff964d8eSMatthias Ringwald sco_out_addr = endpoint->bEndpointAddress;
737ff964d8eSMatthias Ringwald log_info("-> using 0x%2.2X for SCO Data Out", sco_out_addr);
738ff964d8eSMatthias Ringwald }
739ff964d8eSMatthias Ringwald break;
740ff964d8eSMatthias Ringwald default:
741ff964d8eSMatthias Ringwald break;
742ff964d8eSMatthias Ringwald }
743ff964d8eSMatthias Ringwald }
744ff964d8eSMatthias Ringwald }
745ff964d8eSMatthias Ringwald libusb_free_config_descriptor(config_descriptor);
746696b00c8SMilanka Ringwald return 0;
747ff964d8eSMatthias Ringwald }
748ff964d8eSMatthias Ringwald
7499ea49f80SMatthias Ringwald #ifndef HAVE_USB_VENDOR_ID_AND_PRODUCT_ID
7509ea49f80SMatthias Ringwald
7519ea49f80SMatthias Ringwald // list of known devices, using VendorID/ProductID tuples
7529ea49f80SMatthias Ringwald static const uint16_t known_bluetooth_devices[] = {
7539ea49f80SMatthias Ringwald // BCM20702A0 - DeLOCK Bluetooth 4.0
7549ea49f80SMatthias Ringwald 0x0a5c, 0x21e8,
7559ea49f80SMatthias Ringwald // BCM20702A0 - Asus BT400
7569ea49f80SMatthias Ringwald 0x0b05, 0x17cb,
7579ea49f80SMatthias Ringwald // BCM20702B0 - Generic USB Detuned Class 1 @ 20 MHz
7589ea49f80SMatthias Ringwald 0x0a5c, 0x22be,
7599ea49f80SMatthias Ringwald // nRF5x Zephyr USB HCI, e.g nRF52840-PCA10056
7609ea49f80SMatthias Ringwald 0x2fe3, 0x0100,
7619ea49f80SMatthias Ringwald 0x2fe3, 0x000b,
7629ea49f80SMatthias Ringwald };
7639ea49f80SMatthias Ringwald
7649ea49f80SMatthias Ringwald static int num_known_devices = sizeof(known_bluetooth_devices) / sizeof(uint16_t) / 2;
7659ea49f80SMatthias Ringwald
is_known_bt_device(uint16_t vendor_id,uint16_t product_id)7669ea49f80SMatthias Ringwald static int is_known_bt_device(uint16_t vendor_id, uint16_t product_id){
7679ea49f80SMatthias Ringwald int i;
7689ea49f80SMatthias Ringwald for (i=0; i<num_known_devices; i++){
7699ea49f80SMatthias Ringwald if (known_bluetooth_devices[i*2] == vendor_id && known_bluetooth_devices[i*2+1] == product_id){
7709ea49f80SMatthias Ringwald return 1;
7719ea49f80SMatthias Ringwald }
7729ea49f80SMatthias Ringwald }
77362ec5f72SMatthias Ringwald btstack_linked_list_iterator_t it;
77462ec5f72SMatthias Ringwald btstack_linked_list_iterator_init(&it, &usb_knwon_devices);
77562ec5f72SMatthias Ringwald while (btstack_linked_list_iterator_has_next(&it)) {
77662ec5f72SMatthias Ringwald usb_known_device_t * device = (usb_known_device_t *) btstack_linked_list_iterator_next(&it);
77762ec5f72SMatthias Ringwald if (device->vendor_id != vendor_id) continue;
77862ec5f72SMatthias Ringwald if (device->product_id != product_id) continue;
77962ec5f72SMatthias Ringwald return 1;
78062ec5f72SMatthias Ringwald }
7819ea49f80SMatthias Ringwald return 0;
7829ea49f80SMatthias Ringwald }
7839ea49f80SMatthias Ringwald
784ff964d8eSMatthias Ringwald // returns index of found device or -1
scan_for_bt_device(libusb_device ** devs,int start_index)785ff964d8eSMatthias Ringwald static int scan_for_bt_device(libusb_device **devs, int start_index) {
786ff964d8eSMatthias Ringwald int i;
787ff964d8eSMatthias Ringwald for (i = start_index; devs[i] ; i++){
788696b00c8SMilanka Ringwald libusb_device * dev = devs[i];
789ff964d8eSMatthias Ringwald int r = libusb_get_device_descriptor(dev, &desc);
790ff964d8eSMatthias Ringwald if (r < 0) {
791ff964d8eSMatthias Ringwald log_error("failed to get device descriptor");
792ff964d8eSMatthias Ringwald return 0;
793ff964d8eSMatthias Ringwald }
794ff964d8eSMatthias Ringwald
795ff964d8eSMatthias Ringwald log_info("%04x:%04x (bus %d, device %d) - class %x subclass %x protocol %x ",
796ff964d8eSMatthias Ringwald desc.idVendor, desc.idProduct,
797ff964d8eSMatthias Ringwald libusb_get_bus_number(dev), libusb_get_device_address(dev),
798ff964d8eSMatthias Ringwald desc.bDeviceClass, desc.bDeviceSubClass, desc.bDeviceProtocol);
799ff964d8eSMatthias Ringwald
800ff964d8eSMatthias Ringwald // Detect USB Dongle based Class, Subclass, and Protocol
801ff964d8eSMatthias Ringwald // The class code (bDeviceClass) is 0xE0 – Wireless Controller.
802ff964d8eSMatthias Ringwald // The SubClass code (bDeviceSubClass) is 0x01 – RF Controller.
803ff964d8eSMatthias Ringwald // The Protocol code (bDeviceProtocol) is 0x01 – Bluetooth programming.
804ff964d8eSMatthias Ringwald if (desc.bDeviceClass == 0xE0 && desc.bDeviceSubClass == 0x01 && desc.bDeviceProtocol == 0x01) {
805ff964d8eSMatthias Ringwald return i;
806ff964d8eSMatthias Ringwald }
807ff964d8eSMatthias Ringwald
808ff964d8eSMatthias Ringwald // Detect USB Dongle based on whitelist
809ff964d8eSMatthias Ringwald if (is_known_bt_device(desc.idVendor, desc.idProduct)) {
810ff964d8eSMatthias Ringwald return i;
811ff964d8eSMatthias Ringwald }
812ff964d8eSMatthias Ringwald }
813ff964d8eSMatthias Ringwald return -1;
814ff964d8eSMatthias Ringwald }
815ff964d8eSMatthias Ringwald #endif
816ff964d8eSMatthias Ringwald
prepare_device(libusb_device_handle * aHandle)817ff964d8eSMatthias Ringwald static int prepare_device(libusb_device_handle * aHandle){
818ff964d8eSMatthias Ringwald
819a64cbea7SMatthias Ringwald // get device path
820ff964d8eSMatthias Ringwald libusb_device * device = libusb_get_device(aHandle);
821a64cbea7SMatthias Ringwald usb_path_len = libusb_get_port_numbers(device, usb_path, USB_MAX_PATH_LEN);
822a64cbea7SMatthias Ringwald
823ff964d8eSMatthias Ringwald int r;
824ff964d8eSMatthias Ringwald int kernel_driver_detached = 0;
825ff964d8eSMatthias Ringwald
8267a6e2d5aSMatthias Ringwald // Detach OS driver (not possible for OS X, FreeBSD, and Windows)
8277a6e2d5aSMatthias Ringwald #if !defined(__APPLE__) && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(__FreeBSD__)
828ff964d8eSMatthias Ringwald r = libusb_kernel_driver_active(aHandle, 0);
829ff964d8eSMatthias Ringwald if (r < 0) {
830ff964d8eSMatthias Ringwald log_error("libusb_kernel_driver_active error %d", r);
831ff964d8eSMatthias Ringwald libusb_close(aHandle);
832ff964d8eSMatthias Ringwald return r;
833ff964d8eSMatthias Ringwald }
834ff964d8eSMatthias Ringwald
835ff964d8eSMatthias Ringwald if (r == 1) {
836ff964d8eSMatthias Ringwald r = libusb_detach_kernel_driver(aHandle, 0);
837ff964d8eSMatthias Ringwald if (r < 0) {
838ff964d8eSMatthias Ringwald log_error("libusb_detach_kernel_driver error %d", r);
839ff964d8eSMatthias Ringwald libusb_close(aHandle);
840ff964d8eSMatthias Ringwald return r;
841ff964d8eSMatthias Ringwald }
842ff964d8eSMatthias Ringwald kernel_driver_detached = 1;
843ff964d8eSMatthias Ringwald }
844ff964d8eSMatthias Ringwald log_info("libusb_detach_kernel_driver");
845ff964d8eSMatthias Ringwald #endif
846ff964d8eSMatthias Ringwald
847ff964d8eSMatthias Ringwald const int configuration = 1;
848ff964d8eSMatthias Ringwald log_info("setting configuration %d...", configuration);
849ff964d8eSMatthias Ringwald r = libusb_set_configuration(aHandle, configuration);
850ff964d8eSMatthias Ringwald if (r < 0) {
851ff964d8eSMatthias Ringwald log_error("Error libusb_set_configuration: %d", r);
852ff964d8eSMatthias Ringwald if (kernel_driver_detached){
853ff964d8eSMatthias Ringwald libusb_attach_kernel_driver(aHandle, 0);
854ff964d8eSMatthias Ringwald }
855ff964d8eSMatthias Ringwald libusb_close(aHandle);
856ff964d8eSMatthias Ringwald return r;
857ff964d8eSMatthias Ringwald }
858ff964d8eSMatthias Ringwald
859ff964d8eSMatthias Ringwald // reserve access to device
860ff964d8eSMatthias Ringwald log_info("claiming interface 0...");
861ff964d8eSMatthias Ringwald r = libusb_claim_interface(aHandle, 0);
862ff964d8eSMatthias Ringwald if (r < 0) {
8632bdb9b6dSMatthias Ringwald log_error("Error %d claiming interface 0", r);
864ff964d8eSMatthias Ringwald if (kernel_driver_detached){
865ff964d8eSMatthias Ringwald libusb_attach_kernel_driver(aHandle, 0);
866ff964d8eSMatthias Ringwald }
867ff964d8eSMatthias Ringwald libusb_close(aHandle);
868ff964d8eSMatthias Ringwald return r;
869ff964d8eSMatthias Ringwald }
870ff964d8eSMatthias Ringwald
871ff964d8eSMatthias Ringwald #ifdef ENABLE_SCO_OVER_HCI
872f4ab4581SMatthias Ringwald // get endpoints from interface descriptor
873f4ab4581SMatthias Ringwald struct libusb_config_descriptor *config_descriptor;
874f4ab4581SMatthias Ringwald r = libusb_get_active_config_descriptor(device, &config_descriptor);
875f4ab4581SMatthias Ringwald if (r >= 0){
876f4ab4581SMatthias Ringwald int num_interfaces = config_descriptor->bNumInterfaces;
877f4ab4581SMatthias Ringwald if (num_interfaces > 1) {
878ff964d8eSMatthias Ringwald r = libusb_claim_interface(aHandle, 1);
879ff964d8eSMatthias Ringwald if (r < 0) {
8802bdb9b6dSMatthias Ringwald log_error("Error %d claiming interface 1: - disabling SCO over HCI", r);
8812bdb9b6dSMatthias Ringwald } else {
8822bdb9b6dSMatthias Ringwald sco_enabled = 1;
883ff964d8eSMatthias Ringwald }
884f4ab4581SMatthias Ringwald } else {
885f4ab4581SMatthias Ringwald log_info("Device has only on interface, disabling SCO over HCI");
886f4ab4581SMatthias Ringwald }
887f4ab4581SMatthias Ringwald }
888ff964d8eSMatthias Ringwald #endif
889ff964d8eSMatthias Ringwald
890ff964d8eSMatthias Ringwald return 0;
891ff964d8eSMatthias Ringwald }
892ff964d8eSMatthias Ringwald
try_open_device(libusb_device * device)893ff964d8eSMatthias Ringwald static libusb_device_handle * try_open_device(libusb_device * device){
894ff964d8eSMatthias Ringwald int r;
895ff964d8eSMatthias Ringwald
896dd5fa345SMatthias Ringwald r = libusb_get_device_descriptor(device, &desc);
897dd5fa345SMatthias Ringwald if (r < 0) {
898dd5fa345SMatthias Ringwald log_error("libusb_get_device_descriptor failed!");
899dd5fa345SMatthias Ringwald return NULL;
900dd5fa345SMatthias Ringwald }
901dd5fa345SMatthias Ringwald usb_vendor_id = desc.idVendor;
902dd5fa345SMatthias Ringwald usb_product_id = desc.idProduct;
903dd5fa345SMatthias Ringwald
904ff964d8eSMatthias Ringwald libusb_device_handle * dev_handle;
905ff964d8eSMatthias Ringwald r = libusb_open(device, &dev_handle);
906ff964d8eSMatthias Ringwald
907ff964d8eSMatthias Ringwald if (r < 0) {
908ff964d8eSMatthias Ringwald log_error("libusb_open failed!");
909ff964d8eSMatthias Ringwald dev_handle = NULL;
910ff964d8eSMatthias Ringwald return NULL;
911ff964d8eSMatthias Ringwald }
912ff964d8eSMatthias Ringwald
913ff964d8eSMatthias Ringwald log_info("libusb open %d, handle %p", r, dev_handle);
914ff964d8eSMatthias Ringwald
915410cddbeSMatthias Ringwald // reset device (Not currently possible under FreeBSD 11.x/12.x due to usb framework)
916410cddbeSMatthias Ringwald #if !defined(__FreeBSD__)
9176f7dfc69SMatthias Ringwald r = libusb_reset_device(dev_handle);
918ff964d8eSMatthias Ringwald if (r < 0) {
919ff964d8eSMatthias Ringwald log_error("libusb_reset_device failed!");
920ff964d8eSMatthias Ringwald libusb_close(dev_handle);
921ff964d8eSMatthias Ringwald return NULL;
922ff964d8eSMatthias Ringwald }
923410cddbeSMatthias Ringwald #endif
924ff964d8eSMatthias Ringwald return dev_handle;
925ff964d8eSMatthias Ringwald }
926ff964d8eSMatthias Ringwald
927ff964d8eSMatthias Ringwald #ifdef ENABLE_SCO_OVER_HCI
usb_sco_start(void)92856e558dbSMatthias Ringwald static int usb_sco_start(void){
92956e558dbSMatthias Ringwald
93056e558dbSMatthias Ringwald log_info("usb_sco_start");
9315728804aSDirk Helbig if( sco_activated ) {
9325728804aSDirk Helbig log_error("double sco start!");
9335728804aSDirk Helbig return -1;
9345728804aSDirk Helbig }
9355728804aSDirk Helbig sco_activated = true;
93656e558dbSMatthias Ringwald
937ff964d8eSMatthias Ringwald sco_state_machine_init();
93856e558dbSMatthias Ringwald
939c6f9dc91SMatthias Ringwald int alt_setting;
940c6f9dc91SMatthias Ringwald if (sco_voice_setting & 0x0020){
941c6f9dc91SMatthias Ringwald // 16-bit PCM
942c6f9dc91SMatthias Ringwald alt_setting = alt_setting_16_bit[sco_num_connections-1];
943c6f9dc91SMatthias Ringwald } else {
944c6f9dc91SMatthias Ringwald // 8-bit PCM or mSBC
945c6f9dc91SMatthias Ringwald alt_setting = alt_setting_8_bit[sco_num_connections-1];
946c6f9dc91SMatthias Ringwald }
947f64229a0SMatthias Ringwald // derive iso packet size from alt setting
948f64229a0SMatthias Ringwald iso_packet_size = iso_packet_size_for_alt_setting[alt_setting];
949c6f9dc91SMatthias Ringwald
950c6f9dc91SMatthias Ringwald log_info("Switching to setting %u on interface 1..", alt_setting);
951c6f9dc91SMatthias Ringwald int r = libusb_set_interface_alt_setting(handle, 1, alt_setting);
9522117d3a5SMatthias Ringwald if (r < 0) {
953c6f9dc91SMatthias Ringwald log_error("Error setting alternative setting %u for interface 1: %s\n", alt_setting, libusb_error_name(r));
9542117d3a5SMatthias Ringwald return r;
9552117d3a5SMatthias Ringwald }
9562117d3a5SMatthias Ringwald
9575728804aSDirk Helbig #ifdef DEBUG
9585728804aSDirk Helbig int in_flight = usb_transfer_list_in_flight( sco_transfer_list );
9595728804aSDirk Helbig // there need to be at least SCO_IN_BUFFER_COUNT packets available to
9605728804aSDirk Helbig // fill them in below
961dd7eda92SDirk Helbig btstack_assert( in_flight <= SCO_OUT_BUFFER_COUNT );
9625728804aSDirk Helbig #endif
9635728804aSDirk Helbig
96456e558dbSMatthias Ringwald // incoming
96556e558dbSMatthias Ringwald int c;
96656e558dbSMatthias Ringwald for (c = 0 ; c < SCO_IN_BUFFER_COUNT ; c++) {
9673faa160fSDirk Helbig
9683faa160fSDirk Helbig struct libusb_transfer *transfer = usb_transfer_list_acquire( sco_transfer_list );
9693faa160fSDirk Helbig uint8_t *data = transfer->buffer;
9703faa160fSDirk Helbig void *user_data = transfer->user_data;
9713faa160fSDirk Helbig
97256e558dbSMatthias Ringwald // configure sco_in handlers
9733faa160fSDirk Helbig libusb_fill_iso_transfer(transfer, handle, sco_in_addr,
9743faa160fSDirk Helbig data, NUM_ISO_PACKETS * iso_packet_size, NUM_ISO_PACKETS, async_callback, user_data, 0);
9753faa160fSDirk Helbig libusb_set_iso_packet_lengths(transfer, iso_packet_size);
9763faa160fSDirk Helbig r = libusb_submit_transfer(transfer);
97756e558dbSMatthias Ringwald if (r) {
97856e558dbSMatthias Ringwald log_error("Error submitting isochronous in transfer %d", r);
97956e558dbSMatthias Ringwald usb_close();
98056e558dbSMatthias Ringwald return r;
98156e558dbSMatthias Ringwald }
98256e558dbSMatthias Ringwald }
98356e558dbSMatthias Ringwald return 0;
98456e558dbSMatthias Ringwald }
98556e558dbSMatthias Ringwald
usb_sco_stop(void)98656e558dbSMatthias Ringwald static void usb_sco_stop(void){
98756e558dbSMatthias Ringwald
98856e558dbSMatthias Ringwald log_info("usb_sco_stop");
9895728804aSDirk Helbig sco_activated = false;
990e0828146SMatthias Ringwald
9915728804aSDirk Helbig usb_transfer_list_cancel( sco_transfer_list );
99256e558dbSMatthias Ringwald
9932117d3a5SMatthias Ringwald log_info("Switching to setting %u on interface 1..", 0);
9942117d3a5SMatthias Ringwald int r = libusb_set_interface_alt_setting(handle, 1, 0);
9952117d3a5SMatthias Ringwald if (r < 0) {
9962117d3a5SMatthias Ringwald log_error("Error setting alternative setting %u for interface 1: %s", 0, libusb_error_name(r));
9972117d3a5SMatthias Ringwald return;
9982117d3a5SMatthias Ringwald }
9992117d3a5SMatthias Ringwald
10004568b2feSMatthias Ringwald log_info("usb_sco_stop done");
100156e558dbSMatthias Ringwald }
1002ff964d8eSMatthias Ringwald #endif
1003ff964d8eSMatthias Ringwald
10045728804aSDirk Helbig void pollfd_added_cb(int fd, short events, void *user_data);
10055728804aSDirk Helbig void pollfd_remove_cb(int fd, void *user_data);
10065728804aSDirk Helbig
pollfd_added_cb(int fd,short events,void * user_data)10075728804aSDirk Helbig void pollfd_added_cb(int fd, short events, void *user_data) {
10084f0e05eaSMatthias Ringwald UNUSED(fd);
10095728804aSDirk Helbig UNUSED(events);
10105728804aSDirk Helbig UNUSED(user_data);
10115728804aSDirk Helbig log_error("add fd: %d", fd);
1012dd7eda92SDirk Helbig btstack_assert(0);
10133faa160fSDirk Helbig }
10143faa160fSDirk Helbig
pollfd_remove_cb(int fd,void * user_data)10155728804aSDirk Helbig void pollfd_remove_cb(int fd, void *user_data) {
10164f0e05eaSMatthias Ringwald UNUSED(fd);
10175728804aSDirk Helbig UNUSED(user_data);
10185728804aSDirk Helbig log_error("remove fd: %d", fd);
1019dd7eda92SDirk Helbig btstack_assert(0);
10203faa160fSDirk Helbig }
10213faa160fSDirk Helbig
usb_open(void)102256e558dbSMatthias Ringwald static int usb_open(void){
102356e558dbSMatthias Ringwald int r;
102456e558dbSMatthias Ringwald
1025d2b52257SMatthias Ringwald if (usb_transport_open) return 0;
1026d2b52257SMatthias Ringwald
1027ff964d8eSMatthias Ringwald // default endpoint addresses
1028ff964d8eSMatthias Ringwald event_in_addr = 0x81; // EP1, IN interrupt
1029ff964d8eSMatthias Ringwald acl_in_addr = 0x82; // EP2, IN bulk
1030ff964d8eSMatthias Ringwald acl_out_addr = 0x02; // EP2, OUT bulk
1031ff964d8eSMatthias Ringwald sco_in_addr = 0x83; // EP3, IN isochronous
1032ff964d8eSMatthias Ringwald sco_out_addr = 0x03; // EP3, OUT isochronous
1033ff964d8eSMatthias Ringwald
1034ff964d8eSMatthias Ringwald // USB init
1035ff964d8eSMatthias Ringwald r = libusb_init(NULL);
1036ff964d8eSMatthias Ringwald if (r < 0) return -1;
1037ff964d8eSMatthias Ringwald
1038ff964d8eSMatthias Ringwald libusb_state = LIB_USB_OPENED;
1039ff964d8eSMatthias Ringwald
1040ff964d8eSMatthias Ringwald // configure debug level
1041ff964d8eSMatthias Ringwald libusb_set_debug(NULL, LIBUSB_LOG_LEVEL_WARNING);
1042ff964d8eSMatthias Ringwald
1043696b00c8SMilanka Ringwald libusb_device * dev = NULL;
1044696b00c8SMilanka Ringwald
1045ff964d8eSMatthias Ringwald #ifdef HAVE_USB_VENDOR_ID_AND_PRODUCT_ID
1046ff964d8eSMatthias Ringwald
1047ff964d8eSMatthias Ringwald // Use a specified device
1048ff964d8eSMatthias Ringwald log_info("Want vend: %04x, prod: %04x", USB_VENDOR_ID, USB_PRODUCT_ID);
1049ff964d8eSMatthias Ringwald handle = libusb_open_device_with_vid_pid(NULL, USB_VENDOR_ID, USB_PRODUCT_ID);
1050ff964d8eSMatthias Ringwald
1051ff964d8eSMatthias Ringwald if (!handle){
1052ff964d8eSMatthias Ringwald log_error("libusb_open_device_with_vid_pid failed!");
1053ff964d8eSMatthias Ringwald usb_close();
1054ff964d8eSMatthias Ringwald return -1;
1055ff964d8eSMatthias Ringwald }
1056ff964d8eSMatthias Ringwald log_info("libusb open %d, handle %p", r, handle);
1057ff964d8eSMatthias Ringwald
1058ff964d8eSMatthias Ringwald r = prepare_device(handle);
1059ff964d8eSMatthias Ringwald if (r < 0){
1060ff964d8eSMatthias Ringwald usb_close();
1061ff964d8eSMatthias Ringwald return -1;
1062ff964d8eSMatthias Ringwald }
1063ff964d8eSMatthias Ringwald
10649ea49f80SMatthias Ringwald dev = libusb_get_device(handle);
10656fc6dfecSMilanka Ringwald r = scan_for_bt_endpoints(dev);
10666fc6dfecSMilanka Ringwald if (r < 0){
10676fc6dfecSMilanka Ringwald usb_close();
10686fc6dfecSMilanka Ringwald return -1;
10696fc6dfecSMilanka Ringwald }
1070696b00c8SMilanka Ringwald
1071dd5fa345SMatthias Ringwald usb_vendor_id = USB_VENDOR_ID;
1072dd5fa345SMatthias Ringwald usb_product_id = USB_PRODUCT_ID;
1073dd5fa345SMatthias Ringwald
1074ff964d8eSMatthias Ringwald #else
1075ff964d8eSMatthias Ringwald // Scan system for an appropriate devices
1076ff964d8eSMatthias Ringwald libusb_device **devs;
1077ff964d8eSMatthias Ringwald ssize_t num_devices;
1078ff964d8eSMatthias Ringwald
1079ff964d8eSMatthias Ringwald log_info("Scanning for USB Bluetooth device");
1080ff964d8eSMatthias Ringwald num_devices = libusb_get_device_list(NULL, &devs);
1081ff964d8eSMatthias Ringwald if (num_devices < 0) {
1082ff964d8eSMatthias Ringwald usb_close();
1083ff964d8eSMatthias Ringwald return -1;
1084ff964d8eSMatthias Ringwald }
1085ff964d8eSMatthias Ringwald
1086ff964d8eSMatthias Ringwald if (usb_path_len){
1087ff964d8eSMatthias Ringwald int i;
1088ff964d8eSMatthias Ringwald for (i=0;i<num_devices;i++){
1089ff964d8eSMatthias Ringwald uint8_t port_numbers[USB_MAX_PATH_LEN];
1090ff964d8eSMatthias Ringwald int len = libusb_get_port_numbers(devs[i], port_numbers, USB_MAX_PATH_LEN);
1091ff964d8eSMatthias Ringwald if (len != usb_path_len) continue;
1092ff964d8eSMatthias Ringwald if (memcmp(usb_path, port_numbers, len) == 0){
1093ff964d8eSMatthias Ringwald log_info("USB device found at specified path");
1094ff964d8eSMatthias Ringwald handle = try_open_device(devs[i]);
1095ff964d8eSMatthias Ringwald if (!handle) continue;
1096ff964d8eSMatthias Ringwald
1097ff964d8eSMatthias Ringwald r = prepare_device(handle);
10986fc6dfecSMilanka Ringwald if (r < 0) {
10996fc6dfecSMilanka Ringwald handle = NULL;
11006fc6dfecSMilanka Ringwald continue;
11016fc6dfecSMilanka Ringwald }
1102ff964d8eSMatthias Ringwald
1103ff964d8eSMatthias Ringwald dev = devs[i];
11046fc6dfecSMilanka Ringwald r = scan_for_bt_endpoints(dev);
11056fc6dfecSMilanka Ringwald if (r < 0) {
11066fc6dfecSMilanka Ringwald handle = NULL;
11076fc6dfecSMilanka Ringwald continue;
11086fc6dfecSMilanka Ringwald }
11096fc6dfecSMilanka Ringwald
1110ff964d8eSMatthias Ringwald libusb_state = LIB_USB_INTERFACE_CLAIMED;
1111ff964d8eSMatthias Ringwald break;
1112ff964d8eSMatthias Ringwald };
1113ff964d8eSMatthias Ringwald }
1114ff964d8eSMatthias Ringwald if (!handle){
1115ff964d8eSMatthias Ringwald log_error("USB device with given path not found");
1116ff964d8eSMatthias Ringwald return -1;
1117ff964d8eSMatthias Ringwald }
1118ff964d8eSMatthias Ringwald } else {
1119ff964d8eSMatthias Ringwald
1120ff964d8eSMatthias Ringwald int deviceIndex = -1;
1121ff3cc4a5SMatthias Ringwald while (true){
1122ff964d8eSMatthias Ringwald // look for next Bluetooth dongle
1123ff964d8eSMatthias Ringwald deviceIndex = scan_for_bt_device(devs, deviceIndex+1);
1124ff964d8eSMatthias Ringwald if (deviceIndex < 0) break;
1125ff964d8eSMatthias Ringwald
1126ff964d8eSMatthias Ringwald log_info("USB Bluetooth device found, index %u", deviceIndex);
1127ff964d8eSMatthias Ringwald
1128ff964d8eSMatthias Ringwald handle = try_open_device(devs[deviceIndex]);
1129ff964d8eSMatthias Ringwald if (!handle) continue;
1130ff964d8eSMatthias Ringwald
1131ff964d8eSMatthias Ringwald r = prepare_device(handle);
11326fc6dfecSMilanka Ringwald if (r < 0) {
11336fc6dfecSMilanka Ringwald handle = NULL;
11346fc6dfecSMilanka Ringwald continue;
11356fc6dfecSMilanka Ringwald }
1136ff964d8eSMatthias Ringwald
1137ff964d8eSMatthias Ringwald dev = devs[deviceIndex];
11386fc6dfecSMilanka Ringwald r = scan_for_bt_endpoints(dev);
11396fc6dfecSMilanka Ringwald if (r < 0) {
11406fc6dfecSMilanka Ringwald handle = NULL;
11416fc6dfecSMilanka Ringwald continue;
11426fc6dfecSMilanka Ringwald }
11436fc6dfecSMilanka Ringwald
1144ff964d8eSMatthias Ringwald libusb_state = LIB_USB_INTERFACE_CLAIMED;
1145ff964d8eSMatthias Ringwald break;
1146ff964d8eSMatthias Ringwald }
1147ff964d8eSMatthias Ringwald }
1148ff964d8eSMatthias Ringwald
1149ff964d8eSMatthias Ringwald libusb_free_device_list(devs, 1);
1150ff964d8eSMatthias Ringwald
1151ff964d8eSMatthias Ringwald if (handle == 0){
1152ff964d8eSMatthias Ringwald log_error("No USB Bluetooth device found");
1153ff964d8eSMatthias Ringwald return -1;
1154ff964d8eSMatthias Ringwald }
1155ff964d8eSMatthias Ringwald
1156ff964d8eSMatthias Ringwald #endif
1157ff964d8eSMatthias Ringwald
1158ff964d8eSMatthias Ringwald // allocate transfer handlers
1159ff964d8eSMatthias Ringwald int c;
1160ff964d8eSMatthias Ringwald
11613faa160fSDirk Helbig default_transfer_list = usb_transfer_list_alloc(
11623faa160fSDirk Helbig EVENT_OUT_BUFFER_COUNT+EVENT_IN_BUFFER_COUNT+ACL_IN_BUFFER_COUNT,
11633faa160fSDirk Helbig 0,
11643faa160fSDirk Helbig LIBUSB_CONTROL_SETUP_SIZE + HCI_INCOMING_PRE_BUFFER_SIZE + HCI_ACL_BUFFER_SIZE ); // biggest packet ever to expect
11653faa160fSDirk Helbig
11663faa160fSDirk Helbig #ifdef ENABLE_SCO_OVER_HCI
11673faa160fSDirk Helbig sco_transfer_list = usb_transfer_list_alloc(
11683faa160fSDirk Helbig SCO_OUT_BUFFER_COUNT+SCO_IN_BUFFER_COUNT,
11693faa160fSDirk Helbig NUM_ISO_PACKETS,
11703faa160fSDirk Helbig SCO_PACKET_SIZE
11713faa160fSDirk Helbig );
11723faa160fSDirk Helbig #endif
1173ff964d8eSMatthias Ringwald
1174ff964d8eSMatthias Ringwald // TODO check for error
1175ff964d8eSMatthias Ringwald
1176ff964d8eSMatthias Ringwald libusb_state = LIB_USB_TRANSFERS_ALLOCATED;
1177ff964d8eSMatthias Ringwald
1178ee73ad13SMatthias Ringwald for (c = 0 ; c < EVENT_IN_BUFFER_COUNT ; c++) {
11793faa160fSDirk Helbig struct libusb_transfer *transfer = usb_transfer_list_acquire( default_transfer_list );
11803faa160fSDirk Helbig uint8_t *data = transfer->buffer;
11813faa160fSDirk Helbig void *user_data = transfer->user_data;
1182ff964d8eSMatthias Ringwald // configure event_in handlers
11833faa160fSDirk Helbig libusb_fill_interrupt_transfer(transfer, handle, event_in_addr,
11843faa160fSDirk Helbig data, HCI_ACL_BUFFER_SIZE, async_callback, user_data, 0);
11853faa160fSDirk Helbig r = libusb_submit_transfer(transfer);
1186ff964d8eSMatthias Ringwald if (r) {
1187ff964d8eSMatthias Ringwald log_error("Error submitting interrupt transfer %d", r);
1188ff964d8eSMatthias Ringwald usb_close();
1189ff964d8eSMatthias Ringwald return r;
1190ff964d8eSMatthias Ringwald }
1191ee73ad13SMatthias Ringwald }
1192ff964d8eSMatthias Ringwald
1193ee73ad13SMatthias Ringwald for (c = 0 ; c < ACL_IN_BUFFER_COUNT ; c++) {
11943faa160fSDirk Helbig struct libusb_transfer *transfer = usb_transfer_list_acquire( default_transfer_list );
11953faa160fSDirk Helbig usb_transfer_list_entry_t *transfer_meta_data = (usb_transfer_list_entry_t*)transfer->user_data;
11963faa160fSDirk Helbig uint8_t *data = transfer_meta_data->data;
11973faa160fSDirk Helbig void *user_data = transfer->user_data;
1198ff964d8eSMatthias Ringwald // configure acl_in handlers
11993faa160fSDirk Helbig libusb_fill_bulk_transfer(transfer, handle, acl_in_addr,
12003faa160fSDirk Helbig data + HCI_INCOMING_PRE_BUFFER_SIZE, HCI_ACL_BUFFER_SIZE, async_callback, user_data, 0) ;
12013faa160fSDirk Helbig r = libusb_submit_transfer(transfer);
1202ff964d8eSMatthias Ringwald if (r) {
1203ff964d8eSMatthias Ringwald log_error("Error submitting bulk in transfer %d", r);
1204ff964d8eSMatthias Ringwald usb_close();
1205ff964d8eSMatthias Ringwald return r;
1206ff964d8eSMatthias Ringwald }
1207ff964d8eSMatthias Ringwald
1208ff964d8eSMatthias Ringwald }
1209ff964d8eSMatthias Ringwald
1210ff964d8eSMatthias Ringwald // Check for pollfds functionality
1211ff964d8eSMatthias Ringwald doing_pollfds = libusb_pollfds_handle_timeouts(NULL);
12123faa160fSDirk Helbig
12133faa160fSDirk Helbig libusb_set_pollfd_notifiers( NULL, pollfd_added_cb, pollfd_remove_cb, NULL );
1214ff964d8eSMatthias Ringwald
1215ff964d8eSMatthias Ringwald if (doing_pollfds) {
1216ff964d8eSMatthias Ringwald log_info("Async using pollfds:");
1217ff964d8eSMatthias Ringwald
1218ff964d8eSMatthias Ringwald const struct libusb_pollfd ** pollfd = libusb_get_pollfds(NULL);
1219ff964d8eSMatthias Ringwald for (num_pollfds = 0 ; pollfd[num_pollfds] ; num_pollfds++);
1220b0920f25SMilanka Ringwald pollfd_data_sources = (btstack_data_source_t *)malloc(sizeof(btstack_data_source_t) * num_pollfds);
1221ff964d8eSMatthias Ringwald if (!pollfd_data_sources){
1222ff964d8eSMatthias Ringwald log_error("Cannot allocate data sources for pollfds");
1223ff964d8eSMatthias Ringwald usb_close();
1224ff964d8eSMatthias Ringwald return 1;
1225ff964d8eSMatthias Ringwald }
1226c77e7c45SMatthias Ringwald memset(pollfd_data_sources, 0, sizeof(btstack_data_source_t) * num_pollfds);
1227ff964d8eSMatthias Ringwald for (r = 0 ; r < num_pollfds ; r++) {
1228ff964d8eSMatthias Ringwald btstack_data_source_t *ds = &pollfd_data_sources[r];
1229ff964d8eSMatthias Ringwald btstack_run_loop_set_data_source_fd(ds, pollfd[r]->fd);
1230ff964d8eSMatthias Ringwald btstack_run_loop_set_data_source_handler(ds, &usb_process_ds);
12313faa160fSDirk Helbig if( pollfd[r]->events & POLLIN )
1232ff964d8eSMatthias Ringwald btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ);
12333faa160fSDirk Helbig else
12343faa160fSDirk Helbig btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE);
1235ff964d8eSMatthias Ringwald btstack_run_loop_add_data_source(ds);
1236ff964d8eSMatthias Ringwald log_info("%u: %p fd: %u, events %x", r, pollfd[r], pollfd[r]->fd, pollfd[r]->events);
1237ff964d8eSMatthias Ringwald }
12383faa160fSDirk Helbig libusb_free_pollfds(pollfd);
1239ff964d8eSMatthias Ringwald } else {
1240ff964d8eSMatthias Ringwald log_info("Async using timers:");
1241ff964d8eSMatthias Ringwald
1242ff964d8eSMatthias Ringwald usb_timer.process = usb_process_ts;
1243ff964d8eSMatthias Ringwald btstack_run_loop_set_timer(&usb_timer, ASYNC_POLLING_INTERVAL_MS);
1244ff964d8eSMatthias Ringwald btstack_run_loop_add_timer(&usb_timer);
1245ff964d8eSMatthias Ringwald usb_timer_active = 1;
1246ff964d8eSMatthias Ringwald }
1247ff964d8eSMatthias Ringwald
1248d2b52257SMatthias Ringwald usb_transport_open = 1;
1249d2b52257SMatthias Ringwald
1250f85342b4SMatthias Ringwald hci_transport_h2_libusb_emit_usb_info();
1251f85342b4SMatthias Ringwald
12523faa160fSDirk Helbig btstack_data_source_t *ds = &transport_response;
12533faa160fSDirk Helbig btstack_run_loop_set_data_source_handler(ds, &usb_transport_response_ds);
12543faa160fSDirk Helbig btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_POLL);
12553faa160fSDirk Helbig btstack_run_loop_add_data_source(ds);
1256ff964d8eSMatthias Ringwald return 0;
1257ff964d8eSMatthias Ringwald }
1258ff964d8eSMatthias Ringwald
usb_close(void)1259ff964d8eSMatthias Ringwald static int usb_close(void) {
1260d2b52257SMatthias Ringwald if (!usb_transport_open) return 0;
1261d2b52257SMatthias Ringwald
12628644aff0SMatthias Ringwald log_info("usb_close");
12638644aff0SMatthias Ringwald
1264ff964d8eSMatthias Ringwald switch (libusb_state){
1265ff964d8eSMatthias Ringwald case LIB_USB_CLOSED:
1266ff964d8eSMatthias Ringwald break;
1267ff964d8eSMatthias Ringwald
1268ff964d8eSMatthias Ringwald case LIB_USB_TRANSFERS_ALLOCATED:
1269ff964d8eSMatthias Ringwald libusb_state = LIB_USB_INTERFACE_CLAIMED;
1270ff964d8eSMatthias Ringwald
1271ff964d8eSMatthias Ringwald if(usb_timer_active) {
1272ff964d8eSMatthias Ringwald btstack_run_loop_remove_timer(&usb_timer);
1273ff964d8eSMatthias Ringwald usb_timer_active = 0;
1274ff964d8eSMatthias Ringwald }
1275ff964d8eSMatthias Ringwald
1276ff964d8eSMatthias Ringwald if (doing_pollfds){
1277ff964d8eSMatthias Ringwald int r;
1278ff964d8eSMatthias Ringwald for (r = 0 ; r < num_pollfds ; r++) {
1279ff964d8eSMatthias Ringwald btstack_data_source_t *ds = &pollfd_data_sources[r];
1280ff964d8eSMatthias Ringwald btstack_run_loop_remove_data_source(ds);
1281ff964d8eSMatthias Ringwald }
1282ff964d8eSMatthias Ringwald free(pollfd_data_sources);
1283ff964d8eSMatthias Ringwald pollfd_data_sources = NULL;
1284ff964d8eSMatthias Ringwald num_pollfds = 0;
1285ff964d8eSMatthias Ringwald doing_pollfds = 0;
1286ff964d8eSMatthias Ringwald }
1287ff964d8eSMatthias Ringwald
1288a8d51f09SMatthias Ringwald /* fall through */
1289a8d51f09SMatthias Ringwald
1290ff964d8eSMatthias Ringwald case LIB_USB_INTERFACE_CLAIMED:
12913faa160fSDirk Helbig libusb_set_pollfd_notifiers( NULL, NULL, NULL, NULL );
12923faa160fSDirk Helbig usb_transfer_list_cancel( default_transfer_list );
1293ff964d8eSMatthias Ringwald #ifdef ENABLE_SCO_OVER_HCI
12943faa160fSDirk Helbig usb_transfer_list_cancel( sco_transfer_list );
1295ff964d8eSMatthias Ringwald #endif
1296ff964d8eSMatthias Ringwald
12973faa160fSDirk Helbig int in_flight_transfers = usb_transfer_list_in_flight( default_transfer_list );
12983faa160fSDirk Helbig #ifdef ENABLE_SCO_OVER_HCI
12993faa160fSDirk Helbig in_flight_transfers += usb_transfer_list_in_flight( sco_transfer_list );
13003faa160fSDirk Helbig #endif
13013faa160fSDirk Helbig while( in_flight_transfers > 0 ) {
13023faa160fSDirk Helbig struct timeval tv = { 0 };
13031b2aa976SMatthias Ringwald libusb_handle_events_timeout(NULL, &tv);
1304ee73ad13SMatthias Ringwald
13053faa160fSDirk Helbig in_flight_transfers = usb_transfer_list_in_flight( default_transfer_list );
13061b2aa976SMatthias Ringwald #ifdef ENABLE_SCO_OVER_HCI
13073faa160fSDirk Helbig in_flight_transfers += usb_transfer_list_in_flight( sco_transfer_list );
13081b2aa976SMatthias Ringwald #endif
13091b2aa976SMatthias Ringwald }
13101b2aa976SMatthias Ringwald
13113faa160fSDirk Helbig usb_transfer_list_free( default_transfer_list );
13123faa160fSDirk Helbig #ifdef ENABLE_SCO_OVER_HCI
13133faa160fSDirk Helbig usb_transfer_list_free( sco_transfer_list );
13143faa160fSDirk Helbig sco_enabled = 0;
13155728804aSDirk Helbig #endif
13163faa160fSDirk Helbig
13171b2aa976SMatthias Ringwald // finally release interface
1318ff964d8eSMatthias Ringwald libusb_release_interface(handle, 0);
13191b2aa976SMatthias Ringwald #ifdef ENABLE_SCO_OVER_HCI
13201b2aa976SMatthias Ringwald libusb_release_interface(handle, 1);
13211b2aa976SMatthias Ringwald #endif
1322a09e374cSJoep Moritz log_info("Libusb shutdown complete");
1323ff964d8eSMatthias Ringwald
1324a8d51f09SMatthias Ringwald /* fall through */
1325a8d51f09SMatthias Ringwald
1326ff964d8eSMatthias Ringwald case LIB_USB_DEVICE_OPENDED:
1327ff964d8eSMatthias Ringwald libusb_close(handle);
1328ff964d8eSMatthias Ringwald
1329a8d51f09SMatthias Ringwald /* fall through */
1330a8d51f09SMatthias Ringwald
1331ff964d8eSMatthias Ringwald case LIB_USB_OPENED:
1332ff964d8eSMatthias Ringwald libusb_exit(NULL);
1333a8d51f09SMatthias Ringwald break;
1334a8d51f09SMatthias Ringwald
1335a8d51f09SMatthias Ringwald default:
1336a8d51f09SMatthias Ringwald btstack_assert(false);
1337a8d51f09SMatthias Ringwald break;
1338ff964d8eSMatthias Ringwald }
1339ff964d8eSMatthias Ringwald
1340ff964d8eSMatthias Ringwald libusb_state = LIB_USB_CLOSED;
1341ff964d8eSMatthias Ringwald handle = NULL;
1342d2b52257SMatthias Ringwald usb_transport_open = 0;
1343ff964d8eSMatthias Ringwald
1344ff964d8eSMatthias Ringwald return 0;
1345ff964d8eSMatthias Ringwald }
1346ff964d8eSMatthias Ringwald
13473faa160fSDirk Helbig static int acknowledge_count = 0;
signal_acknowledge(void)13482eaf98e7SMatthias Ringwald static void signal_acknowledge(void) {
13493faa160fSDirk Helbig ++acknowledge_count;
13503faa160fSDirk Helbig btstack_run_loop_poll_data_sources_from_irq();
13513faa160fSDirk Helbig }
13523faa160fSDirk Helbig
13537d6cb61eSMatthias Ringwald #ifdef ENABLE_SCO_OVER_HCI
13543faa160fSDirk Helbig static int sco_can_send_now_count = 0;
signal_sco_can_send_now(void)13552eaf98e7SMatthias Ringwald static void signal_sco_can_send_now(void) {
13563faa160fSDirk Helbig ++sco_can_send_now_count;
13573faa160fSDirk Helbig btstack_run_loop_poll_data_sources_from_irq();
13583faa160fSDirk Helbig }
13597d6cb61eSMatthias Ringwald #endif
13603faa160fSDirk Helbig
usb_transport_response_ds(btstack_data_source_t * ds,btstack_data_source_callback_type_t callback_type)13613faa160fSDirk Helbig static void usb_transport_response_ds(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type) {
13623faa160fSDirk Helbig UNUSED(ds);
13633faa160fSDirk Helbig UNUSED(callback_type);
13643faa160fSDirk Helbig for(; acknowledge_count>0; --acknowledge_count) {
13653faa160fSDirk Helbig static const uint8_t event[] = { HCI_EVENT_TRANSPORT_PACKET_SENT, 0 };
13665728804aSDirk Helbig packet_handler(HCI_EVENT_PACKET, (uint8_t*)&event[0], sizeof(event));
13673faa160fSDirk Helbig }
13683faa160fSDirk Helbig
13697d6cb61eSMatthias Ringwald #ifdef ENABLE_SCO_OVER_HCI
13703faa160fSDirk Helbig for(; sco_can_send_now_count>0; --sco_can_send_now_count) {
13713faa160fSDirk Helbig static const uint8_t event[] = { HCI_EVENT_SCO_CAN_SEND_NOW, 0 };
13725728804aSDirk Helbig packet_handler(HCI_EVENT_PACKET, (uint8_t*)&event[0], sizeof(event));
13733faa160fSDirk Helbig }
13747d6cb61eSMatthias Ringwald #endif
13753faa160fSDirk Helbig
13763faa160fSDirk Helbig }
13773faa160fSDirk Helbig
usb_send_cmd_packet(uint8_t * packet,int size)1378ff964d8eSMatthias Ringwald static int usb_send_cmd_packet(uint8_t *packet, int size){
1379ff964d8eSMatthias Ringwald int r;
1380ff964d8eSMatthias Ringwald
1381ff964d8eSMatthias Ringwald if (libusb_state != LIB_USB_TRANSFERS_ALLOCATED) return -1;
13823faa160fSDirk Helbig // printf("%s( %p, %d )\n", __FUNCTION__, packet, size );
13833faa160fSDirk Helbig
13843faa160fSDirk Helbig struct libusb_transfer *transfer = usb_transfer_list_acquire( default_transfer_list );
13853faa160fSDirk Helbig uint8_t *data = transfer->buffer;
13863faa160fSDirk Helbig void *user_data = transfer->user_data;
1387ff964d8eSMatthias Ringwald
1388ff964d8eSMatthias Ringwald // async
13893faa160fSDirk Helbig libusb_fill_control_setup(data, LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, 0, 0, 0, size);
13903faa160fSDirk Helbig memcpy(data + LIBUSB_CONTROL_SETUP_SIZE, packet, size);
1391ff964d8eSMatthias Ringwald
1392ff964d8eSMatthias Ringwald // prepare transfer
13933faa160fSDirk Helbig libusb_fill_control_transfer(transfer, handle, data, async_callback, user_data, 0);
1394ff964d8eSMatthias Ringwald
1395ff964d8eSMatthias Ringwald // submit transfer
13963faa160fSDirk Helbig r = libusb_submit_transfer(transfer);
1397ff964d8eSMatthias Ringwald
1398ff964d8eSMatthias Ringwald if (r < 0) {
1399ff964d8eSMatthias Ringwald log_error("Error submitting cmd transfer %d", r);
1400ff964d8eSMatthias Ringwald return -1;
1401ff964d8eSMatthias Ringwald }
1402ff964d8eSMatthias Ringwald
14033faa160fSDirk Helbig signal_acknowledge();
14043faa160fSDirk Helbig
1405ff964d8eSMatthias Ringwald return 0;
1406ff964d8eSMatthias Ringwald }
1407ff964d8eSMatthias Ringwald
usb_send_acl_packet(uint8_t * packet,int size)1408ff964d8eSMatthias Ringwald static int usb_send_acl_packet(uint8_t *packet, int size){
1409ff964d8eSMatthias Ringwald int r;
1410ff964d8eSMatthias Ringwald
1411ff964d8eSMatthias Ringwald if (libusb_state != LIB_USB_TRANSFERS_ALLOCATED) return -1;
14123faa160fSDirk Helbig // printf("%s( %p, %d )\n", __FUNCTION__, packet, size );
1413ff964d8eSMatthias Ringwald // log_info("usb_send_acl_packet enter, size %u", size);
1414ff964d8eSMatthias Ringwald
14153faa160fSDirk Helbig struct libusb_transfer *transfer = usb_transfer_list_acquire( default_transfer_list );
14163faa160fSDirk Helbig uint8_t *data = transfer->buffer;
14173faa160fSDirk Helbig
1418ff964d8eSMatthias Ringwald // prepare transfer
14193faa160fSDirk Helbig memcpy( data, packet, size );
14203faa160fSDirk Helbig libusb_fill_bulk_transfer(transfer, handle, acl_out_addr, data, size,
14213faa160fSDirk Helbig async_callback, transfer->user_data, 0);
1422ff964d8eSMatthias Ringwald
14233faa160fSDirk Helbig r = libusb_submit_transfer(transfer);
1424ff964d8eSMatthias Ringwald
1425ff964d8eSMatthias Ringwald if (r < 0) {
1426ff964d8eSMatthias Ringwald log_error("Error submitting acl transfer, %d", r);
1427ff964d8eSMatthias Ringwald return -1;
1428ff964d8eSMatthias Ringwald }
1429ff964d8eSMatthias Ringwald
14303faa160fSDirk Helbig signal_acknowledge();
14313faa160fSDirk Helbig
1432ff964d8eSMatthias Ringwald return 0;
1433ff964d8eSMatthias Ringwald }
1434ff964d8eSMatthias Ringwald
usb_can_send_packet_now(uint8_t packet_type)1435ff964d8eSMatthias Ringwald static int usb_can_send_packet_now(uint8_t packet_type){
1436ff964d8eSMatthias Ringwald switch (packet_type){
14373faa160fSDirk Helbig case HCI_COMMAND_DATA_PACKET: {
14383faa160fSDirk Helbig int ret = !usb_transfer_list_empty( default_transfer_list );
14395728804aSDirk Helbig if( !ret ) {
14405728804aSDirk Helbig log_error("command transfers shouldn't be empty!");
14415728804aSDirk Helbig }
14423faa160fSDirk Helbig return ret;
14433faa160fSDirk Helbig }
14443faa160fSDirk Helbig case HCI_ACL_DATA_PACKET: {
14453faa160fSDirk Helbig int ret = !usb_transfer_list_empty( default_transfer_list );
14465728804aSDirk Helbig if( !ret ) {
14475728804aSDirk Helbig log_error("acl transfers shouldn't be empty!");
14485728804aSDirk Helbig }
14493faa160fSDirk Helbig return ret;
14503faa160fSDirk Helbig }
14513faa160fSDirk Helbig
1452ff964d8eSMatthias Ringwald #ifdef ENABLE_SCO_OVER_HCI
14533faa160fSDirk Helbig case HCI_SCO_DATA_PACKET: {
14545728804aSDirk Helbig if (!sco_enabled || !sco_activated) return 0;
14553faa160fSDirk Helbig int ret = !usb_transfer_list_empty( sco_transfer_list );
14565728804aSDirk Helbig if( !ret ) {
14575728804aSDirk Helbig log_error("sco transfers shouldn't be empty!");
14585728804aSDirk Helbig }
14593faa160fSDirk Helbig return ret;
14603faa160fSDirk Helbig }
1461ff964d8eSMatthias Ringwald #endif
1462ff964d8eSMatthias Ringwald default:
1463ff964d8eSMatthias Ringwald return 0;
1464ff964d8eSMatthias Ringwald }
1465ff964d8eSMatthias Ringwald }
1466ff964d8eSMatthias Ringwald
usb_send_packet(uint8_t packet_type,uint8_t * packet,int size)1467ff964d8eSMatthias Ringwald static int usb_send_packet(uint8_t packet_type, uint8_t * packet, int size){
1468ff964d8eSMatthias Ringwald switch (packet_type){
1469ff964d8eSMatthias Ringwald case HCI_COMMAND_DATA_PACKET:
1470ff964d8eSMatthias Ringwald return usb_send_cmd_packet(packet, size);
1471*dd1620d3SMatthias Ringwald #ifdef ENABLE_LE_ISOCHRONOUS_STREAMS
1472*dd1620d3SMatthias Ringwald case HCI_ISO_DATA_PACKET:
1473*dd1620d3SMatthias Ringwald #endif
1474ff964d8eSMatthias Ringwald case HCI_ACL_DATA_PACKET:
1475ff964d8eSMatthias Ringwald return usb_send_acl_packet(packet, size);
1476ff964d8eSMatthias Ringwald #ifdef ENABLE_SCO_OVER_HCI
1477ff964d8eSMatthias Ringwald case HCI_SCO_DATA_PACKET:
14782bdb9b6dSMatthias Ringwald if (!sco_enabled) return -1;
1479ff964d8eSMatthias Ringwald return usb_send_sco_packet(packet, size);
1480ff964d8eSMatthias Ringwald #endif
1481ff964d8eSMatthias Ringwald default:
1482348725beSMatthias Ringwald btstack_assert(false);
1483ff964d8eSMatthias Ringwald return -1;
1484ff964d8eSMatthias Ringwald }
1485ff964d8eSMatthias Ringwald }
1486ff964d8eSMatthias Ringwald
148756e558dbSMatthias Ringwald #ifdef ENABLE_SCO_OVER_HCI
usb_set_sco_config(uint16_t voice_setting,int num_connections)1488ee752bb8SMatthias Ringwald static void usb_set_sco_config(uint16_t voice_setting, int num_connections){
14892bdb9b6dSMatthias Ringwald if (!sco_enabled) return;
14902bdb9b6dSMatthias Ringwald
1491c6f9dc91SMatthias Ringwald log_info("usb_set_sco_config: voice settings 0x%04x, num connections %u", voice_setting, num_connections);
149256e558dbSMatthias Ringwald
149356e558dbSMatthias Ringwald if (num_connections != sco_num_connections){
149456e558dbSMatthias Ringwald sco_voice_setting = voice_setting;
149556e558dbSMatthias Ringwald if (sco_num_connections){
149656e558dbSMatthias Ringwald usb_sco_stop();
1497ee752bb8SMatthias Ringwald }
1498c6f9dc91SMatthias Ringwald sco_num_connections = num_connections;
149956e558dbSMatthias Ringwald if (num_connections){
150056e558dbSMatthias Ringwald usb_sco_start();
150156e558dbSMatthias Ringwald }
150256e558dbSMatthias Ringwald }
150356e558dbSMatthias Ringwald }
150456e558dbSMatthias Ringwald #endif
1505ee752bb8SMatthias Ringwald
usb_register_packet_handler(void (* handler)(uint8_t packet_type,uint8_t * packet,uint16_t size))1506ff964d8eSMatthias Ringwald static void usb_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)){
1507ff964d8eSMatthias Ringwald log_info("registering packet handler");
1508ff964d8eSMatthias Ringwald packet_handler = handler;
1509ff964d8eSMatthias Ringwald }
1510ff964d8eSMatthias Ringwald
dummy_handler(uint8_t packet_type,uint8_t * packet,uint16_t size)1511ff964d8eSMatthias Ringwald static void dummy_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){
15129ec2630cSMatthias Ringwald UNUSED(packet_type);
15139ec2630cSMatthias Ringwald UNUSED(packet);
15149ec2630cSMatthias Ringwald UNUSED(size);
1515ff964d8eSMatthias Ringwald }
1516ff964d8eSMatthias Ringwald
1517ff964d8eSMatthias Ringwald // get usb singleton
hci_transport_usb_instance(void)1518ff964d8eSMatthias Ringwald const hci_transport_t * hci_transport_usb_instance(void) {
1519ff964d8eSMatthias Ringwald if (!hci_transport_usb) {
1520ff964d8eSMatthias Ringwald hci_transport_usb = (hci_transport_t*) malloc( sizeof(hci_transport_t));
1521ff964d8eSMatthias Ringwald memset(hci_transport_usb, 0, sizeof(hci_transport_t));
1522ff964d8eSMatthias Ringwald hci_transport_usb->name = "H2_LIBUSB";
1523ff964d8eSMatthias Ringwald hci_transport_usb->open = usb_open;
1524ff964d8eSMatthias Ringwald hci_transport_usb->close = usb_close;
1525ff964d8eSMatthias Ringwald hci_transport_usb->register_packet_handler = usb_register_packet_handler;
1526ff964d8eSMatthias Ringwald hci_transport_usb->can_send_packet_now = usb_can_send_packet_now;
1527ff964d8eSMatthias Ringwald hci_transport_usb->send_packet = usb_send_packet;
152856e558dbSMatthias Ringwald #ifdef ENABLE_SCO_OVER_HCI
1529ee752bb8SMatthias Ringwald hci_transport_usb->set_sco_config = usb_set_sco_config;
153056e558dbSMatthias Ringwald #endif
1531ff964d8eSMatthias Ringwald }
1532ff964d8eSMatthias Ringwald return hci_transport_usb;
1533ff964d8eSMatthias Ringwald }
1534