int usb_setup(char *name, size_t namelen) { if (libusb_init(NULL) < 0) { return -1; } if (libusb_pollfds_handle_timeouts(NULL) == 0) { printf("I'm too dumb to handle events on such an old system.\n"); return -1; } for (d = devices; d->product_id; d += 1) { usb_dev = libusb_open_device_with_vid_pid(NULL, 0x6f8, d->product_id); if (usb_dev) { break; } } if (! usb_dev) { printf("Couldn't find a controller.\n"); return -1; } // Figure out what it's called { int ret; struct libusb_device_descriptor ddesc; libusb_get_device_descriptor(libusb_get_device(usb_dev), &ddesc); ret = libusb_get_string_descriptor_ascii(usb_dev, ddesc.iManufacturer, (unsigned char *)name, namelen); if (ret > 0) { char *p = name + ret; *p = ' '; p += 1; ret = libusb_get_string_descriptor_ascii(usb_dev, ddesc.iProduct, (unsigned char *)p, namelen - ret - 1); } if (ret < 0) { printf("Warning: I can't figure out what to call this thing.\n"); } printf("Opened [%s]\n", name); } usb_initiate_transfer(); return 0; }
int usb_init(void) { int phase = 0; log_debug("Initializing USB subsystem"); _libusb_log_source.file = "libusb"; _libusb_log_source.name = "libusb"; #if defined(_WIN32) || defined(__APPLE__) libusb_set_log_function(usb_forward_message); #endif switch (log_get_effective_level()) { case LOG_LEVEL_ERROR: putenv("LIBUSB_DEBUG=1"); break; case LOG_LEVEL_WARN: putenv("LIBUSB_DEBUG=2"); break; case LOG_LEVEL_INFO: putenv("LIBUSB_DEBUG=3"); break; case LOG_LEVEL_DEBUG: if (log_is_included(LOG_LEVEL_DEBUG, &_libusb_log_source, LOG_DEBUG_GROUP_LIBUSB)) { putenv("LIBUSB_DEBUG=4"); } else { putenv("LIBUSB_DEBUG=3"); } break; default: break; } if (usb_init_platform() < 0) { goto cleanup; } phase = 1; // initialize main libusb context if (usb_create_context(&_context)) { goto cleanup; } phase = 2; if (!libusb_pollfds_handle_timeouts(_context)) { log_debug("libusb requires special timeout handling"); // FIXME } else { log_debug("libusb can handle timeouts on its own"); } // create USB stack array. the USBStack struct is not relocatable, because // its USB transfers keep a pointer to it if (array_create(&_usb_stacks, 32, sizeof(USBStack), false) < 0) { log_error("Could not create USB stack array: %s (%d)", get_errno_name(errno), errno); goto cleanup; } phase = 3; if (usb_has_hotplug()) { log_debug("libusb supports hotplug"); if (usb_init_hotplug(_context) < 0) { goto cleanup; } _initialized_hotplug = true; } else { log_debug("libusb does not support hotplug"); } if (usb_rescan() < 0) { goto cleanup; } phase = 4; cleanup: switch (phase) { // no breaks, all cases fall through intentionally case 3: array_destroy(&_usb_stacks, (ItemDestroyFunction)usb_stack_destroy); case 2: usb_destroy_context(_context); case 1: usb_exit_platform(); default: break; } return phase == 4 ? 0 : -1; }
static int usb_open(void *transport_config){ int r; sco_state_machine_init(); sco_ring_init(); handle_packet = NULL; // default endpoint addresses event_in_addr = 0x81; // EP1, IN interrupt acl_in_addr = 0x82; // EP2, IN bulk acl_out_addr = 0x02; // EP2, OUT bulk sco_in_addr = 0x83; // EP3, IN isochronous sco_out_addr = 0x03; // EP3, OUT isochronous // USB init r = libusb_init(NULL); if (r < 0) return -1; libusb_state = LIB_USB_OPENED; // configure debug level libusb_set_debug(NULL, LIBUSB_LOG_LEVEL_WARNING); #ifdef HAVE_USB_VENDOR_ID_AND_PRODUCT_ID // Use a specified device log_info("Want vend: %04x, prod: %04x", USB_VENDOR_ID, USB_PRODUCT_ID); handle = libusb_open_device_with_vid_pid(NULL, USB_VENDOR_ID, USB_PRODUCT_ID); if (!handle){ log_error("libusb_open_device_with_vid_pid failed!"); usb_close(handle); return -1; } log_info("libusb open %d, handle %p", r, handle); r = prepare_device(handle); if (r < 0){ usb_close(handle); return -1; } #else // Scan system for an appropriate devices libusb_device **devs; ssize_t cnt; log_info("Scanning for USB Bluetooth device"); cnt = libusb_get_device_list(NULL, &devs); if (cnt < 0) { usb_close(handle); return -1; } int startIndex = 0; dev = NULL; while (1){ int deviceIndex = scan_for_bt_device(devs, startIndex); if (deviceIndex < 0){ break; } startIndex = deviceIndex+1; log_info("USB Bluetooth device found, index %u", deviceIndex); handle = NULL; r = libusb_open(devs[deviceIndex], &handle); if (r < 0) { log_error("libusb_open failed!"); handle = NULL; continue; } log_info("libusb open %d, handle %p", r, handle); // reset device libusb_reset_device(handle); if (r < 0) { log_error("libusb_reset_device failed!"); libusb_close(handle); handle = NULL; continue; } // device found r = prepare_device(handle); if (r < 0){ continue; } libusb_state = LIB_USB_INTERFACE_CLAIMED; break; } libusb_free_device_list(devs, 1); if (handle == 0){ log_error("No USB Bluetooth device found"); return -1; } scan_for_bt_endpoints(); #endif // allocate transfer handlers int c; for (c = 0 ; c < ASYNC_BUFFERS ; c++) { event_in_transfer[c] = libusb_alloc_transfer(0); // 0 isochronous transfers Events acl_in_transfer[c] = libusb_alloc_transfer(0); // 0 isochronous transfers ACL in if ( !event_in_transfer[c] || !acl_in_transfer[c]) { usb_close(handle); return LIBUSB_ERROR_NO_MEM; } } command_out_transfer = libusb_alloc_transfer(0); acl_out_transfer = libusb_alloc_transfer(0); // TODO check for error libusb_state = LIB_USB_TRANSFERS_ALLOCATED; #ifdef HAVE_SCO // incoming for (c = 0 ; c < ASYNC_BUFFERS ; c++) { sco_in_transfer[c] = libusb_alloc_transfer(NUM_ISO_PACKETS); // isochronous transfers SCO in log_info("Alloc iso transfer"); if (!sco_in_transfer[c]) { usb_close(handle); return LIBUSB_ERROR_NO_MEM; } // configure sco_in handlers libusb_fill_iso_transfer(sco_in_transfer[c], handle, sco_in_addr, hci_sco_in_buffer[c], SCO_PACKET_SIZE, NUM_ISO_PACKETS, async_callback, NULL, 0); libusb_set_iso_packet_lengths(sco_in_transfer[c], ISO_PACKET_SIZE); r = libusb_submit_transfer(sco_in_transfer[c]); log_info("Submit iso transfer res = %d", r); if (r) { log_error("Error submitting isochronous in transfer %d", r); usb_close(handle); return r; } } // outgoing for (c=0; c < SCO_RING_BUFFER_COUNT ; c++){ sco_ring_transfers[c] = libusb_alloc_transfer(NUM_ISO_PACKETS); // 1 isochronous transfers SCO out - up to 3 parts } #endif for (c = 0 ; c < ASYNC_BUFFERS ; c++) { // configure event_in handlers 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) ; r = libusb_submit_transfer(event_in_transfer[c]); if (r) { log_error("Error submitting interrupt transfer %d", r); usb_close(handle); return r; } // configure acl_in handlers 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) ; r = libusb_submit_transfer(acl_in_transfer[c]); if (r) { log_error("Error submitting bulk in transfer %d", r); usb_close(handle); return r; } } // Check for pollfds functionality doing_pollfds = libusb_pollfds_handle_timeouts(NULL); // NOTE: using pollfds doesn't work on Linux, so it is disable until further investigation here doing_pollfds = 0; if (doing_pollfds) { log_info("Async using pollfds:"); const struct libusb_pollfd ** pollfd = libusb_get_pollfds(NULL); for (num_pollfds = 0 ; pollfd[num_pollfds] ; num_pollfds++); pollfd_data_sources = malloc(sizeof(data_source_t) * num_pollfds); if (!pollfd_data_sources){ log_error("Cannot allocate data sources for pollfds"); usb_close(handle); return 1; } for (r = 0 ; r < num_pollfds ; r++) { data_source_t *ds = &pollfd_data_sources[r]; ds->fd = pollfd[r]->fd; ds->process = usb_process_ds; run_loop_add_data_source(ds); log_info("%u: %p fd: %u, events %x", r, pollfd[r], pollfd[r]->fd, pollfd[r]->events); } free(pollfd); } else { log_info("Async using timers:"); usb_timer.process = usb_process_ts; run_loop_set_timer(&usb_timer, AYSNC_POLLING_INTERVAL_MS); run_loop_add_timer(&usb_timer); usb_timer_active = 1; } return 0; }