libusb: streamline names for different packet types and transfers

This commit is contained in:
Matthias Ringwald 2017-01-11 10:21:07 +01:00
parent 01f6d60c42
commit ee73ad13c7

View File

@ -69,8 +69,9 @@
#define HAVE_USB_VENDOR_ID_AND_PRODUCT_ID #define HAVE_USB_VENDOR_ID_AND_PRODUCT_ID
#endif #endif
#define ASYNC_BUFFERS 3 #define ACL_IN_BUFFER_COUNT 3
#define ISOC_BUFFERS 10 #define EVENT_IN_BUFFER_COUNT 3
#define SCO_IN_BUFFER_COUNT 10
#define ASYNC_POLLING_INTERVAL_MS 1 #define ASYNC_POLLING_INTERVAL_MS 1
@ -98,8 +99,8 @@
// Outgoing SCO packet queue // Outgoing SCO packet queue
// simplified ring buffer implementation // simplified ring buffer implementation
#define SCO_RING_BUFFER_COUNT (8) #define SCO_OUT_BUFFER_COUNT (8)
#define SCO_RING_BUFFER_SIZE (SCO_RING_BUFFER_COUNT * SCO_PACKET_SIZE) #define SCO_OUT_BUFFER_SIZE (SCO_OUT_BUFFER_COUNT * SCO_PACKET_SIZE)
// seems to be the max depth for USB 3 // seems to be the max depth for USB 3
#define USB_MAX_PATH_LEN 7 #define USB_MAX_PATH_LEN 7
@ -138,8 +139,8 @@ static libusb_device_handle * handle;
static struct libusb_transfer *command_out_transfer; static struct libusb_transfer *command_out_transfer;
static struct libusb_transfer *acl_out_transfer; static struct libusb_transfer *acl_out_transfer;
static struct libusb_transfer *event_in_transfer[ASYNC_BUFFERS]; static struct libusb_transfer *event_in_transfer[EVENT_IN_BUFFER_COUNT];
static struct libusb_transfer *acl_in_transfer[ASYNC_BUFFERS]; static struct libusb_transfer *acl_in_transfer[ACL_IN_BUFFER_COUNT];
#ifdef ENABLE_SCO_OVER_HCI #ifdef ENABLE_SCO_OVER_HCI
@ -152,23 +153,23 @@ static H2_SCO_STATE sco_state;
static uint8_t sco_buffer[255+3 + SCO_PACKET_SIZE]; static uint8_t sco_buffer[255+3 + SCO_PACKET_SIZE];
static uint16_t sco_read_pos; static uint16_t sco_read_pos;
static uint16_t sco_bytes_to_read; static uint16_t sco_bytes_to_read;
static struct libusb_transfer *sco_in_transfer[ISOC_BUFFERS]; static struct libusb_transfer *sco_in_transfer[SCO_IN_BUFFER_COUNT];
static uint8_t hci_sco_in_buffer[ISOC_BUFFERS][SCO_PACKET_SIZE]; static uint8_t hci_sco_in_buffer[SCO_IN_BUFFER_COUNT][SCO_PACKET_SIZE];
// outgoing SCO // outgoing SCO
static uint8_t sco_ring_buffer[SCO_RING_BUFFER_SIZE]; static uint8_t sco_out_ring_buffer[SCO_OUT_BUFFER_SIZE];
static int sco_ring_write; // packet idx static int sco_ring_write; // packet idx
static int sco_ring_transfers_active; static int sco_out_transfers_active;
static struct libusb_transfer *sco_ring_transfers[SCO_RING_BUFFER_COUNT]; static struct libusb_transfer *sco_out_transfers[SCO_OUT_BUFFER_COUNT];
static int sco_ring_transfers_in_flight[SCO_RING_BUFFER_COUNT]; static int sco_out_transfers_in_flight[SCO_OUT_BUFFER_COUNT];
#endif #endif
// outgoing buffer for HCI Command packets // outgoing buffer for HCI Command packets
static uint8_t hci_cmd_buffer[3 + 256 + LIBUSB_CONTROL_SETUP_SIZE]; static uint8_t hci_cmd_buffer[3 + 256 + LIBUSB_CONTROL_SETUP_SIZE];
// incoming buffer for HCI Events and ACL Packets // incoming buffer for HCI Events and ACL Packets
static uint8_t hci_event_in_buffer[ASYNC_BUFFERS][HCI_ACL_BUFFER_SIZE]; // bigger than largest packet 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[ASYNC_BUFFERS][HCI_INCOMING_PRE_BUFFER_SIZE + HCI_ACL_BUFFER_SIZE]; static uint8_t hci_acl_in_buffer[ACL_IN_BUFFER_COUNT][HCI_INCOMING_PRE_BUFFER_SIZE + HCI_ACL_BUFFER_SIZE];
// For (ab)use as a linked list of received packets // For (ab)use as a linked list of received packets
static struct libusb_transfer *handle_packet; static struct libusb_transfer *handle_packet;
@ -197,10 +198,10 @@ static uint8_t usb_path[USB_MAX_PATH_LEN];
#ifdef ENABLE_SCO_OVER_HCI #ifdef ENABLE_SCO_OVER_HCI
static void sco_ring_init(void){ static void sco_ring_init(void){
sco_ring_write = 0; sco_ring_write = 0;
sco_ring_transfers_active = 0; sco_out_transfers_active = 0;
} }
static int sco_ring_have_space(void){ static int sco_ring_have_space(void){
return sco_ring_transfers_active < SCO_RING_BUFFER_COUNT; return sco_out_transfers_active < SCO_OUT_BUFFER_COUNT;
} }
#endif #endif
@ -235,15 +236,19 @@ static void queue_transfer(struct libusb_transfer *transfer){
} }
LIBUSB_CALL static void async_callback(struct libusb_transfer *transfer){ LIBUSB_CALL static void async_callback(struct libusb_transfer *transfer){
// identify and free transfers as part of shutdown
int c; int c;
// identify and free transfers as part of shutdown
if (libusb_state != LIB_USB_TRANSFERS_ALLOCATED) { if (libusb_state != LIB_USB_TRANSFERS_ALLOCATED) {
for (c=0;c<ASYNC_BUFFERS;c++){ for (c=0;c<EVENT_IN_BUFFER_COUNT;c++){
if (transfer == event_in_transfer[c]){ if (transfer == event_in_transfer[c]){
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
event_in_transfer[c] = 0; event_in_transfer[c] = 0;
return; return;
} }
}
for (c=0;c<ACL_IN_BUFFER_COUNT;c++){
if (transfer == acl_in_transfer[c]){ if (transfer == acl_in_transfer[c]){
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
acl_in_transfer[c] = 0; acl_in_transfer[c] = 0;
@ -251,7 +256,7 @@ LIBUSB_CALL static void async_callback(struct libusb_transfer *transfer){
} }
} }
#ifdef ENABLE_SCO_OVER_HCI #ifdef ENABLE_SCO_OVER_HCI
for (c=0;c<ISOC_BUFFERS;c++){ for (c=0;c<SCO_IN_BUFFER_COUNT;c++){
if (transfer == sco_in_transfer[c]){ if (transfer == sco_in_transfer[c]){
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
sco_in_transfer[c] = 0; sco_in_transfer[c] = 0;
@ -259,11 +264,11 @@ LIBUSB_CALL static void async_callback(struct libusb_transfer *transfer){
} }
} }
for (c=0;c<SCO_RING_BUFFER_COUNT;c++){ for (c=0;c<SCO_OUT_BUFFER_COUNT;c++){
if (transfer == sco_ring_transfers[c]){ if (transfer == sco_out_transfers[c]){
sco_ring_transfers_in_flight[c] = 0; sco_out_transfers_in_flight[c] = 0;
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
sco_ring_transfers[c] = 0; sco_out_transfers[c] = 0;
return; return;
} }
} }
@ -272,9 +277,10 @@ LIBUSB_CALL static void async_callback(struct libusb_transfer *transfer){
return; return;
} }
for (c=0;c<SCO_RING_BUFFER_COUNT;c++){ // mark SCO OUT transfer as done
if (transfer == sco_ring_transfers[c]){ for (c=0;c<SCO_OUT_BUFFER_COUNT;c++){
sco_ring_transfers_in_flight[c] = 0; if (transfer == sco_out_transfers[c]){
sco_out_transfers_in_flight[c] = 0;
} }
} }
@ -316,11 +322,11 @@ static int usb_send_sco_packet(uint8_t *packet, int size){
// store packet in free slot // store packet in free slot
int tranfer_index = sco_ring_write; int tranfer_index = sco_ring_write;
uint8_t * data = &sco_ring_buffer[tranfer_index * SCO_PACKET_SIZE]; uint8_t * data = &sco_out_ring_buffer[tranfer_index * SCO_PACKET_SIZE];
memcpy(data, packet, size); memcpy(data, packet, size);
// setup transfer // setup transfer
struct libusb_transfer * sco_transfer = sco_ring_transfers[tranfer_index]; struct libusb_transfer * sco_transfer = sco_out_transfers[tranfer_index];
libusb_fill_iso_transfer(sco_transfer, handle, sco_out_addr, data, size, NUM_ISO_PACKETS, async_callback, NULL, 0); libusb_fill_iso_transfer(sco_transfer, handle, sco_out_addr, data, size, NUM_ISO_PACKETS, async_callback, NULL, 0);
libusb_set_iso_packet_lengths(sco_transfer, ISO_PACKET_SIZE); libusb_set_iso_packet_lengths(sco_transfer, ISO_PACKET_SIZE);
r = libusb_submit_transfer(sco_transfer); r = libusb_submit_transfer(sco_transfer);
@ -331,13 +337,13 @@ static int usb_send_sco_packet(uint8_t *packet, int size){
// mark slot as full // mark slot as full
sco_ring_write++; sco_ring_write++;
if (sco_ring_write == SCO_RING_BUFFER_COUNT){ if (sco_ring_write == SCO_OUT_BUFFER_COUNT){
sco_ring_write = 0; sco_ring_write = 0;
} }
sco_ring_transfers_active++; sco_out_transfers_active++;
sco_ring_transfers_in_flight[tranfer_index] = 1; sco_out_transfers_in_flight[tranfer_index] = 1;
// log_info("H2: queued packet at index %u, num active %u", tranfer_index, sco_ring_transfers_active); // log_info("H2: queued packet at index %u, num active %u", tranfer_index, sco_out_transfers_active);
// notify upper stack that provided buffer can be used again // notify upper stack that provided buffer can be used again
uint8_t event[] = { HCI_EVENT_TRANSPORT_PACKET_SENT, 0}; uint8_t event[] = { HCI_EVENT_TRANSPORT_PACKET_SENT, 0};
@ -444,8 +450,8 @@ static void handle_completed_transfer(struct libusb_transfer *transfer){
packet_handler(HCI_EVENT_PACKET, &event[0], sizeof(event)); packet_handler(HCI_EVENT_PACKET, &event[0], sizeof(event));
} }
// decrease tab // decrease tab
sco_ring_transfers_active--; sco_out_transfers_active--;
// log_info("H2: sco out complete, num active num active %u", sco_ring_transfers_active); // log_info("H2: sco out complete, num active num active %u", sco_out_transfers_active);
#endif #endif
} else { } else {
log_info("usb_process_ds endpoint unknown %x", transfer->endpoint); log_info("usb_process_ds endpoint unknown %x", transfer->endpoint);
@ -871,10 +877,16 @@ static int usb_open(void){
// allocate transfer handlers // allocate transfer handlers
int c; int c;
for (c = 0 ; c < ASYNC_BUFFERS ; c++) { for (c = 0 ; c < EVENT_IN_BUFFER_COUNT ; c++) {
event_in_transfer[c] = libusb_alloc_transfer(0); // 0 isochronous transfers Events event_in_transfer[c] = libusb_alloc_transfer(0); // 0 isochronous transfers Events
if (!event_in_transfer[c]) {
usb_close();
return LIBUSB_ERROR_NO_MEM;
}
}
for (c = 0 ; c < ACL_IN_BUFFER_COUNT ; c++) {
acl_in_transfer[c] = libusb_alloc_transfer(0); // 0 isochronous transfers ACL in acl_in_transfer[c] = libusb_alloc_transfer(0); // 0 isochronous transfers ACL in
if ( !event_in_transfer[c] || !acl_in_transfer[c]) { if (!acl_in_transfer[c]) {
usb_close(); usb_close();
return LIBUSB_ERROR_NO_MEM; return LIBUSB_ERROR_NO_MEM;
} }
@ -890,7 +902,7 @@ static int usb_open(void){
#ifdef ENABLE_SCO_OVER_HCI #ifdef ENABLE_SCO_OVER_HCI
// incoming // incoming
for (c = 0 ; c < ISOC_BUFFERS ; c++) { for (c = 0 ; c < SCO_IN_BUFFER_COUNT ; c++) {
sco_in_transfer[c] = libusb_alloc_transfer(NUM_ISO_PACKETS); // isochronous transfers SCO in sco_in_transfer[c] = libusb_alloc_transfer(NUM_ISO_PACKETS); // isochronous transfers SCO in
log_info("Alloc iso transfer"); log_info("Alloc iso transfer");
if (!sco_in_transfer[c]) { if (!sco_in_transfer[c]) {
@ -911,13 +923,13 @@ static int usb_open(void){
} }
// outgoing // outgoing
for (c=0; c < SCO_RING_BUFFER_COUNT ; c++){ for (c=0; c < SCO_OUT_BUFFER_COUNT ; c++){
sco_ring_transfers[c] = libusb_alloc_transfer(NUM_ISO_PACKETS); // 1 isochronous transfers SCO out - up to 3 parts sco_out_transfers[c] = libusb_alloc_transfer(NUM_ISO_PACKETS); // 1 isochronous transfers SCO out - up to 3 parts
sco_ring_transfers_in_flight[c] = 0; sco_out_transfers_in_flight[c] = 0;
} }
#endif #endif
for (c = 0 ; c < ASYNC_BUFFERS ; c++) { for (c = 0 ; c < EVENT_IN_BUFFER_COUNT ; c++) {
// configure event_in handlers // configure event_in handlers
libusb_fill_interrupt_transfer(event_in_transfer[c], handle, event_in_addr, libusb_fill_interrupt_transfer(event_in_transfer[c], handle, event_in_addr,
hci_event_in_buffer[c], HCI_ACL_BUFFER_SIZE, async_callback, NULL, 0) ; hci_event_in_buffer[c], HCI_ACL_BUFFER_SIZE, async_callback, NULL, 0) ;
@ -927,7 +939,9 @@ static int usb_open(void){
usb_close(); usb_close();
return r; return r;
} }
}
for (c = 0 ; c < ACL_IN_BUFFER_COUNT ; c++) {
// configure acl_in handlers // configure acl_in handlers
libusb_fill_bulk_transfer(acl_in_transfer[c], handle, acl_in_addr, libusb_fill_bulk_transfer(acl_in_transfer[c], handle, acl_in_addr,
hci_acl_in_buffer[c] + HCI_INCOMING_PRE_BUFFER_SIZE, HCI_ACL_BUFFER_SIZE, async_callback, NULL, 0) ; hci_acl_in_buffer[c] + HCI_INCOMING_PRE_BUFFER_SIZE, HCI_ACL_BUFFER_SIZE, async_callback, NULL, 0) ;
@ -1008,24 +1022,24 @@ static int usb_close(void){
case LIB_USB_INTERFACE_CLAIMED: case LIB_USB_INTERFACE_CLAIMED:
// Cancel all transfers, ignore warnings for this // Cancel all transfers, ignore warnings for this
libusb_set_debug(NULL, LIBUSB_LOG_LEVEL_ERROR); libusb_set_debug(NULL, LIBUSB_LOG_LEVEL_ERROR);
for (c = 0 ; c < ASYNC_BUFFERS ; c++) { for (c = 0 ; c < EVENT_IN_BUFFER_COUNT ; c++) {
libusb_cancel_transfer(event_in_transfer[c]); libusb_cancel_transfer(event_in_transfer[c]);
}
for (c = 0 ; c < ACL_IN_BUFFER_COUNT ; c++) {
libusb_cancel_transfer(acl_in_transfer[c]); libusb_cancel_transfer(acl_in_transfer[c]);
} }
#ifdef ENABLE_SCO_OVER_HCI #ifdef ENABLE_SCO_OVER_HCI
for (c = 0 ; c < ISOC_BUFFERS ; c++) { for (c = 0 ; c < SCO_IN_BUFFER_COUNT ; c++) {
libusb_cancel_transfer(sco_in_transfer[c]); libusb_cancel_transfer(sco_in_transfer[c]);
log_info("libusb_cancel_transfer sco_in_transfer[%d]", c);
} }
for (c = 0; c < SCO_OUT_BUFFER_COUNT ; c++){
for (c = 0; c < SCO_RING_BUFFER_COUNT ; c++){ if (sco_out_transfers_in_flight[c]) {
if (sco_ring_transfers_in_flight[c]) { log_info("libusb_cancel_transfer sco_out_transfers[%d]", c);
log_info("libusb_cancel_transfer sco_ring_transfers[%d]", c); libusb_cancel_transfer(sco_out_transfers[c]);
libusb_cancel_transfer(sco_ring_transfers[c]);
} else { } else {
log_info("libusb_free_transfer sco_ring_transfers[%d]", c); log_info("libusb_free_transfer sco_out_transfers[%d]", c);
libusb_free_transfer(sco_ring_transfers[c]); libusb_free_transfer(sco_out_transfers[c]);
sco_ring_transfers[c] = 0; sco_out_transfers[c] = 0;
} }
} }
#endif #endif
@ -1039,17 +1053,27 @@ static int usb_close(void){
libusb_handle_events_timeout(NULL, &tv); libusb_handle_events_timeout(NULL, &tv);
// check if all done // check if all done
completed = 1; completed = 1;
for (c=0;c<ASYNC_BUFFERS;c++){ for (c=0;c<EVENT_IN_BUFFER_COUNT;c++){
if (event_in_transfer[c] || acl_in_transfer[c]) { if (event_in_transfer[c]) {
completed = 0; completed = 0;
break; break;
} }
} }
if (!completed) continue;
for (c=0;c<ACL_IN_BUFFER_COUNT;c++){
if (acl_in_transfer[c]) {
completed = 0;
break;
}
}
#ifdef ENABLE_SCO_OVER_HCI #ifdef ENABLE_SCO_OVER_HCI
if (!completed) continue; if (!completed) continue;
// Cancel all synchronous transfer // Cancel all synchronous transfer
for (c = 0 ; c < ISOC_BUFFERS ; c++) { for (c = 0 ; c < SCO_IN_BUFFER_COUNT ; c++) {
if (sco_in_transfer[c]){ if (sco_in_transfer[c]){
completed = 0; completed = 0;
break; break;
@ -1058,8 +1082,8 @@ static int usb_close(void){
if (!completed) continue; if (!completed) continue;
for (c=0; c < SCO_RING_BUFFER_COUNT ; c++){ for (c=0; c < SCO_OUT_BUFFER_COUNT ; c++){
if (sco_ring_transfers[c]){ if (sco_out_transfers[c]){
completed = 0; completed = 0;
break; break;
} }