mon_text.c
来自「linux 内核源代码」· C语言 代码 · 共 753 行 · 第 1/2 页
C
753 行
{ struct mon_reader_text *rp = file->private_data; struct mon_event_text *ep; struct mon_text_ptr ptr; if (IS_ERR(ep = mon_text_read_wait(rp, file))) return PTR_ERR(ep); mutex_lock(&rp->printf_lock); ptr.cnt = 0; ptr.pbuf = rp->printf_buf; ptr.limit = rp->printf_size; mon_text_read_head_t(rp, &ptr, ep); mon_text_read_statset(rp, &ptr, ep); ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt, " %d", ep->length); mon_text_read_data(rp, &ptr, ep); if (copy_to_user(buf, rp->printf_buf, ptr.cnt)) ptr.cnt = -EFAULT; mutex_unlock(&rp->printf_lock); kmem_cache_free(rp->e_slab, ep); return ptr.cnt;}static ssize_t mon_text_read_u(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos){ struct mon_reader_text *rp = file->private_data; struct mon_event_text *ep; struct mon_text_ptr ptr; if (IS_ERR(ep = mon_text_read_wait(rp, file))) return PTR_ERR(ep); mutex_lock(&rp->printf_lock); ptr.cnt = 0; ptr.pbuf = rp->printf_buf; ptr.limit = rp->printf_size; mon_text_read_head_u(rp, &ptr, ep); if (ep->type == 'E') { mon_text_read_statset(rp, &ptr, ep); } else if (ep->xfertype == USB_ENDPOINT_XFER_ISOC) { mon_text_read_isostat(rp, &ptr, ep); mon_text_read_isodesc(rp, &ptr, ep); } else if (ep->xfertype == USB_ENDPOINT_XFER_INT) { mon_text_read_intstat(rp, &ptr, ep); } else { mon_text_read_statset(rp, &ptr, ep); } ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt, " %d", ep->length); mon_text_read_data(rp, &ptr, ep); if (copy_to_user(buf, rp->printf_buf, ptr.cnt)) ptr.cnt = -EFAULT; mutex_unlock(&rp->printf_lock); kmem_cache_free(rp->e_slab, ep); return ptr.cnt;}static struct mon_event_text *mon_text_read_wait(struct mon_reader_text *rp, struct file *file){ struct mon_bus *mbus = rp->r.m_bus; DECLARE_WAITQUEUE(waita, current); struct mon_event_text *ep; add_wait_queue(&rp->wait, &waita); set_current_state(TASK_INTERRUPTIBLE); while ((ep = mon_text_fetch(rp, mbus)) == NULL) { if (file->f_flags & O_NONBLOCK) { set_current_state(TASK_RUNNING); remove_wait_queue(&rp->wait, &waita); return ERR_PTR(-EWOULDBLOCK); } /* * We do not count nwaiters, because ->release is supposed * to be called when all openers are gone only. */ schedule(); if (signal_pending(current)) { remove_wait_queue(&rp->wait, &waita); return ERR_PTR(-EINTR); } set_current_state(TASK_INTERRUPTIBLE); } set_current_state(TASK_RUNNING); remove_wait_queue(&rp->wait, &waita); return ep;}static void mon_text_read_head_t(struct mon_reader_text *rp, struct mon_text_ptr *p, const struct mon_event_text *ep){ char udir, utype; udir = (ep->is_in ? 'i' : 'o'); switch (ep->xfertype) { case USB_ENDPOINT_XFER_ISOC: utype = 'Z'; break; case USB_ENDPOINT_XFER_INT: utype = 'I'; break; case USB_ENDPOINT_XFER_CONTROL: utype = 'C'; break; default: /* PIPE_BULK */ utype = 'B'; } p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt, "%lx %u %c %c%c:%03u:%02u", ep->id, ep->tstamp, ep->type, utype, udir, ep->devnum, ep->epnum);}static void mon_text_read_head_u(struct mon_reader_text *rp, struct mon_text_ptr *p, const struct mon_event_text *ep){ char udir, utype; udir = (ep->is_in ? 'i' : 'o'); switch (ep->xfertype) { case USB_ENDPOINT_XFER_ISOC: utype = 'Z'; break; case USB_ENDPOINT_XFER_INT: utype = 'I'; break; case USB_ENDPOINT_XFER_CONTROL: utype = 'C'; break; default: /* PIPE_BULK */ utype = 'B'; } p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt, "%lx %u %c %c%c:%d:%03u:%u", ep->id, ep->tstamp, ep->type, utype, udir, ep->busnum, ep->devnum, ep->epnum);}static void mon_text_read_statset(struct mon_reader_text *rp, struct mon_text_ptr *p, const struct mon_event_text *ep){ if (ep->setup_flag == 0) { /* Setup packet is present and captured */ p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt, " s %02x %02x %04x %04x %04x", ep->setup[0], ep->setup[1], (ep->setup[3] << 8) | ep->setup[2], (ep->setup[5] << 8) | ep->setup[4], (ep->setup[7] << 8) | ep->setup[6]); } else if (ep->setup_flag != '-') { /* Unable to capture setup packet */ p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt, " %c __ __ ____ ____ ____", ep->setup_flag); } else { /* No setup for this kind of URB */ p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt, " %d", ep->status); }}static void mon_text_read_intstat(struct mon_reader_text *rp, struct mon_text_ptr *p, const struct mon_event_text *ep){ p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt, " %d:%d", ep->status, ep->interval);}static void mon_text_read_isostat(struct mon_reader_text *rp, struct mon_text_ptr *p, const struct mon_event_text *ep){ if (ep->type == 'S') { p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt, " %d:%d:%d", ep->status, ep->interval, ep->start_frame); } else { p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt, " %d:%d:%d:%d", ep->status, ep->interval, ep->start_frame, ep->error_count); }}static void mon_text_read_isodesc(struct mon_reader_text *rp, struct mon_text_ptr *p, const struct mon_event_text *ep){ int ndesc; /* Display this many */ int i; const struct mon_iso_desc *dp; p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt, " %d", ep->numdesc); ndesc = ep->numdesc; if (ndesc > ISODESC_MAX) ndesc = ISODESC_MAX; if (ndesc < 0) ndesc = 0; dp = ep->isodesc; for (i = 0; i < ndesc; i++) { p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt, " %d:%u:%u", dp->status, dp->offset, dp->length); dp++; }}static void mon_text_read_data(struct mon_reader_text *rp, struct mon_text_ptr *p, const struct mon_event_text *ep){ int data_len, i; if ((data_len = ep->length) > 0) { if (ep->data_flag == 0) { p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt, " ="); if (data_len >= DATA_MAX) data_len = DATA_MAX; for (i = 0; i < data_len; i++) { if (i % 4 == 0) { p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt, " "); } p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt, "%02x", ep->data[i]); } p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt, "\n"); } else { p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt, " %c\n", ep->data_flag); } } else { p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt, "\n"); }}static int mon_text_release(struct inode *inode, struct file *file){ struct mon_reader_text *rp = file->private_data; struct mon_bus *mbus; /* unsigned long flags; */ struct list_head *p; struct mon_event_text *ep; mutex_lock(&mon_lock); mbus = inode->i_private; if (mbus->nreaders <= 0) { printk(KERN_ERR TAG ": consistency error on close\n"); mutex_unlock(&mon_lock); return 0; } mon_reader_del(mbus, &rp->r); /* * In theory, e_list is protected by mbus->lock. However, * after mon_reader_del has finished, the following is the case: * - we are not on reader list anymore, so new events won't be added; * - whole mbus may be dropped if it was orphaned. * So, we better not touch mbus. */ /* spin_lock_irqsave(&mbus->lock, flags); */ while (!list_empty(&rp->e_list)) { p = rp->e_list.next; ep = list_entry(p, struct mon_event_text, e_link); list_del(p); --rp->nevents; kmem_cache_free(rp->e_slab, ep); } /* spin_unlock_irqrestore(&mbus->lock, flags); */ kmem_cache_destroy(rp->e_slab); kfree(rp->printf_buf); kfree(rp); mutex_unlock(&mon_lock); return 0;}static const struct file_operations mon_fops_text_t = { .owner = THIS_MODULE, .open = mon_text_open, .llseek = no_llseek, .read = mon_text_read_t, .release = mon_text_release,};static const struct file_operations mon_fops_text_u = { .owner = THIS_MODULE, .open = mon_text_open, .llseek = no_llseek, .read = mon_text_read_u, .release = mon_text_release,};int mon_text_add(struct mon_bus *mbus, const struct usb_bus *ubus){ struct dentry *d; enum { NAMESZ = 10 }; char name[NAMESZ]; int busnum = ubus? ubus->busnum: 0; int rc; if (ubus != NULL) { rc = snprintf(name, NAMESZ, "%dt", busnum); if (rc <= 0 || rc >= NAMESZ) goto err_print_t; d = debugfs_create_file(name, 0600, mon_dir, mbus, &mon_fops_text_t); if (d == NULL) goto err_create_t; mbus->dent_t = d; } rc = snprintf(name, NAMESZ, "%du", busnum); if (rc <= 0 || rc >= NAMESZ) goto err_print_u; d = debugfs_create_file(name, 0600, mon_dir, mbus, &mon_fops_text_u); if (d == NULL) goto err_create_u; mbus->dent_u = d; rc = snprintf(name, NAMESZ, "%ds", busnum); if (rc <= 0 || rc >= NAMESZ) goto err_print_s; d = debugfs_create_file(name, 0600, mon_dir, mbus, &mon_fops_stat); if (d == NULL) goto err_create_s; mbus->dent_s = d; return 1;err_create_s:err_print_s: debugfs_remove(mbus->dent_u); mbus->dent_u = NULL;err_create_u:err_print_u: if (ubus != NULL) { debugfs_remove(mbus->dent_t); mbus->dent_t = NULL; }err_create_t:err_print_t: return 0;}void mon_text_del(struct mon_bus *mbus){ debugfs_remove(mbus->dent_u); if (mbus->dent_t != NULL) debugfs_remove(mbus->dent_t); debugfs_remove(mbus->dent_s);}/* * Slab interface: constructor. */static void mon_text_ctor(struct kmem_cache *slab, void *mem){ /* * Nothing to initialize. No, really! * So, we fill it with garbage to emulate a reused object. */ memset(mem, 0xe5, sizeof(struct mon_event_text));}int __init mon_text_init(void){ struct dentry *mondir; mondir = debugfs_create_dir("usbmon", NULL); if (IS_ERR(mondir)) { printk(KERN_NOTICE TAG ": debugfs is not available\n"); return -ENODEV; } if (mondir == NULL) { printk(KERN_NOTICE TAG ": unable to create usbmon directory\n"); return -ENODEV; } mon_dir = mondir; return 0;}void mon_text_exit(void){ debugfs_remove(mon_dir);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?