diff --git a/platform/libusb/hci_transport_h2_libusb.c b/platform/libusb/hci_transport_h2_libusb.c index e68db7946..64e3f5395 100644 --- a/platform/libusb/hci_transport_h2_libusb.c +++ b/platform/libusb/hci_transport_h2_libusb.c @@ -74,6 +74,8 @@ #include "hci_transport.h" #include "hci_transport_usb.h" +#define DEBUG + // deal with changes in libusb API: #ifdef LIBUSB_API_VERSION #if LIBUSB_API_VERSION >= 0x01000106 @@ -131,7 +133,7 @@ static const uint16_t iso_packet_size_for_alt_setting[] = { // Outgoing SCO packet queue // simplified ring buffer implementation -#define SCO_OUT_BUFFER_COUNT (8) +#define SCO_OUT_BUFFER_COUNT (20) #define SCO_OUT_BUFFER_SIZE (SCO_OUT_BUFFER_COUNT * SCO_PACKET_SIZE) // seems to be the max depth for USB 3 @@ -168,10 +170,6 @@ static struct libusb_device_descriptor desc; #endif static libusb_device_handle * handle; -//static struct libusb_transfer *acl_out_transfer; -//static struct libusb_transfer *event_in_transfer[EVENT_IN_BUFFER_COUNT]; -//static struct libusb_transfer *acl_in_transfer[ACL_IN_BUFFER_COUNT]; - // known devices typedef struct { btstack_linked_item_t next; @@ -245,6 +243,7 @@ static struct libusb_transfer *usb_transfer_list_acquire( usb_transfer_list_t *l current->in_flight = true; return transfer; } +void usb_transfer_list_free( usb_transfer_list_t *list ); static void usb_transfer_list_release( usb_transfer_list_t *list, struct libusb_transfer *transfer ) { usb_transfer_list_entry_t *current = (usb_transfer_list_entry_t*)transfer->user_data; @@ -267,7 +266,6 @@ static usb_transfer_list_t *usb_transfer_list_alloc( int nbr, int iso_packets, i struct libusb_transfer *transfer = libusb_alloc_transfer(iso_packets); entry->data = malloc( length ); transfer->buffer = entry->data; -// transfer->flags = LIBUSB_TRANSFER_FREE_BUFFER; transfer->user_data = entry; entry->t = transfer; usb_transfer_list_release( list, transfer ); @@ -328,17 +326,8 @@ static void enqueue_transfer(struct libusb_transfer *transfer) { list_add_tail( ¤t->list, &handle_packet_list ); } -static void signal_acknowledge(); -static void signal_sco_can_send_now(); - -// outgoing buffer for HCI Command packets -//static uint8_t hci_cmd_buffer[3 + 256 + LIBUSB_CONTROL_SETUP_SIZE]; - -// incoming buffer for HCI Events and ACL Packets -//static uint8_t hci_event_in_buffer[EVENT_IN_BUFFER_COUNT][HCI_ACL_BUFFER_SIZE]; // bigger than largest packet -//static uint8_t hci_acl_in_buffer[ACL_IN_BUFFER_COUNT][HCI_INCOMING_PRE_BUFFER_SIZE + HCI_ACL_BUFFER_SIZE]; - - +static void signal_acknowledge(void); +static void signal_sco_can_send_now(void); #ifdef ENABLE_SCO_OVER_HCI @@ -351,20 +340,11 @@ static H2_SCO_STATE sco_state; static uint8_t sco_buffer[255+3 + SCO_PACKET_SIZE]; static uint16_t sco_read_pos; static uint16_t sco_bytes_to_read; -//static struct libusb_transfer *sco_in_transfer[SCO_IN_BUFFER_COUNT]; -//static uint8_t hci_sco_in_buffer[SCO_IN_BUFFER_COUNT][SCO_PACKET_SIZE]; - -// outgoing SCO -//static uint8_t sco_out_ring_buffer[SCO_OUT_BUFFER_SIZE]; -//static int sco_ring_write; // packet idx -//static int sco_out_transfers_active; -//static struct libusb_transfer *sco_out_transfers[SCO_OUT_BUFFER_COUNT]; -//static int sco_out_transfers_in_flight[SCO_OUT_BUFFER_COUNT]; // pause/resume static uint16_t sco_voice_setting; static int sco_num_connections; -static int sco_shutdown; +static bool sco_activated; // dynamic SCO configuration static uint16_t iso_packet_size; @@ -375,8 +355,6 @@ usb_transfer_list_t *sco_transfer_list = NULL; #endif - - static int doing_pollfds; static int num_pollfds; static btstack_data_source_t * pollfd_data_sources; @@ -436,67 +414,12 @@ void hci_transport_usb_set_path(int len, uint8_t * port_numbers){ memcpy(usb_path, port_numbers, len); } -LIBUSB_CALL static void async_callback(struct libusb_transfer *transfer){ - - int c; - +LIBUSB_CALL static void async_callback(struct libusb_transfer *transfer) { if (libusb_state != LIB_USB_TRANSFERS_ALLOCATED) { log_info("shutdown, transfer %p", transfer); usb_transfer_list_free_entry( transfer ); return; } -#if 0 - - // identify and free transfers as part of shutdown -#ifdef ENABLE_SCO_OVER_HCI - if (libusb_state != LIB_USB_TRANSFERS_ALLOCATED || sco_shutdown) { - for (c=0;cendpoint, transfer->status, transfer->actual_length ); @@ -529,6 +452,11 @@ LIBUSB_CALL static void async_callback(struct libusb_transfer *transfer){ static int usb_send_sco_packet(uint8_t *packet, int size){ int r; + if( !sco_activated ) { + log_error("sco send without beeing active!"); + return -1; + } + if (libusb_state != LIB_USB_TRANSFERS_ALLOCATED) return -1; struct libusb_transfer *transfer = usb_transfer_list_acquire( sco_transfer_list ); @@ -624,7 +552,7 @@ static void handle_completed_transfer(struct libusb_transfer *transfer){ // log_info("handle_completed_transfer for SCO IN! num packets %u", transfer->NUM_ISO_PACKETS); // give the transfer back to the pool, without resubmiting - if( sco_shutdown ) { + if( !sco_activated ) { usb_transfer_list_release( sco_transfer_list, transfer ); return; } @@ -650,7 +578,7 @@ static void handle_completed_transfer(struct libusb_transfer *transfer){ } } usb_transfer_list_release( sco_transfer_list, transfer ); - if( sco_shutdown ) { + if( !sco_activated ) { return; } // log_info("sco out done, {{ %u/%u (%x)}, { %u/%u (%x)}, { %u/%u (%x)}}", @@ -672,7 +600,6 @@ static void handle_completed_transfer(struct libusb_transfer *transfer){ if (resubmit){ // Re-submit transfer -// transfer->user_data = NULL; int r = libusb_submit_transfer(transfer); if (r) { log_error("Error re-submitting transfer %d", r); @@ -680,7 +607,8 @@ static void handle_completed_transfer(struct libusb_transfer *transfer){ } } -void usb_handle_pending_events() { +void usb_handle_pending_events(void); +void usb_handle_pending_events(void) { struct timeval tv = { 0 }; libusb_handle_events_timeout_completed(NULL, &tv, NULL); } @@ -985,6 +913,11 @@ static libusb_device_handle * try_open_device(libusb_device * device){ static int usb_sco_start(void){ log_info("usb_sco_start"); + if( sco_activated ) { + log_error("double sco start!"); + return -1; + } + sco_activated = true; sco_state_machine_init(); @@ -1000,12 +933,19 @@ static int usb_sco_start(void){ iso_packet_size = iso_packet_size_for_alt_setting[alt_setting]; log_info("Switching to setting %u on interface 1..", alt_setting); - int r = libusb_set_interface_alt_setting(handle, 1, alt_setting); + int r = libusb_set_interface_alt_setting(handle, 1, alt_setting); if (r < 0) { log_error("Error setting alternative setting %u for interface 1: %s\n", alt_setting, libusb_error_name(r)); return r; } +#ifdef DEBUG + int in_flight = usb_transfer_list_in_flight( sco_transfer_list ); + // there need to be at least SCO_IN_BUFFER_COUNT packets available to + // fill them in below + assert( in_flight <= SCO_OUT_BUFFER_COUNT ); +#endif + // incoming int c; for (c = 0 ; c < SCO_IN_BUFFER_COUNT ; c++) { @@ -1031,97 +971,12 @@ static int usb_sco_start(void){ static void usb_sco_stop(void){ log_info("usb_sco_stop"); - sco_shutdown = 1; -#if 0 - // Free SCO transfers already in queue - struct libusb_transfer* transfer = handle_packet; - struct libusb_transfer* prev_transfer = NULL; - while (transfer != NULL) { - uint16_t c; - bool drop_transfer = false; - for (c=0;cuser_data; - if (drop_transfer) { - log_info("Drop completed SCO transfer %p", transfer); - if (prev_transfer == NULL) { - // first item - handle_packet = (struct libusb_transfer *) next_transfer; - } else { - // other item - prev_transfer->user_data = (struct libusb_transfer *) next_transfer; - } - libusb_free_transfer(transfer); - } else { - prev_transfer = transfer; - } - transfer = next_transfer; - } + sco_activated = false; - libusb_set_debug(NULL, LIBUSB_LOG_LEVEL_ERROR); + usb_transfer_list_cancel( sco_transfer_list ); - int c; - for (c = 0 ; c < SCO_IN_BUFFER_COUNT ; c++) { - if (sco_in_transfer[c] != NULL) { - libusb_cancel_transfer(sco_in_transfer[c]); - } - } - - for (c = 0; c < SCO_OUT_BUFFER_COUNT ; c++){ - if (sco_out_transfers_in_flight[c]) { - libusb_cancel_transfer(sco_out_transfers[c]); - } else { - if (sco_out_transfers[c] != NULL) { - libusb_free_transfer(sco_out_transfers[c]); - sco_out_transfers[c] = 0; - } - } - } - - // wait until all transfers are completed - int completed = 0; - while (!completed){ - struct timeval tv; - memset(&tv, 0, sizeof(struct timeval)); - libusb_handle_events_timeout_completed(NULL, &tv, NULL); - // check if all done - completed = 1; - - // Cancel all synchronous transfer - for (c = 0 ; c < SCO_IN_BUFFER_COUNT ; c++) { - if (sco_in_transfer[c] != NULL){ - completed = 0; - break; - } - } - - if (!completed) continue; - - for (c=0; c < SCO_OUT_BUFFER_COUNT ; c++){ - if (sco_out_transfers[c] != NULL){ - completed = 0; - break; - } - } - } - sco_shutdown = 0; - libusb_set_debug(NULL, LIBUSB_LOG_LEVEL_WARNING); -#endif log_info("Switching to setting %u on interface 1..", 0); - int r = libusb_set_interface_alt_setting(handle, 1, 0); + int r = libusb_set_interface_alt_setting(handle, 1, 0); if (r < 0) { log_error("Error setting alternative setting %u for interface 1: %s", 0, libusb_error_name(r)); return; @@ -1129,24 +984,24 @@ static void usb_sco_stop(void){ log_info("usb_sco_stop done"); } - - - #endif -void pollfd_added_cb(int fd, short events, void *user_data) -{ - printf("add %d\n", fd); +void pollfd_added_cb(int fd, short events, void *user_data); +void pollfd_remove_cb(int fd, void *user_data); + +void pollfd_added_cb(int fd, short events, void *user_data) { + UNUSED(events); + UNUSED(user_data); + log_error("add fd: %d", fd); assert(0); } -void pollfd_remove_cb(int fd, void *user_data) -{ - printf("remove %d\n", fd); +void pollfd_remove_cb(int fd, void *user_data) { + UNUSED(user_data); + log_error("remove fd: %d", fd); assert(0); } - static int usb_open(void){ int r; @@ -1384,10 +1239,7 @@ static int usb_open(void){ return 0; } -static int usb_close(void){ - int c; - int completed = 0; - +static int usb_close(void) { if (!usb_transport_open) return 0; log_info("usb_close"); @@ -1442,8 +1294,8 @@ static int usb_close(void){ usb_transfer_list_free( default_transfer_list ); #ifdef ENABLE_SCO_OVER_HCI usb_transfer_list_free( sco_transfer_list ); -#endif sco_enabled = 0; +#endif // finally release interface libusb_release_interface(handle, 0); @@ -1493,12 +1345,12 @@ static void usb_transport_response_ds(btstack_data_source_t *ds, btstack_data_so // printf("%s packet sent: %d sco can send now: %d\n", __FUNCTION__, acknowledge_count, sco_can_send_now_count); for(; acknowledge_count>0; --acknowledge_count) { static const uint8_t event[] = { HCI_EVENT_TRANSPORT_PACKET_SENT, 0 }; - packet_handler(HCI_EVENT_PACKET, &event[0], sizeof(event)); + packet_handler(HCI_EVENT_PACKET, (uint8_t*)&event[0], sizeof(event)); } for(; sco_can_send_now_count>0; --sco_can_send_now_count) { static const uint8_t event[] = { HCI_EVENT_SCO_CAN_SEND_NOW, 0 }; - packet_handler(HCI_EVENT_PACKET, &event[0], sizeof(event)); + packet_handler(HCI_EVENT_PACKET, (uint8_t*)&event[0], sizeof(event)); } } @@ -1566,22 +1418,26 @@ static int usb_can_send_packet_now(uint8_t packet_type){ switch (packet_type){ case HCI_COMMAND_DATA_PACKET: { int ret = !usb_transfer_list_empty( default_transfer_list ); - btstack_assert( ret == 1 ); -// printf("can send now: %d\n", ret ); + if( !ret ) { + log_error("command transfers shouldn't be empty!"); + } return ret; } case HCI_ACL_DATA_PACKET: { int ret = !usb_transfer_list_empty( default_transfer_list ); - btstack_assert( ret == 1 ); -// printf("can send now: %d\n", ret ); + if( !ret ) { + log_error("acl transfers shouldn't be empty!"); + } return ret; } #ifdef ENABLE_SCO_OVER_HCI case HCI_SCO_DATA_PACKET: { -// printf("%s sco\n", __FUNCTION__); - if (!sco_enabled) return 0; + if (!sco_enabled || !sco_activated) return 0; int ret = !usb_transfer_list_empty( sco_transfer_list ); + if( !ret ) { + log_error("sco transfers shouldn't be empty!"); + } return ret; } #endif