Esempio n. 1
0
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);
}
Esempio n. 2
0
//  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();
}
Esempio n. 3
0
/*****************************************************************************
 *
 *					OpenUSBByName
 *
 ****************************************************************************/
status_t OpenUSBByName(unsigned int reader_index, /*@[email protected]*/ 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 */
Esempio n. 4
0
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;
	}
}
Esempio n. 5
0
void commdev_close(struct commdev_t *commdev)
{
    libusb_release_interface(commdev->handle, 0);
    libusb_close(commdev->handle);
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
void minipro_close(minipro_handle_t *handle) {
	libusb_close(handle->usb_handle);
	free(handle);
}
Esempio n. 8
0
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;
}
Esempio n. 9
0
File: usb.c Progetto: daladim/gammu
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;
}
Esempio n. 10
0
TankChassis::~TankChassis()
{
	libusb_release_interface(devh, 0);
    libusb_close(devh);
    libusb_exit(0);
}
Esempio n. 11
0
void usb_device_close(device_t *dev)
{
	libusb_release_interface(dev->handle, 0);
	libusb_close(dev->handle);
	free(dev);
}
Esempio n. 12
0
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;
    }
  }
}
Esempio n. 13
0
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;
}
Esempio n. 14
0
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;
}
Esempio n. 15
0
/* 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;
}
Esempio n. 16
0
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;
}
Esempio n. 17
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;
}
Esempio n. 18
0
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;
}
Esempio n. 19
0
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;
}
Esempio n. 20
0
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;
}
Esempio n. 21
0
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;
	}
}
Esempio n. 22
0
USBTransport::~USBTransport() {
    libusb_release_interface(m_device, 0);
    libusb_close(m_device);
}
Esempio n. 23
0
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;
}
Esempio n. 24
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;
}
Esempio n. 25
0
/**
 * 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;
}
Esempio n. 26
0
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

}
Esempio n. 27
0
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;
}
Esempio n. 28
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;
}
Esempio n. 29
0
/*****************************************************************************
 *
 *					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 */
Esempio n. 30
0
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;
}