Loading Documentation/input/yealink.txt 0 → 100644 +203 −0 Original line number Diff line number Diff line Driver documentation for yealink usb-p1k phones 0. Status ~~~~~~~~~ The p1k is a relatively cheap usb 1.1 phone with: - keyboard full support, yealink.ko / input event API - LCD full support, yealink.ko / sysfs API - LED full support, yealink.ko / sysfs API - dialtone full support, yealink.ko / sysfs API - ringtone full support, yealink.ko / sysfs API - audio playback full support, snd_usb_audio.ko / alsa API - audio record full support, snd_usb_audio.ko / alsa API For vendor documentation see http://www.yealink.com 1. Compilation (stand alone version) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Currently only kernel 2.6.x.y versions are supported. In order to build the yealink.ko module do: make If you encounter problems please check if in the MAKE_OPTS variable in the Makefile is pointing to the location where your kernel sources are located, default /usr/src/linux. 2. keyboard features ~~~~~~~~~~~~~~~~~~~~ The current mapping in the kernel is provided by the map_p1k_to_key function: Physical USB-P1K button layout input events up up IN OUT left, right down down pickup C hangup enter, backspace, escape 1 2 3 1, 2, 3 4 5 6 4, 5, 6, 7 8 9 7, 8, 9, * 0 # *, 0, #, The "up" and "down" keys, are symbolised by arrows on the button. The "pickup" and "hangup" keys are symbolised by a green and red phone on the button. 3. LCD features ~~~~~~~~~~~~~~~ The LCD is divided and organised as a 3 line display: |[] [][] [][] [][] in |[][] |[] M [][] D [][] : [][] out |[][] store NEW REP SU MO TU WE TH FR SA [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] Line 1 Format (see below) : 18.e8.M8.88...188 Icon names : M D : IN OUT STORE Line 2 Format : ......... Icon name : NEW REP SU MO TU WE TH FR SA Line 3 Format : 888888888888 Format description: From a user space perspective the world is seperated in "digits" and "icons". A digit can have a character set, an icon can only be ON or OFF. Format specifier '8' : Generic 7 segment digit with individual addressable segments Reduced capabillity 7 segm digit, when segments are hard wired together. '1' : 2 segments digit only able to produce a 1. 'e' : Most significant day of the month digit, able to produce at least 1 2 3. 'M' : Most significant minute digit, able to produce at least 0 1 2 3 4 5. Icons or pictograms: '.' : For example like AM, PM, SU, a 'dot' .. or other single segment elements. 4. Driver usage ~~~~~~~~~~~~~~~ For userland the following interfaces are available using the sysfs interface: /sys/.../ line1 Read/Write, lcd line1 line2 Read/Write, lcd line2 line3 Read/Write, lcd line3 get_icons Read, returns a set of available icons. hide_icon Write, hide the element by writing the icon name. show_icon Write, display the element by writing the icon name. map_seg7 Read/Write, the 7 segments char set, common for all yealink phones. (see map_to_7segment.h) ringtone Write, upload binary representation of a ringtone, see yealink.c. status EXPERIMENTAL due to potential races between async. and sync usb calls. 4.1 lineX ~~~~~~~~~ Reading /sys/../lineX will return the format string with its current value: Example: cat ./line3 888888888888 Linux Rocks! Writing to /sys/../lineX will set the coresponding LCD line. - Excess characters are ignored. - If less characters are written than allowed, the remaining digits are unchanged. - The tab '\t'and '\n' char does not overwrite the original content. - Writing a space to an icon will always hide its content. Example: date +"%m.%e.%k:%M" | sed 's/^0/ /' > ./line1 Will update the LCD with the current date & time. 4.2 get_icons ~~~~~~~~~~~~~ Reading will return all available icon names and its current settings: cat ./get_icons on M on D on : IN OUT STORE NEW REP SU MO TU WE TH FR SA LED DIALTONE RINGTONE 4.3 show/hide icons ~~~~~~~~~~~~~~~~~~~ Writing to these files will update the state of the icon. Only one icon at a time can be updated. If an icon is also on a ./lineX the corresponding value is updated with the first letter of the icon. Example - light up the store icon: echo -n "STORE" > ./show_icon cat ./line1 18.e8.M8.88...188 S Example - sound the ringtone for 10 seconds: echo -n RINGTONE > /sys/..../show_icon sleep 10 echo -n RINGTONE > /sys/..../hide_icon 5. Sound features ~~~~~~~~~~~~~~~~~ Sound is supported by the ALSA driver: snd_usb_audio One 16-bit channel with sample and playback rates of 8000 Hz is the practical limit of the device. Example - recording test: arecord -v -d 10 -r 8000 -f S16_LE -t wav foobar.wav Example - playback test: aplay foobar.wav 6. Credits & Acknowledgments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Olivier Vandorpe, for starting the usbb2k-api project doing much of the reverse engineering. - Martin Diehl, for pointing out how to handle USB memory allocation. - Dmitry Torokhov, for the numerous code reviews and suggestions. MAINTAINERS +6 −0 Original line number Diff line number Diff line Loading @@ -116,6 +116,12 @@ M: ajk@iehk.rwth-aachen.de L: linux-hams@vger.kernel.org S: Maintained YEALINK PHONE DRIVER P: Henk Vergonet M: Henk.Vergonet@gmail.com L: usbb2k-api-dev@nongnu.org S: Maintained 8139CP 10/100 FAST ETHERNET DRIVER P: Jeff Garzik M: jgarzik@pobox.com Loading drivers/block/ub.c +150 −123 Original line number Diff line number Diff line Loading @@ -16,9 +16,10 @@ * -- verify the 13 conditions and do bulk resets * -- kill last_pipe and simply do two-state clearing on both pipes * -- verify protocol (bulk) from USB descriptors (maybe...) * -- highmem and sg * -- highmem * -- move top_sense and work_bcs into separate allocations (if they survive) * for cache purists and esoteric architectures. * -- Allocate structure for LUN 0 before the first ub_sync_tur, avoid NULL. ? * -- prune comments, they are too volumnous * -- Exterminate P3 printks * -- Resove XXX's Loading Loading @@ -171,7 +172,7 @@ struct bulk_cs_wrap { */ struct ub_dev; #define UB_MAX_REQ_SG 1 #define UB_MAX_REQ_SG 4 #define UB_MAX_SECTORS 64 /* Loading Loading @@ -234,13 +235,10 @@ struct ub_scsi_cmd { int stat_count; /* Retries getting status. */ /* * We do not support transfers from highmem pages * because the underlying USB framework does not do what we need. */ char *data; /* Requested buffer */ unsigned int len; /* Requested length */ // struct scatterlist sgv[UB_MAX_REQ_SG]; unsigned int current_sg; unsigned int nsg; /* sgv[nsg] */ struct scatterlist sgv[UB_MAX_REQ_SG]; struct ub_lun *lun; void (*done)(struct ub_dev *, struct ub_scsi_cmd *); Loading Loading @@ -389,17 +387,18 @@ struct ub_dev { struct bulk_cs_wrap work_bcs; struct usb_ctrlrequest work_cr; int sg_stat[UB_MAX_REQ_SG+1]; struct ub_scsi_trace tr; }; /* */ static void ub_cleanup(struct ub_dev *sc); static int ub_bd_rq_fn_1(struct ub_lun *lun, struct request *rq); static int ub_request_fn_1(struct ub_lun *lun, struct request *rq); static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun, struct ub_scsi_cmd *cmd, struct request *rq); static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_scsi_cmd *cmd, struct request *rq); static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun, struct ub_scsi_cmd *cmd, struct request *rq); static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd); static void ub_end_rq(struct request *rq, int uptodate); static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd); Loading @@ -407,6 +406,7 @@ static void ub_urb_complete(struct urb *urb, struct pt_regs *pt); static void ub_scsi_action(unsigned long _dev); static void ub_scsi_dispatch(struct ub_dev *sc); static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd); static void ub_data_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd); static void ub_state_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd, int rc); static int __ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd); static void ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd); Loading Loading @@ -500,7 +500,8 @@ static void ub_cmdtr_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd, } } static ssize_t ub_diag_show(struct device *dev, struct device_attribute *attr, char *page) static ssize_t ub_diag_show(struct device *dev, struct device_attribute *attr, char *page) { struct usb_interface *intf; struct ub_dev *sc; Loading @@ -523,6 +524,13 @@ static ssize_t ub_diag_show(struct device *dev, struct device_attribute *attr, c cnt += sprintf(page + cnt, "qlen %d qmax %d\n", sc->cmd_queue.qlen, sc->cmd_queue.qmax); cnt += sprintf(page + cnt, "sg %d %d %d %d %d\n", sc->sg_stat[0], sc->sg_stat[1], sc->sg_stat[2], sc->sg_stat[3], sc->sg_stat[4]); list_for_each (p, &sc->luns) { lun = list_entry(p, struct ub_lun, link); Loading Loading @@ -744,20 +752,20 @@ static struct ub_scsi_cmd *ub_cmdq_pop(struct ub_dev *sc) * The request function is our main entry point */ static void ub_bd_rq_fn(request_queue_t *q) static void ub_request_fn(request_queue_t *q) { struct ub_lun *lun = q->queuedata; struct request *rq; while ((rq = elv_next_request(q)) != NULL) { if (ub_bd_rq_fn_1(lun, rq) != 0) { if (ub_request_fn_1(lun, rq) != 0) { blk_stop_queue(q); break; } } } static int ub_bd_rq_fn_1(struct ub_lun *lun, struct request *rq) static int ub_request_fn_1(struct ub_lun *lun, struct request *rq) { struct ub_dev *sc = lun->udev; struct ub_scsi_cmd *cmd; Loading @@ -774,9 +782,8 @@ static int ub_bd_rq_fn_1(struct ub_lun *lun, struct request *rq) memset(cmd, 0, sizeof(struct ub_scsi_cmd)); blkdev_dequeue_request(rq); if (blk_pc_request(rq)) { rc = ub_cmd_build_packet(sc, cmd, rq); rc = ub_cmd_build_packet(sc, lun, cmd, rq); } else { rc = ub_cmd_build_block(sc, lun, cmd, rq); } Loading @@ -791,7 +798,7 @@ static int ub_bd_rq_fn_1(struct ub_lun *lun, struct request *rq) cmd->back = rq; cmd->tag = sc->tagcnt++; if ((rc = ub_submit_scsi(sc, cmd)) != 0) { if (ub_submit_scsi(sc, cmd) != 0) { ub_put_cmd(lun, cmd); ub_end_rq(rq, 0); return 0; Loading @@ -804,58 +811,31 @@ static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun, struct ub_scsi_cmd *cmd, struct request *rq) { int ub_dir; #if 0 /* We use rq->buffer for now */ struct scatterlist *sg; int n_elem; #endif unsigned int block, nblks; if (rq_data_dir(rq) == WRITE) ub_dir = UB_DIR_WRITE; else ub_dir = UB_DIR_READ; cmd->dir = ub_dir; /* * get scatterlist from block layer */ #if 0 /* We use rq->buffer for now */ sg = &cmd->sgv[0]; n_elem = blk_rq_map_sg(q, rq, sg); n_elem = blk_rq_map_sg(lun->disk->queue, rq, &cmd->sgv[0]); if (n_elem <= 0) { ub_put_cmd(lun, cmd); ub_end_rq(rq, 0); blk_start_queue(q); return 0; /* request with no s/g entries? */ printk(KERN_INFO "%s: failed request map (%d)\n", sc->name, n_elem); /* P3 */ return -1; /* request with no s/g entries? */ } if (n_elem != 1) { /* Paranoia */ if (n_elem > UB_MAX_REQ_SG) { /* Paranoia */ printk(KERN_WARNING "%s: request with %d segments\n", sc->name, n_elem); ub_put_cmd(lun, cmd); ub_end_rq(rq, 0); blk_start_queue(q); return 0; } #endif /* * XXX Unfortunately, this check does not work. It is quite possible * to get bogus non-null rq->buffer if you allow sg by mistake. */ if (rq->buffer == NULL) { /* * This must not happen if we set the queue right. * The block level must create bounce buffers for us. */ static int do_print = 1; if (do_print) { printk(KERN_WARNING "%s: unmapped block request" " flags 0x%lx sectors %lu\n", sc->name, rq->flags, rq->nr_sectors); do_print = 0; } return -1; } cmd->nsg = n_elem; sc->sg_stat[n_elem]++; /* * build the command Loading @@ -876,30 +856,15 @@ static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun, cmd->cdb[8] = nblks; cmd->cdb_len = 10; cmd->dir = ub_dir; cmd->data = rq->buffer; cmd->len = rq->nr_sectors * 512; return 0; } static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_scsi_cmd *cmd, struct request *rq) static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun, struct ub_scsi_cmd *cmd, struct request *rq) { if (rq->data_len != 0 && rq->data == NULL) { static int do_print = 1; if (do_print) { printk(KERN_WARNING "%s: unmapped packet request" " flags 0x%lx length %d\n", sc->name, rq->flags, rq->data_len); do_print = 0; } return -1; } memcpy(&cmd->cdb, rq->cmd, rq->cmd_len); cmd->cdb_len = rq->cmd_len; int n_elem; if (rq->data_len == 0) { cmd->dir = UB_DIR_NONE; Loading @@ -908,8 +873,29 @@ static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_scsi_cmd *cmd, cmd->dir = UB_DIR_WRITE; else cmd->dir = UB_DIR_READ; } cmd->data = rq->data; /* * get scatterlist from block layer */ n_elem = blk_rq_map_sg(lun->disk->queue, rq, &cmd->sgv[0]); if (n_elem < 0) { printk(KERN_INFO "%s: failed request map (%d)\n", sc->name, n_elem); /* P3 */ return -1; } if (n_elem > UB_MAX_REQ_SG) { /* Paranoia */ printk(KERN_WARNING "%s: request with %d segments\n", sc->name, n_elem); return -1; } cmd->nsg = n_elem; sc->sg_stat[n_elem]++; memcpy(&cmd->cdb, rq->cmd, rq->cmd_len); cmd->cdb_len = rq->cmd_len; cmd->len = rq->data_len; return 0; Loading @@ -919,24 +905,34 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd) { struct request *rq = cmd->back; struct ub_lun *lun = cmd->lun; struct gendisk *disk = lun->disk; request_queue_t *q = disk->queue; int uptodate; if (cmd->error == 0) { uptodate = 1; if (blk_pc_request(rq)) { if (cmd->act_len >= rq->data_len) rq->data_len = 0; else rq->data_len -= cmd->act_len; } } else { uptodate = 0; if (blk_pc_request(rq)) { /* UB_SENSE_SIZE is smaller than SCSI_SENSE_BUFFERSIZE */ memcpy(rq->sense, sc->top_sense, UB_SENSE_SIZE); rq->sense_len = UB_SENSE_SIZE; } if (cmd->error == 0) uptodate = 1; if (sc->top_sense[0] != 0) rq->errors = SAM_STAT_CHECK_CONDITION; else uptodate = 0; rq->errors = DID_ERROR << 16; } } ub_put_cmd(lun, cmd); ub_end_rq(rq, uptodate); blk_start_queue(q); blk_start_queue(lun->disk->queue); } static void ub_end_rq(struct request *rq, int uptodate) Loading Loading @@ -1014,7 +1010,7 @@ static int ub_scsi_cmd_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd) sc->last_pipe = sc->send_bulk_pipe; usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->send_bulk_pipe, bcb, US_BULK_CB_WRAP_LEN, ub_urb_complete, sc); sc->work_urb.transfer_flags = URB_ASYNC_UNLINK; sc->work_urb.transfer_flags = 0; /* Fill what we shouldn't be filling, because usb-storage did so. */ sc->work_urb.actual_length = 0; Loading Loading @@ -1103,7 +1099,6 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) { struct urb *urb = &sc->work_urb; struct bulk_cs_wrap *bcs; int pipe; int rc; if (atomic_read(&sc->poison)) { Loading Loading @@ -1204,38 +1199,13 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) goto Bad_End; } if (cmd->dir == UB_DIR_NONE) { if (cmd->dir == UB_DIR_NONE || cmd->nsg < 1) { ub_state_stat(sc, cmd); return; } UB_INIT_COMPLETION(sc->work_done); if (cmd->dir == UB_DIR_READ) pipe = sc->recv_bulk_pipe; else pipe = sc->send_bulk_pipe; sc->last_pipe = pipe; usb_fill_bulk_urb(&sc->work_urb, sc->dev, pipe, cmd->data, cmd->len, ub_urb_complete, sc); sc->work_urb.transfer_flags = URB_ASYNC_UNLINK; sc->work_urb.actual_length = 0; sc->work_urb.error_count = 0; sc->work_urb.status = 0; if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) { /* XXX Clear stalls */ printk("ub: data #%d submit failed (%d)\n", cmd->tag, rc); /* P3 */ ub_complete(&sc->work_done); ub_state_done(sc, cmd, rc); return; } sc->work_timer.expires = jiffies + UB_DATA_TIMEOUT; add_timer(&sc->work_timer); cmd->state = UB_CMDST_DATA; ub_cmdtr_state(sc, cmd); // udelay(125); // usb-storage has this ub_data_start(sc, cmd); } else if (cmd->state == UB_CMDST_DATA) { if (urb->status == -EPIPE) { Loading @@ -1257,16 +1227,22 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) if (urb->status == -EOVERFLOW) { /* * A babble? Failure, but we must transfer CSW now. * XXX This is going to end in perpetual babble. Reset. */ cmd->error = -EOVERFLOW; /* A cheap trick... */ } else { ub_state_stat(sc, cmd); return; } if (urb->status != 0) goto Bad_End; } cmd->act_len = urb->actual_length; cmd->act_len += urb->actual_length; ub_cmdtr_act_len(sc, cmd); if (++cmd->current_sg < cmd->nsg) { ub_data_start(sc, cmd); return; } ub_state_stat(sc, cmd); } else if (cmd->state == UB_CMDST_STAT) { Loading Loading @@ -1399,6 +1375,46 @@ Bad_End: /* Little Excel is dead */ ub_state_done(sc, cmd, -EIO); } /* * Factorization helper for the command state machine: * Initiate a data segment transfer. */ static void ub_data_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd) { struct scatterlist *sg = &cmd->sgv[cmd->current_sg]; int pipe; int rc; UB_INIT_COMPLETION(sc->work_done); if (cmd->dir == UB_DIR_READ) pipe = sc->recv_bulk_pipe; else pipe = sc->send_bulk_pipe; sc->last_pipe = pipe; usb_fill_bulk_urb(&sc->work_urb, sc->dev, pipe, page_address(sg->page) + sg->offset, sg->length, ub_urb_complete, sc); sc->work_urb.transfer_flags = 0; sc->work_urb.actual_length = 0; sc->work_urb.error_count = 0; sc->work_urb.status = 0; if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) { /* XXX Clear stalls */ printk("ub: data #%d submit failed (%d)\n", cmd->tag, rc); /* P3 */ ub_complete(&sc->work_done); ub_state_done(sc, cmd, rc); return; } sc->work_timer.expires = jiffies + UB_DATA_TIMEOUT; add_timer(&sc->work_timer); cmd->state = UB_CMDST_DATA; ub_cmdtr_state(sc, cmd); } /* * Factorization helper for the command state machine: * Finish the command. Loading Loading @@ -1426,7 +1442,7 @@ static int __ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd) sc->last_pipe = sc->recv_bulk_pipe; usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->recv_bulk_pipe, &sc->work_bcs, US_BULK_CS_WRAP_LEN, ub_urb_complete, sc); sc->work_urb.transfer_flags = URB_ASYNC_UNLINK; sc->work_urb.transfer_flags = 0; sc->work_urb.actual_length = 0; sc->work_urb.error_count = 0; sc->work_urb.status = 0; Loading Loading @@ -1484,6 +1500,7 @@ static void ub_state_stat_counted(struct ub_dev *sc, struct ub_scsi_cmd *cmd) static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd) { struct ub_scsi_cmd *scmd; struct scatterlist *sg; int rc; if (cmd->cdb[0] == REQUEST_SENSE) { Loading @@ -1492,12 +1509,17 @@ static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd) } scmd = &sc->top_rqs_cmd; memset(scmd, 0, sizeof(struct ub_scsi_cmd)); scmd->cdb[0] = REQUEST_SENSE; scmd->cdb[4] = UB_SENSE_SIZE; scmd->cdb_len = 6; scmd->dir = UB_DIR_READ; scmd->state = UB_CMDST_INIT; scmd->data = sc->top_sense; scmd->nsg = 1; sg = &scmd->sgv[0]; sg->page = virt_to_page(sc->top_sense); sg->offset = (unsigned int)sc->top_sense & (PAGE_SIZE-1); sg->length = UB_SENSE_SIZE; scmd->len = UB_SENSE_SIZE; scmd->lun = cmd->lun; scmd->done = ub_top_sense_done; Loading Loading @@ -1541,7 +1563,7 @@ static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd, usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe, (unsigned char*) cr, NULL, 0, ub_urb_complete, sc); sc->work_urb.transfer_flags = URB_ASYNC_UNLINK; sc->work_urb.transfer_flags = 0; sc->work_urb.actual_length = 0; sc->work_urb.error_count = 0; sc->work_urb.status = 0; Loading @@ -1560,7 +1582,7 @@ static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd, */ static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd) { unsigned char *sense = scmd->data; unsigned char *sense = sc->top_sense; struct ub_scsi_cmd *cmd; /* Loading Loading @@ -1852,6 +1874,7 @@ static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun, struct ub_capacity *ret) { struct ub_scsi_cmd *cmd; struct scatterlist *sg; char *p; enum { ALLOC_SIZE = sizeof(struct ub_scsi_cmd) + 8 }; unsigned long flags; Loading @@ -1872,7 +1895,11 @@ static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun, cmd->cdb_len = 10; cmd->dir = UB_DIR_READ; cmd->state = UB_CMDST_INIT; cmd->data = p; cmd->nsg = 1; sg = &cmd->sgv[0]; sg->page = virt_to_page(p); sg->offset = (unsigned int)p & (PAGE_SIZE-1); sg->length = 8; cmd->len = 8; cmd->lun = lun; cmd->done = ub_probe_done; Loading Loading @@ -2289,7 +2316,7 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum) disk->driverfs_dev = &sc->intf->dev; /* XXX Many to one ok? */ rc = -ENOMEM; if ((q = blk_init_queue(ub_bd_rq_fn, &sc->lock)) == NULL) if ((q = blk_init_queue(ub_request_fn, &sc->lock)) == NULL) goto err_blkqinit; disk->queue = q; Loading drivers/net/irda/irda-usb.c +2 −11 Original line number Diff line number Diff line Loading @@ -267,7 +267,7 @@ static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self) frame, IRDA_USB_SPEED_MTU, speed_bulk_callback, self); urb->transfer_buffer_length = USB_IRDA_HEADER; urb->transfer_flags = URB_ASYNC_UNLINK; urb->transfer_flags = 0; /* Irq disabled -> GFP_ATOMIC */ if ((ret = usb_submit_urb(urb, GFP_ATOMIC))) { Loading Loading @@ -401,15 +401,12 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev) skb->data, IRDA_SKB_MAX_MTU, write_bulk_callback, skb); urb->transfer_buffer_length = skb->len; /* Note : unlink *must* be Asynchronous because of the code in * irda_usb_net_timeout() -> call in irq - Jean II */ urb->transfer_flags = URB_ASYNC_UNLINK; /* This flag (URB_ZERO_PACKET) indicates that what we send is not * a continuous stream of data but separate packets. * In this case, the USB layer will insert an empty USB frame (TD) * after each of our packets that is exact multiple of the frame size. * This is how the dongle will detect the end of packet - Jean II */ urb->transfer_flags |= URB_ZERO_PACKET; urb->transfer_flags = URB_ZERO_PACKET; /* Generate min turn time. FIXME: can we do better than this? */ /* Trying to a turnaround time at this level is trying to measure Loading Loading @@ -630,8 +627,6 @@ static void irda_usb_net_timeout(struct net_device *netdev) * in completion handler, because urb->status will * be -ENOENT. We will fix that at the next watchdog, * leaving more time to USB to recover... * Also, we are in interrupt, so we need to have * URB_ASYNC_UNLINK to work properly... * Jean II */ done = 1; break; Loading Loading @@ -1008,9 +1003,7 @@ static int irda_usb_net_close(struct net_device *netdev) } } /* Cancel Tx and speed URB - need to be synchronous to avoid races */ self->tx_urb->transfer_flags &= ~URB_ASYNC_UNLINK; usb_kill_urb(self->tx_urb); self->speed_urb->transfer_flags &= ~URB_ASYNC_UNLINK; usb_kill_urb(self->speed_urb); /* Stop and remove instance of IrLAP */ Loading Loading @@ -1521,9 +1514,7 @@ static void irda_usb_disconnect(struct usb_interface *intf) usb_kill_urb(self->rx_urb[i]); /* Cancel Tx and speed URB. * Toggle flags to make sure it's synchronous. */ self->tx_urb->transfer_flags &= ~URB_ASYNC_UNLINK; usb_kill_urb(self->tx_urb); self->speed_urb->transfer_flags &= ~URB_ASYNC_UNLINK; usb_kill_urb(self->speed_urb); } Loading drivers/usb/atm/cxacru.c +0 −2 Original line number Diff line number Diff line Loading @@ -715,13 +715,11 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance, usb_dev, usb_rcvintpipe(usb_dev, CXACRU_EP_CMD), instance->rcv_buf, PAGE_SIZE, cxacru_blocking_completion, &instance->rcv_done, 1); instance->rcv_urb->transfer_flags |= URB_ASYNC_UNLINK; usb_fill_int_urb(instance->snd_urb, usb_dev, usb_sndintpipe(usb_dev, CXACRU_EP_CMD), instance->snd_buf, PAGE_SIZE, cxacru_blocking_completion, &instance->snd_done, 4); instance->snd_urb->transfer_flags |= URB_ASYNC_UNLINK; init_MUTEX(&instance->cm_serialize); Loading Loading
Documentation/input/yealink.txt 0 → 100644 +203 −0 Original line number Diff line number Diff line Driver documentation for yealink usb-p1k phones 0. Status ~~~~~~~~~ The p1k is a relatively cheap usb 1.1 phone with: - keyboard full support, yealink.ko / input event API - LCD full support, yealink.ko / sysfs API - LED full support, yealink.ko / sysfs API - dialtone full support, yealink.ko / sysfs API - ringtone full support, yealink.ko / sysfs API - audio playback full support, snd_usb_audio.ko / alsa API - audio record full support, snd_usb_audio.ko / alsa API For vendor documentation see http://www.yealink.com 1. Compilation (stand alone version) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Currently only kernel 2.6.x.y versions are supported. In order to build the yealink.ko module do: make If you encounter problems please check if in the MAKE_OPTS variable in the Makefile is pointing to the location where your kernel sources are located, default /usr/src/linux. 2. keyboard features ~~~~~~~~~~~~~~~~~~~~ The current mapping in the kernel is provided by the map_p1k_to_key function: Physical USB-P1K button layout input events up up IN OUT left, right down down pickup C hangup enter, backspace, escape 1 2 3 1, 2, 3 4 5 6 4, 5, 6, 7 8 9 7, 8, 9, * 0 # *, 0, #, The "up" and "down" keys, are symbolised by arrows on the button. The "pickup" and "hangup" keys are symbolised by a green and red phone on the button. 3. LCD features ~~~~~~~~~~~~~~~ The LCD is divided and organised as a 3 line display: |[] [][] [][] [][] in |[][] |[] M [][] D [][] : [][] out |[][] store NEW REP SU MO TU WE TH FR SA [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] Line 1 Format (see below) : 18.e8.M8.88...188 Icon names : M D : IN OUT STORE Line 2 Format : ......... Icon name : NEW REP SU MO TU WE TH FR SA Line 3 Format : 888888888888 Format description: From a user space perspective the world is seperated in "digits" and "icons". A digit can have a character set, an icon can only be ON or OFF. Format specifier '8' : Generic 7 segment digit with individual addressable segments Reduced capabillity 7 segm digit, when segments are hard wired together. '1' : 2 segments digit only able to produce a 1. 'e' : Most significant day of the month digit, able to produce at least 1 2 3. 'M' : Most significant minute digit, able to produce at least 0 1 2 3 4 5. Icons or pictograms: '.' : For example like AM, PM, SU, a 'dot' .. or other single segment elements. 4. Driver usage ~~~~~~~~~~~~~~~ For userland the following interfaces are available using the sysfs interface: /sys/.../ line1 Read/Write, lcd line1 line2 Read/Write, lcd line2 line3 Read/Write, lcd line3 get_icons Read, returns a set of available icons. hide_icon Write, hide the element by writing the icon name. show_icon Write, display the element by writing the icon name. map_seg7 Read/Write, the 7 segments char set, common for all yealink phones. (see map_to_7segment.h) ringtone Write, upload binary representation of a ringtone, see yealink.c. status EXPERIMENTAL due to potential races between async. and sync usb calls. 4.1 lineX ~~~~~~~~~ Reading /sys/../lineX will return the format string with its current value: Example: cat ./line3 888888888888 Linux Rocks! Writing to /sys/../lineX will set the coresponding LCD line. - Excess characters are ignored. - If less characters are written than allowed, the remaining digits are unchanged. - The tab '\t'and '\n' char does not overwrite the original content. - Writing a space to an icon will always hide its content. Example: date +"%m.%e.%k:%M" | sed 's/^0/ /' > ./line1 Will update the LCD with the current date & time. 4.2 get_icons ~~~~~~~~~~~~~ Reading will return all available icon names and its current settings: cat ./get_icons on M on D on : IN OUT STORE NEW REP SU MO TU WE TH FR SA LED DIALTONE RINGTONE 4.3 show/hide icons ~~~~~~~~~~~~~~~~~~~ Writing to these files will update the state of the icon. Only one icon at a time can be updated. If an icon is also on a ./lineX the corresponding value is updated with the first letter of the icon. Example - light up the store icon: echo -n "STORE" > ./show_icon cat ./line1 18.e8.M8.88...188 S Example - sound the ringtone for 10 seconds: echo -n RINGTONE > /sys/..../show_icon sleep 10 echo -n RINGTONE > /sys/..../hide_icon 5. Sound features ~~~~~~~~~~~~~~~~~ Sound is supported by the ALSA driver: snd_usb_audio One 16-bit channel with sample and playback rates of 8000 Hz is the practical limit of the device. Example - recording test: arecord -v -d 10 -r 8000 -f S16_LE -t wav foobar.wav Example - playback test: aplay foobar.wav 6. Credits & Acknowledgments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Olivier Vandorpe, for starting the usbb2k-api project doing much of the reverse engineering. - Martin Diehl, for pointing out how to handle USB memory allocation. - Dmitry Torokhov, for the numerous code reviews and suggestions.
MAINTAINERS +6 −0 Original line number Diff line number Diff line Loading @@ -116,6 +116,12 @@ M: ajk@iehk.rwth-aachen.de L: linux-hams@vger.kernel.org S: Maintained YEALINK PHONE DRIVER P: Henk Vergonet M: Henk.Vergonet@gmail.com L: usbb2k-api-dev@nongnu.org S: Maintained 8139CP 10/100 FAST ETHERNET DRIVER P: Jeff Garzik M: jgarzik@pobox.com Loading
drivers/block/ub.c +150 −123 Original line number Diff line number Diff line Loading @@ -16,9 +16,10 @@ * -- verify the 13 conditions and do bulk resets * -- kill last_pipe and simply do two-state clearing on both pipes * -- verify protocol (bulk) from USB descriptors (maybe...) * -- highmem and sg * -- highmem * -- move top_sense and work_bcs into separate allocations (if they survive) * for cache purists and esoteric architectures. * -- Allocate structure for LUN 0 before the first ub_sync_tur, avoid NULL. ? * -- prune comments, they are too volumnous * -- Exterminate P3 printks * -- Resove XXX's Loading Loading @@ -171,7 +172,7 @@ struct bulk_cs_wrap { */ struct ub_dev; #define UB_MAX_REQ_SG 1 #define UB_MAX_REQ_SG 4 #define UB_MAX_SECTORS 64 /* Loading Loading @@ -234,13 +235,10 @@ struct ub_scsi_cmd { int stat_count; /* Retries getting status. */ /* * We do not support transfers from highmem pages * because the underlying USB framework does not do what we need. */ char *data; /* Requested buffer */ unsigned int len; /* Requested length */ // struct scatterlist sgv[UB_MAX_REQ_SG]; unsigned int current_sg; unsigned int nsg; /* sgv[nsg] */ struct scatterlist sgv[UB_MAX_REQ_SG]; struct ub_lun *lun; void (*done)(struct ub_dev *, struct ub_scsi_cmd *); Loading Loading @@ -389,17 +387,18 @@ struct ub_dev { struct bulk_cs_wrap work_bcs; struct usb_ctrlrequest work_cr; int sg_stat[UB_MAX_REQ_SG+1]; struct ub_scsi_trace tr; }; /* */ static void ub_cleanup(struct ub_dev *sc); static int ub_bd_rq_fn_1(struct ub_lun *lun, struct request *rq); static int ub_request_fn_1(struct ub_lun *lun, struct request *rq); static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun, struct ub_scsi_cmd *cmd, struct request *rq); static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_scsi_cmd *cmd, struct request *rq); static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun, struct ub_scsi_cmd *cmd, struct request *rq); static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd); static void ub_end_rq(struct request *rq, int uptodate); static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd); Loading @@ -407,6 +406,7 @@ static void ub_urb_complete(struct urb *urb, struct pt_regs *pt); static void ub_scsi_action(unsigned long _dev); static void ub_scsi_dispatch(struct ub_dev *sc); static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd); static void ub_data_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd); static void ub_state_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd, int rc); static int __ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd); static void ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd); Loading Loading @@ -500,7 +500,8 @@ static void ub_cmdtr_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd, } } static ssize_t ub_diag_show(struct device *dev, struct device_attribute *attr, char *page) static ssize_t ub_diag_show(struct device *dev, struct device_attribute *attr, char *page) { struct usb_interface *intf; struct ub_dev *sc; Loading @@ -523,6 +524,13 @@ static ssize_t ub_diag_show(struct device *dev, struct device_attribute *attr, c cnt += sprintf(page + cnt, "qlen %d qmax %d\n", sc->cmd_queue.qlen, sc->cmd_queue.qmax); cnt += sprintf(page + cnt, "sg %d %d %d %d %d\n", sc->sg_stat[0], sc->sg_stat[1], sc->sg_stat[2], sc->sg_stat[3], sc->sg_stat[4]); list_for_each (p, &sc->luns) { lun = list_entry(p, struct ub_lun, link); Loading Loading @@ -744,20 +752,20 @@ static struct ub_scsi_cmd *ub_cmdq_pop(struct ub_dev *sc) * The request function is our main entry point */ static void ub_bd_rq_fn(request_queue_t *q) static void ub_request_fn(request_queue_t *q) { struct ub_lun *lun = q->queuedata; struct request *rq; while ((rq = elv_next_request(q)) != NULL) { if (ub_bd_rq_fn_1(lun, rq) != 0) { if (ub_request_fn_1(lun, rq) != 0) { blk_stop_queue(q); break; } } } static int ub_bd_rq_fn_1(struct ub_lun *lun, struct request *rq) static int ub_request_fn_1(struct ub_lun *lun, struct request *rq) { struct ub_dev *sc = lun->udev; struct ub_scsi_cmd *cmd; Loading @@ -774,9 +782,8 @@ static int ub_bd_rq_fn_1(struct ub_lun *lun, struct request *rq) memset(cmd, 0, sizeof(struct ub_scsi_cmd)); blkdev_dequeue_request(rq); if (blk_pc_request(rq)) { rc = ub_cmd_build_packet(sc, cmd, rq); rc = ub_cmd_build_packet(sc, lun, cmd, rq); } else { rc = ub_cmd_build_block(sc, lun, cmd, rq); } Loading @@ -791,7 +798,7 @@ static int ub_bd_rq_fn_1(struct ub_lun *lun, struct request *rq) cmd->back = rq; cmd->tag = sc->tagcnt++; if ((rc = ub_submit_scsi(sc, cmd)) != 0) { if (ub_submit_scsi(sc, cmd) != 0) { ub_put_cmd(lun, cmd); ub_end_rq(rq, 0); return 0; Loading @@ -804,58 +811,31 @@ static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun, struct ub_scsi_cmd *cmd, struct request *rq) { int ub_dir; #if 0 /* We use rq->buffer for now */ struct scatterlist *sg; int n_elem; #endif unsigned int block, nblks; if (rq_data_dir(rq) == WRITE) ub_dir = UB_DIR_WRITE; else ub_dir = UB_DIR_READ; cmd->dir = ub_dir; /* * get scatterlist from block layer */ #if 0 /* We use rq->buffer for now */ sg = &cmd->sgv[0]; n_elem = blk_rq_map_sg(q, rq, sg); n_elem = blk_rq_map_sg(lun->disk->queue, rq, &cmd->sgv[0]); if (n_elem <= 0) { ub_put_cmd(lun, cmd); ub_end_rq(rq, 0); blk_start_queue(q); return 0; /* request with no s/g entries? */ printk(KERN_INFO "%s: failed request map (%d)\n", sc->name, n_elem); /* P3 */ return -1; /* request with no s/g entries? */ } if (n_elem != 1) { /* Paranoia */ if (n_elem > UB_MAX_REQ_SG) { /* Paranoia */ printk(KERN_WARNING "%s: request with %d segments\n", sc->name, n_elem); ub_put_cmd(lun, cmd); ub_end_rq(rq, 0); blk_start_queue(q); return 0; } #endif /* * XXX Unfortunately, this check does not work. It is quite possible * to get bogus non-null rq->buffer if you allow sg by mistake. */ if (rq->buffer == NULL) { /* * This must not happen if we set the queue right. * The block level must create bounce buffers for us. */ static int do_print = 1; if (do_print) { printk(KERN_WARNING "%s: unmapped block request" " flags 0x%lx sectors %lu\n", sc->name, rq->flags, rq->nr_sectors); do_print = 0; } return -1; } cmd->nsg = n_elem; sc->sg_stat[n_elem]++; /* * build the command Loading @@ -876,30 +856,15 @@ static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun, cmd->cdb[8] = nblks; cmd->cdb_len = 10; cmd->dir = ub_dir; cmd->data = rq->buffer; cmd->len = rq->nr_sectors * 512; return 0; } static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_scsi_cmd *cmd, struct request *rq) static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun, struct ub_scsi_cmd *cmd, struct request *rq) { if (rq->data_len != 0 && rq->data == NULL) { static int do_print = 1; if (do_print) { printk(KERN_WARNING "%s: unmapped packet request" " flags 0x%lx length %d\n", sc->name, rq->flags, rq->data_len); do_print = 0; } return -1; } memcpy(&cmd->cdb, rq->cmd, rq->cmd_len); cmd->cdb_len = rq->cmd_len; int n_elem; if (rq->data_len == 0) { cmd->dir = UB_DIR_NONE; Loading @@ -908,8 +873,29 @@ static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_scsi_cmd *cmd, cmd->dir = UB_DIR_WRITE; else cmd->dir = UB_DIR_READ; } cmd->data = rq->data; /* * get scatterlist from block layer */ n_elem = blk_rq_map_sg(lun->disk->queue, rq, &cmd->sgv[0]); if (n_elem < 0) { printk(KERN_INFO "%s: failed request map (%d)\n", sc->name, n_elem); /* P3 */ return -1; } if (n_elem > UB_MAX_REQ_SG) { /* Paranoia */ printk(KERN_WARNING "%s: request with %d segments\n", sc->name, n_elem); return -1; } cmd->nsg = n_elem; sc->sg_stat[n_elem]++; memcpy(&cmd->cdb, rq->cmd, rq->cmd_len); cmd->cdb_len = rq->cmd_len; cmd->len = rq->data_len; return 0; Loading @@ -919,24 +905,34 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd) { struct request *rq = cmd->back; struct ub_lun *lun = cmd->lun; struct gendisk *disk = lun->disk; request_queue_t *q = disk->queue; int uptodate; if (cmd->error == 0) { uptodate = 1; if (blk_pc_request(rq)) { if (cmd->act_len >= rq->data_len) rq->data_len = 0; else rq->data_len -= cmd->act_len; } } else { uptodate = 0; if (blk_pc_request(rq)) { /* UB_SENSE_SIZE is smaller than SCSI_SENSE_BUFFERSIZE */ memcpy(rq->sense, sc->top_sense, UB_SENSE_SIZE); rq->sense_len = UB_SENSE_SIZE; } if (cmd->error == 0) uptodate = 1; if (sc->top_sense[0] != 0) rq->errors = SAM_STAT_CHECK_CONDITION; else uptodate = 0; rq->errors = DID_ERROR << 16; } } ub_put_cmd(lun, cmd); ub_end_rq(rq, uptodate); blk_start_queue(q); blk_start_queue(lun->disk->queue); } static void ub_end_rq(struct request *rq, int uptodate) Loading Loading @@ -1014,7 +1010,7 @@ static int ub_scsi_cmd_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd) sc->last_pipe = sc->send_bulk_pipe; usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->send_bulk_pipe, bcb, US_BULK_CB_WRAP_LEN, ub_urb_complete, sc); sc->work_urb.transfer_flags = URB_ASYNC_UNLINK; sc->work_urb.transfer_flags = 0; /* Fill what we shouldn't be filling, because usb-storage did so. */ sc->work_urb.actual_length = 0; Loading Loading @@ -1103,7 +1099,6 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) { struct urb *urb = &sc->work_urb; struct bulk_cs_wrap *bcs; int pipe; int rc; if (atomic_read(&sc->poison)) { Loading Loading @@ -1204,38 +1199,13 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) goto Bad_End; } if (cmd->dir == UB_DIR_NONE) { if (cmd->dir == UB_DIR_NONE || cmd->nsg < 1) { ub_state_stat(sc, cmd); return; } UB_INIT_COMPLETION(sc->work_done); if (cmd->dir == UB_DIR_READ) pipe = sc->recv_bulk_pipe; else pipe = sc->send_bulk_pipe; sc->last_pipe = pipe; usb_fill_bulk_urb(&sc->work_urb, sc->dev, pipe, cmd->data, cmd->len, ub_urb_complete, sc); sc->work_urb.transfer_flags = URB_ASYNC_UNLINK; sc->work_urb.actual_length = 0; sc->work_urb.error_count = 0; sc->work_urb.status = 0; if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) { /* XXX Clear stalls */ printk("ub: data #%d submit failed (%d)\n", cmd->tag, rc); /* P3 */ ub_complete(&sc->work_done); ub_state_done(sc, cmd, rc); return; } sc->work_timer.expires = jiffies + UB_DATA_TIMEOUT; add_timer(&sc->work_timer); cmd->state = UB_CMDST_DATA; ub_cmdtr_state(sc, cmd); // udelay(125); // usb-storage has this ub_data_start(sc, cmd); } else if (cmd->state == UB_CMDST_DATA) { if (urb->status == -EPIPE) { Loading @@ -1257,16 +1227,22 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) if (urb->status == -EOVERFLOW) { /* * A babble? Failure, but we must transfer CSW now. * XXX This is going to end in perpetual babble. Reset. */ cmd->error = -EOVERFLOW; /* A cheap trick... */ } else { ub_state_stat(sc, cmd); return; } if (urb->status != 0) goto Bad_End; } cmd->act_len = urb->actual_length; cmd->act_len += urb->actual_length; ub_cmdtr_act_len(sc, cmd); if (++cmd->current_sg < cmd->nsg) { ub_data_start(sc, cmd); return; } ub_state_stat(sc, cmd); } else if (cmd->state == UB_CMDST_STAT) { Loading Loading @@ -1399,6 +1375,46 @@ Bad_End: /* Little Excel is dead */ ub_state_done(sc, cmd, -EIO); } /* * Factorization helper for the command state machine: * Initiate a data segment transfer. */ static void ub_data_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd) { struct scatterlist *sg = &cmd->sgv[cmd->current_sg]; int pipe; int rc; UB_INIT_COMPLETION(sc->work_done); if (cmd->dir == UB_DIR_READ) pipe = sc->recv_bulk_pipe; else pipe = sc->send_bulk_pipe; sc->last_pipe = pipe; usb_fill_bulk_urb(&sc->work_urb, sc->dev, pipe, page_address(sg->page) + sg->offset, sg->length, ub_urb_complete, sc); sc->work_urb.transfer_flags = 0; sc->work_urb.actual_length = 0; sc->work_urb.error_count = 0; sc->work_urb.status = 0; if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) { /* XXX Clear stalls */ printk("ub: data #%d submit failed (%d)\n", cmd->tag, rc); /* P3 */ ub_complete(&sc->work_done); ub_state_done(sc, cmd, rc); return; } sc->work_timer.expires = jiffies + UB_DATA_TIMEOUT; add_timer(&sc->work_timer); cmd->state = UB_CMDST_DATA; ub_cmdtr_state(sc, cmd); } /* * Factorization helper for the command state machine: * Finish the command. Loading Loading @@ -1426,7 +1442,7 @@ static int __ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd) sc->last_pipe = sc->recv_bulk_pipe; usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->recv_bulk_pipe, &sc->work_bcs, US_BULK_CS_WRAP_LEN, ub_urb_complete, sc); sc->work_urb.transfer_flags = URB_ASYNC_UNLINK; sc->work_urb.transfer_flags = 0; sc->work_urb.actual_length = 0; sc->work_urb.error_count = 0; sc->work_urb.status = 0; Loading Loading @@ -1484,6 +1500,7 @@ static void ub_state_stat_counted(struct ub_dev *sc, struct ub_scsi_cmd *cmd) static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd) { struct ub_scsi_cmd *scmd; struct scatterlist *sg; int rc; if (cmd->cdb[0] == REQUEST_SENSE) { Loading @@ -1492,12 +1509,17 @@ static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd) } scmd = &sc->top_rqs_cmd; memset(scmd, 0, sizeof(struct ub_scsi_cmd)); scmd->cdb[0] = REQUEST_SENSE; scmd->cdb[4] = UB_SENSE_SIZE; scmd->cdb_len = 6; scmd->dir = UB_DIR_READ; scmd->state = UB_CMDST_INIT; scmd->data = sc->top_sense; scmd->nsg = 1; sg = &scmd->sgv[0]; sg->page = virt_to_page(sc->top_sense); sg->offset = (unsigned int)sc->top_sense & (PAGE_SIZE-1); sg->length = UB_SENSE_SIZE; scmd->len = UB_SENSE_SIZE; scmd->lun = cmd->lun; scmd->done = ub_top_sense_done; Loading Loading @@ -1541,7 +1563,7 @@ static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd, usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe, (unsigned char*) cr, NULL, 0, ub_urb_complete, sc); sc->work_urb.transfer_flags = URB_ASYNC_UNLINK; sc->work_urb.transfer_flags = 0; sc->work_urb.actual_length = 0; sc->work_urb.error_count = 0; sc->work_urb.status = 0; Loading @@ -1560,7 +1582,7 @@ static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd, */ static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd) { unsigned char *sense = scmd->data; unsigned char *sense = sc->top_sense; struct ub_scsi_cmd *cmd; /* Loading Loading @@ -1852,6 +1874,7 @@ static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun, struct ub_capacity *ret) { struct ub_scsi_cmd *cmd; struct scatterlist *sg; char *p; enum { ALLOC_SIZE = sizeof(struct ub_scsi_cmd) + 8 }; unsigned long flags; Loading @@ -1872,7 +1895,11 @@ static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun, cmd->cdb_len = 10; cmd->dir = UB_DIR_READ; cmd->state = UB_CMDST_INIT; cmd->data = p; cmd->nsg = 1; sg = &cmd->sgv[0]; sg->page = virt_to_page(p); sg->offset = (unsigned int)p & (PAGE_SIZE-1); sg->length = 8; cmd->len = 8; cmd->lun = lun; cmd->done = ub_probe_done; Loading Loading @@ -2289,7 +2316,7 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum) disk->driverfs_dev = &sc->intf->dev; /* XXX Many to one ok? */ rc = -ENOMEM; if ((q = blk_init_queue(ub_bd_rq_fn, &sc->lock)) == NULL) if ((q = blk_init_queue(ub_request_fn, &sc->lock)) == NULL) goto err_blkqinit; disk->queue = q; Loading
drivers/net/irda/irda-usb.c +2 −11 Original line number Diff line number Diff line Loading @@ -267,7 +267,7 @@ static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self) frame, IRDA_USB_SPEED_MTU, speed_bulk_callback, self); urb->transfer_buffer_length = USB_IRDA_HEADER; urb->transfer_flags = URB_ASYNC_UNLINK; urb->transfer_flags = 0; /* Irq disabled -> GFP_ATOMIC */ if ((ret = usb_submit_urb(urb, GFP_ATOMIC))) { Loading Loading @@ -401,15 +401,12 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev) skb->data, IRDA_SKB_MAX_MTU, write_bulk_callback, skb); urb->transfer_buffer_length = skb->len; /* Note : unlink *must* be Asynchronous because of the code in * irda_usb_net_timeout() -> call in irq - Jean II */ urb->transfer_flags = URB_ASYNC_UNLINK; /* This flag (URB_ZERO_PACKET) indicates that what we send is not * a continuous stream of data but separate packets. * In this case, the USB layer will insert an empty USB frame (TD) * after each of our packets that is exact multiple of the frame size. * This is how the dongle will detect the end of packet - Jean II */ urb->transfer_flags |= URB_ZERO_PACKET; urb->transfer_flags = URB_ZERO_PACKET; /* Generate min turn time. FIXME: can we do better than this? */ /* Trying to a turnaround time at this level is trying to measure Loading Loading @@ -630,8 +627,6 @@ static void irda_usb_net_timeout(struct net_device *netdev) * in completion handler, because urb->status will * be -ENOENT. We will fix that at the next watchdog, * leaving more time to USB to recover... * Also, we are in interrupt, so we need to have * URB_ASYNC_UNLINK to work properly... * Jean II */ done = 1; break; Loading Loading @@ -1008,9 +1003,7 @@ static int irda_usb_net_close(struct net_device *netdev) } } /* Cancel Tx and speed URB - need to be synchronous to avoid races */ self->tx_urb->transfer_flags &= ~URB_ASYNC_UNLINK; usb_kill_urb(self->tx_urb); self->speed_urb->transfer_flags &= ~URB_ASYNC_UNLINK; usb_kill_urb(self->speed_urb); /* Stop and remove instance of IrLAP */ Loading Loading @@ -1521,9 +1514,7 @@ static void irda_usb_disconnect(struct usb_interface *intf) usb_kill_urb(self->rx_urb[i]); /* Cancel Tx and speed URB. * Toggle flags to make sure it's synchronous. */ self->tx_urb->transfer_flags &= ~URB_ASYNC_UNLINK; usb_kill_urb(self->tx_urb); self->speed_urb->transfer_flags &= ~URB_ASYNC_UNLINK; usb_kill_urb(self->speed_urb); } Loading
drivers/usb/atm/cxacru.c +0 −2 Original line number Diff line number Diff line Loading @@ -715,13 +715,11 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance, usb_dev, usb_rcvintpipe(usb_dev, CXACRU_EP_CMD), instance->rcv_buf, PAGE_SIZE, cxacru_blocking_completion, &instance->rcv_done, 1); instance->rcv_urb->transfer_flags |= URB_ASYNC_UNLINK; usb_fill_int_urb(instance->snd_urb, usb_dev, usb_sndintpipe(usb_dev, CXACRU_EP_CMD), instance->snd_buf, PAGE_SIZE, cxacru_blocking_completion, &instance->snd_done, 4); instance->snd_urb->transfer_flags |= URB_ASYNC_UNLINK; init_MUTEX(&instance->cm_serialize); Loading