* This is a binary format reader.
*
* Copyright (C) 2006 Paolo Abeni (paolo.abeni@email.it)
- * Copyright (C) 2006 Pete Zaitcev (zaitcev@redhat.com)
+ * Copyright (C) 2006,2007 Pete Zaitcev (zaitcev@redhat.com)
*/
#include <linux/kernel.h>
#define MON_RING_EMPTY(rp) ((rp)->b_cnt == 0)
+static unsigned char xfer_to_pipe[4] = {
+ PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
+};
+
+static struct class *mon_bin_class;
static dev_t mon_bin_dev0;
static struct cdev mon_bin_cdev;
const struct urb *urb, char ev_type)
{
- if (!usb_pipecontrol(urb->pipe) || ev_type != 'S')
+ if (!usb_endpoint_xfer_control(&urb->ep->desc) || ev_type != 'S')
return '-';
- if (urb->transfer_flags & URB_NO_SETUP_DMA_MAP)
- return mon_dmapeek(setupb, urb->setup_dma, SETUP_LEN);
if (urb->setup_packet == NULL)
return 'Z';
unsigned int offset, struct urb *urb, unsigned int length)
{
- if (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) {
+ if (urb->dev->bus->uses_dma &&
+ (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
mon_dmapeek_vec(rp, offset, urb->transfer_dma, length);
return 0;
}
}
static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
- char ev_type)
+ char ev_type, int status)
{
+ const struct usb_endpoint_descriptor *epd = &urb->ep->desc;
unsigned long flags;
struct timeval ts;
unsigned int urb_length;
unsigned int offset;
unsigned int length;
+ unsigned char dir;
struct mon_bin_hdr *ep;
char data_tag = 0;
if (length >= rp->b_size/5)
length = rp->b_size/5;
- if (usb_pipein(urb->pipe)) {
+ if (usb_urb_dir_in(urb)) {
if (ev_type == 'S') {
length = 0;
data_tag = '<';
}
+ /* Cannot rely on endpoint number in case of control ep.0 */
+ dir = USB_DIR_IN;
} else {
if (ev_type == 'C') {
length = 0;
data_tag = '>';
}
+ dir = 0;
}
if (rp->mmap_active)
*/
memset(ep, 0, PKT_SIZE);
ep->type = ev_type;
- ep->xfer_type = usb_pipetype(urb->pipe);
- /* We use the fact that usb_pipein() returns 0x80 */
- ep->epnum = usb_pipeendpoint(urb->pipe) | usb_pipein(urb->pipe);
- ep->devnum = usb_pipedevice(urb->pipe);
- ep->busnum = rp->r.m_bus->u_bus->busnum;
+ ep->xfer_type = xfer_to_pipe[usb_endpoint_type(epd)];
+ ep->epnum = dir | usb_endpoint_num(epd);
+ ep->devnum = urb->dev->devnum;
+ ep->busnum = urb->dev->bus->busnum;
ep->id = (unsigned long) urb;
ep->ts_sec = ts.tv_sec;
ep->ts_usec = ts.tv_usec;
- ep->status = urb->status;
+ ep->status = status;
ep->len_urb = urb_length;
ep->len_cap = length;
static void mon_bin_submit(void *data, struct urb *urb)
{
struct mon_reader_bin *rp = data;
- mon_bin_event(rp, urb, 'S');
+ mon_bin_event(rp, urb, 'S', -EINPROGRESS);
}
-static void mon_bin_complete(void *data, struct urb *urb)
+static void mon_bin_complete(void *data, struct urb *urb, int status)
{
struct mon_reader_bin *rp = data;
- mon_bin_event(rp, urb, 'C');
+ mon_bin_event(rp, urb, 'C', status);
}
static void mon_bin_error(void *data, struct urb *urb, int error)
memset(ep, 0, PKT_SIZE);
ep->type = 'E';
- ep->xfer_type = usb_pipetype(urb->pipe);
- /* We use the fact that usb_pipein() returns 0x80 */
- ep->epnum = usb_pipeendpoint(urb->pipe) | usb_pipein(urb->pipe);
- ep->devnum = usb_pipedevice(urb->pipe);
- ep->busnum = rp->r.m_bus->u_bus->busnum;
+ ep->xfer_type = xfer_to_pipe[usb_endpoint_type(&urb->ep->desc)];
+ ep->epnum = usb_urb_dir_in(urb) ? USB_DIR_IN : 0;
+ ep->epnum |= usb_endpoint_num(&urb->ep->desc);
+ ep->devnum = urb->dev->devnum;
+ ep->busnum = urb->dev->bus->busnum;
ep->id = (unsigned long) urb;
ep->status = error;
static int mon_bin_open(struct inode *inode, struct file *file)
{
struct mon_bus *mbus;
- struct usb_bus *ubus;
struct mon_reader_bin *rp;
size_t size;
int rc;
mutex_unlock(&mon_lock);
return -ENODEV;
}
- if ((ubus = mbus->u_bus) == NULL) {
+ if (mbus != &mon_bus0 && mbus->u_bus == NULL) {
printk(KERN_ERR TAG ": consistency error on open\n");
mutex_unlock(&mon_lock);
return -ENODEV;
free_page((unsigned long) map[n].ptr);
}
+int mon_bin_add(struct mon_bus *mbus, const struct usb_bus *ubus)
+{
+ struct device *dev;
+ unsigned minor = ubus? ubus->busnum: 0;
+
+ if (minor >= MON_BIN_MAX_MINOR)
+ return 0;
+
+ dev = device_create(mon_bin_class, ubus? ubus->controller: NULL,
+ MKDEV(MAJOR(mon_bin_dev0), minor), "usbmon%d", minor);
+ if (IS_ERR(dev))
+ return 0;
+
+ mbus->classdev = dev;
+ return 1;
+}
+
+void mon_bin_del(struct mon_bus *mbus)
+{
+ device_destroy(mon_bin_class, mbus->classdev->devt);
+}
+
int __init mon_bin_init(void)
{
int rc;
+ mon_bin_class = class_create(THIS_MODULE, "usbmon");
+ if (IS_ERR(mon_bin_class)) {
+ rc = PTR_ERR(mon_bin_class);
+ goto err_class;
+ }
+
rc = alloc_chrdev_region(&mon_bin_dev0, 0, MON_BIN_MAX_MINOR, "usbmon");
if (rc < 0)
goto err_dev;
err_add:
unregister_chrdev_region(mon_bin_dev0, MON_BIN_MAX_MINOR);
err_dev:
+ class_destroy(mon_bin_class);
+err_class:
return rc;
}
{
cdev_del(&mon_bin_cdev);
unregister_chrdev_region(mon_bin_dev0, MON_BIN_MAX_MINOR);
+ class_destroy(mon_bin_class);
}