diff options
| author | Linus Torvalds <torvalds@home.transmeta.com> | 2002-09-11 20:42:39 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2002-09-11 20:42:39 -0700 |
| commit | 916da46bf85402b77280ee656b2a684879e6c284 (patch) | |
| tree | 6ecf109b993f8f7c35286d1cac19d61804e53af9 | |
| parent | f2a7c7825d5a31cd6e924945bfdd6b30698e782f (diff) | |
| parent | 6cbd4aa91aee38afd0bd3760bac119fa58bb4128 (diff) | |
Merge bk://linuxusb.bkbits.net/linus-2.5
into home.transmeta.com:/home/torvalds/v2.5/linux
| -rw-r--r-- | drivers/usb/class/usb-midi.c | 10 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-hcd.c | 15 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-q.c | 59 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-sched.c | 113 | ||||
| -rw-r--r-- | drivers/usb/host/ehci.h | 3 | ||||
| -rw-r--r-- | drivers/usb/image/hpusbscsi.c | 8 | ||||
| -rw-r--r-- | drivers/usb/image/microtek.c | 19 | ||||
| -rw-r--r-- | drivers/usb/misc/Config.in | 2 | ||||
| -rw-r--r-- | drivers/usb/net/kaweth.c | 48 | ||||
| -rw-r--r-- | drivers/usb/net/usbnet.c | 75 | ||||
| -rw-r--r-- | drivers/usb/serial/belkin_sa.c | 1 | ||||
| -rw-r--r-- | drivers/usb/serial/belkin_sa.h | 1 |
12 files changed, 168 insertions, 186 deletions
diff --git a/drivers/usb/class/usb-midi.c b/drivers/usb/class/usb-midi.c index cd35694b7d35..1a04189b3a49 100644 --- a/drivers/usb/class/usb-midi.c +++ b/drivers/usb/class/usb-midi.c @@ -368,7 +368,7 @@ static void usb_bulk_read(struct urb *urb) { struct midi_in_endpoint *ep = (struct midi_in_endpoint *)(urb->context); unsigned char *data = urb->transfer_buffer; - int i, l, wake; + int i, j, wake; unsigned long int flags; if ( !ep->urbSubmitted ) { @@ -379,14 +379,14 @@ static void usb_bulk_read(struct urb *urb) wake = 0; spin_lock_irqsave( &ep->lock, flags ); - for(l = 0; l < urb->actual_length; l += 4) { - int cin = (data[l]>>0)&0xf; - int cab = (data[l]>>4)&0xf; + for(j = 0; j < urb->actual_length; j += 4) { + int cin = (data[j]>>0)&0xf; + int cab = (data[j]>>4)&0xf; struct usb_mididev *cable = ep->cables[cab]; if ( cable ) { int len = cin_to_len[cin]; /** length of MIDI data **/ for (i = 0; i < len; i++) { - cable->min.buf[cable->min.bufWrPtr] = data[1+i]; + cable->min.buf[cable->min.bufWrPtr] = data[1+i+j]; cable->min.bufWrPtr = (cable->min.bufWrPtr+1)%MIDI_IN_BUFSIZ; if (cable->min.bufRemains < MIDI_IN_BUFSIZ) cable->min.bufRemains += 1; diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index e81e56ac2c17..a770b258fb25 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -111,6 +111,7 @@ #define EHCI_TUNE_MULT_TT 1 #define EHCI_WATCHDOG_JIFFIES (HZ/100) /* arbitrary; ~10 msec */ +#define EHCI_ASYNC_JIFFIES (HZ/3) /* async idle timeout */ /* Initial IRQ latency: lower than default */ static int log2_irq_thresh = 0; // 0 to 6 @@ -190,7 +191,7 @@ static int ehci_reset (struct ehci_hcd *ehci) dbg_cmd (ehci, "reset", command); writel (command, &ehci->regs->command); ehci->hcd.state = USB_STATE_HALT; - return handshake (&ehci->regs->command, CMD_RESET, 0, 050); + return handshake (&ehci->regs->command, CMD_RESET, 0, 250); } /* idle the controller (from running) */ @@ -247,9 +248,14 @@ static void ehci_watchdog (unsigned long param) struct ehci_hcd *ehci = (struct ehci_hcd *) param; unsigned long flags; - /* guard against lost IAA, which wedges everything */ spin_lock_irqsave (&ehci->lock, flags); + /* guard against lost IAA, which wedges everything */ ehci_irq (&ehci->hcd); + /* unlink the last qh after it's idled a while */ + if (ehci->async_idle) { + start_unlink_async (ehci, ehci->async); + ehci->async_idle = 0; + } spin_unlock_irqrestore (&ehci->lock, flags); } @@ -368,6 +374,7 @@ static int ehci_start (struct usb_hcd *hcd) * * NOTE: layered drivers can't yet tell when we enable that, * so they can't pass this info along (like NETIF_F_HIGHDMA) + * (or like Scsi_Host.highmem_io) ... usb_bus.flags? */ if (HCC_64BIT_ADDR (hcc_params)) { writel (0, &ehci->regs->segment); @@ -586,6 +593,10 @@ static void ehci_tasklet (unsigned long param) struct ehci_hcd *ehci = (struct ehci_hcd *) param; unsigned long flags; + // FIXME don't pass flags; on sparc they aren't really flags. + // qh_completions can just leave irqs blocked, + // then have scan_async() allow IRQs if it's very busy + spin_lock_irqsave (&ehci->lock, flags); if (ehci->reclaim_ready) diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 157e2306e793..3a02e28112b9 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -26,8 +26,7 @@ * Control, bulk, and interrupt traffic all use "qh" lists. They list "qtd" * entries describing USB transactions, max 16-20kB/entry (with 4kB-aligned * buffers needed for the larger number). We use one QH per endpoint, queue - * multiple (bulk or control) urbs per endpoint. URBs may need several qtds. - * A scheduled interrupt qh always (for now) has one qtd, one urb. + * multiple urbs (all three types) per endpoint. URBs may need several qtds. * * ISO traffic uses "ISO TD" (itd, and sitd) records, and (along with * interrupts) needs careful scheduling. Performance improvements can be @@ -281,7 +280,12 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh, unsigned long flags) || (qh->qh_state == QH_STATE_IDLE); // FIXME Remove the automagic unlink mode. - // Drivers can now clean up safely; its' their job. + // Drivers can now clean up safely; it's their job. + // + // FIXME Removing it should fix the short read scenarios + // with "huge" urb data (more than one 16+KByte td) with + // the short read someplace other than the last data TD. + // Except the control case: 'retrigger' status ACKs. /* fault: unlink the rest, since this qtd saw an error? */ if (unlikely ((token & QTD_STS_HALT) != 0)) { @@ -391,7 +395,7 @@ qh_urb_transaction ( struct ehci_qtd *qtd, *qtd_prev; dma_addr_t buf; int len, maxpacket; - int is_input; + int is_input, status_patch = 0; u32 token; /* @@ -422,6 +426,9 @@ qh_urb_transaction ( qtd->urb = urb; qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma); list_add_tail (&qtd->qtd_list, head); + + if (!(urb->transfer_flags & URB_SHORT_NOT_OK)) + status_patch = 1; } /* @@ -499,6 +506,19 @@ qh_urb_transaction ( } } + /* if we're permitting a short control read, we want the hardware to + * just continue after short data and send the status ack. it can do + * that on the last data packet (typically the only one). for other + * packets, software fixup is needed (in qh_completions). + */ + if (status_patch) { + struct ehci_qtd *prev; + + prev = list_entry (qtd->qtd_list.prev, + struct ehci_qtd, qtd_list); + prev->hw_alt_next = QTD_NEXT (qtd->qtd_dma); + } + /* by default, enable interrupt on urb completion */ if (likely (!(urb->transfer_flags & URB_NO_INTERRUPT))) qtd->hw_token |= __constant_cpu_to_le32 (QTD_IOC); @@ -653,9 +673,8 @@ ehci_qh_make ( } break; default: -#ifdef DEBUG - BUG (); -#endif + dbg ("bogus dev %p speed %d", urb->dev, urb->dev->speed); + return 0; } /* NOTE: if (PIPE_INTERRUPT) { scheduler sets s-mask } */ @@ -717,6 +736,8 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) } qh->qh_state = QH_STATE_LINKED; /* qtd completions reported later by interrupt */ + + ehci->async_idle = 0; } /*-------------------------------------------------------------------------*/ @@ -837,7 +858,7 @@ submit_async ( qtd = list_entry (qtd_list->next, struct ehci_qtd, qtd_list); dev = (struct hcd_dev *)urb->dev->hcpriv; epnum = usb_pipeendpoint (urb->pipe); - if (usb_pipein (urb->pipe)) + if (usb_pipein (urb->pipe) && !usb_pipecontrol (urb->pipe)) epnum |= 0x10; vdbg ("%s: submit_async urb %p len %d ep %d-%s qtd %p [qh %p]", @@ -923,9 +944,11 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) if (unlikely (qh == ehci->async && qh->qh_next.qh == qh)) { /* can't get here without STS_ASS set */ if (ehci->hcd.state != USB_STATE_HALT) { - if (cmd & CMD_PSE) + if (cmd & CMD_PSE) { writel (cmd & ~CMD_ASE, &ehci->regs->command); - else + (void) handshake (&ehci->regs->status, + STS_ASS, 0, 150); + } else ehci_ready (ehci); } qh->qh_next.qh = ehci->async = 0; @@ -944,10 +967,6 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) prev = ehci->async; while (prev->qh_next.qh != qh && prev->qh_next.qh != ehci->async) prev = prev->qh_next.qh; -#ifdef DEBUG - if (prev->qh_next.qh != qh) - BUG (); -#endif if (qh->hw_info1 & __constant_cpu_to_le32 (QH_HEAD)) { ehci->async = prev; @@ -987,16 +1006,18 @@ rescan: } /* unlink idle entries, reducing HC PCI usage as - * well as HCD schedule-scanning costs + * well as HCD schedule-scanning costs. removing + * the last qh is deferred, since it's costly. */ if (list_empty (&qh->qtd_list) && !ehci->reclaim) { if (qh->qh_next.qh != qh) { // dbg ("irq/empty"); start_unlink_async (ehci, qh); - } else { - // FIXME: arrange to stop - // after it's been idle a while. - // stop/restart isn't free... + } else if (!timer_pending (&ehci->watchdog)) { + /* can't use IAA for last entry */ + ehci->async_idle = 1; + mod_timer (&ehci->watchdog, + jiffies + EHCI_ASYNC_JIFFIES); } } qh = qh->qh_next.qh; diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 2802fa125663..c926375417c0 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -971,119 +971,10 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, int mem_flags) /* * "Split ISO TDs" ... used for USB 1.1 devices going through * the TTs in USB 2.0 hubs. + * + * FIXME not yet implemented */ -static void -sitd_free (struct ehci_hcd *ehci, struct ehci_sitd *sitd) -{ - pci_pool_free (ehci->sitd_pool, sitd, sitd->sitd_dma); -} - -static struct ehci_sitd * -sitd_make ( - struct ehci_hcd *ehci, - struct urb *urb, - unsigned index, // urb->iso_frame_desc [index] - unsigned uframe, // scheduled start - dma_addr_t dma, // mapped transfer buffer - int mem_flags -) { - struct ehci_sitd *sitd; - unsigned length; - - sitd = pci_pool_alloc (ehci->sitd_pool, mem_flags, &dma); - if (!sitd) - return sitd; - sitd->urb = urb; - length = urb->iso_frame_desc [index].length; - dma += urb->iso_frame_desc [index].offset; - -#if 0 - // FIXME: do the rest! -#else - sitd_free (ehci, sitd); - return 0; -#endif - -} - -static void -sitd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_sitd *sitd) -{ - u32 ptr; - - ptr = cpu_to_le32 (sitd->sitd_dma | 2); // type 2 == sitd - if (ehci->pshadow [frame].ptr) { - if (!sitd->sitd_next.ptr) { - sitd->sitd_next = ehci->pshadow [frame]; - sitd->hw_next = ehci->periodic [frame]; - } else if (sitd->sitd_next.ptr != ehci->pshadow [frame].ptr) { - dbg ("frame %d sitd link goof", frame); - BUG (); - } - } - ehci->pshadow [frame].sitd = sitd; - ehci->periodic [frame] = ptr; -} - -static unsigned long -sitd_complete ( - struct ehci_hcd *ehci, - struct ehci_sitd *sitd, - unsigned long flags -) { - // FIXME -- implement! - - dbg ("NYI -- sitd_complete"); - return flags; -} - -/*-------------------------------------------------------------------------*/ - -static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, int mem_flags) -{ - // struct ehci_sitd *first_sitd = 0; - unsigned frame_index; - dma_addr_t dma; - - dbg ("NYI -- sitd_submit"); - - // FIXME -- implement! - - // FIXME: setup one big dma mapping - dma = 0; - - for (frame_index = 0; - frame_index < urb->number_of_packets; - frame_index++) { - struct ehci_sitd *sitd; - unsigned uframe; - - // FIXME: use real arguments, schedule this! - uframe = -1; - - sitd = sitd_make (ehci, urb, frame_index, - uframe, dma, mem_flags); - - if (sitd) { - /* - if (first_sitd) - list_add_tail (&sitd->sitd_list, - &first_sitd->sitd_list); - else - first_sitd = sitd; - */ - } else { - // FIXME: clean everything up - } - } - - // if we have a first sitd, then - // store them all into the periodic schedule! - // urb->hcpriv = first sitd in sitd_list - - return -ENOSYS; -} #endif /* have_split_iso */ /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 30a2035df996..e7e6f4ba8164 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -39,7 +39,8 @@ struct ehci_hcd { /* one per controller */ /* async schedule support */ struct ehci_qh *async; struct ehci_qh *reclaim; - int reclaim_ready; + int reclaim_ready : 1, + async_idle : 1; /* periodic schedule support */ #define DEFAULT_I_TDPS 1024 /* some HCs can do less */ diff --git a/drivers/usb/image/hpusbscsi.c b/drivers/usb/image/hpusbscsi.c index 5d02c88fcf1b..1782109ebeb0 100644 --- a/drivers/usb/image/hpusbscsi.c +++ b/drivers/usb/image/hpusbscsi.c @@ -154,7 +154,13 @@ hpusbscsi_usb_disconnect (struct usb_device *dev, void *ptr) static struct usb_device_id hpusbscsi_usb_ids[] = { {USB_DEVICE (0x03f0, 0x0701)}, /* HP 53xx */ {USB_DEVICE (0x03f0, 0x0801)}, /* HP 7400 */ - {USB_DEVICE (0x0638, 0x026a)}, /*Scan Dual II */ + {USB_DEVICE (0x0638, 0x0268)}, /*iVina 1200U */ + {USB_DEVICE (0x0638, 0x026a)}, /*Scan Dual II */ + {USB_DEVICE (0x0638, 0x0A13)}, /*Avision AV600U */ + {USB_DEVICE (0x0638, 0x0A16)}, /*Avision DS610CU Scancopier */ + {USB_DEVICE (0x0638, 0x0A18)}, /*Avision AV600U Plus */ + {USB_DEVICE (0x0638, 0x0A23)}, /*Avision AV220 */ + {USB_DEVICE (0x0638, 0x0A24)}, /*Avision AV210 */ {USB_DEVICE (0x0686, 0x4004)}, /*Minolta Elite II */ {} /* Terminating entry */ }; diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c index dd454fd08fab..2a49b94b48d1 100644 --- a/drivers/usb/image/microtek.c +++ b/drivers/usb/image/microtek.c @@ -583,13 +583,22 @@ static void mts_command_done( struct urb *transfer ) return; } - if ( context->data ) { + if (context->srb->cmnd[0] == REQUEST_SENSE) { mts_int_submit_urb(transfer, context->data_pipe, - context->data, + context->srb->sense_buffer, context->data_length, - context->srb->use_sg ? mts_do_sg : mts_data_done); - } else mts_get_status(transfer); + mts_data_done); + } else { if ( context->data ) { + mts_int_submit_urb(transfer, + context->data_pipe, + context->data, + context->data_length, + context->srb->use_sg ? mts_do_sg : mts_data_done); + } else { + mts_get_status(transfer); + } + } return; } @@ -598,7 +607,7 @@ static void mts_do_sg (struct urb* transfer) { struct scatterlist * sg; MTS_INT_INIT(); - + MTS_DEBUG("Processing fragment %d of %d\n", context->fragment,context->srb->use_sg); if (unlikely(transfer->status)) { diff --git a/drivers/usb/misc/Config.in b/drivers/usb/misc/Config.in index 3b21ec8d862d..d5066aa93d4b 100644 --- a/drivers/usb/misc/Config.in +++ b/drivers/usb/misc/Config.in @@ -8,4 +8,4 @@ dep_tristate ' USB Auerswald ISDN support (EXPERIMENTAL)' CONFIG_USB_AUERSWALD dep_tristate ' USB Diamond Rio500 support (EXPERIMENTAL)' CONFIG_USB_RIO500 $CONFIG_USB $CONFIG_EXPERIMENTAL dep_tristate ' Tieman Voyager USB Braille display support (EXPERIMENTAL)' CONFIG_USB_BRLVGER $CONFIG_USB $CONFIG_EXPERIMENTAL dep_tristate ' USB LCD driver support' CONFIG_USB_LCD $CONFIG_USB -dep_tristate ' Alcatel Speedtouch ADSL USB Modem' CONFIG_USB_SPEEDTOUCH $CONFIG_USB +dep_tristate ' Alcatel Speedtouch ADSL USB Modem' CONFIG_USB_SPEEDTOUCH $CONFIG_USB $CONFIG_ATM diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c index 2562a704a438..ee4cbb9f9c6d 100644 --- a/drivers/usb/net/kaweth.c +++ b/drivers/usb/net/kaweth.c @@ -464,7 +464,7 @@ static int kaweth_reset(struct kaweth_device *kaweth) } static void kaweth_usb_receive(struct urb *); -static void kaweth_resubmit_rx_urb(struct kaweth_device *, int); +static int kaweth_resubmit_rx_urb(struct kaweth_device *, int); /**************************************************************** int_callback @@ -493,7 +493,7 @@ static void int_callback(struct urb *u) /**************************************************************** * kaweth_resubmit_rx_urb ****************************************************************/ -static void kaweth_resubmit_rx_urb(struct kaweth_device *kaweth, +static int kaweth_resubmit_rx_urb(struct kaweth_device *kaweth, int mem_flags) { int result; @@ -513,6 +513,8 @@ static void kaweth_resubmit_rx_urb(struct kaweth_device *kaweth, } else { kaweth->suspend_lowmem = 0; } + + return result; } static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth); @@ -592,14 +594,15 @@ static void kaweth_usb_receive(struct urb *urb) static int kaweth_open(struct net_device *net) { struct kaweth_device *kaweth = (struct kaweth_device *)net->priv; + int res; kaweth_dbg("Dev usage: %d", kaweth->dev->refcnt.counter); kaweth_dbg("Opening network device."); - MOD_INC_USE_COUNT; - - kaweth_resubmit_rx_urb(kaweth, GFP_KERNEL); + res = kaweth_resubmit_rx_urb(kaweth, GFP_KERNEL); + if (res) + return -EIO; FILL_INT_URB( kaweth->irq_urb, @@ -611,7 +614,11 @@ static int kaweth_open(struct net_device *net) kaweth, HZ/4); - usb_submit_urb(kaweth->irq_urb, GFP_KERNEL); + res = usb_submit_urb(kaweth->irq_urb, GFP_KERNEL); + if (res) { + usb_unlink_urb(kaweth->rx_urb); + return -EIO; + } netif_start_queue(net); @@ -635,7 +642,6 @@ static int kaweth_close(struct net_device *net) kaweth->status &= ~KAWETH_STATUS_CLOSING; - MOD_DEC_USE_COUNT; printk("Dev usage: %d", kaweth->dev->refcnt.counter); @@ -848,6 +854,7 @@ static void *kaweth_probe( ) { struct kaweth_device *kaweth; + struct net_device *netdev; const eth_addr_t bcast_addr = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; int result = 0; @@ -863,10 +870,8 @@ static void *kaweth_probe( (int)dev->descriptor.bLength, (int)dev->descriptor.bDescriptorType); - if(!(kaweth = kmalloc(sizeof(struct kaweth_device), GFP_KERNEL))) { - kaweth_dbg("out of memory allocating device structure\n"); + if(!(kaweth = kmalloc(sizeof(struct kaweth_device), GFP_KERNEL))) return NULL; - } memset(kaweth, 0, sizeof(struct kaweth_device)); @@ -992,11 +997,17 @@ static void *kaweth_probe( if(result < 0) { kaweth_err("Error setting receive filter"); - return kaweth; + kfree(kaweth); + return NULL; } kaweth_dbg("Initializing net device."); + if(!(netdev = kmalloc(sizeof(struct net_device), GFP_KERNEL))) { + kfree(kaweth); + return NULL; + } + kaweth->tx_urb = usb_alloc_urb(0, GFP_KERNEL); if (!kaweth->tx_urb) goto err_no_urb; @@ -1007,12 +1018,7 @@ static void *kaweth_probe( if (!kaweth->irq_urb) goto err_tx_and_rx; - kaweth->net = init_etherdev(0, 0); - if (!kaweth->net) { - kaweth_err("Error calling init_etherdev."); - return kaweth; - } - + kaweth->net = netdev; memcpy(kaweth->net->broadcast, &bcast_addr, sizeof(bcast_addr)); memcpy(kaweth->net->dev_addr, &kaweth->configuration.hw_addr, @@ -1032,6 +1038,13 @@ static void *kaweth_probe( kaweth->net->mtu = le16_to_cpu(kaweth->configuration.segment_size); memset(&kaweth->stats, 0, sizeof(kaweth->stats)); + + SET_MODULE_OWNER(netdev); + + if (!init_etherdev(netdev, 0)) { + kaweth_err("Error calling init_etherdev."); + goto err_tx_and_rx; + } kaweth_info("kaweth interface created at %s", kaweth->net->name); @@ -1045,6 +1058,7 @@ err_only_tx: usb_free_urb(kaweth->tx_urb); err_no_urb: kfree(kaweth); + kfree(netdev); return NULL; } diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c index 4904c614f40d..b922aef6d8ae 100644 --- a/drivers/usb/net/usbnet.c +++ b/drivers/usb/net/usbnet.c @@ -16,6 +16,7 @@ * * - AnchorChip 2720 * - Belkin, eTEK (interops with Win32 drivers) + * - EPSON USB clients * - GeneSys GL620USB-A * - "Linux Devices" (like iPaq and similar SA-1100 based PDAs) * - NetChip 1080 (interoperates with NetChip Win32 drivers) @@ -23,7 +24,7 @@ * * USB devices can implement their side of this protocol at the cost * of two bulk endpoints; it's not restricted to "cable" applications. - * See the LINUXDEV support. + * See the LINUXDEV or EPSON device/client support. * * * Status: @@ -57,7 +58,7 @@ * * Need smarter hotplug policy scripts ... ones that know how to arrange * bridging with "brctl", and can handle static and dynamic ("pump") setups. - * Use those eventual "peer connected" events. + * Use those eventual "peer connected" events, and zeroconf. * * * CHANGELOG: @@ -128,6 +129,7 @@ /* minidrivers _could_ be individually configured */ #define CONFIG_USB_AN2720 #define CONFIG_USB_BELKIN +#define CONFIG_USB_EPSON2888 #define CONFIG_USB_GENESYS #define CONFIG_USB_LINUXDEV #define CONFIG_USB_NET1080 @@ -329,6 +331,29 @@ static const struct driver_info belkin_info = { +#ifdef CONFIG_USB_EPSON2888 + +/*------------------------------------------------------------------------- + * + * EPSON USB clients + * + * This is the same idea as "linuxdev" (below) except the firmware in the + * device might not be Tux-powered. Epson provides reference firmware that + * implements this interface. Product developers can reuse or modify that + * code, such as by using their own product and vendor codes. + * + *-------------------------------------------------------------------------*/ + +static const struct driver_info epson2888_info = { + .description = "Epson USB Device", + + .in = 4, .out = 3, + .epsize = 64, +}; + +#endif /* CONFIG_USB_EPSON2888 */ + + #ifdef CONFIG_USB_GENESYS /*------------------------------------------------------------------------- @@ -338,6 +363,15 @@ static const struct driver_info belkin_info = { * ... should partially interop with the Win32 driver for this hardware * The GeneSys docs imply there's some NDIS issue motivating this framing. * + * Some info from GeneSys: + * - GL620USB-A is full duplex; GL620USB is only half duplex for bulk. + * (Some cables, like the BAFO-100c, use the half duplex version.) + * - For the full duplex model, the low bit of the version code says + * which side is which ("left/right"). + * - For the half duplex type, a control/interrupt handshake settles + * the transfer direction. (That's disabled here, partially coded.) + * A control URB would block until other side writes an interrupt. + * *-------------------------------------------------------------------------*/ // control msg write command @@ -504,13 +538,6 @@ static int genelink_free (struct usbnet *dev) #endif -// reset the device status -static int genelink_reset (struct usbnet *dev) -{ - // we don't need to reset, just return 0 - return 0; -} - static int genelink_rx_fixup (struct usbnet *dev, struct sk_buff *skb) { struct gl_header *header; @@ -632,7 +659,6 @@ genelink_tx_fixup (struct usbnet *dev, struct sk_buff *skb, int flags) static const struct driver_info genelink_info = { .description = "Genesys GeneLink", .flags = FLAG_FRAMING_GL | FLAG_NO_SETINT, - .reset = genelink_reset, .rx_fixup = genelink_rx_fixup, .tx_fixup = genelink_tx_fixup, @@ -662,25 +688,19 @@ static const struct driver_info genelink_info = { * * One example is Intel's SA-1100 chip, which integrates basic USB * support (arch/arm/sa1100/usb-eth.c); it's used in the iPaq PDA. + * And others too, like the Yopy. * *-------------------------------------------------------------------------*/ -static int linuxdev_check_connect (struct usbnet *dev) -{ - return 0; // by definition, always connected -} - static const struct driver_info linuxdev_info = { .description = "Linux Device", - // no reset defined (yet?) - .check_connect =linuxdev_check_connect, + .in = 2, .out = 1, - .epsize =64, + .epsize = 64, }; #endif /* CONFIG_USB_LINUXDEV */ - #ifdef CONFIG_USB_NET1080 @@ -2049,9 +2069,7 @@ static const struct usb_device_id products [] = { { USB_DEVICE (0x0547, 0x2720), // AnchorChips defaults .driver_info = (unsigned long) &an2720_info, -}, - -{ +}, { USB_DEVICE (0x0547, 0x2727), // Xircom PGUNET .driver_info = (unsigned long) &an2720_info, }, @@ -2070,11 +2088,21 @@ static const struct usb_device_id products [] = { }, #endif +#ifdef CONFIG_USB_EPSON2888 +{ + USB_DEVICE (0x0525, 0x2888), // EPSON USB client + driver_info: (unsigned long) &epson2888_info, +}, +#endif + #ifdef CONFIG_USB_GENESYS { USB_DEVICE (0x05e3, 0x0502), // GL620USB-A .driver_info = (unsigned long) &genelink_info, }, + /* NOT: USB_DEVICE (0x05e3, 0x0501), // GL620USB + * that's half duplex, not currently supported + */ #endif #ifdef CONFIG_USB_LINUXDEV @@ -2098,8 +2126,7 @@ static const struct usb_device_id products [] = { { USB_DEVICE (0x0525, 0x1080), // NetChip ref design .driver_info = (unsigned long) &net1080_info, -}, -{ +}, { USB_DEVICE (0x06D0, 0x0622), // Laplink Gold .driver_info = (unsigned long) &net1080_info, }, diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c index fcda41011b0f..adbbf74bdf4f 100644 --- a/drivers/usb/serial/belkin_sa.c +++ b/drivers/usb/serial/belkin_sa.c @@ -108,6 +108,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(BELKIN_OLD_VID, BELKIN_OLD_PID) }, { USB_DEVICE(PERACOM_VID, PERACOM_PID) }, { USB_DEVICE(GOHUBS_VID, GOHUBS_PID) }, + { USB_DEVICE(GOHUBS_VID, HANDYLINK_PID) }, { USB_DEVICE(BELKIN_DOCKSTATION_VID, BELKIN_DOCKSTATION_PID) }, { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/belkin_sa.h b/drivers/usb/serial/belkin_sa.h index 73f401cc341d..9116b92f4622 100644 --- a/drivers/usb/serial/belkin_sa.h +++ b/drivers/usb/serial/belkin_sa.h @@ -47,6 +47,7 @@ #define GOHUBS_VID 0x0921 /* GoHubs vendor id */ #define GOHUBS_PID 0x1000 /* GoHubs single port serial converter's id (identical to the Peracom device) */ +#define HANDYLINK_PID 0x1200 /* HandyLink USB's id (identical to the Peracom device) */ /* Vendor Request Interface */ #define BELKIN_SA_SET_BAUDRATE_REQUEST 0 /* Set baud rate */ |
