From 0b624384cd52be20e61284551d832b499d7b7707 Mon Sep 17 00:00:00 2001 From: Jonathan McCrohan Date: Sat, 14 Apr 2012 12:56:48 +0100 Subject: Imported Upstream version 2.1.8.20120216 --- linux/cusblinux.c | 673 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 673 insertions(+) create mode 100644 linux/cusblinux.c (limited to 'linux/cusblinux.c') diff --git a/linux/cusblinux.c b/linux/cusblinux.c new file mode 100644 index 0000000..3a12fca --- /dev/null +++ b/linux/cusblinux.c @@ -0,0 +1,673 @@ +/* + * cusblinux.cpp + * + * Filled in by Daniel Risacher on 6/21/05 + * Filled in more by Patrick McNeil on 6/27/05 + * Copyright 2005 Phidgets Inc. All rights reserved. + * + */ + +#include "stdafx.h" +#include "cusb.h" + +int CUSBCloseHandle(CPhidgetHandle phid) { + int ret = 0; + int result = EPHIDGET_OK; + + if (!phid) + return EPHIDGET_INVALIDARG; + + CPhidget_clearStatusFlag(&phid->status, PHIDGET_ATTACHED_FLAG, &phid->lock); + + if (phid->deviceHandle == NULL) + return EPHIDGET_NOTATTACHED; + + CThread_join(&phid->readThread); + + if((ret = usb_release_interface((usb_dev_handle *) phid->deviceHandle, phid->deviceDef->pdd_iid)) < 0) + { + switch(ret) + { + case -ENODEV: + //usb_release_interface called after the device was unplugged + LOG(PHIDGET_LOG_WARNING, "usb_release_interface called on unplugged device."); + break; + default: + LOG(PHIDGET_LOG_ERROR, "usb_release_interface failed with error code: %d \"%s\"", ret, strerror(-ret)); + } + } + + //if we notice that PHIDGET_USB_ERROR_FLAG is set, then reset this device before closing + //this gives us a better chance of getting it back if something has gone wrong. + if(CPhidget_statusFlagIsSet(phid->status, PHIDGET_USB_ERROR_FLAG)) + { + LOG(PHIDGET_LOG_WARNING,"PHIDGET_USB_ERROR_FLAG is set - resetting device."); + if((ret = usb_reset((usb_dev_handle *) phid->deviceHandle)) < 0) + { + LOG(PHIDGET_LOG_ERROR, "usb_reset failed with error code: %d \"%s\"", ret, strerror(-ret)); + result = EPHIDGET_UNEXPECTED; + } + } + + if((ret = usb_close((usb_dev_handle *) phid->deviceHandle)) < 0) + { + LOG(PHIDGET_LOG_ERROR, "usb_close failed with error code: %d \"%s\"", ret, strerror(-ret)); + result = EPHIDGET_UNEXPECTED; + } + + phid->deviceHandle = NULL; + + return result; +} + +int CUSBSendPacket(CPhidgetHandle phid, unsigned char *buffer) { + int BytesWritten = 0; + + if (!phid) + return EPHIDGET_INVALIDARG; + + if (!CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG) + && !CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHING_FLAG)) + return EPHIDGET_NOTATTACHED; + + if (phid->deviceHandle == NULL) + { + LOG(PHIDGET_LOG_WARNING,"Handle for writing is not valid"); + return EPHIDGET_UNEXPECTED; + } + + if(phid->interruptOutEndpoint) + { + BytesWritten = usb_interrupt_write((usb_dev_handle *)phid->deviceHandle, + phid->deviceDef->pdd_iid+1, + (char *)buffer, + phid->outputReportByteLength, /* size */ + 500); /* FIXME? timeout */ + } + else + { + BytesWritten = usb_control_msg((usb_dev_handle *)phid->deviceHandle, + USB_ENDPOINT_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, + USB_REQ_SET_CONFIGURATION, + 0x0200, /* value */ + phid->deviceDef->pdd_iid, /* index*/ + (char *)buffer, + phid->outputReportByteLength, /* size */ + 500); /* FIXME? timeout */ + } + + if(BytesWritten < 0) + { + switch(BytesWritten) + { + case -ETIMEDOUT: //important case? + return EPHIDGET_TIMEOUT; + case -ENODEV: + //device is gone - unplugged. + LOG(PHIDGET_LOG_INFO, "Device was unplugged - detach."); + return EPHIDGET_NOTATTACHED; + default: + LOG(PHIDGET_LOG_ERROR, "usb_control_msg failed with error code: %d \"%s\"", BytesWritten, strerror(-BytesWritten)); + return EPHIDGET_UNEXPECTED; + } + } + + if (BytesWritten != phid->outputReportByteLength) + { + LOG(PHIDGET_LOG_WARNING,"Failure in CUSBSendPacket - Report Length" + ": %d, bytes written: %d", + (int)phid->outputReportByteLength, (int)BytesWritten); + return EPHIDGET_UNEXPECTED; + } + + return EPHIDGET_OK; +} + +int CUSBSetLabel(CPhidgetHandle phid, char *buffer) { + int BytesWritten = 0; + int size = buffer[0]; + + if(size>22) return EPHIDGET_INVALID; + + if (!phid) + return EPHIDGET_INVALIDARG; + + if (!CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG) + && !CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHING_FLAG)) + return EPHIDGET_NOTATTACHED; + + if (phid->deviceHandle == NULL) + { + LOG(PHIDGET_LOG_WARNING,"Handle for writing is not valid"); + return EPHIDGET_UNEXPECTED; + } + + BytesWritten = usb_control_msg(phid->deviceHandle, + USB_ENDPOINT_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, + USB_REQ_SET_DESCRIPTOR, + 0x0304, /* value */ + 0x0409, /* index*/ + (char *)buffer, + size, /* size */ + 500); /* FIXME? timeout */ + + if(BytesWritten < 0) + { + switch(BytesWritten) + { + case -ETIMEDOUT: //important case? + default: + LOG(PHIDGET_LOG_INFO, "usb_control_msg failed with error code: %d \"%s\"", BytesWritten, strerror(-BytesWritten)); + return EPHIDGET_UNSUPPORTED; + } + } + + if (BytesWritten != size) + { + LOG(PHIDGET_LOG_WARNING,"Failure in CUSBSetLabel - Report Length" + ": %d, bytes written: %d", + size, (int)BytesWritten); + return EPHIDGET_UNEXPECTED; + } + + return EPHIDGET_OK; +} + +/* Buffer should be at least 8 bytes long */ +int CUSBReadPacket(CPhidgetHandle phid, unsigned char *buffer) { + int BytesRead = 0; + + if (!phid) + return EPHIDGET_INVALIDARG; + + if (!CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG) + && !CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHING_FLAG)) + return EPHIDGET_NOTATTACHED; + + if (phid->deviceHandle == NULL) + { + LOG(PHIDGET_LOG_WARNING,"Handle for writing is not valid"); + return EPHIDGET_UNEXPECTED; + } + + BytesRead = usb_interrupt_read((usb_dev_handle *)phid->deviceHandle, + phid->deviceDef->pdd_iid+1, + (char *)buffer, + phid->inputReportByteLength, + 500); + + if (BytesRead < 0) + { + switch(BytesRead) + { + // A timeout occured, but we'll just try again + case -ETIMEDOUT: + LOG(PHIDGET_LOG_VERBOSE, "usb_interrupt_read timeout: %d \"%s\"", BytesRead, strerror(-BytesRead)); + return EPHIDGET_TIMEOUT; + case -EBUSY: + //This happens when someone else calls claim_interface on this interface (a manager for ex.) - basically just wait until they release it. + //This will happen if an open occurs in another app which (for some reason) can steal the interface from this one. + LOG(PHIDGET_LOG_INFO, "Device is busy on Read - try again."); + return EPHIDGET_TRYAGAIN; + case -ENOSPC: + //This happens when too many Interrupt devices are plugged in (Phidgets, HID devices, etc. + LOG(PHIDGET_LOG_ERROR, "USB Interrupt bandwidth exceeded. Try distributing devices more evenly. Reads will continue, but data is being lost."); + goto tryagain; + case -ENODEV: + //device is gone - unplugged. + LOG(PHIDGET_LOG_INFO, "Device was unplugged - detach."); + return EPHIDGET_NOTATTACHED; + default: + LOG(PHIDGET_LOG_ERROR, "usb_interrupt_read returned: %d \"%s\"", BytesRead, strerror(-BytesRead)); + goto tryagain; + } + } + + if (BytesRead != phid->inputReportByteLength) + { + //Generally means the device was unplugged, but can mean that there is not enough Interrupt bandwidth + //We keep trying and we'll get data, just not all data + LOG(PHIDGET_LOG_WARNING,"Failure in CUSBReadPacket - Report Length" + ": %d, bytes read: %d. Probably trying to use too many Phidgets at once, and some data is being lost.", + (int)phid->inputReportByteLength, (int)BytesRead); + goto tryagain; + } + + phid->tryAgainCounter = 0; + return EPHIDGET_OK; + + //if we see too many tryagains in a row, then we assume something has actually gone wrong and reset the device +tryagain: + phid->tryAgainCounter++; + if(phid->tryAgainCounter > 30) //this will be hit in < 1 second for all devices + { + LOG(PHIDGET_LOG_ERROR, "CUSBReadPacket returned EPHIDGET_TRYAGAIN too many times in a row - reset device.", BytesRead, strerror(-BytesRead)); + phid->tryAgainCounter = 0; + return EPHIDGET_UNEXPECTED; + } + return EPHIDGET_TRYAGAIN; +} + +static int getLabelString(CPhidgetHandle phid, struct usb_dev_handle *udev) +{ + int len = 0; + char labelBuf[22]; + memset(labelBuf, 0, sizeof(labelBuf)); + + //Note that this returns the whole descriptor, including the length and type bytes + len = usb_get_string(udev, 4, 0, (char *)labelBuf, 22); + + if(len < 0) + { + switch(len) + { + case -ETIMEDOUT: //important case? + default: + LOG(PHIDGET_LOG_INFO, "usb_get_string_simple failed in CUSBGetDeviceCapabilities with error code: %d \"%s\" while reading label - this probably just means the device doesn't support labels, so this is fine.", len, strerror(-len)); + } + phid->label[0]='\0'; + return EPHIDGET_OK; + } + else + return decodeLabelString(labelBuf, phid->label, phid->serialNumber); +} + +int CUSBRefreshLabelString(CPhidgetHandle phid) +{ + return getLabelString(phid, (struct usb_dev_handle *)phid->deviceHandle); +} + +int CUSBGetDeviceCapabilities(CPhidgetHandle phid, struct usb_device *dev, struct usb_dev_handle *udev) { + unsigned char buf[255]; + int len = 0, i = 0; + struct usb_interface_descriptor *interfaceDesc; + struct usb_config_descriptor configDesc; + + memset(buf, 0, sizeof(buf)); + +// if(usb_device->config->interface->bNumEndpoints == 2) +// { +// LOG(PHIDGET_LOG_INFO, "Using Interrupt OUT endpoing to Host->Device communication."); +// phid->interruptOutEndpoint = PTRUE; +// } +// else +// { +// LOG(PHIDGET_LOG_INFO, "Using Control endpoing to Host->Device communication."); +// phid->interruptOutEndpoint = PFALSE; +// } + + //Get config descriptor + len = usb_get_descriptor(udev, USB_DT_CONFIG, 0, (void *)&configDesc, USB_DT_CONFIG_SIZE); + + if(len == USB_DT_CONFIG_SIZE) + { + //Get the rest + len = usb_get_descriptor(udev, USB_DT_CONFIG, 0, (void *)buf, configDesc.wTotalLength); + + if(len == configDesc.wTotalLength) + { + int i; + interfaceDesc = NULL; + struct usb_descriptor_header *currentDesc; + + //Find the interface Descriptor + for(i=0;ibLength) + { + currentDesc = (struct usb_descriptor_header *)&buf[i]; + if (currentDesc->bDescriptorType == USB_DT_INTERFACE) + { + interfaceDesc = (struct usb_interface_descriptor *)&buf[i]; + if(interfaceDesc->bInterfaceNumber == phid->deviceDef->pdd_iid) + break; + else + interfaceDesc = NULL; + } + } + + if(interfaceDesc == NULL) + { + LOG(PHIDGET_LOG_ERROR, "Couldn't find interface descriptor!"); + return EPHIDGET_UNEXPECTED; + } + + if(interfaceDesc->bNumEndpoints == 2) + { + LOG(PHIDGET_LOG_INFO, "Using Interrupt OUT Endpoint for Host->Device communication."); + phid->interruptOutEndpoint = PTRUE; + } + else + { + LOG(PHIDGET_LOG_INFO, "Using Control Endpoint for Host->Device communication."); + phid->interruptOutEndpoint = PFALSE; + } + } + else if (len < 0) + { + LOG(PHIDGET_LOG_ERROR, "usb_get_descriptor failed in CUSBGetDeviceCapabilities with error code: %d \"%s\"", len, strerror(-len)); + return EPHIDGET_UNEXPECTED; + } + else + { + LOG(PHIDGET_LOG_ERROR, "Couldn't get interface descriptor in CUSBGetDeviceCapabilities"); + return EPHIDGET_UNEXPECTED; + } + } + else if (len < 0) + { + LOG(PHIDGET_LOG_ERROR, "usb_get_descriptor failed in CUSBGetDeviceCapabilities with error code: %d \"%s\"", len, strerror(-len)); + return EPHIDGET_UNEXPECTED; + } + else + { + LOG(PHIDGET_LOG_ERROR, "Couldn't get interface descriptor in CUSBGetDeviceCapabilities"); + return EPHIDGET_UNEXPECTED; + } + + //Get a HID descriptor + len = usb_control_msg(udev, USB_ENDPOINT_IN+1, + USB_REQ_GET_DESCRIPTOR, + (USB_DT_REPORT << 8) + 0, phid->deviceDef->pdd_iid, (char*)buf, + sizeof(buf), 500 /* ms timeout */); + + if(len < 0) + { + switch(len) + { + case -ETIMEDOUT: //important case? + default: + LOG(PHIDGET_LOG_ERROR, "usb_control_msg failed in CUSBGetDeviceCapabilities with error code: %d \"%s\"", len, strerror(-len)); + return EPHIDGET_UNEXPECTED; + } + } + + if(len >= 10) + { + for(i=10;iinputReportByteLength=buf[i-1]; + else if(buf[i]==0x81 && buf[i-4]==0x95) + phid->inputReportByteLength=buf[i-3]; + if(buf[i]==0x91 && buf[i-2]==0x95) + phid->outputReportByteLength=buf[i-1]; + else if(buf[i]==0x91 && buf[i-4]==0x95) + phid->outputReportByteLength=buf[i-3]; + } + } + else + { + LOG(PHIDGET_LOG_ERROR, "Couldn't get report lengths in CUSBGetDeviceCapabilities"); + return EPHIDGET_UNEXPECTED; + } + + return getLabelString(phid, udev); +} + +/* + This needs to maintain a list of devices - it's used by the phidget manager for + keeping track of attach and detach events. (On Mac this is handled with + notifications, so this is not needed.) - PM +*/ +int CUSBBuildList(CPhidgetList **curList) { + int MemberIndex, i, ret, found; + unsigned long Length; + CPhidgetList *traverse; + Length = 0; + MemberIndex = 0; + struct usb_bus *bus; + struct usb_device *dev; + usb_dev_handle *udev; + CPhidgetHandle phid; + char unique_name[1024]; + + TESTPTR(curList) + + usb_init(); + if((ret = usb_find_busses()) < 0) + { + LOG(PHIDGET_LOG_ERROR, "usb_find_busses failed with error code: %d \"%s\"", ret, strerror(-ret)); + } + if((ret = usb_find_devices()) < 0) + { + LOG(PHIDGET_LOG_ERROR, "usb_find_devices failed with error code: %d \"%s\"", ret, strerror(-ret)); + } + + //search through all USB devices + for (bus = usb_busses; bus; bus = bus->next) { + for (dev = bus->devices; dev; dev = dev->next) { + + snprintf(unique_name,1024,"%s%s",bus->dirname, dev->filename); + + //LOG(PHIDGET_LOG_VERBOSE,"New Device: %s", unique_name); + + found = PFALSE; + if (AttachedDevices) { + // we need to loop all the way through because composite devices will appear twice in the list with the same 'unique' name + for (traverse = AttachedDevices; traverse; traverse=traverse->next) { + if (!strcmp((char *)traverse->phid->CPhidgetFHandle, unique_name)) { + CList_addToList((CListHandle *)curList, traverse->phid, CPhidget_areEqual); + found = PTRUE; + } + } + if(found) goto next; + } + + + for (i = 1; idescriptor.idVendor == Phid_Device_Def[i].pdd_vid) && + (dev->descriptor.idProduct == Phid_Device_Def[i].pdd_pid)) + { + if (!(phid = (CPhidgetHandle)malloc(sizeof (*phid)))) + return EPHIDGET_NOMEMORY; + ZEROMEM(phid, sizeof(*phid)); + + //LOG(PHIDGET_LOG_DEBUG,"New Device: %s",(char *)Phid_DeviceName[Phid_Device_Def[i].pdd_did]); + + udev = usb_open(dev); + if(udev) { + if (dev->descriptor.bcdDevice < 0x100) + phid->deviceVersion = dev->descriptor.bcdDevice * 100; + else + phid->deviceVersion = ((dev->descriptor.bcdDevice >> 8) * 100) + ((dev->descriptor.bcdDevice & 0xff)); + phid->deviceType = (char *)Phid_DeviceName[Phid_Device_Def[i].pdd_did]; + + CPhidget_setStatusFlag(&phid->status, PHIDGET_ATTACHED_FLAG, &phid->lock); + phid->deviceIDSpec = Phid_Device_Def[i].pdd_sdid; + phid->deviceDef = &Phid_Device_Def[i]; + phid->deviceID = Phid_Device_Def[i].pdd_did; + phid->ProductID = dev->descriptor.idProduct; + phid->VendorID = dev->descriptor.idVendor; + + if (dev->descriptor.iSerialNumber) { + char string[256]; + memset(string, 0, 256); + if((ret = usb_get_string_simple(udev, dev->descriptor.iSerialNumber, string, sizeof(string))) < 0) + { + LOG(PHIDGET_LOG_ERROR, "usb_get_string_simple failed with error code: %d \"%s\"", ret, strerror(-ret)); + LOG(PHIDGET_LOG_INFO, "This usually means you need to run as root"); + if((ret = usb_close(udev)) < 0) + { + LOG(PHIDGET_LOG_ERROR, "usb_close failed with error code: %d \"%s\"", ret, strerror(-ret)); + } + free(phid); + goto next; + } + else + { + phid->serialNumber = atol(string); + getLabelString(phid, udev); + } + } + phid->specificDevice = TRUE; + phid->attr = Phid_Device_Def[i].pdd_attr; + + if(!(phid->CPhidgetFHandle = strdup(unique_name))) + return EPHIDGET_NOMEMORY; + + LOG(PHIDGET_LOG_INFO, "New device in CUSBBuildList: %s", (char *)phid->CPhidgetFHandle); + + if((ret = usb_close(udev)) < 0) + { + LOG(PHIDGET_LOG_ERROR, "usb_close failed with error code: %d \"%s\"", ret, strerror(-ret)); + } + CList_addToList((CListHandle *)curList, phid, CPhidget_areEqual); + } //if(udev) + else + { + free(phid); + if((ret = usb_close(udev)) < 0) + { + LOG(PHIDGET_LOG_ERROR, "usb_close failed with error code: %d \"%s\"", ret, strerror(-ret)); + } + } + } //vendor, product ids match + } /* iterate over phidget device table */ +next: ; + } /* iterate over USB devices */ + } /* iterate over USB busses */ + return EPHIDGET_OK; +} + +void CUSBCleanup(void) +{ + ; +} +/* + CUSBOpenHandle takes a CPhidgetInfo structure, with + ProductID/VendorID/SerialNumber filled in. + + Serial number is always filled in. +*/ +int CUSBOpenHandle(CPhidgetHandle phid) +{ + int idVendor; + int idProduct; + int serial = 0; + int i,ret; + struct usb_bus *bus; + struct usb_device *dev; + usb_dev_handle *udev; + + usb_init(); + if((ret = usb_find_busses()) < 0) + { + LOG(PHIDGET_LOG_ERROR, "usb_find_busses failed with error code: %d \"%s\"", ret, strerror(-ret)); + } + if((ret = usb_find_devices()) < 0) + { + LOG(PHIDGET_LOG_ERROR, "usb_find_devices failed with error code: %d \"%s\"", ret, strerror(-ret)); + } + + for (bus = usb_busses; bus; bus = bus->next) { + for (dev = bus->devices; dev; dev = dev->next) { + for (i = 1; ideviceID) { + idVendor = Phid_Device_Def[i].pdd_vid; + idProduct = Phid_Device_Def[i].pdd_pid; + if ((dev->descriptor.idVendor == idVendor) && (dev->descriptor.idProduct == idProduct)) { + /* the vend/prod matches! */ + udev = usb_open(dev); + if (udev) { + serial = -1; + if (dev->descriptor.iSerialNumber) { + char string[256]; + if((ret = usb_get_string_simple(udev, dev->descriptor.iSerialNumber, string, sizeof(string))) < 0) + { + LOG(PHIDGET_LOG_WARNING, "usb_get_string_simple failed with error code: %d \"%s\"", ret, strerror(-ret)); + LOG(PHIDGET_LOG_INFO, "This usually means you need to run as root"); + if((ret = usb_close(udev)) < 0) + { + LOG(PHIDGET_LOG_ERROR, "usb_close failed with error code: %d \"%s\"", ret, strerror(-ret)); + } + goto next; + } + else + { + serial = atol(string); + } + } + if (serial == phid->serialNumber) { + /* On Linux, the HID driver likes to claim Phidgets - we can disconnect it here. + Maybe the user has installed the kernel drivers for the interface kit or servo - disconnect them too (does this work) + Note this is Linux Only - PM + Note that we don't need to claim it if usbfs has it - this is what libusb uses. */ +#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP + char name[32]; + if((ret = usb_get_driver_np(udev, Phid_Device_Def[i].pdd_iid, name, 32)) < 0) + { + LOG(PHIDGET_LOG_WARNING, "usb_get_driver_np failed with error code: %d \"%s\"", ret, strerror(-ret)); + } + else + { + LOG(PHIDGET_LOG_INFO, "Kernel driver name: %s", name); + if(strncmp(name, "usbfs", 5)) //not usbfs + { + if((ret = usb_detach_kernel_driver_np(udev, Phid_Device_Def[i].pdd_iid)) < 0) + { + LOG(PHIDGET_LOG_WARNING, "usb_detach_kernel_driver_np failed with error code: %d \"%s\"", ret, strerror(-ret)); + } + else + { + LOG(PHIDGET_LOG_INFO, "Successfully detached kernel driver: %s", name); + } + } + } +#endif + if((ret = usb_claim_interface(udev, Phid_Device_Def[i].pdd_iid)) < 0) + { + LOG(PHIDGET_LOG_WARNING, "usb_claim_interface failed with error code: %d \"%s\"", ret, strerror(-ret)); + if((ret = usb_close(udev)) < 0) + { + LOG(PHIDGET_LOG_ERROR, "usb_close failed with error code: %d \"%s\"", ret, strerror(-ret)); + } + } + else + { + /* the serialnum is okay */ + + phid->deviceHandle = (HANDLE)udev; + phid->deviceIDSpec = Phid_Device_Def[i].pdd_sdid; + phid->deviceDef = &Phid_Device_Def[i]; + phid->deviceType = (char *)Phid_DeviceName[Phid_Device_Def[i].pdd_did]; + + phid->ProductID = idProduct; + phid->VendorID = idVendor; + if (dev->descriptor.bcdDevice < 0x100) + phid->deviceVersion = dev->descriptor.bcdDevice * 100; + else + phid->deviceVersion = ((dev->descriptor.bcdDevice >> 8) * 100) + ((dev->descriptor.bcdDevice & 0xff)); + phid->serialNumber = serial; + + if((ret = CUSBGetDeviceCapabilities(phid, dev, udev))) + { + LOG(PHIDGET_LOG_ERROR, "CUSBGetDeviceCapabilities returned nonzero code: %d", ret); + } + + phid->attr = Phid_Device_Def[i].pdd_attr; + + return EPHIDGET_OK; + } /* usb_claim_interface */ + } /* serial matches */ + else + { + if((ret = usb_close(udev)) < 0) + { + LOG(PHIDGET_LOG_ERROR, "usb_close failed with error code: %d \"%s\"", ret, strerror(-ret)); + } + } + } /* udev open */ + else + { + if((ret = usb_close(udev)) < 0) + { + LOG(PHIDGET_LOG_ERROR, "usb_close failed with error code: %d \"%s\"", ret, strerror(-ret)); + } + LOG(PHIDGET_LOG_WARNING, "usb_open failed - bad permission or what?"); + } + } /* vendor/product match */ + } /* deviceID matches in table */ + } /* iterate over phidget device table */ +next: ; + } /* iterate over USB devices */ + } /* iterate over USB busses */ + return EPHIDGET_NOTFOUND; +} -- cgit v1.2.3