static int probe(std::unique_ptr<usb_handle> &h, ifc_match_func callback) { usb_ifc_info info; libusb_device_descriptor ddesc; libusb_config_descriptor *pcfg; int i, j; if (libusb_open(h->dev, &h->handle) < 0) return (-1); if (libusb_get_device_descriptor(h->dev, &ddesc) < 0) { libusb_close(h->handle); return (-1); } memset(&info, 0, sizeof(info)); info.dev_vendor = ddesc.idVendor; info.dev_product = ddesc.idProduct; info.dev_class = ddesc.bDeviceClass; info.dev_subclass = ddesc.bDeviceSubClass; info.dev_protocol = ddesc.bDeviceProtocol; info.writable = 1; snprintf(info.device_path, sizeof(info.device_path), "ugen%d.%d", libusb_get_bus_number(h->dev), libusb_get_device_address(h->dev)); if (ddesc.iSerialNumber != 0) { libusb_get_string_descriptor_ascii(h->handle, ddesc.iSerialNumber, (unsigned char *)info.serial_number, sizeof(info.serial_number)); } if (libusb_get_active_config_descriptor(h->dev, &pcfg)) { libusb_close(h->handle); return (-1); } for (i = 0; i < pcfg->bNumInterfaces; i++) { h->ep_in = 0; h->ep_out = 0; h->iface = i; for (j = 0; j < pcfg->interface[i].altsetting[0].bNumEndpoints; j++) { unsigned char temp = pcfg->interface[i].altsetting[0]. endpoint[j].bEndpointAddress; unsigned char type = pcfg->interface[i].altsetting[0]. endpoint[j].bmAttributes & 0x03; /* check for BULK endpoint */ if ((type & 0x03) == 0x02) { /* check for IN endpoint */ if (temp & 0x80) h->ep_in = temp; else h->ep_out = temp; } } info.ifc_class = pcfg->interface[i].altsetting[0].bInterfaceClass; info.ifc_subclass = pcfg->interface[i].altsetting[0].bInterfaceSubClass; info.ifc_protocol = pcfg->interface[i].altsetting[0].bInterfaceProtocol; info.has_bulk_in = (h->ep_in != 0); info.has_bulk_out = (h->ep_out != 0); if (libusb_claim_interface(h->handle, h->iface) < 0) continue; if (callback(&info) == 0) { libusb_free_config_descriptor(pcfg); return (0); } libusb_release_interface(h->handle, h->iface); } libusb_free_config_descriptor(pcfg); libusb_close(h->handle); return (-1); }
// open - open 1 or more devices // // Inputs: // max = maximum number of devices to open // vid = Vendor ID, or -1 if any // pid = Product ID, or -1 if any // usage_page = unused, argument kept for api consistency // usage = unused, argument kept for api consistency // Output: // actual number of devices opened // int pjrc_rawhid::open(int max, int vid, int pid, int /* usage_page */, int /* usage */) { //check if there are still open devices and close them if (!m_DeviceHandles.empty()) { for (std::size_t iDevice = 0; iDevice < m_DeviceHandles.size(); ++iDevice) { if (m_DeviceHandles[iDevice] != NULL) close(iDevice); } m_DeviceHandles.clear(); m_DeviceInterfaces.clear(); } int retval; //enumerate all devices libusb_device** list = NULL; ssize_t num_devices; num_devices = libusb_get_device_list(m_pLibraryContext, &list); for (ssize_t iDevice = 0; iDevice < num_devices && m_DeviceHandles.size() < (std::size_t)max; ++iDevice) { libusb_device_descriptor device_desc; retval = libusb_get_device_descriptor(list[iDevice], &device_desc); if (retval < 0) { fprintf(stderr, "pjrc_rawhid_unix: Failed to get device descriptor (%d)\n", retval); continue; } //check if we are interested in this device if (device_desc.idVendor != vid || device_desc.idProduct != pid) continue; //search for proper interface libusb_config_descriptor* config_desc; retval = libusb_get_config_descriptor(list[iDevice], 0, &config_desc); if (retval != 0) { fprintf(stderr, "pjrc_rawhid_unix: libusb_get_config_descriptor error (%d)\n", retval); continue; } int device_interface = -1; const libusb_interface* interface; const libusb_interface_descriptor* interface_desc; for (ssize_t iInterface = 0; iInterface < config_desc->bNumInterfaces && device_interface == -1; ++iInterface) { interface = &config_desc->interface[iInterface]; for (ssize_t iAltSetting = 0; iAltSetting < interface->num_altsetting && device_interface == -1; ++iAltSetting) { interface_desc = &interface->altsetting[iAltSetting]; if (interface_desc->bInterfaceClass == LIBUSB_CLASS_HID && interface_desc->bInterfaceSubClass == 0 && interface_desc->bInterfaceProtocol == 0) { device_interface = iInterface; } } } libusb_free_config_descriptor(config_desc); //check if we found an interface, if not, skip device if (device_interface == -1) continue; libusb_device_handle* device_handle; retval = libusb_open(list[iDevice], &device_handle); //skip if device cant be opened if (retval != 0) { fprintf(stderr, "pjrc_rawhid_unix: Failed to open device (%d)\n", retval); continue; } //detach kernel retval = libusb_detach_kernel_driver(device_handle, device_interface); if (retval != 0 && retval != LIBUSB_ERROR_NOT_FOUND) { fprintf(stderr, "pjrc_rawhid_unix: Unable to detach kernel driver (%d)\n", retval); libusb_close(device_handle); continue; } //claim interface retval = libusb_claim_interface(device_handle, device_interface); if (retval != 0) { fprintf(stderr, "pjrc_rawhid_unix: libusb_claim_interface error (%d)\n", retval); libusb_close(device_handle); continue; } m_DeviceHandles.push_back(device_handle); m_DeviceInterfaces.push_back(device_interface); } libusb_free_device_list(list, 1); return m_DeviceHandles.size(); }
/***************************************************************************** * * OpenUSBByName * ****************************************************************************/ status_t OpenUSBByName(unsigned int reader_index, /*@null@*/ char *device) { unsigned int alias; struct libusb_device_handle *dev_handle; char infofile[FILENAME_MAX]; #ifndef __APPLE__ unsigned int device_vendor, device_product; unsigned int device_bus = 0; unsigned int device_addr = 0; #else /* 100 ms delay */ struct timespec sleep_time = { 0, 100 * 1000 * 1000 }; int count_libusb = 10; #endif int interface_number = -1; int i; static int previous_reader_index = -1; libusb_device **devs, *dev; ssize_t cnt; list_t plist, *values, *ifdVendorID, *ifdProductID, *ifdFriendlyName; int rv; int claim_failed = FALSE; int return_value = STATUS_SUCCESS; DEBUG_COMM3("Reader index: %X, Device: %s", reader_index, device); #ifndef __APPLE__ /* device name specified */ if (device) { char *dirname; /* format: usb:%04x/%04x, vendor, product */ if (strncmp("usb:", device, 4) != 0) { DEBUG_CRITICAL2("device name does not start with \"usb:\": %s", device); return STATUS_UNSUCCESSFUL; } if (sscanf(device, "usb:%x/%x", &device_vendor, &device_product) != 2) { DEBUG_CRITICAL2("device name can't be parsed: %s", device); return STATUS_UNSUCCESSFUL; } /* format usb:%04x/%04x:libudev:%d:%s * with %d set to * 01 (or whatever the interface number is) * and %s set to * /dev/bus/usb/008/004 */ if ((dirname = strstr(device, "libudev:")) != NULL) { /* convert the interface number, bus and device ids */ if (sscanf(dirname + 8, "%d:/dev/bus/usb/%d/%d", &interface_number, &device_bus, &device_addr) == 3) { DEBUG_COMM2("interface_number: %d", interface_number); DEBUG_COMM3("usb bus/device: %d/%d", device_bus, device_addr); } } } #endif /* is the reader_index already used? */ if (usbDevice[reader_index].dev_handle != NULL) { DEBUG_CRITICAL2("USB driver with index %X already in use", reader_index); return STATUS_UNSUCCESSFUL; } /* Info.plist full patch filename */ (void)snprintf(infofile, sizeof(infofile), "%s/%s/Contents/Info.plist", PCSCLITE_HP_DROPDIR, BUNDLE); DEBUG_INFO2("Using: %s", infofile); rv = bundleParse(infofile, &plist); if (rv) return STATUS_UNSUCCESSFUL; #define GET_KEY(key, values) \ rv = LTPBundleFindValueWithKey(&plist, key, &values); \ if (rv) \ { \ DEBUG_CRITICAL2("Value/Key not defined for " key " in %s", infofile); \ return_value = STATUS_UNSUCCESSFUL; \ goto end1; \ } \ else \ DEBUG_INFO2(key ": %s", (char *)list_get_at(values, 0)); /* general driver info */ GET_KEY("ifdManufacturerString", values) GET_KEY("ifdProductString", values) GET_KEY("Copyright", values) if (NULL == ctx) { rv = libusb_init(&ctx); if (rv != 0) { DEBUG_CRITICAL2("libusb_init failed: %s", libusb_error_name(rv)); return_value = STATUS_UNSUCCESSFUL; goto end1; } } #define GET_KEYS(key, values) \ rv = LTPBundleFindValueWithKey(&plist, key, values); \ if (rv) \ { \ DEBUG_CRITICAL2("Value/Key not defined for " key " in %s", infofile); \ return_value = STATUS_UNSUCCESSFUL; \ goto end1; \ } GET_KEYS("ifdVendorID", &ifdVendorID) GET_KEYS("ifdProductID", &ifdProductID); GET_KEYS("ifdFriendlyName", &ifdFriendlyName) /* The 3 lists do not have the same size */ if ((list_size(ifdVendorID) != list_size(ifdProductID)) || (list_size(ifdVendorID) != list_size(ifdFriendlyName))) { DEBUG_CRITICAL2("Error parsing %s", infofile); return_value = STATUS_UNSUCCESSFUL; goto end1; } #ifdef __APPLE__ again_libusb: #endif cnt = libusb_get_device_list(ctx, &devs); if (cnt < 0) { DEBUG_CRITICAL("libusb_get_device_list() failed\n"); return_value = STATUS_UNSUCCESSFUL; goto end1; } /* for any supported reader */ for (alias=0; alias<list_size(ifdVendorID); alias++) { unsigned int vendorID, productID; char *friendlyName; vendorID = strtoul(list_get_at(ifdVendorID, alias), NULL, 0); productID = strtoul(list_get_at(ifdProductID, alias), NULL, 0); friendlyName = list_get_at(ifdFriendlyName, alias); #ifndef __APPLE__ /* the device was specified but is not the one we are trying to find */ if (device && (vendorID != device_vendor || productID != device_product)) continue; #else /* Leopard puts the friendlyname in the device argument */ if (device && strcmp(device, friendlyName)) continue; #endif /* for every device */ i = 0; while ((dev = devs[i++]) != NULL) { struct libusb_device_descriptor desc; struct libusb_config_descriptor *config_desc; uint8_t bus_number = libusb_get_bus_number(dev); uint8_t device_address = libusb_get_device_address(dev); #ifndef __APPLE__ if ((device_bus || device_addr) && ((bus_number != device_bus) || (device_address != device_addr))) { /* not USB the device we are looking for */ continue; } #endif DEBUG_COMM3("Try device: %d/%d", bus_number, device_address); int r = libusb_get_device_descriptor(dev, &desc); if (r < 0) { DEBUG_INFO3("failed to get device descriptor for %d/%d", bus_number, device_address); continue; } DEBUG_COMM3("vid/pid : %04X/%04X", desc.idVendor, desc.idProduct); if (desc.idVendor == vendorID && desc.idProduct == productID) { int already_used; const struct libusb_interface *usb_interface = NULL; int interface; int num = 0; const unsigned char *device_descriptor; int readerID = (vendorID << 16) + productID; #ifdef USE_COMPOSITE_AS_MULTISLOT static int static_interface = 1; /* simulate a composite device as when libudev is used */ if ((GEMALTOPROXDU == readerID) || (GEMALTOPROXSU == readerID) || (FEITIANR502DUAL == readerID)) { /* * We can't talk to the two CCID interfaces * at the same time (the reader enters a * dead lock). So we simulate a multi slot * reader. By default multi slot readers * can't use the slots at the same time. See * TAG_IFD_SLOT_THREAD_SAFE * * One side effect is that the two readers * are seen by pcscd as one reader so the * interface name is the same for the two. * * So we have: * 0: Gemalto Prox-DU [Prox-DU Contact_09A00795] (09A00795) 00 00 * 1: Gemalto Prox-DU [Prox-DU Contact_09A00795] (09A00795) 00 01 * instead of * 0: Gemalto Prox-DU [Prox-DU Contact_09A00795] (09A00795) 00 00 * 1: Gemalto Prox-DU [Prox-DU Contactless_09A00795] (09A00795) 01 00 */ /* the CCID interfaces are 1 and 2 */ interface_number = static_interface; } #endif /* is it already opened? */ already_used = FALSE; DEBUG_COMM3("Checking device: %d/%d", bus_number, device_address); for (r=0; r<CCID_DRIVER_MAX_READERS; r++) { if (usbDevice[r].dev_handle) { /* same bus, same address */ if (usbDevice[r].bus_number == bus_number && usbDevice[r].device_address == device_address) already_used = TRUE; } } /* this reader is already managed by us */ if (already_used) { if ((previous_reader_index != -1) && usbDevice[previous_reader_index].dev_handle && (usbDevice[previous_reader_index].bus_number == bus_number) && (usbDevice[previous_reader_index].device_address == device_address) && usbDevice[previous_reader_index].ccid.bCurrentSlotIndex < usbDevice[previous_reader_index].ccid.bMaxSlotIndex) { /* we reuse the same device * and the reader is multi-slot */ usbDevice[reader_index] = usbDevice[previous_reader_index]; /* The other slots of GemCore SIM Pro firmware * 1.0 do not have the same data rates. * Firmware 2.0 do not have this limitation */ if ((GEMCOREPOSPRO == readerID) || ((GEMCORESIMPRO == readerID) && (usbDevice[reader_index].ccid.IFD_bcdDevice < 0x0200))) { usbDevice[reader_index].ccid.arrayOfSupportedDataRates = SerialCustomDataRates; usbDevice[reader_index].ccid.dwMaxDataRate = 125000; } *usbDevice[reader_index].nb_opened_slots += 1; usbDevice[reader_index].ccid.bCurrentSlotIndex++; usbDevice[reader_index].ccid.dwSlotStatus = IFD_ICC_PRESENT; DEBUG_INFO2("Opening slot: %d", usbDevice[reader_index].ccid.bCurrentSlotIndex); /* This is a multislot reader * Init the multislot stuff for this next slot */ usbDevice[reader_index].multislot_extension = Multi_CreateNextSlot(previous_reader_index); goto end; } else { /* if an interface number is given by HAL we * continue with this device. */ if (-1 == interface_number) { DEBUG_INFO3("USB device %d/%d already in use." " Checking next one.", bus_number, device_address); continue; } } } DEBUG_COMM3("Trying to open USB bus/device: %d/%d", bus_number, device_address); r = libusb_open(dev, &dev_handle); if (r < 0) { DEBUG_CRITICAL4("Can't libusb_open(%d/%d): %s", bus_number, device_address, libusb_error_name(r)); continue; } again: r = libusb_get_active_config_descriptor(dev, &config_desc); if (r < 0) { #ifdef __APPLE__ /* Some early Gemalto Ezio CB+ readers have * bDeviceClass, bDeviceSubClass and bDeviceProtocol set * to 0xFF (proprietary) instead of 0x00. * * So on Mac OS X the reader configuration is not done * by the OS/kernel and we do it ourself. */ if ((0xFF == desc.bDeviceClass) && (0xFF == desc.bDeviceSubClass) && (0xFF == desc.bDeviceProtocol)) { r = libusb_set_configuration(dev_handle, 1); if (r < 0) { (void)libusb_close(dev_handle); DEBUG_CRITICAL4("Can't set configuration on %d/%d: %s", bus_number, device_address, libusb_error_name(r)); continue; } } /* recall */ r = libusb_get_active_config_descriptor(dev, &config_desc); if (r < 0) { #endif (void)libusb_close(dev_handle); DEBUG_CRITICAL4("Can't get config descriptor on %d/%d: %s", bus_number, device_address, libusb_error_name(r)); continue; } #ifdef __APPLE__ } #endif usb_interface = get_ccid_usb_interface(config_desc, &num); if (usb_interface == NULL) { (void)libusb_close(dev_handle); if (0 == num) DEBUG_CRITICAL3("Can't find a CCID interface on %d/%d", bus_number, device_address); interface_number = -1; continue; } device_descriptor = get_ccid_device_descriptor(usb_interface); if (NULL == device_descriptor) { (void)libusb_close(dev_handle); DEBUG_CRITICAL3("Unable to find the device descriptor for %d/%d", bus_number, device_address); return_value = STATUS_UNSUCCESSFUL; goto end2; } interface = usb_interface->altsetting->bInterfaceNumber; if (interface_number >= 0 && interface != interface_number) { /* an interface was specified and it is not the * current one */ DEBUG_INFO3("Found interface %d but expecting %d", interface, interface_number); DEBUG_INFO3("Wrong interface for USB device %d/%d." " Checking next one.", bus_number, device_address); /* check for another CCID interface on the same device */ num++; goto again; } r = libusb_claim_interface(dev_handle, interface); if (r < 0) { (void)libusb_close(dev_handle); DEBUG_CRITICAL4("Can't claim interface %d/%d: %s", bus_number, device_address, libusb_error_name(r)); claim_failed = TRUE; interface_number = -1; continue; } DEBUG_INFO4("Found Vendor/Product: %04X/%04X (%s)", desc.idVendor, desc.idProduct, friendlyName); DEBUG_INFO3("Using USB bus/device: %d/%d", bus_number, device_address); /* check for firmware bugs */ if (ccid_check_firmware(&desc)) { (void)libusb_close(dev_handle); return_value = STATUS_UNSUCCESSFUL; goto end2; } #ifdef USE_COMPOSITE_AS_MULTISLOT /* use the next interface for the next "slot" */ static_interface++; /* reset for a next reader */ if (static_interface > 2) static_interface = (FEITIANR502DUAL == readerID) ? 0: 1; #endif /* Get Endpoints values*/ (void)get_end_points(config_desc, &usbDevice[reader_index], num); /* store device information */ usbDevice[reader_index].dev_handle = dev_handle; usbDevice[reader_index].bus_number = bus_number; usbDevice[reader_index].device_address = device_address; usbDevice[reader_index].interface = interface; usbDevice[reader_index].real_nb_opened_slots = 1; usbDevice[reader_index].nb_opened_slots = &usbDevice[reader_index].real_nb_opened_slots; usbDevice[reader_index].polling_transfer = NULL; /* CCID common informations */ usbDevice[reader_index].ccid.real_bSeq = 0; usbDevice[reader_index].ccid.pbSeq = &usbDevice[reader_index].ccid.real_bSeq; usbDevice[reader_index].ccid.readerID = (desc.idVendor << 16) + desc.idProduct; usbDevice[reader_index].ccid.dwFeatures = dw2i(device_descriptor, 40); usbDevice[reader_index].ccid.wLcdLayout = (device_descriptor[51] << 8) + device_descriptor[50]; usbDevice[reader_index].ccid.bPINSupport = device_descriptor[52]; usbDevice[reader_index].ccid.dwMaxCCIDMessageLength = dw2i(device_descriptor, 44); usbDevice[reader_index].ccid.dwMaxIFSD = dw2i(device_descriptor, 28); usbDevice[reader_index].ccid.dwDefaultClock = dw2i(device_descriptor, 10); usbDevice[reader_index].ccid.dwMaxDataRate = dw2i(device_descriptor, 23); usbDevice[reader_index].ccid.bMaxSlotIndex = device_descriptor[4]; usbDevice[reader_index].ccid.bCurrentSlotIndex = 0; usbDevice[reader_index].ccid.readTimeout = DEFAULT_COM_READ_TIMEOUT; if (device_descriptor[27]) usbDevice[reader_index].ccid.arrayOfSupportedDataRates = get_data_rates(reader_index, config_desc, num); else { usbDevice[reader_index].ccid.arrayOfSupportedDataRates = NULL; DEBUG_INFO1("bNumDataRatesSupported is 0"); } usbDevice[reader_index].ccid.bInterfaceProtocol = usb_interface->altsetting->bInterfaceProtocol; usbDevice[reader_index].ccid.bNumEndpoints = usb_interface->altsetting->bNumEndpoints; usbDevice[reader_index].ccid.dwSlotStatus = IFD_ICC_PRESENT; usbDevice[reader_index].ccid.bVoltageSupport = device_descriptor[5]; usbDevice[reader_index].ccid.sIFD_serial_number = NULL; usbDevice[reader_index].ccid.gemalto_firmware_features = NULL; if (desc.iSerialNumber) { unsigned char serial[128]; int ret; ret = libusb_get_string_descriptor_ascii(dev_handle, desc.iSerialNumber, serial, sizeof(serial)); if (ret > 0) usbDevice[reader_index].ccid.sIFD_serial_number = strdup((char *)serial); } usbDevice[reader_index].ccid.sIFD_iManufacturer = NULL; if (desc.iManufacturer) { unsigned char iManufacturer[128]; int ret; ret = libusb_get_string_descriptor_ascii(dev_handle, desc.iManufacturer, iManufacturer, sizeof(iManufacturer)); if (ret > 0) usbDevice[reader_index].ccid.sIFD_iManufacturer = strdup((char *)iManufacturer); } usbDevice[reader_index].ccid.IFD_bcdDevice = desc.bcdDevice; /* If this is a multislot reader, init the multislot stuff */ if (usbDevice[reader_index].ccid.bMaxSlotIndex) usbDevice[reader_index].multislot_extension = Multi_CreateFirstSlot(reader_index); else usbDevice[reader_index].multislot_extension = NULL; goto end; } } } end: if (usbDevice[reader_index].dev_handle == NULL) { /* free the libusb allocated list & devices */ libusb_free_device_list(devs, 1); #ifdef __APPLE__ /* give some time to libusb to detect the new USB devices on Mac OS X */ if (count_libusb > 0) { count_libusb--; DEBUG_INFO2("Wait after libusb: %d", count_libusb); nanosleep(&sleep_time, NULL); goto again_libusb; } #endif /* failed */ close_libusb_if_needed(); if (claim_failed) return STATUS_COMM_ERROR; DEBUG_INFO1("Device not found?"); return STATUS_NO_SUCH_DEVICE; } /* memorise the current reader_index so we can detect * a new OpenUSBByName on a multi slot reader */ previous_reader_index = reader_index; end2: /* free the libusb allocated list & devices */ libusb_free_device_list(devs, 1); end1: /* free bundle list */ bundleRelease(&plist); if (return_value != STATUS_SUCCESS) close_libusb_if_needed(); return return_value; } /* OpenUSBByName */
int fnusb_open_subdevices(freenect_device *dev, int index) { freenect_context *ctx = dev->parent; dev->usb_cam.parent = dev; dev->usb_cam.dev = NULL; dev->usb_motor.parent = dev; dev->usb_motor.dev = NULL; #ifdef BUILD_AUDIO dev->usb_audio.parent = dev; dev->usb_audio.dev = NULL; #endif libusb_device **devs; //pointer to pointer of device, used to retrieve a list of devices ssize_t cnt = libusb_get_device_list (dev->parent->usb.ctx, &devs); //get the list of devices if (cnt < 0) return -1; int i = 0, nr_cam = 0, nr_mot = 0; #ifdef BUILD_AUDIO int nr_audio = 0; #endif int res; struct libusb_device_descriptor desc; for (i = 0; i < cnt; i++) { int r = libusb_get_device_descriptor (devs[i], &desc); if (r < 0) continue; if (desc.idVendor != VID_MICROSOFT) continue; // Search for the camera if ((ctx->enabled_subdevices & FREENECT_DEVICE_CAMERA) && !dev->usb_cam.dev && desc.idProduct == PID_NUI_CAMERA) { // If the index given by the user matches our camera index if (nr_cam == index) { res = libusb_open (devs[i], &dev->usb_cam.dev); if (res < 0 || !dev->usb_cam.dev) { FN_ERROR("Could not open camera: %d\n", res); dev->usb_cam.dev = NULL; break; } #ifndef _WIN32 // Detach an existing kernel driver for the device res = libusb_kernel_driver_active(dev->usb_cam.dev, 0); if (res == 1) { res = libusb_detach_kernel_driver(dev->usb_cam.dev, 0); if (res < 0) { FN_ERROR("Could not detach kernel driver for camera: %d\n", res); libusb_close(dev->usb_cam.dev); dev->usb_cam.dev = NULL; break; } } #endif res = libusb_claim_interface (dev->usb_cam.dev, 0); if (res < 0) { FN_ERROR("Could not claim interface on camera: %d\n", res); libusb_close(dev->usb_cam.dev); dev->usb_cam.dev = NULL; break; } } else { nr_cam++; } } // Search for the motor if ((ctx->enabled_subdevices & FREENECT_DEVICE_MOTOR) && !dev->usb_motor.dev && desc.idProduct == PID_NUI_MOTOR) { // If the index given by the user matches our camera index if (nr_mot == index) { res = libusb_open (devs[i], &dev->usb_motor.dev); if (res < 0 || !dev->usb_motor.dev) { FN_ERROR("Could not open motor: %d\n", res); dev->usb_motor.dev = NULL; break; } res = libusb_claim_interface (dev->usb_motor.dev, 0); if (res < 0) { FN_ERROR("Could not claim interface on motor: %d\n", res); libusb_close(dev->usb_motor.dev); dev->usb_motor.dev = NULL; break; } } else { nr_mot++; } } #ifdef BUILD_AUDIO // TODO: check that the firmware has already been loaded; if not, upload firmware. // Search for the audio if ((ctx->enabled_subdevices & FREENECT_DEVICE_AUDIO) && !dev->usb_audio.dev && desc.idProduct == PID_NUI_AUDIO) { // If the index given by the user matches our audio index if (nr_audio == index) { res = libusb_open (devs[i], &dev->usb_audio.dev); if (res < 0 || !dev->usb_audio.dev) { FN_ERROR("Could not open audio: %d\n", res); dev->usb_audio.dev = NULL; break; } res = libusb_claim_interface (dev->usb_audio.dev, 0); if (res < 0) { FN_ERROR("Could not claim interface on audio: %d\n", res); libusb_close(dev->usb_audio.dev); dev->usb_audio.dev = NULL; break; } // Using the device handle that we've claimed, see if this // device has already uploaded firmware (has 2 interfaces). If // not, save the serial number (by reading the appropriate // descriptor), upload the firmware, and then enter a loop // waiting for a device with the same serial number to // reappear. int num_interfaces = fnusb_num_interfaces(&dev->usb_audio); if (num_interfaces == 1) { // Read the serial number from the string descriptor and save it. unsigned char string_desc[256]; // String descriptors are at most 256 bytes res = libusb_get_string_descriptor_ascii(dev->usb_audio.dev, desc.iSerialNumber, string_desc, 256); if (res < 0) { FN_ERROR("Failed to retrieve serial number for audio device in bootloader state\n"); break; } char* audio_serial = strdup((char*)string_desc); FN_SPEW("Uploading firmware to audio device in bootloader state.\n"); res = upload_firmware(&dev->usb_audio); if (res < 0) { FN_ERROR("upload_firmware failed: %d\n", res); break; } libusb_close(dev->usb_audio.dev); dev->usb_audio.dev = NULL; // Wait for the device to reappear. int loops = 0; for (loops = 0; loops < 10; loops++) { // Loop for at most 10 tries. FN_SPEW("Try %d: Looking for new audio device matching serial %s\n", loops, audio_serial); // Scan devices. libusb_device **new_dev_list; int dev_index; ssize_t num_new_devs = libusb_get_device_list(ctx->usb.ctx, &new_dev_list); for (dev_index = 0; dev_index < num_new_devs; ++dev_index) { struct libusb_device_descriptor new_dev_desc; int r; r = libusb_get_device_descriptor (new_dev_list[dev_index], &new_dev_desc); if (r < 0) continue; // If this dev is a Kinect audio device, open device, read serial, and compare. if (new_dev_desc.idVendor == VID_MICROSOFT && new_dev_desc.idProduct == PID_NUI_AUDIO) { FN_SPEW("Matched VID/PID!\n"); libusb_device_handle* new_dev_handle; // Open device r = libusb_open(new_dev_list[dev_index], &new_dev_handle); if (r < 0) continue; // Read serial r = libusb_get_string_descriptor_ascii(new_dev_handle, new_dev_desc.iSerialNumber, string_desc, 256); if (r < 0) { FN_SPEW("Lost new audio device while fetching serial number.\n"); libusb_close(new_dev_handle); continue; } // Compare to expected serial if (r == strlen(audio_serial) && strcmp((char*)string_desc, audio_serial) == 0) { // We found it! r = libusb_claim_interface(new_dev_handle, 0); if (r != 0) { // Ouch, found the device but couldn't claim the interface. FN_SPEW("Device with serial %s reappeared but couldn't claim interface 0\n", audio_serial); libusb_close(new_dev_handle); continue; } // Save the device handle. dev->usb_audio.dev = new_dev_handle; // Verify that we've actually found a device running the right firmware. if (fnusb_num_interfaces(&dev->usb_audio) != 2) { FN_SPEW("Opened audio with matching serial but too few interfaces.\n"); dev->usb_audio.dev = NULL; libusb_close(new_dev_handle); continue; } break; } else { FN_SPEW("Got serial %s, expected serial %s\n", (char*)string_desc, audio_serial); } } } libusb_free_device_list(new_dev_list, 1); // If we found the right device, break out of this loop. if (dev->usb_audio.dev) break; // Sleep for a second to give the device more time to reenumerate. sleep(1); } free(audio_serial); } } else { nr_audio++; } } #endif } libusb_free_device_list (devs, 1); // free the list, unref the devices in it // Check that each subdevice is either opened or not enabled. if ( (dev->usb_cam.dev || !(ctx->enabled_subdevices & FREENECT_DEVICE_CAMERA)) && (dev->usb_motor.dev || !(ctx->enabled_subdevices & FREENECT_DEVICE_MOTOR)) #ifdef BUILD_AUDIO && (dev->usb_audio.dev || !(ctx->enabled_subdevices & FREENECT_DEVICE_AUDIO)) #endif ) { return 0; } else { if (dev->usb_cam.dev) { libusb_release_interface(dev->usb_cam.dev, 0); libusb_close(dev->usb_cam.dev); } if (dev->usb_motor.dev) { libusb_release_interface(dev->usb_motor.dev, 0); libusb_close(dev->usb_motor.dev); } #ifdef BUILD_AUDIO if (dev->usb_audio.dev) { libusb_release_interface(dev->usb_audio.dev, 0); libusb_close(dev->usb_audio.dev); } #endif return -1; } }
void commdev_close(struct commdev_t *commdev) { libusb_release_interface(commdev->handle, 0); libusb_close(commdev->handle); }
FN_INTERNAL int fnusb_list_device_attributes(fnusb_ctx *ctx, struct freenect_device_attributes** attribute_list) { // todo: figure out how to log without freenect_context *attribute_list = NULL; // initialize some return value in case the user is careless. libusb_device **devs; // pointer to pointer of device, used to retrieve a list of devices ssize_t count = libusb_get_device_list (ctx->ctx, &devs); if (count < 0) { return -1; } struct freenect_device_attributes** next_attr = attribute_list; // Pass over the list. For each camera seen, if we already have a camera // for the newest_camera device, allocate a new one and append it to the list, // incrementing num_cams. int num_cams = 0; int i; for (i = 0; i < count; i++) { libusb_device* camera_device = devs[i]; struct libusb_device_descriptor desc; int res = libusb_get_device_descriptor (camera_device, &desc); if (res < 0) { continue; } if (desc.idVendor == VID_MICROSOFT && (desc.idProduct == PID_NUI_CAMERA || desc.idProduct == PID_K4W_CAMERA)) { // Verify that a serial number exists to query. If not, don't touch the device. if (desc.iSerialNumber == 0) { continue; } libusb_device_handle *camera_handle; res = libusb_open(camera_device, &camera_handle); if (res != 0) { continue; } // Read string descriptor referring to serial number. unsigned char serial[256]; // String descriptors are at most 256 bytes. res = libusb_get_string_descriptor_ascii(camera_handle, desc.iSerialNumber, serial, 256); libusb_close(camera_handle); if (res < 0) { continue; } // K4W and 1473 don't provide a camera serial; use audio serial instead. const char* const K4W_1473_SERIAL = "0000000000000000"; if (strncmp((const char*)serial, K4W_1473_SERIAL, 16) == 0) { libusb_device* audio_device = fnusb_find_connected_audio_device(camera_device, devs, count); if (audio_device != NULL) { struct libusb_device_descriptor audio_desc; res = libusb_get_device_descriptor(audio_device, &audio_desc); if (res != 0) { //FN_ERROR("Failed to get audio serial descriptors of K4W or 1473 device: %d\n", res); } else { libusb_device_handle * audio_handle = NULL; res = libusb_open(audio_device, &audio_handle); if (res != 0) { //FN_ERROR("Failed to open audio device for serial of K4W or 1473 device: %d\n", res); } else { res = libusb_get_string_descriptor_ascii(audio_handle, audio_desc.iSerialNumber, serial, 256); libusb_close(audio_handle); if (res != 0) { //FN_ERROR("Failed to get audio serial of K4W or 1473 device: %d\n", res); } } } } } // Add item to linked list. struct freenect_device_attributes* current_attr = (struct freenect_device_attributes*)malloc(sizeof(struct freenect_device_attributes)); memset(current_attr, 0, sizeof(*current_attr)); current_attr->camera_serial = strdup((char*)serial); *next_attr = current_attr; next_attr = &(current_attr->next); num_cams++; } } libusb_free_device_list(devs, 1); return num_cams; }
void minipro_close(minipro_handle_t *handle) { libusb_close(handle->usb_handle); free(handle); }
static int test_device(uint16_t vid, uint16_t pid) { libusb_device_handle *handle; libusb_device *dev; uint8_t bus, port_path[8]; struct libusb_config_descriptor *conf_desc; const struct libusb_endpoint_descriptor *endpoint; int i, j, k, r; int iface, nb_ifaces, first_iface = -1; // For attaching/detaching the kernel driver, if needed int iface_detached = -1; struct libusb_device_descriptor dev_desc; const char* speed_name[5] = { "Unknown", "1.5 Mbit/s (USB LowSpeed)", "12 Mbit/s (USB FullSpeed)", "480 Mbit/s (USB HighSpeed)", "5000 Mbit/s (USB SuperSpeed)"}; char string[128]; uint8_t string_index[3]; // indexes of the string descriptors uint8_t endpoint_in = 0, endpoint_out = 0; // default IN and OUT endpoints printf("Opening device %04X:%04X...\n", vid, pid); handle = libusb_open_device_with_vid_pid(NULL, vid, pid); if (handle == NULL) { perr(" Failed.\n"); return -1; } dev = libusb_get_device(handle); bus = libusb_get_bus_number(dev); if (extra_info) { r = libusb_get_port_path(NULL, dev, port_path, sizeof(port_path)); if (r > 0) { printf("\nDevice properties:\n"); printf(" bus number: %d\n", bus); printf(" port path: %d", port_path[0]); for (i=1; i<r; i++) { printf("->%d", port_path[i]); } printf(" (from root hub)\n"); } r = libusb_get_device_speed(dev); if ((r<0) || (r>4)) r=0; printf(" speed: %s\n", speed_name[r]); } printf("\nReading device descriptor:\n"); CALL_CHECK(libusb_get_device_descriptor(dev, &dev_desc)); printf(" length: %d\n", dev_desc.bLength); printf(" device class: %d\n", dev_desc.bDeviceClass); printf(" S/N: %d\n", dev_desc.iSerialNumber); printf(" VID:PID: %04X:%04X\n", dev_desc.idVendor, dev_desc.idProduct); printf(" bcdDevice: %04X\n", dev_desc.bcdDevice); printf(" iMan:iProd:iSer: %d:%d:%d\n", dev_desc.iManufacturer, dev_desc.iProduct, dev_desc.iSerialNumber); printf(" nb confs: %d\n", dev_desc.bNumConfigurations); // Copy the string descriptors for easier parsing string_index[0] = dev_desc.iManufacturer; string_index[1] = dev_desc.iProduct; string_index[2] = dev_desc.iSerialNumber; printf("\nReading configuration descriptors:\n"); CALL_CHECK(libusb_get_config_descriptor(dev, 0, &conf_desc)); nb_ifaces = conf_desc->bNumInterfaces; printf(" nb interfaces: %d\n", nb_ifaces); if (nb_ifaces > 0) first_iface = conf_desc->usb_interface[0].altsetting[0].bInterfaceNumber; for (i=0; i<nb_ifaces; i++) { printf(" interface[%d]: id = %d\n", i, conf_desc->usb_interface[i].altsetting[0].bInterfaceNumber); for (j=0; j<conf_desc->usb_interface[i].num_altsetting; j++) { printf("interface[%d].altsetting[%d]: num endpoints = %d\n", i, j, conf_desc->usb_interface[i].altsetting[j].bNumEndpoints); printf(" Class.SubClass.Protocol: %02X.%02X.%02X\n", conf_desc->usb_interface[i].altsetting[j].bInterfaceClass, conf_desc->usb_interface[i].altsetting[j].bInterfaceSubClass, conf_desc->usb_interface[i].altsetting[j].bInterfaceProtocol); if ( (conf_desc->usb_interface[i].altsetting[j].bInterfaceClass == LIBUSB_CLASS_MASS_STORAGE) && ( (conf_desc->usb_interface[i].altsetting[j].bInterfaceSubClass == 0x01) || (conf_desc->usb_interface[i].altsetting[j].bInterfaceSubClass == 0x06) ) && (conf_desc->usb_interface[i].altsetting[j].bInterfaceProtocol == 0x50) ) { // Mass storage devices that can use basic SCSI commands test_mode = USE_SCSI; } for (k=0; k<conf_desc->usb_interface[i].altsetting[j].bNumEndpoints; k++) { endpoint = &conf_desc->usb_interface[i].altsetting[j].endpoint[k]; printf(" endpoint[%d].address: %02X\n", k, endpoint->bEndpointAddress); // Use the first interrupt or bulk IN/OUT endpoints as default for testing if ((endpoint->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) & (LIBUSB_TRANSFER_TYPE_BULK | LIBUSB_TRANSFER_TYPE_INTERRUPT)) { if (endpoint->bEndpointAddress & LIBUSB_ENDPOINT_IN) { if (!endpoint_in) endpoint_in = endpoint->bEndpointAddress; } else { if (!endpoint_out) endpoint_out = endpoint->bEndpointAddress; } } printf(" max packet size: %04X\n", endpoint->wMaxPacketSize); printf(" polling interval: %02X\n", endpoint->bInterval); } } } libusb_free_config_descriptor(conf_desc); for (iface = 0; iface < nb_ifaces; iface++) { printf("\nClaiming interface %d...\n", iface); r = libusb_claim_interface(handle, iface); if ((r != LIBUSB_SUCCESS) && libusb_has_capability(LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER) && (libusb_kernel_driver_active(handle, iface) > 0)) { // Try to detach the kernel driver perr(" A kernel driver is active, trying to detach it...\n"); r = libusb_detach_kernel_driver(handle, iface); if (r == LIBUSB_SUCCESS) { iface_detached = iface; printf(" Claiming interface again...\n"); r = libusb_claim_interface(handle, iface); } } if (r != LIBUSB_SUCCESS) { perr(" Failed.\n"); } } printf("\nReading string descriptors:\n"); for (i=0; i<3; i++) { if (string_index[i] == 0) { continue; } if (libusb_get_string_descriptor_ascii(handle, string_index[i], (unsigned char*)string, 128) >= 0) { printf(" String (0x%02X): \"%s\"\n", string_index[i], string); } } // Read the OS String Descriptor if (libusb_get_string_descriptor_ascii(handle, 0xEE, (unsigned char*)string, 128) >= 0) { printf(" String (0x%02X): \"%s\"\n", 0xEE, string); // If this is a Microsoft OS String Descriptor, // attempt to read the WinUSB extended Feature Descriptors if (strncmp(string, "MSFT100", 7) == 0) read_ms_winsub_feature_descriptors(handle, string[7], first_iface); } switch(test_mode) { case USE_PS3: CALL_CHECK(display_ps3_status(handle)); break; case USE_XBOX: CALL_CHECK(display_xbox_status(handle)); CALL_CHECK(set_xbox_actuators(handle, 128, 222)); msleep(2000); CALL_CHECK(set_xbox_actuators(handle, 0, 0)); break; case USE_HID: test_hid(handle, endpoint_in); break; case USE_SCSI: CALL_CHECK(test_mass_storage(handle, endpoint_in, endpoint_out)); case USE_GENERIC: break; } printf("\n"); for (iface = 0; iface<nb_ifaces; iface++) { printf("Releasing interface %d...\n", iface); libusb_release_interface(handle, iface); } if (iface_detached >= 0) { printf("Re-attaching kernel driver...\n"); libusb_attach_kernel_driver(handle, iface_detached); } printf("Closing device...\n"); libusb_close(handle); return 0; }
GSM_Error GSM_USB_Probe(GSM_StateMachine *s, GSM_USB_Match_Function matcher) { libusb_device **devs; libusb_device *dev; GSM_Device_USBData *d = &s->Device.Data.USB; ssize_t cnt; int rc; int i = 0; struct libusb_device_descriptor desc; struct libusb_config_descriptor *config; GSM_Error error; int vendor = -1, product = -1, bus = -1, deviceid = -1; char *serial = NULL; char buffer[300]; gboolean do_match; /* Device selection */ GSM_USB_ParseDevice(s, &vendor, &product, &bus, &deviceid, &serial); do_match = (vendor != -1 || product != -1 || bus != -1 || deviceid != -1 || serial != NULL); cnt = libusb_get_device_list(d->context, &devs); if (cnt < 0) { smprintf(s, "Failed to list USB devices (%d)!\n", (int)cnt); return GSM_USB_Error(s, cnt); } /* Check all devices */ i = 0; while ((dev = devs[i++]) != NULL) { rc = libusb_get_device_descriptor(dev, &desc); if (rc < 0) { smprintf(s, "Failed to get device descriptor (%d)!\n", rc); GSM_USB_Error(s, rc); continue; } smprintf(s, "Checking %04x:%04x (bus %d, device %d)\n", desc.idVendor, desc.idProduct, libusb_get_bus_number(dev), libusb_get_device_address(dev)); if (do_match) { if (vendor != -1 && vendor != desc.idVendor) { smprintf(s, "Vendor does not match requested 0x%04x, ignoring\n", vendor); continue; } if (product != -1 && product != desc.idProduct) { smprintf(s, "Product does not match requested 0x%04x, ignoring\n", product); continue; } if (bus != -1 && bus != libusb_get_bus_number(dev)) { smprintf(s, "Bus does not match requested %d, ignoring\n", bus); continue; } if (deviceid != -1 && deviceid != libusb_get_device_address(dev)) { smprintf(s, "Device address does not match requested %d, ignoring\n", deviceid); continue; } if (serial != NULL && desc.iSerialNumber) { rc = libusb_open(dev, &d->handle); if (rc != 0) { smprintf(s, "Failed to read serial!\n"); } else { libusb_get_string_descriptor_ascii(d->handle, desc.iSerialNumber, buffer, sizeof(buffer) - 1); smprintf(s, "Device serial: %s\n", buffer); libusb_close(d->handle); if (strcasecmp(buffer, serial) != 0) { smprintf(s, "Device serial does not match requested %s, ignoring\n", serial); continue; } } } } if (matcher(s, dev, &desc)) { break; } } if (dev == NULL) { error = ERR_DEVICENOTEXIST; goto done; } smprintf(s, "Trying to open device, config=%d, c_iface=%d, c_alt=%d, d_iface=%d, d_alt=%d\n", d->configuration, d->control_iface, d->control_altsetting, d->data_iface, d->data_altsetting); rc = libusb_open(dev, &d->handle); if (rc != 0) { d->handle = NULL; error = GSM_USB_Error(s, rc); goto done; } /* Unhook kernel driver */ rc = libusb_get_active_config_descriptor(dev, &config); if (rc != 0) { smprintf(s, "Failed to get current device configuration!\n"); libusb_close(d->handle); d->handle = NULL; error = GSM_USB_Error(s, rc); goto done; } /* Do we have to change configuration? */ if (config->bConfigurationValue != d->configuration) { smprintf(s, "Will change configuration, unhooking all interfaces!\n"); for (i = 0; i < config->bNumInterfaces; i++) { if (libusb_kernel_driver_active(d->handle, i) == 1) { smprintf(s, "Detaching kernel driver from interface %d\n", i); rc = libusb_detach_kernel_driver(d->handle, i); if (rc != 0) { smprintf(s, "Failed to detach kernel driver!\n"); libusb_free_config_descriptor(config); libusb_close(d->handle); d->handle = NULL; error = GSM_USB_Error(s, rc); goto done; } } } smprintf(s, "Configuring USB device...\n"); rc = libusb_set_configuration(d->handle, d->configuration); if (rc != 0) { smprintf(s, "Failed to set device configuration %d (%d)!\n", d->configuration, rc); libusb_free_config_descriptor(config); libusb_close(d->handle); d->handle = NULL; error = GSM_USB_Error(s, rc); goto done; } } else { smprintf(s, "Configuration change not required, unhooking only required interfaces!\n"); if (libusb_kernel_driver_active(d->handle, d->control_iface) == 1) { smprintf(s, "Detaching kernel driver from interface %d\n", d->control_iface); rc = libusb_detach_kernel_driver(d->handle, d->control_iface); if (rc != 0) { smprintf(s, "Failed to detach kernel driver!\n"); libusb_free_config_descriptor(config); libusb_close(d->handle); d->handle = NULL; error = GSM_USB_Error(s, rc); goto done; } } if (libusb_kernel_driver_active(d->handle, d->data_iface) == 1) { smprintf(s, "Detaching kernel driver from interface %d\n", d->data_iface); rc = libusb_detach_kernel_driver(d->handle, d->data_iface); if (rc != 0) { smprintf(s, "Failed to detach kernel driver!\n"); libusb_free_config_descriptor(config); libusb_close(d->handle); d->handle = NULL; error = GSM_USB_Error(s, rc); goto done; } } } libusb_free_config_descriptor(config); smprintf(s, "Claiming USB control interface...\n"); rc = libusb_claim_interface(d->handle, d->control_iface); if (rc != 0) { smprintf(s, "Failed to set claim control interface %d (%d)!\n", d->control_iface, rc); libusb_close(d->handle); d->handle = NULL; error = GSM_USB_Error(s, rc); goto done; } smprintf(s, "Configuring USB control interface...\n"); rc = libusb_set_interface_alt_setting(d->handle, d->control_iface, d->control_altsetting); if (rc != 0) { smprintf(s, "Failed to set control alt setting %d (%d)!\n", d->control_altsetting, rc); libusb_close(d->handle); d->handle = NULL; error = GSM_USB_Error(s, rc); goto done; } smprintf(s, "Claiming USB data interface...\n"); rc = libusb_claim_interface(d->handle, d->data_iface); if (rc != 0) { smprintf(s, "Failed to set claim data interface %d (%d)!\n", d->data_iface, rc); libusb_close(d->handle); d->handle = NULL; error = GSM_USB_Error(s, rc); goto done; } smprintf(s, "Configuring USB data interface...\n"); rc = libusb_set_interface_alt_setting(d->handle, d->data_iface, d->data_altsetting); if (rc != 0) { smprintf(s, "Failed to set data alt setting %d (%d)!\n", d->data_altsetting, rc); libusb_close(d->handle); d->handle = NULL; error = GSM_USB_Error(s, rc); goto done; } smprintf(s, "Connected!\n"); error = ERR_NONE; done: return error; }
TankChassis::~TankChassis() { libusb_release_interface(devh, 0); libusb_close(devh); libusb_exit(0); }
void usb_device_close(device_t *dev) { libusb_release_interface(dev->handle, 0); libusb_close(dev->handle); free(dev); }
int main (int argc, char **argv) { int flag; libusb_device_handle *udev = NULL; struct tm calDate; int ch; int temp; int transferred; int i, j; int tc_type; uint8_t input; uint8_t channel, gain, rate, mode, flags; char serial[9]; uint16_t version[4]; float cjc[2]; int queue_index; int data; int ret; double table_AIN[NGAINS_2408][2]; double table_AO[NCHAN_AO_2408][2]; float table_CJCGrad[nCJCGrad_2408]; AInScanQueue scanQueue; int usb2408_2AO = FALSE; double voltage; double temperature; double frequency; double sine[512]; int16_t sdata[512]; // holds 16 bit signed analog output data int32_t idata[512]; // holds 24 bit signed analog input data uint8_t status; uint16_t depth; uint16_t count; udev = NULL; ret = libusb_init(NULL); if (ret < 0) { perror("usb_device_find_USB_MCC: Failed to initialize libusb"); exit(1); } if ((udev = usb_device_find_USB_MCC(USB2408_PID, NULL))) { printf("Success, found a USB 2408!\n"); } else if ((udev = usb_device_find_USB_MCC(USB2408_2AO_PID, NULL))) { printf("Success, found a USB 2408_2AO!\n"); usb2408_2AO = TRUE; } else { printf("Failure, did not find a USB 2408 or 2408_2AO!\n"); return 0; } //print out the wMaxPacketSize. Should be 64 printf("wMaxPacketSize = %d\n", usb_get_max_packet_size(udev,0)); usbBuildGainTable_USB2408(udev, table_AIN); for (i = 0; i < NGAINS_2408; i++) { printf("Gain: %d Slope = %lf Offset = %lf\n", i, table_AIN[i][0], table_AIN[i][1]); } printf("\n"); usbBuildCJCGradientTable_USB2408(udev, table_CJCGrad); for (i = 0; i < nCJCGrad_2408; i++) { printf("Ch: %d CJC gradient = %lf\n", i, table_CJCGrad[i]); } if (usb2408_2AO) { usbBuildGainTable_USB2408_2AO(udev, table_AO); printf("\n"); for (i = 0; i < NCHAN_AO_2408; i++) { printf("VDAC%d: Slope = %lf Offset = %lf\n", i, table_AO[i][0], table_AO[i][1]); } } usbCalDate_USB2408(udev, &calDate); printf("\n"); printf("MFG Calibration date = %s\n", asctime(&calDate)); while(1) { printf("\nUSB 2408 Testing\n"); printf("----------------\n"); printf("Hit 'b' to blink\n"); printf("Hit 'c' to test counter\n"); printf("Hit 'C' to test continuous sampling at 1000 Hz.\n"); printf("Hit 'd' to test digitial IO\n"); printf("Hit 'i' to test Analog Input\n"); printf("Hit 'I' to test Analog Input Scan\n"); printf("Hit 'j' read CJC sensors.\n"); printf("Hit 'o' to test Analog Output\n"); printf("Hit 'O' to test Analog Output Scan\n"); printf("Hit 'r' to reset the device\n"); printf("Hit 's' to get serial number\n"); printf("Hit 'S' to get Status\n"); printf("Hit 't' to get TC temperature\n"); printf("Hit 'v' to get version numbers\n"); printf("Hit 'e' to exit\n"); while((ch = getchar()) == '\0' || ch == '\n'); switch(ch) { case 'b': /* test to see if led blinks */ printf("Enter number or times to blink: "); scanf("%d", &temp); usbBlink_USB2408(udev, temp); break; case 'c': usbCounterInit_USB2408(udev, COUNTER0); printf("Connect DO0 to CTR0\n"); toContinue(); for (i = 0; i < 100; i++) { usbDOut_USB2408(udev, 0x0, 0); usbDOut_USB2408(udev, 0xff, 0); } printf("Count = %d. Should read 100.\n", usbCounter_USB2408(udev, COUNTER0)); break; case 'C': printf("Testing USB-2408 Analog Input Scan in Continuous mode 8 channels\n"); printf("Hit any key to exit\n"); usbAInScanStop_USB2408(udev); count = 0; // for continuous mode rate = HZ1000; mode = DIFFERENTIAL; scanQueue.count = 8; for (i = 0; i < 8; i++ ) { scanQueue.queue[i].channel = i; scanQueue.queue[i].mode = mode; scanQueue.queue[i].range = BP_10V; scanQueue.queue[i].rate = rate; } usbAInScanQueueWrite_USB2408(udev, &scanQueue); for (i = 0; i < 512; i++) { idata[i] = 0xdeadbeef; } usbAInScanStart_USB2408(udev, 100, count, 15); flag = fcntl(fileno(stdin), F_GETFL); fcntl(0, F_SETFL, flag | O_NONBLOCK); j = 0; do { ret = libusb_bulk_transfer(udev, LIBUSB_ENDPOINT_IN|1, (unsigned char *) idata, 512*4, &transferred, 1000); if (ret < 0) { perror(" Continuous scan error in libusb_bulk_transfer"); } for (i = 0; i < 512; i++) { queue_index = idata[i] >> 24; // MSB of data contains the queue index; gain = scanQueue.queue[queue_index].range; channel = scanQueue.queue[queue_index].channel; data = int24ToInt(idata[i]); // convert from signed 24 to signed 32 data = data*table_AIN[gain][0] + table_AIN[gain][1]; // correct for non-linearities in A/D printf("Sample %d Index %d Channel %d gain = %d raw = %#x voltage = %f\n", i, queue_index, channel, gain, idata[i], volts_USB2408(gain, data)); } // printf("bulk transfer = %d\n", j); // Each transfer contains 512 samples or 64 scans j++; } while (!isalpha(getchar())); fcntl(fileno(stdin), F_SETFL, flag); usbAInScanStop_USB2408(udev); usbReset_USB2408(udev); libusb_close(udev); sleep(2); // let things settle down. break; case 'd': printf("\nTesting Digital I/O....\n"); do { printf("Enter a number [0-0xff] : " ); scanf("%x", &temp); usbDOut_USB2408(udev, (uint8_t)temp, 0); input = usbDOutR_USB2408(udev, 0); printf("The number you entered = %#x\n\n",input); input = usbDIn_USB2408(udev, 0); printf("The number you entered = %#x\n\n",input); } while (toContinue()); break; case 'e': cleanup_USB2408(udev); return 0; case 'i': printf("Input channel [0-7]: "); scanf("%hhd", &channel); printf("Gain Range for channel %d: 1 = 10V 2 = 5V 2 = 2.5V Differential: ", channel); while((ch = getchar()) == '\0' || ch == '\n'); switch(ch) { case '1': gain = BP_10V; break; case '2': gain = BP_5V; break; case '3': gain = BP_2_5V; break; default: gain = BP_10V; break; } rate = HZ1000; mode = DIFFERENTIAL; for (i = 0; i < 20; i++) { data = usbAIn_USB2408(udev, channel, mode, gain, rate, &flags); data = data*table_AIN[gain][0] + table_AIN[gain][1]; printf("Channel %d Sample[%d] = %#x Volts = %lf\n", channel, i, data, volts_USB2408(gain, data)); usleep(50000); } break; case 'I': printf("Testing USB-2408 Analog Input Scan\n"); usbAInScanStop_USB2408(udev); printf("Input channel [0-7]: "); scanf("%hhd", &channel); printf("Input the number of scans (1-512): "); scanf("%hd", &count); printf("Gain Range for channel %d: 1 = 10V 2 = 5V 3 = 2.5V Differential: ", channel); while((ch = getchar()) == '\0' || ch == '\n'); switch(ch) { case '1': gain = BP_10V; break; case '2': gain = BP_5V; break; case '3': gain = BP_2_5V; break; default: gain = BP_10V; break; } rate = HZ1000; mode = DIFFERENTIAL; scanQueue.count = 1; scanQueue.queue[0].channel = channel; scanQueue.queue[0].mode = mode; scanQueue.queue[0].range = gain; scanQueue.queue[0].rate = rate; for (i = 0; i < 512; i++) { idata[i] = 0xdeadbeef; } usbAInScanQueueWrite_USB2408(udev, &scanQueue); usbAInScanStart_USB2408(udev, 900, count, 15); usbAInScanRead_USB2408(udev, count, 1, idata); usbAInScanStop_USB2408(udev); usbAInScanQueueRead_USB2408(udev, &scanQueue); for (i = 0; i < count; i++) { queue_index = idata[i] >> 24; // MSB of data contains the queue index; gain = scanQueue.queue[queue_index].range; channel = scanQueue.queue[queue_index].channel; data = int24ToInt(idata[i]); // convert from signed 24 to signed 32 data = data*table_AIN[gain][0] + table_AIN[gain][1]; // correct for non-linearities in A/D printf("Sample %d Index %d Channel %d gain = %d raw = %#x voltage = %f\n", i, queue_index, channel, gain, idata[i], volts_USB2408(gain, data)); } break; case 'j': usbCJC_USB2408(udev, cjc); for (i = 0; i < 2; i++) { printf("CJC sensor[%d] = %f degree C.\n", i, cjc[i]); } break; case 'O': if (!usb2408_2AO) { printf("Analog output only on the USB-2408-2AO model.\n"); break; } channel = 0; printf("Test of Analog Output Scan.\n"); printf("Hook scope up to VDAC 0\n"); printf("Enter desired frequency of sine wave [Hz]: "); scanf("%lf", &frequency); for (i = 0; i < 512; i ++) { sine[i] = 10*sin(2.*M_PI*i/128.); } voltsTos16_USB2408_2AO(sine, sdata, 512, table_AO[channel]); usbAOutScanStop_USB2408_2AO(udev); usbAOutScanStart_USB2408_2AO(udev, 128.*frequency, 0, (1 << channel)); printf("Hit \'s <CR>\' to stop "); flag = fcntl(fileno(stdin), F_GETFL); fcntl(0, F_SETFL, flag | O_NONBLOCK); do { libusb_bulk_transfer(udev, LIBUSB_ENDPOINT_OUT|1, (unsigned char *) sdata, sizeof(sdata), &transferred, 1000); } while (!isalpha(getchar())); fcntl(fileno(stdin), F_SETFL, flag); usbAOutScanStop_USB2408_2AO(udev); break; case 'o': if (!usb2408_2AO) { printf("Analog output only on the USB-2408-2AO model.\n"); break; } printf("output value on VDAC 0\n"); do { printf("Enter output voltage [-10 to 10]: "); scanf("%lf", &voltage); usbAOut_USB2408_2AO(udev, 0, voltage, table_AO); } while (toContinue()); break; case 'r': usbReset_USB2408(udev); return 0; break; case 's': usbGetSerialNumber_USB2408(udev, serial); printf("Serial number = %s\n", serial); break; case 'S': printf("Status = %#x\n", usbStatus_USB2408(udev)); status = usbAInScanStatus_USB2408(udev, &depth); printf("Analog In status = %#x, depth = %d\n", status, depth); break; case 't': printf("Input channel [0-7]: "); scanf("%hhd", &channel); printf("Input Thermocouple type [J,K,R,S,T,N,E,B]: "); while((ch = getchar()) == '\0' || ch == '\n'); switch(ch) { case 'J': case 'j': tc_type = TYPE_J; break; case 'K': case 'k': tc_type = TYPE_K; break; case 'R': case 'r': tc_type = TYPE_R; break; case 'S': case 's': tc_type = TYPE_S; break; case 'T': case 't': tc_type = TYPE_T; break; case 'N': case 'n': tc_type = TYPE_N; break; case 'E': case 'e': tc_type = TYPE_E; break; case 'B': case 'b': tc_type = TYPE_B; break; default: tc_type = TYPE_J; break; } temperature = tc_temperature_USB2408(udev, tc_type, channel); printf("Temperature = %.3f C %.3f F\n", temperature, temperature*9./5. + 32.); break; case 'v': usbGetVersion_USB2408(udev, version); printf("USB micro firmware version = %x.%2.2x\n", version[0]/0x100, version[0]%0x100); printf("USB update firmware version = %x.%2.2x\n", version[1]/0x100, version[1]%0x100); printf("isolated micro firmware version = %x.%2.2x\n", version[2]/0x100, version[2]%0x100); printf("isolated update firmware version = %x.%2.2x\n", version[3]/0x100, version[3]%0x100); break; default: break; } } }
int main(void) { struct sigaction sigact; int r = 1; r = libusb_init(NULL); if (r < 0) { fprintf(stderr, "failed to initialise libusb\n"); exit(1); } r = find_dpfp_device(); if (r < 0) { fprintf(stderr, "Could not find/open device\n"); goto out; } r = libusb_claim_interface(devh, 0); if (r < 0) { fprintf(stderr, "usb_claim_interface error %d %s\n", r, strerror(-r)); goto out; } printf("claimed interface\n"); r = print_f0_data(); if (r < 0) goto out_release; r = do_init(); if (r < 0) goto out_deinit; sigact.sa_handler = sighandler; sigemptyset(&sigact.sa_mask); sigact.sa_flags = 0; sigaction(SIGINT, &sigact, NULL); sigaction(SIGTERM, &sigact, NULL); sigaction(SIGQUIT, &sigact, NULL); r = pthread_create(&poll_thread, NULL, poll_thread_main, NULL); if (r) goto out_deinit; r = alloc_transfers(); if (r < 0) { request_exit(1); pthread_join(poll_thread, NULL); goto out_deinit; } r = init_capture(); if (r < 0) { request_exit(1); pthread_join(poll_thread, NULL); goto out_deinit; } while (!do_exit) { pthread_mutex_lock(&exit_cond_lock); pthread_cond_wait(&exit_cond, &exit_cond_lock); pthread_mutex_unlock(&exit_cond_lock); } printf("shutting down...\n"); pthread_join(poll_thread, NULL); r = libusb_cancel_transfer(irq_transfer); if (r < 0) { request_exit(1); goto out_deinit; } r = libusb_cancel_transfer(img_transfer); if (r < 0) { request_exit(1); goto out_deinit; } while (img_transfer || irq_transfer) if (libusb_handle_events(NULL) < 0) break; if (do_exit == 1) r = 0; else r = 1; out_deinit: libusb_free_transfer(img_transfer); libusb_free_transfer(irq_transfer); set_mode(0); set_hwstat(0x80); out_release: libusb_release_interface(devh, 0); out: libusb_close(devh); libusb_exit(NULL); return r >= 0 ? r : -r; }
static GSList *scan(struct sr_dev_driver *di, GSList *options) { struct sr_dev_inst *sdi; struct drv_context *drvc; struct dev_context *devc; const struct zp_model *prof; struct libusb_device_descriptor des; struct libusb_device_handle *hdl; libusb_device **devlist; GSList *devices; int ret, i, j; char serial_num[64], connection_id[64]; (void)options; drvc = di->context; devices = NULL; /* Find all ZEROPLUS analyzers and add them to device list. */ libusb_get_device_list(drvc->sr_ctx->libusb_ctx, &devlist); /* TODO: Errors. */ for (i = 0; devlist[i]; i++) { libusb_get_device_descriptor(devlist[i], &des); if ((ret = libusb_open(devlist[i], &hdl)) < 0) continue; if (des.iSerialNumber == 0) { serial_num[0] = '\0'; } else if ((ret = libusb_get_string_descriptor_ascii(hdl, des.iSerialNumber, (unsigned char *) serial_num, sizeof(serial_num))) < 0) { sr_warn("Failed to get serial number string descriptor: %s.", libusb_error_name(ret)); continue; } libusb_close(hdl); usb_get_port_path(devlist[i], connection_id, sizeof(connection_id)); prof = NULL; for (j = 0; j < zeroplus_models[j].vid; j++) { if (des.idVendor == zeroplus_models[j].vid && des.idProduct == zeroplus_models[j].pid) { prof = &zeroplus_models[j]; } } /* Skip if the device was not found. */ if (!prof) continue; sr_info("Found ZEROPLUS %s.", prof->model_name); /* Register the device with libsigrok. */ sdi = g_malloc0(sizeof(struct sr_dev_inst)); sdi->status = SR_ST_INACTIVE; sdi->vendor = g_strdup(VENDOR_NAME); sdi->model = g_strdup(prof->model_name); sdi->driver = di; sdi->serial_num = g_strdup(serial_num); sdi->connection_id = g_strdup(connection_id); /* Allocate memory for our private driver context. */ devc = g_malloc0(sizeof(struct dev_context)); sdi->priv = devc; devc->prof = prof; devc->num_channels = prof->channels; #ifdef ZP_EXPERIMENTAL devc->max_sample_depth = 128 * 1024; devc->max_samplerate = 200; #else devc->max_sample_depth = prof->sample_depth * 1024; devc->max_samplerate = prof->max_sampling_freq; #endif devc->max_samplerate *= SR_MHZ(1); devc->memory_size = MEMORY_SIZE_8K; // memset(devc->trigger_buffer, 0, NUM_TRIGGER_STAGES); /* Fill in channellist according to this device's profile. */ for (j = 0; j < devc->num_channels; j++) sr_channel_new(sdi, j, SR_CHANNEL_LOGIC, TRUE, channel_names[j]); devices = g_slist_append(devices, sdi); drvc->instances = g_slist_append(drvc->instances, sdi); sdi->inst_type = SR_INST_USB; sdi->conn = sr_usb_dev_inst_new( libusb_get_bus_number(devlist[i]), libusb_get_device_address(devlist[i]), NULL); } libusb_free_device_list(devlist, 1); return devices; }
/* Configure CH341A, find the device and set the default interface. */ int32_t ch341Configure(uint16_t vid, uint16_t pid) { struct libusb_device *dev; int32_t ret; struct sigaction sa; uint8_t desc[0x12]; if (devHandle != NULL) { fprintf(stderr, "Call ch341Release before re-configure\n"); return -1; } ret = libusb_init(NULL); if(ret < 0) { fprintf(stderr, "Couldn't initialise libusb\n"); return -1; } libusb_set_option(NULL, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_INFO); if(!(devHandle = libusb_open_device_with_vid_pid(NULL, vid, pid))) { fprintf(stderr, "Couldn't open device [%04x:%04x].\n", vid, pid); return -1; } if(!(dev = libusb_get_device(devHandle))) { fprintf(stderr, "Couldn't get bus number and address.\n"); goto close_handle; } if(libusb_kernel_driver_active(devHandle, 0)) { ret = libusb_detach_kernel_driver(devHandle, 0); if(ret) { fprintf(stderr, "Failed to detach kernel driver: '%s'\n", strerror(-ret)); goto close_handle; } } ret = libusb_claim_interface(devHandle, 0); if(ret) { fprintf(stderr, "Failed to claim interface 0: '%s'\n", strerror(-ret)); goto close_handle; } ret = libusb_get_descriptor(devHandle, LIBUSB_DT_DEVICE, 0x00, desc, 0x12); if(ret < 0) { fprintf(stderr, "Failed to get device descriptor: '%s'\n", strerror(-ret)); goto release_interface; } printf("Device reported its revision [%d.%02d]\n", desc[12], desc[13]); sa.sa_handler = &sig_int; sa.sa_flags = SA_RESTART; sigfillset(&sa.sa_mask); if (sigaction(SIGINT, &sa, &saold) == -1) { perror("Error: cannot handle SIGINT"); // Should not happen } return 0; release_interface: libusb_release_interface(devHandle, 0); close_handle: libusb_close(devHandle); devHandle = NULL; return -1; }
static int udevman_unregister_udevice(IUDEVMAN * idevman, int bus_number, int dev_number) { UDEVMAN * udevman = (UDEVMAN *) idevman; UDEVICE * pdev, * dev; int ret = 0, err = 0; dev = (UDEVICE *)udevman_get_udevice_by_addr(idevman, bus_number, dev_number); idevman->loading_lock(idevman); idevman->rewind(idevman); while (idevman->has_next(idevman) != 0) { pdev = (UDEVICE *)idevman->get_next(idevman); if (pdev == dev) /* device exists */ { /* set previous device to point to next device */ if (dev->prev != NULL) { /* unregistered device is not the head */ pdev = dev->prev; pdev->next = dev->next; } else { /* unregistered device is the head, update head */ udevman->head = (IUDEVICE*)dev->next; } /* set next device to point to previous device */ if (dev->next != NULL) { /* unregistered device is not the tail */ pdev = (UDEVICE *)dev->next; pdev->prev = dev->prev; } else { /* unregistered device is the tail, update tail */ udevman->tail = (IUDEVICE*)dev->prev; } udevman->device_num--; break; } } idevman->loading_unlock(idevman); if (dev) { /* reset device */ if (err != LIBUSB_ERROR_NO_DEVICE) { ret = libusb_reset_device(dev->libusb_handle); if (ret<0){ LLOGLN(10, ("libusb_reset_device: ERROR!!ret:%d\n", ret)); } } /* release all interface and attach kernel driver */ dev->iface.attach_kernel_driver((IUDEVICE*)dev); if(dev->request_queue) zfree(dev->request_queue); /* free the config descriptor that send from windows */ msusb_msconfig_free(dev->MsConfig); libusb_close (dev->libusb_handle); libusb_close (dev->hub_handle); sem_destroy(&dev->sem_id); /* free device info */ if (dev->devDescriptor) zfree(dev->devDescriptor); if (dev) zfree(dev); return 1; /* unregistration successful */ } /* if we reach this point, the device wasn't found */ return 0; }
static int open_device(const struct bladerf_devinfo *info, libusb_context *context, libusb_device *libusb_dev_in, struct bladerf_lusb **dev_out) { int status; struct bladerf_lusb *dev; *dev_out = NULL; dev = (struct bladerf_lusb *) calloc(1, sizeof(dev[0])); if (dev == NULL) { log_debug("Failed to allocate handle for instance %d.\n", info->instance); /* Report "no device" so we could try again with * another matching device */ return BLADERF_ERR_NODEV; } dev->context = context; dev->dev = libusb_dev_in; status = libusb_open(libusb_dev_in, &dev->handle); if (status < 0) { log_debug("Failed to open device instance %d: %s\n", info->instance, libusb_error_name(status)); status = error_conv(status); goto out; } status = libusb_claim_interface(dev->handle, 0); if (status < 0) { log_debug("Failed to claim interface 0 for instance %d: %s\n", info->instance, libusb_error_name(status)); status = error_conv(status); goto out; } status = create_device_mutex(info, dev); if (status < 0) { log_debug("Failed to get device mutex for instance %d: %s\n", info->instance, bladerf_strerror(status)); status = error_conv(status); goto out; } out: if (status != 0) { if (dev->handle != NULL) { libusb_close(dev->handle); } free(dev); } else { *dev_out = dev; } return status; }
HANDLE LJUSB_OpenDevice(UINT DevNum, unsigned int dwReserved, unsigned long ProductID) { (void)dwReserved; libusb_device **devs = NULL, *dev = NULL; struct libusb_device_handle *devh = NULL; struct libusb_device_descriptor desc; ssize_t cnt = 0; int r = 1; unsigned int i = 0; unsigned int ljFoundCount = 0; HANDLE handle = NULL; if (!gIsLibUSBInitialized) { r = libusb_init(&gLJContext); if (r < 0) { fprintf(stderr, "failed to initialize libusb\n"); LJUSB_libusbError(r); return NULL; } gIsLibUSBInitialized = true; } cnt = libusb_get_device_list(gLJContext, &devs); if (cnt < 0) { fprintf(stderr, "failed to get device list\n"); LJUSB_libusbError(cnt); LJUSB_libusb_exit(); return NULL; } while ((dev = devs[i++]) != NULL) { #if LJ_DEBUG fprintf(stderr, "LJUSB_OpenDevice: calling libusb_get_device_descriptor\n"); #endif r = libusb_get_device_descriptor(dev, &desc); if (r < 0) { fprintf(stderr, "failed to get device descriptor"); LJUSB_libusbError(r); LJUSB_libusb_exit(); return NULL; } if (LJ_VENDOR_ID == desc.idVendor && ProductID == desc.idProduct) { ljFoundCount++; if (ljFoundCount == DevNum) { // Found the one requested r = libusb_open(dev, &devh); if (r < 0) { LJUSB_libusbError(r); return NULL; } // Test if the kernel driver has the device. // Should only be true for HIDs. if (libusb_kernel_driver_active(devh, 0)) { #if LJ_DEBUG fprintf(stderr, "Kernel Driver was active, detaching...\n"); #endif // Detaches U12s from kernel driver. r = libusb_detach_kernel_driver(devh, 0); // Check the return value if ( r != 0 ) { fprintf(stderr, "failed to detach from kernel driver. Error Number: %i", r); return NULL; } } r = libusb_claim_interface(devh, 0); if (r < 0) { LJUSB_libusbError(r); libusb_close(devh); return NULL; } handle = (HANDLE) devh; #if LJ_DEBUG fprintf(stderr, "LJUSB_OpenDevice: Found handle for product ID %ld\n", ProductID); #endif break; } } } libusb_free_device_list(devs, 1); if (handle != NULL) { //We found a device, now check if it meets the minimum firmware requirement if (!LJUSB_isMinFirmware(handle, ProductID)) { //Does not meet the requirement. Close device and return an invalid handle. LJUSB_CloseDevice(handle); return NULL; } } #if LJ_DEBUG fprintf(stderr, "LJUSB_OpenDevice: Returning handle\n"); #endif return handle; }
FN_INTERNAL int fnusb_open_subdevices(freenect_device *dev, int index) { freenect_context *ctx = dev->parent; dev->device_does_motor_control_with_audio = 0; dev->motor_control_with_audio_enabled = 0; dev->usb_cam.parent = dev; dev->usb_cam.dev = NULL; dev->usb_motor.parent = dev; dev->usb_motor.dev = NULL; dev->usb_audio.parent = dev; dev->usb_audio.dev = NULL; libusb_device **devs; // pointer to pointer of device, used to retrieve a list of devices ssize_t cnt = libusb_get_device_list (dev->parent->usb.ctx, &devs); //get the list of devices if (cnt < 0) return -1; int i = 0, nr_cam = 0, nr_mot = 0; int nr_audio = 0; int res; struct libusb_device_descriptor desc; for (i = 0; i < cnt; i++) { int r = libusb_get_device_descriptor (devs[i], &desc); if (r < 0) continue; if (desc.idVendor != VID_MICROSOFT) continue; res = 0; // Search for the camera if ((ctx->enabled_subdevices & FREENECT_DEVICE_CAMERA) && !dev->usb_cam.dev && (desc.idProduct == PID_NUI_CAMERA || desc.idProduct == PID_K4W_CAMERA)) { // If the index given by the user matches our camera index if (nr_cam == index) { dev->usb_cam.VID = desc.idVendor; dev->usb_cam.PID = desc.idProduct; res = libusb_open (devs[i], &dev->usb_cam.dev); if (res < 0 || !dev->usb_cam.dev) { FN_ERROR("Could not open camera: %d\n", res); dev->usb_cam.dev = NULL; break; } if (desc.idProduct == PID_K4W_CAMERA || desc.bcdDevice != fn_le32(267)) { freenect_device_flags requested_devices = ctx->enabled_subdevices; // Not the 1414 kinect so remove the motor flag, this should preserve the audio flag if set ctx->enabled_subdevices = (freenect_device_flags)(ctx->enabled_subdevices & ~FREENECT_DEVICE_MOTOR); ctx->zero_plane_res = 334; dev->device_does_motor_control_with_audio = 1; // set the LED for non 1414 devices to keep the camera alive for some systems which get freezes libusb_device * audioDevice = fnusb_find_connected_audio_device(devs[i], devs, cnt); if (audioDevice != NULL) { libusb_device_handle * audioHandle = NULL; res = libusb_open(audioDevice, &audioHandle); if (res != 0) { FN_ERROR("Failed to set the LED of K4W or 1473 device: %d\n", res); } else { // we need to do this as it is possible that the device was not closed properly in a previous session // if we don't do this and the device wasn't closed properly - it can cause infinite hangs on LED and TILT functions libusb_reset_device(audioHandle); libusb_close(audioHandle); res = libusb_open(audioDevice, &audioHandle); if (res == 0) { res = libusb_claim_interface(audioHandle, 0); if (res != 0) { FN_ERROR("Unable to claim interface %d\n", res); } else { fnusb_set_led_alt(audioHandle, ctx, LED_GREEN); libusb_release_interface(audioHandle, 0); } libusb_close(audioHandle); } } } // for newer devices we need to enable the audio device for motor control // we only do this though if motor has been requested. if ((requested_devices & FREENECT_DEVICE_MOTOR) && (requested_devices & FREENECT_DEVICE_AUDIO) == 0) { ctx->enabled_subdevices = (freenect_device_flags)(ctx->enabled_subdevices | FREENECT_DEVICE_AUDIO); } } else { // The good old kinect that tilts and tweets ctx->zero_plane_res = 322; } res = fnusb_claim_camera(dev); if (res < 0) { break; } } else { nr_cam++; } } } if (ctx->enabled_subdevices == FREENECT_DEVICE_CAMERA || res < 0) cnt = 0; // Search for the motor for (i = 0; i < cnt; i++) { int r = libusb_get_device_descriptor (devs[i], &desc); if (r < 0) continue; if (desc.idVendor != VID_MICROSOFT) continue; if ((ctx->enabled_subdevices & FREENECT_DEVICE_MOTOR) && !dev->usb_motor.dev && desc.idProduct == PID_NUI_MOTOR) { // If the index given by the user matches our camera index if (nr_mot == index) { dev->usb_motor.VID = desc.idVendor; dev->usb_motor.PID = desc.idProduct; res = libusb_open (devs[i], &dev->usb_motor.dev); if (res < 0 || !dev->usb_motor.dev) { FN_ERROR("Could not open motor: %d\n", res); dev->usb_motor.dev = NULL; break; } res = libusb_claim_interface (dev->usb_motor.dev, 0); if (res < 0) { FN_ERROR("Could not claim interface on motor: %d\n", res); libusb_close(dev->usb_motor.dev); dev->usb_motor.dev = NULL; break; } } else { nr_mot++; } } // Search for the audio if ((ctx->enabled_subdevices & FREENECT_DEVICE_AUDIO) && !dev->usb_audio.dev && (desc.idProduct == PID_NUI_AUDIO || fnusb_is_pid_k4w_audio(desc.idProduct))) { // If the index given by the user matches our audio index if (nr_audio == index) { dev->usb_audio.VID = desc.idVendor; dev->usb_audio.PID = desc.idProduct; res = libusb_open (devs[i], &dev->usb_audio.dev); if (res < 0 || !dev->usb_audio.dev) { FN_ERROR("Could not open audio: %d\n", res); dev->usb_audio.dev = NULL; break; } res = libusb_claim_interface (dev->usb_audio.dev, 0); if (res < 0) { FN_ERROR("Could not claim interface on audio: %d\n", res); libusb_close(dev->usb_audio.dev); dev->usb_audio.dev = NULL; break; } // Using the device handle that we've claimed, see if this // device has already uploaded firmware (has 2 interfaces). // If not, save the serial number (by reading the appropriate // descriptor), upload the firmware, and then enter a loop // waiting for a device with the same serial number to // reappear. int num_interfaces = fnusb_num_interfaces(&dev->usb_audio); if (num_interfaces >= 2) { if (dev->device_does_motor_control_with_audio) { dev->motor_control_with_audio_enabled = 1; } } else { // Read the serial number from the string descriptor and save it. unsigned char string_desc[256]; // String descriptors are at most 256 bytes res = libusb_get_string_descriptor_ascii(dev->usb_audio.dev, desc.iSerialNumber, string_desc, 256); if (res < 0) { FN_ERROR("Failed to retrieve serial number for audio device in bootloader state\n"); break; } char* audio_serial = strdup((char*)string_desc); FN_SPEW("Uploading firmware to audio device in bootloader state.\n"); // Check if we can load from memory - otherwise load from disk if (desc.idProduct == PID_NUI_AUDIO && ctx->fn_fw_nui_ptr && ctx->fn_fw_nui_size > 0) { FN_SPEW("loading firmware from memory\n"); res = upload_firmware_from_memory(&dev->usb_audio, ctx->fn_fw_nui_ptr, ctx->fn_fw_nui_size); } else if (desc.idProduct == PID_K4W_AUDIO && ctx->fn_fw_k4w_ptr && ctx->fn_fw_k4w_size > 0) { FN_SPEW("loading firmware from memory\n"); res = upload_firmware_from_memory(&dev->usb_audio, ctx->fn_fw_k4w_ptr, ctx->fn_fw_k4w_size); } else { res = upload_firmware(&dev->usb_audio, "audios.bin"); } if (res < 0) { FN_ERROR("upload_firmware failed: %d\n", res); break; } libusb_close(dev->usb_audio.dev); dev->usb_audio.dev = NULL; // Wait for the device to reappear. int loops = 0; for (loops = 0; loops < 10; loops++) { FN_SPEW("Try %d: Looking for new audio device matching serial %s\n", loops, audio_serial); // Scan devices. libusb_device **new_dev_list; int dev_index; ssize_t num_new_devs = libusb_get_device_list(ctx->usb.ctx, &new_dev_list); for (dev_index = 0; dev_index < num_new_devs; ++dev_index) { struct libusb_device_descriptor new_dev_desc; int r; r = libusb_get_device_descriptor (new_dev_list[dev_index], &new_dev_desc); if (r < 0) continue; // If this dev is a Kinect audio device, open device, read serial, and compare. if (new_dev_desc.idVendor == VID_MICROSOFT && (new_dev_desc.idProduct == PID_NUI_AUDIO || fnusb_is_pid_k4w_audio(desc.idProduct))) { FN_SPEW("Matched VID/PID!\n"); libusb_device_handle* new_dev_handle; // Open device r = libusb_open(new_dev_list[dev_index], &new_dev_handle); if (r < 0) continue; // Read serial r = libusb_get_string_descriptor_ascii(new_dev_handle, new_dev_desc.iSerialNumber, string_desc, 256); if (r < 0) { FN_SPEW("Lost new audio device while fetching serial number.\n"); libusb_close(new_dev_handle); continue; } // Compare to expected serial if (r == strlen(audio_serial) && strcmp((char*)string_desc, audio_serial) == 0) { // We found it! r = libusb_claim_interface(new_dev_handle, 0); if (r != 0) { // Ouch, found the device but couldn't claim the interface. FN_SPEW("Device with serial %s reappeared but couldn't claim interface 0\n", audio_serial); libusb_close(new_dev_handle); continue; } // Save the device handle. dev->usb_audio.dev = new_dev_handle; // Verify that we've actually found a device running the right firmware. num_interfaces = fnusb_num_interfaces(&dev->usb_audio); if (num_interfaces >= 2) { if (dev->device_does_motor_control_with_audio) { dev->motor_control_with_audio_enabled = 1; } } else { FN_SPEW("Opened audio with matching serial but too few interfaces.\n"); dev->usb_audio.dev = NULL; libusb_close(new_dev_handle); continue; } break; } else { FN_SPEW("Got serial %s, expected serial %s\n", (char*)string_desc, audio_serial); } } } libusb_free_device_list(new_dev_list, 1); // If we found the right device, break out of this loop. if (dev->usb_audio.dev) break; // Sleep for a second to give the device more time to reenumerate. sleep(1); } free(audio_serial); } } else { nr_audio++; } } } libusb_free_device_list (devs, 1); // free the list, unref the devices in it if ((dev->usb_cam.dev || !(ctx->enabled_subdevices & FREENECT_DEVICE_CAMERA)) && (dev->usb_motor.dev || !(ctx->enabled_subdevices & FREENECT_DEVICE_MOTOR))) //&& (dev->usb_audio.dev || !(ctx->enabled_subdevices & FREENECT_DEVICE_AUDIO))) { // Each requested subdevice is open. // Except audio, which may fail if firmware is missing (or because it hates us). return 0; } if (dev->usb_cam.dev != NULL) { libusb_release_interface(dev->usb_cam.dev, 0); libusb_close(dev->usb_cam.dev); } else { FN_ERROR("Failed to open camera subdevice or it is not disabled."); } if (dev->usb_motor.dev != NULL) { libusb_release_interface(dev->usb_motor.dev, 0); libusb_close(dev->usb_motor.dev); } else { FN_ERROR("Failed to open motor subddevice or it is not disabled."); } if (dev->usb_audio.dev != NULL) { libusb_release_interface(dev->usb_audio.dev, 0); libusb_close(dev->usb_audio.dev); } else { FN_ERROR("Failed to open audio subdevice or it is not disabled."); } return -1; }
int LJUSB_OpenAllDevices(HANDLE* devHandles, UINT* productIds, UINT maxDevices) { libusb_device **devs = NULL, *dev = NULL; struct libusb_device_handle *devh = NULL; struct libusb_device_descriptor desc; ssize_t cnt = 0; int r = 1; unsigned int i = 0, ljFoundCount = 0; HANDLE handle = NULL; if (!gIsLibUSBInitialized) { r = libusb_init(&gLJContext); if (r < 0) { fprintf(stderr, "failed to initialize libusb\n"); LJUSB_libusbError(r); return -1; } gIsLibUSBInitialized = true; } cnt = libusb_get_device_list(gLJContext, &devs); if (cnt < 0) { fprintf(stderr, "failed to get device list\n"); LJUSB_libusbError(cnt); LJUSB_libusb_exit(); return -1; } while ((dev = devs[i++]) != NULL) { #if LJ_DEBUG fprintf(stderr, "LJUSB_OpenDevice: calling libusb_get_device_descriptor\n"); #endif r = libusb_get_device_descriptor(dev, &desc); if (r < 0) { fprintf(stderr, "failed to get device descriptor"); LJUSB_libusbError(r); LJUSB_libusb_exit(); return -1; } if (LJ_VENDOR_ID == desc.idVendor) { // Found a LabJack device r = libusb_open(dev, &devh); if (r < 0) { LJUSB_libusbError(r); continue; } // Test if the kernel driver has the device. // Should only be true for HIDs. if (libusb_kernel_driver_active(devh, 0) ) { #if LJ_DEBUG fprintf(stderr, "Kernel Driver was active, detaching...\n"); #endif // Detaches U12s from kernel driver. r = libusb_detach_kernel_driver(devh, 0); // Check the return value if ( r != 0 ) { fprintf(stderr, "failed to detach from kernel driver. Error Number: %i", r); libusb_close(devh); continue; } } r = libusb_claim_interface(devh, 0); if (r < 0) { //LJUSB_libusbError(r); libusb_close(devh); continue; } handle = (HANDLE) devh; if (handle == NULL) { // Not a valid handle continue; } else if (ljFoundCount < maxDevices) { if (LJUSB_isMinFirmware(handle, desc.idProduct)) { devHandles[ljFoundCount] = handle; productIds[ljFoundCount] = desc.idProduct; ljFoundCount++; } else { // Not high enough firmware, keep moving. libusb_close(devh); ljFoundCount--; } } else { // Too many devices have been found. libusb_close(devh); break; } } } libusb_free_device_list(devs, 1); return ljFoundCount; }
FN_INTERNAL int fnusb_open_subdevices(freenect_device *dev, int index) { freenect_context *ctx = dev->parent; dev->device_does_motor_control_with_audio = 0; dev->motor_control_with_audio_enabled = 0; dev->usb_cam.parent = dev; dev->usb_cam.dev = NULL; dev->usb_motor.parent = dev; dev->usb_motor.dev = NULL; #ifdef BUILD_AUDIO dev->usb_audio.parent = dev; dev->usb_audio.dev = NULL; #endif libusb_device **devs; //pointer to pointer of device, used to retrieve a list of devices ssize_t cnt = libusb_get_device_list (dev->parent->usb.ctx, &devs); //get the list of devices if (cnt < 0) return -1; int i = 0, nr_cam = 0, nr_mot = 0; #ifdef BUILD_AUDIO int nr_audio = 0; #endif int res; struct libusb_device_descriptor desc; for (i = 0; i < cnt; i++) { int r = libusb_get_device_descriptor (devs[i], &desc); if (r < 0) continue; if (desc.idVendor != VID_MICROSOFT) continue; res = 0; // Search for the camera if ((ctx->enabled_subdevices & FREENECT_DEVICE_CAMERA) && !dev->usb_cam.dev && (desc.idProduct == PID_NUI_CAMERA || desc.idProduct == PID_K4W_CAMERA)) { // If the index given by the user matches our camera index if (nr_cam == index) { res = libusb_open (devs[i], &dev->usb_cam.dev); if (res < 0 || !dev->usb_cam.dev) { FN_ERROR("Could not open camera: %d\n", res); dev->usb_cam.dev = NULL; break; } if (desc.idProduct == PID_K4W_CAMERA || desc.bcdDevice != fn_le32(267)) { freenect_device_flags requested_devices = ctx->enabled_subdevices; // Not the old kinect so we only set up the camera ctx->enabled_subdevices = FREENECT_DEVICE_CAMERA; ctx->zero_plane_res = 334; dev->device_does_motor_control_with_audio = 1; //lets also set the LED ON //this keeps the camera alive for some systems which get freezes if( desc.idProduct == PID_K4W_CAMERA ){ freenect_extra_keep_alive(PID_K4W_AUDIO); }else{ freenect_extra_keep_alive(PID_NUI_AUDIO); } #ifdef BUILD_AUDIO //for newer devices we need to enable the audio device for motor control //we only do this though if motor has been requested. if ((requested_devices & FREENECT_DEVICE_MOTOR) && (requested_devices & FREENECT_DEVICE_AUDIO) == 0) { ctx->enabled_subdevices = (freenect_device_flags)(ctx->enabled_subdevices | FREENECT_DEVICE_AUDIO); } #endif }else{ /* The good old kinect that tilts and tweets */ ctx->zero_plane_res = 322; } #ifndef _WIN32 // Detach an existing kernel driver for the device res = libusb_kernel_driver_active(dev->usb_cam.dev, 0); if (res == 1) { res = libusb_detach_kernel_driver(dev->usb_cam.dev, 0); if (res < 0) { FN_ERROR("Could not detach kernel driver for camera: %d\n", res); libusb_close(dev->usb_cam.dev); dev->usb_cam.dev = NULL; break; } } #endif res = libusb_claim_interface (dev->usb_cam.dev, 0); if (res < 0) { FN_ERROR("Could not claim interface on camera: %d\n", res); libusb_close(dev->usb_cam.dev); dev->usb_cam.dev = NULL; break; } if(desc.idProduct == PID_K4W_CAMERA){ res = libusb_set_interface_alt_setting(dev->usb_cam.dev, 0, 1); if (res != 0) { FN_ERROR("Failed to set alternate interface #1 for K4W: %d\n", res); libusb_close(dev->usb_cam.dev); dev->usb_cam.dev = NULL; break; } } } else { nr_cam++; } } } if(ctx->enabled_subdevices == FREENECT_DEVICE_CAMERA || res < 0) cnt = 0; // Search for the motor for (i = 0; i < cnt; i++) { int r = libusb_get_device_descriptor (devs[i], &desc); if (r < 0) continue; if (desc.idVendor != VID_MICROSOFT) continue; if ((ctx->enabled_subdevices & FREENECT_DEVICE_MOTOR) && !dev->usb_motor.dev && desc.idProduct == PID_NUI_MOTOR) { // If the index given by the user matches our camera index if (nr_mot == index) { res = libusb_open (devs[i], &dev->usb_motor.dev); if (res < 0 || !dev->usb_motor.dev) { FN_ERROR("Could not open motor: %d\n", res); dev->usb_motor.dev = NULL; break; } res = libusb_claim_interface (dev->usb_motor.dev, 0); if (res < 0) { FN_ERROR("Could not claim interface on motor: %d\n", res); libusb_close(dev->usb_motor.dev); dev->usb_motor.dev = NULL; break; } } else { nr_mot++; } } #ifdef BUILD_AUDIO // TODO: check that the firmware has already been loaded; if not, upload firmware. // Search for the audio if ((ctx->enabled_subdevices & FREENECT_DEVICE_AUDIO) && !dev->usb_audio.dev && (desc.idProduct == PID_NUI_AUDIO || fnusb_is_pid_k4w_audio(desc.idProduct))) { // If the index given by the user matches our audio index if (nr_audio == index) { res = libusb_open (devs[i], &dev->usb_audio.dev); if (res < 0 || !dev->usb_audio.dev) { FN_ERROR("Could not open audio: %d\n", res); dev->usb_audio.dev = NULL; break; } res = libusb_claim_interface (dev->usb_audio.dev, 0); if (res < 0) { FN_ERROR("Could not claim interface on audio: %d\n", res); libusb_close(dev->usb_audio.dev); dev->usb_audio.dev = NULL; break; } // Using the device handle that we've claimed, see if this // device has already uploaded firmware (has 2 interfaces). If // not, save the serial number (by reading the appropriate // descriptor), upload the firmware, and then enter a loop // waiting for a device with the same serial number to // reappear. int num_interfaces = fnusb_num_interfaces(&dev->usb_audio); if( num_interfaces >= 2 ){ if( dev->device_does_motor_control_with_audio ){ dev->motor_control_with_audio_enabled = 1; } }else{ // Read the serial number from the string descriptor and save it. unsigned char string_desc[256]; // String descriptors are at most 256 bytes res = libusb_get_string_descriptor_ascii(dev->usb_audio.dev, desc.iSerialNumber, string_desc, 256); if (res < 0) { FN_ERROR("Failed to retrieve serial number for audio device in bootloader state\n"); break; } char* audio_serial = strdup((char*)string_desc); FN_SPEW("Uploading firmware to audio device in bootloader state.\n"); // Check if we can load from memory - otherwise load from disk if( desc.idProduct == PID_NUI_AUDIO && ctx->fn_fw_nui_ptr && ctx->fn_fw_nui_size > 0){ FN_SPEW("loading firmware from memory\n"); res = upload_firmware_from_memory(&dev->usb_audio, ctx->fn_fw_nui_ptr, ctx->fn_fw_nui_size); } else if( desc.idProduct == PID_K4W_AUDIO && ctx->fn_fw_k4w_ptr && ctx->fn_fw_k4w_size > 0 ){ FN_SPEW("loading firmware from memory\n"); res = upload_firmware_from_memory(&dev->usb_audio, ctx->fn_fw_k4w_ptr, ctx->fn_fw_k4w_size); } else{ res = upload_firmware(&dev->usb_audio, "audios.bin"); } if (res < 0) { FN_ERROR("upload_firmware failed: %d\n", res); break; } libusb_close(dev->usb_audio.dev); dev->usb_audio.dev = NULL; // Wait for the device to reappear. int loops = 0; for (loops = 0; loops < 10; loops++) { // Loop for at most 10 tries. FN_SPEW("Try %d: Looking for new audio device matching serial %s\n", loops, audio_serial); // Scan devices. libusb_device **new_dev_list; int dev_index; ssize_t num_new_devs = libusb_get_device_list(ctx->usb.ctx, &new_dev_list); for (dev_index = 0; dev_index < num_new_devs; ++dev_index) { struct libusb_device_descriptor new_dev_desc; int r; r = libusb_get_device_descriptor (new_dev_list[dev_index], &new_dev_desc); if (r < 0) continue; // If this dev is a Kinect audio device, open device, read serial, and compare. if (new_dev_desc.idVendor == VID_MICROSOFT && (new_dev_desc.idProduct == PID_NUI_AUDIO || fnusb_is_pid_k4w_audio(desc.idProduct))) { FN_SPEW("Matched VID/PID!\n"); libusb_device_handle* new_dev_handle; // Open device r = libusb_open(new_dev_list[dev_index], &new_dev_handle); if (r < 0) continue; // Read serial r = libusb_get_string_descriptor_ascii(new_dev_handle, new_dev_desc.iSerialNumber, string_desc, 256); if (r < 0) { FN_SPEW("Lost new audio device while fetching serial number.\n"); libusb_close(new_dev_handle); continue; } // Compare to expected serial if (r == strlen(audio_serial) && strcmp((char*)string_desc, audio_serial) == 0) { // We found it! r = libusb_claim_interface(new_dev_handle, 0); if (r != 0) { // Ouch, found the device but couldn't claim the interface. FN_SPEW("Device with serial %s reappeared but couldn't claim interface 0\n", audio_serial); libusb_close(new_dev_handle); continue; } // Save the device handle. dev->usb_audio.dev = new_dev_handle; // Verify that we've actually found a device running the right firmware. num_interfaces = fnusb_num_interfaces(&dev->usb_audio); if( num_interfaces >= 2 ){ if( dev->device_does_motor_control_with_audio ){ dev->motor_control_with_audio_enabled = 1; } }else{ FN_SPEW("Opened audio with matching serial but too few interfaces.\n"); dev->usb_audio.dev = NULL; libusb_close(new_dev_handle); continue; } break; } else { FN_SPEW("Got serial %s, expected serial %s\n", (char*)string_desc, audio_serial); } } } libusb_free_device_list(new_dev_list, 1); // If we found the right device, break out of this loop. if (dev->usb_audio.dev) break; // Sleep for a second to give the device more time to reenumerate. sleep(1); } free(audio_serial); } } else { nr_audio++; } } #endif } libusb_free_device_list (devs, 1); // free the list, unref the devices in it // Check that each subdevice is either opened or not enabled. if ( (dev->usb_cam.dev || !(ctx->enabled_subdevices & FREENECT_DEVICE_CAMERA)) && (dev->usb_motor.dev || !(ctx->enabled_subdevices & FREENECT_DEVICE_MOTOR)) #ifdef BUILD_AUDIO && (dev->usb_audio.dev || !(ctx->enabled_subdevices & FREENECT_DEVICE_AUDIO)) #endif ) { return 0; } else { if (dev->usb_cam.dev) { libusb_release_interface(dev->usb_cam.dev, 0); libusb_close(dev->usb_cam.dev); } else { FN_ERROR("Failed to open camera subdevice or it is not disabled."); } if (dev->usb_motor.dev) { libusb_release_interface(dev->usb_motor.dev, 0); libusb_close(dev->usb_motor.dev); } else { FN_ERROR("Failed to open motor subddevice or it is not disabled."); } #ifdef BUILD_AUDIO if (dev->usb_audio.dev) { libusb_release_interface(dev->usb_audio.dev, 0); libusb_close(dev->usb_audio.dev); } else { FN_ERROR("Failed to open audio subdevice or it is not disabled."); } #endif return -1; } }
USBTransport::~USBTransport() { libusb_release_interface(m_device, 0); libusb_close(m_device); }
int main() { #ifdef GUB211_DOLIST libusb_device **devs; ssize_t cnt; #endif libusb_context *ctx = NULL; libusb_device_handle *handle; int r; r = libusb_init(&ctx); if (r < 0) { fprintf(stderr, "Error initializing libusb: %d\n", r); return 1; } libusb_set_debug(ctx, 3); #ifdef GUB211_DOLIST cnt = libusb_get_device_list(ctx, &devs); if (cnt < 0) { fprintf(stderr, "Error getting device list: %zd\n", cnt); return 1; } #endif handle = libusb_open_device_with_vid_pid(ctx, GUB211_VENDORID, GUB211_PRODUCTID); #ifdef GUB211_DOLIST libusb_free_device_list(devs, cnt); #endif if (libusb_kernel_driver_active(handle, 0) == 1) { if ((r = libusb_detach_kernel_driver(handle, 0)) < 0) { fprintf(stderr, "Detaching kernel driver from interface 0 failed: %d\n", r); return 1; } } if (libusb_kernel_driver_active(handle, 1) == 1) { if ((r = libusb_detach_kernel_driver(handle, 1)) < 0) { fprintf(stderr, "Detaching kernel driver from interface 1 failed: %d\n", r); return 1; } } if ((r = libusb_claim_interface(handle, 0)) < 0) { fprintf(stderr, "Claiming interface 0 failed: %d\n", r); return 1; } if ((r = libusb_claim_interface(handle, 1)) < 0) { fprintf(stderr, "Claiming interface 1 failed: %d\n", r); return 1; } /* magic numbers obtained by sniffing the usb bus */ if ((r = libusb_control_transfer(handle, 0x21, 0x09, 0x0203, 0x0001, (unsigned char *)"\x03\x5d\x42\x00\x00", 5, 100)) != 5) { fprintf(stderr, "Control transfer failed: %d\n", r); return 1; } if ((r = libusb_release_interface(handle, 0)) < 0) { fprintf(stderr, "Releasing interface 0 failed: %d\n", r); return 2; } if ((r = libusb_release_interface(handle, 1)) < 0) { fprintf(stderr, "Releasing interface 1 failed: %d\n", r); return 2; } libusb_close(handle); libusb_exit(ctx); return 0; }
void* rocs_usb_openUSB(int vendor, int product, int configNr, int interfaceNr, int* input, int* output) { void* husb = NULL; // discover devices libusb_device **list; libusb_device *found = NULL; libusb_context *ctx = NULL; int attached = 0; libusb_init(&ctx); libusb_set_debug(ctx,3); ssize_t cnt = libusb_get_device_list(ctx, &list); ssize_t i = 0; int err = 0; TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "%d USB devices found", cnt ); // find our device for(i = 0; i < cnt; i++){ libusb_device *device = list[i]; if( isWantedDevice(device, vendor, product, input, output) ){ found = device; break; } } if( found != NULL ) { libusb_device_handle *handle; err = libusb_open(found, &handle); if (err) { TraceOp.trc( name, TRCLEVEL_EXCEPTION, __LINE__, 9999, "could not open USB device: %s", libusb_error_name(err) ); return NULL; } husb = handle; if ( libusb_kernel_driver_active(husb,0) ){ TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "detach kernel driver..." ); err = libusb_detach_kernel_driver(husb,0); if(err) { TraceOp.trc( name, TRCLEVEL_EXCEPTION, __LINE__, 9999, "detach kernel driver: %s", libusb_error_name(err) ); } } else TraceOp.trc( name, TRCLEVEL_INFO, __LINE__, 9999, "Device free from kernel" ); err = libusb_claim_interface( husb, 0 ); if (err) { TraceOp.trc( name, TRCLEVEL_EXCEPTION, __LINE__, 9999, "could not claim interface: %s", libusb_error_name(err) ); libusb_close(handle); husb = NULL; } } libusb_free_device_list(list, 1); if( husb == NULL ) { TraceOp.trc( name, TRCLEVEL_WARNING, __LINE__, 9999, "wanted device 0x%04X:0x%04X not found", vendor, product ); } return husb; }
/** * Wraps a CDB mass storage command in the appropriate gunk to get it down * @param handle * @param endpoint * @param cdb * @param cdb_length * @param lun * @param flags * @param expected_rx_size * @return */ int send_usb_mass_storage_command(libusb_device_handle *handle, uint8_t endpoint_out, uint8_t *cdb, uint8_t cdb_length, uint8_t lun, uint8_t flags, uint32_t expected_rx_size) { DLOG("Sending usb m-s cmd: cdblen:%d, rxsize=%d\n", cdb_length, expected_rx_size); dump_CDB_command(cdb, cdb_length); static uint32_t tag; if (tag == 0) { tag = 1; } int try = 0; int ret = 0; int real_transferred; int i = 0; uint8_t c_buf[STLINK_SG_SIZE]; // tag is allegedly ignored... TODO - verify c_buf[i++] = 'U'; c_buf[i++] = 'S'; c_buf[i++] = 'B'; c_buf[i++] = 'C'; write_uint32(&c_buf[i], tag); uint32_t this_tag = tag++; write_uint32(&c_buf[i+4], expected_rx_size); i+= 8; c_buf[i++] = flags; c_buf[i++] = lun; c_buf[i++] = cdb_length; // Now the actual CDB request assert(cdb_length <= CDB_SL); memcpy(&(c_buf[i]), cdb, cdb_length); int sending_length = STLINK_SG_SIZE; // send.... do { ret = libusb_bulk_transfer(handle, endpoint_out, c_buf, sending_length, &real_transferred, SG_TIMEOUT_MSEC); if (ret == LIBUSB_ERROR_PIPE) { libusb_clear_halt(handle, endpoint_out); } try++; } while ((ret == LIBUSB_ERROR_PIPE) && (try < 3)); if (ret != LIBUSB_SUCCESS) { WLOG("sending failed: %d\n", ret); return -1; } return this_tag; } /** * Straight from stm8 stlink code... * @param handle * @param endpoint_in * @param endpoint_out */ static void get_sense(libusb_device_handle *handle, uint8_t endpoint_in, uint8_t endpoint_out) { DLOG("Fetching sense...\n"); uint8_t cdb[16]; memset(cdb, 0, sizeof(cdb)); #define REQUEST_SENSE 0x03 #define REQUEST_SENSE_LENGTH 18 cdb[0] = REQUEST_SENSE; cdb[4] = REQUEST_SENSE_LENGTH; uint32_t tag = send_usb_mass_storage_command(handle, endpoint_out, cdb, sizeof(cdb), 0, LIBUSB_ENDPOINT_IN, REQUEST_SENSE_LENGTH); if (tag == 0) { WLOG("refusing to send request sense with tag 0\n"); return; } unsigned char sense[REQUEST_SENSE_LENGTH]; int transferred; int ret; int try = 0; do { ret = libusb_bulk_transfer(handle, endpoint_in, sense, sizeof(sense), &transferred, SG_TIMEOUT_MSEC); if (ret == LIBUSB_ERROR_PIPE) { libusb_clear_halt(handle, endpoint_in); } try++; } while ((ret == LIBUSB_ERROR_PIPE) && (try < 3)); if (ret != LIBUSB_SUCCESS) { WLOG("receiving sense failed: %d\n", ret); return; } if (transferred != sizeof(sense)) { WLOG("received unexpected amount of sense: %d != %d\n", transferred, sizeof(sense)); } uint32_t received_tag; int status = get_usb_mass_storage_status(handle, endpoint_in, &received_tag); if (status != 0) { WLOG("receiving sense failed with status: %02x\n", status); return; } if (sense[0] != 0x70 && sense[0] != 0x71) { WLOG("No sense data\n"); } else { WLOG("Sense KCQ: %02X %02X %02X\n", sense[2] & 0x0f, sense[12], sense[13]); } } /** * Just send a buffer on an endpoint, no questions asked. * Handles repeats, and time outs. Also handles reading status reports and sense * @param handle libusb device * * @param endpoint_out sends * @param endpoint_in used to read status reports back in * @param cbuf what to send * @param length how much to send * @return number of bytes actually sent, or -1 for failures. */ int send_usb_data_only(libusb_device_handle *handle, unsigned char endpoint_out, unsigned char endpoint_in, unsigned char *cbuf, unsigned int length) { int ret; int real_transferred; int try = 0; do { ret = libusb_bulk_transfer(handle, endpoint_out, cbuf, length, &real_transferred, SG_TIMEOUT_MSEC); if (ret == LIBUSB_ERROR_PIPE) { libusb_clear_halt(handle, endpoint_out); } try++; } while ((ret == LIBUSB_ERROR_PIPE) && (try < 3)); if (ret != LIBUSB_SUCCESS) { WLOG("sending failed: %d\n", ret); return -1; } // now, swallow up the status, so that things behave nicely... uint32_t received_tag; // -ve is for my errors, 0 is good, +ve is libusb sense status bytes int status = get_usb_mass_storage_status(handle, endpoint_in, &received_tag); if (status < 0) { WLOG("receiving status failed: %d\n", status); return -1; } if (status != 0) { WLOG("receiving status not passed :(: %02x\n", status); } if (status == 1) { get_sense(handle, endpoint_in, endpoint_out); return -1; } return real_transferred; } int stlink_q(stlink_t *sl) { struct stlink_libsg* sg = sl->backend_data; //uint8_t cdb_len = 6; // FIXME varies!!! uint8_t cdb_len = 10; // FIXME varies!!! uint8_t lun = 0; // always zero... uint32_t tag = send_usb_mass_storage_command(sg->usb_handle, sg->ep_req, sg->cdb_cmd_blk, cdb_len, lun, LIBUSB_ENDPOINT_IN, sl->q_len); // now wait for our response... // length copied from stlink-usb... int rx_length = sl->q_len; int try = 0; int real_transferred; int ret; if (rx_length > 0) { do { ret = libusb_bulk_transfer(sg->usb_handle, sg->ep_rep, sl->q_buf, rx_length, &real_transferred, SG_TIMEOUT_MSEC); if (ret == LIBUSB_ERROR_PIPE) { libusb_clear_halt(sg->usb_handle, sg->ep_req); } try++; } while ((ret == LIBUSB_ERROR_PIPE) && (try < 3)); if (ret != LIBUSB_SUCCESS) { WLOG("Receiving failed: %d\n", ret); return -1; } if (real_transferred != rx_length) { WLOG("received unexpected amount: %d != %d\n", real_transferred, rx_length); } } uint32_t received_tag; // -ve is for my errors, 0 is good, +ve is libusb sense status bytes int status = get_usb_mass_storage_status(sg->usb_handle, sg->ep_rep, &received_tag); if (status < 0) { WLOG("receiving status failed: %d\n", status); return -1; } if (status != 0) { WLOG("receiving status not passed :(: %02x\n", status); } if (status == 1) { get_sense(sg->usb_handle, sg->ep_rep, sg->ep_req); return -1; } if (received_tag != tag) { WLOG("received tag %d but expected %d\n", received_tag, tag); //return -1; } if (rx_length > 0 && real_transferred != rx_length) { return -1; } return 0; } // TODO thinking, cleanup void stlink_stat(stlink_t *stl, char *txt) { if (stl->q_len <= 0) return; stlink_print_data(stl); switch (stl->q_buf[0]) { case STLINK_OK: DLOG(" %s: ok\n", txt); return; case STLINK_FALSE: DLOG(" %s: false\n", txt); return; default: DLOG(" %s: unknown\n", txt); } } int _stlink_sg_version(stlink_t *stl) { struct stlink_libsg *sl = stl->backend_data; clear_cdb(sl); sl->cdb_cmd_blk[0] = STLINK_GET_VERSION; stl->q_len = 6; sl->q_addr = 0; return stlink_q(stl); } // Get stlink mode: // STLINK_DEV_DFU_MODE || STLINK_DEV_MASS_MODE || STLINK_DEV_DEBUG_MODE // usb dfu || usb mass || jtag or swd int _stlink_sg_current_mode(stlink_t *stl) { struct stlink_libsg *sl = stl->backend_data; clear_cdb(sl); sl->cdb_cmd_blk[0] = STLINK_GET_CURRENT_MODE; stl->q_len = 2; sl->q_addr = 0; if (stlink_q(stl)) return -1; return stl->q_buf[0]; } // Exit the mass mode and enter the swd debug mode. int _stlink_sg_enter_swd_mode(stlink_t *sl) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_ENTER; sg->cdb_cmd_blk[2] = STLINK_DEBUG_ENTER_SWD; sl->q_len = 0; // >0 -> aboard return stlink_q(sl); } // Exit the mass mode and enter the jtag debug mode. // (jtag is disabled in the discovery's stlink firmware) int _stlink_sg_enter_jtag_mode(stlink_t *sl) { struct stlink_libsg *sg = sl->backend_data; DLOG("\n*** stlink_enter_jtag_mode ***\n"); clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_ENTER; sg->cdb_cmd_blk[2] = STLINK_DEBUG_ENTER_JTAG; sl->q_len = 0; return stlink_q(sl); } // XXX kernel driver performs reset, the device temporally disappears // Suspect this is no longer the case when we have ignore on? RECHECK int _stlink_sg_exit_dfu_mode(stlink_t *sl) { struct stlink_libsg *sg = sl->backend_data; DLOG("\n*** stlink_exit_dfu_mode ***\n"); clear_cdb(sg); sg->cdb_cmd_blk[0] = STLINK_DFU_COMMAND; sg->cdb_cmd_blk[1] = STLINK_DFU_EXIT; sl->q_len = 0; // ?? return stlink_q(sl); /* [135121.844564] sd 19:0:0:0: [sdb] Unhandled error code [135121.844569] sd 19:0:0:0: [sdb] Result: hostbyte=DID_ERROR driverbyte=DRIVER_OK [135121.844574] sd 19:0:0:0: [sdb] CDB: Read(10): 28 00 00 00 10 00 00 00 08 00 [135121.844584] end_request: I/O error, dev sdb, sector 4096 [135121.844590] Buffer I/O error on device sdb, logical block 512 [135130.122567] usb 6-1: reset full speed USB device using uhci_hcd and address 7 [135130.274551] usb 6-1: device firmware changed [135130.274618] usb 6-1: USB disconnect, address 7 [135130.275186] VFS: busy inodes on changed media or resized disk sdb [135130.275424] VFS: busy inodes on changed media or resized disk sdb [135130.286758] VFS: busy inodes on changed media or resized disk sdb [135130.292796] VFS: busy inodes on changed media or resized disk sdb [135130.301481] VFS: busy inodes on changed media or resized disk sdb [135130.304316] VFS: busy inodes on changed media or resized disk sdb [135130.431113] usb 6-1: new full speed USB device using uhci_hcd and address 8 [135130.629444] usb-storage 6-1:1.0: Quirks match for vid 0483 pid 3744: 102a1 [135130.629492] scsi20 : usb-storage 6-1:1.0 [135131.625600] scsi 20:0:0:0: Direct-Access STM32 PQ: 0 ANSI: 0 [135131.627010] sd 20:0:0:0: Attached scsi generic sg2 type 0 [135131.633603] sd 20:0:0:0: [sdb] 64000 512-byte logical blocks: (32.7 MB/31.2 MiB) [135131.633613] sd 20:0:0:0: [sdb] Assuming Write Enabled [135131.633620] sd 20:0:0:0: [sdb] Assuming drive cache: write through [135131.640584] sd 20:0:0:0: [sdb] Assuming Write Enabled [135131.640592] sd 20:0:0:0: [sdb] Assuming drive cache: write through [135131.640609] sdb: [135131.652634] sd 20:0:0:0: [sdb] Assuming Write Enabled [135131.652639] sd 20:0:0:0: [sdb] Assuming drive cache: write through [135131.652645] sd 20:0:0:0: [sdb] Attached SCSI removable disk [135131.671536] sd 20:0:0:0: [sdb] Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE [135131.671548] sd 20:0:0:0: [sdb] Sense Key : Illegal Request [current] [135131.671553] sd 20:0:0:0: [sdb] Add. Sense: Logical block address out of range [135131.671560] sd 20:0:0:0: [sdb] CDB: Read(10): 28 00 00 00 f9 80 00 00 08 00 [135131.671570] end_request: I/O error, dev sdb, sector 63872 [135131.671575] Buffer I/O error on device sdb, logical block 7984 [135131.678527] sd 20:0:0:0: [sdb] Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE [135131.678532] sd 20:0:0:0: [sdb] Sense Key : Illegal Request [current] [135131.678537] sd 20:0:0:0: [sdb] Add. Sense: Logical block address out of range [135131.678542] sd 20:0:0:0: [sdb] CDB: Read(10): 28 00 00 00 f9 80 00 00 08 00 [135131.678551] end_request: I/O error, dev sdb, sector 63872 ... [135131.853565] end_request: I/O error, dev sdb, sector 4096 */ } int _stlink_sg_core_id(stlink_t *sl) { struct stlink_libsg *sg = sl->backend_data; int ret; clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_READCOREID; sl->q_len = 4; sg->q_addr = 0; ret = stlink_q(sl); if (ret) return ret; sl->core_id = read_uint32(sl->q_buf, 0); return 0; } // Arm-core reset -> halted state. int _stlink_sg_reset(stlink_t *sl) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_RESETSYS; sl->q_len = 2; sg->q_addr = 0; if (stlink_q(sl)) return -1; stlink_stat(sl, "core reset"); return 0; } // Arm-core reset -> halted state. int _stlink_sg_jtag_reset(stlink_t *sl, int value) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_JTAG_DRIVE_NRST; sg->cdb_cmd_blk[2] = (value)?0:1; sl->q_len = 3; sg->q_addr = 2; if (stlink_q(sl)) return -1; stlink_stat(sl, "core reset"); return 0; } // Arm-core status: halted or running. int _stlink_sg_status(stlink_t *sl) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_GETSTATUS; sl->q_len = 2; sg->q_addr = 0; return stlink_q(sl); } // Force the core into the debug mode -> halted state. int _stlink_sg_force_debug(stlink_t *sl) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_FORCEDEBUG; sl->q_len = 2; sg->q_addr = 0; if (stlink_q(sl)) return -1; stlink_stat(sl, "force debug"); return 0; } // Read all arm-core registers. int _stlink_sg_read_all_regs(stlink_t *sl, reg *regp) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_READALLREGS; sl->q_len = 84; sg->q_addr = 0; if (stlink_q(sl)) return -1; stlink_print_data(sl); // TODO - most of this should be re-extracted up.... // 0-3 | 4-7 | ... | 60-63 | 64-67 | 68-71 | 72-75 | 76-79 | 80-83 // r0 | r1 | ... | r15 | xpsr | main_sp | process_sp | rw | rw2 for (int i = 0; i < 16; i++) { regp->r[i] = read_uint32(sl->q_buf, 4 * i); if (sl->verbose > 1) DLOG("r%2d = 0x%08x\n", i, regp->r[i]); } regp->xpsr = read_uint32(sl->q_buf, 64); regp->main_sp = read_uint32(sl->q_buf, 68); regp->process_sp = read_uint32(sl->q_buf, 72); regp->rw = read_uint32(sl->q_buf, 76); regp->rw2 = read_uint32(sl->q_buf, 80); if (sl->verbose < 2) return 0; DLOG("xpsr = 0x%08x\n", regp->xpsr); DLOG("main_sp = 0x%08x\n", regp->main_sp); DLOG("process_sp = 0x%08x\n", regp->process_sp); DLOG("rw = 0x%08x\n", regp->rw); DLOG("rw2 = 0x%08x\n", regp->rw2); return 0; } // Read an arm-core register, the index must be in the range 0..20. // 0 | 1 | ... | 15 | 16 | 17 | 18 | 19 | 20 // r0 | r1 | ... | r15 | xpsr | main_sp | process_sp | rw | rw2 int _stlink_sg_read_reg(stlink_t *sl, int r_idx, reg *regp) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_READREG; sg->cdb_cmd_blk[2] = r_idx; sl->q_len = 4; sg->q_addr = 0; if (stlink_q(sl)) return -1; // 0 | 1 | ... | 15 | 16 | 17 | 18 | 19 | 20 // 0-3 | 4-7 | ... | 60-63 | 64-67 | 68-71 | 72-75 | 76-79 | 80-83 // r0 | r1 | ... | r15 | xpsr | main_sp | process_sp | rw | rw2 stlink_print_data(sl); uint32_t r = read_uint32(sl->q_buf, 0); DLOG("r_idx (%2d) = 0x%08x\n", r_idx, r); switch (r_idx) { case 16: regp->xpsr = r; break; case 17: regp->main_sp = r; break; case 18: regp->process_sp = r; break; case 19: regp->rw = r; //XXX ?(primask, basemask etc.) break; case 20: regp->rw2 = r; //XXX ?(primask, basemask etc.) break; default: regp->r[r_idx] = r; } return 0; } // Write an arm-core register. Index: // 0 | 1 | ... | 15 | 16 | 17 | 18 | 19 | 20 // r0 | r1 | ... | r15 | xpsr | main_sp | process_sp | rw | rw2 int _stlink_sg_write_reg(stlink_t *sl, uint32_t reg, int idx) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_WRITEREG; // 2: reg index // 3-6: reg content sg->cdb_cmd_blk[2] = idx; write_uint32(sg->cdb_cmd_blk + 3, reg); sl->q_len = 2; sg->q_addr = 0; if (stlink_q(sl)) return -1; stlink_stat(sl, "write reg"); return 0; } // Write a register of the debug module of the core. // XXX ?(atomic writes) // TODO test void stlink_write_dreg(stlink_t *sl, uint32_t reg, uint32_t addr) { struct stlink_libsg *sg = sl->backend_data; DLOG("\n*** stlink_write_dreg ***\n"); clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_WRITEDEBUGREG; // 2-5: address of reg of the debug module // 6-9: reg content write_uint32(sg->cdb_cmd_blk + 2, addr); write_uint32(sg->cdb_cmd_blk + 6, reg); sl->q_len = 2; sg->q_addr = addr; stlink_q(sl); stlink_stat(sl, "write debug reg"); } // Force the core exit the debug mode. int _stlink_sg_run(stlink_t *sl) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_RUNCORE; sl->q_len = 2; sg->q_addr = 0; if (stlink_q(sl)) return -1; stlink_stat(sl, "run core"); return 0; } // Step the arm-core. int _stlink_sg_step(stlink_t *sl) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_STEPCORE; sl->q_len = 2; sg->q_addr = 0; if (stlink_q(sl)) return -1; stlink_stat(sl, "step core"); return 0; } // TODO test // see Cortex-M3 Technical Reference Manual // TODO make delegate! void stlink_set_hw_bp(stlink_t *sl, int fp_nr, uint32_t addr, int fp) { DLOG("\n*** stlink_set_hw_bp ***\n"); struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_SETFP; // 2:The number of the flash patch used to set the breakpoint // 3-6: Address of the breakpoint (LSB) // 7: FP_ALL (0x02) / FP_UPPER (0x01) / FP_LOWER (0x00) sl->q_buf[2] = fp_nr; write_uint32(sl->q_buf, addr); sl->q_buf[7] = fp; sl->q_len = 2; stlink_q(sl); stlink_stat(sl, "set flash breakpoint"); } // TODO test // TODO make delegate! void stlink_clr_hw_bp(stlink_t *sl, int fp_nr) { struct stlink_libsg *sg = sl->backend_data; DLOG("\n*** stlink_clr_hw_bp ***\n"); clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_CLEARFP; sg->cdb_cmd_blk[2] = fp_nr; sl->q_len = 2; stlink_q(sl); stlink_stat(sl, "clear flash breakpoint"); } // Read a "len" bytes to the sl->q_buf from the memory, max 6kB (6144 bytes) int _stlink_sg_read_mem32(stlink_t *sl, uint32_t addr, uint16_t len) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_READMEM_32BIT; // 2-5: addr // 6-7: len write_uint32(sg->cdb_cmd_blk + 2, addr); write_uint16(sg->cdb_cmd_blk + 6, len); // data_in 0-0x40-len // !!! len _and_ q_len must be max 6k, // i.e. >1024 * 6 = 6144 -> aboard) // !!! if len < q_len: 64*k, 1024*n, n=1..5 -> aboard // (broken residue issue) sl->q_len = len; sg->q_addr = addr; if (stlink_q(sl)) return -1; stlink_print_data(sl); return 0; } // Write a "len" bytes from the sl->q_buf to the memory, max 64 Bytes. int _stlink_sg_write_mem8(stlink_t *sl, uint32_t addr, uint16_t len) { struct stlink_libsg *sg = sl->backend_data; int ret; clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_WRITEMEM_8BIT; // 2-5: addr // 6-7: len (>0x40 (64) -> aboard) write_uint32(sg->cdb_cmd_blk + 2, addr); write_uint16(sg->cdb_cmd_blk + 6, len); // this sends the command... ret = send_usb_mass_storage_command(sg->usb_handle, sg->ep_req, sg->cdb_cmd_blk, CDB_SL, 0, 0, 0); if (ret == -1) return ret; // This sends the data... ret = send_usb_data_only(sg->usb_handle, sg->ep_req, sg->ep_rep, sl->q_buf, len); if (ret == -1) return ret; stlink_print_data(sl); return 0; } // Write a "len" bytes from the sl->q_buf to the memory, max Q_BUF_LEN bytes. int _stlink_sg_write_mem32(stlink_t *sl, uint32_t addr, uint16_t len) { struct stlink_libsg *sg = sl->backend_data; int ret; clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_DEBUG_WRITEMEM_32BIT; // 2-5: addr // 6-7: len "unlimited" write_uint32(sg->cdb_cmd_blk + 2, addr); write_uint16(sg->cdb_cmd_blk + 6, len); // this sends the command... ret = send_usb_mass_storage_command(sg->usb_handle, sg->ep_req, sg->cdb_cmd_blk, CDB_SL, 0, 0, 0); if (ret == -1) return ret; // This sends the data... ret = send_usb_data_only(sg->usb_handle, sg->ep_req, sg->ep_rep, sl->q_buf, len); if (ret == -1) return ret; stlink_print_data(sl); return 0; } // Write one DWORD data to memory int _stlink_sg_write_debug32(stlink_t *sl, uint32_t addr, uint32_t data) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_JTAG_WRITEDEBUG_32BIT; // 2-5: addr write_uint32(sg->cdb_cmd_blk + 2, addr); write_uint32(sg->cdb_cmd_blk + 6, data); sl->q_len = 2; return stlink_q(sl); } // Read one DWORD data from memory int _stlink_sg_read_debug32(stlink_t *sl, uint32_t addr, uint32_t *data) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); sg->cdb_cmd_blk[1] = STLINK_JTAG_READDEBUG_32BIT; // 2-5: addr write_uint32(sg->cdb_cmd_blk + 2, addr); sl->q_len = 8; if (stlink_q(sl)) return -1; *data = read_uint32(sl->q_buf, 4); return 0; } // Exit the jtag or swd mode and enter the mass mode. int _stlink_sg_exit_debug_mode(stlink_t *stl) { if (stl) { struct stlink_libsg* sl = stl->backend_data; clear_cdb(sl); sl->cdb_cmd_blk[1] = STLINK_DEBUG_EXIT; stl->q_len = 0; // >0 -> aboard return stlink_q(stl); } return 0; } // 1) open a sg device, switch the stlink from dfu to mass mode // 2) wait 5s until the kernel driver stops reseting the broken device // 3) reopen the device // 4) the device driver is now ready for a switch to jtag/swd mode // TODO thinking, better error handling, wait until the kernel driver stops reseting the plugged-in device stlink_backend_t _stlink_sg_backend = { _stlink_sg_close, _stlink_sg_exit_debug_mode, _stlink_sg_enter_swd_mode, _stlink_sg_enter_jtag_mode, _stlink_sg_exit_dfu_mode, _stlink_sg_core_id, _stlink_sg_reset, _stlink_sg_jtag_reset, _stlink_sg_run, _stlink_sg_status, _stlink_sg_version, _stlink_sg_read_debug32, _stlink_sg_read_mem32, _stlink_sg_write_debug32, _stlink_sg_write_mem32, _stlink_sg_write_mem8, _stlink_sg_read_all_regs, _stlink_sg_read_reg, NULL, /* read_all_unsupported_regs */ NULL, /* read_unsupported_regs */ NULL, /* write_unsupported_regs */ _stlink_sg_write_reg, _stlink_sg_step, _stlink_sg_current_mode, _stlink_sg_force_debug, NULL }; static stlink_t* stlink_open(const int verbose) { stlink_t *sl = malloc(sizeof (stlink_t)); memset(sl, 0, sizeof(stlink_t)); struct stlink_libsg *slsg = malloc(sizeof (struct stlink_libsg)); if (sl == NULL || slsg == NULL) { WLOG("Couldn't malloc stlink and stlink_sg structures out of memory!\n"); return NULL; } if (libusb_init(&(slsg->libusb_ctx))) { WLOG("failed to init libusb context, wrong version of libraries?\n"); free(sl); free(slsg); return NULL; } libusb_set_debug(slsg->libusb_ctx, 3); slsg->usb_handle = libusb_open_device_with_vid_pid(slsg->libusb_ctx, USB_ST_VID, USB_STLINK_PID); if (slsg->usb_handle == NULL) { WLOG("Failed to find an stlink v1 by VID:PID\n"); libusb_close(slsg->usb_handle); libusb_exit(slsg->libusb_ctx); free(sl); free(slsg); return NULL; } // TODO // Could read the interface config descriptor, and assert lots of the assumptions // assumption: numInterfaces is always 1... if (libusb_kernel_driver_active(slsg->usb_handle, 0) == 1) { int r = libusb_detach_kernel_driver(slsg->usb_handle, 0); if (r < 0) { WLOG("libusb_detach_kernel_driver(() error %s\n", strerror(-r)); libusb_close(slsg->usb_handle); libusb_exit(slsg->libusb_ctx); free(sl); free(slsg); return NULL; } DLOG("Kernel driver was successfully detached\n"); } int config; if (libusb_get_configuration(slsg->usb_handle, &config)) { /* this may fail for a previous configured device */ WLOG("libusb_get_configuration()\n"); libusb_close(slsg->usb_handle); libusb_exit(slsg->libusb_ctx); free(sl); free(slsg); return NULL; } // assumption: bConfigurationValue is always 1 if (config != 1) { WLOG("Your stlink got into a real weird configuration, trying to fix it!\n"); DLOG("setting new configuration (%d -> 1)\n", config); if (libusb_set_configuration(slsg->usb_handle, 1)) { /* this may fail for a previous configured device */ WLOG("libusb_set_configuration() failed\n"); libusb_close(slsg->usb_handle); libusb_exit(slsg->libusb_ctx); free(sl); free(slsg); return NULL; } } if (libusb_claim_interface(slsg->usb_handle, 0)) { WLOG("libusb_claim_interface() failed\n"); libusb_close(slsg->usb_handle); libusb_exit(slsg->libusb_ctx); free(sl); free(slsg); return NULL; } // assumption: endpoint config is fixed mang. really. slsg->ep_rep = 1 /* ep rep */ | LIBUSB_ENDPOINT_IN; slsg->ep_req = 2 /* ep req */ | LIBUSB_ENDPOINT_OUT; DLOG("Successfully opened stlinkv1 by libusb :)\n"); sl->verbose = verbose; sl->backend_data = slsg; sl->backend = &_stlink_sg_backend; sl->core_stat = STLINK_CORE_STAT_UNKNOWN; slsg->q_addr = 0; return sl; }
void CWII_IPC_HLE_Device_hid::FillOutDevices(u32 BufferOut, u32 BufferOutSize) { static u16 check = 1; int OffsetBuffer = BufferOut; int OffsetStart = 0; //int OffsetDevice = 0; int d,c,ic,i,e; /* config, interface container, interface, endpoint */ libusb_device **list; //libusb_device *found = NULL; ssize_t cnt = libusb_get_device_list(NULL, &list); DEBUG_LOG(WII_IPC_HID, "Found %ld viable USB devices.", cnt); for (d = 0; d < cnt; d++) { libusb_device *device = list[d]; struct libusb_device_descriptor desc; int dRet = libusb_get_device_descriptor (device, &desc); if (dRet) { // could not aquire the descriptor, no point in trying to use it. DEBUG_LOG(WII_IPC_HID, "libusb_get_device_descriptor failed with error: %d", dRet); continue; } OffsetStart = OffsetBuffer; OffsetBuffer += 4; // skip length for now, fill at end OffsetBuffer += 4; // skip devNum for now WiiHIDDeviceDescriptor wii_device; ConvertDeviceToWii(&wii_device, &desc); Memory::WriteBigEData((const u8*)&wii_device, OffsetBuffer, Align(wii_device.bLength, 4)); OffsetBuffer += Align(wii_device.bLength, 4); bool deviceValid = true; for (c = 0; deviceValid && c < desc.bNumConfigurations; c++) { struct libusb_config_descriptor *config = NULL; int cRet = libusb_get_config_descriptor(device, c, &config); // do not try to use usb devices with more than one interface, games can crash if(cRet == 0 && config->bNumInterfaces <= MAX_HID_INTERFACES) { WiiHIDConfigDescriptor wii_config; ConvertConfigToWii(&wii_config, config); Memory::WriteBigEData((const u8*)&wii_config, OffsetBuffer, Align(wii_config.bLength, 4)); OffsetBuffer += Align(wii_config.bLength, 4); for (ic = 0; ic < config->bNumInterfaces; ic++) { const struct libusb_interface *interfaceContainer = &config->interface[ic]; for (i = 0; i < interfaceContainer->num_altsetting; i++) { const struct libusb_interface_descriptor *interface = &interfaceContainer->altsetting[i]; WiiHIDInterfaceDescriptor wii_interface; ConvertInterfaceToWii(&wii_interface, interface); Memory::WriteBigEData((const u8*)&wii_interface, OffsetBuffer, Align(wii_interface.bLength, 4)); OffsetBuffer += Align(wii_interface.bLength, 4); for (e = 0; e < interface->bNumEndpoints; e++) { const struct libusb_endpoint_descriptor *endpoint = &interface->endpoint[e]; WiiHIDEndpointDescriptor wii_endpoint; ConvertEndpointToWii(&wii_endpoint, endpoint); Memory::WriteBigEData((const u8*)&wii_endpoint, OffsetBuffer, Align(wii_endpoint.bLength, 4)); OffsetBuffer += Align(wii_endpoint.bLength, 4); } //endpoints } // interfaces } // interface containters libusb_free_config_descriptor(config); config = NULL; } else { if(cRet) DEBUG_LOG(WII_IPC_HID, "libusb_get_config_descriptor failed with: %d", cRet); deviceValid = false; OffsetBuffer = OffsetStart; } } // configs if (deviceValid) { Memory::Write_U32(OffsetBuffer-OffsetStart, OffsetStart); // fill in length int devNum = GetAvaiableDevNum(desc.idVendor, desc.idProduct, libusb_get_bus_number (device), libusb_get_device_address (device), check); if (devNum < 0 ) { // too many devices to handle. ERROR_LOG(WII_IPC_HID, "Exhausted device list, you have way too many usb devices plugged in." "Or it might be our fault. Let us know at https://code.google.com/p/dolphin-emu/issues/entry?template=Defect%%20report"); OffsetBuffer = OffsetStart; continue; } DEBUG_LOG(WII_IPC_HID, "Found device with Vendor: %X Product: %X Devnum: %d", desc.idVendor, desc.idProduct, devNum); Memory::Write_U32(devNum , OffsetStart+4); //write device num } } // Find devices that no longer exists and free them for (i=0; i<MAX_DEVICE_DEVNUM; i++) { u16 check_cur = (u16)(hidDeviceAliases[i] >> 48); if(hidDeviceAliases[i] != 0 && check_cur != check) { DEBUG_LOG(WII_IPC_HID, "Removing: device %d %hX %hX", i, check, check_cur); std::lock_guard<std::mutex> lk(s_open_devices); if (open_devices.find(i) != open_devices.end()) { libusb_device_handle *handle = open_devices[i]; libusb_close(handle); open_devices.erase(i); } hidDeviceAliases[i] = 0; } } check++; libusb_free_device_list(list, 1); Memory::Write_U32(0xFFFFFFFF, OffsetBuffer); // no more devices }
int main() { int i=0, cnt=0; unsigned short VID = 0x045e; //vendor id unsigned short PID = 0x00f7; //product id // unsigned char EP_out = 0x82; // write into usb end point // unsigned char EP_in = 0x01; // read from usb end point // unsigned char TX[] = {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00}; //reqwest // unsigned char RX[521]; //answer struct libusb_device_descriptor desc; //description of device structure libusb_device_handle *dev_handle = NULL; //a device handle libusb_context *ctx = NULL; //a libusb session libusb_device *dev = NULL; //pointer to device libusb_device **devs = NULL; //pointer to pointer of device int r; // ssize_t cnt; //holding number of devices in list //init libusb r = libusb_init(&ctx); if(r < 0) { printf("Init Error %d\n", r); // Ошибка инициализации сессии libusb return 1; } libusb_set_debug(ctx, 3); // get device list cnt = libusb_get_device_list(ctx, &devs); //get the list of devices printf("Количество устройств: %d\n", cnt); //get need device descriptor and number while ((dev = devs[i++]) != NULL) //take all connected device one by one { cnt = libusb_get_device_descriptor(dev, &desc); // look in deckritption of current device if(cnt == 0) printf("\tУстройство = VID:%04x, PID:%04x, Конф:%04x\n", desc.idVendor, desc.idProduct, desc.bNumConfigurations); //test device vendor and product identify if( desc.idVendor == VID && desc.idProduct == PID ) // if VID & PID is positive { // open device cnt = libusb_open(dev, &dev_handle); if(cnt == 0) printf("Открываем наше устройство:\n"); break; } } // Очищаем список устройств, убрираем ссылки на устройства в нем libusb_free_device_list(devs, 1); // test to enable device if ( dev_handle == NULL ) { printf("Устройство не найдено\n"); //exit work with usb libusb_exit(ctx); printf("Закрываем libusb\n"); return 0; } // test to device to grubed by kernel if(libusb_kernel_driver_active(dev_handle, 0) == 1) if(libusb_detach_kernel_driver(dev_handle, 0) == 0) //detach it printf("Отсоединяем устройство от драйвера ядра\n"); // config device cnt = libusb_set_configuration(dev_handle, 1); if(cnt == 0) printf("Устанавливаем конфигурацию\n"); // claim interface cnt = libusb_claim_interface(dev_handle, 0); if( cnt == 0 ) printf("Запрос %d интерфейса\n", cnt); // uint8_t index = valreg[0][1]; // uint8_t *buff; // cnt = sn9c102_write_reg(dev_handle, index, 1); // libusb_control_transfer(dev_handle, 0x41, 0x08, index, 0, buff, 1, TIMEOUT); // cnt = libusb_control_transfer(dev_handle, // 0x41, // 0x08, index, 0, // buff, 1, TIMEOUT); // (udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41, index, 0, data, len, SN9C102_CTRL_TIMEOUT); // printf("Read from device.\n\tReturn value = %d\n\tAccept bytes = %d\n",cnt); //static int sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) //{ // struct libusb_device *dev = //} //int sn9c102_write_regs(struct sn9c102_device* cam, const uint8_t valreg[][2], int count) //{ // struct libusb_d //} // send data block to device // cnt = libusb_bulk_transfer(dev_handle, EP_in, TX, sizeof(TX), &bTransfer, TIMEOUT); // printf("Write to device.\n\tReturn value = %d\n\tSend bytes = %s\n",cnt,buff); // read answer // cnt = libusb_bulk_transfer(dev_handle, EP_out, RX, sizeof(RX), &bTransfer, TIMEOUT); // printf("Read from device.\n\tReturn value = %d\n\tAccept bytes = %s\n",cnt,buff); //release the claimed interface cnt = libusb_release_interface(dev_handle, 0); if( cnt == 0 ) printf("Release 0 interface\n"); // close usb device libusb_close(dev_handle); printf("Close device\n"); //exit work with usb libusb_exit(ctx); printf("Exit libusb\n"); //erase dev_handle dev_handle = NULL; return 0; }
libusb_device_handle * CWII_IPC_HLE_Device_hid::GetDeviceByDevNum(u32 devNum) { u32 i; libusb_device **list; libusb_device_handle *handle = NULL; ssize_t cnt; if(devNum >= MAX_DEVICE_DEVNUM) return NULL; std::lock_guard<std::mutex> lk(s_open_devices); if (open_devices.find(devNum) != open_devices.end()) { handle = open_devices[devNum]; if(libusb_kernel_driver_active(handle, 0) != LIBUSB_ERROR_NO_DEVICE) { return handle; } else { libusb_close(handle); open_devices.erase(devNum); } } cnt = libusb_get_device_list(NULL, &list); if (cnt < 0) return NULL; for (i = 0; i < cnt; i++) { libusb_device *device = list[i]; struct libusb_device_descriptor desc; int dRet = libusb_get_device_descriptor (device, &desc); u8 bus = libusb_get_bus_number (device); u8 port = libusb_get_device_address (device); u64 unique_id = ((u64)desc.idVendor << 32) | ((u64)desc.idProduct << 16) | ((u64)bus << 8) | (u64)port; if ((hidDeviceAliases[devNum] & HID_ID_MASK) == unique_id) { int ret = libusb_open(device, &handle); if (ret) { if (ret == LIBUSB_ERROR_ACCESS) { if( dRet ) { ERROR_LOG(WII_IPC_HID, "Dolphin does not have access to this device: Bus %03d Device %03d: ID ????:???? (couldn't get id).", bus, port ); } else{ ERROR_LOG(WII_IPC_HID, "Dolphin does not have access to this device: Bus %03d Device %03d: ID %04X:%04X.", bus, port, desc.idVendor, desc.idProduct ); } } #ifdef _WIN32 else if (ret == LIBUSB_ERROR_NOT_SUPPORTED) { WARN_LOG(WII_IPC_HID, "Please install the libusb drivers for the device %04X:%04X", desc.idVendor, desc.idProduct); } #endif else { ERROR_LOG(WII_IPC_HID, "libusb_open failed to open device with error = %d", ret); } continue; } if (!ClaimDevice(handle)) { ERROR_LOG(WII_IPC_HID, "Could not claim the device for handle: %X", devNum); libusb_close(handle); continue; } open_devices[devNum] = handle; break; } else { handle = NULL; } } libusb_free_device_list(list, 1); return handle; }
/***************************************************************************** * * CloseUSB * ****************************************************************************/ status_t CloseUSB(unsigned int reader_index) { /* device not opened */ if (usbDevice[reader_index].dev_handle == NULL) return STATUS_UNSUCCESSFUL; DEBUG_COMM3("Closing USB device: %d/%d", usbDevice[reader_index].bus_number, usbDevice[reader_index].device_address); /* one slot closed */ (*usbDevice[reader_index].nb_opened_slots)--; /* release the allocated ressources for the last slot only */ if (0 == *usbDevice[reader_index].nb_opened_slots) { struct usbDevice_MultiSlot_Extension *msExt; DEBUG_COMM("Last slot closed. Release resources"); msExt = usbDevice[reader_index].multislot_extension; /* If this is a multislot reader, close using the multislot stuff */ if (msExt) { /* terminate the interrupt waiter thread */ Multi_PollingTerminate(msExt); /* wait for the thread to actually terminate */ pthread_join(msExt->thread_proc, NULL); /* release the shared objects */ pthread_cond_destroy(&msExt->condition); pthread_mutex_destroy(&msExt->mutex); /* Deallocate the extension itself */ free(msExt); /* Stop the slot */ usbDevice[reader_index].multislot_extension = NULL; } if (usbDevice[reader_index].ccid.gemalto_firmware_features) free(usbDevice[reader_index].ccid.gemalto_firmware_features); if (usbDevice[reader_index].ccid.sIFD_serial_number) free(usbDevice[reader_index].ccid.sIFD_serial_number); if (usbDevice[reader_index].ccid.sIFD_iManufacturer) free(usbDevice[reader_index].ccid.sIFD_iManufacturer); if (usbDevice[reader_index].ccid.arrayOfSupportedDataRates) free(usbDevice[reader_index].ccid.arrayOfSupportedDataRates); (void)libusb_release_interface(usbDevice[reader_index].dev_handle, usbDevice[reader_index].interface); (void)libusb_close(usbDevice[reader_index].dev_handle); } /* mark the resource unused */ usbDevice[reader_index].dev_handle = NULL; usbDevice[reader_index].interface = 0; close_libusb_if_needed(); return STATUS_SUCCESS; } /* CloseUSB */
static int usbOpenDevice(libusb_device_handle **device, int vendor, char *vendorName, int product, char *productName) { libusb_device_handle *handle = NULL; int errorCode = USB_ERROR_NOTFOUND; static int didUsbInit = 0; int j; int r; if(!didUsbInit){ didUsbInit = 1; libusb_init(&ctx); } libusb_device **dev_list; int dev_list_len = libusb_get_device_list(ctx, &dev_list); for (j=0; j<dev_list_len; ++j) { libusb_device *dev = dev_list[j]; struct libusb_device_descriptor descriptor; libusb_get_device_descriptor(dev, &descriptor); if (descriptor.idVendor == vendor && descriptor.idProduct == product) { char string[256]; /* we need to open the device in order to query strings */ r = libusb_open(dev, &handle); if (!handle) { errorCode = USB_ERROR_ACCESS; fprintf(stderr, "%s: Warning: cannot open USB device: %s\n", progname, strerror(libusb_to_errno(r))); continue; } if (vendorName == NULL && productName == NULL) { /* name does not matter */ break; } /* now check whether the names match: */ r = libusb_get_string_descriptor_ascii(handle, descriptor.iManufacturer & 0xff, string, sizeof(string)); if (r < 0) { errorCode = USB_ERROR_IO; fprintf(stderr, "%s: Warning: cannot query manufacturer for device: %s\n", progname, strerror(libusb_to_errno(r))); } else { errorCode = USB_ERROR_NOTFOUND; if (verbose > 1) fprintf(stderr, "%s: seen device from vendor ->%s<-\n", progname, string); if (strcmp(string, vendorName) == 0){ r = libusb_get_string_descriptor_ascii(handle, descriptor.iProduct & 0xff, string, sizeof(string)); if (r < 0) { errorCode = USB_ERROR_IO; fprintf(stderr, "%s: Warning: cannot query product for device: %s\n", progname, strerror(libusb_to_errno(r))); } else { errorCode = USB_ERROR_NOTFOUND; if (verbose > 1) fprintf(stderr, "%s: seen product ->%s<-\n", progname, string); if(strcmp(string, productName) == 0) break; } } } libusb_close(handle); handle = NULL; } } if (handle != NULL){ errorCode = 0; *device = handle; } return errorCode; }