aboutsummaryrefslogtreecommitdiffstats
path: root/linux/cusblinux-1.0.c
diff options
context:
space:
mode:
authorJonathan McCrohan <jmccrohan@gmail.com>2012-10-19 19:38:06 +0100
committerJonathan McCrohan <jmccrohan@gmail.com>2012-10-19 19:38:06 +0100
commit2891593727a0151a66ed7860fed6399548c74c02 (patch)
tree1cb52da179b4ab23ba2a22f44d88ea3523f51f0c /linux/cusblinux-1.0.c
parentcff96463a694573a9f87b014482a45c25bf4c7b0 (diff)
parent8f3c91e91b634adaca77dac6cf314445cceefc78 (diff)
downloadlibphidget21-2891593727a0151a66ed7860fed6399548c74c02.tar.gz
Merge tag 'upstream/2.1.8.20120912'
Upstream version 2.1.8.20120912
Diffstat (limited to '')
-rw-r--r--linux/cusblinux-1.0.c233
1 files changed, 169 insertions, 64 deletions
diff --git a/linux/cusblinux-1.0.c b/linux/cusblinux-1.0.c
index 204ef53..0e3a5e8 100644
--- a/linux/cusblinux-1.0.c
+++ b/linux/cusblinux-1.0.c
@@ -10,6 +10,8 @@
#include "stdafx.h"
#include "cusb.h"
#include <libusb-1.0/libusb.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
int CUSBCloseHandle(CPhidgetHandle phid) {
int ret = 0;
@@ -106,7 +108,10 @@ int CUSBSendPacket(CPhidgetHandle phid, unsigned char *buffer) {
LOG(PHIDGET_LOG_INFO, "Device was unplugged - detach.");
return EPHIDGET_NOTATTACHED;
default:
- LOG(PHIDGET_LOG_ERROR, "libusb_control_msg failed with error code: %d", ret);
+ if(phid->interruptOutEndpoint)
+ LOG(PHIDGET_LOG_ERROR, "libusb_interrupt_transfer failed in CUSBSendPacket with error code: %d", ret);
+ else
+ LOG(PHIDGET_LOG_ERROR, "libusb_control_msg failed in CUSBSendPacket with error code: %d", ret);
return EPHIDGET_UNEXPECTED;
}
}
@@ -123,53 +128,60 @@ int CUSBSendPacket(CPhidgetHandle phid, unsigned char *buffer) {
}
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)
+ if(deviceSupportsGeneralUSBProtocol(phid))
{
- LOG(PHIDGET_LOG_WARNING,"Handle for writing is not valid");
- return EPHIDGET_UNEXPECTED;
+ return CPhidgetGPP_setLabel(phid, buffer);
}
-
- BytesWritten = libusb_control_transfer((libusb_device_handle *)phid->deviceHandle,
- LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE,
- LIBUSB_REQUEST_SET_DESCRIPTOR,
- 0x0304, /* value */
- 0x0409, /* index*/
- (char *)buffer,
- size, /* size */
- 500); /* FIXME? timeout */
-
- if(BytesWritten < 0)
+ else
{
- switch(BytesWritten)
+ 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)
{
- case LIBUSB_ERROR_TIMEOUT: //important case?
- default:
- LOG(PHIDGET_LOG_INFO, "usb_control_msg failed with error code: %d", BytesWritten);
- return EPHIDGET_UNSUPPORTED;
+ LOG(PHIDGET_LOG_WARNING,"Handle for writing is not valid");
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ BytesWritten = libusb_control_transfer((libusb_device_handle *)phid->deviceHandle,
+ LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE,
+ LIBUSB_REQUEST_SET_DESCRIPTOR,
+ 0x0304, /* value */
+ 0x0409, /* index*/
+ (char *)buffer,
+ size, /* size */
+ 500); /* FIXME? timeout */
+
+ if(BytesWritten < 0)
+ {
+ switch(BytesWritten)
+ {
+ case LIBUSB_ERROR_TIMEOUT: //important case?
+ default:
+ LOG(PHIDGET_LOG_INFO, "usb_control_msg failed in CUSBSetLabel with error code: %d", 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;
+ 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;
}
-
- return EPHIDGET_OK;
}
/* Buffer should be at least 8 bytes long */
@@ -202,7 +214,7 @@ int CUSBReadPacket(CPhidgetHandle phid, unsigned char *buffer) {
{
// A timeout occured, but we'll just try again
case LIBUSB_ERROR_TIMEOUT:
- LOG(PHIDGET_LOG_VERBOSE, "libusb_interrupt_transfer timeout");
+ LOG(PHIDGET_LOG_VERBOSE, "libusb_interrupt_transfer timeout in CUSBReadPacket");
return EPHIDGET_TIMEOUT;
case LIBUSB_ERROR_BUSY:
//This happens when someone else calls claim_interface on this interface (a manager for ex.) - basically just wait until they release it.
@@ -216,7 +228,7 @@ int CUSBReadPacket(CPhidgetHandle phid, unsigned char *buffer) {
case LIBUSB_ERROR_PIPE:
case LIBUSB_ERROR_OVERFLOW:
default:
- LOG(PHIDGET_LOG_ERROR, "libusb_interrupt_transfer returned: %d \"%s\"", ret);
+ LOG(PHIDGET_LOG_ERROR, "libusb_interrupt_transfer in CUSBReadPacket returned: %d", ret);
goto tryagain;
}
}
@@ -248,27 +260,42 @@ tryagain:
static int getLabelString(CPhidgetHandle phid, struct libusb_device_handle *handle)
{
- int len = 0;
+ int len = 0, ret;
char labelBuf[22];
memset(labelBuf, 0, sizeof(labelBuf));
+ libusb_device *device = libusb_get_device(handle);
+ struct libusb_device_descriptor desc;
- //Note that this returns the whole descriptor, including the length and type bytes
- len = libusb_get_string_descriptor(handle, 4, 0, (char *)labelBuf, 22);
+ if((ret = libusb_get_device_descriptor(device, &desc)) != 0)
+ {
+ LOG(PHIDGET_LOG_ERROR, "libusb_get_device_descriptor failed with error code: %d", ret);
+ return EPHIDGET_UNEXPECTED;
+ }
- if(len < 0)
+ if(desc.iSerialNumber == 3)
{
- switch(len)
+
+ //Note that this returns the whole descriptor, including the length and type bytes
+ len = libusb_get_string_descriptor(handle, 4, 0, (char *)labelBuf, 22);
+
+ if(len < 0)
{
- case LIBUSB_ERROR_TIMEOUT: //important case?
- default:
- LOG(PHIDGET_LOG_INFO, "libusb_get_string_descriptor failed in CUSBGetDeviceCapabilities with error code: %d while reading label"\
- " - this probably just means the device doesn't support labels, so this is fine.", len);
+ switch(len)
+ {
+ case LIBUSB_ERROR_TIMEOUT: //important case?
+ default:
+ LOG(PHIDGET_LOG_INFO, "libusb_get_string_descriptor failed in CUSBGetDeviceCapabilities with error code: %d while reading label"\
+ " - this probably just means the device doesn't support labels, so this is fine.", len);
+ }
+ phid->label[0]='\0';
+ return EPHIDGET_OK;
}
- phid->label[0]='\0';
- return EPHIDGET_OK;
+ else
+ return decodeLabelString(labelBuf, phid->label, phid->serialNumber);
}
- else
- return decodeLabelString(labelBuf, phid->label, phid->serialNumber);
+
+ phid->label[0]='\0';
+ return EPHIDGET_OK;
}
int CUSBRefreshLabelString(CPhidgetHandle phid)
@@ -488,6 +515,15 @@ int CUSBBuildList(CPhidgetList **curList) {
getLabelString(phid, handle);
}
}
+ if (desc.iProduct) {
+ if((ret = libusb_get_string_descriptor_ascii(handle, desc.iProduct, phid->usbProduct, sizeof(phid->usbProduct))) < 0)
+ {
+ LOG(PHIDGET_LOG_ERROR, "libusb_get_string_descriptor_ascii failed with error code: %d", ret);
+ libusb_close(handle);
+ free(phid);
+ goto next;
+ }
+ }
phid->specificDevice = TRUE;
phid->attr = Phid_Device_Def[i].pdd_attr;
@@ -520,6 +556,49 @@ done:
return ret;
}
+/*
+ * Got this from libusb-0.1 because 1.0 doesn't expose driver name!
+ */
+#define USB_MAXDRIVERNAME 255
+struct usb_getdriver {
+ unsigned int interface;
+ char driver[USB_MAXDRIVERNAME + 1];
+};
+struct linux_device_handle_priv {
+ int fd;
+};
+struct list_head {
+ struct list_head *prev, *next;
+};
+struct libusb_device_handle_internal {
+ pthread_mutex_t lock;
+ unsigned long claimed_interfaces;
+ struct list_head list;
+ void *dev;
+ unsigned char os_priv[0];
+};
+static struct linux_device_handle_priv *_device_handle_priv(struct libusb_device_handle_internal *handle)
+{
+ return (struct linux_device_handle_priv *) handle->os_priv;
+}
+#define IOCTL_USB_GETDRIVER _IOW('U', 8, struct usb_getdriver)
+static int libusb_get_driver_name(libusb_device_handle *handle, int interface, char *name, unsigned int namelen)
+{
+ int fd = _device_handle_priv((struct libusb_device_handle_internal *)handle)->fd;
+ struct usb_getdriver getdrv;
+ int ret;
+
+ getdrv.interface = interface;
+ ret = ioctl(fd, IOCTL_USB_GETDRIVER, &getdrv);
+ if (ret)
+ LOG(PHIDGET_LOG_ERROR, "could not get bound driver: %d", errno);
+
+ strncpy(name, getdrv.driver, namelen - 1);
+ name[namelen - 1] = 0;
+
+ return 0;
+}
+
void CUSBCleanup(void)
{
;
@@ -535,7 +614,7 @@ int CUSBOpenHandle(CPhidgetHandle phid)
int idVendor;
int idProduct;
int serial = 0;
- int i, j,ret = EPHIDGET_OK;
+ int i, j, ret, retVal = EPHIDGET_NOTFOUND;
libusb_device **list = NULL;
ssize_t cnt = libusb_get_device_list(libusbContext, &list);
@@ -582,6 +661,15 @@ int CUSBOpenHandle(CPhidgetHandle phid)
serial = atol(string);
}
}
+ if (desc.iProduct) {
+ if((ret = libusb_get_string_descriptor_ascii(handle, desc.iProduct, phid->usbProduct, sizeof(phid->usbProduct))) < 0)
+ {
+ LOG(PHIDGET_LOG_ERROR, "libusb_get_string_descriptor_ascii failed with error code: %d", ret);
+ libusb_close(handle);
+ free(phid);
+ goto next;
+ }
+ }
if (serial == phid->serialNumber) {
//Detach any Kernel Drivers
if((ret = libusb_kernel_driver_active(handle, Phid_Device_Def[i].pdd_iid)) < 0)
@@ -590,20 +678,37 @@ int CUSBOpenHandle(CPhidgetHandle phid)
}
else if(ret == 1)
{
- LOG(PHIDGET_LOG_INFO, "Kernel driver is active - will attempt a detach");
- if((ret = libusb_detach_kernel_driver(handle, Phid_Device_Def[i].pdd_iid)) != 0)
+ char name[64];
+ if((ret = libusb_get_driver_name(handle, Phid_Device_Def[i].pdd_iid, name, 32)) < 0)
{
- LOG(PHIDGET_LOG_WARNING, "libusb_detach_kernel_driver failed with error code: %d", ret);
+ LOG(PHIDGET_LOG_WARNING, "libusb_get_driver_name failed with error code: %d", ret);
}
else
{
- LOG(PHIDGET_LOG_INFO, "Successfully detached kernel driver");
+ LOG(PHIDGET_LOG_INFO, "Kernel driver name: %s", name);
+ if(strncmp(name, "usbfs", 5)) //not usbfs
+ {
+ LOG(PHIDGET_LOG_INFO, "Kernel driver is active - will attempt a detach");
+ if((ret = libusb_detach_kernel_driver(handle, Phid_Device_Def[i].pdd_iid)) != 0)
+ {
+ LOG(PHIDGET_LOG_WARNING, "libusb_detach_kernel_driver failed with error code: %d", ret);
+ }
+ else
+ {
+ LOG(PHIDGET_LOG_INFO, "Successfully detached kernel driver");
+ }
+ }
+ else
+ LOG(PHIDGET_LOG_INFO, "Not detaching kernel driver - already using usbfs.");
}
}
if((ret = libusb_claim_interface(handle, Phid_Device_Def[i].pdd_iid)) != 0)
{
- LOG(PHIDGET_LOG_WARNING, "libusb_claim_interface failed with error code: %d", ret);
+ if(ret == LIBUSB_ERROR_BUSY)
+ LOG(PHIDGET_LOG_WARNING, "libusb_claim_interface failed with BUSY - probably the device is opened by another program.");
+ else
+ LOG(PHIDGET_LOG_WARNING, "libusb_claim_interface failed with error code: %d", ret);
libusb_close(handle);
}
else
@@ -632,7 +737,7 @@ int CUSBOpenHandle(CPhidgetHandle phid)
phid->attr = Phid_Device_Def[i].pdd_attr;
- ret = EPHIDGET_OK;
+ retVal = EPHIDGET_OK;
goto done;
} /* usb_claim_interface */
} /* serial matches */
@@ -656,5 +761,5 @@ done:
if(list)
libusb_free_device_list(list, 1);
- return ret;
+ return retVal;
}