* There were a few (new) usbdevfs capabilities which libusbx could not
discover in any other way then checking the kernel version.
* However, this presents the following problems:
1) It is just not very pretty
2) Given the tendency of enterprise distros to backport stuff it is not
reliable
3) Some of these features turn out to not work with certain host controllers,
making depending on them based on the kernel version not a good idea
* Therefore a new USBDEVFS_GET_CAPABILITIES ioctl has been added to the kernel
to offer a better way to find out a device's capabilities (technically
the capabilities of the host controller to which the device is attached,
but that does not matter).
struct linux_device_handle_priv {
int fd;
struct linux_device_handle_priv {
int fd;
{
struct linux_device_handle_priv *hpriv = _device_handle_priv(handle);
char filename[PATH_MAX];
{
struct linux_device_handle_priv *hpriv = _device_handle_priv(handle);
char filename[PATH_MAX];
_get_usbfs_path(handle->dev, filename);
usbi_dbg("opening %s", filename);
_get_usbfs_path(handle->dev, filename);
usbi_dbg("opening %s", filename);
+ r = ioctl(hpriv->fd, IOCTL_USBFS_GET_CAPABILITIES, &hpriv->caps);
+ if (r < 0) {
+ if (errno == ENOTTY)
+ usbi_dbg("%s: getcap not available", filename);
+ else
+ usbi_err(HANDLE_CTX(handle),
+ "%s: getcap failed (%d)", filename, errno);
+ hpriv->caps = 0;
+ if (supports_flag_zero_packet)
+ hpriv->caps |= USBFS_CAP_ZERO_PACKET;
+ if (supports_flag_bulk_continuation)
+ hpriv->caps |= USBFS_CAP_BULK_CONTINUATION;
+ }
+
return usbi_add_pollfd(HANDLE_CTX(handle), hpriv->fd, POLLOUT);
}
return usbi_add_pollfd(HANDLE_CTX(handle), hpriv->fd, POLLOUT);
}
if (tpriv->urbs)
return LIBUSB_ERROR_BUSY;
if (tpriv->urbs)
return LIBUSB_ERROR_BUSY;
- if (is_out && transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET &&
- !supports_flag_zero_packet)
+ if (is_out && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) &&
+ !(dpriv->caps & USBFS_CAP_ZERO_PACKET))
return LIBUSB_ERROR_NOT_SUPPORTED;
/* usbfs places a 16kb limit on bulk URBs. we divide up larger requests
return LIBUSB_ERROR_NOT_SUPPORTED;
/* usbfs places a 16kb limit on bulk URBs. we divide up larger requests
urb->type = urb_type;
urb->endpoint = transfer->endpoint;
urb->buffer = transfer->buffer + (i * MAX_BULK_BUFFER_LENGTH);
urb->type = urb_type;
urb->endpoint = transfer->endpoint;
urb->buffer = transfer->buffer + (i * MAX_BULK_BUFFER_LENGTH);
- if (supports_flag_bulk_continuation && !is_out)
+ if ((dpriv->caps & USBFS_CAP_BULK_CONTINUATION) && !is_out)
urb->flags = USBFS_URB_SHORT_NOT_OK;
if (i == num_urbs - 1 && last_urb_partial)
urb->buffer_length = transfer->length % MAX_BULK_BUFFER_LENGTH;
urb->flags = USBFS_URB_SHORT_NOT_OK;
if (i == num_urbs - 1 && last_urb_partial)
urb->buffer_length = transfer->length % MAX_BULK_BUFFER_LENGTH;
else
urb->buffer_length = MAX_BULK_BUFFER_LENGTH;
else
urb->buffer_length = MAX_BULK_BUFFER_LENGTH;
- if (i > 0 && supports_flag_bulk_continuation)
+ if (i > 0 && (dpriv->caps & USBFS_CAP_BULK_CONTINUATION))
urb->flags |= USBFS_URB_BULK_CONTINUATION;
/* we have already checked that the flag is supported */
urb->flags |= USBFS_URB_BULK_CONTINUATION;
/* we have already checked that the flag is supported */
#ifndef LIBUSB_USBFS_H
#define LIBUSB_USBFS_H
#ifndef LIBUSB_USBFS_H
#define LIBUSB_USBFS_H
+#include <linux/types.h>
+
#define SYSFS_DEVICE_PATH "/sys/bus/usb/devices"
struct usbfs_ctrltransfer {
#define SYSFS_DEVICE_PATH "/sys/bus/usb/devices"
struct usbfs_ctrltransfer {
unsigned char port[127]; /* port to device num mapping */
};
unsigned char port[127]; /* port to device num mapping */
};
+#define USBFS_CAP_ZERO_PACKET 0x01
+#define USBFS_CAP_BULK_CONTINUATION 0x02
+#define USBFS_CAP_NO_PACKET_SIZE_LIM 0x04
+#define USBFS_CAP_BULK_SCATTER_GATHER 0x08
+
#define IOCTL_USBFS_CONTROL _IOWR('U', 0, struct usbfs_ctrltransfer)
#define IOCTL_USBFS_BULK _IOWR('U', 2, struct usbfs_bulktransfer)
#define IOCTL_USBFS_RESETEP _IOR('U', 3, unsigned int)
#define IOCTL_USBFS_CONTROL _IOWR('U', 0, struct usbfs_ctrltransfer)
#define IOCTL_USBFS_BULK _IOWR('U', 2, struct usbfs_bulktransfer)
#define IOCTL_USBFS_RESETEP _IOR('U', 3, unsigned int)
#define IOCTL_USBFS_CLEAR_HALT _IOR('U', 21, unsigned int)
#define IOCTL_USBFS_DISCONNECT _IO('U', 22)
#define IOCTL_USBFS_CONNECT _IO('U', 23)
#define IOCTL_USBFS_CLEAR_HALT _IOR('U', 21, unsigned int)
#define IOCTL_USBFS_DISCONNECT _IO('U', 22)
#define IOCTL_USBFS_CONNECT _IO('U', 23)
+#define IOCTL_USBFS_CLAIM_PORT _IOR('U', 24, unsigned int)
+#define IOCTL_USBFS_RELEASE_PORT _IOR('U', 25, unsigned int)
+#define IOCTL_USBFS_GET_CAPABILITIES _IOR('U', 26, __u32)
-#define LIBUSB_NANO 10553
+#define LIBUSB_NANO 10554