|
@@ -100,11 +100,15 @@ MODULE_PARM_DESC(usbfs_snoop, "true to log all usbfs traffic");
|
|
|
dev_info(dev , format , ## arg); \
|
|
|
} while (0)
|
|
|
|
|
|
-#define USB_DEVICE_DEV MKDEV(USB_DEVICE_MAJOR, 0)
|
|
|
+enum snoop_when {
|
|
|
+ SUBMIT, COMPLETE
|
|
|
+};
|
|
|
|
|
|
+#define USB_DEVICE_DEV MKDEV(USB_DEVICE_MAJOR, 0)
|
|
|
|
|
|
#define MAX_USBFS_BUFFER_SIZE 16384
|
|
|
|
|
|
+
|
|
|
static int connected(struct dev_state *ps)
|
|
|
{
|
|
|
return (!list_empty(&ps->list) &&
|
|
@@ -301,24 +305,42 @@ static struct async *async_getpending(struct dev_state *ps,
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
-static void snoop_urb(struct urb *urb, void __user *userurb)
|
|
|
+static void snoop_urb(struct usb_device *udev,
|
|
|
+ void __user *userurb, int pipe, unsigned length,
|
|
|
+ int timeout_or_status, enum snoop_when when)
|
|
|
{
|
|
|
- unsigned j;
|
|
|
- unsigned char *data = urb->transfer_buffer;
|
|
|
+ static const char *types[] = {"isoc", "int", "ctrl", "bulk"};
|
|
|
+ static const char *dirs[] = {"out", "in"};
|
|
|
+ int ep;
|
|
|
+ const char *t, *d;
|
|
|
|
|
|
if (!usbfs_snoop)
|
|
|
return;
|
|
|
|
|
|
- dev_info(&urb->dev->dev, "direction=%s\n",
|
|
|
- usb_urb_dir_in(urb) ? "IN" : "OUT");
|
|
|
- dev_info(&urb->dev->dev, "userurb=%p\n", userurb);
|
|
|
- dev_info(&urb->dev->dev, "transfer_buffer_length=%u\n",
|
|
|
- urb->transfer_buffer_length);
|
|
|
- dev_info(&urb->dev->dev, "actual_length=%u\n", urb->actual_length);
|
|
|
- dev_info(&urb->dev->dev, "data: ");
|
|
|
- for (j = 0; j < urb->transfer_buffer_length; ++j)
|
|
|
- printk("%02x ", data[j]);
|
|
|
- printk("\n");
|
|
|
+ ep = usb_pipeendpoint(pipe);
|
|
|
+ t = types[usb_pipetype(pipe)];
|
|
|
+ d = dirs[!!usb_pipein(pipe)];
|
|
|
+
|
|
|
+ if (userurb) { /* Async */
|
|
|
+ if (when == SUBMIT)
|
|
|
+ dev_info(&udev->dev, "userurb %p, ep%d %s-%s, "
|
|
|
+ "length %u\n",
|
|
|
+ userurb, ep, t, d, length);
|
|
|
+ else
|
|
|
+ dev_info(&udev->dev, "userurb %p, ep%d %s-%s, "
|
|
|
+ "actual_length %u status %d\n",
|
|
|
+ userurb, ep, t, d, length,
|
|
|
+ timeout_or_status);
|
|
|
+ } else {
|
|
|
+ if (when == SUBMIT)
|
|
|
+ dev_info(&udev->dev, "ep%d %s-%s, length %u, "
|
|
|
+ "timeout %d\n",
|
|
|
+ ep, t, d, length, timeout_or_status);
|
|
|
+ else
|
|
|
+ dev_info(&udev->dev, "ep%d %s-%s, actual_length %u, "
|
|
|
+ "status %d\n",
|
|
|
+ ep, t, d, length, timeout_or_status);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
static void async_completed(struct urb *urb)
|
|
@@ -347,7 +369,8 @@ static void async_completed(struct urb *urb)
|
|
|
secid = as->secid;
|
|
|
}
|
|
|
snoop(&urb->dev->dev, "urb complete\n");
|
|
|
- snoop_urb(urb, as->userurb);
|
|
|
+ snoop_urb(urb->dev, as->userurb, urb->pipe, urb->actual_length,
|
|
|
+ as->status, COMPLETE);
|
|
|
spin_unlock(&ps->lock);
|
|
|
|
|
|
if (signr)
|
|
@@ -690,7 +713,7 @@ static int proc_control(struct dev_state *ps, void __user *arg)
|
|
|
unsigned int tmo;
|
|
|
unsigned char *tbuf;
|
|
|
unsigned wLength;
|
|
|
- int i, j, ret;
|
|
|
+ int i, pipe, ret;
|
|
|
|
|
|
if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
|
|
|
return -EFAULT;
|
|
@@ -710,24 +733,17 @@ static int proc_control(struct dev_state *ps, void __user *arg)
|
|
|
free_page((unsigned long)tbuf);
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
- snoop(&dev->dev, "control read: bRequest=%02x "
|
|
|
- "bRrequestType=%02x wValue=%04x "
|
|
|
- "wIndex=%04x wLength=%04x\n",
|
|
|
- ctrl.bRequest, ctrl.bRequestType, ctrl.wValue,
|
|
|
- ctrl.wIndex, ctrl.wLength);
|
|
|
+ pipe = usb_rcvctrlpipe(dev, 0);
|
|
|
+ snoop_urb(dev, NULL, pipe, ctrl.wLength, tmo, SUBMIT);
|
|
|
|
|
|
usb_unlock_device(dev);
|
|
|
- i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.bRequest,
|
|
|
+ i = usb_control_msg(dev, pipe, ctrl.bRequest,
|
|
|
ctrl.bRequestType, ctrl.wValue, ctrl.wIndex,
|
|
|
tbuf, ctrl.wLength, tmo);
|
|
|
usb_lock_device(dev);
|
|
|
+ snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE);
|
|
|
+
|
|
|
if ((i > 0) && ctrl.wLength) {
|
|
|
- if (usbfs_snoop) {
|
|
|
- dev_info(&dev->dev, "control read: data ");
|
|
|
- for (j = 0; j < i; ++j)
|
|
|
- printk("%02x ", (u8)(tbuf)[j]);
|
|
|
- printk("\n");
|
|
|
- }
|
|
|
if (copy_to_user(ctrl.data, tbuf, i)) {
|
|
|
free_page((unsigned long)tbuf);
|
|
|
return -EFAULT;
|
|
@@ -740,22 +756,15 @@ static int proc_control(struct dev_state *ps, void __user *arg)
|
|
|
return -EFAULT;
|
|
|
}
|
|
|
}
|
|
|
- snoop(&dev->dev, "control write: bRequest=%02x "
|
|
|
- "bRrequestType=%02x wValue=%04x "
|
|
|
- "wIndex=%04x wLength=%04x\n",
|
|
|
- ctrl.bRequest, ctrl.bRequestType, ctrl.wValue,
|
|
|
- ctrl.wIndex, ctrl.wLength);
|
|
|
- if (usbfs_snoop) {
|
|
|
- dev_info(&dev->dev, "control write: data: ");
|
|
|
- for (j = 0; j < ctrl.wLength; ++j)
|
|
|
- printk("%02x ", (unsigned char)(tbuf)[j]);
|
|
|
- printk("\n");
|
|
|
- }
|
|
|
+ pipe = usb_sndctrlpipe(dev, 0);
|
|
|
+ snoop_urb(dev, NULL, pipe, ctrl.wLength, tmo, SUBMIT);
|
|
|
+
|
|
|
usb_unlock_device(dev);
|
|
|
i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.bRequest,
|
|
|
ctrl.bRequestType, ctrl.wValue, ctrl.wIndex,
|
|
|
tbuf, ctrl.wLength, tmo);
|
|
|
usb_lock_device(dev);
|
|
|
+ snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE);
|
|
|
}
|
|
|
free_page((unsigned long)tbuf);
|
|
|
if (i < 0 && i != -EPIPE) {
|
|
@@ -774,7 +783,7 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
|
|
|
unsigned int tmo, len1, pipe;
|
|
|
int len2;
|
|
|
unsigned char *tbuf;
|
|
|
- int i, j, ret;
|
|
|
+ int i, ret;
|
|
|
|
|
|
if (copy_from_user(&bulk, arg, sizeof(bulk)))
|
|
|
return -EFAULT;
|
|
@@ -801,18 +810,14 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
|
|
|
kfree(tbuf);
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
- snoop(&dev->dev, "bulk read: len=0x%02x timeout=%04d\n",
|
|
|
- bulk.len, bulk.timeout);
|
|
|
+ snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT);
|
|
|
+
|
|
|
usb_unlock_device(dev);
|
|
|
i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
|
|
|
usb_lock_device(dev);
|
|
|
+ snoop_urb(dev, NULL, pipe, len2, i, COMPLETE);
|
|
|
+
|
|
|
if (!i && len2) {
|
|
|
- if (usbfs_snoop) {
|
|
|
- dev_info(&dev->dev, "bulk read: data ");
|
|
|
- for (j = 0; j < len2; ++j)
|
|
|
- printk("%02x ", (u8)(tbuf)[j]);
|
|
|
- printk("\n");
|
|
|
- }
|
|
|
if (copy_to_user(bulk.data, tbuf, len2)) {
|
|
|
kfree(tbuf);
|
|
|
return -EFAULT;
|
|
@@ -825,17 +830,12 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
|
|
|
return -EFAULT;
|
|
|
}
|
|
|
}
|
|
|
- snoop(&dev->dev, "bulk write: len=0x%02x timeout=%04d\n",
|
|
|
- bulk.len, bulk.timeout);
|
|
|
- if (usbfs_snoop) {
|
|
|
- dev_info(&dev->dev, "bulk write: data: ");
|
|
|
- for (j = 0; j < len1; ++j)
|
|
|
- printk("%02x ", (unsigned char)(tbuf)[j]);
|
|
|
- printk("\n");
|
|
|
- }
|
|
|
+ snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT);
|
|
|
+
|
|
|
usb_unlock_device(dev);
|
|
|
i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
|
|
|
usb_lock_device(dev);
|
|
|
+ snoop_urb(dev, NULL, pipe, len2, i, COMPLETE);
|
|
|
}
|
|
|
kfree(tbuf);
|
|
|
if (i < 0)
|
|
@@ -1053,13 +1053,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
|
|
|
is_in = 0;
|
|
|
uurb->endpoint &= ~USB_DIR_IN;
|
|
|
}
|
|
|
- snoop(&ps->dev->dev, "control urb: bRequest=%02x "
|
|
|
- "bRrequestType=%02x wValue=%04x "
|
|
|
- "wIndex=%04x wLength=%04x\n",
|
|
|
- dr->bRequest, dr->bRequestType,
|
|
|
- __le16_to_cpup(&dr->wValue),
|
|
|
- __le16_to_cpup(&dr->wIndex),
|
|
|
- __le16_to_cpup(&dr->wLength));
|
|
|
break;
|
|
|
|
|
|
case USBDEVFS_URB_TYPE_BULK:
|
|
@@ -1072,7 +1065,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
|
|
|
uurb->number_of_packets = 0;
|
|
|
if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
|
|
|
return -EINVAL;
|
|
|
- snoop(&ps->dev->dev, "bulk urb\n");
|
|
|
break;
|
|
|
|
|
|
case USBDEVFS_URB_TYPE_ISO:
|
|
@@ -1104,7 +1096,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
uurb->buffer_length = totlen;
|
|
|
- snoop(&ps->dev->dev, "iso urb\n");
|
|
|
break;
|
|
|
|
|
|
case USBDEVFS_URB_TYPE_INTERRUPT:
|
|
@@ -1113,7 +1104,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
|
|
|
return -EINVAL;
|
|
|
if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
|
|
|
return -EINVAL;
|
|
|
- snoop(&ps->dev->dev, "interrupt urb\n");
|
|
|
break;
|
|
|
|
|
|
default:
|
|
@@ -1200,11 +1190,14 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
|
|
|
return -EFAULT;
|
|
|
}
|
|
|
}
|
|
|
- snoop_urb(as->urb, as->userurb);
|
|
|
+ snoop_urb(ps->dev, as->userurb, as->urb->pipe,
|
|
|
+ as->urb->transfer_buffer_length, 0, SUBMIT);
|
|
|
async_newpending(as);
|
|
|
if ((ret = usb_submit_urb(as->urb, GFP_KERNEL))) {
|
|
|
dev_printk(KERN_DEBUG, &ps->dev->dev,
|
|
|
"usbfs: usb_submit_urb returned %d\n", ret);
|
|
|
+ snoop_urb(ps->dev, as->userurb, as->urb->pipe,
|
|
|
+ 0, ret, COMPLETE);
|
|
|
async_removepending(as);
|
|
|
free_async(as);
|
|
|
return ret;
|
|
@@ -1670,7 +1663,7 @@ static int usbdev_ioctl(struct inode *inode, struct file *file,
|
|
|
break;
|
|
|
|
|
|
case USBDEVFS_REAPURBNDELAY32:
|
|
|
- snoop(&dev->dev, "%s: REAPURBDELAY32\n", __func__);
|
|
|
+ snoop(&dev->dev, "%s: REAPURBNDELAY32\n", __func__);
|
|
|
ret = proc_reapurbnonblock_compat(ps, p);
|
|
|
break;
|
|
|
|
|
@@ -1691,7 +1684,7 @@ static int usbdev_ioctl(struct inode *inode, struct file *file,
|
|
|
break;
|
|
|
|
|
|
case USBDEVFS_REAPURBNDELAY:
|
|
|
- snoop(&dev->dev, "%s: REAPURBDELAY\n", __func__);
|
|
|
+ snoop(&dev->dev, "%s: REAPURBNDELAY\n", __func__);
|
|
|
ret = proc_reapurbnonblock(ps, p);
|
|
|
break;
|
|
|
|