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; }
/* * For simplicity, we read one record in one system call and throw out * what does not fit. This means that the following does not work: * dd if=/dbg/usbmon/0t bs=10 * Also, we do not allow seeks and do not bother advancing the offset. */ static ssize_t mon_text_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) { struct mon_reader_text *rp = file->private_data; struct mon_bus *mbus = rp->r.m_bus; DECLARE_WAITQUEUE(waita, current); struct mon_event_text *ep; int cnt, limit; char *pbuf; char udir, utype; int data_len, i; 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 -EWOULDBLOCK; /* Same as EAGAIN in Linux */ } /* * 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 -EINTR; } set_current_state(TASK_INTERRUPTIBLE); } set_current_state(TASK_RUNNING); remove_wait_queue(&rp->wait, &waita); down(&rp->printf_lock); cnt = 0; pbuf = rp->printf_buf; limit = rp->printf_size; udir = usb_pipein(ep->pipe) ? 'i' : 'o'; switch (usb_pipetype(ep->pipe)) { case PIPE_ISOCHRONOUS: utype = 'Z'; break; case PIPE_INTERRUPT: utype = 'I'; break; case PIPE_CONTROL: utype = 'C'; break; default: /* PIPE_BULK */ utype = 'B'; } cnt += snprintf(pbuf + cnt, limit - cnt, "%lx %u %c %c%c:%03u:%02u", ep->id, ep->tstamp, ep->type, utype, udir, usb_pipedevice(ep->pipe), usb_pipeendpoint(ep->pipe)); if (ep->setup_flag == 0) { /* Setup packet is present and captured */ cnt += snprintf(pbuf + cnt, limit - 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 */ cnt += snprintf(pbuf + cnt, limit - cnt, " %c __ __ ____ ____ ____", ep->setup_flag); } else { /* No setup for this kind of URB */ cnt += snprintf(pbuf + cnt, limit - cnt, " %d", ep->status); } cnt += snprintf(pbuf + cnt, limit - cnt, " %d", ep->length); if ((data_len = ep->length) > 0) { if (ep->data_flag == 0) { cnt += snprintf(pbuf + cnt, limit - cnt, " ="); if (data_len >= DATA_MAX) data_len = DATA_MAX; for (i = 0; i < data_len; i++) { if (i % 4 == 0) { cnt += snprintf(pbuf + cnt, limit - cnt, " "); } cnt += snprintf(pbuf + cnt, limit - cnt, "%02x", ep->data[i]); } cnt += snprintf(pbuf + cnt, limit - cnt, "\n"); } else { cnt += snprintf(pbuf + cnt, limit - cnt, " %c\n", ep->data_flag); } } else { cnt += snprintf(pbuf + cnt, limit - cnt, "\n"); } if (copy_to_user(buf, rp->printf_buf, cnt)) cnt = -EFAULT; up(&rp->printf_lock); kmem_cache_free(rp->e_slab, ep); return cnt; }