Hi Dave (and all linux usb developers) I just ported/merged your USBMon for linux 2.4.4 into the 2.4.20 kernel.
You might be interested in making this available to other users, patch is attached. Since I'm currently debugging some issues while developing a USB driver, it is likely that I'll port/merge USBMon for 2.4.26 and 2.6.6 during the next week, too. -- - Harald Welte <[EMAIL PROTECTED]> http://www.gnumonks.org/ ============================================================================ Programming is like sex: One mistake and you have to support it your lifetime
diff --exclude-from /sunbeam/home/laforge/scripts/dontdiff -Nru
linux-2.4.20-cjtest/drivers/usb/devio.c linux-2.4.20-cjtest-usbmon/drivers/usb/devio.c
--- linux-2.4.20-cjtest/drivers/usb/devio.c 2002-11-29 00:53:14.000000000 +0100
+++ linux-2.4.20-cjtest-usbmon/drivers/usb/devio.c 2004-06-04 15:30:19.000000000
+0200
@@ -43,6 +43,7 @@
#include <linux/usb.h>
#include <linux/usbdevice_fs.h>
#include <asm/uaccess.h>
+#include <linux/time.h> /*for USBMon*/
struct async {
@@ -57,6 +58,7 @@
static loff_t usbdev_lseek(struct file *file, loff_t offset, int orig)
{
+ printk("usbdev_lseek called.\n");
switch (orig) {
case 0:
file->f_pos = offset;
@@ -1238,3 +1240,430 @@
open: usbdev_open,
release: usbdev_release,
};
+
+
+/*************************** USBMon Addition *********************************/
+
+
+static int usbmon_open(struct inode *inode, struct file *file)
+{
+ struct usb_device *dev;
+ int ret;
+
+ printk("[USBMon] usbmon_open called with inode=&%p\n",inode);
+
+ lock_kernel();
+ ret = -ENOENT;
+ if (ITYPE(inode->i_ino) != IDEVICEMON)
+ goto out;
+ dev = inode->u.usbdev_i.p.dev;
+ if (!dev)
+ goto out;
+
+ ret = 0;
+
+ dev->USBMon_data->USBMon_urb_ll_buffered =
+ dev->USBMon_data->USBMon_urb_ll_head;
+ wmb();
+ dev->USBMon_data->USBMon_urb_ll_head = NULL;
+ wmb();
+ dev->USBMon_data->USBMon_urb_ll_last = NULL;
+ wmb();
+
+ file->private_data = dev;
+ out:
+ unlock_kernel();
+ return ret;
+}
+
+static int usbmon_release(struct inode *inode, struct file *file)
+{
+ struct urb *temp_urb1, *temp_urb2;
+ struct usb_device *dev;
+
+ dev = (struct usb_device *)(file->private_data);
+
+ temp_urb1=dev->USBMon_data->USBMon_urb_ll_buffered;
+
+ wmb();
+
+ dev->USBMon_data->USBMon_urb_ll_buffered=NULL;
+
+
+ while(temp_urb1 != NULL){
+ temp_urb2 = temp_urb1;
+ if(temp_urb1->transfer_buffer){
+ kfree(temp_urb1->transfer_buffer);
+ }
+ temp_urb1=temp_urb1->next;
+ kfree(temp_urb2);
+ }
+ return 0;
+}
+
+static ssize_t usbmon_read(struct file *file, char * buf, size_t nbytes, loff_t *ppos)
+{
+ ssize_t ret = 0;
+ unsigned int len=0;
+ unsigned int already_copied=0;
+ unsigned int skipped=0;
+ int i;
+ loff_t pos;
+ char a[5120];
+ struct usb_device *dev;
+ struct urb *purb;
+ int finished=0;
+
+ pos = *ppos;
+
+ if (!file->private_data) {
+ ret = -ENODEV;
+ goto err;
+ } else if (pos < 0) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ dev=(struct usb_device *)file->private_data;
+
+ printk("[USBMon] read on device %d, buffered=%8p\n",
+ dev->devnum,
+ dev->USBMon_data->USBMon_urb_ll_buffered);
+
+ purb = dev->USBMon_data->USBMon_urb_ll_buffered;
+
+ if(purb == NULL){
+ finished=1;
+ }
+ while(finished == 0){
+ {
+ int dp=0, al=0;
+ if(purb->transfer_buffer == NULL){
+ dp=0;
+ }else{
+ dp=1;
+ }
+ sprintf(a,"[URB completed on Device=%03d, "
+ "Endpoint=%02d, Pipe=%08X, "
+ "status= % 03d, size= %08d, transfer_flags = "
+ "%08X, actual_length = %08d, "
+ "error count = %05d completion_time = %02ld"
+ ":%02ld:%02ld:%06ld dp=%d data=",
+ purb->dev->devnum,
+ (purb->pipe & (0xf <<15))>>15,
+ purb->pipe,
+ purb->status,
+ purb->transfer_buffer_length,
+ purb->transfer_flags,
+ purb->actual_length,
+ purb->error_count,
+
+ ((purb->completion_time).tv_sec%86400)/(60*60),
+ (((purb->completion_time).tv_sec%86400)%(60*60))
+ /60,
+ ((purb->completion_time).tv_sec%86400)%60,
+ (purb->completion_time).tv_usec,
+ dp);
+
+ al=strlen(a);
+ i=0;
+ if(purb->transfer_buffer != NULL){
+ for(i=0;
+ (i<4096 &&
+ i<(purb->transfer_buffer_length));
+ i++){
+ if(purb->transfer_buffer != NULL){
+
+ a[al+i+1]=
+ *((char
+ *)purb->transfer_buffer+i);
+ }
+ }
+ }
+ a[al+i+1]=']';
+ a[al+i+2]='\n';
+ /*a[al+i+3]='\0';*/
+ al = al+i+3;
+
+ if (pos+already_copied < (al+skipped)) {
+ len = (al+skipped)-(pos+already_copied);
+ if ((len+already_copied) >= nbytes){
+ len = nbytes-already_copied;
+ finished=1;
+ }
+
+ for(i=0;i<len;i++){
+ put_user(a[pos+already_copied-skipped+i],
+ buf+already_copied+i);
+ }
+ already_copied += len;
+
+ }else{
+ skipped += al;
+ purb = purb->next;
+ if(purb == NULL){
+ finished=1;
+ put_user(-1,buf+already_copied);
+ }
+ }
+ }
+ }
+
+ *ppos += already_copied;
+ buf += already_copied;
+ nbytes -= already_copied;
+ ret = already_copied;
+
+err:
+ return ret;
+}
+
+
+static ssize_t usbmon_write(struct file *file, const char * buf, size_t nbytes,
loff_t *ppos)
+{
+
+ ssize_t ret = 0;
+ struct usbmon_endpoint_ll *new_endpoint;
+ loff_t pos;
+ char a[255];
+ struct usb_device *dev;
+ int i=0;
+
+ pos = *ppos;
+
+ if (pos < 0) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ dev=(struct usb_device *)file->private_data;
+
+ printk("[USBMon] write on device %d, nbytes=%d\n",
+ dev->devnum, nbytes);
+
+ if((nbytes) > 4){
+ printk("[USBMon] Warning - trying to write more than 4
bytes.pos=%d,nbytes=%d ... continuing\n",(int)pos,(int)nbytes);
+ /*ret=-EINVAL;
+ goto err;*/
+ }
+ if((nbytes) < 4){
+ printk("[USBMon] Warning - trying to write less than 4
bytes.pos=%d,nbytes=%d ... ignoring\n",(int)pos,(int)nbytes);
+ ret=-EINVAL;
+ goto err;
+ }
+
+ for(i=0; i<4 && i<nbytes; i++){
+ get_user(a[i],buf+i);
+ }
+
+ ret=i;
+ if((a[0] == 'E') &&
+ (a[2] == 'L')){
+ struct usbmon_endpoint_ll *tmp_ep, *tmp_ep_last;
+ int found=0;
+ int tmp1;
+
+ tmp1 = a[1];
+
+ /*check to see if ep already exists*/
+
+ tmp_ep = dev->USBMon_data->USBMon_monitored_endpoints;
+ tmp_ep_last=NULL;
+ while(tmp_ep != NULL){
+ /*printk("[USBMon] checking ep=%8X\n",tmp_ep->value);*/
+ if(tmp_ep->value==((dev->devnum << 8) | (tmp1 << 15))){
+ if(a[3]==0){ /*remove it*/
+ printk("[USBMon]removing monitored endpoint.
device=%d, endpoint=%d",dev->devnum, a[1]);
+ if(tmp_ep_last==NULL){
+ dev->USBMon_data->
+ USBMon_monitored_endpoints=
+ tmp_ep->next;
+ }else{
+ tmp_ep_last->next=tmp_ep->next;
+ }
+ kfree(tmp_ep);
+ }else{
+ tmp_ep->level=a[3];
+ }
+ tmp_ep=NULL;
+ found=1;
+ }else{
+ tmp_ep_last=tmp_ep;
+ tmp_ep=tmp_ep->next;
+ }
+ }
+
+ if(!found){ /* ep doesn't already exist */
+ new_endpoint = kmalloc(sizeof(struct
+ usbmon_endpoint_ll),
+ GFP_KERNEL);
+
+ if(new_endpoint != NULL){
+
+ new_endpoint->value = ((dev->devnum << 8) |
+ (tmp1 << 15));
+ printk("[USBMon] Monitoring endpoint %d on device %d,
value=%8X, new level=%d \n", tmp1, dev->devnum, new_endpoint->value, a[3]);
+ /*printk("new ep=%8X\n",(int)new_endpoint);
+ */
+ new_endpoint->level = a[3];
+
+ new_endpoint->next =
+ dev->USBMon_data->USBMon_monitored_endpoints;
+
+ dev->USBMon_data->USBMon_monitored_endpoints =
+ new_endpoint;
+ }else{
+ ret=-ENOMEM;
+ goto err;
+ }
+ }
+ }else{
+ printk("[USBMon] Unrecognised Instruction from user on device %d\n",
dev->devnum);
+ }
+
+err:
+
+ return ret;
+}
+
+
+
+
+
+
+struct file_operations usbdevfs_devicemon_file_operations = {
+ /*llseek: NULL,*/
+ read: usbmon_read,
+ write: usbmon_write,
+ /*poll: NULL,
+ ioctl: NULL,*/
+ open: usbmon_open,
+ release: usbmon_release,
+};
+
+
+
+struct urb *USBMon_cpy_urb(struct urb *orig, int level)
+{
+ struct urb *cpy;
+
+ cpy = kmalloc(sizeof(*cpy), GFP_ATOMIC);
+ if(!cpy){
+ printk("[USBMon] Unable to kmalloc URB copy\n");
+ return NULL;
+ }
+
+ cpy->dev = orig->dev;
+ cpy->pipe = orig->pipe;
+ cpy->status = orig->status;
+ cpy->transfer_flags = orig->transfer_flags;
+ cpy->transfer_buffer_length = orig->transfer_buffer_length;
+ cpy->actual_length = orig->actual_length;
+ cpy->bandwidth = orig->bandwidth;
+ cpy->setup_packet = orig->setup_packet;
+ cpy->start_frame = orig->start_frame;
+ cpy->number_of_packets = orig->number_of_packets;
+ cpy->interval = orig->interval;
+ cpy->error_count = orig->error_count;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)
+ get_fast_time(&(cpy->completion_time));
+#else
+ do_gettimeofday(&(cpy->completion_time));
+#endif
+
+ if(level==3){
+ printk("[USBMon] kmalloc()ing %d bytes as transfer_buffer\n",
+ orig->transfer_buffer_length);
+ cpy->transfer_buffer = (void *)
+ kmalloc(orig->transfer_buffer_length,
+ GFP_ATOMIC);
+ if(!(cpy->transfer_buffer)){
+ printk("[USBMon] Unable to kmalloc URB buffer\n");
+ cpy->transfer_buffer = NULL;
+ }else{
+ memcpy( cpy->transfer_buffer,
+ orig->transfer_buffer,
+ orig->transfer_buffer_length);
+ }
+ }else{
+ cpy->transfer_buffer = NULL;
+ }
+ return(cpy);
+}
+
+
+void USBMon_urb_pre_completion(struct urb *purb)
+{
+ struct urb *pcpy_urb;
+ struct usbmon_endpoint_ll *ep;
+ int a=0;
+
+ /* printk("[USBMon] urb_pre_completion called for urb=%p\n", purb); */
+
+ if(purb->dev !=NULL){
+ if(purb->dev->USBMon_data != NULL){
+
+ ep = (struct usbmon_endpoint_ll *)
+ purb->dev->USBMon_data->USBMon_monitored_endpoints;
+
+ }else{
+ printk("[USBMON] -special- "
+ "USBMon_data is NULL, device number=%d\n",
+ purb->dev->devnum);
+ return;
+ }
+ }else{
+ printk("[USBMON] -special- "
+ "device pointer is NULL\n");
+ return;
+ }
+
+ while(ep != NULL){
+ a++;
+
+ if((purb->pipe & ((0x4f << 8) | (0xf << 15))) == ep->value){
+
+ a=a+1000;
+ pcpy_urb = USBMon_cpy_urb(purb, ep->level);
+ if(pcpy_urb != NULL){
+
+ /* printk("[USBMon] copying urb\n"); */
+ pcpy_urb->next=NULL;
+
+ if(purb->dev->USBMon_data->USBMon_urb_ll_head ==
+ NULL){
+
+ purb->dev->USBMon_data->
+ USBMon_urb_ll_head =
+ pcpy_urb;
+ purb->dev->USBMon_data->
+ USBMon_urb_ll_last =
+ pcpy_urb;
+
+ }else{
+ purb->dev->USBMon_data->
+ USBMon_urb_ll_last->next =
+ pcpy_urb;
+ wmb();
+ purb->dev->USBMon_data->
+ USBMon_urb_ll_last=
+ pcpy_urb;
+ }
+
+ }else{
+ printk("[USBMon] failed to copy URB for monitoring\n");
+ }
+
+ ep = NULL; /* So as to break out of while loop faster*/
+
+ }else{ /* endif check on endpoint */
+
+ ep = ep->next;
+
+ }
+ }
+
+}
+
+/*end USBMon Addition */
diff --exclude-from /sunbeam/home/laforge/scripts/dontdiff -Nru
linux-2.4.20-cjtest/drivers/usb/inode.c linux-2.4.20-cjtest-usbmon/drivers/usb/inode.c
--- linux-2.4.20-cjtest/drivers/usb/inode.c 2002-11-29 00:53:14.000000000 +0100
+++ linux-2.4.20-cjtest-usbmon/drivers/usb/inode.c 2004-06-04 12:03:10.000000000
+0200
@@ -71,7 +71,7 @@
const char *name;
unsigned int s;
- if (dentry->d_name.len != 3)
+ if ((dentry->d_name.len != 3) && (dentry->d_name.len != 4))/*USBMon*/
return -1;
name = dentry->d_name.name;
if (name[0] < '0' || name[0] > '9' ||
@@ -92,6 +92,7 @@
static void new_dev_inode(struct usb_device *dev, struct super_block *sb)
{
struct inode *inode;
+ struct inode *inode2; /*USBMon Addition*/
unsigned int devnum = dev->devnum;
unsigned int busnum = dev->bus->busnum;
@@ -111,6 +112,24 @@
inode->u.usbdev_i.p.dev = dev;
list_add_tail(&inode->u.usbdev_i.slist, &sb->u.usbdevfs_sb.ilist);
list_add_tail(&inode->u.usbdev_i.dlist, &dev->inodes);
+
+ /*USBMon Addition */
+
+ inode2 = iget(sb, IDEVICEMON | (busnum << 8) | devnum);
+ if (!inode) {
+ printk(KERN_ERR "usbdevfs: cannot create monitor inode for bus %u
device %u\n", busnum, devnum);
+ return;
+ }
+ inode2->i_atime = inode2->i_mtime = inode2->i_ctime = CURRENT_TIME;
+ inode2->i_uid = sb->u.usbdevfs_sb.devuid;
+ inode2->i_gid = sb->u.usbdevfs_sb.devgid;
+ inode2->i_mode = sb->u.usbdevfs_sb.devmode | S_IFREG;
+ inode2->i_fop = &usbdevfs_devicemon_file_operations;
+ inode2->i_size = 1024; /*** needs to change */
+ inode2->u.usbdev_i.p.dev = dev;
+ list_add_tail(&inode2->u.usbdev_i.slist, &sb->u.usbdevfs_sb.ilist);
+ list_add_tail(&inode2->u.usbdev_i.dlist, &dev->inodes);
+ /*end USBMon Addition*/
}
static void recurse_new_dev_inode(struct usb_device *dev, struct super_block *sb)
@@ -362,9 +381,15 @@
return ERR_PTR(-EINVAL);
dentry->d_op = &usbdevfs_dentry_operations;
devnr = dnumber(dentry);
- if (devnr < 1 || devnr > 127)
+ if (devnr < 1 || devnr > 127){
+ printk("[USBMon] Invalid dev id %d on lookup\n",devnr);
return ERR_PTR(-ENOENT);
- inode = iget(dir->i_sb, IDEVICE | (dir->i_ino & (0xff << 8)) | devnr);
+ }
+ if(dentry->d_name.len == 4){
+ inode = iget(dir->i_sb, IDEVICEMON | (dir->i_ino & (0xff << 8)) |
devnr);
+ }else{
+ inode = iget(dir->i_sb, IDEVICE | (dir->i_ino & (0xff << 8)) | devnr);
+ }
if (!inode)
return ERR_PTR(-EINVAL);
if (inode && inode->u.usbdev_i.p.dev == NULL) {
@@ -436,17 +461,28 @@
static int bus_readdir(struct usb_device *dev, unsigned long ino, int pos, struct
file *filp, void *dirent, filldir_t filldir)
{
char numbuf[8];
+ char numbuf2[8]; /*USBMon*/
unsigned int i;
if (!dev)
return pos;
sprintf(numbuf, "%03d", dev->devnum);
+ sprintf(numbuf2, "%03dM", dev->devnum);/*USBMon*/
+
if (pos > 0)
pos--;
else {
- if (filldir(dirent, numbuf, 3, filp->f_pos, ino | (dev->devnum &
0xff), DT_UNKNOWN) < 0)
+ if (filldir(dirent, numbuf, 3, filp->f_pos, IDEVICE | ino |
(dev->devnum & 0xff), DT_UNKNOWN) < 0)
return -1;
filp->f_pos++;
+
+ /*USBMon Addition*/
+ if (filldir(dirent, numbuf2, 4, filp->f_pos, IDEVICEMON | ino |
(dev->devnum & 0xff), DT_UNKNOWN) < 0){
+ printk("[USBMon] FAILED to insert monitor file\n");
+ return -1;
+ }
+ filp->f_pos++;
+ /*USBMon end*/
}
for (i = 0; i < dev->maxchild; i++) {
if (!dev->children[i])
@@ -483,7 +519,7 @@
default:
lock_kernel();
bus = usbdevfs_findbus(IBUSNR(ino));
- bus_readdir(bus->root_hub, IDEVICE | ((bus->busnum & 0xff) << 8),
filp->f_pos-2, filp, dirent, filldir);
+ bus_readdir(bus->root_hub, ((bus->busnum & 0xff) << 8), filp->f_pos-2,
filp, dirent, filldir);/* has changed due to USBMon*/
unlock_kernel();
return 0;
}
diff --exclude-from /sunbeam/home/laforge/scripts/dontdiff -Nru
linux-2.4.20-cjtest/drivers/usb/uhci.c linux-2.4.20-cjtest-usbmon/drivers/usb/uhci.c
--- linux-2.4.20-cjtest/drivers/usb/uhci.c 2002-11-29 00:53:15.000000000 +0100
+++ linux-2.4.20-cjtest-usbmon/drivers/usb/uhci.c 2004-06-04 12:07:53.000000000
+0200
@@ -2361,11 +2361,15 @@
if (!killed)
urb->status = status;
- urb->dev = NULL;
- spin_unlock_irqrestore(&urb->lock, flags);
-
- if (urb->complete)
- urb->complete(urb);
+ if (urb->complete) {
+ USBMon_urb_pre_completion(urb);/*USBMon*/
+ urb->dev = NULL;
+ spin_unlock_irqrestore(&urb->lock, flags);
+ urb->complete(urb);
+ } else {
+ urb->dev = NULL;
+ spin_unlock_irqrestore(&urb->lock, flags);
+ }
if (resubmit_interrupt)
/* Recheck the status. The completion handler may have */
diff --exclude-from /sunbeam/home/laforge/scripts/dontdiff -Nru
linux-2.4.20-cjtest/drivers/usb/usb-ohci.c
linux-2.4.20-cjtest-usbmon/drivers/usb/usb-ohci.c
--- linux-2.4.20-cjtest/drivers/usb/usb-ohci.c 2002-11-29 00:53:15.000000000 +0100
+++ linux-2.4.20-cjtest-usbmon/drivers/usb/usb-ohci.c 2004-06-04 12:03:10.000000000
+0200
@@ -489,6 +489,7 @@
usb_pipeout (urb->pipe)
? PCI_DMA_TODEVICE
: PCI_DMA_FROMDEVICE);
+ USBMon_urb_pre_completion(urb);/*USBMon*/
urb->complete (urb);
/* implicitly requeued */
@@ -506,6 +507,7 @@
usb_pipeout (urb->pipe)
? PCI_DMA_TODEVICE
: PCI_DMA_FROMDEVICE);
+ USBMon_urb_pre_completion(urb);/*USBMon*/
urb->complete (urb);
spin_lock_irqsave (&usb_ed_lock, flags);
urb->actual_length = 0;
@@ -522,6 +524,7 @@
} else { /* unlink URB, call complete */
urb_rm_priv (urb);
+ USBMon_urb_pre_completion(urb);/*USBMon*/
urb->complete (urb);
}
break;
@@ -529,6 +532,7 @@
case PIPE_BULK:
case PIPE_CONTROL: /* unlink URB, call complete */
urb_rm_priv (urb);
+ USBMon_urb_pre_completion(urb);/*USBMon*/
urb->complete (urb);
break;
}
@@ -803,6 +807,8 @@
if (urb->transfer_flags & USB_ASYNC_UNLINK) {
urb->status = -ECONNRESET;
if (urb->complete)
+ USBMon_urb_pre_completion(urb);
+ /*USBMon*/
urb->complete (urb);
} else
urb->status = -ENOENT;
@@ -1510,6 +1516,7 @@
if (urb->transfer_flags & USB_ASYNC_UNLINK) {
urb->status = -ECONNRESET;
if (urb->complete)
+ USBMon_urb_pre_completion(urb);/*USBMon*/
urb->complete (urb);
} else {
urb->status = -ENOENT;
@@ -1869,6 +1876,7 @@
urb_print (urb, "RET-t(rh)", usb_pipeout (urb->pipe));
#endif
if (urb->complete)
+ USBMon_urb_pre_completion(urb);/*USBMon*/
urb->complete (urb);
}
}
@@ -2105,6 +2113,7 @@
usb_dec_dev_use (usb_dev);
urb->dev = NULL;
if (urb->complete)
+ USBMon_urb_pre_completion(urb);/*USBMon*/
urb->complete (urb);
return 0;
}
@@ -2126,6 +2135,7 @@
if (urb->transfer_flags & USB_ASYNC_UNLINK) {
urb->status = -ECONNRESET;
if (urb->complete)
+ USBMon_urb_pre_completion(urb);/*USBMon*/
urb->complete (urb);
} else
urb->status = -ENOENT;
diff --exclude-from /sunbeam/home/laforge/scripts/dontdiff -Nru
linux-2.4.20-cjtest/drivers/usb/usb-uhci.c
linux-2.4.20-cjtest-usbmon/drivers/usb/usb-uhci.c
--- linux-2.4.20-cjtest/drivers/usb/usb-uhci.c 2002-11-29 00:53:15.000000000 +0100
+++ linux-2.4.20-cjtest-usbmon/drivers/usb/usb-uhci.c 2004-06-04 12:03:10.000000000
+0200
@@ -1212,6 +1212,7 @@
usb_dev = urb->dev;
if (urb->complete) {
dbg("unlink_urb: calling completion");
+ USBMon_urb_pre_completion(urb); /*USBMon*/
urb->dev = NULL;
urb->complete ((struct urb *) urb);
}
@@ -1281,6 +1282,7 @@
uhci_urb_dma_sync(s, urb, urb_priv);
if (urb->complete) {
spin_unlock(&s->urb_list_lock);
+ USBMon_urb_pre_completion(urb);/*USBMon*/
urb->dev = NULL;
urb->complete ((struct urb *) urb);
spin_lock(&s->urb_list_lock);
@@ -1900,6 +1902,7 @@
if ((data > 0) && (uhci->rh.send != 0)) {
dbg("Root-Hub INT complete: port1: %x port2: %x data: %x",
inw (io_addr + USBPORTSC1), inw (io_addr + USBPORTSC2), data);
+ USBMon_urb_pre_completion(urb);/*USBMon*/
urb->complete (urb);
}
return 0;
@@ -1919,8 +1922,10 @@
len = rh_send_irq (urb);
if (len > 0) {
urb->actual_length = len;
- if (urb->complete)
+ if (urb->complete){
+ USBMon_urb_pre_completion(urb);/*USBMon*/
urb->complete (urb);
+ }
}
}
rh_init_int_timer (urb);
@@ -2157,9 +2162,12 @@
urb->actual_length = len;
urb->status = stat;
- urb->dev=NULL;
- if (urb->complete)
+ /*urb->dev=NULL; commented out for USBMon*/
+ if (urb->complete){
+ USBMon_urb_pre_completion(urb);/*USBMon*/
+ urb->dev=NULL;/*USBMon*/
urb->complete (urb);
+ }
return 0;
}
/*-------------------------------------------------------------------------*/
@@ -2483,6 +2491,8 @@
spin_unlock(&s->urb_list_lock);
+ USBMon_urb_pre_completion(urb);/*USBMon*/
+
urb->complete ((struct urb *) urb);
spin_lock(&s->urb_list_lock);
@@ -2703,6 +2713,7 @@
// Completion
if (urb->complete) {
int was_unlinked = (urb->status == -ENOENT);
+ USBMon_urb_pre_completion(urb);/*USBMon*/
urb->dev = NULL;
spin_unlock(&s->urb_list_lock);
diff --exclude-from /sunbeam/home/laforge/scripts/dontdiff -Nru
linux-2.4.20-cjtest/drivers/usb/usb.c linux-2.4.20-cjtest-usbmon/drivers/usb/usb.c
--- linux-2.4.20-cjtest/drivers/usb/usb.c 2002-11-29 00:53:15.000000000 +0100
+++ linux-2.4.20-cjtest-usbmon/drivers/usb/usb.c 2004-06-04 13:32:23.000000000
+0200
@@ -268,7 +268,8 @@
/*
* usb_check_bandwidth():
*
- * old_alloc is from host_controller->bandwidth_allocated in microseconds;
+ * old_
+ is from host_controller->bandwidth_allocated in microseconds;
* bustime is from calc_bus_time(), but converted to microseconds.
*
* returns <bustime in us> if successful,
@@ -960,6 +961,15 @@
init_MUTEX(&dev->serialize);
+ dev->USBMon_data = kmalloc(sizeof(struct USBMon_data), GFP_KERNEL);
+ if(dev->USBMon_data == NULL){
+ return(NULL);
+ }
+ dev->USBMon_data->USBMon_urb_ll_head = NULL;/*USBMon*/
+ dev->USBMon_data->USBMon_urb_ll_last = NULL;/*USBMon*/
+ dev->USBMon_data->USBMon_urb_ll_buffered = NULL;/*USBMon*/
+ dev->USBMon_data->USBMon_monitored_endpoints = NULL;/*USBMon*/
+
dev->bus->op->allocate(dev);
return dev;
@@ -967,7 +977,22 @@
void usb_free_dev(struct usb_device *dev)
{
+ /*USBMon*/
+ struct usbmon_endpoint_ll *tmp_ep1,*tmp_ep2;
+ /*
+ tmp_ep1=dev->USBMon_data->USBMon_monitored_endpoints;
+ while(tmp_ep1 != NULL){
+ tmp_ep2=tmp_ep1->next;
+ kfree(tmp_ep1);
+ tmp_ep1=tmp_ep2;
+ }
+ kfree(dev->USBMon_data);
+ /*end USBMon*/
+
+
if (atomic_dec_and_test(&dev->refcnt)) {
+
+
dev->bus->op->deallocate(dev);
usb_destroy_configuration(dev);
@@ -2442,3 +2467,5 @@
EXPORT_SYMBOL(usb_devfs_handle);
MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(USBMon_urb_pre_completion);
diff --exclude-from /sunbeam/home/laforge/scripts/dontdiff -Nru
linux-2.4.20-cjtest/include/linux/usb.h linux-2.4.20-cjtest-usbmon/include/linux/usb.h
--- linux-2.4.20-cjtest/include/linux/usb.h 2004-06-01 14:44:47.000000000 +0200
+++ linux-2.4.20-cjtest-usbmon/include/linux/usb.h 2004-06-04 13:30:34.000000000
+0200
@@ -139,6 +139,7 @@
#include <linux/interrupt.h> /* for in_interrupt() */
#include <linux/config.h>
#include <linux/list.h>
+#include <linux/time.h> /* for USBMon */
#define USB_MAJOR 180
@@ -525,6 +526,7 @@
usb_complete_t complete; // pointer to completion routine
//
struct iso_packet_descriptor iso_frame_desc[0];
+ struct timeval completion_time; // for USBMon timestamping
};
/**
@@ -813,6 +815,25 @@
*/
#define USB_MAXCHILDREN (16)
+/*
+ * struct usbmon_endpoint_ll;
+ */
+struct usbmon_endpoint_ll {
+ unsigned int value;
+ struct usbmon_endpoint_ll *next;
+ int level;
+};
+
+struct USBMon_data {
+ struct usbmon_endpoint_ll *USBMon_monitored_endpoints; /*USBMon*/
+ struct urb *USBMon_urb_ll_head;/*USBMon*/
+ struct urb *USBMon_urb_ll_last;/*USBMon*/
+ struct urb *USBMon_urb_ll_buffered;/*USBMon*/
+ unsigned char USBMon_write_buffer[4];
+};
+
+void USBMon_urb_pre_completion(struct urb *purb);
+
struct usb_device {
int devnum; /* Address on USB bus */
char devpath [16]; /* Use in messages: /port/port/... */
@@ -863,6 +884,7 @@
int maxchild; /* Number of ports if hub */
struct usb_device *children[USB_MAXCHILDREN];
+ struct USBMon_data *USBMon_data;
};
extern struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum);
diff --exclude-from /sunbeam/home/laforge/scripts/dontdiff -Nru
linux-2.4.20-cjtest/include/linux/usbdevice_fs.h
linux-2.4.20-cjtest-usbmon/include/linux/usbdevice_fs.h
--- linux-2.4.20-cjtest/include/linux/usbdevice_fs.h 2004-06-01 14:47:42.000000000
+0200
+++ linux-2.4.20-cjtest-usbmon/include/linux/usbdevice_fs.h 2004-06-04
12:03:10.000000000 +0200
@@ -157,6 +157,7 @@
#define ISPECIAL (0<<28)
#define IBUS (1<<28)
#define IDEVICE (2<<28)
+#define IDEVICEMON (4<<28) /*USBMon Addition */
#define IBUSNR(x) (((x)>>8)&0xff)
#define IDEVNR(x) ((x)&0xff)
@@ -181,7 +182,8 @@
extern struct usb_driver usbdevfs_driver;
extern struct file_operations usbdevfs_drivers_fops;
extern struct file_operations usbdevfs_devices_fops;
-extern struct file_operations usbdevfs_device_file_operations;
+extern struct file_operations usbdevfs_devicemon_file_operations;
+extern struct file_operations usbdevfs_device_file_operations; /*USBMon*/
extern struct inode_operations usbdevfs_device_inode_operations;
extern struct inode_operations usbdevfs_bus_inode_operations;
extern struct file_operations usbdevfs_bus_file_operations;
signature.asc
Description: Digital signature
