From 907d861754eccbdc89efed65955b7894f52eb382 Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Tue, 6 Jan 2009 17:20:42 -0700 Subject: usblp: continuously poll for status MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The usblp in 2.6.18 polled for status regardless if we actually needed it. At some point I dropped it, to save the batteries if nothing else. As it turned out, printers exist (e.g. Canon BJC-3000) that need prodding this way or else they stop. This patch restores the old behaviour. If you want to save battery, don't leave jobs in the print queue. I tested this on my printers by printing and examining usbmon traces to make sure status is being requested and printers continue to print. Tuomas Jäntti verified the fix on BJC-3000. Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usblp.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index 3f3ee1351930..d2747a49b974 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -880,16 +880,19 @@ static int usblp_wwait(struct usblp *usblp, int nonblock) if (rc <= 0) break; - if (usblp->flags & LP_ABORT) { - if (schedule_timeout(msecs_to_jiffies(5000)) == 0) { + if (schedule_timeout(msecs_to_jiffies(1500)) == 0) { + if (usblp->flags & LP_ABORT) { err = usblp_check_status(usblp, err); if (err == 1) { /* Paper out */ rc = -ENOSPC; break; } + } else { + /* Prod the printer, Gentoo#251237. */ + mutex_lock(&usblp->mut); + usblp_read_status(usblp, usblp->statusbuf); + mutex_unlock(&usblp->mut); } - } else { - schedule(); } } set_current_state(TASK_RUNNING); -- cgit v1.2.3 From 78c5d452a1fd5c2c72a96cf31bdd58eeeddbef03 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sat, 24 Jan 2009 23:54:31 -0800 Subject: USB: gpio_vbus: add delayed vbus_session calls Call usb_gadget_vbus_connect() and ...disconnect() from a workqueue rather than from an irq handler, allowing msleep() calls in vbus_session. Update kerneldoc to match. [ dbrownell@users.sourceforge.net: more kerneldoc updates ] Signed-off-by: Robert Jarzmik Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/otg/gpio_vbus.c | 42 +++++++++++++++++++++++++++++++----------- include/linux/usb/gadget.h | 6 ++++-- include/linux/usb/otg.h | 4 ++++ 3 files changed, 39 insertions(+), 13 deletions(-) diff --git a/drivers/usb/otg/gpio_vbus.c b/drivers/usb/otg/gpio_vbus.c index 63a6036f04be..1c26c94513e9 100644 --- a/drivers/usb/otg/gpio_vbus.c +++ b/drivers/usb/otg/gpio_vbus.c @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -34,6 +35,7 @@ struct gpio_vbus_data { struct regulator *vbus_draw; int vbus_draw_enabled; unsigned mA; + struct work_struct work; }; @@ -76,24 +78,26 @@ static void set_vbus_draw(struct gpio_vbus_data *gpio_vbus, unsigned mA) gpio_vbus->mA = mA; } -/* VBUS change IRQ handler */ -static irqreturn_t gpio_vbus_irq(int irq, void *data) +static int is_vbus_powered(struct gpio_vbus_mach_info *pdata) { - struct platform_device *pdev = data; - struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data; - struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev); - int gpio, vbus; + int vbus; vbus = gpio_get_value(pdata->gpio_vbus); if (pdata->gpio_vbus_inverted) vbus = !vbus; - dev_dbg(&pdev->dev, "VBUS %s (gadget: %s)\n", - vbus ? "supplied" : "inactive", - gpio_vbus->otg.gadget ? gpio_vbus->otg.gadget->name : "none"); + return vbus; +} + +static void gpio_vbus_work(struct work_struct *work) +{ + struct gpio_vbus_data *gpio_vbus = + container_of(work, struct gpio_vbus_data, work); + struct gpio_vbus_mach_info *pdata = gpio_vbus->dev->platform_data; + int gpio; if (!gpio_vbus->otg.gadget) - return IRQ_HANDLED; + return; /* Peripheral controllers which manage the pullup themselves won't have * gpio_pullup configured here. If it's configured here, we'll do what @@ -101,7 +105,7 @@ static irqreturn_t gpio_vbus_irq(int irq, void *data) * that may complicate usb_gadget_{,dis}connect() support. */ gpio = pdata->gpio_pullup; - if (vbus) { + if (is_vbus_powered(pdata)) { gpio_vbus->otg.state = OTG_STATE_B_PERIPHERAL; usb_gadget_vbus_connect(gpio_vbus->otg.gadget); @@ -121,6 +125,21 @@ static irqreturn_t gpio_vbus_irq(int irq, void *data) usb_gadget_vbus_disconnect(gpio_vbus->otg.gadget); gpio_vbus->otg.state = OTG_STATE_B_IDLE; } +} + +/* VBUS change IRQ handler */ +static irqreturn_t gpio_vbus_irq(int irq, void *data) +{ + struct platform_device *pdev = data; + struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data; + struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev); + + dev_dbg(&pdev->dev, "VBUS %s (gadget: %s)\n", + is_vbus_powered(pdata) ? "supplied" : "inactive", + gpio_vbus->otg.gadget ? gpio_vbus->otg.gadget->name : "none"); + + if (gpio_vbus->otg.gadget) + schedule_work(&gpio_vbus->work); return IRQ_HANDLED; } @@ -257,6 +276,7 @@ static int __init gpio_vbus_probe(struct platform_device *pdev) irq, err); goto err_irq; } + INIT_WORK(&gpio_vbus->work, gpio_vbus_work); /* only active when a gadget is registered */ err = otg_set_transceiver(&gpio_vbus->otg); diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 0460a746480c..bbf45d500b6d 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -598,6 +598,7 @@ static inline int usb_gadget_clear_selfpowered(struct usb_gadget *gadget) /** * usb_gadget_vbus_connect - Notify controller that VBUS is powered * @gadget:The device which now has VBUS power. + * Context: can sleep * * This call is used by a driver for an external transceiver (or GPIO) * that detects a VBUS power session starting. Common responses include @@ -636,6 +637,7 @@ static inline int usb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA) /** * usb_gadget_vbus_disconnect - notify controller about VBUS session end * @gadget:the device whose VBUS supply is being described + * Context: can sleep * * This call is used by a driver for an external transceiver (or GPIO) * that detects a VBUS power session ending. Common responses include @@ -792,19 +794,20 @@ struct usb_gadget_driver { /** * usb_gadget_register_driver - register a gadget driver * @driver:the driver being registered + * Context: can sleep * * Call this in your gadget driver's module initialization function, * to tell the underlying usb controller driver about your driver. * The driver's bind() function will be called to bind it to a * gadget before this registration call returns. It's expected that * the bind() functions will be in init sections. - * This function must be called in a context that can sleep. */ int usb_gadget_register_driver(struct usb_gadget_driver *driver); /** * usb_gadget_unregister_driver - unregister a gadget driver * @driver:the driver being unregistered + * Context: can sleep * * Call this in your gadget driver's module cleanup function, * to tell the underlying usb controller that your driver is @@ -813,7 +816,6 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver); * to unbind() and clean up any device state, before this procedure * finally returns. It's expected that the unbind() functions * will in in exit sections, so may not be linked in some kernels. - * This function must be called in a context that can sleep. */ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver); diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h index 94df4fe6c6c0..60a52576fd5c 100644 --- a/include/linux/usb/otg.h +++ b/include/linux/usb/otg.h @@ -86,6 +86,7 @@ extern int otg_set_transceiver(struct otg_transceiver *); extern struct otg_transceiver *otg_get_transceiver(void); extern void otg_put_transceiver(struct otg_transceiver *); +/* Context: can sleep */ static inline int otg_start_hnp(struct otg_transceiver *otg) { @@ -102,6 +103,8 @@ otg_set_host(struct otg_transceiver *otg, struct usb_bus *host) /* for usb peripheral controller drivers */ + +/* Context: can sleep */ static inline int otg_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *periph) { @@ -114,6 +117,7 @@ otg_set_power(struct otg_transceiver *otg, unsigned mA) return otg->set_power(otg, mA); } +/* Context: can sleep */ static inline int otg_set_suspend(struct otg_transceiver *otg, int suspend) { -- cgit v1.2.3 From fa9caf9dafb2ab6354e57c61c2f685b7d08640f4 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sat, 24 Jan 2009 23:55:34 -0800 Subject: USB: pxa27x_udc: factor pullup code to prepare otg transceiver Prepare pxa27x_udc to handle usb D+ pullup properly : it should connect the pullup resistor and disconnect it only if no external transceiver is handling it. [ dbrownell@users.sourceforge.net: kerneldoc and gpio fixes ] Signed-off-by: Robert Jarzmik Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/pxa27x_udc.c | 140 +++++++++++++++++++++++++++++++++++++--- drivers/usb/gadget/pxa27x_udc.h | 6 ++ 2 files changed, 138 insertions(+), 8 deletions(-) diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index 990f40f988d4..f8145590944f 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -1471,6 +1472,32 @@ static struct usb_ep_ops pxa_ep_ops = { .fifo_flush = pxa_ep_fifo_flush, }; +/** + * dplus_pullup - Connect or disconnect pullup resistor to D+ pin + * @udc: udc device + * @on: 0 if disconnect pullup resistor, 1 otherwise + * Context: any + * + * Handle D+ pullup resistor, make the device visible to the usb bus, and + * declare it as a full speed usb device + */ +static void dplus_pullup(struct pxa_udc *udc, int on) +{ + if (on) { + if (gpio_is_valid(udc->mach->gpio_pullup)) + gpio_set_value(udc->mach->gpio_pullup, + !udc->mach->gpio_pullup_inverted); + if (udc->mach->udc_command) + udc->mach->udc_command(PXA2XX_UDC_CMD_CONNECT); + } else { + if (gpio_is_valid(udc->mach->gpio_pullup)) + gpio_set_value(udc->mach->gpio_pullup, + udc->mach->gpio_pullup_inverted); + if (udc->mach->udc_command) + udc->mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT); + } + udc->pullup_on = on; +} /** * pxa_udc_get_frame - Returns usb frame number @@ -1500,21 +1527,91 @@ static int pxa_udc_wakeup(struct usb_gadget *_gadget) return 0; } +static void udc_enable(struct pxa_udc *udc); +static void udc_disable(struct pxa_udc *udc); + +/** + * should_enable_udc - Tells if UDC should be enabled + * @udc: udc device + * Context: any + * + * The UDC should be enabled if : + * - the pullup resistor is connected + * - and a gadget driver is bound + * + * Returns 1 if UDC should be enabled, 0 otherwise + */ +static int should_enable_udc(struct pxa_udc *udc) +{ + int put_on; + + put_on = ((udc->pullup_on) && (udc->driver)); + return put_on; +} + +/** + * should_disable_udc - Tells if UDC should be disabled + * @udc: udc device + * Context: any + * + * The UDC should be disabled if : + * - the pullup resistor is not connected + * - or no gadget driver is bound + * + * Returns 1 if UDC should be disabled + */ +static int should_disable_udc(struct pxa_udc *udc) +{ + int put_off; + + put_off = ((!udc->pullup_on) || (!udc->driver)); + return put_off; +} + +/** + * pxa_udc_pullup - Offer manual D+ pullup control + * @_gadget: usb gadget using the control + * @is_active: 0 if disconnect, else connect D+ pullup resistor + * Context: !in_interrupt() + * + * Returns 0 if OK, -EOPNOTSUPP if udc driver doesn't handle D+ pullup + */ +static int pxa_udc_pullup(struct usb_gadget *_gadget, int is_active) +{ + struct pxa_udc *udc = to_gadget_udc(_gadget); + + if (!gpio_is_valid(udc->mach->gpio_pullup) && !udc->mach->udc_command) + return -EOPNOTSUPP; + + dplus_pullup(udc, is_active); + + if (should_enable_udc(udc)) + udc_enable(udc); + if (should_disable_udc(udc)) + udc_disable(udc); + return 0; +} + static const struct usb_gadget_ops pxa_udc_ops = { .get_frame = pxa_udc_get_frame, .wakeup = pxa_udc_wakeup, + .pullup = pxa_udc_pullup, /* current versions must always be self-powered */ }; /** * udc_disable - disable udc device controller * @udc: udc device + * Context: any * * Disables the udc device : disables clocks, udc interrupts, control endpoint * interrupts. */ static void udc_disable(struct pxa_udc *udc) { + if (!udc->enabled) + return; + udc_writel(udc, UDCICR0, 0); udc_writel(udc, UDCICR1, 0); @@ -1523,8 +1620,8 @@ static void udc_disable(struct pxa_udc *udc) ep0_idle(udc); udc->gadget.speed = USB_SPEED_UNKNOWN; - if (udc->mach->udc_command) - udc->mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT); + + udc->enabled = 0; } /** @@ -1570,6 +1667,9 @@ static __init void udc_init_data(struct pxa_udc *dev) */ static void udc_enable(struct pxa_udc *udc) { + if (udc->enabled) + return; + udc_writel(udc, UDCICR0, 0); udc_writel(udc, UDCICR1, 0); udc_clear_mask_UDCCR(udc, UDCCR_UDE); @@ -1598,9 +1698,7 @@ static void udc_enable(struct pxa_udc *udc) /* enable ep0 irqs */ pio_irq_enable(&udc->pxa_ep[0]); - dev_info(udc->dev, "UDC connecting\n"); - if (udc->mach->udc_command) - udc->mach->udc_command(PXA2XX_UDC_CMD_CONNECT); + udc->enabled = 1; } /** @@ -1612,6 +1710,9 @@ static void udc_enable(struct pxa_udc *udc) * usb traffic follows until a disconnect is reported. Then a host may connect * again, or the driver might get unbound. * + * Note that the udc is not automatically enabled. Check function + * should_enable_udc(). + * * Returns 0 if no error, -EINVAL, -ENODEV, -EBUSY otherwise */ int usb_gadget_register_driver(struct usb_gadget_driver *driver) @@ -1630,6 +1731,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) /* first hook up the driver ... */ udc->driver = driver; udc->gadget.dev.driver = &driver->driver; + dplus_pullup(udc, 1); retval = device_add(&udc->gadget.dev); if (retval) { @@ -1645,7 +1747,8 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) dev_dbg(udc->dev, "registered gadget driver '%s'\n", driver->driver.name); - udc_enable(udc); + if (should_enable_udc(udc)) + udc_enable(udc); return 0; bind_fail: @@ -1699,6 +1802,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) stop_activity(udc, driver); udc_disable(udc); + dplus_pullup(udc, 0); driver->unbind(&udc->gadget); udc->driver = NULL; @@ -2212,7 +2316,7 @@ static int __init pxa_udc_probe(struct platform_device *pdev) { struct resource *regs; struct pxa_udc *udc = &memory; - int retval; + int retval = 0, gpio; regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!regs) @@ -2224,6 +2328,19 @@ static int __init pxa_udc_probe(struct platform_device *pdev) udc->dev = &pdev->dev; udc->mach = pdev->dev.platform_data; + gpio = udc->mach->gpio_pullup; + if (gpio_is_valid(gpio)) { + retval = gpio_request(gpio, "USB D+ pullup"); + if (retval == 0) + gpio_direction_output(gpio, + udc->mach->gpio_pullup_inverted); + } + if (retval) { + dev_err(&pdev->dev, "Couldn't request gpio %d : %d\n", + gpio, retval); + return retval; + } + udc->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(udc->clk)) { retval = PTR_ERR(udc->clk); @@ -2273,10 +2390,13 @@ err_clk: static int __exit pxa_udc_remove(struct platform_device *_dev) { struct pxa_udc *udc = platform_get_drvdata(_dev); + int gpio = udc->mach->gpio_pullup; usb_gadget_unregister_driver(udc->driver); free_irq(udc->irq, udc); pxa_cleanup_debugfs(udc); + if (gpio_is_valid(gpio)) + gpio_free(gpio); platform_set_drvdata(_dev, NULL); the_controller = NULL; @@ -2319,6 +2439,8 @@ static int pxa_udc_suspend(struct platform_device *_dev, pm_message_t state) } udc_disable(udc); + udc->pullup_resume = udc->pullup_on; + dplus_pullup(udc, 0); return 0; } @@ -2346,7 +2468,9 @@ static int pxa_udc_resume(struct platform_device *_dev) ep->udccsr_value, ep->udccr_value); } - udc_enable(udc); + dplus_pullup(udc, udc->pullup_resume); + if (should_enable_udc(udc)) + udc_enable(udc); /* * We do not handle OTG yet. * diff --git a/drivers/usb/gadget/pxa27x_udc.h b/drivers/usb/gadget/pxa27x_udc.h index 1d1b7936ee11..6f5234dff8a5 100644 --- a/drivers/usb/gadget/pxa27x_udc.h +++ b/drivers/usb/gadget/pxa27x_udc.h @@ -425,6 +425,9 @@ struct udc_stats { * @stats: statistics on udc usage * @udc_usb_ep: array of usb endpoints offered by the gadget * @pxa_ep: array of pxa available endpoints + * @enabled: UDC was enabled by a previous udc_enable() + * @pullup_on: if pullup resistor connected to D+ pin + * @pullup_resume: if pullup resistor should be connected to D+ pin on resume * @config: UDC active configuration * @last_interface: UDC interface of the last SET_INTERFACE host request * @last_alternate: UDC altsetting of the last SET_INTERFACE host request @@ -450,6 +453,9 @@ struct pxa_udc { struct udc_usb_ep udc_usb_ep[NR_USB_ENDPOINTS]; struct pxa_ep pxa_ep[NR_PXA_ENDPOINTS]; + unsigned enabled:1; + unsigned pullup_on:1; + unsigned pullup_resume:1; unsigned config:2; unsigned last_interface:3; unsigned last_alternate:3; -- cgit v1.2.3 From 708e7adf8d07aaaa2eb6526e7251dc3d7a7e13ec Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sat, 24 Jan 2009 23:56:42 -0800 Subject: USB: pxa27x_udc: add vbus session handling On vbus_session() call, optionally activate D+ pullup resistor and enable the udc, or deactivate D+ pullup resistor and disable the udc. It is intentional to not handle any VBus sense related irq. An external transceiver driver (like gpio_vbus) should catch VBus sense signal, and call usb_gadget_vbus_connect() or usb_gadget_vbus_disconnect(). Signed-off-by: Robert Jarzmik Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/pxa27x_udc.c | 33 +++++++++++++++++++++++++++++++++ drivers/usb/gadget/pxa27x_udc.h | 1 + 2 files changed, 34 insertions(+) diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index f8145590944f..0c9307118b54 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -1536,8 +1536,10 @@ static void udc_disable(struct pxa_udc *udc); * Context: any * * The UDC should be enabled if : + * - the pullup resistor is connected * - and a gadget driver is bound + * - and vbus is sensed (or no vbus sense is available) * * Returns 1 if UDC should be enabled, 0 otherwise */ @@ -1546,6 +1548,7 @@ static int should_enable_udc(struct pxa_udc *udc) int put_on; put_on = ((udc->pullup_on) && (udc->driver)); + put_on &= ((udc->vbus_sensed) || (!udc->transceiver)); return put_on; } @@ -1557,6 +1560,7 @@ static int should_enable_udc(struct pxa_udc *udc) * The UDC should be disabled if : * - the pullup resistor is not connected * - or no gadget driver is bound + * - or no vbus is sensed (when vbus sesing is available) * * Returns 1 if UDC should be disabled */ @@ -1565,6 +1569,7 @@ static int should_disable_udc(struct pxa_udc *udc) int put_off; put_off = ((!udc->pullup_on) || (!udc->driver)); + put_off |= ((!udc->vbus_sensed) && (udc->transceiver)); return put_off; } @@ -1592,10 +1597,37 @@ static int pxa_udc_pullup(struct usb_gadget *_gadget, int is_active) return 0; } +static void udc_enable(struct pxa_udc *udc); +static void udc_disable(struct pxa_udc *udc); + +/** + * pxa_udc_vbus_session - Called by external transceiver to enable/disable udc + * @_gadget: usb gadget + * @is_active: 0 if should disable the udc, 1 if should enable + * + * Enables the udc, and optionnaly activates D+ pullup resistor. Or disables the + * udc, and deactivates D+ pullup resistor. + * + * Returns 0 + */ +static int pxa_udc_vbus_session(struct usb_gadget *_gadget, int is_active) +{ + struct pxa_udc *udc = to_gadget_udc(_gadget); + + udc->vbus_sensed = is_active; + if (should_enable_udc(udc)) + udc_enable(udc); + if (should_disable_udc(udc)) + udc_disable(udc); + + return 0; +} + static const struct usb_gadget_ops pxa_udc_ops = { .get_frame = pxa_udc_get_frame, .wakeup = pxa_udc_wakeup, .pullup = pxa_udc_pullup, + .vbus_session = pxa_udc_vbus_session, /* current versions must always be self-powered */ }; @@ -2357,6 +2389,7 @@ static int __init pxa_udc_probe(struct platform_device *pdev) device_initialize(&udc->gadget.dev); udc->gadget.dev.parent = &pdev->dev; udc->gadget.dev.dma_mask = NULL; + udc->vbus_sensed = 0; the_controller = udc; platform_set_drvdata(pdev, udc); diff --git a/drivers/usb/gadget/pxa27x_udc.h b/drivers/usb/gadget/pxa27x_udc.h index 6f5234dff8a5..64741e199204 100644 --- a/drivers/usb/gadget/pxa27x_udc.h +++ b/drivers/usb/gadget/pxa27x_udc.h @@ -456,6 +456,7 @@ struct pxa_udc { unsigned enabled:1; unsigned pullup_on:1; unsigned pullup_resume:1; + unsigned vbus_sensed:1; unsigned config:2; unsigned last_interface:3; unsigned last_alternate:3; -- cgit v1.2.3 From 87d13dda99d226653cc0b6003f3ab0c6ff8066c0 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sat, 24 Jan 2009 23:57:30 -0800 Subject: USB: pxa27x_udc: add otg transceiver support When a transceiver driver is used, no automatic udc enable is done. The transceiver (OTG or not) should : - take care of VBus sensing - call usb_gadget_vbus_connect() - call usb_gadget_vbus_disconnect() The pullup should remain within this driver's management, either by gpio_pullup of udc_command() fields. Signed-off-by: Robert Jarzmik Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/Kconfig | 1 + drivers/usb/gadget/pxa27x_udc.c | 19 ++++++++++++++++++- drivers/usb/gadget/pxa27x_udc.h | 3 +++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index e55fef52a5dc..770b3eaa9184 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -254,6 +254,7 @@ config USB_PXA25X_SMALL config USB_GADGET_PXA27X boolean "PXA 27x" depends on ARCH_PXA && PXA27x + select USB_OTG_UTILS help Intel's PXA 27x series XScale ARM v5TE processors include an integrated full speed USB 1.1 device controller. diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index 0c9307118b54..11510472ee00 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -1779,10 +1779,21 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) dev_dbg(udc->dev, "registered gadget driver '%s'\n", driver->driver.name); + if (udc->transceiver) { + retval = otg_set_peripheral(udc->transceiver, &udc->gadget); + if (retval) { + dev_err(udc->dev, "can't bind to transceiver\n"); + goto transceiver_fail; + } + } + if (should_enable_udc(udc)) udc_enable(udc); return 0; +transceiver_fail: + if (driver->unbind) + driver->unbind(&udc->gadget); bind_fail: device_del(&udc->gadget.dev); add_fail: @@ -1840,9 +1851,11 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) udc->driver = NULL; device_del(&udc->gadget.dev); - dev_info(udc->dev, "unregistered gadget driver '%s'\n", driver->driver.name); + + if (udc->transceiver) + return otg_set_peripheral(udc->transceiver, NULL); return 0; } EXPORT_SYMBOL(usb_gadget_unregister_driver); @@ -2359,6 +2372,7 @@ static int __init pxa_udc_probe(struct platform_device *pdev) udc->dev = &pdev->dev; udc->mach = pdev->dev.platform_data; + udc->transceiver = otg_get_transceiver(); gpio = udc->mach->gpio_pullup; if (gpio_is_valid(gpio)) { @@ -2431,6 +2445,9 @@ static int __exit pxa_udc_remove(struct platform_device *_dev) if (gpio_is_valid(gpio)) gpio_free(gpio); + otg_put_transceiver(udc->transceiver); + + udc->transceiver = NULL; platform_set_drvdata(_dev, NULL); the_controller = NULL; clk_put(udc->clk); diff --git a/drivers/usb/gadget/pxa27x_udc.h b/drivers/usb/gadget/pxa27x_udc.h index 64741e199204..db58125331da 100644 --- a/drivers/usb/gadget/pxa27x_udc.h +++ b/drivers/usb/gadget/pxa27x_udc.h @@ -26,6 +26,7 @@ #include #include #include +#include /* * Register definitions @@ -421,6 +422,7 @@ struct udc_stats { * @driver: bound gadget (zero, g_ether, g_file_storage, ...) * @dev: device * @mach: machine info, used to activate specific GPIO + * @transceiver: external transceiver to handle vbus sense and D+ pullup * @ep0state: control endpoint state machine state * @stats: statistics on udc usage * @udc_usb_ep: array of usb endpoints offered by the gadget @@ -446,6 +448,7 @@ struct pxa_udc { struct usb_gadget_driver *driver; struct device *dev; struct pxa2xx_udc_mach_info *mach; + struct otg_transceiver *transceiver; enum ep0_state ep0state; struct udc_stats stats; -- cgit v1.2.3 From 0d4dc0e3d86618e54332e9eef1f2fbd93155bd30 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sat, 24 Jan 2009 23:59:38 -0800 Subject: USB: pxa27x_udc: add vbus_draw callback Add the vbus_draw() callback to inform the transceiver, if it exists, how much current may be drawn. The decision is taken on gadget driver side using the configuration chosen by the host and its bMaxPower field. Some systems can use the host's VBUS supply to augment or recharge a battery. (There's also a default of 100 mA for unconfigured devices, or 8 mA if they're OTG devices.) Signed-off-by: Robert Jarzmik Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/pxa27x_udc.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index 11510472ee00..e50419d08996 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -1623,12 +1623,34 @@ static int pxa_udc_vbus_session(struct usb_gadget *_gadget, int is_active) return 0; } +/** + * pxa_udc_vbus_draw - Called by gadget driver after SET_CONFIGURATION completed + * @_gadget: usb gadget + * @mA: current drawn + * + * Context: !in_interrupt() + * + * Called after a configuration was chosen by a USB host, to inform how much + * current can be drawn by the device from VBus line. + * + * Returns 0 or -EOPNOTSUPP if no transceiver is handling the udc + */ +static int pxa_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA) +{ + struct pxa_udc *udc; + + udc = to_gadget_udc(_gadget); + if (udc->transceiver) + return otg_set_power(udc->transceiver, mA); + return -EOPNOTSUPP; +} + static const struct usb_gadget_ops pxa_udc_ops = { .get_frame = pxa_udc_get_frame, .wakeup = pxa_udc_wakeup, .pullup = pxa_udc_pullup, .vbus_session = pxa_udc_vbus_session, - /* current versions must always be self-powered */ + .vbus_draw = pxa_udc_vbus_draw, }; /** -- cgit v1.2.3 From e5323b6a8901df0c16015443e93fad26232e1754 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 29 Dec 2008 22:48:19 +0100 Subject: USB: Move definitions from usb.h to usb/ch9.h The functions: usb_endpoint_dir_in(epd) usb_endpoint_dir_out(epd) usb_endpoint_is_bulk_in(epd) usb_endpoint_is_bulk_out(epd) usb_endpoint_is_int_in(epd) usb_endpoint_is_int_out(epd) usb_endpoint_is_isoc_in(epd) usb_endpoint_is_isoc_out(epd) usb_endpoint_num(epd) usb_endpoint_type(epd) usb_endpoint_xfer_bulk(epd) usb_endpoint_xfer_control(epd) usb_endpoint_xfer_int(epd) usb_endpoint_xfer_isoc(epd) are moved from include/linux/usb.h to include/linux/usb/ch9.h. include/linux/usb/ch9.h makes more sense for these functions because they only depend on constants that are defined in this file. Signed-off-by: Julia Lawall Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- include/linux/usb.h | 180 ------------------------------------------------ include/linux/usb/ch9.h | 179 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 179 insertions(+), 180 deletions(-) diff --git a/include/linux/usb.h b/include/linux/usb.h index 88079fd60235..0c05ff621192 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -643,186 +643,6 @@ static inline int usb_make_path(struct usb_device *dev, char *buf, size_t size) /*-------------------------------------------------------------------------*/ -/** - * usb_endpoint_num - get the endpoint's number - * @epd: endpoint to be checked - * - * Returns @epd's number: 0 to 15. - */ -static inline int usb_endpoint_num(const struct usb_endpoint_descriptor *epd) -{ - return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; -} - -/** - * usb_endpoint_type - get the endpoint's transfer type - * @epd: endpoint to be checked - * - * Returns one of USB_ENDPOINT_XFER_{CONTROL, ISOC, BULK, INT} according - * to @epd's transfer type. - */ -static inline int usb_endpoint_type(const struct usb_endpoint_descriptor *epd) -{ - return epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; -} - -/** - * usb_endpoint_dir_in - check if the endpoint has IN direction - * @epd: endpoint to be checked - * - * Returns true if the endpoint is of type IN, otherwise it returns false. - */ -static inline int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd) -{ - return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN); -} - -/** - * usb_endpoint_dir_out - check if the endpoint has OUT direction - * @epd: endpoint to be checked - * - * Returns true if the endpoint is of type OUT, otherwise it returns false. - */ -static inline int usb_endpoint_dir_out( - const struct usb_endpoint_descriptor *epd) -{ - return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT); -} - -/** - * usb_endpoint_xfer_bulk - check if the endpoint has bulk transfer type - * @epd: endpoint to be checked - * - * Returns true if the endpoint is of type bulk, otherwise it returns false. - */ -static inline int usb_endpoint_xfer_bulk( - const struct usb_endpoint_descriptor *epd) -{ - return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_BULK); -} - -/** - * usb_endpoint_xfer_control - check if the endpoint has control transfer type - * @epd: endpoint to be checked - * - * Returns true if the endpoint is of type control, otherwise it returns false. - */ -static inline int usb_endpoint_xfer_control( - const struct usb_endpoint_descriptor *epd) -{ - return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_CONTROL); -} - -/** - * usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type - * @epd: endpoint to be checked - * - * Returns true if the endpoint is of type interrupt, otherwise it returns - * false. - */ -static inline int usb_endpoint_xfer_int( - const struct usb_endpoint_descriptor *epd) -{ - return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_INT); -} - -/** - * usb_endpoint_xfer_isoc - check if the endpoint has isochronous transfer type - * @epd: endpoint to be checked - * - * Returns true if the endpoint is of type isochronous, otherwise it returns - * false. - */ -static inline int usb_endpoint_xfer_isoc( - const struct usb_endpoint_descriptor *epd) -{ - return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_ISOC); -} - -/** - * usb_endpoint_is_bulk_in - check if the endpoint is bulk IN - * @epd: endpoint to be checked - * - * Returns true if the endpoint has bulk transfer type and IN direction, - * otherwise it returns false. - */ -static inline int usb_endpoint_is_bulk_in( - const struct usb_endpoint_descriptor *epd) -{ - return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_in(epd)); -} - -/** - * usb_endpoint_is_bulk_out - check if the endpoint is bulk OUT - * @epd: endpoint to be checked - * - * Returns true if the endpoint has bulk transfer type and OUT direction, - * otherwise it returns false. - */ -static inline int usb_endpoint_is_bulk_out( - const struct usb_endpoint_descriptor *epd) -{ - return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_out(epd)); -} - -/** - * usb_endpoint_is_int_in - check if the endpoint is interrupt IN - * @epd: endpoint to be checked - * - * Returns true if the endpoint has interrupt transfer type and IN direction, - * otherwise it returns false. - */ -static inline int usb_endpoint_is_int_in( - const struct usb_endpoint_descriptor *epd) -{ - return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd)); -} - -/** - * usb_endpoint_is_int_out - check if the endpoint is interrupt OUT - * @epd: endpoint to be checked - * - * Returns true if the endpoint has interrupt transfer type and OUT direction, - * otherwise it returns false. - */ -static inline int usb_endpoint_is_int_out( - const struct usb_endpoint_descriptor *epd) -{ - return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd)); -} - -/** - * usb_endpoint_is_isoc_in - check if the endpoint is isochronous IN - * @epd: endpoint to be checked - * - * Returns true if the endpoint has isochronous transfer type and IN direction, - * otherwise it returns false. - */ -static inline int usb_endpoint_is_isoc_in( - const struct usb_endpoint_descriptor *epd) -{ - return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_in(epd)); -} - -/** - * usb_endpoint_is_isoc_out - check if the endpoint is isochronous OUT - * @epd: endpoint to be checked - * - * Returns true if the endpoint has isochronous transfer type and OUT direction, - * otherwise it returns false. - */ -static inline int usb_endpoint_is_isoc_out( - const struct usb_endpoint_descriptor *epd) -{ - return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_out(epd)); -} - -/*-------------------------------------------------------------------------*/ - #define USB_DEVICE_ID_MATCH_DEVICE \ (USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT) #define USB_DEVICE_ID_MATCH_DEV_RANGE \ diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h index 9b42baed3900..fa777db7f7eb 100644 --- a/include/linux/usb/ch9.h +++ b/include/linux/usb/ch9.h @@ -353,6 +353,185 @@ struct usb_endpoint_descriptor { #define USB_ENDPOINT_XFER_INT 3 #define USB_ENDPOINT_MAX_ADJUSTABLE 0x80 +/*-------------------------------------------------------------------------*/ + +/** + * usb_endpoint_num - get the endpoint's number + * @epd: endpoint to be checked + * + * Returns @epd's number: 0 to 15. + */ +static inline int usb_endpoint_num(const struct usb_endpoint_descriptor *epd) +{ + return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; +} + +/** + * usb_endpoint_type - get the endpoint's transfer type + * @epd: endpoint to be checked + * + * Returns one of USB_ENDPOINT_XFER_{CONTROL, ISOC, BULK, INT} according + * to @epd's transfer type. + */ +static inline int usb_endpoint_type(const struct usb_endpoint_descriptor *epd) +{ + return epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; +} + +/** + * usb_endpoint_dir_in - check if the endpoint has IN direction + * @epd: endpoint to be checked + * + * Returns true if the endpoint is of type IN, otherwise it returns false. + */ +static inline int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN); +} + +/** + * usb_endpoint_dir_out - check if the endpoint has OUT direction + * @epd: endpoint to be checked + * + * Returns true if the endpoint is of type OUT, otherwise it returns false. + */ +static inline int usb_endpoint_dir_out( + const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT); +} + +/** + * usb_endpoint_xfer_bulk - check if the endpoint has bulk transfer type + * @epd: endpoint to be checked + * + * Returns true if the endpoint is of type bulk, otherwise it returns false. + */ +static inline int usb_endpoint_xfer_bulk( + const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_BULK); +} + +/** + * usb_endpoint_xfer_control - check if the endpoint has control transfer type + * @epd: endpoint to be checked + * + * Returns true if the endpoint is of type control, otherwise it returns false. + */ +static inline int usb_endpoint_xfer_control( + const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_CONTROL); +} + +/** + * usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type + * @epd: endpoint to be checked + * + * Returns true if the endpoint is of type interrupt, otherwise it returns + * false. + */ +static inline int usb_endpoint_xfer_int( + const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_INT); +} + +/** + * usb_endpoint_xfer_isoc - check if the endpoint has isochronous transfer type + * @epd: endpoint to be checked + * + * Returns true if the endpoint is of type isochronous, otherwise it returns + * false. + */ +static inline int usb_endpoint_xfer_isoc( + const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_ISOC); +} + +/** + * usb_endpoint_is_bulk_in - check if the endpoint is bulk IN + * @epd: endpoint to be checked + * + * Returns true if the endpoint has bulk transfer type and IN direction, + * otherwise it returns false. + */ +static inline int usb_endpoint_is_bulk_in( + const struct usb_endpoint_descriptor *epd) +{ + return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_in(epd)); +} + +/** + * usb_endpoint_is_bulk_out - check if the endpoint is bulk OUT + * @epd: endpoint to be checked + * + * Returns true if the endpoint has bulk transfer type and OUT direction, + * otherwise it returns false. + */ +static inline int usb_endpoint_is_bulk_out( + const struct usb_endpoint_descriptor *epd) +{ + return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_out(epd)); +} + +/** + * usb_endpoint_is_int_in - check if the endpoint is interrupt IN + * @epd: endpoint to be checked + * + * Returns true if the endpoint has interrupt transfer type and IN direction, + * otherwise it returns false. + */ +static inline int usb_endpoint_is_int_in( + const struct usb_endpoint_descriptor *epd) +{ + return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd)); +} + +/** + * usb_endpoint_is_int_out - check if the endpoint is interrupt OUT + * @epd: endpoint to be checked + * + * Returns true if the endpoint has interrupt transfer type and OUT direction, + * otherwise it returns false. + */ +static inline int usb_endpoint_is_int_out( + const struct usb_endpoint_descriptor *epd) +{ + return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd)); +} + +/** + * usb_endpoint_is_isoc_in - check if the endpoint is isochronous IN + * @epd: endpoint to be checked + * + * Returns true if the endpoint has isochronous transfer type and IN direction, + * otherwise it returns false. + */ +static inline int usb_endpoint_is_isoc_in( + const struct usb_endpoint_descriptor *epd) +{ + return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_in(epd)); +} + +/** + * usb_endpoint_is_isoc_out - check if the endpoint is isochronous OUT + * @epd: endpoint to be checked + * + * Returns true if the endpoint has isochronous transfer type and OUT direction, + * otherwise it returns false. + */ +static inline int usb_endpoint_is_isoc_out( + const struct usb_endpoint_descriptor *epd) +{ + return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_out(epd)); +} /*-------------------------------------------------------------------------*/ -- cgit v1.2.3 From b146897a3a5e358051dea54c4e5abe9f27c4289f Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 29 Dec 2008 11:19:10 +0100 Subject: USB: ub: use USB API functions rather than constants This set of patches introduces calls to the following set of functions: usb_endpoint_dir_in(epd) usb_endpoint_dir_out(epd) usb_endpoint_is_bulk_in(epd) usb_endpoint_is_bulk_out(epd) usb_endpoint_is_int_in(epd) usb_endpoint_is_int_out(epd) usb_endpoint_num(epd) usb_endpoint_type(epd) usb_endpoint_xfer_bulk(epd) usb_endpoint_xfer_control(epd) usb_endpoint_xfer_int(epd) usb_endpoint_xfer_isoc(epd) In some cases, introducing one of these functions is not possible, and it just replaces an explicit integer value by one of the following constants: USB_ENDPOINT_XFER_BULK USB_ENDPOINT_XFER_CONTROL USB_ENDPOINT_XFER_INT USB_ENDPOINT_XFER_ISOC An extract of the semantic patch that makes these changes is as follows: (http://www.emn.fr/x-info/coccinelle/) // @r1@ struct usb_endpoint_descriptor *epd; @@ - ((epd->bmAttributes & \(USB_ENDPOINT_XFERTYPE_MASK\|3\)) == - \(USB_ENDPOINT_XFER_CONTROL\|0\)) + usb_endpoint_xfer_control(epd) @r5@ struct usb_endpoint_descriptor *epd; @@ - ((epd->bEndpointAddress & \(USB_ENDPOINT_DIR_MASK\|0x80\)) == - \(USB_DIR_IN\|0x80\)) + usb_endpoint_dir_in(epd) @inc@ @@ #include @depends on !inc && (r1||r5)@ @@ + #include #include // Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/block/ub.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/block/ub.c b/drivers/block/ub.c index 12fb816db7b0..b36b84fbe390 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -2146,10 +2146,9 @@ static int ub_get_pipes(struct ub_dev *sc, struct usb_device *dev, ep = &altsetting->endpoint[i].desc; /* Is it a BULK endpoint? */ - if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) - == USB_ENDPOINT_XFER_BULK) { + if (usb_endpoint_xfer_bulk(ep)) { /* BULK in or out? */ - if (ep->bEndpointAddress & USB_DIR_IN) { + if (usb_endpoint_dir_in(ep)) { if (ep_in == NULL) ep_in = ep; } else { @@ -2168,9 +2167,9 @@ static int ub_get_pipes(struct ub_dev *sc, struct usb_device *dev, sc->send_ctrl_pipe = usb_sndctrlpipe(dev, 0); sc->recv_ctrl_pipe = usb_rcvctrlpipe(dev, 0); sc->send_bulk_pipe = usb_sndbulkpipe(dev, - ep_out->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); + usb_endpoint_num(ep_out)); sc->recv_bulk_pipe = usb_rcvbulkpipe(dev, - ep_in->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); + usb_endpoint_num(ep_in)); return 0; } -- cgit v1.2.3 From 61b56e041f835fcd8f5dba819ca325f50d4b470e Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 21 Dec 2008 16:41:36 +0100 Subject: USB: Remove redundant test in pxa27x_udc and ftdi_sio priv is checked not to be NULL near the beginning of the function and not changed subsequently, making the test redundant. A simplified version of the semantic patch that makes this change is as follows: (http://www.emn.fr/x-info/coccinelle/) // @r exists@ local idexpression x; expression E; position p1,p2; @@ if (x@p1 == NULL || ...) { ... when forall return ...; } ... when != \(x=E\|x--\|x++\|--x\|++x\|x-=E\|x+=E\|x|=E\|x&=E\|&x\) ( x@p2 == NULL | x@p2 != NULL ) // another path to the test that is not through p1? @s exists@ local idexpression r.x; position r.p1,r.p2; @@ ... when != x@p1 ( x@p2 == NULL | x@p2 != NULL ) @fix depends on !s@ position r.p1,r.p2; expression x,E; statement S1,S2; @@ ( - if ((x@p2 != NULL) || ...) S1 | - if ((x@p2 == NULL) && ...) S1 | - BUG_ON(x@p2 == NULL); ) // Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/pxa27x_udc.c | 2 +- drivers/usb/serial/ftdi_sio.c | 16 +++++++--------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index e50419d08996..91ba1e939475 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -279,7 +279,7 @@ static void pxa_init_debugfs(struct pxa_udc *udc) goto err_queues; eps = debugfs_create_file("epstate", 0400, root, udc, &eps_dbg_fops); - if (!queues) + if (!eps) goto err_eps; udc->debugfs_root = root; diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index ae84c326a540..d889216bcb30 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1938,15 +1938,13 @@ static void ftdi_process_read(struct work_struct *work) /* Compare new line status to the old one, signal if different/ N.B. packet may be processed more than once, but differences are only processed once. */ - if (priv != NULL) { - char new_status = data[packet_offset + 0] & - FTDI_STATUS_B0_MASK; - if (new_status != priv->prev_status) { - priv->diff_status |= - new_status ^ priv->prev_status; - wake_up_interruptible(&priv->delta_msr_wait); - priv->prev_status = new_status; - } + char new_status = data[packet_offset + 0] & + FTDI_STATUS_B0_MASK; + if (new_status != priv->prev_status) { + priv->diff_status |= + new_status ^ priv->prev_status; + wake_up_interruptible(&priv->delta_msr_wait); + priv->prev_status = new_status; } length = min(PKTSZ, urb->actual_length-packet_offset)-2; -- cgit v1.2.3 From 40836fd7f3ad91431ad0ddf911cd47b65790fe2e Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 29 Dec 2008 11:22:14 +0100 Subject: USB: drivers: use USB API functions rather than constants This set of patches introduces calls to the following set of functions: usb_endpoint_dir_in(epd) usb_endpoint_dir_out(epd) usb_endpoint_is_bulk_in(epd) usb_endpoint_is_bulk_out(epd) usb_endpoint_is_int_in(epd) usb_endpoint_is_int_out(epd) usb_endpoint_num(epd) usb_endpoint_type(epd) usb_endpoint_xfer_bulk(epd) usb_endpoint_xfer_control(epd) usb_endpoint_xfer_int(epd) usb_endpoint_xfer_isoc(epd) In some cases, introducing one of these functions is not possible, and it just replaces an explicit integer value by one of the following constants: USB_ENDPOINT_XFER_BULK USB_ENDPOINT_XFER_CONTROL USB_ENDPOINT_XFER_INT USB_ENDPOINT_XFER_ISOC An extract of the semantic patch that makes these changes is as follows: (http://www.emn.fr/x-info/coccinelle/) // @r1@ struct usb_endpoint_descriptor *epd; @@ - ((epd->bmAttributes & \(USB_ENDPOINT_XFERTYPE_MASK\|3\)) == - \(USB_ENDPOINT_XFER_CONTROL\|0\)) + usb_endpoint_xfer_control(epd) @r5@ struct usb_endpoint_descriptor *epd; @@ - ((epd->bEndpointAddress & \(USB_ENDPOINT_DIR_MASK\|0x80\)) == - \(USB_DIR_IN\|0x80\)) + usb_endpoint_dir_in(epd) @inc@ @@ #include @depends on !inc && (r1||r5)@ @@ + #include #include // Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devices.c | 2 +- drivers/usb/core/endpoint.c | 9 ++++----- drivers/usb/host/r8a66597-hcd.c | 15 +++++++-------- drivers/usb/serial/keyspan.c | 2 +- drivers/usb/storage/usb.c | 6 +++--- 5 files changed, 16 insertions(+), 18 deletions(-) diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index 6ec38175a817..73c108d117b4 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -187,7 +187,7 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end, } /* this isn't checking for illegal values */ - switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + switch (usb_endpoint_type(desc)) { case USB_ENDPOINT_XFER_CONTROL: type = "Ctrl"; if (speed == USB_SPEED_HIGH) /* uframes per NAK */ diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c index e1710f260b4f..40dee2ac0133 100644 --- a/drivers/usb/core/endpoint.c +++ b/drivers/usb/core/endpoint.c @@ -66,7 +66,7 @@ static ssize_t show_ep_type(struct device *dev, struct device_attribute *attr, struct ep_device *ep = to_ep_device(dev); char *type = "unknown"; - switch (ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + switch (usb_endpoint_type(ep->desc)) { case USB_ENDPOINT_XFER_CONTROL: type = "Control"; break; @@ -94,7 +94,7 @@ static ssize_t show_ep_interval(struct device *dev, in = (ep->desc->bEndpointAddress & USB_DIR_IN); - switch (ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + switch (usb_endpoint_type(ep->desc)) { case USB_ENDPOINT_XFER_CONTROL: if (ep->udev->speed == USB_SPEED_HIGH) /* uframes per NAK */ interval = ep->desc->bInterval; @@ -131,10 +131,9 @@ static ssize_t show_ep_direction(struct device *dev, struct ep_device *ep = to_ep_device(dev); char *direction; - if ((ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_CONTROL) + if (usb_endpoint_xfer_control(ep->desc)) direction = "both"; - else if (ep->desc->bEndpointAddress & USB_DIR_IN) + else if (usb_endpoint_dir_in(ep->desc)) direction = "in"; else direction = "out"; diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 319041205b57..5e942d94aebe 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -660,9 +660,9 @@ static u16 get_empty_pipenum(struct r8a66597 *r8a66597, u16 array[R8A66597_MAX_NUM_PIPE], i = 0, min; memset(array, 0, sizeof(array)); - switch (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + switch (usb_endpoint_type(ep)) { case USB_ENDPOINT_XFER_BULK: - if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) + if (usb_endpoint_dir_in(ep)) array[i++] = 4; else { array[i++] = 3; @@ -670,7 +670,7 @@ static u16 get_empty_pipenum(struct r8a66597 *r8a66597, } break; case USB_ENDPOINT_XFER_INT: - if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) { + if (usb_endpoint_dir_in(ep)) { array[i++] = 6; array[i++] = 7; array[i++] = 8; @@ -678,7 +678,7 @@ static u16 get_empty_pipenum(struct r8a66597 *r8a66597, array[i++] = 9; break; case USB_ENDPOINT_XFER_ISOC: - if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) + if (usb_endpoint_dir_in(ep)) array[i++] = 2; else array[i++] = 1; @@ -928,10 +928,9 @@ static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb, info.pipenum = get_empty_pipenum(r8a66597, ep); info.address = get_urb_to_r8a66597_addr(r8a66597, urb); - info.epnum = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; + info.epnum = usb_endpoint_num(ep); info.maxpacket = le16_to_cpu(ep->wMaxPacketSize); - info.type = get_r8a66597_type(ep->bmAttributes - & USB_ENDPOINT_XFERTYPE_MASK); + info.type = get_r8a66597_type(usb_endpoint_type(ep)); info.bufnum = get_bufnum(info.pipenum); info.buf_bsize = get_buf_bsize(info.pipenum); if (info.type == R8A66597_BULK) { @@ -941,7 +940,7 @@ static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb, info.interval = get_interval(urb, ep->bInterval); info.timer_interval = get_timer_interval(urb, ep->bInterval); } - if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) + if (usb_endpoint_dir_in(ep)) info.dir_in = 1; else info.dir_in = 0; diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 9878c0fb3859..00daa8f7759a 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -1507,7 +1507,7 @@ static struct urb *keyspan_setup_urb(struct usb_serial *serial, int endpoint, } else { dev_warn(&serial->interface->dev, "unsupported endpoint type %x\n", - ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK); + usb_endpoint_type(ep_desc)); usb_free_urb(urb); return NULL; } diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 4becf495ca2d..b01dade63cb3 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -846,12 +846,12 @@ static int get_pipes(struct us_data *us) us->send_ctrl_pipe = usb_sndctrlpipe(us->pusb_dev, 0); us->recv_ctrl_pipe = usb_rcvctrlpipe(us->pusb_dev, 0); us->send_bulk_pipe = usb_sndbulkpipe(us->pusb_dev, - ep_out->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); + usb_endpoint_num(ep_out)); us->recv_bulk_pipe = usb_rcvbulkpipe(us->pusb_dev, - ep_in->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); + usb_endpoint_num(ep_in)); if (ep_int) { us->recv_intr_pipe = usb_rcvintpipe(us->pusb_dev, - ep_int->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); + usb_endpoint_num(ep_int)); us->ep_bInterval = ep_int->bInterval; } return 0; -- cgit v1.2.3 From 89e8d18a0310cce3d03d2a83e6e3f3d10f962794 Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Sun, 11 Jan 2009 17:25:13 +0800 Subject: USB: gadget: remove duplicated #include Removed duplicated #include in drivers/usb/gadget/ci13xxx_udc.c Signed-off-by: Huang Weiyi Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/ci13xxx_udc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c index 7f4e5eb1dc80..22c65960c429 100644 --- a/drivers/usb/gadget/ci13xxx_udc.c +++ b/drivers/usb/gadget/ci13xxx_udc.c @@ -56,7 +56,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3 From 8dea84f05ac45e217793aa360d02fa9d812020b1 Mon Sep 17 00:00:00 2001 From: Werner Cornelius Date: Fri, 16 Jan 2009 21:02:41 +0100 Subject: USB: usb-serial ch341: support for DTR/RTS/CTS Fixup of Werner Cornelius patch to the ch341 USB-serial driver, which adds: - support all baudrates, not just a hard-coded set - support for controlling DTR, RTS and CTS Features still missing: - character length other than 8 bits - parity settings - break control I adapted his patch for the new usb_serial API introduced in 2.6.25-git8 by Alan Cox on 22 July 2008. Non-compliance to the new API was a reason for refusing a similar patch from Tollef Fog Heen. Usage example by Tollef Fog Heen : TEMPer USB thermometer Signed-off-by: Werner Cornelius Signed-off-by: Boris Hajduk Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ch341.c | 374 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 302 insertions(+), 72 deletions(-) diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index f61e3ca64305..d5ea679e1698 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -1,5 +1,7 @@ /* * Copyright 2007, Frank A Kingswood + * Copyright 2007, Werner Cornelius + * Copyright 2009, Boris Hajduk * * ch341.c implements a serial port driver for the Winchiphead CH341. * @@ -21,9 +23,39 @@ #include #include -#define DEFAULT_BAUD_RATE 2400 +#define DEFAULT_BAUD_RATE 9600 #define DEFAULT_TIMEOUT 1000 +/* flags for IO-Bits */ +#define CH341_BIT_RTS (1 << 6) +#define CH341_BIT_DTR (1 << 5) + +/******************************/ +/* interrupt pipe definitions */ +/******************************/ +/* always 4 interrupt bytes */ +/* first irq byte normally 0x08 */ +/* second irq byte base 0x7d + below */ +/* third irq byte base 0x94 + below */ +/* fourth irq byte normally 0xee */ + +/* second interrupt byte */ +#define CH341_MULT_STAT 0x04 /* multiple status since last interrupt event */ + +/* status returned in third interrupt answer byte, inverted in data + from irq */ +#define CH341_BIT_CTS 0x01 +#define CH341_BIT_DSR 0x02 +#define CH341_BIT_RI 0x04 +#define CH341_BIT_DCD 0x08 +#define CH341_BITS_MODEM_STAT 0x0f /* all bits */ + +/*******************************/ +/* baudrate calculation factor */ +/*******************************/ +#define CH341_BAUDBASE_FACTOR 1532620800 +#define CH341_BAUDBASE_DIVMAX 3 + static int debug; static struct usb_device_id id_table [] = { @@ -34,9 +66,12 @@ static struct usb_device_id id_table [] = { MODULE_DEVICE_TABLE(usb, id_table); struct ch341_private { - unsigned baud_rate; - u8 dtr; - u8 rts; + spinlock_t lock; /* access lock */ + wait_queue_head_t delta_msr_wait; /* wait queue for modem status */ + unsigned baud_rate; /* set baud rate */ + u8 line_control; /* set line control value RTS/DTR */ + u8 line_status; /* active status of modem control inputs */ + u8 multi_status_change; /* status changed multiple since last call */ }; static int ch341_control_out(struct usb_device *dev, u8 request, @@ -72,37 +107,28 @@ static int ch341_set_baudrate(struct usb_device *dev, { short a, b; int r; + unsigned long factor; + short divisor; dbg("ch341_set_baudrate(%d)", priv->baud_rate); - switch (priv->baud_rate) { - case 2400: - a = 0xd901; - b = 0x0038; - break; - case 4800: - a = 0x6402; - b = 0x001f; - break; - case 9600: - a = 0xb202; - b = 0x0013; - break; - case 19200: - a = 0xd902; - b = 0x000d; - break; - case 38400: - a = 0x6403; - b = 0x000a; - break; - case 115200: - a = 0xcc03; - b = 0x0008; - break; - default: + + if (!priv->baud_rate) return -EINVAL; + factor = (CH341_BAUDBASE_FACTOR / priv->baud_rate); + divisor = CH341_BAUDBASE_DIVMAX; + + while ((factor > 0xfff0) && divisor) { + factor >>= 3; + divisor--; } + if (factor > 0xfff0) + return -EINVAL; + + factor = 0x10000 - factor; + a = (factor & 0xff00) | divisor; + b = factor & 0xff; + r = ch341_control_out(dev, 0x9a, 0x1312, a); if (!r) r = ch341_control_out(dev, 0x9a, 0x0f2c, b); @@ -110,19 +136,18 @@ static int ch341_set_baudrate(struct usb_device *dev, return r; } -static int ch341_set_handshake(struct usb_device *dev, - struct ch341_private *priv) +static int ch341_set_handshake(struct usb_device *dev, u8 control) { - dbg("ch341_set_handshake(%d,%d)", priv->dtr, priv->rts); - return ch341_control_out(dev, 0xa4, - ~((priv->dtr?1<<5:0)|(priv->rts?1<<6:0)), 0); + dbg("ch341_set_handshake(0x%02x)", control); + return ch341_control_out(dev, 0xa4, ~control, 0); } -static int ch341_get_status(struct usb_device *dev) +static int ch341_get_status(struct usb_device *dev, struct ch341_private *priv) { char *buffer; int r; const unsigned size = 8; + unsigned long flags; dbg("ch341_get_status()"); @@ -134,10 +159,15 @@ static int ch341_get_status(struct usb_device *dev) if (r < 0) goto out; - /* Not having the datasheet for the CH341, we ignore the bytes returned - * from the device. Return error if the device did not respond in time. - */ - r = 0; + /* setup the private status if available */ + if (r == 2) { + r = 0; + spin_lock_irqsave(&priv->lock, flags); + priv->line_status = (~(*buffer)) & CH341_BITS_MODEM_STAT; + priv->multi_status_change = 0; + spin_unlock_irqrestore(&priv->lock, flags); + } else + r = -EPROTO; out: kfree(buffer); return r; @@ -180,7 +210,7 @@ static int ch341_configure(struct usb_device *dev, struct ch341_private *priv) goto out; /* expect 0xff 0xee */ - r = ch341_get_status(dev); + r = ch341_get_status(dev, priv); if (r < 0) goto out; @@ -192,12 +222,12 @@ static int ch341_configure(struct usb_device *dev, struct ch341_private *priv) if (r < 0) goto out; - r = ch341_set_handshake(dev, priv); + r = ch341_set_handshake(dev, priv->line_control); if (r < 0) goto out; /* expect 0x9f 0xee */ - r = ch341_get_status(dev); + r = ch341_get_status(dev, priv); out: kfree(buffer); return r; @@ -216,9 +246,10 @@ static int ch341_attach(struct usb_serial *serial) if (!priv) return -ENOMEM; + spin_lock_init(&priv->lock); + init_waitqueue_head(&priv->delta_msr_wait); priv->baud_rate = DEFAULT_BAUD_RATE; - priv->dtr = 1; - priv->rts = 1; + priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR; r = ch341_configure(serial->dev, priv); if (r < 0) @@ -231,6 +262,35 @@ error: kfree(priv); return r; } +static void ch341_close(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp) +{ + struct ch341_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + unsigned int c_cflag; + + dbg("%s - port %d", __func__, port->number); + + /* shutdown our urbs */ + dbg("%s - shutting down urbs", __func__); + usb_kill_urb(port->write_urb); + usb_kill_urb(port->read_urb); + usb_kill_urb(port->interrupt_in_urb); + + if (tty) { + c_cflag = tty->termios->c_cflag; + if (c_cflag & HUPCL) { + /* drop DTR and RTS */ + spin_lock_irqsave(&priv->lock, flags); + priv->line_control = 0; + spin_unlock_irqrestore(&priv->lock, flags); + ch341_set_handshake(port->serial->dev, 0); + } + } + wake_up_interruptible(&priv->delta_msr_wait); +} + + /* open this device, set default parameters */ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port, struct file *filp) @@ -242,14 +302,13 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port, dbg("ch341_open()"); priv->baud_rate = DEFAULT_BAUD_RATE; - priv->dtr = 1; - priv->rts = 1; + priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR; r = ch341_configure(serial->dev, priv); if (r) goto out; - r = ch341_set_handshake(serial->dev, priv); + r = ch341_set_handshake(serial->dev, priv->line_control); if (r) goto out; @@ -257,6 +316,16 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port, if (r) goto out; + dbg("%s - submitting interrupt urb", __func__); + port->interrupt_in_urb->dev = serial->dev; + r = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); + if (r) { + dev_err(&port->dev, "%s - failed submitting interrupt urb," + " error %d\n", __func__, r); + ch341_close(tty, port, NULL); + return -EPROTO; + } + r = usb_serial_generic_open(tty, port, filp); out: return r; @@ -270,38 +339,194 @@ static void ch341_set_termios(struct tty_struct *tty, { struct ch341_private *priv = usb_get_serial_port_data(port); unsigned baud_rate; + unsigned long flags; dbg("ch341_set_termios()"); + if (!tty || !tty->termios) + return; + baud_rate = tty_get_baud_rate(tty); - switch (baud_rate) { - case 2400: - case 4800: - case 9600: - case 19200: - case 38400: - case 115200: - priv->baud_rate = baud_rate; - break; - default: - dbg("Rate %d not supported, using %d", - baud_rate, DEFAULT_BAUD_RATE); - priv->baud_rate = DEFAULT_BAUD_RATE; + priv->baud_rate = baud_rate; + + if (baud_rate) { + spin_lock_irqsave(&priv->lock, flags); + priv->line_control |= (CH341_BIT_DTR | CH341_BIT_RTS); + spin_unlock_irqrestore(&priv->lock, flags); + ch341_set_baudrate(port->serial->dev, priv); + } else { + spin_lock_irqsave(&priv->lock, flags); + priv->line_control &= ~(CH341_BIT_DTR | CH341_BIT_RTS); + spin_unlock_irqrestore(&priv->lock, flags); } - ch341_set_baudrate(port->serial->dev, priv); + ch341_set_handshake(port->serial->dev, priv->line_control); /* Unimplemented: * (cflag & CSIZE) : data bits [5, 8] * (cflag & PARENB) : parity {NONE, EVEN, ODD} * (cflag & CSTOPB) : stop bits [1, 2] */ +} + +static int ch341_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) +{ + struct usb_serial_port *port = tty->driver_data; + struct ch341_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + u8 control; + + spin_lock_irqsave(&priv->lock, flags); + if (set & TIOCM_RTS) + priv->line_control |= CH341_BIT_RTS; + if (set & TIOCM_DTR) + priv->line_control |= CH341_BIT_DTR; + if (clear & TIOCM_RTS) + priv->line_control &= ~CH341_BIT_RTS; + if (clear & TIOCM_DTR) + priv->line_control &= ~CH341_BIT_DTR; + control = priv->line_control; + spin_unlock_irqrestore(&priv->lock, flags); + + return ch341_set_handshake(port->serial->dev, control); +} + +static void ch341_read_int_callback(struct urb *urb) +{ + struct usb_serial_port *port = (struct usb_serial_port *) urb->context; + unsigned char *data = urb->transfer_buffer; + unsigned int actual_length = urb->actual_length; + int status; + + dbg("%s (%d)", __func__, port->number); + + switch (urb->status) { + case 0: + /* success */ + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", __func__, + urb->status); + return; + default: + dbg("%s - nonzero urb status received: %d", __func__, + urb->status); + goto exit; + } + + usb_serial_debug_data(debug, &port->dev, __func__, + urb->actual_length, urb->transfer_buffer); + + if (actual_length >= 4) { + struct ch341_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + priv->line_status = (~(data[2])) & CH341_BITS_MODEM_STAT; + if ((data[1] & CH341_MULT_STAT)) + priv->multi_status_change = 1; + spin_unlock_irqrestore(&priv->lock, flags); + wake_up_interruptible(&priv->delta_msr_wait); + } + +exit: + status = usb_submit_urb(urb, GFP_ATOMIC); + if (status) + dev_err(&urb->dev->dev, + "%s - usb_submit_urb failed with result %d\n", + __func__, status); +} + +static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) +{ + struct ch341_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + u8 prevstatus; + u8 status; + u8 changed; + u8 multi_change = 0; + + spin_lock_irqsave(&priv->lock, flags); + prevstatus = priv->line_status; + priv->multi_status_change = 0; + spin_unlock_irqrestore(&priv->lock, flags); + + while (!multi_change) { + interruptible_sleep_on(&priv->delta_msr_wait); + /* see if a signal did it */ + if (signal_pending(current)) + return -ERESTARTSYS; + + spin_lock_irqsave(&priv->lock, flags); + status = priv->line_status; + multi_change = priv->multi_status_change; + spin_unlock_irqrestore(&priv->lock, flags); + + changed = prevstatus ^ status; + + if (((arg & TIOCM_RNG) && (changed & CH341_BIT_RI)) || + ((arg & TIOCM_DSR) && (changed & CH341_BIT_DSR)) || + ((arg & TIOCM_CD) && (changed & CH341_BIT_DCD)) || + ((arg & TIOCM_CTS) && (changed & CH341_BIT_CTS))) { + return 0; + } + prevstatus = status; + } + + return 0; +} + +/*static int ch341_ioctl(struct usb_serial_port *port, struct file *file,*/ +static int ch341_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct usb_serial_port *port = tty->driver_data; + dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd); + + switch (cmd) { + case TIOCMIWAIT: + dbg("%s (%d) TIOCMIWAIT", __func__, port->number); + return wait_modem_info(port, arg); + + default: + dbg("%s not supported = 0x%04x", __func__, cmd); + break; + } + + return -ENOIOCTLCMD; +} + +static int ch341_tiocmget(struct tty_struct *tty, struct file *file) +{ + struct usb_serial_port *port = tty->driver_data; + struct ch341_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + u8 mcr; + u8 status; + unsigned int result; + + dbg("%s (%d)", __func__, port->number); + + spin_lock_irqsave(&priv->lock, flags); + mcr = priv->line_control; + status = priv->line_status; + spin_unlock_irqrestore(&priv->lock, flags); + + result = ((mcr & CH341_BIT_DTR) ? TIOCM_DTR : 0) + | ((mcr & CH341_BIT_RTS) ? TIOCM_RTS : 0) + | ((status & CH341_BIT_CTS) ? TIOCM_CTS : 0) + | ((status & CH341_BIT_DSR) ? TIOCM_DSR : 0) + | ((status & CH341_BIT_RI) ? TIOCM_RI : 0) + | ((status & CH341_BIT_DCD) ? TIOCM_CD : 0); + + dbg("%s - result = %x", __func__, result); - /* Copy back the old hardware settings */ - tty_termios_copy_hw(tty->termios, old_termios); - /* And re-encode with the new baud */ - tty_encode_baud_rate(tty, baud_rate, baud_rate); + return result; } static struct usb_driver ch341_driver = { @@ -317,12 +542,17 @@ static struct usb_serial_driver ch341_device = { .owner = THIS_MODULE, .name = "ch341-uart", }, - .id_table = id_table, - .usb_driver = &ch341_driver, - .num_ports = 1, - .open = ch341_open, - .set_termios = ch341_set_termios, - .attach = ch341_attach, + .id_table = id_table, + .usb_driver = &ch341_driver, + .num_ports = 1, + .open = ch341_open, + .close = ch341_close, + .ioctl = ch341_ioctl, + .set_termios = ch341_set_termios, + .tiocmget = ch341_tiocmget, + .tiocmset = ch341_tiocmset, + .read_int_callback = ch341_read_int_callback, + .attach = ch341_attach, }; static int __init ch341_init(void) -- cgit v1.2.3 From f3d835224f5bdce58c970cd63ed44c7a185b78b9 Mon Sep 17 00:00:00 2001 From: Darius Augulis Date: Wed, 21 Jan 2009 15:17:25 +0200 Subject: USB: imx_udc: Fix IMX UDC gadget bugs Fix small bugs and add some omptimization in IMX UDC Gadget. Signed-off-by: Darius Augulis Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/imx_udc.c | 33 +++++++++++++++++++-------------- drivers/usb/gadget/imx_udc.h | 2 +- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c index cd67ac75e624..78488fbe220c 100644 --- a/drivers/usb/gadget/imx_udc.c +++ b/drivers/usb/gadget/imx_udc.c @@ -283,7 +283,7 @@ void imx_ep_stall(struct imx_ep_struct *imx_ep) imx_flush(imx_ep); /* Special care for ep0 */ - if (EP_NO(imx_ep)) { + if (!EP_NO(imx_ep)) { temp = __raw_readl(imx_usb->base + USB_CTRL); __raw_writel(temp | CTRL_CMDOVER | CTRL_CMDERROR, imx_usb->base + USB_CTRL); do { } while (__raw_readl(imx_usb->base + USB_CTRL) & CTRL_CMDOVER); @@ -301,7 +301,7 @@ void imx_ep_stall(struct imx_ep_struct *imx_ep) break; udelay(20); } - if (i == 50) + if (i == 100) D_ERR(imx_usb->dev, "<%s> Non finished stall on %s\n", __func__, imx_ep->ep.name); } @@ -539,10 +539,9 @@ static int handle_ep0(struct imx_ep_struct *imx_ep) struct imx_request *req = NULL; int ret = 0; - if (!list_empty(&imx_ep->queue)) + if (!list_empty(&imx_ep->queue)) { req = list_entry(imx_ep->queue.next, struct imx_request, queue); - if (req) { switch (imx_ep->imx_usb->ep0state) { case EP0_IN_DATA_PHASE: /* GET_DESCRIPTOR */ @@ -561,6 +560,10 @@ static int handle_ep0(struct imx_ep_struct *imx_ep) } } + else + D_ERR(imx_ep->imx_usb->dev, "<%s> no request on %s\n", + __func__, imx_ep->ep.name); + return ret; } @@ -759,7 +762,7 @@ static int imx_ep_queue */ if (imx_usb->set_config && !EP_NO(imx_ep)) { imx_usb->set_config = 0; - D_EPX(imx_usb->dev, + D_ERR(imx_usb->dev, "<%s> gadget reply set config\n", __func__); return 0; } @@ -779,8 +782,6 @@ static int imx_ep_queue return -ESHUTDOWN; } - local_irq_save(flags); - /* Debug */ D_REQ(imx_usb->dev, "<%s> ep%d %s request for [%d] bytes\n", __func__, EP_NO(imx_ep), @@ -790,17 +791,18 @@ static int imx_ep_queue if (imx_ep->stopped) { usb_req->status = -ESHUTDOWN; - ret = -ESHUTDOWN; - goto out; + return -ESHUTDOWN; } if (req->in_use) { D_ERR(imx_usb->dev, "<%s> refusing to queue req %p (already queued)\n", __func__, req); - goto out; + return 0; } + local_irq_save(flags); + usb_req->status = -EINPROGRESS; usb_req->actual = 0; @@ -810,7 +812,7 @@ static int imx_ep_queue ret = handle_ep0(imx_ep); else ret = handle_ep(imx_ep); -out: + local_irq_restore(flags); return ret; } @@ -1010,10 +1012,8 @@ static irqreturn_t imx_udc_irq(int irq, void *dev) dump_usb_stat(__func__, imx_usb); } - if (!imx_usb->driver) { - /*imx_udc_disable(imx_usb);*/ + if (!imx_usb->driver) goto end_irq; - } if (intr & INTR_WAKEUP) { if (imx_usb->gadget.speed == USB_SPEED_UNKNOWN @@ -1095,6 +1095,11 @@ static irqreturn_t imx_udc_irq(int irq, void *dev) } if (intr & INTR_SOF) { + /* Copy from Freescale BSP. + We must enable SOF intr and set CMDOVER. + Datasheet don't specifiy this action, but it + is done in Freescale BSP, so just copy it. + */ if (imx_usb->ep0state == EP0_IDLE) { temp = __raw_readl(imx_usb->base + USB_CTRL); __raw_writel(temp | CTRL_CMDOVER, imx_usb->base + USB_CTRL); diff --git a/drivers/usb/gadget/imx_udc.h b/drivers/usb/gadget/imx_udc.h index 850076937d8d..d1dfb2d2fa8b 100644 --- a/drivers/usb/gadget/imx_udc.h +++ b/drivers/usb/gadget/imx_udc.h @@ -170,7 +170,7 @@ struct imx_udc_struct { /* #define DEBUG_IRQ */ /* #define DEBUG_EPIRQ */ /* #define DEBUG_DUMP */ -#define DEBUG_ERR +/* #define DEBUG_ERR */ #ifdef DEBUG_REQ #define D_REQ(dev, args...) dev_dbg(dev, ## args) -- cgit v1.2.3 From ed382f798c2f371b13427d178a15ca6a00a4411c Mon Sep 17 00:00:00 2001 From: Darius Augulis Date: Wed, 21 Jan 2009 15:17:55 +0200 Subject: USB: imx_udc: Fix IMX UDC gadget code style Fix code style errors in IMX UDC Gadget. Signed-off-by: Darius Augulis Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/imx_udc.c | 59 +++++++++++++++++++++++++++++--------------- drivers/usb/gadget/imx_udc.h | 46 ++++++++++++++++++++++------------ 2 files changed, 69 insertions(+), 36 deletions(-) diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c index 78488fbe220c..e37730ec5efb 100644 --- a/drivers/usb/gadget/imx_udc.c +++ b/drivers/usb/gadget/imx_udc.c @@ -1,7 +1,7 @@ /* * driver/usb/gadget/imx_udc.c * - * Copyright (C) 2005 Mike Lee(eemike@gmail.com) + * Copyright (C) 2005 Mike Lee * Copyright (C) 2008 Darius Augulis * * This program is free software; you can redistribute it and/or modify @@ -51,7 +51,8 @@ void ep0_chg_stat(const char *label, struct imx_udc_struct *imx_usb, void imx_udc_enable(struct imx_udc_struct *imx_usb) { int temp = __raw_readl(imx_usb->base + USB_CTRL); - __raw_writel(temp | CTRL_FE_ENA | CTRL_AFE_ENA, imx_usb->base + USB_CTRL); + __raw_writel(temp | CTRL_FE_ENA | CTRL_AFE_ENA, + imx_usb->base + USB_CTRL); imx_usb->gadget.speed = USB_SPEED_FULL; } @@ -126,7 +127,8 @@ void imx_udc_config(struct imx_udc_struct *imx_usb) for (j = 0; j < 5; j++) { __raw_writeb(ep_conf[j], imx_usb->base + USB_DDAT); - do {} while (__raw_readl(imx_usb->base + USB_DADR) + do {} while (__raw_readl(imx_usb->base + + USB_DADR) & DADR_BSY); } } @@ -183,7 +185,8 @@ void imx_udc_init_ep(struct imx_udc_struct *imx_usb) temp = (EP_DIR(imx_ep) << 7) | (max << 5) | (imx_ep->bmAttributes << 3); __raw_writel(temp, imx_usb->base + USB_EP_STAT(i)); - __raw_writel(temp | EPSTAT_FLUSH, imx_usb->base + USB_EP_STAT(i)); + __raw_writel(temp | EPSTAT_FLUSH, + imx_usb->base + USB_EP_STAT(i)); D_INI(imx_usb->dev, "<%s> ep%d_stat %08x\n", __func__, i, __raw_readl(imx_usb->base + USB_EP_STAT(i))); } @@ -278,15 +281,18 @@ void imx_ep_stall(struct imx_ep_struct *imx_ep) struct imx_udc_struct *imx_usb = imx_ep->imx_usb; int temp, i; - D_ERR(imx_usb->dev, "<%s> Forced stall on %s\n", __func__, imx_ep->ep.name); + D_ERR(imx_usb->dev, + "<%s> Forced stall on %s\n", __func__, imx_ep->ep.name); imx_flush(imx_ep); /* Special care for ep0 */ if (!EP_NO(imx_ep)) { temp = __raw_readl(imx_usb->base + USB_CTRL); - __raw_writel(temp | CTRL_CMDOVER | CTRL_CMDERROR, imx_usb->base + USB_CTRL); - do { } while (__raw_readl(imx_usb->base + USB_CTRL) & CTRL_CMDOVER); + __raw_writel(temp | CTRL_CMDOVER | CTRL_CMDERROR, + imx_usb->base + USB_CTRL); + do { } while (__raw_readl(imx_usb->base + USB_CTRL) + & CTRL_CMDOVER); temp = __raw_readl(imx_usb->base + USB_CTRL); __raw_writel(temp & ~CTRL_CMDERROR, imx_usb->base + USB_CTRL); } @@ -296,7 +302,8 @@ void imx_ep_stall(struct imx_ep_struct *imx_ep) imx_usb->base + USB_EP_STAT(EP_NO(imx_ep))); for (i = 0; i < 100; i ++) { - temp = __raw_readl(imx_usb->base + USB_EP_STAT(EP_NO(imx_ep))); + temp = __raw_readl(imx_usb->base + + USB_EP_STAT(EP_NO(imx_ep))); if (!(temp & EPSTAT_STALL)) break; udelay(20); @@ -325,7 +332,8 @@ static int imx_udc_wakeup(struct usb_gadget *_gadget) ******************************************************************************* */ -static void ep_add_request(struct imx_ep_struct *imx_ep, struct imx_request *req) +static void ep_add_request(struct imx_ep_struct *imx_ep, + struct imx_request *req) { if (unlikely(!req)) return; @@ -334,7 +342,8 @@ static void ep_add_request(struct imx_ep_struct *imx_ep, struct imx_request *req list_add_tail(&req->queue, &imx_ep->queue); } -static void ep_del_request(struct imx_ep_struct *imx_ep, struct imx_request *req) +static void ep_del_request(struct imx_ep_struct *imx_ep, + struct imx_request *req) { if (unlikely(!req)) return; @@ -343,7 +352,8 @@ static void ep_del_request(struct imx_ep_struct *imx_ep, struct imx_request *req req->in_use = 0; } -static void done(struct imx_ep_struct *imx_ep, struct imx_request *req, int status) +static void done(struct imx_ep_struct *imx_ep, + struct imx_request *req, int status) { ep_del_request(imx_ep, req); @@ -494,7 +504,8 @@ static int write_fifo(struct imx_ep_struct *imx_ep, struct imx_request *req) __func__, imx_ep->ep.name, req, completed ? "completed" : "not completed"); if (!EP_NO(imx_ep)) - ep0_chg_stat(__func__, imx_ep->imx_usb, EP0_IDLE); + ep0_chg_stat(__func__, + imx_ep->imx_usb, EP0_IDLE); } } @@ -586,7 +597,8 @@ static void handle_ep0_devreq(struct imx_udc_struct *imx_usb) "<%s> no setup packet received\n", __func__); goto stall; } - u.word[i] = __raw_readl(imx_usb->base + USB_EP_FDAT(EP_NO(imx_ep))); + u.word[i] = __raw_readl(imx_usb->base + + USB_EP_FDAT(EP_NO(imx_ep))); } temp = imx_ep_empty(imx_ep); @@ -785,8 +797,10 @@ static int imx_ep_queue /* Debug */ D_REQ(imx_usb->dev, "<%s> ep%d %s request for [%d] bytes\n", __func__, EP_NO(imx_ep), - ((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state == EP0_IN_DATA_PHASE) - || (EP_NO(imx_ep) && EP_DIR(imx_ep))) ? "IN" : "OUT", usb_req->length); + ((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state + == EP0_IN_DATA_PHASE) + || (EP_NO(imx_ep) && EP_DIR(imx_ep))) + ? "IN" : "OUT", usb_req->length); dump_req(__func__, imx_ep, usb_req); if (imx_ep->stopped) { @@ -1061,7 +1075,8 @@ static irqreturn_t imx_udc_irq(int irq, void *dev) /* Config setup */ if (imx_usb->cfg != cfg) { - D_REQ(imx_usb->dev, "<%s> Change config start\n",__func__); + D_REQ(imx_usb->dev, + "<%s> Change config start\n", __func__); u.bRequest = USB_REQ_SET_CONFIGURATION; u.bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | @@ -1073,11 +1088,13 @@ static irqreturn_t imx_udc_irq(int irq, void *dev) imx_usb->set_config = 1; imx_usb->driver->setup(&imx_usb->gadget, &u); imx_usb->set_config = 0; - D_REQ(imx_usb->dev, "<%s> Change config done\n",__func__); + D_REQ(imx_usb->dev, + "<%s> Change config done\n", __func__); } if (imx_usb->intf != intf || imx_usb->alt != alt) { - D_REQ(imx_usb->dev, "<%s> Change interface start\n",__func__); + D_REQ(imx_usb->dev, + "<%s> Change interface start\n", __func__); u.bRequest = USB_REQ_SET_INTERFACE; u.bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | @@ -1090,7 +1107,8 @@ static irqreturn_t imx_udc_irq(int irq, void *dev) imx_usb->set_config = 1; imx_usb->driver->setup(&imx_usb->gadget, &u); imx_usb->set_config = 0; - D_REQ(imx_usb->dev, "<%s> Change interface done\n",__func__); + D_REQ(imx_usb->dev, + "<%s> Change interface done\n", __func__); } } @@ -1102,7 +1120,8 @@ static irqreturn_t imx_udc_irq(int irq, void *dev) */ if (imx_usb->ep0state == EP0_IDLE) { temp = __raw_readl(imx_usb->base + USB_CTRL); - __raw_writel(temp | CTRL_CMDOVER, imx_usb->base + USB_CTRL); + __raw_writel(temp | CTRL_CMDOVER, + imx_usb->base + USB_CTRL); } } diff --git a/drivers/usb/gadget/imx_udc.h b/drivers/usb/gadget/imx_udc.h index d1dfb2d2fa8b..6b0b1e3d6fc7 100644 --- a/drivers/usb/gadget/imx_udc.h +++ b/drivers/usb/gadget/imx_udc.h @@ -23,7 +23,8 @@ /* Helper macros */ #define EP_NO(ep) ((ep->bEndpointAddress) & ~USB_DIR_IN) /* IN:1, OUT:0 */ #define EP_DIR(ep) ((ep->bEndpointAddress) & USB_DIR_IN ? 1 : 0) -#define irq_to_ep(irq) (((irq) >= USBD_INT0) || ((irq) <= USBD_INT6) ? ((irq) - USBD_INT0) : (USBD_INT6)) /*should not happen*/ +#define irq_to_ep(irq) (((irq) >= USBD_INT0) || ((irq) <= USBD_INT6) \ + ? ((irq) - USBD_INT0) : (USBD_INT6)) /*should not happen*/ #define ep_to_irq(ep) (EP_NO((ep)) + USBD_INT0) #define IMX_USB_NB_EP 6 @@ -88,8 +89,8 @@ struct imx_udc_struct { #define USB_EP_FDAT3(x) (0x3F + (x*0x30)) /* USB FIFO data */ #define USB_EP_FSTAT(x) (0x40 + (x*0x30)) /* USB FIFO status */ #define USB_EP_FCTRL(x) (0x44 + (x*0x30)) /* USB FIFO control */ -#define USB_EP_LRFP(x) (0x48 + (x*0x30)) /* USB last read frame pointer */ -#define USB_EP_LWFP(x) (0x4C + (x*0x30)) /* USB last write frame pointer */ +#define USB_EP_LRFP(x) (0x48 + (x*0x30)) /* USB last rd f. pointer */ +#define USB_EP_LWFP(x) (0x4C + (x*0x30)) /* USB last wr f. pointer */ #define USB_EP_FALRM(x) (0x50 + (x*0x30)) /* USB FIFO alarm */ #define USB_EP_FRDP(x) (0x54 + (x*0x30)) /* USB FIFO read pointer */ #define USB_EP_FWRP(x) (0x58 + (x*0x30)) /* USB FIFO write pointer */ @@ -228,7 +229,8 @@ struct imx_udc_struct { #endif /* DEBUG_IRQ */ #ifdef DEBUG_EPIRQ - static void dump_ep_intr(const char *label, int nr, int irqreg, struct device *dev) + static void dump_ep_intr(const char *label, int nr, int irqreg, + struct device *dev) { dev_dbg(dev, "<%s> EP%d_INTR=[%s%s%s%s%s%s%s%s%s]\n", label, nr, (irqreg & EPINTR_FIFO_FULL) ? " full" : "", @@ -246,7 +248,8 @@ struct imx_udc_struct { #endif /* DEBUG_IRQ */ #ifdef DEBUG_DUMP - static void dump_usb_stat(const char *label, struct imx_udc_struct *imx_usb) + static void dump_usb_stat(const char *label, + struct imx_udc_struct *imx_usb) { int temp = __raw_readl(imx_usb->base + USB_STAT); @@ -259,12 +262,15 @@ struct imx_udc_struct { (temp & STAT_ALTSET)); } - static void dump_ep_stat(const char *label, struct imx_ep_struct *imx_ep) + static void dump_ep_stat(const char *label, + struct imx_ep_struct *imx_ep) { - int temp = __raw_readl(imx_ep->imx_usb->base + USB_EP_INTR(EP_NO(imx_ep))); + int temp = __raw_readl(imx_ep->imx_usb->base + + USB_EP_INTR(EP_NO(imx_ep))); dev_dbg(imx_ep->imx_usb->dev, - "<%s> EP%d_INTR=[%s%s%s%s%s%s%s%s%s]\n", label, EP_NO(imx_ep), + "<%s> EP%d_INTR=[%s%s%s%s%s%s%s%s%s]\n", + label, EP_NO(imx_ep), (temp & EPINTR_FIFO_FULL) ? " full" : "", (temp & EPINTR_FIFO_EMPTY) ? " fempty" : "", (temp & EPINTR_FIFO_ERROR) ? " ferr" : "", @@ -275,18 +281,22 @@ struct imx_udc_struct { (temp & EPINTR_DEVREQ) ? " devreq" : "", (temp & EPINTR_EOT) ? " eot" : ""); - temp = __raw_readl(imx_ep->imx_usb->base + USB_EP_STAT(EP_NO(imx_ep))); + temp = __raw_readl(imx_ep->imx_usb->base + + USB_EP_STAT(EP_NO(imx_ep))); dev_dbg(imx_ep->imx_usb->dev, - "<%s> EP%d_STAT=[%s%s bcount=%d]\n", label, EP_NO(imx_ep), + "<%s> EP%d_STAT=[%s%s bcount=%d]\n", + label, EP_NO(imx_ep), (temp & EPSTAT_SIP) ? " sip" : "", (temp & EPSTAT_STALL) ? " stall" : "", (temp & EPSTAT_BCOUNT) >> 16); - temp = __raw_readl(imx_ep->imx_usb->base + USB_EP_FSTAT(EP_NO(imx_ep))); + temp = __raw_readl(imx_ep->imx_usb->base + + USB_EP_FSTAT(EP_NO(imx_ep))); dev_dbg(imx_ep->imx_usb->dev, - "<%s> EP%d_FSTAT=[%s%s%s%s%s%s%s]\n", label, EP_NO(imx_ep), + "<%s> EP%d_FSTAT=[%s%s%s%s%s%s%s]\n", + label, EP_NO(imx_ep), (temp & FSTAT_ERR) ? " ferr" : "", (temp & FSTAT_UF) ? " funder" : "", (temp & FSTAT_OF) ? " fover" : "", @@ -296,19 +306,23 @@ struct imx_udc_struct { (temp & FSTAT_EMPTY) ? " fempty" : ""); } - static void dump_req(const char *label, struct imx_ep_struct *imx_ep, struct usb_request *req) + static void dump_req(const char *label, struct imx_ep_struct *imx_ep, + struct usb_request *req) { int i; if (!req || !req->buf) { - dev_dbg(imx_ep->imx_usb->dev, "<%s> req or req buf is free\n", label); + dev_dbg(imx_ep->imx_usb->dev, + "<%s> req or req buf is free\n", label); return; } - if ((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state == EP0_IN_DATA_PHASE) + if ((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state + == EP0_IN_DATA_PHASE) || (EP_NO(imx_ep) && EP_DIR(imx_ep))) { - dev_dbg(imx_ep->imx_usb->dev, "<%s> request dump <", label); + dev_dbg(imx_ep->imx_usb->dev, + "<%s> request dump <", label); for (i = 0; i < req->length; i++) printk("%02x-", *((u8 *)req->buf + i)); printk(">\n"); -- cgit v1.2.3 From 00d2fffbb9a6dccbca5661038a60a5a16bbe17e9 Mon Sep 17 00:00:00 2001 From: Darius Augulis Date: Wed, 21 Jan 2009 15:18:33 +0200 Subject: USB: imx_udc: Fix IMX UDC gadget ep0 irq handling Fix ep0 interrupt handling in IMX UDC Gadget. Signed-off-by: Darius Augulis Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/imx_udc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c index e37730ec5efb..b0dfd083c696 100644 --- a/drivers/usb/gadget/imx_udc.c +++ b/drivers/usb/gadget/imx_udc.c @@ -1133,6 +1133,7 @@ end_irq: static irqreturn_t imx_udc_ctrl_irq(int irq, void *dev) { struct imx_udc_struct *imx_usb = dev; + struct imx_ep_struct *imx_ep = &imx_usb->imx_ep[0]; int intr = __raw_readl(imx_usb->base + USB_EP_INTR(0)); dump_ep_intr(__func__, 0, intr, imx_usb->dev); @@ -1142,16 +1143,15 @@ static irqreturn_t imx_udc_ctrl_irq(int irq, void *dev) return IRQ_HANDLED; } - /* DEVREQ IRQ has highest priority */ + /* DEVREQ has highest priority */ if (intr & (EPINTR_DEVREQ | EPINTR_MDEVREQ)) handle_ep0_devreq(imx_usb); /* Seem i.MX is missing EOF interrupt sometimes. - * Therefore we monitor both EOF and FIFO_EMPTY interrups - * when transmiting, and both EOF and FIFO_FULL when - * receiving data. + * Therefore we don't monitor EOF. + * We call handle_ep0() only if a request is queued for ep0. */ - else if (intr & (EPINTR_EOF | EPINTR_FIFO_EMPTY | EPINTR_FIFO_FULL)) - handle_ep0(&imx_usb->imx_ep[0]); + else if (!list_empty(&imx_ep->queue)) + handle_ep0(imx_ep); __raw_writel(intr, imx_usb->base + USB_EP_INTR(0)); -- cgit v1.2.3 From e5929b177716c504c71ed627a28874e85f503184 Mon Sep 17 00:00:00 2001 From: Darius Augulis Date: Wed, 21 Jan 2009 15:19:19 +0200 Subject: USB: imx_udc: Fix IMX UDC gadget general irq handling Workaround of hw bug in IMX UDC. This bug causes wrong handling of CFG_CHG interrupt. Workaround is documented inline source code. Signed-off-by: Darius Augulis Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/imx_udc.c | 158 +++++++++++++++++++++++++------------------ drivers/usb/gadget/imx_udc.h | 1 + 2 files changed, 94 insertions(+), 65 deletions(-) diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c index b0dfd083c696..168658b4b4e2 100644 --- a/drivers/usb/gadget/imx_udc.c +++ b/drivers/usb/gadget/imx_udc.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -1013,70 +1014,32 @@ static void udc_stop_activity(struct imx_udc_struct *imx_usb, ******************************************************************************* */ -static irqreturn_t imx_udc_irq(int irq, void *dev) +/* + * Called when timer expires. + * Timer is started when CFG_CHG is received. + */ +static void handle_config(unsigned long data) { - struct imx_udc_struct *imx_usb = dev; + struct imx_udc_struct *imx_usb = (void *)data; struct usb_ctrlrequest u; int temp, cfg, intf, alt; - int intr = __raw_readl(imx_usb->base + USB_INTR); - - if (intr & (INTR_WAKEUP | INTR_SUSPEND | INTR_RESUME | INTR_RESET_START - | INTR_RESET_STOP | INTR_CFG_CHG)) { - dump_intr(__func__, intr, imx_usb->dev); - dump_usb_stat(__func__, imx_usb); - } - - if (!imx_usb->driver) - goto end_irq; - - if (intr & INTR_WAKEUP) { - if (imx_usb->gadget.speed == USB_SPEED_UNKNOWN - && imx_usb->driver && imx_usb->driver->resume) - imx_usb->driver->resume(&imx_usb->gadget); - imx_usb->set_config = 0; - imx_usb->gadget.speed = USB_SPEED_FULL; - } - - if (intr & INTR_SUSPEND) { - if (imx_usb->gadget.speed != USB_SPEED_UNKNOWN - && imx_usb->driver && imx_usb->driver->suspend) - imx_usb->driver->suspend(&imx_usb->gadget); - imx_usb->set_config = 0; - imx_usb->gadget.speed = USB_SPEED_UNKNOWN; - } - if (intr & INTR_RESET_START) { - __raw_writel(intr, imx_usb->base + USB_INTR); - udc_stop_activity(imx_usb, imx_usb->driver); - imx_usb->set_config = 0; - imx_usb->gadget.speed = USB_SPEED_UNKNOWN; - } - - if (intr & INTR_RESET_STOP) - imx_usb->gadget.speed = USB_SPEED_FULL; + local_irq_disable(); - if (intr & INTR_CFG_CHG) { - __raw_writel(INTR_CFG_CHG, imx_usb->base + USB_INTR); - temp = __raw_readl(imx_usb->base + USB_STAT); - cfg = (temp & STAT_CFG) >> 5; - intf = (temp & STAT_INTF) >> 3; - alt = temp & STAT_ALTSET; + temp = __raw_readl(imx_usb->base + USB_STAT); + cfg = (temp & STAT_CFG) >> 5; + intf = (temp & STAT_INTF) >> 3; + alt = temp & STAT_ALTSET; - D_REQ(imx_usb->dev, - "<%s> orig config C=%d, I=%d, A=%d / " - "req config C=%d, I=%d, A=%d\n", - __func__, imx_usb->cfg, imx_usb->intf, imx_usb->alt, - cfg, intf, alt); + D_REQ(imx_usb->dev, + "<%s> orig config C=%d, I=%d, A=%d / " + "req config C=%d, I=%d, A=%d\n", + __func__, imx_usb->cfg, imx_usb->intf, imx_usb->alt, + cfg, intf, alt); - if (cfg != 1 && cfg != 2) - goto end_irq; + if (cfg == 1 || cfg == 2) { - imx_usb->set_config = 0; - - /* Config setup */ if (imx_usb->cfg != cfg) { - D_REQ(imx_usb->dev, - "<%s> Change config start\n", __func__); u.bRequest = USB_REQ_SET_CONFIGURATION; u.bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | @@ -1085,16 +1048,10 @@ static irqreturn_t imx_udc_irq(int irq, void *dev) u.wIndex = 0; u.wLength = 0; imx_usb->cfg = cfg; - imx_usb->set_config = 1; imx_usb->driver->setup(&imx_usb->gadget, &u); - imx_usb->set_config = 0; - D_REQ(imx_usb->dev, - "<%s> Change config done\n", __func__); } if (imx_usb->intf != intf || imx_usb->alt != alt) { - D_REQ(imx_usb->dev, - "<%s> Change interface start\n", __func__); u.bRequest = USB_REQ_SET_INTERFACE; u.bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | @@ -1104,14 +1061,30 @@ static irqreturn_t imx_udc_irq(int irq, void *dev) u.wLength = 0; imx_usb->intf = intf; imx_usb->alt = alt; - imx_usb->set_config = 1; imx_usb->driver->setup(&imx_usb->gadget, &u); - imx_usb->set_config = 0; - D_REQ(imx_usb->dev, - "<%s> Change interface done\n", __func__); } } + imx_usb->set_config = 0; + + local_irq_enable(); +} + +static irqreturn_t imx_udc_irq(int irq, void *dev) +{ + struct imx_udc_struct *imx_usb = dev; + int intr = __raw_readl(imx_usb->base + USB_INTR); + int temp; + + if (intr & (INTR_WAKEUP | INTR_SUSPEND | INTR_RESUME | INTR_RESET_START + | INTR_RESET_STOP | INTR_CFG_CHG)) { + dump_intr(__func__, intr, imx_usb->dev); + dump_usb_stat(__func__, imx_usb); + } + + if (!imx_usb->driver) + goto end_irq; + if (intr & INTR_SOF) { /* Copy from Freescale BSP. We must enable SOF intr and set CMDOVER. @@ -1125,6 +1098,55 @@ static irqreturn_t imx_udc_irq(int irq, void *dev) } } + if (intr & INTR_CFG_CHG) { + /* A workaround of serious IMX UDC bug. + Handling of CFG_CHG should be delayed for some time, because + IMX does not NACK the host when CFG_CHG interrupt is pending. + There is no time to handle current CFG_CHG + if next CFG_CHG or SETUP packed is send immediately. + We have to clear CFG_CHG, start the timer and + NACK the host by setting CTRL_CMDOVER + if it sends any SETUP packet. + When timer expires, handler is called to handle configuration + changes. While CFG_CHG is not handled (set_config=1), + we must NACK the host to every SETUP packed. + This delay prevents from going out of sync with host. + */ + __raw_writel(INTR_CFG_CHG, imx_usb->base + USB_INTR); + imx_usb->set_config = 1; + mod_timer(&imx_usb->timer, jiffies + 5); + goto end_irq; + } + + if (intr & INTR_WAKEUP) { + if (imx_usb->gadget.speed == USB_SPEED_UNKNOWN + && imx_usb->driver && imx_usb->driver->resume) + imx_usb->driver->resume(&imx_usb->gadget); + imx_usb->set_config = 0; + del_timer(&imx_usb->timer); + imx_usb->gadget.speed = USB_SPEED_FULL; + } + + if (intr & INTR_SUSPEND) { + if (imx_usb->gadget.speed != USB_SPEED_UNKNOWN + && imx_usb->driver && imx_usb->driver->suspend) + imx_usb->driver->suspend(&imx_usb->gadget); + imx_usb->set_config = 0; + del_timer(&imx_usb->timer); + imx_usb->gadget.speed = USB_SPEED_UNKNOWN; + } + + if (intr & INTR_RESET_START) { + __raw_writel(intr, imx_usb->base + USB_INTR); + udc_stop_activity(imx_usb, imx_usb->driver); + imx_usb->set_config = 0; + del_timer(&imx_usb->timer); + imx_usb->gadget.speed = USB_SPEED_UNKNOWN; + } + + if (intr & INTR_RESET_STOP) + imx_usb->gadget.speed = USB_SPEED_FULL; + end_irq: __raw_writel(intr, imx_usb->base + USB_INTR); return IRQ_HANDLED; @@ -1342,6 +1364,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) udc_stop_activity(imx_usb, driver); imx_udc_disable(imx_usb); + del_timer(&imx_usb->timer); driver->unbind(&imx_usb->gadget); imx_usb->gadget.dev.driver = NULL; @@ -1459,6 +1482,10 @@ static int __init imx_udc_probe(struct platform_device *pdev) usb_init_data(imx_usb); imx_udc_init(imx_usb); + init_timer(&imx_usb->timer); + imx_usb->timer.function = handle_config; + imx_usb->timer.data = (unsigned long)imx_usb; + return 0; fail3: @@ -1481,6 +1508,7 @@ static int __exit imx_udc_remove(struct platform_device *pdev) int i; imx_udc_disable(imx_usb); + del_timer(&imx_usb->timer); for (i = 0; i < IMX_USB_NB_EP + 1; i++) free_irq(imx_usb->usbd_int[i], imx_usb); diff --git a/drivers/usb/gadget/imx_udc.h b/drivers/usb/gadget/imx_udc.h index 6b0b1e3d6fc7..b48ad59603d1 100644 --- a/drivers/usb/gadget/imx_udc.h +++ b/drivers/usb/gadget/imx_udc.h @@ -59,6 +59,7 @@ struct imx_udc_struct { struct device *dev; struct imx_ep_struct imx_ep[IMX_USB_NB_EP]; struct clk *clk; + struct timer_list timer; enum ep0_state ep0state; struct resource *res; void __iomem *base; -- cgit v1.2.3 From 83221b13dfc9c3af22af877d018a3fc1776d53b8 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Tue, 27 Jan 2009 17:21:40 +0100 Subject: USB: suspend/resume support for option driver This patch implements suspend and resume methods for the option driver. With my hardware I can even suspend the system and keep up a connection for a short time. Signed-off-by: Oliver Neukum Signed-Off-By: Matthias Urlichs Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 86 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 80 insertions(+), 6 deletions(-) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 61ebddc48497..d560c0b54e6e 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -62,6 +62,8 @@ static int option_tiocmget(struct tty_struct *tty, struct file *file); static int option_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *port); +static int option_suspend(struct usb_serial *serial, pm_message_t message); +static int option_resume(struct usb_serial *serial); /* Vendor and product IDs */ #define OPTION_VENDOR_ID 0x0AF0 @@ -523,6 +525,8 @@ static struct usb_driver option_driver = { .name = "option", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, + .suspend = usb_serial_suspend, + .resume = usb_serial_resume, .id_table = option_ids, .no_dynamic_id = 1, }; @@ -551,6 +555,8 @@ static struct usb_serial_driver option_1port_device = { .attach = option_startup, .shutdown = option_shutdown, .read_int_callback = option_instat_callback, + .suspend = option_suspend, + .resume = option_resume, }; static int debug; @@ -821,10 +827,10 @@ static void option_instat_callback(struct urb *urb) req_pkt->bRequestType, req_pkt->bRequest); } } else - dbg("%s: error %d", __func__, status); + err("%s: error %d", __func__, status); /* Resubmit urb so we continue receiving IRQ data */ - if (status != -ESHUTDOWN) { + if (status != -ESHUTDOWN && status != -ENOENT) { urb->dev = serial->dev; err = usb_submit_urb(urb, GFP_ATOMIC); if (err) @@ -843,7 +849,6 @@ static int option_write_room(struct tty_struct *tty) portdata = usb_get_serial_port_data(port); - for (i = 0; i < N_OUT_URB; i++) { this_urb = portdata->out_urbs[i]; if (this_urb && !test_bit(i, &portdata->out_busy)) @@ -1105,14 +1110,12 @@ bail_out_error: return 1; } -static void option_shutdown(struct usb_serial *serial) +static void stop_read_write_urbs(struct usb_serial *serial) { int i, j; struct usb_serial_port *port; struct option_port_private *portdata; - dbg("%s", __func__); - /* Stop reading/writing urbs */ for (i = 0; i < serial->num_ports; ++i) { port = serial->port[i]; @@ -1122,6 +1125,17 @@ static void option_shutdown(struct usb_serial *serial) for (j = 0; j < N_OUT_URB; j++) usb_kill_urb(portdata->out_urbs[j]); } +} + +static void option_shutdown(struct usb_serial *serial) +{ + int i, j; + struct usb_serial_port *port; + struct option_port_private *portdata; + + dbg("%s", __func__); + + stop_read_write_urbs(serial); /* Now free them */ for (i = 0; i < serial->num_ports; ++i) { @@ -1152,6 +1166,66 @@ static void option_shutdown(struct usb_serial *serial) } } +static int option_suspend(struct usb_serial *serial, pm_message_t message) +{ + dbg("%s entered", __func__); + stop_read_write_urbs(serial); + + return 0; +} + +static int option_resume(struct usb_serial *serial) +{ + int err, i, j; + struct usb_serial_port *port; + struct urb *urb; + struct option_port_private *portdata; + + dbg("%s entered", __func__); + /* get the interrupt URBs resubmitted unconditionally */ + for (i = 0; i < serial->num_ports; i++) { + port = serial->port[i]; + if (!port->interrupt_in_urb) { + dbg("%s: No interrupt URB for port %d\n", __func__, i); + continue; + } + port->interrupt_in_urb->dev = serial->dev; + err = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO); + dbg("Submitted interrupt URB for port %d (result %d)", i, err); + if (err < 0) { + err("%s: Error %d for interrupt URB of port%d", + __func__, err, i); + return err; + } + } + + for (i = 0; i < serial->num_ports; i++) { + /* walk all ports */ + port = serial->port[i]; + portdata = usb_get_serial_port_data(port); + mutex_lock(&port->mutex); + + /* skip closed ports */ + if (!port->port.count) { + mutex_unlock(&port->mutex); + continue; + } + + for (j = 0; j < N_IN_URB; j++) { + urb = portdata->in_urbs[j]; + err = usb_submit_urb(urb, GFP_NOIO); + if (err < 0) { + mutex_unlock(&port->mutex); + err("%s: Error %d for bulk URB %d", + __func__, err, i); + return err; + } + } + mutex_unlock(&port->mutex); + } + return 0; +} + MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_VERSION(DRIVER_VERSION); -- cgit v1.2.3 From 28d0a9da9c44658afa5b7d0ccc64ada29b101586 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Wed, 14 Jan 2009 18:34:06 +0100 Subject: USB: suspend/resume for opticon driver this does the standard support for suspend/resume for the opticon driver. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/opticon.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index cea326f1f105..00d5c60adeda 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -306,11 +306,37 @@ static void opticon_shutdown(struct usb_serial *serial) usb_set_serial_data(serial, NULL); } +static int opticon_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct usb_serial *serial = usb_get_intfdata(intf); + struct opticon_private *priv = usb_get_serial_data(serial); + + usb_kill_urb(priv->bulk_read_urb); + return 0; +} + +static int opticon_resume(struct usb_interface *intf) +{ + struct usb_serial *serial = usb_get_intfdata(intf); + struct opticon_private *priv = usb_get_serial_data(serial); + struct usb_serial_port *port = serial->port[0]; + int result; + + mutex_lock(&port->mutex); + if (port->port.count) + result = usb_submit_urb(priv->bulk_read_urb, GFP_NOIO); + else + result = 0; + mutex_unlock(&port->mutex); + return result; +} static struct usb_driver opticon_driver = { .name = "opticon", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, + .suspend = opticon_suspend, + .resume = opticon_resume, .id_table = id_table, .no_dynamic_id = 1, }; -- cgit v1.2.3 From 9f7da016eecde731c8be632b711dd48edccca231 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Sat, 31 Jan 2009 12:37:04 +0100 Subject: USB: count reaches -1, tested 0 With a postfix decrement count will reach -1 rather than 0, so the warning will not be issued. Signed-off-by: Roel Kluin Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/pci-quirks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 75b69847918e..033c2846ce59 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -234,7 +234,7 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev) */ hcc_params = readl(base + EHCI_HCC_PARAMS); offset = (hcc_params >> 8) & 0xff; - while (offset && count--) { + while (offset && --count) { u32 cap; int msec; -- cgit v1.2.3 From 67070e831dc0fd5ed7e6f5170fe67a4f3eca876f Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Thu, 5 Feb 2009 16:54:25 +0100 Subject: USB: serial: introduce a flag into the usb serial layer to tell drivers that their URBs are killed due to suspension This patch introduces a flag into the usb serial layer to tell drivers that their URBs are killed due to suspension. That is necessary to let drivers know whether they should report an error back. Signed-off-by: Oliver Neukum Hi Greg, this is for 2.6.30. Patches to use this in drivers are under development. Regards Oliver --- drivers/usb/serial/usb-serial.c | 4 ++++ include/linux/usb/serial.h | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index cfcfd5ab06ce..c6aaa6dc7564 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1067,6 +1067,8 @@ int usb_serial_suspend(struct usb_interface *intf, pm_message_t message) struct usb_serial_port *port; int i, r = 0; + serial->suspending = 1; + for (i = 0; i < serial->num_ports; ++i) { port = serial->port[i]; if (port) @@ -1084,8 +1086,10 @@ int usb_serial_resume(struct usb_interface *intf) { struct usb_serial *serial = usb_get_intfdata(intf); + serial->suspending = 0; if (serial->type->resume) return serial->type->resume(serial); + return 0; } EXPORT_SYMBOL(usb_serial_resume); diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index 0b8617a9176d..b95842542590 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -130,7 +130,8 @@ struct usb_serial { struct usb_device *dev; struct usb_serial_driver *type; struct usb_interface *interface; - unsigned char disconnected; + unsigned char disconnected:1; + unsigned char suspending:1; unsigned char minor; unsigned char num_ports; unsigned char num_port_pointers; -- cgit v1.2.3 From ffe7eac0d2a0b901b77c2743358fe1b9e359cc7f Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Fri, 6 Feb 2009 15:01:54 +0100 Subject: USB: serial generic resume function fix This removes an unnecessary check for autoresume from the generic resume method. The check has been obsoleted by the now delayed increase of the usage counter which makes the error this check prevented impossible. This change allows drivers which only use the bulk read URB the use of the generic method even if they support autosuspend. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/generic.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 814909f1ee63..c4a47abfee68 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -177,14 +177,6 @@ int usb_serial_generic_resume(struct usb_serial *serial) struct usb_serial_port *port; int i, c = 0, r; -#ifdef CONFIG_PM - /* - * If this is an autoresume, don't submit URBs. - * They will be submitted in the open function instead. - */ - if (serial->dev->auto_pm) - return 0; -#endif for (i = 0; i < serial->num_ports; i++) { port = serial->port[i]; if (port->port.count && port->read_urb) { -- cgit v1.2.3 From 48d3452c898c6dd0e7b57ded3c36e8536b718333 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Fri, 6 Feb 2009 15:37:14 +0100 Subject: USB: serial: export symbol of usb_serial_generic_resume This exports a symbol for usb_serial_generic_resume, so that modules can use it. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/generic.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index c4a47abfee68..9d57cace3731 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -188,6 +188,7 @@ int usb_serial_generic_resume(struct usb_serial *serial) return c ? -EIO : 0; } +EXPORT_SYMBOL_GPL(usb_serial_generic_resume); void usb_serial_generic_close(struct tty_struct *tty, struct usb_serial_port *port, struct file *filp) -- cgit v1.2.3 From c89a1e6940d9bc330b4d9bd79bcdb5f033a9eea4 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Fri, 6 Feb 2009 18:06:43 +0100 Subject: USB: serial: use generic method if no alternative is provided in usb serial layer This patch makes use of the generic method if a serial driver provides no implementation. This simplifies implementing suspend/resume support in serial drivers. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index c6aaa6dc7564..18f940847316 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1085,12 +1085,15 @@ EXPORT_SYMBOL(usb_serial_suspend); int usb_serial_resume(struct usb_interface *intf) { struct usb_serial *serial = usb_get_intfdata(intf); + int rv; serial->suspending = 0; if (serial->type->resume) - return serial->type->resume(serial); + rv = serial->type->resume(serial); + else + rv = usb_serial_generic_resume(serial); - return 0; + return rv; } EXPORT_SYMBOL(usb_serial_resume); -- cgit v1.2.3 From 06e1ff32cfaca9aef695c88d780eb1d6e89d9325 Mon Sep 17 00:00:00 2001 From: Frank Seidel Date: Thu, 5 Feb 2009 16:16:24 +0100 Subject: USB: add missing KERN_* constants to printks According to kerneljanitors todo list all printk calls (beginning a new line) should have an according KERN_* constant. Those are the missing peaces here for the usb subsystem. Signed-off-by: Frank Seidel Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/fsl_usb2_udc.c | 8 +++++--- drivers/usb/gadget/lh7a40x_udc.c | 16 +++++++++------- drivers/usb/host/isp116x.h | 8 ++++---- drivers/usb/storage/alauda.c | 25 ++++++++++++++++--------- drivers/usb/storage/sddr09.c | 37 ++++++++++++++++++++++--------------- drivers/usb/storage/sddr55.c | 4 +++- 6 files changed, 59 insertions(+), 39 deletions(-) diff --git a/drivers/usb/gadget/fsl_usb2_udc.c b/drivers/usb/gadget/fsl_usb2_udc.c index d8d9a52a44b3..9d7b95d4e3d2 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.c +++ b/drivers/usb/gadget/fsl_usb2_udc.c @@ -1802,7 +1802,8 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) out: if (retval) - printk("gadget driver register failed %d\n", retval); + printk(KERN_WARNING "gadget driver register failed %d\n", + retval); return retval; } EXPORT_SYMBOL(usb_gadget_register_driver); @@ -1847,7 +1848,8 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) udc_controller->gadget.dev.driver = NULL; udc_controller->driver = NULL; - printk("unregistered gadget driver '%s'\n", driver->driver.name); + printk(KERN_WARNING "unregistered gadget driver '%s'\n", + driver->driver.name); return 0; } EXPORT_SYMBOL(usb_gadget_unregister_driver); @@ -2455,7 +2457,7 @@ module_init(udc_init); static void __exit udc_exit(void) { platform_driver_unregister(&udc_driver); - printk("%s unregistered\n", driver_desc); + printk(KERN_WARNING "%s unregistered\n", driver_desc); } module_exit(udc_exit); diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c index d554b0895603..6cd3d54f5640 100644 --- a/drivers/usb/gadget/lh7a40x_udc.c +++ b/drivers/usb/gadget/lh7a40x_udc.c @@ -432,8 +432,8 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) device_add(&dev->gadget.dev); retval = driver->bind(&dev->gadget); if (retval) { - printk("%s: bind to driver %s --> error %d\n", dev->gadget.name, - driver->driver.name, retval); + printk(KERN_WARNING "%s: bind to driver %s --> error %d\n", + dev->gadget.name, driver->driver.name, retval); device_del(&dev->gadget.dev); dev->driver = 0; @@ -445,8 +445,8 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) * for set_configuration as well as eventual disconnect. * NOTE: this shouldn't power up until later. */ - printk("%s: registered gadget driver '%s'\n", dev->gadget.name, - driver->driver.name); + printk(KERN_WARNING "%s: registered gadget driver '%s'\n", + dev->gadget.name, driver->driver.name); udc_enable(dev); @@ -581,7 +581,8 @@ static int read_fifo(struct lh7a40x_ep *ep, struct lh7a40x_request *req) * discard the extra data. */ if (req->req.status != -EOVERFLOW) - printk("%s overflow %d\n", ep->ep.name, count); + printk(KERN_WARNING "%s overflow %d\n", + ep->ep.name, count); req->req.status = -EOVERFLOW; } else { *buf++ = byte; @@ -831,7 +832,8 @@ static void lh7a40x_out_epn(struct lh7a40x_udc *dev, u32 ep_idx, u32 intr) queue); if (!req) { - printk("%s: NULL REQ %d\n", + printk(KERN_WARNING + "%s: NULL REQ %d\n", __func__, ep_idx); flush(ep); break; @@ -844,7 +846,7 @@ static void lh7a40x_out_epn(struct lh7a40x_udc *dev, u32 ep_idx, u32 intr) } else { /* Throw packet away.. */ - printk("%s: No descriptor?!?\n", __func__); + printk(KERN_WARNING "%s: No descriptor?!?\n", __func__); flush(ep); } } diff --git a/drivers/usb/host/isp116x.h b/drivers/usb/host/isp116x.h index aa211bafcff9..12db961acdfb 100644 --- a/drivers/usb/host/isp116x.h +++ b/drivers/usb/host/isp116x.h @@ -563,7 +563,7 @@ static void urb_dbg(struct urb *urb, char *msg) */ static inline void dump_ptd(struct ptd *ptd) { - printk("td: %x %d%c%d %d,%d,%d %x %x%x%x\n", + printk(KERN_WARNING "td: %x %d%c%d %d,%d,%d %x %x%x%x\n", PTD_GET_CC(ptd), PTD_GET_FA(ptd), PTD_DIR_STR(ptd), PTD_GET_EP(ptd), PTD_GET_COUNT(ptd), PTD_GET_LEN(ptd), PTD_GET_MPS(ptd), @@ -576,7 +576,7 @@ static inline void dump_ptd_out_data(struct ptd *ptd, u8 * buf) int k; if (PTD_GET_DIR(ptd) != PTD_DIR_IN && PTD_GET_LEN(ptd)) { - printk("-> "); + printk(KERN_WARNING "-> "); for (k = 0; k < PTD_GET_LEN(ptd); ++k) printk("%02x ", ((u8 *) buf)[k]); printk("\n"); @@ -588,13 +588,13 @@ static inline void dump_ptd_in_data(struct ptd *ptd, u8 * buf) int k; if (PTD_GET_DIR(ptd) == PTD_DIR_IN && PTD_GET_COUNT(ptd)) { - printk("<- "); + printk(KERN_WARNING "<- "); for (k = 0; k < PTD_GET_COUNT(ptd); ++k) printk("%02x ", ((u8 *) buf)[k]); printk("\n"); } if (PTD_GET_LAST(ptd)) - printk("-\n"); + printk(KERN_WARNING "-\n"); } #else diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c index 8d3711a7ff06..5407411e30e0 100644 --- a/drivers/usb/storage/alauda.c +++ b/drivers/usb/storage/alauda.c @@ -307,7 +307,8 @@ static int alauda_init_media(struct us_data *us) data[0], data[1], data[2], data[3]); media_info = alauda_card_find_id(data[1]); if (media_info == NULL) { - printk("alauda_init_media: Unrecognised media signature: " + printk(KERN_WARNING + "alauda_init_media: Unrecognised media signature: " "%02X %02X %02X %02X\n", data[0], data[1], data[2], data[3]); return USB_STOR_TRANSPORT_ERROR; @@ -518,7 +519,8 @@ static int alauda_read_map(struct us_data *us, unsigned int zone) /* check even parity */ if (parity[data[6] ^ data[7]]) { - printk("alauda_read_map: Bad parity in LBA for block %d" + printk(KERN_WARNING + "alauda_read_map: Bad parity in LBA for block %d" " (%02X %02X)\n", i, data[6], data[7]); pba_to_lba[i] = UNUSABLE; continue; @@ -538,13 +540,16 @@ static int alauda_read_map(struct us_data *us, unsigned int zone) */ if (lba_offset >= uzonesize) { - printk("alauda_read_map: Bad low LBA %d for block %d\n", + printk(KERN_WARNING + "alauda_read_map: Bad low LBA %d for block %d\n", lba_real, blocknum); continue; } if (lba_to_pba[lba_offset] != UNDEF) { - printk("alauda_read_map: LBA %d seen for PBA %d and %d\n", + printk(KERN_WARNING + "alauda_read_map: " + "LBA %d seen for PBA %d and %d\n", lba_real, lba_to_pba[lba_offset], blocknum); continue; } @@ -712,13 +717,15 @@ static int alauda_write_lba(struct us_data *us, u16 lba, if (pba == 1) { /* Maybe it is impossible to write to PBA 1. Fake success, but don't do anything. */ - printk("alauda_write_lba: avoid writing to pba 1\n"); + printk(KERN_WARNING + "alauda_write_lba: avoid writing to pba 1\n"); return USB_STOR_TRANSPORT_GOOD; } new_pba = alauda_find_unused_pba(&MEDIA_INFO(us), zone); if (!new_pba) { - printk("alauda_write_lba: Out of unused blocks\n"); + printk(KERN_WARNING + "alauda_write_lba: Out of unused blocks\n"); return USB_STOR_TRANSPORT_ERROR; } @@ -818,7 +825,7 @@ static int alauda_read_data(struct us_data *us, unsigned long address, len = min(sectors, blocksize) * (pagesize + 64); buffer = kmalloc(len, GFP_NOIO); if (buffer == NULL) { - printk("alauda_read_data: Out of memory\n"); + printk(KERN_WARNING "alauda_read_data: Out of memory\n"); return USB_STOR_TRANSPORT_ERROR; } @@ -911,7 +918,7 @@ static int alauda_write_data(struct us_data *us, unsigned long address, len = min(sectors, blocksize) * pagesize; buffer = kmalloc(len, GFP_NOIO); if (buffer == NULL) { - printk("alauda_write_data: Out of memory\n"); + printk(KERN_WARNING "alauda_write_data: Out of memory\n"); return USB_STOR_TRANSPORT_ERROR; } @@ -921,7 +928,7 @@ static int alauda_write_data(struct us_data *us, unsigned long address, */ blockbuffer = kmalloc((pagesize + 64) * blocksize, GFP_NOIO); if (blockbuffer == NULL) { - printk("alauda_write_data: Out of memory\n"); + printk(KERN_WARNING "alauda_write_data: Out of memory\n"); kfree(buffer); return USB_STOR_TRANSPORT_ERROR; } diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c index 531ae5c5abf3..b667c7d2b837 100644 --- a/drivers/usb/storage/sddr09.c +++ b/drivers/usb/storage/sddr09.c @@ -723,7 +723,7 @@ sddr09_read_data(struct us_data *us, len = min(sectors, (unsigned int) info->blocksize) * info->pagesize; buffer = kmalloc(len, GFP_NOIO); if (buffer == NULL) { - printk("sddr09_read_data: Out of memory\n"); + printk(KERN_WARNING "sddr09_read_data: Out of memory\n"); return -ENOMEM; } @@ -838,7 +838,8 @@ sddr09_write_lba(struct us_data *us, unsigned int lba, if (pba == UNDEF) { pba = sddr09_find_unused_pba(info, lba); if (!pba) { - printk("sddr09_write_lba: Out of unused blocks\n"); + printk(KERN_WARNING + "sddr09_write_lba: Out of unused blocks\n"); return -ENOSPC; } info->pba_to_lba[pba] = lba; @@ -849,7 +850,7 @@ sddr09_write_lba(struct us_data *us, unsigned int lba, if (pba == 1) { /* Maybe it is impossible to write to PBA 1. Fake success, but don't do anything. */ - printk("sddr09: avoid writing to pba 1\n"); + printk(KERN_WARNING "sddr09: avoid writing to pba 1\n"); return 0; } @@ -954,7 +955,7 @@ sddr09_write_data(struct us_data *us, blocklen = (pagelen << info->blockshift); blockbuffer = kmalloc(blocklen, GFP_NOIO); if (!blockbuffer) { - printk("sddr09_write_data: Out of memory\n"); + printk(KERN_WARNING "sddr09_write_data: Out of memory\n"); return -ENOMEM; } @@ -965,7 +966,7 @@ sddr09_write_data(struct us_data *us, len = min(sectors, (unsigned int) info->blocksize) * info->pagesize; buffer = kmalloc(len, GFP_NOIO); if (buffer == NULL) { - printk("sddr09_write_data: Out of memory\n"); + printk(KERN_WARNING "sddr09_write_data: Out of memory\n"); kfree(blockbuffer); return -ENOMEM; } @@ -1112,7 +1113,7 @@ sddr09_get_cardinfo(struct us_data *us, unsigned char flags) { if (result) { US_DEBUGP("Result of read_deviceID is %d\n", result); - printk("sddr09: could not read card info\n"); + printk(KERN_WARNING "sddr09: could not read card info\n"); return NULL; } @@ -1153,7 +1154,7 @@ sddr09_get_cardinfo(struct us_data *us, unsigned char flags) { sprintf(blurbtxt + strlen(blurbtxt), ", WP"); - printk("%s\n", blurbtxt); + printk(KERN_WARNING "%s\n", blurbtxt); return cardinfo; } @@ -1184,7 +1185,7 @@ sddr09_read_map(struct us_data *us) { alloc_len = (alloc_blocks << CONTROL_SHIFT); buffer = kmalloc(alloc_len, GFP_NOIO); if (buffer == NULL) { - printk("sddr09_read_map: out of memory\n"); + printk(KERN_WARNING "sddr09_read_map: out of memory\n"); result = -1; goto done; } @@ -1198,7 +1199,7 @@ sddr09_read_map(struct us_data *us) { info->pba_to_lba = kmalloc(numblocks*sizeof(int), GFP_NOIO); if (info->lba_to_pba == NULL || info->pba_to_lba == NULL) { - printk("sddr09_read_map: out of memory\n"); + printk(KERN_WARNING "sddr09_read_map: out of memory\n"); result = -1; goto done; } @@ -1238,7 +1239,8 @@ sddr09_read_map(struct us_data *us) { if (ptr[j] != 0) goto nonz; info->pba_to_lba[i] = UNUSABLE; - printk("sddr09: PBA %d has no logical mapping\n", i); + printk(KERN_WARNING "sddr09: PBA %d has no logical mapping\n", + i); continue; nonz: @@ -1251,7 +1253,8 @@ sddr09_read_map(struct us_data *us) { nonff: /* normal PBAs start with six FFs */ if (j < 6) { - printk("sddr09: PBA %d has no logical mapping: " + printk(KERN_WARNING + "sddr09: PBA %d has no logical mapping: " "reserved area = %02X%02X%02X%02X " "data status %02X block status %02X\n", i, ptr[0], ptr[1], ptr[2], ptr[3], @@ -1261,7 +1264,8 @@ sddr09_read_map(struct us_data *us) { } if ((ptr[6] >> 4) != 0x01) { - printk("sddr09: PBA %d has invalid address field " + printk(KERN_WARNING + "sddr09: PBA %d has invalid address field " "%02X%02X/%02X%02X\n", i, ptr[6], ptr[7], ptr[11], ptr[12]); info->pba_to_lba[i] = UNUSABLE; @@ -1270,7 +1274,8 @@ sddr09_read_map(struct us_data *us) { /* check even parity */ if (parity[ptr[6] ^ ptr[7]]) { - printk("sddr09: Bad parity in LBA for block %d" + printk(KERN_WARNING + "sddr09: Bad parity in LBA for block %d" " (%02X %02X)\n", i, ptr[6], ptr[7]); info->pba_to_lba[i] = UNUSABLE; continue; @@ -1289,7 +1294,8 @@ sddr09_read_map(struct us_data *us) { */ if (lba >= 1000) { - printk("sddr09: Bad low LBA %d for block %d\n", + printk(KERN_WARNING + "sddr09: Bad low LBA %d for block %d\n", lba, i); goto possibly_erase; } @@ -1297,7 +1303,8 @@ sddr09_read_map(struct us_data *us) { lba += 1000*(i/0x400); if (info->lba_to_pba[lba] != UNDEF) { - printk("sddr09: LBA %d seen for PBA %d and %d\n", + printk(KERN_WARNING + "sddr09: LBA %d seen for PBA %d and %d\n", lba, info->lba_to_pba[lba], i); goto possibly_erase; } diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c index 0d8df7577899..5a0106ba256c 100644 --- a/drivers/usb/storage/sddr55.c +++ b/drivers/usb/storage/sddr55.c @@ -703,7 +703,9 @@ static int sddr55_read_map(struct us_data *us) { if (info->lba_to_pba[lba + zone * 1000] != NOT_ALLOCATED && !info->force_read_only) { - printk("sddr55: map inconsistency at LBA %04X\n", lba + zone * 1000); + printk(KERN_WARNING + "sddr55: map inconsistency at LBA %04X\n", + lba + zone * 1000); info->force_read_only = 1; } -- cgit v1.2.3 From b9a4ffdc5b7fc1a05ed35f5359ec7b5b1f6d2244 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Fri, 6 Feb 2009 02:39:11 -0800 Subject: USB: ftdi_sio: remove pointless syslog spew Remove some pointless messages from the FTDI serial driver; I found these filling up syslog on one system. Also remove a pointless "break" after a "return" in the same area. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index d889216bcb30..adeb23fb8003 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -2292,11 +2292,8 @@ static int ftdi_tiocmget(struct tty_struct *tty, struct file *file) FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, 0, 0, buf, 1, WDR_TIMEOUT); - if (ret < 0) { - dbg("%s Could not get modem status of device - err: %d", __func__, - ret); + if (ret < 0) return ret; - } break; case FT8U232AM: case FT232BM: @@ -2311,15 +2308,11 @@ static int ftdi_tiocmget(struct tty_struct *tty, struct file *file) FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, 0, priv->interface, buf, 2, WDR_TIMEOUT); - if (ret < 0) { - dbg("%s Could not get modem status of device - err: %d", __func__, - ret); + if (ret < 0) return ret; - } break; default: return -EFAULT; - break; } return (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) | -- cgit v1.2.3 From 4499b36f4b989b40d86d12adf140bcfb46312f5e Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Fri, 6 Feb 2009 17:32:35 +0530 Subject: USB: otg: adding nop usb transceiver NOP transceiver is used by all the usb transceiver which are mostly autonomous and doesn't require any programming or which are built into the usb ip itself.NOP transceiver only allocates the memory for struct xceiv and calls otg_set_transceiver() so function call to otg_get_transceiver() will return a valid transceiver. NOP transceiver device should be registered by calling usb_nop_xceiv_register() from platform files. Signed-off-by: Ajay Kumar Gupta Cc: Felipe Balbi Cc: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/otg/Kconfig | 8 ++ drivers/usb/otg/Makefile | 1 + drivers/usb/otg/nop-usb-xceiv.c | 180 ++++++++++++++++++++++++++++++++++++++++ include/linux/usb/otg.h | 4 + 4 files changed, 193 insertions(+) create mode 100644 drivers/usb/otg/nop-usb-xceiv.c diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index ee55b449ffde..fc1ca03ce4da 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig @@ -51,4 +51,12 @@ config TWL4030_USB This transceiver supports high and full speed devices plus, in host mode, low speed. +config NOP_USB_XCEIV + tristate "NOP USB Transceiver Driver" + select USB_OTG_UTILS + help + this driver is to be used by all the usb transceiver which are either + built-in with usb ip or which are autonomous and doesn't require any + phy programming such as ISP1x04 etc. + endif # USB || OTG diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile index d73c7cf5e2f7..208167856529 100644 --- a/drivers/usb/otg/Makefile +++ b/drivers/usb/otg/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_USB_OTG_UTILS) += otg.o obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus.o obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o +obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o ccflags-$(CONFIG_USB_DEBUG) += -DDEBUG ccflags-$(CONFIG_USB_GADGET_DEBUG) += -DDEBUG diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c new file mode 100644 index 000000000000..4b933f646f2e --- /dev/null +++ b/drivers/usb/otg/nop-usb-xceiv.c @@ -0,0 +1,180 @@ +/* + * drivers/usb/otg/nop-usb-xceiv.c + * + * NOP USB transceiver for all USB transceiver which are either built-in + * into USB IP or which are mostly autonomous. + * + * Copyright (C) 2009 Texas Instruments Inc + * Author: Ajay Kumar Gupta + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Current status: + * this is to add "nop" transceiver for all those phy which is + * autonomous such as isp1504 etc. + */ + +#include +#include +#include +#include + +struct nop_usb_xceiv { + struct otg_transceiver otg; + struct device *dev; +}; + +static u64 nop_xceiv_dmamask = DMA_32BIT_MASK; + +static struct platform_device nop_xceiv_device = { + .name = "nop_usb_xceiv", + .id = -1, + .dev = { + .dma_mask = &nop_xceiv_dmamask, + .coherent_dma_mask = DMA_32BIT_MASK, + .platform_data = NULL, + }, +}; + +void usb_nop_xceiv_register(void) +{ + if (platform_device_register(&nop_xceiv_device) < 0) { + printk(KERN_ERR "Unable to register usb nop transceiver\n"); + return; + } +} + +void usb_nop_xceiv_unregister(void) +{ + platform_device_unregister(&nop_xceiv_device); +} + +static inline struct nop_usb_xceiv *xceiv_to_nop(struct otg_transceiver *x) +{ + return container_of(x, struct nop_usb_xceiv, otg); +} + +static int nop_set_suspend(struct otg_transceiver *x, int suspend) +{ + return 0; +} + +static int nop_set_peripheral(struct otg_transceiver *x, + struct usb_gadget *gadget) +{ + struct nop_usb_xceiv *nop; + + if (!x) + return -ENODEV; + + nop = xceiv_to_nop(x); + + if (!gadget) { + nop->otg.gadget = NULL; + return -ENODEV; + } + + nop->otg.gadget = gadget; + nop->otg.state = OTG_STATE_B_IDLE; + return 0; +} + +static int nop_set_host(struct otg_transceiver *x, struct usb_bus *host) +{ + struct nop_usb_xceiv *nop; + + if (!x) + return -ENODEV; + + nop = xceiv_to_nop(x); + + if (!host) { + nop->otg.host = NULL; + return -ENODEV; + } + + nop->otg.host = host; + return 0; +} + +static int __devinit nop_usb_xceiv_probe(struct platform_device *pdev) +{ + struct nop_usb_xceiv *nop; + int err; + + nop = kzalloc(sizeof *nop, GFP_KERNEL); + if (!nop) + return -ENOMEM; + + nop->dev = &pdev->dev; + nop->otg.dev = nop->dev; + nop->otg.label = "nop-xceiv"; + nop->otg.state = OTG_STATE_UNDEFINED; + nop->otg.set_host = nop_set_host; + nop->otg.set_peripheral = nop_set_peripheral; + nop->otg.set_suspend = nop_set_suspend; + + err = otg_set_transceiver(&nop->otg); + if (err) { + dev_err(&pdev->dev, "can't register transceiver, err: %d\n", + err); + goto exit; + } + + platform_set_drvdata(pdev, nop); + + return 0; +exit: + kfree(nop); + return err; +} + +static int __devexit nop_usb_xceiv_remove(struct platform_device *pdev) +{ + struct nop_usb_xceiv *nop = platform_get_drvdata(pdev); + + otg_set_transceiver(NULL); + + platform_set_drvdata(pdev, NULL); + kfree(nop); + + return 0; +} + +static struct platform_driver nop_usb_xceiv_driver = { + .probe = nop_usb_xceiv_probe, + .remove = __devexit_p(nop_usb_xceiv_remove), + .driver = { + .name = "nop_usb_xceiv", + .owner = THIS_MODULE, + }, +}; + +static int __init nop_usb_xceiv_init(void) +{ + return platform_driver_register(&nop_usb_xceiv_driver); +} +subsys_initcall(nop_usb_xceiv_init); + +static void __exit nop_usb_xceiv_exit(void) +{ + platform_driver_unregister(&nop_usb_xceiv_driver); +} +module_exit(nop_usb_xceiv_exit); + +MODULE_ALIAS("platform:nop_usb_xceiv"); +MODULE_AUTHOR("Texas Instruments Inc"); +MODULE_DESCRIPTION("NOP USB Transceiver driver"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h index 60a52576fd5c..1aaa826396a1 100644 --- a/include/linux/usb/otg.h +++ b/include/linux/usb/otg.h @@ -80,6 +80,10 @@ struct otg_transceiver { /* for board-specific init logic */ extern int otg_set_transceiver(struct otg_transceiver *); +#ifdef CONFIG_NOP_USB_XCEIV +extern void usb_nop_xceiv_register(void); +extern void usb_nop_xceiv_unregister(void); +#endif /* for usb host and peripheral controller drivers */ -- cgit v1.2.3 From df0eecea2527972480c6355d6a42998112368101 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 6 Feb 2009 18:30:56 -0800 Subject: USB: serial: opticon: add write support This patch allows data to be sent to the scanner. Cc: Kees Stoop Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/opticon.c | 124 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 122 insertions(+), 2 deletions(-) diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 00d5c60adeda..8c87a49ee2bb 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -1,8 +1,8 @@ /* * Opticon USB barcode to serial driver * - * Copyright (C) 2008 Greg Kroah-Hartman - * Copyright (C) 2008 Novell Inc. + * Copyright (C) 2008 - 2009 Greg Kroah-Hartman + * Copyright (C) 2008 - 2009 Novell Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version @@ -40,8 +40,12 @@ struct opticon_private { bool throttled; bool actually_throttled; bool rts; + int outstanding_urbs; }; +/* max number of write urbs in flight */ +#define URB_UPPER_LIMIT 4 + static void opticon_bulk_callback(struct urb *urb) { struct opticon_private *priv = urb->context; @@ -188,6 +192,120 @@ static void opticon_close(struct tty_struct *tty, struct usb_serial_port *port, usb_kill_urb(priv->bulk_read_urb); } +static void opticon_write_bulk_callback(struct urb *urb) +{ + struct opticon_private *priv = urb->context; + int status = urb->status; + unsigned long flags; + + /* free up the transfer buffer, as usb_free_urb() does not do this */ + kfree(urb->transfer_buffer); + + if (status) + dbg("%s - nonzero write bulk status received: %d", + __func__, status); + + spin_lock_irqsave(&priv->lock, flags); + --priv->outstanding_urbs; + spin_unlock_irqrestore(&priv->lock, flags); + + usb_serial_port_softint(priv->port); +} + +static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *buf, int count) +{ + struct opticon_private *priv = usb_get_serial_data(port->serial); + struct usb_serial *serial = port->serial; + struct urb *urb; + unsigned char *buffer; + unsigned long flags; + int status; + + dbg("%s - port %d", __func__, port->number); + + spin_lock_irqsave(&priv->lock, flags); + if (priv->outstanding_urbs > URB_UPPER_LIMIT) { + spin_unlock_irqrestore(&priv->lock, flags); + dbg("%s - write limit hit\n", __func__); + return 0; + } + priv->outstanding_urbs++; + spin_unlock_irqrestore(&priv->lock, flags); + + buffer = kmalloc(count, GFP_ATOMIC); + if (!buffer) { + dev_err(&port->dev, "out of memory\n"); + count = -ENOMEM; + goto error_no_buffer; + } + + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!urb) { + dev_err(&port->dev, "no more free urbs\n"); + count = -ENOMEM; + goto error_no_urb; + } + + memcpy(buffer, buf, count); + + usb_serial_debug_data(debug, &port->dev, __func__, count, buffer); + + usb_fill_bulk_urb(urb, serial->dev, + usb_sndbulkpipe(serial->dev, + port->bulk_out_endpointAddress), + buffer, count, opticon_write_bulk_callback, priv); + + /* send it down the pipe */ + status = usb_submit_urb(urb, GFP_ATOMIC); + if (status) { + dev_err(&port->dev, + "%s - usb_submit_urb(write bulk) failed with status = %d\n", + __func__, status); + count = status; + goto error; + } + + /* we are done with this urb, so let the host driver + * really free it when it is finished with it */ + usb_free_urb(urb); + + return count; +error: + usb_free_urb(urb); +error_no_urb: + kfree(buffer); +error_no_buffer: + spin_lock_irqsave(&priv->lock, flags); + --priv->outstanding_urbs; + spin_unlock_irqrestore(&priv->lock, flags); + return count; +} + +static int opticon_write_room(struct tty_struct *tty) +{ + struct usb_serial_port *port = tty->driver_data; + struct opticon_private *priv = usb_get_serial_data(port->serial); + unsigned long flags; + + dbg("%s - port %d", __func__, port->number); + + /* + * We really can take almost anything the user throws at us + * but let's pick a nice big number to tell the tty + * layer that we have lots of free space, unless we don't. + */ + spin_lock_irqsave(&priv->lock, flags); + if (priv->outstanding_urbs > URB_UPPER_LIMIT * 2 / 3) { + spin_unlock_irqrestore(&priv->lock, flags); + dbg("%s - write limit hit\n", __func__); + return 0; + } + spin_unlock_irqrestore(&priv->lock, flags); + + return 2048; +} + static void opticon_throttle(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; @@ -352,6 +470,8 @@ static struct usb_serial_driver opticon_device = { .attach = opticon_startup, .open = opticon_open, .close = opticon_close, + .write = opticon_write, + .write_room = opticon_write_room, .shutdown = opticon_shutdown, .throttle = opticon_throttle, .unthrottle = opticon_unthrottle, -- cgit v1.2.3 From 02a54ddb41ea55f086cd2b2f24d27604e0808ed9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 6 Feb 2009 18:31:46 -0800 Subject: USB: serial: opticon: add serial line ioctls This lets userspace determine what the state of the RTS line is, which is what is needed to properly handle data flow for this device (it raises RTS when there is data to be sent from it.) Cc: Kees Stoop Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/opticon.c | 65 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 8c87a49ee2bb..839583dc8b6a 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -110,7 +111,6 @@ static void opticon_bulk_callback(struct urb *urb) priv->rts = false; else priv->rts = true; - /* FIXME change the RTS level */ } else { dev_dbg(&priv->udev->dev, "Unknown data packet received from the device:" @@ -341,6 +341,67 @@ static void opticon_unthrottle(struct tty_struct *tty) __func__, result); } +static int opticon_tiocmget(struct tty_struct *tty, struct file *file) +{ + struct usb_serial_port *port = tty->driver_data; + struct opticon_private *priv = usb_get_serial_data(port->serial); + unsigned long flags; + int result = 0; + + dbg("%s - port %d", __func__, port->number); + + spin_lock_irqsave(&priv->lock, flags); + if (priv->rts) + result = TIOCM_RTS; + spin_unlock_irqrestore(&priv->lock, flags); + + dbg("%s - %x", __func__, result); + return result; +} + +static int get_serial_info(struct opticon_private *priv, + struct serial_struct __user *serial) +{ + struct serial_struct tmp; + + if (!serial) + return -EFAULT; + + memset(&tmp, 0x00, sizeof(tmp)); + + /* fake emulate a 16550 uart to make userspace code happy */ + tmp.type = PORT_16550A; + tmp.line = priv->serial->minor; + tmp.port = 0; + tmp.irq = 0; + tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; + tmp.xmit_fifo_size = 1024; + tmp.baud_base = 9600; + tmp.close_delay = 5*HZ; + tmp.closing_wait = 30*HZ; + + if (copy_to_user(serial, &tmp, sizeof(*serial))) + return -EFAULT; + return 0; +} + +static int opticon_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct usb_serial_port *port = tty->driver_data; + struct opticon_private *priv = usb_get_serial_data(port->serial); + + dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd); + + switch (cmd) { + case TIOCGSERIAL: + return get_serial_info(priv, + (struct serial_struct __user *)arg); + } + + return -ENOIOCTLCMD; +} + static int opticon_startup(struct usb_serial *serial) { struct opticon_private *priv; @@ -475,6 +536,8 @@ static struct usb_serial_driver opticon_device = { .shutdown = opticon_shutdown, .throttle = opticon_throttle, .unthrottle = opticon_unthrottle, + .ioctl = opticon_ioctl, + .tiocmget = opticon_tiocmget, }; static int __init opticon_init(void) -- cgit v1.2.3 From 9d4b9b1447cd608adeead3c28f7defa72d4fae54 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Sat, 7 Feb 2009 20:20:42 +0100 Subject: usb_storage: make Kconfig note visible in the console Make lines about usb_storage depending on SCSI visible when configuring the kernel in a 80x25 console Signed-off-by: Borislav Petkov Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 9df6887b91f6..5c367566be8d 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -2,8 +2,8 @@ # USB Storage driver configuration # -comment "NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;" -comment "see USB_STORAGE Help for more information" +comment "NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may" +comment "also be needed; see USB_STORAGE Help for more info" depends on USB config USB_STORAGE -- cgit v1.2.3 From 131b61bdcec5bb126500a2a0483ae9ec8f2714cc Mon Sep 17 00:00:00 2001 From: Matt Kraai Date: Fri, 6 Feb 2009 19:38:51 -0800 Subject: USB: skeleton: Use dev_info instead of info 338b67b0c1a97ca705023a8189cf41aa0828d294 removed the info macro and replaced its uses with dev_info. This patch does so for usb-skeleton.c, which was missed. Signed-off-by: Matt Kraai Signed-off-by: Greg Kroah-Hartman --- drivers/usb/usb-skeleton.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c index be76084c8d7e..60ba631e99c2 100644 --- a/drivers/usb/usb-skeleton.c +++ b/drivers/usb/usb-skeleton.c @@ -410,7 +410,9 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i } /* let the user know what node this device is now attached to */ - info("USB Skeleton device now attached to USBSkel-%d", interface->minor); + dev_info(&interface->dev, + "USB Skeleton device now attached to USBSkel-%d", + interface->minor); return 0; error: @@ -441,7 +443,7 @@ static void skel_disconnect(struct usb_interface *interface) /* decrement our usage count */ kref_put(&dev->kref, skel_delete); - info("USB Skeleton #%d now disconnected", minor); + dev_info(&interface->dev, "USB Skeleton #%d now disconnected", minor); } static void skel_draw_down(struct usb_skel *dev) -- cgit v1.2.3 From 93f1bdc065394a59f044adb709d1d979fd582416 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 9 Feb 2009 10:03:49 +0100 Subject: USB: serial: remove recourse to generic method This removes the fallback to the generic method. It is cleaner to explicitely request it. Introducing this was my mistake. This will be solved by an explicit test and the driver being allowed to request what it needs to be done upon resumption. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 18f940847316..9a2617845dfc 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1229,7 +1229,6 @@ static void fixup_generic(struct usb_serial_driver *device) set_to_generic_if_null(device, read_bulk_callback); set_to_generic_if_null(device, write_bulk_callback); set_to_generic_if_null(device, shutdown); - set_to_generic_if_null(device, resume); } int usb_serial_register(struct usb_serial_driver *driver) -- cgit v1.2.3 From deedcd25efa6ce2c20e2f18f7cc10de7decf7926 Mon Sep 17 00:00:00 2001 From: James Woodcock Date: Wed, 11 Feb 2009 15:06:53 +0000 Subject: USB: serial: refuse to open recently removed USB Serial devices A USB-serial converter device is plugged into a system, and a process opens it's device node. If the device is physically removed whilst the process still has its device node open, then other processes can sucessfully open the now non-existent device's node. I would expect that open() on a device that has been physically removed should return ENODEV. This is manifesting itself with getty on my system. I do the following: 1. set up inittab to spawn getty on ttyUSB0, eg: T1:23:respawn:/sbin/getty -L ttyUSB0 115200 vt100 2. Plug in USB-serial converter cable 3. Wait for a login prompt on a terminal program attached to the serial cable 4. Login 5. Pull the USB-serial converter cable from the box 6. getty doesn't realise that ttyUSB0 no longer exists as /dev/ttyUSB0 can still be opened. 7. Re-insert the USB-serial converter cable 8. You should no longer get a login prompt over the serial cable, as the the USB-serial cable now shows up as /dev/ttyUSB1, and getty is trying to talk to /dev/ttyUSB0. The attached patch will cause open("/dev/ttyUSB0", O_RDONLY) to return ENODEV after the USB-serial converter has been pulled. The patch was created against 2.6.28.1. I can supply it against something else if needs be. It is fairly simple, so should be OK. I am using a pl2303 device, although I don't think that makes any difference. From: James Woodcock Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 9a2617845dfc..73172898ccb3 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -204,6 +204,11 @@ static int serial_open (struct tty_struct *tty, struct file *filp) goto bailout_kref_put; } + if (port->serial->disconnected) { + retval = -ENODEV; + goto bailout_kref_put; + } + if (mutex_lock_interruptible(&port->mutex)) { retval = -ERESTARTSYS; goto bailout_kref_put; -- cgit v1.2.3 From e2d331f3957db2ecb6c53462c7853c5dc4673558 Mon Sep 17 00:00:00 2001 From: Thierry Vignaud Date: Wed, 11 Feb 2009 13:31:05 -0800 Subject: usb: kill prehistorical comments about USB_EHCI_HCD Remove old comments about USB_EHCI_HCD. Cc: Alan Stern Signed-off-by: Andrew Morton Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/Kconfig | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 2c63bfb1f8d9..c1cfed7eefb5 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -24,10 +24,7 @@ config USB_EHCI_HCD The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0 "high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware. If your USB host controller supports USB 2.0, you will likely want to - configure this Host Controller Driver. At the time of this writing, - the primary implementation of EHCI is a chip from NEC, widely available - in add-on PCI cards, but implementations are in the works from other - vendors including Intel and Philips. Motherboard support is appearing. + configure this Host Controller Driver. EHCI controllers are packaged with "companion" host controllers (OHCI or UHCI) to handle USB 1.1 devices connected to root hub ports. Ports -- cgit v1.2.3 From 259c7af8ee55bd6ad97336c9f5f4cbc79ab8ec7d Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 11 Feb 2009 14:26:38 -0500 Subject: USB: EHCI: Make timer_action out-of-line This patch (as1205) moves timer_action() from ehci.h to ehci-hcd.c and makes it out-of-line. Over the years it has grown too big to be inline any more. Signed-off-by: Alan Stern Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hcd.c | 36 ++++++++++++++++++++++++++++++++++++ drivers/usb/host/ehci.h | 34 ---------------------------------- 2 files changed, 36 insertions(+), 34 deletions(-) diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index e551bb38852b..f2618d17710d 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -110,6 +110,42 @@ MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications"); /*-------------------------------------------------------------------------*/ +static void +timer_action(struct ehci_hcd *ehci, enum ehci_timer_action action) +{ + /* Don't override timeouts which shrink or (later) disable + * the async ring; just the I/O watchdog. Note that if a + * SHRINK were pending, OFF would never be requested. + */ + if (timer_pending(&ehci->watchdog) + && ((BIT(TIMER_ASYNC_SHRINK) | BIT(TIMER_ASYNC_OFF)) + & ehci->actions)) + return; + + if (!test_and_set_bit(action, &ehci->actions)) { + unsigned long t; + + switch (action) { + case TIMER_IO_WATCHDOG: + t = EHCI_IO_JIFFIES; + break; + case TIMER_ASYNC_OFF: + t = EHCI_ASYNC_JIFFIES; + break; + /* case TIMER_ASYNC_SHRINK: */ + default: + /* add a jiffie since we synch against the + * 8 KHz uframe counter. + */ + t = DIV_ROUND_UP(EHCI_SHRINK_FRAMES * HZ, 1000) + 1; + break; + } + mod_timer(&ehci->watchdog, t + jiffies); + } +} + +/*-------------------------------------------------------------------------*/ + /* * handshake - spin reading hc until handshake completes or fails * @ptr: address of hc register to be read diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 262b00c9b334..0042deb671dd 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -190,40 +190,6 @@ timer_action_done (struct ehci_hcd *ehci, enum ehci_timer_action action) clear_bit (action, &ehci->actions); } -static inline void -timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action) -{ - /* Don't override timeouts which shrink or (later) disable - * the async ring; just the I/O watchdog. Note that if a - * SHRINK were pending, OFF would never be requested. - */ - if (timer_pending(&ehci->watchdog) - && ((BIT(TIMER_ASYNC_SHRINK) | BIT(TIMER_ASYNC_OFF)) - & ehci->actions)) - return; - - if (!test_and_set_bit (action, &ehci->actions)) { - unsigned long t; - - switch (action) { - case TIMER_IO_WATCHDOG: - t = EHCI_IO_JIFFIES; - break; - case TIMER_ASYNC_OFF: - t = EHCI_ASYNC_JIFFIES; - break; - // case TIMER_ASYNC_SHRINK: - default: - /* add a jiffie since we synch against the - * 8 KHz uframe counter. - */ - t = DIV_ROUND_UP(EHCI_SHRINK_FRAMES * HZ, 1000) + 1; - break; - } - mod_timer(&ehci->watchdog, t + jiffies); - } -} - static void free_cached_itd_list(struct ehci_hcd *ehci); /*-------------------------------------------------------------------------*/ -- cgit v1.2.3 From b2abba3df23bd50adf978b4351a8dcb7589f91d8 Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Wed, 11 Feb 2009 09:54:31 +0200 Subject: USB: fix USB_STORAGE_CYPRESS_ATACB commit 64a87b24: [SCSI] Let scsi_cmnd->cmnd use request->cmd buffer changed the scsi_eh_prep_cmnd logic by making it clear the ->cmnd buffer. But the sat to cypress atacb translation supposed the ->cmnd buffer wasn't modified. This patch makes it set the ->cmnd buffer after scsi_eh_prep_cmnd call. The problem and a fix was reported by Matthieu CASTET It also removes all the hackery fiddling of scsi_cmnd and scsi_eh_save by requesting from scsi_eh_prep_cmnd to prepare a read into ->sense_buffer, which is much more suitable a buffer for HW transfers, then after the command execution the regs read is copied into regs buffer before actual preparation of sense_buffer. Also fix an alien comment character to my utf-8 editor. Signed-off-by: Boaz Harrosh Signed-off-by: Matthieu CASTET Cc: stable Cc: James Bottomley Cc: Matthew Dharm Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/cypress_atacb.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/usb/storage/cypress_atacb.c b/drivers/usb/storage/cypress_atacb.c index 898e67d30e56..9466a99baab6 100644 --- a/drivers/usb/storage/cypress_atacb.c +++ b/drivers/usb/storage/cypress_atacb.c @@ -133,19 +133,18 @@ void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us) /* build the command for * reading the ATA registers */ - scsi_eh_prep_cmnd(srb, &ses, NULL, 0, 0); - srb->sdb.length = sizeof(regs); - sg_init_one(&ses.sense_sgl, regs, srb->sdb.length); - srb->sdb.table.sgl = &ses.sense_sgl; - srb->sc_data_direction = DMA_FROM_DEVICE; - srb->sdb.table.nents = 1; + scsi_eh_prep_cmnd(srb, &ses, NULL, 0, sizeof(regs)); + /* we use the same command as before, but we set * the read taskfile bit, for not executing atacb command, * but reading register selected in srb->cmnd[4] */ + srb->cmd_len = 16; + srb->cmnd = ses.cmnd; srb->cmnd[2] = 1; usb_stor_transparent_scsi_command(srb, us); + memcpy(regs, srb->sense_buffer, sizeof(regs)); tmp_result = srb->result; scsi_eh_restore_cmnd(srb, &ses); /* we fail to get registers, report invalid command */ @@ -162,8 +161,8 @@ void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us) /* XXX we should generate sk, asc, ascq from status and error * regs - * (see 11.1 Error translation ­ ATA device error to SCSI error map) - * and ata_to_sense_error from libata. + * (see 11.1 Error translation ATA device error to SCSI error + * map, and ata_to_sense_error from libata.) */ /* Sense data is current and format is descriptor. */ -- cgit v1.2.3 From ca40886c9881dafc6eede6c9bd286d879e5d2a6a Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 10 Feb 2009 10:16:58 -0500 Subject: USB: EHCI: add software retry for transaction errors This patch (as1204) adds a software retry mechanism to ehci-hcd. It gets invoked when the driver encounters transaction errors on an asynchronous endpoint. On many systems, hardware deficiencies cause such errors to occur if one device is unplugged while the host is communicating with another device. With the patch, the failed transactions are retried and generally succeed the second or third time through. This is based on code originally written by Koichiro Saito. Signed-off-by: Alan Stern Tested by: Koichiro Saito CC: David Brownell Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-q.c | 32 ++++++++++++++++++++++++++++++++ drivers/usb/host/ehci.h | 3 +++ 2 files changed, 35 insertions(+) diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index ecc9b66c03cd..01132ac74eb8 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -333,12 +333,40 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) token = hc32_to_cpu(ehci, qtd->hw_token); /* always clean up qtds the hc de-activated */ + retry_xacterr: if ((token & QTD_STS_ACTIVE) == 0) { /* on STALL, error, and short reads this urb must * complete and all its qtds must be recycled. */ if ((token & QTD_STS_HALT) != 0) { + + /* retry transaction errors until we + * reach the software xacterr limit + */ + if ((token & QTD_STS_XACT) && + QTD_CERR(token) == 0 && + --qh->xacterrs > 0 && + !urb->unlinked) { + ehci_dbg(ehci, + "detected XactErr len %d/%d retry %d\n", + qtd->length - QTD_LENGTH(token), qtd->length, + QH_XACTERR_MAX - qh->xacterrs); + + /* reset the token in the qtd and the + * qh overlay (which still contains + * the qtd) so that we pick up from + * where we left off + */ + token &= ~QTD_STS_HALT; + token |= QTD_STS_ACTIVE | + (EHCI_TUNE_CERR << 10); + qtd->hw_token = cpu_to_hc32(ehci, + token); + wmb(); + qh->hw_token = cpu_to_hc32(ehci, token); + goto retry_xacterr; + } stopped = 1; /* magic dummy for some short reads; qh won't advance. @@ -421,6 +449,9 @@ halt: /* remove qtd; it's recycled after possible urb completion */ list_del (&qtd->qtd_list); last = qtd; + + /* reinit the xacterr counter for the next qtd */ + qh->xacterrs = QH_XACTERR_MAX; } /* last urb's completion might still need calling */ @@ -862,6 +893,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) head->qh_next.qh = qh; head->hw_next = dma; + qh->xacterrs = QH_XACTERR_MAX; qh->qh_state = QH_STATE_LINKED; /* qtd completions reported later by interrupt */ } diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 0042deb671dd..9aba560fd569 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -342,6 +342,9 @@ struct ehci_qh { #define QH_STATE_UNLINK_WAIT 4 /* LINKED and on reclaim q */ #define QH_STATE_COMPLETING 5 /* don't touch token.HALT */ + u8 xacterrs; /* XactErr retry counter */ +#define QH_XACTERR_MAX 32 /* XactErr retry limit */ + /* periodic schedule info */ u8 usecs; /* intr bandwidth */ u8 gap_uf; /* uframes split/csplit gap */ -- cgit v1.2.3 From 68736937c8e58a7500f0800d15164898316efe4a Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Tue, 10 Feb 2009 16:55:45 +0000 Subject: USB: Make the isp1760_register function prototype more generic The patch changes the prototype of the isp1760_register() function to use predefined types like phys_addr_t and resource_size_t rather than u64 Signed-off-by: Catalin Marinas Cc: Sebastian Siewior Cc: Russell King Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/isp1760-hcd.c | 7 ++++--- drivers/usb/host/isp1760-hcd.h | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index b899f1a59c26..8ee2f4159845 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -2235,9 +2235,10 @@ void deinit_kmem_cache(void) kmem_cache_destroy(qh_cachep); } -struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq, - u64 irqflags, struct device *dev, const char *busname, - unsigned int devflags) +struct usb_hcd *isp1760_register(phys_addr_t res_start, resource_size_t res_len, + int irq, unsigned long irqflags, + struct device *dev, const char *busname, + unsigned int devflags) { struct usb_hcd *hcd; struct isp1760_hcd *priv; diff --git a/drivers/usb/host/isp1760-hcd.h b/drivers/usb/host/isp1760-hcd.h index a9daea587962..462f4943cb1b 100644 --- a/drivers/usb/host/isp1760-hcd.h +++ b/drivers/usb/host/isp1760-hcd.h @@ -2,9 +2,10 @@ #define _ISP1760_HCD_H_ /* exports for if */ -struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq, - u64 irqflags, struct device *dev, const char *busname, - unsigned int devflags); +struct usb_hcd *isp1760_register(phys_addr_t res_start, resource_size_t res_len, + int irq, unsigned long irqflags, + struct device *dev, const char *busname, + unsigned int devflags); int init_kmem_once(void); void deinit_kmem_cache(void); -- cgit v1.2.3 From 30175aa83f17ce07a59e9da41b659eae5c249bd5 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Tue, 10 Feb 2009 16:55:51 +0000 Subject: USB: Add platform device support for the ISP1760 USB chip Currently, the driver only supports PCI and PPC_OF but there are boards like ARM RealView where this is a platform device. The patch adds the necessary functions and registration to the isp1760-if.c file and modifies the corresponding Makefile and Kconfig to be able to use this driver even if PCI and PPC_OF are not enabled. Signed-off-by: Catalin Marinas Cc: Sebastian Siewior Cc: Russell King Signed-off-by: Greg Kroah-Hartman --- drivers/usb/Makefile | 1 + drivers/usb/host/Kconfig | 2 +- drivers/usb/host/isp1760-if.c | 95 +++++++++++++++++++++++++++++++++++-------- 3 files changed, 81 insertions(+), 17 deletions(-) diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index b2ceb4aff233..89299a5ce168 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_USB_SL811_HCD) += host/ obj-$(CONFIG_USB_U132_HCD) += host/ obj-$(CONFIG_USB_R8A66597_HCD) += host/ obj-$(CONFIG_USB_HWA_HCD) += host/ +obj-$(CONFIG_USB_ISP1760_HCD) += host/ obj-$(CONFIG_USB_C67X00_HCD) += c67x00/ diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index c1cfed7eefb5..845479f7c707 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -120,7 +120,7 @@ config USB_ISP116X_HCD config USB_ISP1760_HCD tristate "ISP 1760 HCD support" - depends on USB && EXPERIMENTAL && (PCI || PPC_OF) + depends on USB && EXPERIMENTAL ---help--- The ISP1760 chip is a USB 2.0 host controller. diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index 4cf7ca428b33..3fa3a1702796 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c @@ -10,6 +10,7 @@ #include #include +#include #include "../core/hcd.h" #include "isp1760-hcd.h" @@ -300,39 +301,101 @@ static struct pci_driver isp1761_pci_driver = { }; #endif +static int __devinit isp1760_plat_probe(struct platform_device *pdev) +{ + int ret = 0; + struct usb_hcd *hcd; + struct resource *mem_res; + struct resource *irq_res; + resource_size_t mem_size; + unsigned long irqflags = IRQF_SHARED | IRQF_DISABLED; + + mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!mem_res) { + pr_warning("isp1760: Memory resource not available\n"); + ret = -ENODEV; + goto out; + } + mem_size = resource_size(mem_res); + if (!request_mem_region(mem_res->start, mem_size, "isp1760")) { + pr_warning("isp1760: Cannot reserve the memory resource\n"); + ret = -EBUSY; + goto out; + } + + irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!irq_res) { + pr_warning("isp1760: IRQ resource not available\n"); + return -ENODEV; + } + irqflags |= irq_res->flags & IRQF_TRIGGER_MASK; + + hcd = isp1760_register(mem_res->start, mem_size, irq_res->start, + irqflags, &pdev->dev, dev_name(&pdev->dev), 0); + if (IS_ERR(hcd)) { + pr_warning("isp1760: Failed to register the HCD device\n"); + ret = -ENODEV; + goto cleanup; + } + + pr_info("ISP1760 USB device initialised\n"); + return ret; + +cleanup: + release_mem_region(mem_res->start, mem_size); +out: + return ret; +} + +static int __devexit isp1760_plat_remove(struct platform_device *pdev) +{ + struct resource *mem_res; + resource_size_t mem_size; + + mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + mem_size = resource_size(mem_res); + release_mem_region(mem_res->start, mem_size); + + return 0; +} + +static struct platform_driver isp1760_plat_driver = { + .probe = isp1760_plat_probe, + .remove = isp1760_plat_remove, + .driver = { + .name = "isp1760", + }, +}; + static int __init isp1760_init(void) { - int ret; + int ret, any_ret = -ENODEV; init_kmem_once(); + ret = platform_driver_register(&isp1760_plat_driver); + if (!ret) + any_ret = 0; #ifdef CONFIG_PPC_OF ret = of_register_platform_driver(&isp1760_of_driver); - if (ret) { - deinit_kmem_cache(); - return ret; - } + if (!ret) + any_ret = 0; #endif #ifdef CONFIG_PCI ret = pci_register_driver(&isp1761_pci_driver); - if (ret) - goto unreg_of; + if (!ret) + any_ret = 0; #endif - return ret; -#ifdef CONFIG_PCI -unreg_of: -#endif -#ifdef CONFIG_PPC_OF - of_unregister_platform_driver(&isp1760_of_driver); -#endif - deinit_kmem_cache(); - return ret; + if (any_ret) + deinit_kmem_cache(); + return any_ret; } module_init(isp1760_init); static void __exit isp1760_exit(void) { + platform_driver_unregister(&isp1760_plat_driver); #ifdef CONFIG_PPC_OF of_unregister_platform_driver(&isp1760_of_driver); #endif -- cgit v1.2.3 From 54a40a2b95ed088af6c6605b70ac9d53463c0ff7 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 13 Feb 2009 17:25:46 -0800 Subject: USB: serial: add symbol serial driver This is for the Symbol 6608 barcode scanner in a fake "HID" mode. Thanks to Dalibor Grgec for working with me to get this to start to work properly. Cc: Dalibor Grgec Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/Kconfig | 9 + drivers/usb/serial/Makefile | 1 + drivers/usb/serial/symbolserial.c | 340 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 350 insertions(+) create mode 100644 drivers/usb/serial/symbolserial.c diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index b361f05cafac..dbc0781a4163 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -515,6 +515,15 @@ config USB_SERIAL_SIERRAWIRELESS To compile this driver as a module, choose M here: the module will be called sierra. +config USB_SERIAL_SYMBOL + tristate "USB Symbol Barcode driver (serial mode)" + help + Say Y here if you want to use a Symbol USB Barcode device + in serial emulation mode. + + To compile this driver as a module, choose M here: the + module will be called symbolserial. + config USB_SERIAL_TI tristate "USB TI 3410/5052 Serial Driver" help diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index b75be91eb8f1..222939739ffe 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -49,6 +49,7 @@ obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o obj-$(CONFIG_USB_SERIAL_SIEMENS_MPI) += siemens_mpi.o obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS) += sierra.o obj-$(CONFIG_USB_SERIAL_SPCP8X5) += spcp8x5.o +obj-$(CONFIG_USB_SERIAL_SYMBOL) += symbolserial.o obj-$(CONFIG_USB_SERIAL_TI) += ti_usb_3410_5052.o obj-$(CONFIG_USB_SERIAL_VISOR) += visor.o obj-$(CONFIG_USB_SERIAL_WHITEHEAT) += whiteheat.o diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c new file mode 100644 index 000000000000..c5990fd88e2c --- /dev/null +++ b/drivers/usb/serial/symbolserial.c @@ -0,0 +1,340 @@ +/* + * Symbol USB barcode to serial driver + * + * Copyright (C) 2009 Greg Kroah-Hartman + * Copyright (C) 2009 Novell Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int debug; + +static struct usb_device_id id_table[] = { + { USB_DEVICE(0x05e0, 0x0600) }, + { }, +}; +MODULE_DEVICE_TABLE(usb, id_table); + +/* This structure holds all of the individual device information */ +struct symbol_private { + struct usb_device *udev; + struct usb_serial *serial; + struct usb_serial_port *port; + unsigned char *int_buffer; + struct urb *int_urb; + int buffer_size; + u8 bInterval; + u8 int_address; + spinlock_t lock; /* protects the following flags */ + bool throttled; + bool actually_throttled; + bool rts; +}; + +static void symbol_int_callback(struct urb *urb) +{ + struct symbol_private *priv = urb->context; + unsigned char *data = urb->transfer_buffer; + struct usb_serial_port *port = priv->port; + int status = urb->status; + struct tty_struct *tty; + int result; + int available_room = 0; + int data_length; + + dbg("%s - port %d", __func__, port->number); + + switch (status) { + case 0: + /* success */ + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", + __func__, status); + return; + default: + dbg("%s - nonzero urb status received: %d", + __func__, status); + goto exit; + } + + usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, + data); + + if (urb->actual_length > 1) { + data_length = urb->actual_length - 1; + + /* + * Data from the device comes with a 1 byte header: + * + * data... + * This is real data to be sent to the tty layer + * we pretty much just ignore the size and send everything + * else to the tty layer. + */ + tty = tty_port_tty_get(&port->port); + if (tty) { + available_room = tty_buffer_request_room(tty, + data_length); + if (available_room) { + tty_insert_flip_string(tty, &data[1], + available_room); + tty_flip_buffer_push(tty); + } + tty_kref_put(tty); + } + } else { + dev_dbg(&priv->udev->dev, + "Improper ammount of data received from the device, " + "%d bytes", urb->actual_length); + } + +exit: + spin_lock(&priv->lock); + + /* Continue trying to always read if we should */ + if (!priv->throttled) { + usb_fill_int_urb(priv->int_urb, priv->udev, + usb_rcvintpipe(priv->udev, + priv->int_address), + priv->int_buffer, priv->buffer_size, + symbol_int_callback, priv, priv->bInterval); + result = usb_submit_urb(priv->int_urb, GFP_ATOMIC); + if (result) + dev_err(&port->dev, + "%s - failed resubmitting read urb, error %d\n", + __func__, result); + } else + priv->actually_throttled = true; + spin_unlock(&priv->lock); +} + +static int symbol_open(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp) +{ + struct symbol_private *priv = usb_get_serial_data(port->serial); + unsigned long flags; + int result = 0; + + dbg("%s - port %d", __func__, port->number); + + spin_lock_irqsave(&priv->lock, flags); + priv->throttled = false; + priv->actually_throttled = false; + priv->port = port; + spin_unlock_irqrestore(&priv->lock, flags); + + /* + * Force low_latency on so that our tty_push actually forces the data + * through, otherwise it is scheduled, and with high data rates (like + * with OHCI) data can get lost. + */ + if (tty) + tty->low_latency = 1; + + /* Start reading from the device */ + usb_fill_int_urb(priv->int_urb, priv->udev, + usb_rcvintpipe(priv->udev, priv->int_address), + priv->int_buffer, priv->buffer_size, + symbol_int_callback, priv, priv->bInterval); + result = usb_submit_urb(priv->int_urb, GFP_KERNEL); + if (result) + dev_err(&port->dev, + "%s - failed resubmitting read urb, error %d\n", + __func__, result); + return result; +} + +static void symbol_close(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp) +{ + struct symbol_private *priv = usb_get_serial_data(port->serial); + + dbg("%s - port %d", __func__, port->number); + + /* shutdown our urbs */ + usb_kill_urb(priv->int_urb); +} + +static void symbol_throttle(struct tty_struct *tty) +{ + struct usb_serial_port *port = tty->driver_data; + struct symbol_private *priv = usb_get_serial_data(port->serial); + unsigned long flags; + + dbg("%s - port %d", __func__, port->number); + spin_lock_irqsave(&priv->lock, flags); + priv->throttled = true; + spin_unlock_irqrestore(&priv->lock, flags); +} + +static void symbol_unthrottle(struct tty_struct *tty) +{ + struct usb_serial_port *port = tty->driver_data; + struct symbol_private *priv = usb_get_serial_data(port->serial); + unsigned long flags; + int result; + + dbg("%s - port %d", __func__, port->number); + + spin_lock_irqsave(&priv->lock, flags); + priv->throttled = false; + priv->actually_throttled = false; + spin_unlock_irqrestore(&priv->lock, flags); + + priv->int_urb->dev = port->serial->dev; + result = usb_submit_urb(priv->int_urb, GFP_ATOMIC); + if (result) + dev_err(&port->dev, + "%s - failed submitting read urb, error %d\n", + __func__, result); +} + +static int symbol_startup(struct usb_serial *serial) +{ + struct symbol_private *priv; + struct usb_host_interface *intf; + int i; + int retval = -ENOMEM; + bool int_in_found = false; + + /* create our private serial structure */ + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (priv == NULL) { + dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__); + return -ENOMEM; + } + spin_lock_init(&priv->lock); + priv->serial = serial; + priv->port = serial->port[0]; + priv->udev = serial->dev; + + /* find our interrupt endpoint */ + intf = serial->interface->altsetting; + for (i = 0; i < intf->desc.bNumEndpoints; ++i) { + struct usb_endpoint_descriptor *endpoint; + + endpoint = &intf->endpoint[i].desc; + if (!usb_endpoint_is_int_in(endpoint)) + continue; + + priv->int_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!priv->int_urb) { + dev_err(&priv->udev->dev, "out of memory\n"); + goto error; + } + + priv->buffer_size = le16_to_cpu(endpoint->wMaxPacketSize) * 2; + priv->int_buffer = kmalloc(priv->buffer_size, GFP_KERNEL); + if (!priv->int_buffer) { + dev_err(&priv->udev->dev, "out of memory\n"); + goto error; + } + + priv->int_address = endpoint->bEndpointAddress; + priv->bInterval = endpoint->bInterval; + + /* set up our int urb */ + usb_fill_int_urb(priv->int_urb, priv->udev, + usb_rcvintpipe(priv->udev, + endpoint->bEndpointAddress), + priv->int_buffer, priv->buffer_size, + symbol_int_callback, priv, priv->bInterval); + + int_in_found = true; + break; + } + + if (!int_in_found) { + dev_err(&priv->udev->dev, + "Error - the proper endpoints were not found!\n"); + goto error; + } + + usb_set_serial_data(serial, priv); + return 0; + +error: + usb_free_urb(priv->int_urb); + kfree(priv->int_buffer); + kfree(priv); + return retval; +} + +static void symbol_shutdown(struct usb_serial *serial) +{ + struct symbol_private *priv = usb_get_serial_data(serial); + + dbg("%s", __func__); + + usb_kill_urb(priv->int_urb); + usb_free_urb(priv->int_urb); + kfree(priv->int_buffer); + kfree(priv); + usb_set_serial_data(serial, NULL); +} + +static struct usb_driver symbol_driver = { + .name = "symbol", + .probe = usb_serial_probe, + .disconnect = usb_serial_disconnect, + .id_table = id_table, + .no_dynamic_id = 1, +}; + +static struct usb_serial_driver symbol_device = { + .driver = { + .owner = THIS_MODULE, + .name = "symbol", + }, + .id_table = id_table, + .usb_driver = &symbol_driver, + .num_ports = 1, + .attach = symbol_startup, + .open = symbol_open, + .close = symbol_close, + .shutdown = symbol_shutdown, + .throttle = symbol_throttle, + .unthrottle = symbol_unthrottle, +}; + +static int __init symbol_init(void) +{ + int retval; + + retval = usb_serial_register(&symbol_device); + if (retval) + return retval; + retval = usb_register(&symbol_driver); + if (retval) + usb_serial_deregister(&symbol_device); + return retval; +} + +static void __exit symbol_exit(void) +{ + usb_deregister(&symbol_driver); + usb_serial_deregister(&symbol_device); +} + +module_init(symbol_init); +module_exit(symbol_exit); +MODULE_LICENSE("GPL"); + +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Debug enabled or not"); -- cgit v1.2.3 From 4d4ce1307aa39b44e2fed2e98ead01f985abb8d9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 17 Feb 2009 22:39:56 -0800 Subject: USB: serial: add qualcomm wireless modem driver Driver originally written by Qualcomm, but rewritten by me due to the totally different coding style. Cleaned up the probe logic to make a bit more sense, this is one wierd device. They could have prevented all of this by just writing sane firmware for the modem. Cc: Tamm Liu Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/Kconfig | 9 +++ drivers/usb/serial/Makefile | 1 + drivers/usb/serial/qcserial.c | 145 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 155 insertions(+) create mode 100644 drivers/usb/serial/qcserial.c diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index dbc0781a4163..4afe73e8ec4a 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -472,6 +472,15 @@ config USB_SERIAL_OTI6858 To compile this driver as a module, choose M here: the module will be called oti6858. +config USB_SERIAL_QUALCOMM + tristate "USB Qualcomm Serial modem" + help + Say Y here if you have a Qualcomm USB modem device. These are + usually wireless cellular modems. + + To compile this driver as a module, choose M here: the + module will be called qcserial. + config USB_SERIAL_SPCP8X5 tristate "USB SPCP8x5 USB To Serial Driver" help diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index 222939739ffe..94043babe1d3 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -45,6 +45,7 @@ obj-$(CONFIG_USB_SERIAL_OPTICON) += opticon.o obj-$(CONFIG_USB_SERIAL_OPTION) += option.o obj-$(CONFIG_USB_SERIAL_OTI6858) += oti6858.o obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o +obj-$(CONFIG_USB_SERIAL_QUALCOMM) += qcserial.o obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o obj-$(CONFIG_USB_SERIAL_SIEMENS_MPI) += siemens_mpi.o obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS) += sierra.o diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c new file mode 100644 index 000000000000..6c6add50feaa --- /dev/null +++ b/drivers/usb/serial/qcserial.c @@ -0,0 +1,145 @@ +/* + * Qualcomm Serial USB driver + * + * Copyright (c) 2008 QUALCOMM Incorporated. + * Copyright (c) 2009 Greg Kroah-Hartman + * Copyright (c) 2009 Novell Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include + +#define DRIVER_AUTHOR "Qualcomm Inc" +#define DRIVER_DESC "Qualcomm USB Serial driver" + +static int debug; + +static struct usb_device_id id_table[] = { + {USB_DEVICE(0x05c6, 0x9211)}, /* Acer Gobi QDL device */ + {USB_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, id_table); + +static struct usb_driver qcdriver = { + .name = "qcserial", + .probe = usb_serial_probe, + .disconnect = usb_serial_disconnect, + .id_table = id_table, + .suspend = usb_serial_suspend, + .resume = usb_serial_resume, + .supports_autosuspend = true, +}; + +static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) +{ + int retval = -ENODEV; + __u8 nintf; + __u8 ifnum; + + dbg("%s", __func__); + + nintf = serial->dev->actconfig->desc.bNumInterfaces; + dbg("Num Interfaces = %d", nintf); + ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber; + dbg("This Interface = %d", ifnum); + + switch (nintf) { + case 1: + /* QDL mode */ + if (serial->interface->num_altsetting == 2) { + struct usb_host_interface *intf; + + intf = &serial->interface->altsetting[1]; + if (intf->desc.bNumEndpoints == 2) { + if (usb_endpoint_is_bulk_in(&intf->endpoint[0].desc) && + usb_endpoint_is_bulk_out(&intf->endpoint[1].desc)) { + dbg("QDL port found"); + retval = usb_set_interface(serial->dev, ifnum, 1); + if (retval < 0) { + dev_err(&serial->dev->dev, + "Could not set interface, error %d\n", + retval); + retval = -ENODEV; + } + return retval; + } + } + } + break; + + case 4: + /* Composite mode */ + if (ifnum == 2) { + dbg("Modem port found"); + retval = usb_set_interface(serial->dev, ifnum, 0); + if (retval < 0) { + dev_err(&serial->dev->dev, + "Could not set interface, error %d\n", + retval); + retval = -ENODEV; + } + return retval; + } + break; + + default: + dev_err(&serial->dev->dev, + "unknown number of interfaces: %d\n", nintf); + return -ENODEV; + } + + return retval; +} + +static struct usb_serial_driver qcdevice = { + .driver = { + .owner = THIS_MODULE, + .name = "qcserial", + }, + .description = "Qualcomm USB modem", + .id_table = id_table, + .usb_driver = &qcdriver, + .num_ports = 1, + .probe = qcprobe, +}; + +static int __init qcinit(void) +{ + int retval; + + retval = usb_serial_register(&qcdevice); + if (retval) + return retval; + + retval = usb_register(&qcdriver); + if (retval) { + usb_serial_deregister(&qcdevice); + return retval; + } + + return 0; +} + +static void __exit qcexit(void) +{ + usb_deregister(&qcdriver); + usb_serial_deregister(&qcdevice); +} + +module_init(qcinit); +module_exit(qcexit); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL v2"); + +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Debug enabled or not"); -- cgit v1.2.3 From 78782222908c7b4d8349b73bd5ce3133c4be0840 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Wed, 11 Feb 2009 14:11:36 -0800 Subject: USB: replace uses of __constant_{endian} The base versions handle constant folding now. Signed-off-by: Harvey Harrison Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 2 +- drivers/usb/core/hub.c | 8 ++++---- drivers/usb/gadget/amd5536udc.c | 2 +- drivers/usb/gadget/atmel_usba_udc.c | 20 ++++++++++---------- drivers/usb/gadget/cdc2.c | 8 ++++---- drivers/usb/gadget/dummy_hcd.c | 2 +- drivers/usb/gadget/epautoconf.c | 2 +- drivers/usb/gadget/ether.c | 8 ++++---- drivers/usb/gadget/f_acm.c | 10 +++++----- drivers/usb/gadget/f_ecm.c | 16 ++++++++-------- drivers/usb/gadget/f_loopback.c | 4 ++-- drivers/usb/gadget/f_obex.c | 8 ++++---- drivers/usb/gadget/f_phonet.c | 8 ++++---- drivers/usb/gadget/f_rndis.c | 10 +++++----- drivers/usb/gadget/f_serial.c | 4 ++-- drivers/usb/gadget/f_sourcesink.c | 4 ++-- drivers/usb/gadget/f_subset.c | 14 +++++++------- drivers/usb/gadget/file_storage.c | 22 +++++++++++----------- drivers/usb/gadget/gmidi.c | 16 ++++++++-------- drivers/usb/gadget/goku_udc.c | 8 ++++---- drivers/usb/gadget/inode.c | 4 ++-- drivers/usb/gadget/net2280.c | 16 ++++++++-------- drivers/usb/gadget/printer.c | 18 +++++++++--------- drivers/usb/gadget/serial.c | 12 ++++++------ drivers/usb/gadget/u_serial.c | 2 +- drivers/usb/gadget/zero.c | 8 ++++---- drivers/usb/host/ehci-sched.c | 2 +- drivers/usb/host/ehci.h | 2 +- drivers/usb/host/isp1760-hcd.c | 4 ++-- drivers/usb/host/oxu210hp-hcd.c | 22 +++++++++++----------- drivers/usb/host/oxu210hp.h | 8 ++++---- drivers/usb/host/uhci-hcd.h | 10 +++++----- drivers/usb/host/uhci-q.c | 10 +++++----- drivers/usb/image/mdc800.c | 8 ++++---- drivers/usb/musb/musb_virthub.c | 2 +- 35 files changed, 152 insertions(+), 152 deletions(-) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 3c711db55d86..0eee32a65e23 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -901,7 +901,7 @@ static int register_root_hub(struct usb_hcd *hcd) mutex_lock(&usb_bus_list_lock); - usb_dev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64); + usb_dev->ep0.desc.wMaxPacketSize = cpu_to_le16(64); retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE); if (retval != sizeof usb_dev->descriptor) { mutex_unlock(&usb_bus_list_lock); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index cd50d86029e7..7e33d63ab92f 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2471,20 +2471,20 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, */ switch (udev->speed) { case USB_SPEED_VARIABLE: /* fixed at 512 */ - udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(512); + udev->ep0.desc.wMaxPacketSize = cpu_to_le16(512); break; case USB_SPEED_HIGH: /* fixed at 64 */ - udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64); + udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64); break; case USB_SPEED_FULL: /* 8, 16, 32, or 64 */ /* to determine the ep0 maxpacket size, try to read * the device descriptor to get bMaxPacketSize0 and * then correct our initial guess. */ - udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64); + udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64); break; case USB_SPEED_LOW: /* fixed at 8 */ - udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(8); + udev->ep0.desc.wMaxPacketSize = cpu_to_le16(8); break; default: goto fail; diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index abf8192f89e8..826f3adde5d8 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -551,7 +551,7 @@ udc_alloc_request(struct usb_ep *usbep, gfp_t gfp) dma_desc->status = AMD_ADDBITS(dma_desc->status, UDC_DMA_STP_STS_BS_HOST_BUSY, UDC_DMA_STP_STS_BS); - dma_desc->bufptr = __constant_cpu_to_le32(DMA_DONT_USE); + dma_desc->bufptr = cpu_to_le32(DMA_DONT_USE); req->td_data = dma_desc; req->td_data_last = NULL; req->chain_len = 1; diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c index 65b03e3445a1..c22fab164113 100644 --- a/drivers/usb/gadget/atmel_usba_udc.c +++ b/drivers/usb/gadget/atmel_usba_udc.c @@ -1017,7 +1017,7 @@ static struct usb_endpoint_descriptor usba_ep0_desc = { .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = 0, .bmAttributes = USB_ENDPOINT_XFER_CONTROL, - .wMaxPacketSize = __constant_cpu_to_le16(64), + .wMaxPacketSize = cpu_to_le16(64), /* FIXME: I have no idea what to put here */ .bInterval = 1, }; @@ -1207,21 +1207,21 @@ static int do_test_mode(struct usba_udc *udc) /* Avoid overly long expressions */ static inline bool feature_is_dev_remote_wakeup(struct usb_ctrlrequest *crq) { - if (crq->wValue == __constant_cpu_to_le16(USB_DEVICE_REMOTE_WAKEUP)) + if (crq->wValue == cpu_to_le16(USB_DEVICE_REMOTE_WAKEUP)) return true; return false; } static inline bool feature_is_dev_test_mode(struct usb_ctrlrequest *crq) { - if (crq->wValue == __constant_cpu_to_le16(USB_DEVICE_TEST_MODE)) + if (crq->wValue == cpu_to_le16(USB_DEVICE_TEST_MODE)) return true; return false; } static inline bool feature_is_ep_halt(struct usb_ctrlrequest *crq) { - if (crq->wValue == __constant_cpu_to_le16(USB_ENDPOINT_HALT)) + if (crq->wValue == cpu_to_le16(USB_ENDPOINT_HALT)) return true; return false; } @@ -1239,7 +1239,7 @@ static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep, status = cpu_to_le16(udc->devstatus); } else if (crq->bRequestType == (USB_DIR_IN | USB_RECIP_INTERFACE)) { - status = __constant_cpu_to_le16(0); + status = cpu_to_le16(0); } else if (crq->bRequestType == (USB_DIR_IN | USB_RECIP_ENDPOINT)) { struct usba_ep *target; @@ -1250,12 +1250,12 @@ static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep, status = 0; if (is_stalled(udc, target)) - status |= __constant_cpu_to_le16(1); + status |= cpu_to_le16(1); } else goto delegate; /* Write directly to the FIFO. No queueing is done. */ - if (crq->wLength != __constant_cpu_to_le16(sizeof(status))) + if (crq->wLength != cpu_to_le16(sizeof(status))) goto stall; ep->state = DATA_STAGE_IN; __raw_writew(status, ep->fifo); @@ -1274,7 +1274,7 @@ static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep, } else if (crq->bRequestType == USB_RECIP_ENDPOINT) { struct usba_ep *target; - if (crq->wLength != __constant_cpu_to_le16(0) + if (crq->wLength != cpu_to_le16(0) || !feature_is_ep_halt(crq)) goto stall; target = get_ep_by_addr(udc, le16_to_cpu(crq->wIndex)); @@ -1308,7 +1308,7 @@ static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep, } else if (crq->bRequestType == USB_RECIP_ENDPOINT) { struct usba_ep *target; - if (crq->wLength != __constant_cpu_to_le16(0) + if (crq->wLength != cpu_to_le16(0) || !feature_is_ep_halt(crq)) goto stall; @@ -1514,7 +1514,7 @@ restart: */ ep->state = DATA_STAGE_IN; } else { - if (crq.crq.wLength != __constant_cpu_to_le16(0)) + if (crq.crq.wLength != cpu_to_le16(0)) ep->state = DATA_STAGE_OUT; else ep->state = STATUS_STAGE_IN; diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c index 5495b171cf29..928137d3dbdc 100644 --- a/drivers/usb/gadget/cdc2.c +++ b/drivers/usb/gadget/cdc2.c @@ -66,7 +66,7 @@ static struct usb_device_descriptor device_desc = { .bLength = sizeof device_desc, .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = __constant_cpu_to_le16(0x0200), + .bcdUSB = cpu_to_le16(0x0200), .bDeviceClass = USB_CLASS_COMM, .bDeviceSubClass = 0, @@ -74,8 +74,8 @@ static struct usb_device_descriptor device_desc = { /* .bMaxPacketSize0 = f(hardware) */ /* Vendor and product id can be overridden by module parameters. */ - .idVendor = __constant_cpu_to_le16(CDC_VENDOR_NUM), - .idProduct = __constant_cpu_to_le16(CDC_PRODUCT_NUM), + .idVendor = cpu_to_le16(CDC_VENDOR_NUM), + .idProduct = cpu_to_le16(CDC_PRODUCT_NUM), /* .bcdDevice = f(hardware) */ /* .iManufacturer = DYNAMIC */ /* .iProduct = DYNAMIC */ @@ -193,7 +193,7 @@ static int __init cdc_bind(struct usb_composite_dev *cdev) gadget->name, cdc_config_driver.label); device_desc.bcdDevice = - __constant_cpu_to_le16(0x0300 | 0x0099); + cpu_to_le16(0x0300 | 0x0099); } diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 9064696636ac..3b42888b72f8 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -1626,7 +1626,7 @@ static int dummy_hub_control ( hub_descriptor ((struct usb_hub_descriptor *) buf); break; case GetHubStatus: - *(__le32 *) buf = __constant_cpu_to_le32 (0); + *(__le32 *) buf = cpu_to_le32 (0); break; case GetPortStatus: if (wIndex != 1) diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c index a36b1175b18d..cd0914ec898e 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c @@ -148,7 +148,7 @@ ep_matches ( return 0; /* BOTH: "high bandwidth" works only at high speed */ - if ((desc->wMaxPacketSize & __constant_cpu_to_le16(3<<11))) { + if ((desc->wMaxPacketSize & cpu_to_le16(3<<11))) { if (!gadget->is_dualspeed) return 0; /* configure your hardware with enough buffering!! */ diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 37252d0012a7..d006dc652e02 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -156,7 +156,7 @@ static struct usb_device_descriptor device_desc = { .bLength = sizeof device_desc, .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = __constant_cpu_to_le16 (0x0200), + .bcdUSB = cpu_to_le16 (0x0200), .bDeviceClass = USB_CLASS_COMM, .bDeviceSubClass = 0, @@ -167,8 +167,8 @@ static struct usb_device_descriptor device_desc = { * we support. (As does bNumConfigurations.) These values can * also be overridden by module parameters. */ - .idVendor = __constant_cpu_to_le16 (CDC_VENDOR_NUM), - .idProduct = __constant_cpu_to_le16 (CDC_PRODUCT_NUM), + .idVendor = cpu_to_le16 (CDC_VENDOR_NUM), + .idProduct = cpu_to_le16 (CDC_PRODUCT_NUM), /* .bcdDevice = f(hardware) */ /* .iManufacturer = DYNAMIC */ /* .iProduct = DYNAMIC */ @@ -318,7 +318,7 @@ static int __init eth_bind(struct usb_composite_dev *cdev) gadget->name, eth_config_driver.label); device_desc.bcdDevice = - __constant_cpu_to_le16(0x0300 | 0x0099); + cpu_to_le16(0x0300 | 0x0099); } diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c index c1d34df0b157..7953948bfe4a 100644 --- a/drivers/usb/gadget/f_acm.c +++ b/drivers/usb/gadget/f_acm.c @@ -125,7 +125,7 @@ static struct usb_cdc_header_desc acm_header_desc __initdata = { .bLength = sizeof(acm_header_desc), .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_HEADER_TYPE, - .bcdCDC = __constant_cpu_to_le16(0x0110), + .bcdCDC = cpu_to_le16(0x0110), }; static struct usb_cdc_call_mgmt_descriptor @@ -159,7 +159,7 @@ static struct usb_endpoint_descriptor acm_fs_notify_desc __initdata = { .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(GS_NOTIFY_MAXPACKET), + .wMaxPacketSize = cpu_to_le16(GS_NOTIFY_MAXPACKET), .bInterval = 1 << GS_LOG2_NOTIFY_INTERVAL, }; @@ -197,7 +197,7 @@ static struct usb_endpoint_descriptor acm_hs_notify_desc __initdata = { .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(GS_NOTIFY_MAXPACKET), + .wMaxPacketSize = cpu_to_le16(GS_NOTIFY_MAXPACKET), .bInterval = GS_LOG2_NOTIFY_INTERVAL+4, }; @@ -205,14 +205,14 @@ static struct usb_endpoint_descriptor acm_hs_in_desc __initdata = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_endpoint_descriptor acm_hs_out_desc __initdata = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_descriptor_header *acm_hs_function[] __initdata = { diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/f_ecm.c index 4ae579948e54..ecf5bdd0ae06 100644 --- a/drivers/usb/gadget/f_ecm.c +++ b/drivers/usb/gadget/f_ecm.c @@ -130,7 +130,7 @@ static struct usb_cdc_header_desc ecm_header_desc __initdata = { .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_HEADER_TYPE, - .bcdCDC = __constant_cpu_to_le16(0x0110), + .bcdCDC = cpu_to_le16(0x0110), }; static struct usb_cdc_union_desc ecm_union_desc __initdata = { @@ -148,9 +148,9 @@ static struct usb_cdc_ether_desc ecm_desc __initdata = { /* this descriptor actually adds value, surprise! */ /* .iMACAddress = DYNAMIC */ - .bmEthernetStatistics = __constant_cpu_to_le32(0), /* no statistics */ - .wMaxSegmentSize = __constant_cpu_to_le16(ETH_FRAME_LEN), - .wNumberMCFilters = __constant_cpu_to_le16(0), + .bmEthernetStatistics = cpu_to_le32(0), /* no statistics */ + .wMaxSegmentSize = cpu_to_le16(ETH_FRAME_LEN), + .wNumberMCFilters = cpu_to_le16(0), .bNumberPowerFilters = 0, }; @@ -192,7 +192,7 @@ static struct usb_endpoint_descriptor fs_ecm_notify_desc __initdata = { .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(ECM_STATUS_BYTECOUNT), + .wMaxPacketSize = cpu_to_le16(ECM_STATUS_BYTECOUNT), .bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC, }; @@ -236,7 +236,7 @@ static struct usb_endpoint_descriptor hs_ecm_notify_desc __initdata = { .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(ECM_STATUS_BYTECOUNT), + .wMaxPacketSize = cpu_to_le16(ECM_STATUS_BYTECOUNT), .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4, }; static struct usb_endpoint_descriptor hs_ecm_in_desc __initdata = { @@ -245,7 +245,7 @@ static struct usb_endpoint_descriptor hs_ecm_in_desc __initdata = { .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_endpoint_descriptor hs_ecm_out_desc __initdata = { @@ -254,7 +254,7 @@ static struct usb_endpoint_descriptor hs_ecm_out_desc __initdata = { .bEndpointAddress = USB_DIR_OUT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_descriptor_header *ecm_hs_function[] __initdata = { diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c index 8affe1dfc2c1..83301bdcdd1a 100644 --- a/drivers/usb/gadget/f_loopback.c +++ b/drivers/usb/gadget/f_loopback.c @@ -100,7 +100,7 @@ static struct usb_endpoint_descriptor hs_loop_source_desc = { .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_endpoint_descriptor hs_loop_sink_desc = { @@ -108,7 +108,7 @@ static struct usb_endpoint_descriptor hs_loop_sink_desc = { .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_descriptor_header *hs_loopback_descs[] = { diff --git a/drivers/usb/gadget/f_obex.c b/drivers/usb/gadget/f_obex.c index 38aa896cc5db..46d6266f30ec 100644 --- a/drivers/usb/gadget/f_obex.c +++ b/drivers/usb/gadget/f_obex.c @@ -123,7 +123,7 @@ static struct usb_cdc_header_desc obex_cdc_header_desc __initdata = { .bLength = sizeof(obex_cdc_header_desc), .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_HEADER_TYPE, - .bcdCDC = __constant_cpu_to_le16(0x0120), + .bcdCDC = cpu_to_le16(0x0120), }; static struct usb_cdc_union_desc obex_cdc_union_desc __initdata = { @@ -138,7 +138,7 @@ static struct usb_cdc_obex_desc obex_desc __initdata = { .bLength = sizeof(obex_desc), .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_OBEX_TYPE, - .bcdVersion = __constant_cpu_to_le16(0x0100), + .bcdVersion = cpu_to_le16(0x0100), }; /* High-Speed Support */ @@ -149,7 +149,7 @@ static struct usb_endpoint_descriptor obex_hs_ep_out_desc __initdata = { .bEndpointAddress = USB_DIR_OUT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_endpoint_descriptor obex_hs_ep_in_desc __initdata = { @@ -158,7 +158,7 @@ static struct usb_endpoint_descriptor obex_hs_ep_in_desc __initdata = { .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_descriptor_header *hs_function[] __initdata = { diff --git a/drivers/usb/gadget/f_phonet.c b/drivers/usb/gadget/f_phonet.c index c0916c7b217e..c1abeb89b413 100644 --- a/drivers/usb/gadget/f_phonet.c +++ b/drivers/usb/gadget/f_phonet.c @@ -79,7 +79,7 @@ pn_header_desc = { .bLength = sizeof pn_header_desc, .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_HEADER_TYPE, - .bcdCDC = __constant_cpu_to_le16(0x0110), + .bcdCDC = cpu_to_le16(0x0110), }; static const struct usb_cdc_header_desc @@ -87,7 +87,7 @@ pn_phonet_desc = { .bLength = sizeof pn_phonet_desc, .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_PHONET_TYPE, - .bcdCDC = __constant_cpu_to_le16(0x1505), /* ??? */ + .bcdCDC = cpu_to_le16(0x1505), /* ??? */ }; static struct usb_cdc_union_desc @@ -138,7 +138,7 @@ pn_hs_sink_desc = { .bEndpointAddress = USB_DIR_OUT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_endpoint_descriptor @@ -157,7 +157,7 @@ pn_hs_source_desc = { .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_descriptor_header *fs_pn_function[] = { diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c index 3a8bb53fc473..3122fb9f3d59 100644 --- a/drivers/usb/gadget/f_rndis.c +++ b/drivers/usb/gadget/f_rndis.c @@ -137,7 +137,7 @@ static struct usb_cdc_header_desc header_desc __initdata = { .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_HEADER_TYPE, - .bcdCDC = __constant_cpu_to_le16(0x0110), + .bcdCDC = cpu_to_le16(0x0110), }; static struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor __initdata = { @@ -187,7 +187,7 @@ static struct usb_endpoint_descriptor fs_notify_desc __initdata = { .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(STATUS_BYTECOUNT), + .wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT), .bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC, }; @@ -230,7 +230,7 @@ static struct usb_endpoint_descriptor hs_notify_desc __initdata = { .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(STATUS_BYTECOUNT), + .wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT), .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4, }; static struct usb_endpoint_descriptor hs_in_desc __initdata = { @@ -239,7 +239,7 @@ static struct usb_endpoint_descriptor hs_in_desc __initdata = { .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_endpoint_descriptor hs_out_desc __initdata = { @@ -248,7 +248,7 @@ static struct usb_endpoint_descriptor hs_out_desc __initdata = { .bEndpointAddress = USB_DIR_OUT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_descriptor_header *eth_hs_function[] __initdata = { diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/f_serial.c index fe5674db344b..db0aa93606ef 100644 --- a/drivers/usb/gadget/f_serial.c +++ b/drivers/usb/gadget/f_serial.c @@ -89,14 +89,14 @@ static struct usb_endpoint_descriptor gser_hs_in_desc __initdata = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_endpoint_descriptor gser_hs_out_desc __initdata = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_descriptor_header *gser_hs_function[] __initdata = { diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c index dc84d26d2835..6aca5c81414a 100644 --- a/drivers/usb/gadget/f_sourcesink.c +++ b/drivers/usb/gadget/f_sourcesink.c @@ -118,7 +118,7 @@ static struct usb_endpoint_descriptor hs_source_desc = { .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_endpoint_descriptor hs_sink_desc = { @@ -126,7 +126,7 @@ static struct usb_endpoint_descriptor hs_sink_desc = { .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_descriptor_header *hs_source_sink_descs[] = { diff --git a/drivers/usb/gadget/f_subset.c b/drivers/usb/gadget/f_subset.c index fe1832875771..a9c98fdb626d 100644 --- a/drivers/usb/gadget/f_subset.c +++ b/drivers/usb/gadget/f_subset.c @@ -108,7 +108,7 @@ static struct usb_cdc_header_desc mdlm_header_desc __initdata = { .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_HEADER_TYPE, - .bcdCDC = __constant_cpu_to_le16(0x0110), + .bcdCDC = cpu_to_le16(0x0110), }; static struct usb_cdc_mdlm_desc mdlm_desc __initdata = { @@ -116,7 +116,7 @@ static struct usb_cdc_mdlm_desc mdlm_desc __initdata = { .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_MDLM_TYPE, - .bcdVersion = __constant_cpu_to_le16(0x0100), + .bcdVersion = cpu_to_le16(0x0100), .bGUID = { 0x5d, 0x34, 0xcf, 0x66, 0x11, 0x18, 0x11, 0xd6, 0xa2, 0x1a, 0x00, 0x01, 0x02, 0xca, 0x9a, 0x7f, @@ -144,9 +144,9 @@ static struct usb_cdc_ether_desc ether_desc __initdata = { /* this descriptor actually adds value, surprise! */ /* .iMACAddress = DYNAMIC */ - .bmEthernetStatistics = __constant_cpu_to_le32(0), /* no statistics */ - .wMaxSegmentSize = __constant_cpu_to_le16(ETH_FRAME_LEN), - .wNumberMCFilters = __constant_cpu_to_le16(0), + .bmEthernetStatistics = cpu_to_le32(0), /* no statistics */ + .wMaxSegmentSize = cpu_to_le16(ETH_FRAME_LEN), + .wNumberMCFilters = cpu_to_le16(0), .bNumberPowerFilters = 0, }; @@ -186,7 +186,7 @@ static struct usb_endpoint_descriptor hs_subset_in_desc __initdata = { .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_endpoint_descriptor hs_subset_out_desc __initdata = { @@ -194,7 +194,7 @@ static struct usb_endpoint_descriptor hs_subset_out_desc __initdata = { .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_descriptor_header *hs_eth_function[] __initdata = { diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index 1ab9dac7e12d..d3c2464dee82 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -847,13 +847,13 @@ device_desc = { .bLength = sizeof device_desc, .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = __constant_cpu_to_le16(0x0200), + .bcdUSB = cpu_to_le16(0x0200), .bDeviceClass = USB_CLASS_PER_INTERFACE, /* The next three values can be overridden by module parameters */ - .idVendor = __constant_cpu_to_le16(DRIVER_VENDOR_ID), - .idProduct = __constant_cpu_to_le16(DRIVER_PRODUCT_ID), - .bcdDevice = __constant_cpu_to_le16(0xffff), + .idVendor = cpu_to_le16(DRIVER_VENDOR_ID), + .idProduct = cpu_to_le16(DRIVER_PRODUCT_ID), + .bcdDevice = cpu_to_le16(0xffff), .iManufacturer = STRING_MANUFACTURER, .iProduct = STRING_PRODUCT, @@ -926,7 +926,7 @@ fs_intr_in_desc = { .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(2), + .wMaxPacketSize = cpu_to_le16(2), .bInterval = 32, // frames -> 32 ms }; @@ -954,7 +954,7 @@ dev_qualifier = { .bLength = sizeof dev_qualifier, .bDescriptorType = USB_DT_DEVICE_QUALIFIER, - .bcdUSB = __constant_cpu_to_le16(0x0200), + .bcdUSB = cpu_to_le16(0x0200), .bDeviceClass = USB_CLASS_PER_INTERFACE, .bNumConfigurations = 1, @@ -967,7 +967,7 @@ hs_bulk_in_desc = { /* bEndpointAddress copied from fs_bulk_in_desc during fsg_bind() */ .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_endpoint_descriptor @@ -977,7 +977,7 @@ hs_bulk_out_desc = { /* bEndpointAddress copied from fs_bulk_out_desc during fsg_bind() */ .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), .bInterval = 1, // NAK every 1 uframe }; @@ -988,7 +988,7 @@ hs_intr_in_desc = { /* bEndpointAddress copied from fs_intr_in_desc during fsg_bind() */ .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(2), + .wMaxPacketSize = cpu_to_le16(2), .bInterval = 9, // 2**(9-1) = 256 uframes -> 32 ms }; @@ -2646,7 +2646,7 @@ static int send_status(struct fsg_dev *fsg) struct bulk_cs_wrap *csw = bh->buf; /* Store and send the Bulk-only CSW */ - csw->Signature = __constant_cpu_to_le32(USB_BULK_CS_SIG); + csw->Signature = cpu_to_le32(USB_BULK_CS_SIG); csw->Tag = fsg->tag; csw->Residue = cpu_to_le32(fsg->residue); csw->Status = status; @@ -3089,7 +3089,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) /* Is the CBW valid? */ if (req->actual != USB_BULK_CB_WRAP_LEN || - cbw->Signature != __constant_cpu_to_le32( + cbw->Signature != cpu_to_le32( USB_BULK_CB_SIG)) { DBG(fsg, "invalid CBW: len %u sig 0x%x\n", req->actual, diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c index 60d3f9e9b51f..bb738bc96d4a 100644 --- a/drivers/usb/gadget/gmidi.c +++ b/drivers/usb/gadget/gmidi.c @@ -199,10 +199,10 @@ DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(1); static struct usb_device_descriptor device_desc = { .bLength = USB_DT_DEVICE_SIZE, .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = __constant_cpu_to_le16(0x0200), + .bcdUSB = cpu_to_le16(0x0200), .bDeviceClass = USB_CLASS_PER_INTERFACE, - .idVendor = __constant_cpu_to_le16(DRIVER_VENDOR_NUM), - .idProduct = __constant_cpu_to_le16(DRIVER_PRODUCT_NUM), + .idVendor = cpu_to_le16(DRIVER_VENDOR_NUM), + .idProduct = cpu_to_le16(DRIVER_PRODUCT_NUM), .iManufacturer = STRING_MANUFACTURER, .iProduct = STRING_PRODUCT, .bNumConfigurations = 1, @@ -241,8 +241,8 @@ static const struct usb_ac_header_descriptor_1 ac_header_desc = { .bLength = USB_DT_AC_HEADER_SIZE(1), .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubtype = USB_MS_HEADER, - .bcdADC = __constant_cpu_to_le16(0x0100), - .wTotalLength = __constant_cpu_to_le16(USB_DT_AC_HEADER_SIZE(1)), + .bcdADC = cpu_to_le16(0x0100), + .wTotalLength = cpu_to_le16(USB_DT_AC_HEADER_SIZE(1)), .bInCollection = 1, .baInterfaceNr = { [0] = GMIDI_MS_INTERFACE, @@ -265,8 +265,8 @@ static const struct usb_ms_header_descriptor ms_header_desc = { .bLength = USB_DT_MS_HEADER_SIZE, .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubtype = USB_MS_HEADER, - .bcdMSC = __constant_cpu_to_le16(0x0100), - .wTotalLength = __constant_cpu_to_le16(USB_DT_MS_HEADER_SIZE + .bcdMSC = cpu_to_le16(0x0100), + .wTotalLength = cpu_to_le16(USB_DT_MS_HEADER_SIZE + 2*USB_DT_MIDI_IN_SIZE + 2*USB_DT_MIDI_OUT_SIZE(1)), }; @@ -1227,7 +1227,7 @@ autoconf_fail: */ pr_warning("%s: controller '%s' not recognized\n", shortname, gadget->name); - device_desc.bcdDevice = __constant_cpu_to_le16(0x9999); + device_desc.bcdDevice = cpu_to_le16(0x9999); } diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index 63419c4d503c..de010c939dbb 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c @@ -1472,7 +1472,7 @@ static void ep0_setup(struct goku_udc *dev) /* active endpoint */ if (tmp > 3 || (!dev->ep[tmp].desc && tmp != 0)) goto stall; - if (ctrl.wIndex & __constant_cpu_to_le16( + if (ctrl.wIndex & cpu_to_le16( USB_DIR_IN)) { if (!dev->ep[tmp].is_in) goto stall; @@ -1480,7 +1480,7 @@ static void ep0_setup(struct goku_udc *dev) if (dev->ep[tmp].is_in) goto stall; } - if (ctrl.wValue != __constant_cpu_to_le16( + if (ctrl.wValue != cpu_to_le16( USB_ENDPOINT_HALT)) goto stall; if (tmp) @@ -1493,7 +1493,7 @@ succeed: return; case USB_RECIP_DEVICE: /* device remote wakeup: always clear */ - if (ctrl.wValue != __constant_cpu_to_le16(1)) + if (ctrl.wValue != cpu_to_le16(1)) goto stall; VDBG(dev, "clear dev remote wakeup\n"); goto succeed; @@ -1519,7 +1519,7 @@ succeed: dev->req_config = (ctrl.bRequest == USB_REQ_SET_CONFIGURATION && ctrl.bRequestType == USB_RECIP_DEVICE); if (unlikely(dev->req_config)) - dev->configured = (ctrl.wValue != __constant_cpu_to_le16(0)); + dev->configured = (ctrl.wValue != cpu_to_le16(0)); /* delegate everything to the gadget driver. * it may respond after this irq handler returns. diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index 317b48fdbf01..d20937f28a19 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -1334,7 +1334,7 @@ static void make_qualifier (struct dev_data *dev) qual.bLength = sizeof qual; qual.bDescriptorType = USB_DT_DEVICE_QUALIFIER; - qual.bcdUSB = __constant_cpu_to_le16 (0x0200); + qual.bcdUSB = cpu_to_le16 (0x0200); desc = dev->dev; qual.bDeviceClass = desc->bDeviceClass; @@ -1908,7 +1908,7 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) || dev->dev->bNumConfigurations != 1) goto fail; dev->dev->bNumConfigurations = 1; - dev->dev->bcdUSB = __constant_cpu_to_le16 (0x0200); + dev->dev->bcdUSB = cpu_to_le16 (0x0200); /* triggers gadgetfs_bind(); then we can enumerate. */ spin_unlock_irq (&dev->lock); diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 12c6d83b218c..9498be87a724 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -142,8 +142,8 @@ static char *type_string (u8 bmAttributes) #include "net2280.h" -#define valid_bit __constant_cpu_to_le32 (1 << VALID_BIT) -#define dma_done_ie __constant_cpu_to_le32 (1 << DMA_DONE_INTERRUPT_ENABLE) +#define valid_bit cpu_to_le32 (1 << VALID_BIT) +#define dma_done_ie cpu_to_le32 (1 << DMA_DONE_INTERRUPT_ENABLE) /*-------------------------------------------------------------------------*/ @@ -425,7 +425,7 @@ net2280_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags) return NULL; } td->dmacount = 0; /* not VALID */ - td->dmaaddr = __constant_cpu_to_le32 (DMA_ADDR_INVALID); + td->dmaaddr = cpu_to_le32 (DMA_ADDR_INVALID); td->dmadesc = td->dmaaddr; req->td = td; } @@ -775,7 +775,7 @@ static void start_dma (struct net2280_ep *ep, struct net2280_request *req) fill_dma_desc (ep, req, 1); if (!use_dma_chaining) - req->td->dmacount |= __constant_cpu_to_le32 (1 << END_OF_CHAIN); + req->td->dmacount |= cpu_to_le32 (1 << END_OF_CHAIN); start_queue (ep, tmp, req->td_dma); } @@ -2407,9 +2407,9 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat) if (readl (&e->regs->ep_rsp) & (1 << SET_ENDPOINT_HALT)) - status = __constant_cpu_to_le32 (1); + status = cpu_to_le32 (1); else - status = __constant_cpu_to_le32 (0); + status = cpu_to_le32 (0); /* don't bother with a request object! */ writel (0, &dev->epregs [0].ep_irqenb); @@ -2667,7 +2667,7 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat) req = list_entry (ep->queue.next, struct net2280_request, queue); dmacount = req->td->dmacount; - dmacount &= __constant_cpu_to_le32 ( + dmacount &= cpu_to_le32 ( (1 << VALID_BIT) | DMA_BYTE_COUNT_MASK); if (dmacount && (dmacount & valid_bit) == 0) @@ -2881,7 +2881,7 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) goto done; } td->dmacount = 0; /* not VALID */ - td->dmaaddr = __constant_cpu_to_le32 (DMA_ADDR_INVALID); + td->dmaaddr = cpu_to_le32 (DMA_ADDR_INVALID); td->dmadesc = td->dmaaddr; dev->ep [i].dummy = td; } diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index 5a3034fdfe47..29500154d00c 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -225,12 +225,12 @@ module_param(qlen, uint, S_IRUGO|S_IWUSR); static struct usb_device_descriptor device_desc = { .bLength = sizeof device_desc, .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = __constant_cpu_to_le16(0x0200), + .bcdUSB = cpu_to_le16(0x0200), .bDeviceClass = USB_CLASS_PER_INTERFACE, .bDeviceSubClass = 0, .bDeviceProtocol = 0, - .idVendor = __constant_cpu_to_le16(PRINTER_VENDOR_NUM), - .idProduct = __constant_cpu_to_le16(PRINTER_PRODUCT_NUM), + .idVendor = cpu_to_le16(PRINTER_VENDOR_NUM), + .idProduct = cpu_to_le16(PRINTER_PRODUCT_NUM), .iManufacturer = STRING_MANUFACTURER, .iProduct = STRING_PRODUCT, .iSerialNumber = STRING_SERIALNUM, @@ -299,20 +299,20 @@ static struct usb_endpoint_descriptor hs_ep_in_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512) + .wMaxPacketSize = cpu_to_le16(512) }; static struct usb_endpoint_descriptor hs_ep_out_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512) + .wMaxPacketSize = cpu_to_le16(512) }; static struct usb_qualifier_descriptor dev_qualifier = { .bLength = sizeof dev_qualifier, .bDescriptorType = USB_DT_DEVICE_QUALIFIER, - .bcdUSB = __constant_cpu_to_le16(0x0200), + .bcdUSB = cpu_to_le16(0x0200), .bDeviceClass = USB_CLASS_PRINTER, .bNumConfigurations = 1 }; @@ -1406,16 +1406,16 @@ printer_bind(struct usb_gadget *gadget) gadget->name); /* unrecognized, but safe unless bulk is REALLY quirky */ device_desc.bcdDevice = - __constant_cpu_to_le16(0xFFFF); + cpu_to_le16(0xFFFF); } snprintf(manufacturer, sizeof(manufacturer), "%s %s with %s", init_utsname()->sysname, init_utsname()->release, gadget->name); device_desc.idVendor = - __constant_cpu_to_le16(PRINTER_VENDOR_NUM); + cpu_to_le16(PRINTER_VENDOR_NUM); device_desc.idProduct = - __constant_cpu_to_le16(PRINTER_PRODUCT_NUM); + cpu_to_le16(PRINTER_PRODUCT_NUM); /* support optional vendor/distro customization */ if (idVendor) { diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index 37879af1c433..f46a60962dab 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -87,12 +87,12 @@ static struct usb_gadget_strings *dev_strings[] = { static struct usb_device_descriptor device_desc = { .bLength = USB_DT_DEVICE_SIZE, .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = __constant_cpu_to_le16(0x0200), + .bcdUSB = cpu_to_le16(0x0200), /* .bDeviceClass = f(use_acm) */ .bDeviceSubClass = 0, .bDeviceProtocol = 0, /* .bMaxPacketSize0 = f(hardware) */ - .idVendor = __constant_cpu_to_le16(GS_VENDOR_ID), + .idVendor = cpu_to_le16(GS_VENDOR_ID), /* .idProduct = f(use_acm) */ /* .bcdDevice = f(hardware) */ /* .iManufacturer = DYNAMIC */ @@ -216,7 +216,7 @@ static int __init gs_bind(struct usb_composite_dev *cdev) pr_warning("gs_bind: controller '%s' not recognized\n", gadget->name); device_desc.bcdDevice = - __constant_cpu_to_le16(GS_VERSION_NUM | 0x0099); + cpu_to_le16(GS_VERSION_NUM | 0x0099); } if (gadget_is_otg(cdev->gadget)) { @@ -255,19 +255,19 @@ static int __init init(void) serial_config_driver.bConfigurationValue = 2; device_desc.bDeviceClass = USB_CLASS_COMM; device_desc.idProduct = - __constant_cpu_to_le16(GS_CDC_PRODUCT_ID); + cpu_to_le16(GS_CDC_PRODUCT_ID); } else if (use_obex) { serial_config_driver.label = "CDC OBEX config"; serial_config_driver.bConfigurationValue = 3; device_desc.bDeviceClass = USB_CLASS_COMM; device_desc.idProduct = - __constant_cpu_to_le16(GS_CDC_OBEX_PRODUCT_ID); + cpu_to_le16(GS_CDC_OBEX_PRODUCT_ID); } else { serial_config_driver.label = "Generic Serial config"; serial_config_driver.bConfigurationValue = 1; device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC; device_desc.idProduct = - __constant_cpu_to_le16(GS_PRODUCT_ID); + cpu_to_le16(GS_PRODUCT_ID); } strings_dev[STRING_DESCRIPTION_IDX].s = serial_config_driver.label; diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c index 53d59287f2bc..0a4d99ab40d8 100644 --- a/drivers/usb/gadget/u_serial.c +++ b/drivers/usb/gadget/u_serial.c @@ -1092,7 +1092,7 @@ int __init gserial_setup(struct usb_gadget *g, unsigned count) gs_tty_driver->init_termios.c_ispeed = 9600; gs_tty_driver->init_termios.c_ospeed = 9600; - coding.dwDTERate = __constant_cpu_to_le32(9600); + coding.dwDTERate = cpu_to_le32(9600); coding.bCharFormat = 8; coding.bParityType = USB_CDC_NO_PARITY; coding.bDataBits = USB_CDC_1_STOP_BITS; diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 361d9659ac48..20614dce8db9 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -113,11 +113,11 @@ static struct usb_device_descriptor device_desc = { .bLength = sizeof device_desc, .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = __constant_cpu_to_le16(0x0200), + .bcdUSB = cpu_to_le16(0x0200), .bDeviceClass = USB_CLASS_VENDOR_SPEC, - .idVendor = __constant_cpu_to_le16(DRIVER_VENDOR_NUM), - .idProduct = __constant_cpu_to_le16(DRIVER_PRODUCT_NUM), + .idVendor = cpu_to_le16(DRIVER_VENDOR_NUM), + .idProduct = cpu_to_le16(DRIVER_PRODUCT_NUM), .bNumConfigurations = 2, }; @@ -265,7 +265,7 @@ static int __init zero_bind(struct usb_composite_dev *cdev) */ pr_warning("%s: controller '%s' not recognized\n", longname, gadget->name); - device_desc.bcdDevice = __constant_cpu_to_le16(0x9999); + device_desc.bcdDevice = cpu_to_le16(0x9999); } diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 1d0b49e3f192..ada5d2ba297b 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -563,7 +563,7 @@ static int qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh) // and this qh is active in the current uframe // (and overlay token SplitXstate is false?) // THEN - // qh->hw_info1 |= __constant_cpu_to_hc32(1 << 7 /* "ignore" */); + // qh->hw_info1 |= cpu_to_hc32(1 << 7 /* "ignore" */); /* high bandwidth, or otherwise part of every microframe */ if ((period = qh->period) == 0) diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 9aba560fd569..6cff195e1a36 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -253,7 +253,7 @@ struct ehci_qtd { /* * Now the following defines are not converted using the - * __constant_cpu_to_le32() macro anymore, since we have to support + * cpu_to_le32() macro anymore, since we have to support * "dynamic" switching between be and le support, so that the driver * can be used on one system with SoC EHCI controller using big-endian * descriptors as well as a normal little-endian PCI EHCI controller. diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index 8ee2f4159845..3172c0fd2a6d 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -644,7 +644,7 @@ static void transform_add_int(struct isp1760_hcd *priv, struct isp1760_qh *qh, if (urb->dev->speed != USB_SPEED_HIGH) { /* split */ - ptd->dw5 = __constant_cpu_to_le32(0x1c); + ptd->dw5 = cpu_to_le32(0x1c); if (qh->period >= 32) period = qh->period / 2; @@ -1054,7 +1054,7 @@ static void do_atl_int(struct usb_hcd *usb_hcd) priv_write_copy(priv, (u32 *)&ptd, usb_hcd->regs + atl_regs, sizeof(ptd)); - ptd.dw0 |= __constant_cpu_to_le32(PTD_VALID); + ptd.dw0 |= cpu_to_le32(PTD_VALID); priv_write_copy(priv, (u32 *)&ptd, usb_hcd->regs + atl_regs, sizeof(ptd)); diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c index 75548f7c716b..2947c69b3476 100644 --- a/drivers/usb/host/oxu210hp-hcd.c +++ b/drivers/usb/host/oxu210hp-hcd.c @@ -845,14 +845,14 @@ static inline void qh_update(struct oxu_hcd *oxu, is_out = !(qtd->hw_token & cpu_to_le32(1 << 8)); epnum = (le32_to_cpup(&qh->hw_info1) >> 8) & 0x0f; if (unlikely(!usb_gettoggle(qh->dev, epnum, is_out))) { - qh->hw_token &= ~__constant_cpu_to_le32(QTD_TOGGLE); + qh->hw_token &= ~cpu_to_le32(QTD_TOGGLE); usb_settoggle(qh->dev, epnum, is_out, 1); } } /* HC must see latest qtd and qh data before we clear ACTIVE+HALT */ wmb(); - qh->hw_token &= __constant_cpu_to_le32(QTD_TOGGLE | QTD_STS_PING); + qh->hw_token &= cpu_to_le32(QTD_TOGGLE | QTD_STS_PING); } /* If it weren't for a common silicon quirk (writing the dummy into the qh @@ -937,7 +937,7 @@ __acquires(oxu->lock) struct ehci_qh *qh = (struct ehci_qh *) urb->hcpriv; /* S-mask in a QH means it's an interrupt urb */ - if ((qh->hw_info2 & __constant_cpu_to_le32(QH_SMASK)) != 0) { + if ((qh->hw_info2 & cpu_to_le32(QH_SMASK)) != 0) { /* ... update hc-wide periodic stats (for usbfs) */ oxu_to_hcd(oxu)->self.bandwidth_int_reqs--; @@ -981,7 +981,7 @@ static void unlink_async(struct oxu_hcd *oxu, struct ehci_qh *qh); static void intr_deschedule(struct oxu_hcd *oxu, struct ehci_qh *qh); static int qh_schedule(struct oxu_hcd *oxu, struct ehci_qh *qh); -#define HALT_BIT __constant_cpu_to_le32(QTD_STS_HALT) +#define HALT_BIT cpu_to_le32(QTD_STS_HALT) /* Process and free completed qtds for a qh, returning URBs to drivers. * Chases up to qh->hw_current. Returns number of completions called, @@ -1160,7 +1160,7 @@ halt: /* should be rare for periodic transfers, * except maybe high bandwidth ... */ - if ((__constant_cpu_to_le32(QH_SMASK) + if ((cpu_to_le32(QH_SMASK) & qh->hw_info2) != 0) { intr_deschedule(oxu, qh); (void) qh_schedule(oxu, qh); @@ -1350,7 +1350,7 @@ static struct list_head *qh_urb_transaction(struct oxu_hcd *oxu, } /* by default, enable interrupt on urb completion */ - qtd->hw_token |= __constant_cpu_to_le32(QTD_IOC); + qtd->hw_token |= cpu_to_le32(QTD_IOC); return head; cleanup: @@ -1539,7 +1539,7 @@ static void qh_link_async(struct oxu_hcd *oxu, struct ehci_qh *qh) /* qtd completions reported later by interrupt */ } -#define QH_ADDR_MASK __constant_cpu_to_le32(0x7f) +#define QH_ADDR_MASK cpu_to_le32(0x7f) /* * For control/bulk/interrupt, return QH with these TDs appended. @@ -2012,7 +2012,7 @@ static void qh_unlink_periodic(struct oxu_hcd *oxu, struct ehci_qh *qh) * and this qh is active in the current uframe * (and overlay token SplitXstate is false?) * THEN - * qh->hw_info1 |= __constant_cpu_to_le32(1 << 7 "ignore"); + * qh->hw_info1 |= cpu_to_le32(1 << 7 "ignore"); */ /* high bandwidth, or otherwise part of every microframe */ @@ -2057,7 +2057,7 @@ static void intr_deschedule(struct oxu_hcd *oxu, struct ehci_qh *qh) * active high speed queues may need bigger delays... */ if (list_empty(&qh->qtd_list) - || (__constant_cpu_to_le32(QH_CMASK) & qh->hw_info2) != 0) + || (cpu_to_le32(QH_CMASK) & qh->hw_info2) != 0) wait = 2; else wait = 55; /* worst case: 3 * 1024 */ @@ -2183,10 +2183,10 @@ static int qh_schedule(struct oxu_hcd *oxu, struct ehci_qh *qh) qh->start = frame; /* reset S-frame and (maybe) C-frame masks */ - qh->hw_info2 &= __constant_cpu_to_le32(~(QH_CMASK | QH_SMASK)); + qh->hw_info2 &= cpu_to_le32(~(QH_CMASK | QH_SMASK)); qh->hw_info2 |= qh->period ? cpu_to_le32(1 << uframe) - : __constant_cpu_to_le32(QH_SMASK); + : cpu_to_le32(QH_SMASK); qh->hw_info2 |= c_mask; } else oxu_dbg(oxu, "reused qh %p schedule\n", qh); diff --git a/drivers/usb/host/oxu210hp.h b/drivers/usb/host/oxu210hp.h index 8910e271cc7d..1c216ad9aad2 100644 --- a/drivers/usb/host/oxu210hp.h +++ b/drivers/usb/host/oxu210hp.h @@ -235,21 +235,21 @@ struct ehci_qtd { } __attribute__ ((aligned(32))); /* mask NakCnt+T in qh->hw_alt_next */ -#define QTD_MASK __constant_cpu_to_le32 (~0x1f) +#define QTD_MASK cpu_to_le32 (~0x1f) #define IS_SHORT_READ(token) (QTD_LENGTH(token) != 0 && QTD_PID(token) == 1) /* Type tag from {qh, itd, sitd, fstn}->hw_next */ -#define Q_NEXT_TYPE(dma) ((dma) & __constant_cpu_to_le32 (3 << 1)) +#define Q_NEXT_TYPE(dma) ((dma) & cpu_to_le32 (3 << 1)) /* values for that type tag */ -#define Q_TYPE_QH __constant_cpu_to_le32 (1 << 1) +#define Q_TYPE_QH cpu_to_le32 (1 << 1) /* next async queue entry, or pointer to interrupt/periodic QH */ #define QH_NEXT(dma) (cpu_to_le32(((u32)dma)&~0x01f)|Q_TYPE_QH) /* for periodic/async schedules and qtd lists, mark end of list */ -#define EHCI_LIST_END __constant_cpu_to_le32(1) /* "null pointer" to hw */ +#define EHCI_LIST_END cpu_to_le32(1) /* "null pointer" to hw */ /* * Entries in periodic shadow table are pointers to one of four kinds diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index 7d01c5677f92..26bd1b2bcbfc 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h @@ -73,11 +73,11 @@ #define USBLEGSUP_RWC 0x8f00 /* the R/WC bits */ #define USBLEGSUP_RO 0x5040 /* R/O and reserved bits */ -#define UHCI_PTR_BITS __constant_cpu_to_le32(0x000F) -#define UHCI_PTR_TERM __constant_cpu_to_le32(0x0001) -#define UHCI_PTR_QH __constant_cpu_to_le32(0x0002) -#define UHCI_PTR_DEPTH __constant_cpu_to_le32(0x0004) -#define UHCI_PTR_BREADTH __constant_cpu_to_le32(0x0000) +#define UHCI_PTR_BITS cpu_to_le32(0x000F) +#define UHCI_PTR_TERM cpu_to_le32(0x0001) +#define UHCI_PTR_QH cpu_to_le32(0x0002) +#define UHCI_PTR_DEPTH cpu_to_le32(0x0004) +#define UHCI_PTR_BREADTH cpu_to_le32(0x0000) #define UHCI_NUMFRAMES 1024 /* in the frame list [array] */ #define UHCI_MAX_SOF_NUMBER 2047 /* in an SOF packet */ diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 5631d89c8730..58f873679145 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -402,7 +402,7 @@ static void uhci_fixup_toggles(struct uhci_qh *qh, int skip_first) /* Otherwise all the toggles in the URB have to be switched */ } else { list_for_each_entry(td, &urbp->td_list, list) { - td->token ^= __constant_cpu_to_le32( + td->token ^= cpu_to_le32( TD_TOKEN_TOGGLE); toggle ^= 1; } @@ -883,7 +883,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0); wmb(); - qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE); + qh->dummy_td->status |= cpu_to_le32(TD_CTRL_ACTIVE); qh->dummy_td = td; /* Low-speed transfers get a different queue, and won't hog the bus. @@ -1003,7 +1003,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, * fast side but not enough to justify delaying an interrupt * more than 2 or 3 URBs, so we will ignore the URB_NO_INTERRUPT * flag setting. */ - td->status |= __constant_cpu_to_le32(TD_CTRL_IOC); + td->status |= cpu_to_le32(TD_CTRL_IOC); /* * Build the new dummy TD and activate the old one @@ -1015,7 +1015,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0); wmb(); - qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE); + qh->dummy_td->status |= cpu_to_le32(TD_CTRL_ACTIVE); qh->dummy_td = td; usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), @@ -1317,7 +1317,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, } /* Set the interrupt-on-completion flag on the last packet. */ - td->status |= __constant_cpu_to_le32(TD_CTRL_IOC); + td->status |= cpu_to_le32(TD_CTRL_IOC); /* Add the TDs to the frame list */ frame = urb->start_frame; diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c index 972f20b3406c..eca355dccf65 100644 --- a/drivers/usb/image/mdc800.c +++ b/drivers/usb/image/mdc800.c @@ -188,7 +188,7 @@ static struct usb_endpoint_descriptor mdc800_ed [4] = .bDescriptorType = 0, .bEndpointAddress = 0x01, .bmAttributes = 0x02, - .wMaxPacketSize = __constant_cpu_to_le16(8), + .wMaxPacketSize = cpu_to_le16(8), .bInterval = 0, .bRefresh = 0, .bSynchAddress = 0, @@ -198,7 +198,7 @@ static struct usb_endpoint_descriptor mdc800_ed [4] = .bDescriptorType = 0, .bEndpointAddress = 0x82, .bmAttributes = 0x03, - .wMaxPacketSize = __constant_cpu_to_le16(8), + .wMaxPacketSize = cpu_to_le16(8), .bInterval = 0, .bRefresh = 0, .bSynchAddress = 0, @@ -208,7 +208,7 @@ static struct usb_endpoint_descriptor mdc800_ed [4] = .bDescriptorType = 0, .bEndpointAddress = 0x03, .bmAttributes = 0x02, - .wMaxPacketSize = __constant_cpu_to_le16(64), + .wMaxPacketSize = cpu_to_le16(64), .bInterval = 0, .bRefresh = 0, .bSynchAddress = 0, @@ -218,7 +218,7 @@ static struct usb_endpoint_descriptor mdc800_ed [4] = .bDescriptorType = 0, .bEndpointAddress = 0x84, .bmAttributes = 0x02, - .wMaxPacketSize = __constant_cpu_to_le16(64), + .wMaxPacketSize = cpu_to_le16(64), .bInterval = 0, .bRefresh = 0, .bSynchAddress = 0, diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c index e0e9ce584175..bf677acc83db 100644 --- a/drivers/usb/musb/musb_virthub.c +++ b/drivers/usb/musb/musb_virthub.c @@ -285,7 +285,7 @@ int musb_hub_control( desc->bDescLength = 9; desc->bDescriptorType = 0x29; desc->bNbrPorts = 1; - desc->wHubCharacteristics = __constant_cpu_to_le16( + desc->wHubCharacteristics = cpu_to_le16( 0x0001 /* per-port power switching */ | 0x0010 /* no overcurrent reporting */ ); -- cgit v1.2.3 From 9a5c00548fb3affaa30daa68d2901a98b4db0341 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 13 Feb 2009 11:22:06 -0800 Subject: USB: fix ehci printk formats Fix ehci printk formats: drivers/usb/host/ehci-q.c:351: warning: format '%d' expects type 'int', but argument 4 has type 'size_t' drivers/usb/host/ehci-q.c:351: warning: format '%d' expects type 'int', but argument 5 has type 'size_t' Signed-off-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-q.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 01132ac74eb8..1976b1b3778c 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -349,7 +349,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) --qh->xacterrs > 0 && !urb->unlinked) { ehci_dbg(ehci, - "detected XactErr len %d/%d retry %d\n", + "detected XactErr len %zu/%zu retry %d\n", qtd->length - QTD_LENGTH(token), qtd->length, QH_XACTERR_MAX - qh->xacterrs); -- cgit v1.2.3 From 184f1bb4b217e276d0e43721915defcfe707b968 Mon Sep 17 00:00:00 2001 From: Dave Young Date: Sat, 14 Feb 2009 21:21:13 +0800 Subject: usb-serial: fix usb_serial_register bug when boot with nousb param With "nousb" cmdline booting, built-in serial drivers (ie. airecable) will trigger kernel oops. Indeed, if nousb, usb_serial_init will failed, and the usb serial bus type will not be registerd, then usb_serial_register call driver_register which try to register the driver to a not registered bus. Here add usb_disabled() check in usb_serial_register to fix it. Signed-off-by: Dave Young Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 73172898ccb3..742a5bc44be8 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1241,6 +1241,9 @@ int usb_serial_register(struct usb_serial_driver *driver) /* must be called with BKL held */ int retval; + if (usb_disabled()) + return -ENODEV; + fixup_generic(driver); if (!driver->description) -- cgit v1.2.3 From e490d635420113f8484c92aac274d84103d319f4 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:47:44 -0500 Subject: usb-storage: prepare for subdriver separation This patch (as1206) is the first step in converting usb-storage's subdrivers into separate modules. It makes the following large-scale changes: Remove a bunch of unnecessary #ifdef's from usb_usual.h. Not truly necessary, but it does clean things up. Move the USB device-ID table (which is duplicated between libusual and usb-storage) into its own source file, usual-tables.c, and arrange for this to be linked with either libusual or usb-storage according to whether USB_LIBUSUAL is configured. Add to usual-tables.c a new usb_usual_ignore_device() function to detect whether a particular device needs to be managed by a subdriver and not by the standard handlers in usb-storage. Export a whole bunch of functions in usb-storage, renaming some of them because their names don't already begin with "usb_stor_". These functions will be needed by the new subdriver modules. Split usb-storage's probe routine into two functions. The subdrivers will call the probe1 routine, then fill in their transport and protocol settings, and then call the probe2 routine. Take the default cases and error checking out of get_transport() and get_protocol(), which run during probe1, and instead put a check for invalid transport or protocol values into the probe2 function. Add a new probe routine to be used for standard devices, i.e., those that don't need a subdriver. This new routine checks whether the device should be ignored (because it should be handled by ub or by a subdriver), and if not, calls the probe1 and probe2 functions. Signed-off-by: Alan Stern CC: Matthew Dharm Signed-off-by: Greg Kroah-Hartman --- drivers/block/ub.c | 2 +- drivers/usb/storage/Makefile | 6 +- drivers/usb/storage/libusual.c | 33 +----- drivers/usb/storage/protocol.c | 3 + drivers/usb/storage/scsiglue.c | 2 +- drivers/usb/storage/transport.c | 10 ++ drivers/usb/storage/usb.c | 209 ++++++++++++++++++++----------------- drivers/usb/storage/usb.h | 21 ++++ drivers/usb/storage/usual-tables.c | 105 +++++++++++++++++++ include/linux/usb_usual.h | 21 +--- 10 files changed, 261 insertions(+), 151 deletions(-) create mode 100644 drivers/usb/storage/usual-tables.c diff --git a/drivers/block/ub.c b/drivers/block/ub.c index b36b84fbe390..69b7f8e77596 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -391,7 +391,7 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum); */ #ifdef CONFIG_USB_LIBUSUAL -#define ub_usb_ids storage_usb_ids +#define ub_usb_ids usb_storage_usb_ids #else static struct usb_device_id ub_usb_ids[] = { diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index b32069313390..a9e475e127a5 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -25,6 +25,8 @@ usb-storage-obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += cypress_atacb.o usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \ initializers.o sierra_ms.o option_ms.o $(usb-storage-obj-y) -ifneq ($(CONFIG_USB_LIBUSUAL),) - obj-$(CONFIG_USB) += libusual.o +ifeq ($(CONFIG_USB_LIBUSUAL),) + usb-storage-objs += usual-tables.o +else + obj-$(CONFIG_USB) += libusual.o usual-tables.o endif diff --git a/drivers/usb/storage/libusual.c b/drivers/usb/storage/libusual.c index f970b27ba308..fe3ffe1459b2 100644 --- a/drivers/usb/storage/libusual.c +++ b/drivers/usb/storage/libusual.c @@ -37,37 +37,6 @@ static atomic_t total_threads = ATOMIC_INIT(0); static int usu_probe_thread(void *arg); -/* - * The table. - */ -#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ - vendorName, productName,useProtocol, useTransport, \ - initFunction, flags) \ -{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } - -#define COMPLIANT_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ - vendorName, productName, useProtocol, useTransport, \ - initFunction, flags) \ -{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ - .driver_info = (flags) } - -#define USUAL_DEV(useProto, useTrans, useType) \ -{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \ - .driver_info = ((useType)<<24) } - -struct usb_device_id storage_usb_ids [] = { -# include "unusual_devs.h" - { } /* Terminating entry */ -}; - -#undef USUAL_DEV -#undef UNUSUAL_DEV -#undef COMPLIANT_DEV - -MODULE_DEVICE_TABLE(usb, storage_usb_ids); -EXPORT_SYMBOL_GPL(storage_usb_ids); - /* * @type: the module type as an integer */ @@ -167,7 +136,7 @@ static struct usb_driver usu_driver = { .name = "libusual", .probe = usu_probe, .disconnect = usu_disconnect, - .id_table = storage_usb_ids, + .id_table = usb_storage_usb_ids, }; /* diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c index be441d84bc64..fc310f75eada 100644 --- a/drivers/usb/storage/protocol.c +++ b/drivers/usb/storage/protocol.c @@ -121,6 +121,7 @@ void usb_stor_transparent_scsi_command(struct scsi_cmnd *srb, /* send the command to the transport layer */ usb_stor_invoke_transport(srb, us); } +EXPORT_SYMBOL_GPL(usb_stor_transparent_scsi_command); /*********************************************************************** * Scatter-gather transfer buffer access routines @@ -199,6 +200,7 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer, /* Return the amount actually transferred */ return cnt; } +EXPORT_SYMBOL_GPL(usb_stor_access_xfer_buf); /* Store the contents of buffer into srb's transfer buffer and set the * SCSI residue. @@ -215,3 +217,4 @@ void usb_stor_set_xfer_buf(unsigned char *buffer, if (buflen < scsi_bufflen(srb)) scsi_set_resid(srb, scsi_bufflen(srb) - buflen); } +EXPORT_SYMBOL_GPL(usb_stor_set_xfer_buf); diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 727c506417cc..b98fedfb3253 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -563,4 +563,4 @@ unsigned char usb_stor_sense_invalidCDB[18] = { [7] = 0x0a, /* additional length */ [12] = 0x24 /* Invalid Field in CDB */ }; - +EXPORT_SYMBOL_GPL(usb_stor_sense_invalidCDB); diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index fb65d221cedf..d48c8553539d 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -220,6 +220,7 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe, status = us->current_urb->actual_length; return status; } +EXPORT_SYMBOL_GPL(usb_stor_control_msg); /* This is a version of usb_clear_halt() that allows early termination and * doesn't read the status from the device -- this is because some devices @@ -254,6 +255,7 @@ int usb_stor_clear_halt(struct us_data *us, unsigned int pipe) US_DEBUGP("%s: result = %d\n", __func__, result); return result; } +EXPORT_SYMBOL_GPL(usb_stor_clear_halt); /* @@ -352,6 +354,7 @@ int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe, return interpret_urb_result(us, pipe, size, result, us->current_urb->actual_length); } +EXPORT_SYMBOL_GPL(usb_stor_ctrl_transfer); /* * Receive one interrupt buffer, without timeouts, but allowing early @@ -407,6 +410,7 @@ int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe, return interpret_urb_result(us, pipe, length, result, us->current_urb->actual_length); } +EXPORT_SYMBOL_GPL(usb_stor_bulk_transfer_buf); /* * Transfer a scatter-gather list via bulk transfer @@ -474,6 +478,7 @@ int usb_stor_bulk_srb(struct us_data* us, unsigned int pipe, scsi_set_resid(srb, scsi_bufflen(srb) - partial); return result; } +EXPORT_SYMBOL_GPL(usb_stor_bulk_srb); /* * Transfer an entire SCSI command's worth of data payload over the bulk @@ -509,6 +514,7 @@ int usb_stor_bulk_transfer_sg(struct us_data* us, unsigned int pipe, *residual = length_left; return result; } +EXPORT_SYMBOL_GPL(usb_stor_bulk_transfer_sg); /*********************************************************************** * Transport routines @@ -940,6 +946,7 @@ int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us) usb_stor_clear_halt(us, pipe); return USB_STOR_TRANSPORT_FAILED; } +EXPORT_SYMBOL_GPL(usb_stor_CB_transport); /* * Bulk only transport @@ -1156,6 +1163,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us) /* we should never get here, but if we do, we're in trouble */ return USB_STOR_TRANSPORT_ERROR; } +EXPORT_SYMBOL_GPL(usb_stor_Bulk_transport); /*********************************************************************** * Reset routines @@ -1230,6 +1238,7 @@ int usb_stor_CB_reset(struct us_data *us) USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, us->ifnum, us->iobuf, CB_RESET_CMD_SIZE); } +EXPORT_SYMBOL_GPL(usb_stor_CB_reset); /* This issues a Bulk-only Reset to the device in question, including * clearing the subsequent endpoint halts that may occur. @@ -1242,6 +1251,7 @@ int usb_stor_Bulk_reset(struct us_data *us) USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, us->ifnum, NULL, 0); } +EXPORT_SYMBOL_GPL(usb_stor_Bulk_reset); /* Issue a USB port reset to the device. The caller must not hold * us->dev_mutex. diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index b01dade63cb3..490ea761398c 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -5,7 +5,7 @@ * * Developed with the assistance of: * (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org) - * (c) 2003 Alan Stern (stern@rowland.harvard.edu) + * (c) 2003-2009 Alan Stern (stern@rowland.harvard.edu) * * Initial work by: * (c) 1999 Michael Gee (michael@linuxspecific.com) @@ -118,36 +118,8 @@ MODULE_PARM_DESC(quirks, "supplemental list of device IDs and their quirks"); /* * The entries in this table correspond, line for line, - * with the entries of us_unusual_dev_list[]. + * with the entries in usb_storage_usb_ids[], defined in usual-tables.c. */ -#ifndef CONFIG_USB_LIBUSUAL - -#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ - vendorName, productName,useProtocol, useTransport, \ - initFunction, flags) \ -{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } - -#define COMPLIANT_DEV UNUSUAL_DEV - -#define USUAL_DEV(useProto, useTrans, useType) \ -{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \ - .driver_info = (USB_US_TYPE_STOR<<24) } - -static struct usb_device_id storage_usb_ids [] = { - -# include "unusual_devs.h" -#undef UNUSUAL_DEV -#undef COMPLIANT_DEV -#undef USUAL_DEV - /* Terminating entry */ - { } -}; - -MODULE_DEVICE_TABLE (usb, storage_usb_ids); -#endif /* CONFIG_USB_LIBUSUAL */ - -/* This is the list of devices we recognize, along with their flag data */ /* The vendor name should be kept at eight characters or less, and * the product name should be kept at 16 characters or less. If a device @@ -179,18 +151,17 @@ MODULE_DEVICE_TABLE (usb, storage_usb_ids); static struct us_unusual_dev us_unusual_dev_list[] = { # include "unusual_devs.h" -# undef UNUSUAL_DEV -# undef COMPLIANT_DEV -# undef USUAL_DEV - - /* Terminating entry */ - { NULL } + { } /* Terminating entry */ }; +#undef UNUSUAL_DEV +#undef COMPLIANT_DEV +#undef USUAL_DEV + #ifdef CONFIG_PM /* Minimal support for suspend and resume */ -static int storage_suspend(struct usb_interface *iface, pm_message_t message) +int usb_stor_suspend(struct usb_interface *iface, pm_message_t message) { struct us_data *us = usb_get_intfdata(iface); @@ -207,8 +178,9 @@ static int storage_suspend(struct usb_interface *iface, pm_message_t message) mutex_unlock(&us->dev_mutex); return 0; } +EXPORT_SYMBOL_GPL(usb_stor_suspend); -static int storage_resume(struct usb_interface *iface) +int usb_stor_resume(struct usb_interface *iface) { struct us_data *us = usb_get_intfdata(iface); @@ -221,8 +193,9 @@ static int storage_resume(struct usb_interface *iface) mutex_unlock(&us->dev_mutex); return 0; } +EXPORT_SYMBOL_GPL(usb_stor_resume); -static int storage_reset_resume(struct usb_interface *iface) +int usb_stor_reset_resume(struct usb_interface *iface) { struct us_data *us = usb_get_intfdata(iface); @@ -235,6 +208,7 @@ static int storage_reset_resume(struct usb_interface *iface) * the device */ return 0; } +EXPORT_SYMBOL_GPL(usb_stor_reset_resume); #endif /* CONFIG_PM */ @@ -243,7 +217,7 @@ static int storage_reset_resume(struct usb_interface *iface) * a USB port reset, whether from this driver or a different one. */ -static int storage_pre_reset(struct usb_interface *iface) +int usb_stor_pre_reset(struct usb_interface *iface) { struct us_data *us = usb_get_intfdata(iface); @@ -253,8 +227,9 @@ static int storage_pre_reset(struct usb_interface *iface) mutex_lock(&us->dev_mutex); return 0; } +EXPORT_SYMBOL_GPL(usb_stor_pre_reset); -static int storage_post_reset(struct usb_interface *iface) +int usb_stor_post_reset(struct usb_interface *iface) { struct us_data *us = usb_get_intfdata(iface); @@ -269,6 +244,7 @@ static int storage_post_reset(struct usb_interface *iface) mutex_unlock(&us->dev_mutex); return 0; } +EXPORT_SYMBOL_GPL(usb_stor_post_reset); /* * fill_inquiry_response takes an unsigned char array (which must @@ -311,6 +287,7 @@ void fill_inquiry_response(struct us_data *us, unsigned char *data, usb_stor_set_xfer_buf(data, data_len, us->srb); } +EXPORT_SYMBOL_GPL(fill_inquiry_response); static int usb_stor_control_thread(void * __us) { @@ -551,20 +528,13 @@ static void adjust_quirks(struct us_data *us) vid, pid, f); } -/* Find an unusual_dev descriptor (always succeeds in the current code) */ -static struct us_unusual_dev *find_unusual(const struct usb_device_id *id) -{ - const int id_index = id - storage_usb_ids; - return &us_unusual_dev_list[id_index]; -} - /* Get the unusual_devs entries and the string descriptors */ -static int get_device_info(struct us_data *us, const struct usb_device_id *id) +static int get_device_info(struct us_data *us, const struct usb_device_id *id, + struct us_unusual_dev *unusual_dev) { struct usb_device *dev = us->pusb_dev; struct usb_interface_descriptor *idesc = &us->pusb_intf->cur_altsetting->desc; - struct us_unusual_dev *unusual_dev = find_unusual(id); /* Store the entries */ us->unusual_dev = unusual_dev; @@ -629,7 +599,7 @@ static int get_device_info(struct us_data *us, const struct usb_device_id *id) } /* Get the transport settings */ -static int get_transport(struct us_data *us) +static void get_transport(struct us_data *us) { switch (us->protocol) { case US_PR_CB: @@ -732,19 +702,11 @@ static int get_transport(struct us_data *us) break; #endif - default: - return -EIO; } - US_DEBUGP("Transport: %s\n", us->transport_name); - - /* fix for single-lun devices */ - if (us->fflags & US_FL_SINGLE_LUN) - us->max_lun = 0; - return 0; } /* Get the protocol settings */ -static int get_protocol(struct us_data *us) +static void get_protocol(struct us_data *us) { switch (us->subclass) { case US_SC_RBC: @@ -794,11 +756,7 @@ static int get_protocol(struct us_data *us) break; #endif - default: - return -EIO; } - US_DEBUGP("Protocol: %s\n", us->protocol_name); - return 0; } /* Get the pipe settings */ @@ -1012,17 +970,15 @@ static int usb_stor_scan_thread(void * __us) } -/* Probe to see if we can drive a newly-connected USB device */ -static int storage_probe(struct usb_interface *intf, - const struct usb_device_id *id) +/* First part of general USB mass-storage probing */ +int usb_stor_probe1(struct us_data **pus, + struct usb_interface *intf, + const struct usb_device_id *id, + struct us_unusual_dev *unusual_dev) { struct Scsi_Host *host; struct us_data *us; int result; - struct task_struct *th; - - if (usb_usual_check_type(id, USB_US_TYPE_STOR)) - return -ENXIO; US_DEBUGP("USB Mass Storage device detected\n"); @@ -1041,7 +997,7 @@ static int storage_probe(struct usb_interface *intf, * Allow 16-byte CDBs and thus > 2TB */ host->max_cmd_len = 16; - us = host_to_us(host); + *pus = us = host_to_us(host); memset(us, 0, sizeof(struct us_data)); mutex_init(&(us->dev_mutex)); init_completion(&us->cmnd_ready); @@ -1054,24 +1010,46 @@ static int storage_probe(struct usb_interface *intf, if (result) goto BadDevice; - /* - * Get the unusual_devs entries and the descriptors - * - * id_index is calculated in the declaration to be the index number - * of the match from the usb_device_id table, so we can find the - * corresponding entry in the private table. - */ - result = get_device_info(us, id); + /* Get the unusual_devs entries and the descriptors */ + result = get_device_info(us, id, unusual_dev); if (result) goto BadDevice; - /* Get the transport, protocol, and pipe settings */ - result = get_transport(us); - if (result) - goto BadDevice; - result = get_protocol(us); - if (result) + /* Get standard transport and protocol settings */ + get_transport(us); + get_protocol(us); + + /* Give the caller a chance to fill in specialized transport + * or protocol settings. + */ + return 0; + +BadDevice: + US_DEBUGP("storage_probe() failed\n"); + release_everything(us); + return result; +} +EXPORT_SYMBOL_GPL(usb_stor_probe1); + +/* Second part of general USB mass-storage probing */ +int usb_stor_probe2(struct us_data *us) +{ + struct task_struct *th; + int result; + + /* Make sure the transport and protocol have both been set */ + if (!us->transport || !us->proto_handler) { + result = -ENXIO; goto BadDevice; + } + US_DEBUGP("Transport: %s\n", us->transport_name); + US_DEBUGP("Protocol: %s\n", us->protocol_name); + + /* fix for single-lun devices */ + if (us->fflags & US_FL_SINGLE_LUN) + us->max_lun = 0; + + /* Find the endpoints and calculate pipe values */ result = get_pipes(us); if (result) goto BadDevice; @@ -1080,7 +1058,7 @@ static int storage_probe(struct usb_interface *intf, result = usb_stor_acquire_resources(us); if (result) goto BadDevice; - result = scsi_add_host(host, &intf->dev); + result = scsi_add_host(us_to_host(us), &us->pusb_intf->dev); if (result) { printk(KERN_WARNING USB_STORAGE "Unable to add the scsi host\n"); @@ -1108,9 +1086,10 @@ BadDevice: release_everything(us); return result; } +EXPORT_SYMBOL_GPL(usb_stor_probe2); -/* Handle a disconnect event from the USB core */ -static void storage_disconnect(struct usb_interface *intf) +/* Handle a USB mass-storage disconnect */ +void usb_stor_disconnect(struct usb_interface *intf) { struct us_data *us = usb_get_intfdata(intf); @@ -1118,6 +1097,42 @@ static void storage_disconnect(struct usb_interface *intf) quiesce_and_remove_host(us); release_everything(us); } +EXPORT_SYMBOL_GPL(usb_stor_disconnect); + +/* The main probe routine for standard devices */ +static int storage_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct us_data *us; + int result; + + /* + * If libusual is configured, let it decide whether a standard + * device should be handled by usb-storage or by ub. + * If the device isn't standard (is handled by a subdriver + * module) then don't accept it. + */ + if (usb_usual_check_type(id, USB_US_TYPE_STOR) || + usb_usual_ignore_device(intf)) + return -ENXIO; + + /* + * Call the general probe procedures. + * + * The unusual_dev_list array is parallel to the usb_storage_usb_ids + * table, so we use the index of the id entry to find the + * corresponding unusual_devs entry. + */ + result = usb_stor_probe1(&us, intf, id, + (id - usb_storage_usb_ids) + us_unusual_dev_list); + if (result) + return result; + + /* No special transport or protocol settings in the main module */ + + result = usb_stor_probe2(us); + return result; +} /*********************************************************************** * Initialization and registration @@ -1126,15 +1141,13 @@ static void storage_disconnect(struct usb_interface *intf) static struct usb_driver usb_storage_driver = { .name = "usb-storage", .probe = storage_probe, - .disconnect = storage_disconnect, -#ifdef CONFIG_PM - .suspend = storage_suspend, - .resume = storage_resume, - .reset_resume = storage_reset_resume, -#endif - .pre_reset = storage_pre_reset, - .post_reset = storage_post_reset, - .id_table = storage_usb_ids, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = usb_storage_usb_ids, .soft_unbind = 1, }; diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h index 65e674e4be99..2609efb2bd7e 100644 --- a/drivers/usb/storage/usb.h +++ b/drivers/usb/storage/usb.h @@ -177,4 +177,25 @@ extern void fill_inquiry_response(struct us_data *us, #define scsi_unlock(host) spin_unlock_irq(host->host_lock) #define scsi_lock(host) spin_lock_irq(host->host_lock) +/* General routines provided by the usb-storage standard core */ +#ifdef CONFIG_PM +extern int usb_stor_suspend(struct usb_interface *iface, pm_message_t message); +extern int usb_stor_resume(struct usb_interface *iface); +extern int usb_stor_reset_resume(struct usb_interface *iface); +#else +#define usb_stor_suspend NULL +#define usb_stor_resume NULL +#define usb_stor_reset_resume NULL +#endif + +extern int usb_stor_pre_reset(struct usb_interface *iface); +extern int usb_stor_post_reset(struct usb_interface *iface); + +extern int usb_stor_probe1(struct us_data **pus, + struct usb_interface *intf, + const struct usb_device_id *id, + struct us_unusual_dev *unusual_dev); +extern int usb_stor_probe2(struct us_data *us); +extern void usb_stor_disconnect(struct usb_interface *intf); + #endif diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c new file mode 100644 index 000000000000..1924e3229409 --- /dev/null +++ b/drivers/usb/storage/usual-tables.c @@ -0,0 +1,105 @@ +/* Driver for USB Mass Storage devices + * Usual Tables File for usb-storage and libusual + * + * Copyright (C) 2009 Alan Stern (stern@rowland.harvard.edu) + * + * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more + * information about this driver. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include + + +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +#define COMPLIANT_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags) } + +#define USUAL_DEV(useProto, useTrans, useType) \ +{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \ + .driver_info = ((useType)<<24) } + +struct usb_device_id usb_storage_usb_ids[] = { +# include "unusual_devs.h" + { } /* Terminating entry */ +}; +EXPORT_SYMBOL_GPL(usb_storage_usb_ids); + +MODULE_DEVICE_TABLE(usb, usb_storage_usb_ids); + +#undef UNUSUAL_DEV +#undef COMPLIANT_DEV +#undef USUAL_DEV + + +/* + * The table of devices to ignore + */ +struct ignore_entry { + u16 vid, pid, bcdmin, bcdmax; +}; + +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ \ + .vid = id_vendor, \ + .pid = id_product, \ + .bcdmin = bcdDeviceMin, \ + .bcdmax = bcdDeviceMax, \ +} + +static struct ignore_entry ignore_ids[] = { + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV + + +/* Return an error if a device is in the ignore_ids list */ +int usb_usual_ignore_device(struct usb_interface *intf) +{ + struct usb_device *udev; + unsigned vid, pid, bcd; + struct ignore_entry *p; + + udev = interface_to_usbdev(intf); + vid = le16_to_cpu(udev->descriptor.idVendor); + pid = le16_to_cpu(udev->descriptor.idProduct); + bcd = le16_to_cpu(udev->descriptor.bcdDevice); + + for (p = ignore_ids; p->vid; ++p) { + if (p->vid == vid && p->pid == pid && + p->bcdmin <= bcd && p->bcdmax >= bcd) + return -ENXIO; + } + return 0; +} +EXPORT_SYMBOL_GPL(usb_usual_ignore_device); diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h index 1eea1ab68dc4..3d15fb9bc116 100644 --- a/include/linux/usb_usual.h +++ b/include/linux/usb_usual.h @@ -96,39 +96,26 @@ enum { US_DO_ALL_FLAGS }; #define US_PR_CBI 0x00 /* Control/Bulk/Interrupt */ #define US_PR_CB 0x01 /* Control/Bulk w/o interrupt */ #define US_PR_BULK 0x50 /* bulk only */ -#ifdef CONFIG_USB_STORAGE_USBAT + #define US_PR_USBAT 0x80 /* SCM-ATAPI bridge */ -#endif -#ifdef CONFIG_USB_STORAGE_SDDR09 #define US_PR_EUSB_SDDR09 0x81 /* SCM-SCSI bridge for SDDR-09 */ -#endif -#ifdef CONFIG_USB_STORAGE_SDDR55 #define US_PR_SDDR55 0x82 /* SDDR-55 (made up) */ -#endif #define US_PR_DPCM_USB 0xf0 /* Combination CB/SDDR09 */ -#ifdef CONFIG_USB_STORAGE_FREECOM #define US_PR_FREECOM 0xf1 /* Freecom */ -#endif -#ifdef CONFIG_USB_STORAGE_DATAFAB #define US_PR_DATAFAB 0xf2 /* Datafab chipsets */ -#endif -#ifdef CONFIG_USB_STORAGE_JUMPSHOT #define US_PR_JUMPSHOT 0xf3 /* Lexar Jumpshot */ -#endif -#ifdef CONFIG_USB_STORAGE_ALAUDA #define US_PR_ALAUDA 0xf4 /* Alauda chipsets */ -#endif -#ifdef CONFIG_USB_STORAGE_KARMA #define US_PR_KARMA 0xf5 /* Rio Karma */ -#endif #define US_PR_DEVICE 0xff /* Use device's value */ /* */ +extern int usb_usual_ignore_device(struct usb_interface *intf); +extern struct usb_device_id usb_storage_usb_ids[]; + #ifdef CONFIG_USB_LIBUSUAL -extern struct usb_device_id storage_usb_ids[]; extern void usb_usual_set_present(int type); extern void usb_usual_clear_present(int type); extern int usb_usual_check_type(const struct usb_device_id *, int type); -- cgit v1.2.3 From 43b02596ebc406a58bc53d503927e9b5d5426ee2 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:47:49 -0500 Subject: usb-storage: make sddr09 a separate module This patch (as1207) converts usb-storage's sddr09 subdriver into a separate module. An unexpected complication arises because of DPCM devices, in which one LUN uses the sddr09 transport and one uses the standard CB transport. Since these devices can be used even when USB_STORAGE_SDDR09 isn't configured, their entries in unusual_devs.h require special treatment. If SDDR09 isn't configured then the entries remain in unusual_devs.h; if it is then the entries are present in unusual_sddr09.h instead. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 +- drivers/usb/storage/Makefile | 5 +- drivers/usb/storage/sddr09.c | 107 +++++++++++++++++++++++++++++++++-- drivers/usb/storage/sddr09.h | 38 ------------- drivers/usb/storage/unusual_devs.h | 50 +++------------- drivers/usb/storage/unusual_sddr09.h | 56 ++++++++++++++++++ drivers/usb/storage/usb.c | 21 ------- drivers/usb/storage/usual-tables.c | 1 + 8 files changed, 174 insertions(+), 108 deletions(-) delete mode 100644 drivers/usb/storage/sddr09.h create mode 100644 drivers/usb/storage/unusual_sddr09.h diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 5c367566be8d..7be8899f2559 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -83,13 +83,15 @@ config USB_STORAGE_USBAT - Sandisk ImageMate SDDR-05b config USB_STORAGE_SDDR09 - bool "SanDisk SDDR-09 (and other SmartMedia, including DPCM) support" + tristate "SanDisk SDDR-09 (and other SmartMedia, including DPCM) support" depends on USB_STORAGE help Say Y here to include additional code to support the Sandisk SDDR-09 SmartMedia reader in the USB Mass Storage driver. Also works for the Microtech Zio! CompactFlash/SmartMedia reader. + If this driver is compiled as a module, it will be named ums-sddr09. + config USB_STORAGE_SDDR55 bool "SanDisk SDDR-55 SmartMedia support" depends on USB_STORAGE diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index a9e475e127a5..a52740a95602 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -11,7 +11,6 @@ obj-$(CONFIG_USB_STORAGE) += usb-storage.o usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG) += debug.o usb-storage-obj-$(CONFIG_USB_STORAGE_USBAT) += shuttle_usbat.o -usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR09) += sddr09.o usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR55) += sddr55.o usb-storage-obj-$(CONFIG_USB_STORAGE_FREECOM) += freecom.o usb-storage-obj-$(CONFIG_USB_STORAGE_ISD200) += isd200.o @@ -30,3 +29,7 @@ ifeq ($(CONFIG_USB_LIBUSUAL),) else obj-$(CONFIG_USB) += libusual.o usual-tables.o endif + +obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o + +ums-sddr09-objs := sddr09.o diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c index b667c7d2b837..170ad86b2d3e 100644 --- a/drivers/usb/storage/sddr09.c +++ b/drivers/usb/storage/sddr09.c @@ -41,6 +41,7 @@ */ #include +#include #include #include @@ -51,7 +52,50 @@ #include "transport.h" #include "protocol.h" #include "debug.h" -#include "sddr09.h" + + +static int usb_stor_sddr09_dpcm_init(struct us_data *us); +static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us); +static int usb_stor_sddr09_init(struct us_data *us); + + +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +struct usb_device_id sddr09_usb_ids[] = { +# include "unusual_sddr09.h" + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, sddr09_usb_ids); + +#undef UNUSUAL_DEV + +/* + * The flags table + */ +#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ + vendor_name, product_name, use_protocol, use_transport, \ + init_function, Flags) \ +{ \ + .vendorName = vendor_name, \ + .productName = product_name, \ + .useProtocol = use_protocol, \ + .useTransport = use_transport, \ + .initFunction = init_function, \ +} + +static struct us_unusual_dev sddr09_unusual_dev_list[] = { +# include "unusual_sddr09.h" + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV #define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) ) @@ -1406,7 +1450,7 @@ sddr09_common_init(struct us_data *us) { * unusual devices list but called from here then LUN 0 of the combo reader * is not recognized. But I do not know what precisely these calls do. */ -int +static int usb_stor_sddr09_dpcm_init(struct us_data *us) { int result; unsigned char *data = us->iobuf; @@ -1456,7 +1500,7 @@ usb_stor_sddr09_dpcm_init(struct us_data *us) { /* * Transport for the Microtech DPCM-USB */ -int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us) +static int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us) { int ret; @@ -1498,7 +1542,7 @@ int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us) /* * Transport for the Sandisk SDDR-09 */ -int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us) +static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us) { static unsigned char sensekey = 0, sensecode = 0; static unsigned char havefakesense = 0; @@ -1697,7 +1741,60 @@ int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us) /* * Initialization routine for the sddr09 subdriver */ -int +static int usb_stor_sddr09_init(struct us_data *us) { return sddr09_common_init(us); } + +static int sddr09_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct us_data *us; + int result; + + result = usb_stor_probe1(&us, intf, id, + (id - sddr09_usb_ids) + sddr09_unusual_dev_list); + if (result) + return result; + + if (us->protocol == US_PR_DPCM_USB) { + us->transport_name = "Control/Bulk-EUSB/SDDR09"; + us->transport = dpcm_transport; + us->transport_reset = usb_stor_CB_reset; + us->max_lun = 1; + } else { + us->transport_name = "EUSB/SDDR09"; + us->transport = sddr09_transport; + us->transport_reset = usb_stor_CB_reset; + us->max_lun = 0; + } + + result = usb_stor_probe2(us); + return result; +} + +static struct usb_driver sddr09_driver = { + .name = "ums-sddr09", + .probe = sddr09_probe, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = sddr09_usb_ids, + .soft_unbind = 1, +}; + +static int __init sddr09_init(void) +{ + return usb_register(&sddr09_driver); +} + +static void __exit sddr09_exit(void) +{ + usb_deregister(&sddr09_driver); +} + +module_init(sddr09_init); +module_exit(sddr09_exit); diff --git a/drivers/usb/storage/sddr09.h b/drivers/usb/storage/sddr09.h deleted file mode 100644 index b701172e12e3..000000000000 --- a/drivers/usb/storage/sddr09.h +++ /dev/null @@ -1,38 +0,0 @@ -/* Driver for SanDisk SDDR-09 SmartMedia reader - * Header File - * - * Current development and maintenance by: - * (c) 2000 Robert Baruch (autophile@dol.net) - * (c) 2002 Andries Brouwer (aeb@cwi.nl) - * - * See sddr09.c for more explanation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _USB_SHUTTLE_EUSB_SDDR09_H -#define _USB_SHUTTLE_EUSB_SDDR09_H - -/* Sandisk SDDR-09 stuff */ - -extern int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us); -extern int usb_stor_sddr09_init(struct us_data *us); - -/* Microtech DPCM-USB stuff */ - -extern int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us); -extern int usb_stor_sddr09_dpcm_init(struct us_data *us); - -#endif diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index cfde74a6faa3..1fe7062f1cda 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -53,6 +53,11 @@ * as opposed to devices that do something strangely or wrongly. */ +#if !defined(CONFIG_USB_STORAGE_SDDR09) && \ + !defined(CONFIG_USB_STORAGE_SDDR09_MODULE) +#define NO_SDDR09 +#endif + /* patch submitted by Vivian Bregier */ UNUSUAL_DEV( 0x03eb, 0x2002, 0x0100, 0x0100, @@ -246,12 +251,7 @@ UNUSUAL_DEV( 0x0424, 0x0fdc, 0x0210, 0x0210, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_SINGLE_LUN ), -#ifdef CONFIG_USB_STORAGE_SDDR09 -UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100, - "Microtech", - "CameraMate (DPCM_USB)", - US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ), -#else +#ifdef NO_SDDR09 UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100, "Microtech", "CameraMate", @@ -467,20 +467,7 @@ UNUSUAL_DEV( 0x04e6, 0x0002, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init, US_FL_SCM_MULT_TARG ), -#ifdef CONFIG_USB_STORAGE_SDDR09 -UNUSUAL_DEV( 0x04e6, 0x0003, 0x0000, 0x9999, - "Sandisk", - "ImageMate SDDR09", - US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init, - 0), - -/* This entry is from Andries.Brouwer@cwi.nl */ -UNUSUAL_DEV( 0x04e6, 0x0005, 0x0100, 0x0208, - "SCM Microsystems", - "eUSB SmartMedia / CompactFlash Adapter", - US_SC_SCSI, US_PR_DPCM_USB, usb_stor_sddr09_dpcm_init, - 0), -#else +#ifdef NO_SDDR09 UNUSUAL_DEV( 0x04e6, 0x0005, 0x0100, 0x0208, "SCM Microsystems", "eUSB CompactFlash Adapter", @@ -935,14 +922,6 @@ UNUSUAL_DEV( 0x0644, 0x0000, 0x0100, 0x0100, "Floppy Drive", US_SC_UFI, US_PR_CB, NULL, 0 ), -#ifdef CONFIG_USB_STORAGE_SDDR09 -UNUSUAL_DEV( 0x066b, 0x0105, 0x0100, 0x0100, - "Olympus", - "Camedia MAUSB-2", - US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init, - 0), -#endif - /* Reported by Darsen Lu */ UNUSUAL_DEV( 0x066f, 0x8000, 0x0001, 0x0001, "SigmaTel", @@ -1057,14 +1036,6 @@ UNUSUAL_DEV( 0x0781, 0x0100, 0x0100, 0x0100, US_SC_SCSI, US_PR_CB, NULL, US_FL_SINGLE_LUN ), -#ifdef CONFIG_USB_STORAGE_SDDR09 -UNUSUAL_DEV( 0x0781, 0x0200, 0x0000, 0x9999, - "Sandisk", - "ImageMate SDDR-09", - US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init, - 0), -#endif - #ifdef CONFIG_USB_STORAGE_FREECOM UNUSUAL_DEV( 0x07ab, 0xfc01, 0x0000, 0x9999, "Freecom", @@ -1091,12 +1062,7 @@ UNUSUAL_DEV( 0x07af, 0x0005, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init, US_FL_SCM_MULT_TARG ), -#ifdef CONFIG_USB_STORAGE_SDDR09 -UNUSUAL_DEV( 0x07af, 0x0006, 0x0100, 0x0100, - "Microtech", - "CameraMate (DPCM_USB)", - US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ), -#else +#ifdef NO_SDDR09 UNUSUAL_DEV( 0x07af, 0x0006, 0x0100, 0x0100, "Microtech", "CameraMate", diff --git a/drivers/usb/storage/unusual_sddr09.h b/drivers/usb/storage/unusual_sddr09.h new file mode 100644 index 000000000000..50cab511a4d7 --- /dev/null +++ b/drivers/usb/storage/unusual_sddr09.h @@ -0,0 +1,56 @@ +/* Unusual Devices File for SanDisk SDDR-09 SmartMedia reader + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if defined(CONFIG_USB_STORAGE_SDDR09) || \ + defined(CONFIG_USB_STORAGE_SDDR09_MODULE) + +UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100, + "Microtech", + "CameraMate (DPCM_USB)", + US_SC_SCSI, US_PR_DPCM_USB, NULL, 0), + +UNUSUAL_DEV( 0x04e6, 0x0003, 0x0000, 0x9999, + "Sandisk", + "ImageMate SDDR09", + US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init, + 0), + +/* This entry is from Andries.Brouwer@cwi.nl */ +UNUSUAL_DEV( 0x04e6, 0x0005, 0x0100, 0x0208, + "SCM Microsystems", + "eUSB SmartMedia / CompactFlash Adapter", + US_SC_SCSI, US_PR_DPCM_USB, usb_stor_sddr09_dpcm_init, + 0), + +UNUSUAL_DEV( 0x066b, 0x0105, 0x0100, 0x0100, + "Olympus", + "Camedia MAUSB-2", + US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init, + 0), + +UNUSUAL_DEV( 0x0781, 0x0200, 0x0000, 0x9999, + "Sandisk", + "ImageMate SDDR-09", + US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init, + 0), + +UNUSUAL_DEV( 0x07af, 0x0006, 0x0100, 0x0100, + "Microtech", + "CameraMate (DPCM_USB)", + US_SC_SCSI, US_PR_DPCM_USB, NULL, 0), + +#endif /* defined(CONFIG_USB_STORAGE_SDDR09) || ... */ diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 490ea761398c..33cce41a5e8a 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -69,9 +69,6 @@ #ifdef CONFIG_USB_STORAGE_USBAT #include "shuttle_usbat.h" #endif -#ifdef CONFIG_USB_STORAGE_SDDR09 -#include "sddr09.h" -#endif #ifdef CONFIG_USB_STORAGE_SDDR55 #include "sddr55.h" #endif @@ -631,15 +628,6 @@ static void get_transport(struct us_data *us) break; #endif -#ifdef CONFIG_USB_STORAGE_SDDR09 - case US_PR_EUSB_SDDR09: - us->transport_name = "EUSB/SDDR09"; - us->transport = sddr09_transport; - us->transport_reset = usb_stor_CB_reset; - us->max_lun = 0; - break; -#endif - #ifdef CONFIG_USB_STORAGE_SDDR55 case US_PR_SDDR55: us->transport_name = "SDDR55"; @@ -649,15 +637,6 @@ static void get_transport(struct us_data *us) break; #endif -#ifdef CONFIG_USB_STORAGE_DPCM - case US_PR_DPCM_USB: - us->transport_name = "Control/Bulk-EUSB/SDDR09"; - us->transport = dpcm_transport; - us->transport_reset = usb_stor_CB_reset; - us->max_lun = 1; - break; -#endif - #ifdef CONFIG_USB_STORAGE_FREECOM case US_PR_FREECOM: us->transport_name = "Freecom"; diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index 1924e3229409..f808c5262d0c 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -77,6 +77,7 @@ struct ignore_entry { } static struct ignore_entry ignore_ids[] = { +# include "unusual_sddr09.h" { } /* Terminating entry */ }; -- cgit v1.2.3 From 44d451e1e407729318d4ae915c073df340788b87 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:47:54 -0500 Subject: usb-storage: make isd200 a separate module This patch (as1208) converts usb-storage's isd200 subdriver into a separate module. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 +- drivers/usb/storage/Makefile | 3 +- drivers/usb/storage/isd200.c | 94 ++++++++++++++++++++++++++++++++++-- drivers/usb/storage/isd200.h | 31 ------------ drivers/usb/storage/unusual_devs.h | 42 ---------------- drivers/usb/storage/unusual_isd200.h | 57 ++++++++++++++++++++++ drivers/usb/storage/usb.c | 10 ---- drivers/usb/storage/usual-tables.c | 1 + 8 files changed, 154 insertions(+), 88 deletions(-) delete mode 100644 drivers/usb/storage/isd200.h create mode 100644 drivers/usb/storage/unusual_isd200.h diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 7be8899f2559..fc356a770a76 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -46,7 +46,7 @@ config USB_STORAGE_FREECOM Freecom has a web page at . config USB_STORAGE_ISD200 - bool "ISD-200 USB/ATA Bridge support" + tristate "ISD-200 USB/ATA Bridge support" depends on USB_STORAGE ---help--- Say Y here if you want to use USB Mass Store devices based @@ -61,6 +61,8 @@ config USB_STORAGE_ISD200 - CyQ've CQ8060A CDRW drive - Planex eXtreme Drive RX-25HU USB-IDE cable (not model RX-25U) + If this driver is compiled as a module, it will be named ums-isd200. + config USB_STORAGE_USBAT bool "USBAT/USBAT02-based storage support" depends on USB_STORAGE diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index a52740a95602..b47f94e59fdc 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -13,7 +13,6 @@ usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG) += debug.o usb-storage-obj-$(CONFIG_USB_STORAGE_USBAT) += shuttle_usbat.o usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR55) += sddr55.o usb-storage-obj-$(CONFIG_USB_STORAGE_FREECOM) += freecom.o -usb-storage-obj-$(CONFIG_USB_STORAGE_ISD200) += isd200.o usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB) += datafab.o usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA) += alauda.o @@ -30,6 +29,8 @@ else obj-$(CONFIG_USB) += libusual.o usual-tables.o endif +obj-$(CONFIG_USB_STORAGE_ISD200) += ums-isd200.o obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o +ums-isd200-objs := isd200.o ums-sddr09-objs := sddr09.o diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c index 383abf2516a5..df943008538c 100644 --- a/drivers/usb/storage/isd200.c +++ b/drivers/usb/storage/isd200.c @@ -44,6 +44,7 @@ #include #include +#include #include #include #include @@ -57,7 +58,50 @@ #include "protocol.h" #include "debug.h" #include "scsiglue.h" -#include "isd200.h" + + +static int isd200_Initialization(struct us_data *us); + + +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +struct usb_device_id isd200_usb_ids[] = { +# include "unusual_isd200.h" + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, isd200_usb_ids); + +#undef UNUSUAL_DEV +#undef USUAL_DEV + +/* + * The flags table + */ +#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ + vendor_name, product_name, use_protocol, use_transport, \ + init_function, Flags) \ +{ \ + .vendorName = vendor_name, \ + .productName = product_name, \ + .useProtocol = use_protocol, \ + .useTransport = use_transport, \ + .initFunction = init_function, \ +} + +static struct us_unusual_dev isd200_unusual_dev_list[] = { +# include "unusual_isd200.h" + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV +#undef USUAL_DEV /* Timeout defines (in Seconds) */ @@ -1518,7 +1562,7 @@ static int isd200_init_info(struct us_data *us) * Initialization for the ISD200 */ -int isd200_Initialization(struct us_data *us) +static int isd200_Initialization(struct us_data *us) { US_DEBUGP("ISD200 Initialization...\n"); @@ -1549,7 +1593,7 @@ int isd200_Initialization(struct us_data *us) * */ -void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us) +static void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us) { int sendToTransport = 1, orig_bufflen; union ata_cdb ataCdb; @@ -1570,3 +1614,47 @@ void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us) isd200_srb_set_bufflen(srb, orig_bufflen); } + +static int isd200_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct us_data *us; + int result; + + result = usb_stor_probe1(&us, intf, id, + (id - isd200_usb_ids) + isd200_unusual_dev_list); + if (result) + return result; + + us->protocol_name = "ISD200 ATA/ATAPI"; + us->proto_handler = isd200_ata_command; + + result = usb_stor_probe2(us); + return result; +} + +static struct usb_driver isd200_driver = { + .name = "ums-isd200", + .probe = isd200_probe, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = isd200_usb_ids, + .soft_unbind = 1, +}; + +static int __init isd200_init(void) +{ + return usb_register(&isd200_driver); +} + +static void __exit isd200_exit(void) +{ + usb_deregister(&isd200_driver); +} + +module_init(isd200_init); +module_exit(isd200_exit); diff --git a/drivers/usb/storage/isd200.h b/drivers/usb/storage/isd200.h deleted file mode 100644 index 0a35f4fa78f8..000000000000 --- a/drivers/usb/storage/isd200.h +++ /dev/null @@ -1,31 +0,0 @@ -/* Header File for In-System Design, Inc. ISD200 ASIC - * - * First release - * - * Current development and maintenance by: - * (c) 2000 In-System Design, Inc. (support@in-system.com) - * - * See isd200.c for more information. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _USB_ISD200_H -#define _USB_ISD200_H - -extern void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us); -extern int isd200_Initialization(struct us_data *us); - -#endif diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 1fe7062f1cda..83ce1d33554a 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -632,14 +632,6 @@ UNUSUAL_DEV( 0x054c, 0x0025, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_SINGLE_LUN ), -#ifdef CONFIG_USB_STORAGE_ISD200 -UNUSUAL_DEV( 0x054c, 0x002b, 0x0100, 0x0110, - "Sony", - "Portable USB Harddrive V2", - US_SC_ISD200, US_PR_BULK, isd200_Initialization, - 0 ), -#endif - /* Submitted by Olaf Hering, SuSE Bugzilla #49049 */ UNUSUAL_DEV( 0x054c, 0x002c, 0x0501, 0x2000, "Sony", @@ -785,32 +777,6 @@ UNUSUAL_DEV( 0x05ab, 0x0060, 0x1104, 0x1110, US_SC_SCSI, US_PR_BULK, NULL, US_FL_NEED_OVERRIDE ), -#ifdef CONFIG_USB_STORAGE_ISD200 -UNUSUAL_DEV( 0x05ab, 0x0031, 0x0100, 0x0110, - "In-System", - "USB/IDE Bridge (ATA/ATAPI)", - US_SC_ISD200, US_PR_BULK, isd200_Initialization, - 0 ), - -UNUSUAL_DEV( 0x05ab, 0x0301, 0x0100, 0x0110, - "In-System", - "Portable USB Harddrive V2", - US_SC_ISD200, US_PR_BULK, isd200_Initialization, - 0 ), - -UNUSUAL_DEV( 0x05ab, 0x0351, 0x0100, 0x0110, - "In-System", - "Portable USB Harddrive V2", - US_SC_ISD200, US_PR_BULK, isd200_Initialization, - 0 ), - -UNUSUAL_DEV( 0x05ab, 0x5701, 0x0100, 0x0110, - "In-System", - "USB Storage Adapter V2", - US_SC_ISD200, US_PR_BULK, isd200_Initialization, - 0 ), -#endif - /* Submitted by Sven Anderson * There are at least four ProductIDs used for iPods, so I added 0x1202 and * 0x1204. They just need the US_FL_FIX_CAPACITY. As the bcdDevice appears @@ -1375,14 +1341,6 @@ UNUSUAL_DEV( 0x0bc2, 0x3010, 0x0000, 0x0000, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_SANE_SENSE ), -#ifdef CONFIG_USB_STORAGE_ISD200 -UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110, - "ATI", - "USB Cable 205", - US_SC_ISD200, US_PR_BULK, isd200_Initialization, - 0 ), -#endif - #ifdef CONFIG_USB_STORAGE_DATAFAB UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff, "Acomdata", diff --git a/drivers/usb/storage/unusual_isd200.h b/drivers/usb/storage/unusual_isd200.h new file mode 100644 index 000000000000..0d99dde3382a --- /dev/null +++ b/drivers/usb/storage/unusual_isd200.h @@ -0,0 +1,57 @@ +/* Unusual Devices File for In-System Design, Inc. ISD200 ASIC + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if defined(CONFIG_USB_STORAGE_ISD200) || \ + defined(CONFIG_USB_STORAGE_ISD200_MODULE) + +UNUSUAL_DEV( 0x054c, 0x002b, 0x0100, 0x0110, + "Sony", + "Portable USB Harddrive V2", + US_SC_ISD200, US_PR_BULK, isd200_Initialization, + 0), + +UNUSUAL_DEV( 0x05ab, 0x0031, 0x0100, 0x0110, + "In-System", + "USB/IDE Bridge (ATA/ATAPI)", + US_SC_ISD200, US_PR_BULK, isd200_Initialization, + 0), + +UNUSUAL_DEV( 0x05ab, 0x0301, 0x0100, 0x0110, + "In-System", + "Portable USB Harddrive V2", + US_SC_ISD200, US_PR_BULK, isd200_Initialization, + 0), + +UNUSUAL_DEV( 0x05ab, 0x0351, 0x0100, 0x0110, + "In-System", + "Portable USB Harddrive V2", + US_SC_ISD200, US_PR_BULK, isd200_Initialization, + 0), + +UNUSUAL_DEV( 0x05ab, 0x5701, 0x0100, 0x0110, + "In-System", + "USB Storage Adapter V2", + US_SC_ISD200, US_PR_BULK, isd200_Initialization, + 0), + +UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110, + "ATI", + "USB Cable 205", + US_SC_ISD200, US_PR_BULK, isd200_Initialization, + 0), + +#endif /* defined(CONFIG_USB_STORAGE_ISD200) || ... */ diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 33cce41a5e8a..e65cbba452b0 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -75,9 +75,6 @@ #ifdef CONFIG_USB_STORAGE_FREECOM #include "freecom.h" #endif -#ifdef CONFIG_USB_STORAGE_ISD200 -#include "isd200.h" -#endif #ifdef CONFIG_USB_STORAGE_DATAFAB #include "datafab.h" #endif @@ -721,13 +718,6 @@ static void get_protocol(struct us_data *us) us->proto_handler = usb_stor_ufi_command; break; -#ifdef CONFIG_USB_STORAGE_ISD200 - case US_SC_ISD200: - us->protocol_name = "ISD200 ATA/ATAPI"; - us->proto_handler = isd200_ata_command; - break; -#endif - #ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB case US_SC_CYP_ATACB: us->protocol_name = "Transparent SCSI with Cypress ATACB"; diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index f808c5262d0c..61ebddcc9ae0 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -77,6 +77,7 @@ struct ignore_entry { } static struct ignore_entry ignore_ids[] = { +# include "unusual_isd200.h" # include "unusual_sddr09.h" { } /* Terminating entry */ }; -- cgit v1.2.3 From 8e7ea46ef972c293362f2d422932bf68076491ce Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:47:59 -0500 Subject: usb-storage: make sddr55 a separate module This patch (as1209) converts usb-storage's sddr55 subdriver into a separate module. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 +- drivers/usb/storage/Makefile | 3 +- drivers/usb/storage/sddr55.c | 92 ++++++++++++++++++++++++++++++++++-- drivers/usb/storage/sddr55.h | 32 ------------- drivers/usb/storage/unusual_devs.h | 32 ------------- drivers/usb/storage/unusual_sddr55.h | 44 +++++++++++++++++ drivers/usb/storage/usb.c | 12 ----- drivers/usb/storage/usual-tables.c | 1 + 8 files changed, 139 insertions(+), 81 deletions(-) delete mode 100644 drivers/usb/storage/sddr55.h create mode 100644 drivers/usb/storage/unusual_sddr55.h diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index fc356a770a76..e6cc245257f8 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -95,12 +95,14 @@ config USB_STORAGE_SDDR09 If this driver is compiled as a module, it will be named ums-sddr09. config USB_STORAGE_SDDR55 - bool "SanDisk SDDR-55 SmartMedia support" + tristate "SanDisk SDDR-55 SmartMedia support" depends on USB_STORAGE help Say Y here to include additional code to support the Sandisk SDDR-55 SmartMedia reader in the USB Mass Storage driver. + If this driver is compiled as a module, it will be named ums-sddr55. + config USB_STORAGE_JUMPSHOT bool "Lexar Jumpshot Compact Flash Reader" depends on USB_STORAGE diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index b47f94e59fdc..5fb7847e41a4 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -11,7 +11,6 @@ obj-$(CONFIG_USB_STORAGE) += usb-storage.o usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG) += debug.o usb-storage-obj-$(CONFIG_USB_STORAGE_USBAT) += shuttle_usbat.o -usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR55) += sddr55.o usb-storage-obj-$(CONFIG_USB_STORAGE_FREECOM) += freecom.o usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB) += datafab.o usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o @@ -31,6 +30,8 @@ endif obj-$(CONFIG_USB_STORAGE_ISD200) += ums-isd200.o obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o +obj-$(CONFIG_USB_STORAGE_SDDR55) += ums-sddr55.o ums-isd200-objs := isd200.o ums-sddr09-objs := sddr09.o +ums-sddr55-objs := sddr55.o diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c index 5a0106ba256c..e97716f8eb02 100644 --- a/drivers/usb/storage/sddr55.c +++ b/drivers/usb/storage/sddr55.c @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -33,7 +34,45 @@ #include "transport.h" #include "protocol.h" #include "debug.h" -#include "sddr55.h" + + +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +struct usb_device_id sddr55_usb_ids[] = { +# include "unusual_sddr55.h" + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, sddr55_usb_ids); + +#undef UNUSUAL_DEV + +/* + * The flags table + */ +#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ + vendor_name, product_name, use_protocol, use_transport, \ + init_function, Flags) \ +{ \ + .vendorName = vendor_name, \ + .productName = product_name, \ + .useProtocol = use_protocol, \ + .useTransport = use_transport, \ + .initFunction = init_function, \ +} + +static struct us_unusual_dev sddr55_unusual_dev_list[] = { +# include "unusual_sddr55.h" + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV #define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) ) @@ -513,7 +552,8 @@ static int sddr55_read_deviceID(struct us_data *us, } -int sddr55_reset(struct us_data *us) { +static int sddr55_reset(struct us_data *us) +{ return 0; } @@ -734,7 +774,7 @@ static void sddr55_card_info_destructor(void *extra) { /* * Transport for the Sandisk SDDR-55 */ -int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us) +static int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us) { int result; static unsigned char inquiry_response[8] = { @@ -931,3 +971,49 @@ int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us) return USB_STOR_TRANSPORT_FAILED; // FIXME: sense buffer? } + +static int sddr55_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct us_data *us; + int result; + + result = usb_stor_probe1(&us, intf, id, + (id - sddr55_usb_ids) + sddr55_unusual_dev_list); + if (result) + return result; + + us->transport_name = "SDDR55"; + us->transport = sddr55_transport; + us->transport_reset = sddr55_reset; + us->max_lun = 0; + + result = usb_stor_probe2(us); + return result; +} + +static struct usb_driver sddr55_driver = { + .name = "ums-sddr55", + .probe = sddr55_probe, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = sddr55_usb_ids, + .soft_unbind = 1, +}; + +static int __init sddr55_init(void) +{ + return usb_register(&sddr55_driver); +} + +static void __exit sddr55_exit(void) +{ + usb_deregister(&sddr55_driver); +} + +module_init(sddr55_init); +module_exit(sddr55_exit); diff --git a/drivers/usb/storage/sddr55.h b/drivers/usb/storage/sddr55.h deleted file mode 100644 index a815a0470c84..000000000000 --- a/drivers/usb/storage/sddr55.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Driver for SanDisk SDDR-55 SmartMedia reader - * Header File - * - * Current development and maintenance by: - * (c) 2002 Simon Munton - * - * See sddr55.c for more explanation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _USB_SHUTTLE_EUSB_SDDR55_H -#define _USB_SHUTTLE_EUSB_SDDR55_H - -/* Sandisk SDDR-55 stuff */ - -extern int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us); -extern int sddr55_reset(struct us_data *us); - -#endif diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 83ce1d33554a..50034e141f94 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1098,15 +1098,6 @@ UNUSUAL_DEV( 0x07c4, 0xa006, 0x0000, 0xffff, US_SC_SCSI, US_PR_DATAFAB, NULL, 0 ), #endif - -#ifdef CONFIG_USB_STORAGE_SDDR55 -/* Contributed by Peter Waechtler */ -UNUSUAL_DEV( 0x07c4, 0xa103, 0x0000, 0x9999, - "Datafab", - "MDSM-B reader", - US_SC_SCSI, US_PR_SDDR55, NULL, - US_FL_FIX_INQUIRY ), -#endif #ifdef CONFIG_USB_STORAGE_DATAFAB /* Submitted by Olaf Hering */ @@ -1116,14 +1107,6 @@ UNUSUAL_DEV( 0x07c4, 0xa109, 0x0000, 0xffff, US_SC_SCSI, US_PR_DATAFAB, NULL, 0 ), #endif -#ifdef CONFIG_USB_STORAGE_SDDR55 -/* SM part - aeb */ -UNUSUAL_DEV( 0x07c4, 0xa109, 0x0000, 0xffff, - "Datafab Systems, Inc.", - "USB to CF + SM Combo (LC1)", - US_SC_SCSI, US_PR_SDDR55, NULL, - US_FL_SINGLE_LUN ), -#endif #ifdef CONFIG_USB_STORAGE_DATAFAB /* Reported by Felix Moeller @@ -1348,13 +1331,6 @@ UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff, US_SC_SCSI, US_PR_DATAFAB, NULL, US_FL_SINGLE_LUN ), #endif -#ifdef CONFIG_USB_STORAGE_SDDR55 -UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff, - "Acomdata", - "SM", - US_SC_SCSI, US_PR_SDDR55, NULL, - US_FL_SINGLE_LUN ), -#endif UNUSUAL_DEV( 0x0d49, 0x7310, 0x0000, 0x9999, "Maxtor", @@ -2041,14 +2017,6 @@ UNUSUAL_DEV( 0x4146, 0xba01, 0x0100, 0x0100, "Micro Mini 1GB", US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ), -#ifdef CONFIG_USB_STORAGE_SDDR55 -UNUSUAL_DEV( 0x55aa, 0xa103, 0x0000, 0x9999, - "Sandisk", - "ImageMate SDDR55", - US_SC_SCSI, US_PR_SDDR55, NULL, - US_FL_SINGLE_LUN), -#endif - /* Reported by Andrew Simmons */ UNUSUAL_DEV( 0xed06, 0x4500, 0x0001, 0x0001, "DataStor", diff --git a/drivers/usb/storage/unusual_sddr55.h b/drivers/usb/storage/unusual_sddr55.h new file mode 100644 index 000000000000..ae81ef7a1cfd --- /dev/null +++ b/drivers/usb/storage/unusual_sddr55.h @@ -0,0 +1,44 @@ +/* Unusual Devices File for SanDisk SDDR-55 SmartMedia reader + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if defined(CONFIG_USB_STORAGE_SDDR55) || \ + defined(CONFIG_USB_STORAGE_SDDR55_MODULE) + +/* Contributed by Peter Waechtler */ +UNUSUAL_DEV( 0x07c4, 0xa103, 0x0000, 0x9999, + "Datafab", + "MDSM-B reader", + US_SC_SCSI, US_PR_SDDR55, NULL, + US_FL_FIX_INQUIRY), + +/* SM part - aeb */ +UNUSUAL_DEV( 0x07c4, 0xa109, 0x0000, 0xffff, + "Datafab Systems, Inc.", + "USB to CF + SM Combo (LC1)", + US_SC_SCSI, US_PR_SDDR55, NULL, 0), + +UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff, + "Acomdata", + "SM", + US_SC_SCSI, US_PR_SDDR55, NULL, 0), + +UNUSUAL_DEV( 0x55aa, 0xa103, 0x0000, 0x9999, + "Sandisk", + "ImageMate SDDR55", + US_SC_SCSI, US_PR_SDDR55, NULL, 0), + +#endif /* defined(CONFIG_USB_STORAGE_SDDR55) || ... */ diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index e65cbba452b0..238f271d8171 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -69,9 +69,6 @@ #ifdef CONFIG_USB_STORAGE_USBAT #include "shuttle_usbat.h" #endif -#ifdef CONFIG_USB_STORAGE_SDDR55 -#include "sddr55.h" -#endif #ifdef CONFIG_USB_STORAGE_FREECOM #include "freecom.h" #endif @@ -625,15 +622,6 @@ static void get_transport(struct us_data *us) break; #endif -#ifdef CONFIG_USB_STORAGE_SDDR55 - case US_PR_SDDR55: - us->transport_name = "SDDR55"; - us->transport = sddr55_transport; - us->transport_reset = sddr55_reset; - us->max_lun = 0; - break; -#endif - #ifdef CONFIG_USB_STORAGE_FREECOM case US_PR_FREECOM: us->transport_name = "Freecom"; diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index 61ebddcc9ae0..5f2703fa48e6 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -79,6 +79,7 @@ struct ignore_entry { static struct ignore_entry ignore_ids[] = { # include "unusual_isd200.h" # include "unusual_sddr09.h" +# include "unusual_sddr55.h" { } /* Terminating entry */ }; -- cgit v1.2.3 From d6c4ac5a419e468bcf478a522e71788f03e67623 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:48:04 -0500 Subject: usb-storage: make cypress_atacb a separate module This patch (as1210) converts usb-storage's cypress_atacb subdriver into a separate module. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 +- drivers/usb/storage/Makefile | 3 +- drivers/usb/storage/cypress_atacb.c | 88 ++++++++++++++++++++++++++++++++++- drivers/usb/storage/cypress_atacb.h | 25 ---------- drivers/usb/storage/unusual_cypress.h | 34 ++++++++++++++ drivers/usb/storage/unusual_devs.h | 16 ------- drivers/usb/storage/usb.c | 11 ----- drivers/usb/storage/usual-tables.c | 1 + 8 files changed, 127 insertions(+), 55 deletions(-) delete mode 100644 drivers/usb/storage/cypress_atacb.h create mode 100644 drivers/usb/storage/unusual_cypress.h diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index e6cc245257f8..2c73fa97d94d 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -146,7 +146,7 @@ config USB_STORAGE_KARMA operation. config USB_STORAGE_CYPRESS_ATACB - bool "SAT emulation on Cypress USB/ATA Bridge with ATACB" + tristate "SAT emulation on Cypress USB/ATA Bridge with ATACB" depends on USB_STORAGE ---help--- Say Y here if you want to use SAT (ata pass through) on devices based @@ -156,6 +156,8 @@ config USB_STORAGE_CYPRESS_ATACB If you say no here your device will still work with the standard usb mass storage class. + If this driver is compiled as a module, it will be named ums-cypress. + config USB_LIBUSUAL bool "The shared table of common (or usual) storage devices" depends on USB diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index 5fb7847e41a4..0650f022e561 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -17,7 +17,6 @@ usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA) += alauda.o usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH) += onetouch.o usb-storage-obj-$(CONFIG_USB_STORAGE_KARMA) += karma.o -usb-storage-obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += cypress_atacb.o usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \ initializers.o sierra_ms.o option_ms.o $(usb-storage-obj-y) @@ -28,10 +27,12 @@ else obj-$(CONFIG_USB) += libusual.o usual-tables.o endif +obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += ums-cypress.o obj-$(CONFIG_USB_STORAGE_ISD200) += ums-isd200.o obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o obj-$(CONFIG_USB_STORAGE_SDDR55) += ums-sddr55.o +ums-cypress-objs := cypress_atacb.o ums-isd200-objs := isd200.o ums-sddr09-objs := sddr09.o ums-sddr55-objs := sddr55.o diff --git a/drivers/usb/storage/cypress_atacb.c b/drivers/usb/storage/cypress_atacb.c index 9466a99baab6..19306f7b1dae 100644 --- a/drivers/usb/storage/cypress_atacb.c +++ b/drivers/usb/storage/cypress_atacb.c @@ -19,6 +19,7 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include #include #include #include @@ -29,6 +30,46 @@ #include "scsiglue.h" #include "debug.h" + +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +struct usb_device_id cypress_usb_ids[] = { +# include "unusual_cypress.h" + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, cypress_usb_ids); + +#undef UNUSUAL_DEV + +/* + * The flags table + */ +#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ + vendor_name, product_name, use_protocol, use_transport, \ + init_function, Flags) \ +{ \ + .vendorName = vendor_name, \ + .productName = product_name, \ + .useProtocol = use_protocol, \ + .useTransport = use_transport, \ + .initFunction = init_function, \ +} + +static struct us_unusual_dev cypress_unusual_dev_list[] = { +# include "unusual_cypress.h" + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV + + /* * ATACB is a protocol used on cypress usb<->ata bridge to * send raw ATA command over mass storage @@ -36,7 +77,7 @@ * More info that be found on cy7c68310_8.pdf and cy7c68300c_8.pdf * datasheet from cypress.com. */ -void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us) +static void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us) { unsigned char save_cmnd[MAX_COMMAND_SIZE]; @@ -197,3 +238,48 @@ end: if (srb->cmnd[0] == ATA_12) srb->cmd_len = 12; } + + +static int cypress_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct us_data *us; + int result; + + result = usb_stor_probe1(&us, intf, id, + (id - cypress_usb_ids) + cypress_unusual_dev_list); + if (result) + return result; + + us->protocol_name = "Transparent SCSI with Cypress ATACB"; + us->proto_handler = cypress_atacb_passthrough; + + result = usb_stor_probe2(us); + return result; +} + +static struct usb_driver cypress_driver = { + .name = "ums-cypress", + .probe = cypress_probe, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = cypress_usb_ids, + .soft_unbind = 1, +}; + +static int __init cypress_init(void) +{ + return usb_register(&cypress_driver); +} + +static void __exit cypress_exit(void) +{ + usb_deregister(&cypress_driver); +} + +module_init(cypress_init); +module_exit(cypress_exit); diff --git a/drivers/usb/storage/cypress_atacb.h b/drivers/usb/storage/cypress_atacb.h deleted file mode 100644 index fbada898d56b..000000000000 --- a/drivers/usb/storage/cypress_atacb.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Support for emulating SAT (ata pass through) on devices based - * on the Cypress USB/ATA bridge supporting ATACB. - * - * Copyright (c) 2008 Matthieu Castet (castet.matthieu@free.fr) - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _CYPRESS_ATACB_H_ -#define _CYPRESS_ATACB_H_ -extern void cypress_atacb_passthrough(struct scsi_cmnd*, struct us_data*); -#endif diff --git a/drivers/usb/storage/unusual_cypress.h b/drivers/usb/storage/unusual_cypress.h new file mode 100644 index 000000000000..44be6d75dab6 --- /dev/null +++ b/drivers/usb/storage/unusual_cypress.h @@ -0,0 +1,34 @@ +/* Unusual Devices File for devices based on the Cypress USB/ATA bridge + * with support for ATACB + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if defined(CONFIG_USB_STORAGE_CYPRESS_ATACB) || \ + defined(CONFIG_USB_STORAGE_CYPRESS_ATACB_MODULE) + +/* CY7C68300 : support atacb */ +UNUSUAL_DEV( 0x04b4, 0x6830, 0x0000, 0x9999, + "Cypress", + "Cypress AT2LP", + US_SC_CYP_ATACB, US_PR_DEVICE, NULL, 0), + +/* CY7C68310 : support atacb and atacb2 */ +UNUSUAL_DEV( 0x04b4, 0x6831, 0x0000, 0x9999, + "Cypress", + "Cypress ISD-300LP", + US_SC_CYP_ATACB, US_PR_DEVICE, NULL, 0), + +#endif /* defined(CONFIG_USB_STORAGE_CYPRESS_ATACB) || ... */ diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 50034e141f94..eff97aed7bfe 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -375,22 +375,6 @@ UNUSUAL_DEV( 0x04b3, 0x4001, 0x0110, 0x0110, US_SC_DEVICE, US_PR_CB, NULL, US_FL_MAX_SECTORS_MIN), -#ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB -/* CY7C68300 : support atacb */ -UNUSUAL_DEV( 0x04b4, 0x6830, 0x0000, 0x9999, - "Cypress", - "Cypress AT2LP", - US_SC_CYP_ATACB, US_PR_DEVICE, NULL, - 0), - -/* CY7C68310 : support atacb and atacb2 */ -UNUSUAL_DEV( 0x04b4, 0x6831, 0x0000, 0x9999, - "Cypress", - "Cypress ISD-300LP", - US_SC_CYP_ATACB, US_PR_DEVICE, NULL, - 0), -#endif - /* Reported by Simon Levitt * This entry needs Sub and Proto fields */ UNUSUAL_DEV( 0x04b8, 0x0601, 0x0100, 0x0100, diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 238f271d8171..241e1944cf10 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -87,9 +87,6 @@ #ifdef CONFIG_USB_STORAGE_KARMA #include "karma.h" #endif -#ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB -#include "cypress_atacb.h" -#endif #include "sierra_ms.h" #include "option_ms.h" @@ -705,14 +702,6 @@ static void get_protocol(struct us_data *us) us->protocol_name = "Uniform Floppy Interface (UFI)"; us->proto_handler = usb_stor_ufi_command; break; - -#ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB - case US_SC_CYP_ATACB: - us->protocol_name = "Transparent SCSI with Cypress ATACB"; - us->proto_handler = cypress_atacb_passthrough; - break; -#endif - } } diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index 5f2703fa48e6..be461ee9f005 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -77,6 +77,7 @@ struct ignore_entry { } static struct ignore_entry ignore_ids[] = { +# include "unusual_cypress.h" # include "unusual_isd200.h" # include "unusual_sddr09.h" # include "unusual_sddr55.h" -- cgit v1.2.3 From e9ad1f9594ec794741b6cb2a0e5f755f36ede71c Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:48:08 -0500 Subject: usb-storage: make shuttle_usbat a separate module This patch (as1211) converts usb-storage's shuttle_usbat subdriver into a separate module. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 +- drivers/usb/storage/Makefile | 3 +- drivers/usb/storage/shuttle_usbat.c | 199 ++++++++++++++++++++++++++++++++---- drivers/usb/storage/shuttle_usbat.h | 123 ---------------------- drivers/usb/storage/unusual_devs.h | 28 ----- drivers/usb/storage/unusual_usbat.h | 43 ++++++++ drivers/usb/storage/usb.c | 12 --- drivers/usb/storage/usual-tables.c | 1 + 8 files changed, 227 insertions(+), 186 deletions(-) delete mode 100644 drivers/usb/storage/shuttle_usbat.h create mode 100644 drivers/usb/storage/unusual_usbat.h diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 2c73fa97d94d..44c6b1940f77 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -64,7 +64,7 @@ config USB_STORAGE_ISD200 If this driver is compiled as a module, it will be named ums-isd200. config USB_STORAGE_USBAT - bool "USBAT/USBAT02-based storage support" + tristate "USBAT/USBAT02-based storage support" depends on USB_STORAGE help Say Y here to include additional code to support storage devices @@ -84,6 +84,8 @@ config USB_STORAGE_USBAT - RCA LYRA MP3 portable - Sandisk ImageMate SDDR-05b + If this driver is compiled as a module, it will be named ums-usbat. + config USB_STORAGE_SDDR09 tristate "SanDisk SDDR-09 (and other SmartMedia, including DPCM) support" depends on USB_STORAGE diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index 0650f022e561..2387368cb7ae 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -10,7 +10,6 @@ EXTRA_CFLAGS := -Idrivers/scsi obj-$(CONFIG_USB_STORAGE) += usb-storage.o usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG) += debug.o -usb-storage-obj-$(CONFIG_USB_STORAGE_USBAT) += shuttle_usbat.o usb-storage-obj-$(CONFIG_USB_STORAGE_FREECOM) += freecom.o usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB) += datafab.o usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o @@ -31,8 +30,10 @@ obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += ums-cypress.o obj-$(CONFIG_USB_STORAGE_ISD200) += ums-isd200.o obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o obj-$(CONFIG_USB_STORAGE_SDDR55) += ums-sddr55.o +obj-$(CONFIG_USB_STORAGE_USBAT) += ums-usbat.o ums-cypress-objs := cypress_atacb.o ums-isd200-objs := isd200.o ums-sddr09-objs := sddr09.o ums-sddr55-objs := sddr55.o +ums-usbat-objs := shuttle_usbat.o diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c index ae6d64810d2a..d4fe0bb327a7 100644 --- a/drivers/usb/storage/shuttle_usbat.c +++ b/drivers/usb/storage/shuttle_usbat.c @@ -42,6 +42,7 @@ */ #include +#include #include #include @@ -52,7 +53,97 @@ #include "transport.h" #include "protocol.h" #include "debug.h" -#include "shuttle_usbat.h" + + +/* Supported device types */ +#define USBAT_DEV_HP8200 0x01 +#define USBAT_DEV_FLASH 0x02 + +#define USBAT_EPP_PORT 0x10 +#define USBAT_EPP_REGISTER 0x30 +#define USBAT_ATA 0x40 +#define USBAT_ISA 0x50 + +/* Commands (need to be logically OR'd with an access type */ +#define USBAT_CMD_READ_REG 0x00 +#define USBAT_CMD_WRITE_REG 0x01 +#define USBAT_CMD_READ_BLOCK 0x02 +#define USBAT_CMD_WRITE_BLOCK 0x03 +#define USBAT_CMD_COND_READ_BLOCK 0x04 +#define USBAT_CMD_COND_WRITE_BLOCK 0x05 +#define USBAT_CMD_WRITE_REGS 0x07 + +/* Commands (these don't need an access type) */ +#define USBAT_CMD_EXEC_CMD 0x80 +#define USBAT_CMD_SET_FEAT 0x81 +#define USBAT_CMD_UIO 0x82 + +/* Methods of accessing UIO register */ +#define USBAT_UIO_READ 1 +#define USBAT_UIO_WRITE 0 + +/* Qualifier bits */ +#define USBAT_QUAL_FCQ 0x20 /* full compare */ +#define USBAT_QUAL_ALQ 0x10 /* auto load subcount */ + +/* USBAT Flash Media status types */ +#define USBAT_FLASH_MEDIA_NONE 0 +#define USBAT_FLASH_MEDIA_CF 1 + +/* USBAT Flash Media change types */ +#define USBAT_FLASH_MEDIA_SAME 0 +#define USBAT_FLASH_MEDIA_CHANGED 1 + +/* USBAT ATA registers */ +#define USBAT_ATA_DATA 0x10 /* read/write data (R/W) */ +#define USBAT_ATA_FEATURES 0x11 /* set features (W) */ +#define USBAT_ATA_ERROR 0x11 /* error (R) */ +#define USBAT_ATA_SECCNT 0x12 /* sector count (R/W) */ +#define USBAT_ATA_SECNUM 0x13 /* sector number (R/W) */ +#define USBAT_ATA_LBA_ME 0x14 /* cylinder low (R/W) */ +#define USBAT_ATA_LBA_HI 0x15 /* cylinder high (R/W) */ +#define USBAT_ATA_DEVICE 0x16 /* head/device selection (R/W) */ +#define USBAT_ATA_STATUS 0x17 /* device status (R) */ +#define USBAT_ATA_CMD 0x17 /* device command (W) */ +#define USBAT_ATA_ALTSTATUS 0x0E /* status (no clear IRQ) (R) */ + +/* USBAT User I/O Data registers */ +#define USBAT_UIO_EPAD 0x80 /* Enable Peripheral Control Signals */ +#define USBAT_UIO_CDT 0x40 /* Card Detect (Read Only) */ + /* CDT = ACKD & !UI1 & !UI0 */ +#define USBAT_UIO_1 0x20 /* I/O 1 */ +#define USBAT_UIO_0 0x10 /* I/O 0 */ +#define USBAT_UIO_EPP_ATA 0x08 /* 1=EPP mode, 0=ATA mode */ +#define USBAT_UIO_UI1 0x04 /* Input 1 */ +#define USBAT_UIO_UI0 0x02 /* Input 0 */ +#define USBAT_UIO_INTR_ACK 0x01 /* Interrupt (ATA/ISA)/Acknowledge (EPP) */ + +/* USBAT User I/O Enable registers */ +#define USBAT_UIO_DRVRST 0x80 /* Reset Peripheral */ +#define USBAT_UIO_ACKD 0x40 /* Enable Card Detect */ +#define USBAT_UIO_OE1 0x20 /* I/O 1 set=output/clr=input */ + /* If ACKD=1, set OE1 to 1 also. */ +#define USBAT_UIO_OE0 0x10 /* I/O 0 set=output/clr=input */ +#define USBAT_UIO_ADPRST 0x01 /* Reset SCM chip */ + +/* USBAT Features */ +#define USBAT_FEAT_ETEN 0x80 /* External trigger enable */ +#define USBAT_FEAT_U1 0x08 +#define USBAT_FEAT_U0 0x04 +#define USBAT_FEAT_ET1 0x02 +#define USBAT_FEAT_ET2 0x01 + +struct usbat_info { + int devicetype; + + /* Used for Flash readers only */ + unsigned long sectors; /* total sector count */ + unsigned long ssize; /* sector size in bytes */ + + unsigned char sense_key; + unsigned long sense_asc; /* additional sense code */ + unsigned long sense_ascq; /* additional sense code qualifier */ +}; #define short_pack(LSB,MSB) ( ((u16)(LSB)) | ( ((u16)(MSB))<<8 ) ) #define LSB_of(s) ((s)&0xFF) @@ -63,6 +154,48 @@ static int transferred = 0; static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us); static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us); +static int init_usbat_cd(struct us_data *us); +static int init_usbat_flash(struct us_data *us); + + +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +struct usb_device_id usbat_usb_ids[] = { +# include "unusual_usbat.h" + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, usbat_usb_ids); + +#undef UNUSUAL_DEV + +/* + * The flags table + */ +#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ + vendor_name, product_name, use_protocol, use_transport, \ + init_function, Flags) \ +{ \ + .vendorName = vendor_name, \ + .productName = product_name, \ + .useProtocol = use_protocol, \ + .useTransport = use_transport, \ + .initFunction = init_function, \ +} + +static struct us_unusual_dev usbat_unusual_dev_list[] = { +# include "unusual_usbat.h" + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV + /* * Convenience function to produce an ATA read/write sectors command * Use cmd=0x20 for read, cmd=0x30 for write @@ -1684,37 +1817,61 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us) return USB_STOR_TRANSPORT_FAILED; } -int init_usbat_cd(struct us_data *us) +static int init_usbat_cd(struct us_data *us) { return init_usbat(us, USBAT_DEV_HP8200); } - -int init_usbat_flash(struct us_data *us) +static int init_usbat_flash(struct us_data *us) { return init_usbat(us, USBAT_DEV_FLASH); } -int init_usbat_probe(struct us_data *us) +static int usbat_probe(struct usb_interface *intf, + const struct usb_device_id *id) { - return init_usbat(us, 0); + struct us_data *us; + int result; + + result = usb_stor_probe1(&us, intf, id, + (id - usbat_usb_ids) + usbat_unusual_dev_list); + if (result) + return result; + + /* The actual transport will be determined later by the + * initialization routine; this is just a placeholder. + */ + us->transport_name = "Shuttle USBAT"; + us->transport = usbat_flash_transport; + us->transport_reset = usb_stor_CB_reset; + us->max_lun = 1; + + result = usb_stor_probe2(us); + return result; } -/* - * Default transport function. Attempts to detect which transport function - * should be called, makes it the new default, and calls it. - * - * This function should never be called. Our usbat_init() function detects the - * device type and changes the us->transport ptr to the transport function - * relevant to the device. - * However, we'll support this impossible(?) case anyway. - */ -int usbat_transport(struct scsi_cmnd *srb, struct us_data *us) +static struct usb_driver usbat_driver = { + .name = "ums-usbat", + .probe = usbat_probe, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = usbat_usb_ids, + .soft_unbind = 1, +}; + +static int __init usbat_init(void) { - struct usbat_info *info = (struct usbat_info*) (us->extra); - - if (usbat_set_transport(us, info, 0)) - return USB_STOR_TRANSPORT_ERROR; + return usb_register(&usbat_driver); +} - return us->transport(srb, us); +static void __exit usbat_exit(void) +{ + usb_deregister(&usbat_driver); } + +module_init(usbat_init); +module_exit(usbat_exit); diff --git a/drivers/usb/storage/shuttle_usbat.h b/drivers/usb/storage/shuttle_usbat.h deleted file mode 100644 index d8bfc43e9044..000000000000 --- a/drivers/usb/storage/shuttle_usbat.h +++ /dev/null @@ -1,123 +0,0 @@ -/* Driver for SCM Microsystems USB-ATAPI cable - * Header File - * - * Current development and maintenance by: - * (c) 2000 Robert Baruch (autophile@dol.net) - * (c) 2004, 2005 Daniel Drake - * - * See shuttle_usbat.c for more explanation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _USB_SHUTTLE_USBAT_H -#define _USB_SHUTTLE_USBAT_H - -/* Supported device types */ -#define USBAT_DEV_HP8200 0x01 -#define USBAT_DEV_FLASH 0x02 - -#define USBAT_EPP_PORT 0x10 -#define USBAT_EPP_REGISTER 0x30 -#define USBAT_ATA 0x40 -#define USBAT_ISA 0x50 - -/* Commands (need to be logically OR'd with an access type */ -#define USBAT_CMD_READ_REG 0x00 -#define USBAT_CMD_WRITE_REG 0x01 -#define USBAT_CMD_READ_BLOCK 0x02 -#define USBAT_CMD_WRITE_BLOCK 0x03 -#define USBAT_CMD_COND_READ_BLOCK 0x04 -#define USBAT_CMD_COND_WRITE_BLOCK 0x05 -#define USBAT_CMD_WRITE_REGS 0x07 - -/* Commands (these don't need an access type) */ -#define USBAT_CMD_EXEC_CMD 0x80 -#define USBAT_CMD_SET_FEAT 0x81 -#define USBAT_CMD_UIO 0x82 - -/* Methods of accessing UIO register */ -#define USBAT_UIO_READ 1 -#define USBAT_UIO_WRITE 0 - -/* Qualifier bits */ -#define USBAT_QUAL_FCQ 0x20 /* full compare */ -#define USBAT_QUAL_ALQ 0x10 /* auto load subcount */ - -/* USBAT Flash Media status types */ -#define USBAT_FLASH_MEDIA_NONE 0 -#define USBAT_FLASH_MEDIA_CF 1 - -/* USBAT Flash Media change types */ -#define USBAT_FLASH_MEDIA_SAME 0 -#define USBAT_FLASH_MEDIA_CHANGED 1 - -/* USBAT ATA registers */ -#define USBAT_ATA_DATA 0x10 /* read/write data (R/W) */ -#define USBAT_ATA_FEATURES 0x11 /* set features (W) */ -#define USBAT_ATA_ERROR 0x11 /* error (R) */ -#define USBAT_ATA_SECCNT 0x12 /* sector count (R/W) */ -#define USBAT_ATA_SECNUM 0x13 /* sector number (R/W) */ -#define USBAT_ATA_LBA_ME 0x14 /* cylinder low (R/W) */ -#define USBAT_ATA_LBA_HI 0x15 /* cylinder high (R/W) */ -#define USBAT_ATA_DEVICE 0x16 /* head/device selection (R/W) */ -#define USBAT_ATA_STATUS 0x17 /* device status (R) */ -#define USBAT_ATA_CMD 0x17 /* device command (W) */ -#define USBAT_ATA_ALTSTATUS 0x0E /* status (no clear IRQ) (R) */ - -/* USBAT User I/O Data registers */ -#define USBAT_UIO_EPAD 0x80 /* Enable Peripheral Control Signals */ -#define USBAT_UIO_CDT 0x40 /* Card Detect (Read Only) */ - /* CDT = ACKD & !UI1 & !UI0 */ -#define USBAT_UIO_1 0x20 /* I/O 1 */ -#define USBAT_UIO_0 0x10 /* I/O 0 */ -#define USBAT_UIO_EPP_ATA 0x08 /* 1=EPP mode, 0=ATA mode */ -#define USBAT_UIO_UI1 0x04 /* Input 1 */ -#define USBAT_UIO_UI0 0x02 /* Input 0 */ -#define USBAT_UIO_INTR_ACK 0x01 /* Interrupt (ATA/ISA)/Acknowledge (EPP) */ - -/* USBAT User I/O Enable registers */ -#define USBAT_UIO_DRVRST 0x80 /* Reset Peripheral */ -#define USBAT_UIO_ACKD 0x40 /* Enable Card Detect */ -#define USBAT_UIO_OE1 0x20 /* I/O 1 set=output/clr=input */ - /* If ACKD=1, set OE1 to 1 also. */ -#define USBAT_UIO_OE0 0x10 /* I/O 0 set=output/clr=input */ -#define USBAT_UIO_ADPRST 0x01 /* Reset SCM chip */ - -/* USBAT Features */ -#define USBAT_FEAT_ETEN 0x80 /* External trigger enable */ -#define USBAT_FEAT_U1 0x08 -#define USBAT_FEAT_U0 0x04 -#define USBAT_FEAT_ET1 0x02 -#define USBAT_FEAT_ET2 0x01 - -extern int usbat_transport(struct scsi_cmnd *srb, struct us_data *us); -extern int init_usbat_cd(struct us_data *us); -extern int init_usbat_flash(struct us_data *us); -extern int init_usbat_probe(struct us_data *us); - -struct usbat_info { - int devicetype; - - /* Used for Flash readers only */ - unsigned long sectors; /* total sector count */ - unsigned long ssize; /* sector size in bytes */ - - unsigned char sense_key; - unsigned long sense_asc; /* additional sense code */ - unsigned long sense_ascq; /* additional sense code qualifier */ -}; - -#endif diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index eff97aed7bfe..6462c4c54dc0 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -85,18 +85,6 @@ UNUSUAL_DEV( 0x03f0, 0x0107, 0x0200, 0x0200, "CD-Writer+", US_SC_8070, US_PR_CB, NULL, 0), -#ifdef CONFIG_USB_STORAGE_USBAT -UNUSUAL_DEV( 0x03f0, 0x0207, 0x0001, 0x0001, - "HP", - "CD-Writer+ 8200e", - US_SC_8070, US_PR_USBAT, init_usbat_cd, 0), - -UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x0001, - "HP", - "CD-Writer+ CD-4e", - US_SC_8070, US_PR_USBAT, init_usbat_cd, 0), -#endif - /* Reported by Ben Efros */ UNUSUAL_DEV( 0x03f0, 0x070c, 0x0000, 0x0000, "HP", @@ -506,14 +494,6 @@ UNUSUAL_DEV( 0x04e6, 0x0101, 0x0200, 0x0200, "CD-RW Device", US_SC_8020, US_PR_CB, NULL, 0), -#ifdef CONFIG_USB_STORAGE_USBAT -UNUSUAL_DEV( 0x04e6, 0x1010, 0x0000, 0x9999, - "Shuttle/SCM", - "USBAT-02", - US_SC_SCSI, US_PR_USBAT, init_usbat_flash, - US_FL_SINGLE_LUN), -#endif - /* Reported by Dmitry Khlystov */ UNUSUAL_DEV( 0x04e8, 0x507c, 0x0220, 0x0220, "Samsung", @@ -972,14 +952,6 @@ UNUSUAL_DEV( 0x0781, 0x0002, 0x0009, 0x0009, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY ), -#ifdef CONFIG_USB_STORAGE_USBAT -UNUSUAL_DEV( 0x0781, 0x0005, 0x0005, 0x0005, - "Sandisk", - "ImageMate SDDR-05b", - US_SC_SCSI, US_PR_USBAT, init_usbat_flash, - US_FL_SINGLE_LUN ), -#endif - UNUSUAL_DEV( 0x0781, 0x0100, 0x0100, 0x0100, "Sandisk", "ImageMate SDDR-12", diff --git a/drivers/usb/storage/unusual_usbat.h b/drivers/usb/storage/unusual_usbat.h new file mode 100644 index 000000000000..80e869f10180 --- /dev/null +++ b/drivers/usb/storage/unusual_usbat.h @@ -0,0 +1,43 @@ +/* Unusual Devices File for SCM Microsystems (a.k.a. Shuttle) USB-ATAPI cable + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if defined(CONFIG_USB_STORAGE_USBAT) || \ + defined(CONFIG_USB_STORAGE_USBAT_MODULE) + +UNUSUAL_DEV( 0x03f0, 0x0207, 0x0001, 0x0001, + "HP", + "CD-Writer+ 8200e", + US_SC_8070, US_PR_USBAT, init_usbat_cd, 0), + +UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x0001, + "HP", + "CD-Writer+ CD-4e", + US_SC_8070, US_PR_USBAT, init_usbat_cd, 0), + +UNUSUAL_DEV( 0x04e6, 0x1010, 0x0000, 0x9999, + "Shuttle/SCM", + "USBAT-02", + US_SC_SCSI, US_PR_USBAT, init_usbat_flash, + US_FL_SINGLE_LUN), + +UNUSUAL_DEV( 0x0781, 0x0005, 0x0005, 0x0005, + "Sandisk", + "ImageMate SDDR-05b", + US_SC_SCSI, US_PR_USBAT, init_usbat_flash, + US_FL_SINGLE_LUN), + +#endif /* defined(CONFIG_USB_STORAGE_USBAT) || ... */ diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 241e1944cf10..3ad22a8142cc 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -66,9 +66,6 @@ #include "debug.h" #include "initializers.h" -#ifdef CONFIG_USB_STORAGE_USBAT -#include "shuttle_usbat.h" -#endif #ifdef CONFIG_USB_STORAGE_FREECOM #include "freecom.h" #endif @@ -610,15 +607,6 @@ static void get_transport(struct us_data *us) us->transport_reset = usb_stor_Bulk_reset; break; -#ifdef CONFIG_USB_STORAGE_USBAT - case US_PR_USBAT: - us->transport_name = "Shuttle USBAT"; - us->transport = usbat_transport; - us->transport_reset = usb_stor_CB_reset; - us->max_lun = 1; - break; -#endif - #ifdef CONFIG_USB_STORAGE_FREECOM case US_PR_FREECOM: us->transport_name = "Freecom"; diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index be461ee9f005..899a8c8da712 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -81,6 +81,7 @@ static struct ignore_entry ignore_ids[] = { # include "unusual_isd200.h" # include "unusual_sddr09.h" # include "unusual_sddr55.h" +# include "unusual_usbat.h" { } /* Terminating entry */ }; -- cgit v1.2.3 From c9feb1bc999a4d5b9e71b668cc3bef250bf3d8a6 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:48:11 -0500 Subject: usb-storage: make freecom a separate module This patch (as1212) converts usb-storage's freecom subdriver into a separate module. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 +- drivers/usb/storage/Makefile | 3 +- drivers/usb/storage/freecom.c | 95 +++++++++++++++++++++++++++++++++-- drivers/usb/storage/freecom.h | 34 ------------- drivers/usb/storage/unusual_devs.h | 7 --- drivers/usb/storage/unusual_freecom.h | 26 ++++++++++ drivers/usb/storage/usb.c | 12 ----- drivers/usb/storage/usual-tables.c | 1 + 8 files changed, 122 insertions(+), 60 deletions(-) delete mode 100644 drivers/usb/storage/freecom.h create mode 100644 drivers/usb/storage/unusual_freecom.h diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 44c6b1940f77..14508b8a55fb 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -39,12 +39,14 @@ config USB_STORAGE_DATAFAB Datafab has a web page at . config USB_STORAGE_FREECOM - bool "Freecom USB/ATAPI Bridge support" + tristate "Freecom USB/ATAPI Bridge support" depends on USB_STORAGE help Support for the Freecom USB to IDE/ATAPI adaptor. Freecom has a web page at . + If this driver is compiled as a module, it will be named ums-freecom. + config USB_STORAGE_ISD200 tristate "ISD-200 USB/ATA Bridge support" depends on USB_STORAGE diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index 2387368cb7ae..93e91ec3a2d2 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -10,7 +10,6 @@ EXTRA_CFLAGS := -Idrivers/scsi obj-$(CONFIG_USB_STORAGE) += usb-storage.o usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG) += debug.o -usb-storage-obj-$(CONFIG_USB_STORAGE_FREECOM) += freecom.o usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB) += datafab.o usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA) += alauda.o @@ -27,12 +26,14 @@ else endif obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += ums-cypress.o +obj-$(CONFIG_USB_STORAGE_FREECOM) += ums-freecom.o obj-$(CONFIG_USB_STORAGE_ISD200) += ums-isd200.o obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o obj-$(CONFIG_USB_STORAGE_SDDR55) += ums-sddr55.o obj-$(CONFIG_USB_STORAGE_USBAT) += ums-usbat.o ums-cypress-objs := cypress_atacb.o +ums-freecom-objs := freecom.o ums-isd200-objs := isd200.o ums-sddr09-objs := sddr09.o ums-sddr55-objs := sddr55.o diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c index 73ac7262239e..393047b3890d 100644 --- a/drivers/usb/storage/freecom.c +++ b/drivers/usb/storage/freecom.c @@ -26,6 +26,7 @@ * (http://www.freecom.de/) */ +#include #include #include @@ -33,7 +34,6 @@ #include "transport.h" #include "protocol.h" #include "debug.h" -#include "freecom.h" #ifdef CONFIG_USB_STORAGE_DEBUG static void pdump (void *, int); @@ -103,6 +103,47 @@ struct freecom_status { #define FCM_PACKET_LENGTH 64 #define FCM_STATUS_PACKET_LENGTH 4 +static int init_freecom(struct us_data *us); + + +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +struct usb_device_id freecom_usb_ids[] = { +# include "unusual_freecom.h" + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, freecom_usb_ids); + +#undef UNUSUAL_DEV + +/* + * The flags table + */ +#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ + vendor_name, product_name, use_protocol, use_transport, \ + init_function, Flags) \ +{ \ + .vendorName = vendor_name, \ + .productName = product_name, \ + .useProtocol = use_protocol, \ + .useTransport = use_transport, \ + .initFunction = init_function, \ +} + +static struct us_unusual_dev freecom_unusual_dev_list[] = { +# include "unusual_freecom.h" + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV + static int freecom_readdata (struct scsi_cmnd *srb, struct us_data *us, unsigned int ipipe, unsigned int opipe, int count) @@ -173,7 +214,7 @@ freecom_writedata (struct scsi_cmnd *srb, struct us_data *us, * Transport for the Freecom USB/IDE adaptor. * */ -int freecom_transport(struct scsi_cmnd *srb, struct us_data *us) +static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us) { struct freecom_cb_wrap *fcb; struct freecom_status *fst; @@ -377,8 +418,7 @@ int freecom_transport(struct scsi_cmnd *srb, struct us_data *us) return USB_STOR_TRANSPORT_GOOD; } -int -freecom_init (struct us_data *us) +static int init_freecom(struct us_data *us) { int result; char *buffer = us->iobuf; @@ -417,7 +457,7 @@ freecom_init (struct us_data *us) return USB_STOR_TRANSPORT_GOOD; } -int usb_stor_freecom_reset(struct us_data *us) +static int usb_stor_freecom_reset(struct us_data *us) { printk (KERN_CRIT "freecom reset called\n"); @@ -479,3 +519,48 @@ static void pdump (void *ibuffer, int length) } #endif +static int freecom_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct us_data *us; + int result; + + result = usb_stor_probe1(&us, intf, id, + (id - freecom_usb_ids) + freecom_unusual_dev_list); + if (result) + return result; + + us->transport_name = "Freecom"; + us->transport = freecom_transport; + us->transport_reset = usb_stor_freecom_reset; + us->max_lun = 0; + + result = usb_stor_probe2(us); + return result; +} + +static struct usb_driver freecom_driver = { + .name = "ums-freecom", + .probe = freecom_probe, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = freecom_usb_ids, + .soft_unbind = 1, +}; + +static int __init freecom_init(void) +{ + return usb_register(&freecom_driver); +} + +static void __exit freecom_exit(void) +{ + usb_deregister(&freecom_driver); +} + +module_init(freecom_init); +module_exit(freecom_exit); diff --git a/drivers/usb/storage/freecom.h b/drivers/usb/storage/freecom.h deleted file mode 100644 index 20d0fe6ba0c8..000000000000 --- a/drivers/usb/storage/freecom.h +++ /dev/null @@ -1,34 +0,0 @@ -/* Driver for Freecom USB/IDE adaptor - * - * Freecom v0.1: - * - * First release - * - * Current development and maintenance by: - * (c) 2000 David Brown - * - * See freecom.c for more explanation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _FREECOM_USB_H -#define _FREECOM_USB_H - -extern int freecom_transport(struct scsi_cmnd *srb, struct us_data *us); -extern int usb_stor_freecom_reset(struct us_data *us); -extern int freecom_init (struct us_data *us); - -#endif diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 6462c4c54dc0..eef2075cf2eb 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -958,13 +958,6 @@ UNUSUAL_DEV( 0x0781, 0x0100, 0x0100, 0x0100, US_SC_SCSI, US_PR_CB, NULL, US_FL_SINGLE_LUN ), -#ifdef CONFIG_USB_STORAGE_FREECOM -UNUSUAL_DEV( 0x07ab, 0xfc01, 0x0000, 0x9999, - "Freecom", - "USB-IDE", - US_SC_QIC, US_PR_FREECOM, freecom_init, 0), -#endif - /* Reported by Eero Volotinen */ UNUSUAL_DEV( 0x07ab, 0xfccd, 0x0000, 0x9999, "Freecom Technologies", diff --git a/drivers/usb/storage/unusual_freecom.h b/drivers/usb/storage/unusual_freecom.h new file mode 100644 index 000000000000..375867942391 --- /dev/null +++ b/drivers/usb/storage/unusual_freecom.h @@ -0,0 +1,26 @@ +/* Unusual Devices File for the Freecom USB/IDE adaptor + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if defined(CONFIG_USB_STORAGE_FREECOM) || \ + defined(CONFIG_USB_STORAGE_FREECOM_MODULE) + +UNUSUAL_DEV( 0x07ab, 0xfc01, 0x0000, 0x9999, + "Freecom", + "USB-IDE", + US_SC_QIC, US_PR_FREECOM, init_freecom, 0), + +#endif /* defined(CONFIG_USB_STORAGE_FREECOM) || ... */ diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 3ad22a8142cc..985275d5d4c5 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -66,9 +66,6 @@ #include "debug.h" #include "initializers.h" -#ifdef CONFIG_USB_STORAGE_FREECOM -#include "freecom.h" -#endif #ifdef CONFIG_USB_STORAGE_DATAFAB #include "datafab.h" #endif @@ -607,15 +604,6 @@ static void get_transport(struct us_data *us) us->transport_reset = usb_stor_Bulk_reset; break; -#ifdef CONFIG_USB_STORAGE_FREECOM - case US_PR_FREECOM: - us->transport_name = "Freecom"; - us->transport = freecom_transport; - us->transport_reset = usb_stor_freecom_reset; - us->max_lun = 0; - break; -#endif - #ifdef CONFIG_USB_STORAGE_DATAFAB case US_PR_DATAFAB: us->transport_name = "Datafab Bulk-Only"; diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index 899a8c8da712..a50f0eefb739 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -78,6 +78,7 @@ struct ignore_entry { static struct ignore_entry ignore_ids[] = { # include "unusual_cypress.h" +# include "unusual_freecom.h" # include "unusual_isd200.h" # include "unusual_sddr09.h" # include "unusual_sddr55.h" -- cgit v1.2.3 From 284999fe498f8244917ba484eb9d6db9ef47ddc5 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:48:15 -0500 Subject: usb-storage: make datafab a separate module This patch (as1213) converts usb-storage's datafab subdriver into a separate module. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 +- drivers/usb/storage/Makefile | 3 +- drivers/usb/storage/datafab.c | 100 +++++++++++++++++++++++++++++++++- drivers/usb/storage/datafab.h | 40 -------------- drivers/usb/storage/unusual_datafab.h | 98 +++++++++++++++++++++++++++++++++ drivers/usb/storage/unusual_devs.h | 86 ----------------------------- drivers/usb/storage/usb.c | 12 ---- drivers/usb/storage/usual-tables.c | 1 + 8 files changed, 202 insertions(+), 142 deletions(-) delete mode 100644 drivers/usb/storage/datafab.h create mode 100644 drivers/usb/storage/unusual_datafab.h diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 14508b8a55fb..7dac413e0f2f 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -32,12 +32,14 @@ config USB_STORAGE_DEBUG verbose debugging messages. config USB_STORAGE_DATAFAB - bool "Datafab Compact Flash Reader support" + tristate "Datafab Compact Flash Reader support" depends on USB_STORAGE help Support for certain Datafab CompactFlash readers. Datafab has a web page at . + If this driver is compiled as a module, it will be named ums-datafab. + config USB_STORAGE_FREECOM tristate "Freecom USB/ATAPI Bridge support" depends on USB_STORAGE diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index 93e91ec3a2d2..0f78bd680f0f 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -10,7 +10,6 @@ EXTRA_CFLAGS := -Idrivers/scsi obj-$(CONFIG_USB_STORAGE) += usb-storage.o usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG) += debug.o -usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB) += datafab.o usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA) += alauda.o usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH) += onetouch.o @@ -26,6 +25,7 @@ else endif obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += ums-cypress.o +obj-$(CONFIG_USB_STORAGE_DATAFAB) += ums-datafab.o obj-$(CONFIG_USB_STORAGE_FREECOM) += ums-freecom.o obj-$(CONFIG_USB_STORAGE_ISD200) += ums-isd200.o obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o @@ -33,6 +33,7 @@ obj-$(CONFIG_USB_STORAGE_SDDR55) += ums-sddr55.o obj-$(CONFIG_USB_STORAGE_USBAT) += ums-usbat.o ums-cypress-objs := cypress_atacb.o +ums-datafab-objs := datafab.o ums-freecom-objs := freecom.o ums-isd200-objs := isd200.o ums-sddr09-objs := sddr09.o diff --git a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c index 17f1ae232919..2d8d83519090 100644 --- a/drivers/usb/storage/datafab.c +++ b/drivers/usb/storage/datafab.c @@ -49,6 +49,7 @@ */ #include +#include #include #include @@ -58,12 +59,61 @@ #include "transport.h" #include "protocol.h" #include "debug.h" -#include "datafab.h" + +struct datafab_info { + unsigned long sectors; /* total sector count */ + unsigned long ssize; /* sector size in bytes */ + signed char lun; /* used for dual-slot readers */ + + /* the following aren't used yet */ + unsigned char sense_key; + unsigned long sense_asc; /* additional sense code */ + unsigned long sense_ascq; /* additional sense code qualifier */ +}; static int datafab_determine_lun(struct us_data *us, struct datafab_info *info); +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +struct usb_device_id datafab_usb_ids[] = { +# include "unusual_datafab.h" + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, datafab_usb_ids); + +#undef UNUSUAL_DEV + +/* + * The flags table + */ +#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ + vendor_name, product_name, use_protocol, use_transport, \ + init_function, Flags) \ +{ \ + .vendorName = vendor_name, \ + .productName = product_name, \ + .useProtocol = use_protocol, \ + .useTransport = use_transport, \ + .initFunction = init_function, \ +} + +static struct us_unusual_dev datafab_unusual_dev_list[] = { +# include "unusual_datafab.h" + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV + + static inline int datafab_bulk_read(struct us_data *us, unsigned char *data, unsigned int len) { if (len == 0) @@ -500,7 +550,7 @@ static void datafab_info_destructor(void *extra) // Transport for the Datafab MDCFE-B // -int datafab_transport(struct scsi_cmnd * srb, struct us_data *us) +static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us) { struct datafab_info *info; int rc; @@ -665,3 +715,49 @@ int datafab_transport(struct scsi_cmnd * srb, struct us_data *us) info->sense_ascq = 0x00; return USB_STOR_TRANSPORT_FAILED; } + +static int datafab_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct us_data *us; + int result; + + result = usb_stor_probe1(&us, intf, id, + (id - datafab_usb_ids) + datafab_unusual_dev_list); + if (result) + return result; + + us->transport_name = "Datafab Bulk-Only"; + us->transport = datafab_transport; + us->transport_reset = usb_stor_Bulk_reset; + us->max_lun = 1; + + result = usb_stor_probe2(us); + return result; +} + +static struct usb_driver datafab_driver = { + .name = "ums-datafab", + .probe = datafab_probe, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = datafab_usb_ids, + .soft_unbind = 1, +}; + +static int __init datafab_init(void) +{ + return usb_register(&datafab_driver); +} + +static void __exit datafab_exit(void) +{ + usb_deregister(&datafab_driver); +} + +module_init(datafab_init); +module_exit(datafab_exit); diff --git a/drivers/usb/storage/datafab.h b/drivers/usb/storage/datafab.h deleted file mode 100644 index 32e3f271e582..000000000000 --- a/drivers/usb/storage/datafab.h +++ /dev/null @@ -1,40 +0,0 @@ -/* Driver for Datafab MDCFE-B USB Compact Flash reader - * Header File - * - * Current development and maintenance by: - * (c) 2000 Jimmie Mayfield (mayfield+datafab@sackheads.org) - * - * See datafab.c for more explanation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _USB_DATAFAB_MDCFE_B_H -#define _USB_DATAFAB_MDCFE_B_H - -extern int datafab_transport(struct scsi_cmnd *srb, struct us_data *us); - -struct datafab_info { - unsigned long sectors; // total sector count - unsigned long ssize; // sector size in bytes - signed char lun; // used for dual-slot readers - - // the following aren't used yet - unsigned char sense_key; - unsigned long sense_asc; // additional sense code - unsigned long sense_ascq; // additional sense code qualifier -}; - -#endif diff --git a/drivers/usb/storage/unusual_datafab.h b/drivers/usb/storage/unusual_datafab.h new file mode 100644 index 000000000000..c9298ce9f223 --- /dev/null +++ b/drivers/usb/storage/unusual_datafab.h @@ -0,0 +1,98 @@ +/* Unusual Devices File for the Datafab USB Compact Flash reader + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if defined(CONFIG_USB_STORAGE_DATAFAB) || \ + defined(CONFIG_USB_STORAGE_DATAFAB_MODULE) + +UNUSUAL_DEV( 0x07c4, 0xa000, 0x0000, 0x0015, + "Datafab", + "MDCFE-B USB CF Reader", + US_SC_SCSI, US_PR_DATAFAB, NULL, + 0), + +/* + * The following Datafab-based devices may or may not work + * using the current driver...the 0xffff is arbitrary since I + * don't know what device versions exist for these guys. + * + * The 0xa003 and 0xa004 devices in particular I'm curious about. + * I'm told they exist but so far nobody has come forward to say that + * they work with this driver. Given the success we've had getting + * other Datafab-based cards operational with this driver, I've decided + * to leave these two devices in the list. + */ +UNUSUAL_DEV( 0x07c4, 0xa001, 0x0000, 0xffff, + "SIIG/Datafab", + "SIIG/Datafab Memory Stick+CF Reader/Writer", + US_SC_SCSI, US_PR_DATAFAB, NULL, + 0), + +/* Reported by Josef Reisinger */ +UNUSUAL_DEV( 0x07c4, 0xa002, 0x0000, 0xffff, + "Datafab/Unknown", + "MD2/MD3 Disk enclosure", + US_SC_SCSI, US_PR_DATAFAB, NULL, + US_FL_SINGLE_LUN), + +UNUSUAL_DEV( 0x07c4, 0xa003, 0x0000, 0xffff, + "Datafab/Unknown", + "Datafab-based Reader", + US_SC_SCSI, US_PR_DATAFAB, NULL, + 0), + +UNUSUAL_DEV( 0x07c4, 0xa004, 0x0000, 0xffff, + "Datafab/Unknown", + "Datafab-based Reader", + US_SC_SCSI, US_PR_DATAFAB, NULL, + 0), + +UNUSUAL_DEV( 0x07c4, 0xa005, 0x0000, 0xffff, + "PNY/Datafab", + "PNY/Datafab CF+SM Reader", + US_SC_SCSI, US_PR_DATAFAB, NULL, + 0), + +UNUSUAL_DEV( 0x07c4, 0xa006, 0x0000, 0xffff, + "Simple Tech/Datafab", + "Simple Tech/Datafab CF+SM Reader", + US_SC_SCSI, US_PR_DATAFAB, NULL, + 0), + +/* Submitted by Olaf Hering */ +UNUSUAL_DEV( 0x07c4, 0xa109, 0x0000, 0xffff, + "Datafab Systems, Inc.", + "USB to CF + SM Combo (LC1)", + US_SC_SCSI, US_PR_DATAFAB, NULL, + 0), + +/* Reported by Felix Moeller + * in Germany this is sold by Hama with the productnumber 46952 + * as "DualSlot CompactFlash(TM) & MStick Drive USB" + */ +UNUSUAL_DEV( 0x07c4, 0xa10b, 0x0000, 0xffff, + "DataFab Systems Inc.", + "USB CF+MS", + US_SC_SCSI, US_PR_DATAFAB, NULL, + 0), + +UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff, + "Acomdata", + "CF", + US_SC_SCSI, US_PR_DATAFAB, NULL, + US_FL_SINGLE_LUN), + +#endif /* defined(CONFIG_USB_STORAGE_DATAFAB) || ... */ diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index eef2075cf2eb..a5867c6d761b 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -992,84 +992,6 @@ UNUSUAL_DEV( 0x07b4, 0x010a, 0x0102, 0x0102, US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0 ), #endif -#ifdef CONFIG_USB_STORAGE_DATAFAB -UNUSUAL_DEV( 0x07c4, 0xa000, 0x0000, 0x0015, - "Datafab", - "MDCFE-B USB CF Reader", - US_SC_SCSI, US_PR_DATAFAB, NULL, - 0 ), - -/* - * The following Datafab-based devices may or may not work - * using the current driver...the 0xffff is arbitrary since I - * don't know what device versions exist for these guys. - * - * The 0xa003 and 0xa004 devices in particular I'm curious about. - * I'm told they exist but so far nobody has come forward to say that - * they work with this driver. Given the success we've had getting - * other Datafab-based cards operational with this driver, I've decided - * to leave these two devices in the list. - */ -UNUSUAL_DEV( 0x07c4, 0xa001, 0x0000, 0xffff, - "SIIG/Datafab", - "SIIG/Datafab Memory Stick+CF Reader/Writer", - US_SC_SCSI, US_PR_DATAFAB, NULL, - 0 ), - -/* Reported by Josef Reisinger */ -UNUSUAL_DEV( 0x07c4, 0xa002, 0x0000, 0xffff, - "Datafab/Unknown", - "MD2/MD3 Disk enclosure", - US_SC_SCSI, US_PR_DATAFAB, NULL, - US_FL_SINGLE_LUN ), - -UNUSUAL_DEV( 0x07c4, 0xa003, 0x0000, 0xffff, - "Datafab/Unknown", - "Datafab-based Reader", - US_SC_SCSI, US_PR_DATAFAB, NULL, - 0 ), - -UNUSUAL_DEV( 0x07c4, 0xa004, 0x0000, 0xffff, - "Datafab/Unknown", - "Datafab-based Reader", - US_SC_SCSI, US_PR_DATAFAB, NULL, - 0 ), - -UNUSUAL_DEV( 0x07c4, 0xa005, 0x0000, 0xffff, - "PNY/Datafab", - "PNY/Datafab CF+SM Reader", - US_SC_SCSI, US_PR_DATAFAB, NULL, - 0 ), - -UNUSUAL_DEV( 0x07c4, 0xa006, 0x0000, 0xffff, - "Simple Tech/Datafab", - "Simple Tech/Datafab CF+SM Reader", - US_SC_SCSI, US_PR_DATAFAB, NULL, - 0 ), -#endif - -#ifdef CONFIG_USB_STORAGE_DATAFAB -/* Submitted by Olaf Hering */ -UNUSUAL_DEV( 0x07c4, 0xa109, 0x0000, 0xffff, - "Datafab Systems, Inc.", - "USB to CF + SM Combo (LC1)", - US_SC_SCSI, US_PR_DATAFAB, NULL, - 0 ), -#endif - -#ifdef CONFIG_USB_STORAGE_DATAFAB -/* Reported by Felix Moeller - * in Germany this is sold by Hama with the productnumber 46952 - * as "DualSlot CompactFlash(TM) & MStick Drive USB" - */ -UNUSUAL_DEV( 0x07c4, 0xa10b, 0x0000, 0xffff, - "DataFab Systems Inc.", - "USB CF+MS", - US_SC_SCSI, US_PR_DATAFAB, NULL, - 0 ), - -#endif - /* Datafab KECF-USB / Sagatek DCS-CF / Simpletech Flashlink UCF-100 * Only revision 1.13 tested (same for all of the above devices, * based on the Datafab DF-UG-07 chip). Needed for US_FL_FIX_INQUIRY. @@ -1273,14 +1195,6 @@ UNUSUAL_DEV( 0x0bc2, 0x3010, 0x0000, 0x0000, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_SANE_SENSE ), -#ifdef CONFIG_USB_STORAGE_DATAFAB -UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff, - "Acomdata", - "CF", - US_SC_SCSI, US_PR_DATAFAB, NULL, - US_FL_SINGLE_LUN ), -#endif - UNUSUAL_DEV( 0x0d49, 0x7310, 0x0000, 0x9999, "Maxtor", "USB to SATA", diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 985275d5d4c5..a537b3513b9b 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -66,9 +66,6 @@ #include "debug.h" #include "initializers.h" -#ifdef CONFIG_USB_STORAGE_DATAFAB -#include "datafab.h" -#endif #ifdef CONFIG_USB_STORAGE_JUMPSHOT #include "jumpshot.h" #endif @@ -604,15 +601,6 @@ static void get_transport(struct us_data *us) us->transport_reset = usb_stor_Bulk_reset; break; -#ifdef CONFIG_USB_STORAGE_DATAFAB - case US_PR_DATAFAB: - us->transport_name = "Datafab Bulk-Only"; - us->transport = datafab_transport; - us->transport_reset = usb_stor_Bulk_reset; - us->max_lun = 1; - break; -#endif - #ifdef CONFIG_USB_STORAGE_JUMPSHOT case US_PR_JUMPSHOT: us->transport_name = "Lexar Jumpshot Control/Bulk"; diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index a50f0eefb739..c6ceac62cf60 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -78,6 +78,7 @@ struct ignore_entry { static struct ignore_entry ignore_ids[] = { # include "unusual_cypress.h" +# include "unusual_datafab.h" # include "unusual_freecom.h" # include "unusual_isd200.h" # include "unusual_sddr09.h" -- cgit v1.2.3 From 5778084264d76b583433abd3f7b9ba21a022189d Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:48:19 -0500 Subject: usb-storage: make jumpshot a separate module This patch (as1214) converts usb-storage's jumpshot subdriver into a separate module. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 +- drivers/usb/storage/Makefile | 3 +- drivers/usb/storage/jumpshot.c | 99 +++++++++++++++++++++++++++++++++- drivers/usb/storage/jumpshot.h | 39 -------------- drivers/usb/storage/unusual_devs.h | 8 --- drivers/usb/storage/unusual_jumpshot.h | 27 ++++++++++ drivers/usb/storage/usb.c | 12 ----- drivers/usb/storage/usual-tables.c | 1 + 8 files changed, 130 insertions(+), 63 deletions(-) delete mode 100644 drivers/usb/storage/jumpshot.h create mode 100644 drivers/usb/storage/unusual_jumpshot.h diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 7dac413e0f2f..43e1afeb7f8c 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -110,12 +110,14 @@ config USB_STORAGE_SDDR55 If this driver is compiled as a module, it will be named ums-sddr55. config USB_STORAGE_JUMPSHOT - bool "Lexar Jumpshot Compact Flash Reader" + tristate "Lexar Jumpshot Compact Flash Reader" depends on USB_STORAGE help Say Y here to include additional code to support the Lexar Jumpshot USB CompactFlash reader. + If this driver is compiled as a module, it will be named ums-jumpshot. + config USB_STORAGE_ALAUDA bool "Olympus MAUSB-10/Fuji DPC-R1 support" depends on USB_STORAGE diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index 0f78bd680f0f..7b9d53563d34 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -10,7 +10,6 @@ EXTRA_CFLAGS := -Idrivers/scsi obj-$(CONFIG_USB_STORAGE) += usb-storage.o usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG) += debug.o -usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA) += alauda.o usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH) += onetouch.o usb-storage-obj-$(CONFIG_USB_STORAGE_KARMA) += karma.o @@ -28,6 +27,7 @@ obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += ums-cypress.o obj-$(CONFIG_USB_STORAGE_DATAFAB) += ums-datafab.o obj-$(CONFIG_USB_STORAGE_FREECOM) += ums-freecom.o obj-$(CONFIG_USB_STORAGE_ISD200) += ums-isd200.o +obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += ums-jumpshot.o obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o obj-$(CONFIG_USB_STORAGE_SDDR55) += ums-sddr55.o obj-$(CONFIG_USB_STORAGE_USBAT) += ums-usbat.o @@ -36,6 +36,7 @@ ums-cypress-objs := cypress_atacb.o ums-datafab-objs := datafab.o ums-freecom-objs := freecom.o ums-isd200-objs := isd200.o +ums-jumpshot-objs := jumpshot.o ums-sddr09-objs := sddr09.o ums-sddr55-objs := sddr55.o ums-usbat-objs := shuttle_usbat.o diff --git a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c index df67f13c9e73..a50d6dc1fe64 100644 --- a/drivers/usb/storage/jumpshot.c +++ b/drivers/usb/storage/jumpshot.c @@ -46,6 +46,7 @@ */ #include +#include #include #include @@ -55,9 +56,57 @@ #include "transport.h" #include "protocol.h" #include "debug.h" -#include "jumpshot.h" +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +struct usb_device_id jumpshot_usb_ids[] = { +# include "unusual_jumpshot.h" + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, jumpshot_usb_ids); + +#undef UNUSUAL_DEV + +/* + * The flags table + */ +#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ + vendor_name, product_name, use_protocol, use_transport, \ + init_function, Flags) \ +{ \ + .vendorName = vendor_name, \ + .productName = product_name, \ + .useProtocol = use_protocol, \ + .useTransport = use_transport, \ + .initFunction = init_function, \ +} + +static struct us_unusual_dev jumpshot_unusual_dev_list[] = { +# include "unusual_jumpshot.h" + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV + + +struct jumpshot_info { + unsigned long sectors; /* total sector count */ + unsigned long ssize; /* sector size in bytes */ + + /* the following aren't used yet */ + unsigned char sense_key; + unsigned long sense_asc; /* additional sense code */ + unsigned long sense_ascq; /* additional sense code qualifier */ +}; + static inline int jumpshot_bulk_read(struct us_data *us, unsigned char *data, unsigned int len) @@ -429,7 +478,7 @@ static void jumpshot_info_destructor(void *extra) // Transport for the Lexar 'Jumpshot' // -int jumpshot_transport(struct scsi_cmnd * srb, struct us_data *us) +static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us) { struct jumpshot_info *info; int rc; @@ -592,3 +641,49 @@ int jumpshot_transport(struct scsi_cmnd * srb, struct us_data *us) info->sense_ascq = 0x00; return USB_STOR_TRANSPORT_FAILED; } + +static int jumpshot_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct us_data *us; + int result; + + result = usb_stor_probe1(&us, intf, id, + (id - jumpshot_usb_ids) + jumpshot_unusual_dev_list); + if (result) + return result; + + us->transport_name = "Lexar Jumpshot Control/Bulk"; + us->transport = jumpshot_transport; + us->transport_reset = usb_stor_Bulk_reset; + us->max_lun = 1; + + result = usb_stor_probe2(us); + return result; +} + +static struct usb_driver jumpshot_driver = { + .name = "ums-jumpshot", + .probe = jumpshot_probe, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = jumpshot_usb_ids, + .soft_unbind = 1, +}; + +static int __init jumpshot_init(void) +{ + return usb_register(&jumpshot_driver); +} + +static void __exit jumpshot_exit(void) +{ + usb_deregister(&jumpshot_driver); +} + +module_init(jumpshot_init); +module_exit(jumpshot_exit); diff --git a/drivers/usb/storage/jumpshot.h b/drivers/usb/storage/jumpshot.h deleted file mode 100644 index 19bac9d1558f..000000000000 --- a/drivers/usb/storage/jumpshot.h +++ /dev/null @@ -1,39 +0,0 @@ -/* Driver for Lexar "Jumpshot" USB Compact Flash reader - * Header File - * - * Current development and maintenance by: - * (c) 2000 Jimmie Mayfield (mayfield+usb@sackheads.org) - * - * See jumpshot.c for more explanation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _USB_JUMPSHOT_H -#define _USB_JUMPSHOT_H - -extern int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us); - -struct jumpshot_info { - unsigned long sectors; // total sector count - unsigned long ssize; // sector size in bytes - - // the following aren't used yet - unsigned char sense_key; - unsigned long sense_asc; // additional sense code - unsigned long sense_ascq; // additional sense code qualifier -}; - -#endif diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index a5867c6d761b..24e23c29d292 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -794,14 +794,6 @@ UNUSUAL_DEV( 0x05c6, 0x1000, 0x0000, 0x9999, US_SC_DEVICE, US_PR_DEVICE, option_ms_init, 0), -#ifdef CONFIG_USB_STORAGE_JUMPSHOT -UNUSUAL_DEV( 0x05dc, 0x0001, 0x0000, 0x0001, - "Lexar", - "Jumpshot USB CF Reader", - US_SC_SCSI, US_PR_JUMPSHOT, NULL, - US_FL_NEED_OVERRIDE ), -#endif - /* Reported by Blake Matheny */ UNUSUAL_DEV( 0x05dc, 0xb002, 0x0000, 0x0113, "Lexar", diff --git a/drivers/usb/storage/unusual_jumpshot.h b/drivers/usb/storage/unusual_jumpshot.h new file mode 100644 index 000000000000..2e549b1c2c62 --- /dev/null +++ b/drivers/usb/storage/unusual_jumpshot.h @@ -0,0 +1,27 @@ +/* Unusual Devices File for the Lexar "Jumpshot" Compact Flash reader + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if defined(CONFIG_USB_STORAGE_JUMPSHOT) || \ + defined(CONFIG_USB_STORAGE_JUMPSHOT_MODULE) + +UNUSUAL_DEV( 0x05dc, 0x0001, 0x0000, 0x0001, + "Lexar", + "Jumpshot USB CF Reader", + US_SC_SCSI, US_PR_JUMPSHOT, NULL, + US_FL_NEED_OVERRIDE), + +#endif /* defined(CONFIG_USB_STORAGE_JUMPSHOT) || ... */ diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index a537b3513b9b..2ea57691a7ba 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -66,9 +66,6 @@ #include "debug.h" #include "initializers.h" -#ifdef CONFIG_USB_STORAGE_JUMPSHOT -#include "jumpshot.h" -#endif #ifdef CONFIG_USB_STORAGE_ONETOUCH #include "onetouch.h" #endif @@ -601,15 +598,6 @@ static void get_transport(struct us_data *us) us->transport_reset = usb_stor_Bulk_reset; break; -#ifdef CONFIG_USB_STORAGE_JUMPSHOT - case US_PR_JUMPSHOT: - us->transport_name = "Lexar Jumpshot Control/Bulk"; - us->transport = jumpshot_transport; - us->transport_reset = usb_stor_Bulk_reset; - us->max_lun = 1; - break; -#endif - #ifdef CONFIG_USB_STORAGE_ALAUDA case US_PR_ALAUDA: us->transport_name = "Alauda Control/Bulk"; diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index c6ceac62cf60..182a097e0767 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -81,6 +81,7 @@ static struct ignore_entry ignore_ids[] = { # include "unusual_datafab.h" # include "unusual_freecom.h" # include "unusual_isd200.h" +# include "unusual_jumpshot.h" # include "unusual_sddr09.h" # include "unusual_sddr55.h" # include "unusual_usbat.h" -- cgit v1.2.3 From 26b9e3bca6c09362d45230402af5565500fd46b9 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:48:22 -0500 Subject: usb-storage: make alauda a separate module This patch (as1215) converts usb-storage's alauda subdriver into a separate module. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 +- drivers/usb/storage/Makefile | 3 +- drivers/usb/storage/alauda.c | 163 ++++++++++++++++++++++++++++++++++- drivers/usb/storage/alauda.h | 100 --------------------- drivers/usb/storage/unusual_alauda.h | 31 +++++++ drivers/usb/storage/unusual_devs.h | 14 --- drivers/usb/storage/usb.c | 12 --- drivers/usb/storage/usual-tables.c | 1 + 8 files changed, 197 insertions(+), 131 deletions(-) delete mode 100644 drivers/usb/storage/alauda.h create mode 100644 drivers/usb/storage/unusual_alauda.h diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 43e1afeb7f8c..c56c2c6d37b7 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -119,7 +119,7 @@ config USB_STORAGE_JUMPSHOT If this driver is compiled as a module, it will be named ums-jumpshot. config USB_STORAGE_ALAUDA - bool "Olympus MAUSB-10/Fuji DPC-R1 support" + tristate "Olympus MAUSB-10/Fuji DPC-R1 support" depends on USB_STORAGE help Say Y here to include additional code to support the Olympus MAUSB-10 @@ -128,6 +128,8 @@ config USB_STORAGE_ALAUDA These devices are based on the Alauda chip and support both XD and SmartMedia cards. + If this driver is compiled as a module, it will be named ums-alauda. + config USB_STORAGE_ONETOUCH bool "Support OneTouch Button on Maxtor Hard Drives" depends on USB_STORAGE diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index 7b9d53563d34..fea05c0b6765 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -10,7 +10,6 @@ EXTRA_CFLAGS := -Idrivers/scsi obj-$(CONFIG_USB_STORAGE) += usb-storage.o usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG) += debug.o -usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA) += alauda.o usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH) += onetouch.o usb-storage-obj-$(CONFIG_USB_STORAGE_KARMA) += karma.o @@ -23,6 +22,7 @@ else obj-$(CONFIG_USB) += libusual.o usual-tables.o endif +obj-$(CONFIG_USB_STORAGE_ALAUDA) += ums-alauda.o obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += ums-cypress.o obj-$(CONFIG_USB_STORAGE_DATAFAB) += ums-datafab.o obj-$(CONFIG_USB_STORAGE_FREECOM) += ums-freecom.o @@ -32,6 +32,7 @@ obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o obj-$(CONFIG_USB_STORAGE_SDDR55) += ums-sddr55.o obj-$(CONFIG_USB_STORAGE_USBAT) += ums-usbat.o +ums-alauda-objs := alauda.o ums-cypress-objs := cypress_atacb.o ums-datafab-objs := datafab.o ums-freecom-objs := freecom.o diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c index 5407411e30e0..d3a88ebe690b 100644 --- a/drivers/usb/storage/alauda.c +++ b/drivers/usb/storage/alauda.c @@ -31,6 +31,8 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include + #include #include #include @@ -39,7 +41,75 @@ #include "transport.h" #include "protocol.h" #include "debug.h" -#include "alauda.h" + +/* + * Status bytes + */ +#define ALAUDA_STATUS_ERROR 0x01 +#define ALAUDA_STATUS_READY 0x40 + +/* + * Control opcodes (for request field) + */ +#define ALAUDA_GET_XD_MEDIA_STATUS 0x08 +#define ALAUDA_GET_SM_MEDIA_STATUS 0x98 +#define ALAUDA_ACK_XD_MEDIA_CHANGE 0x0a +#define ALAUDA_ACK_SM_MEDIA_CHANGE 0x9a +#define ALAUDA_GET_XD_MEDIA_SIG 0x86 +#define ALAUDA_GET_SM_MEDIA_SIG 0x96 + +/* + * Bulk command identity (byte 0) + */ +#define ALAUDA_BULK_CMD 0x40 + +/* + * Bulk opcodes (byte 1) + */ +#define ALAUDA_BULK_GET_REDU_DATA 0x85 +#define ALAUDA_BULK_READ_BLOCK 0x94 +#define ALAUDA_BULK_ERASE_BLOCK 0xa3 +#define ALAUDA_BULK_WRITE_BLOCK 0xb4 +#define ALAUDA_BULK_GET_STATUS2 0xb7 +#define ALAUDA_BULK_RESET_MEDIA 0xe0 + +/* + * Port to operate on (byte 8) + */ +#define ALAUDA_PORT_XD 0x00 +#define ALAUDA_PORT_SM 0x01 + +/* + * LBA and PBA are unsigned ints. Special values. + */ +#define UNDEF 0xffff +#define SPARE 0xfffe +#define UNUSABLE 0xfffd + +struct alauda_media_info { + unsigned long capacity; /* total media size in bytes */ + unsigned int pagesize; /* page size in bytes */ + unsigned int blocksize; /* number of pages per block */ + unsigned int uzonesize; /* number of usable blocks per zone */ + unsigned int zonesize; /* number of blocks per zone */ + unsigned int blockmask; /* mask to get page from address */ + + unsigned char pageshift; + unsigned char blockshift; + unsigned char zoneshift; + + u16 **lba_to_pba; /* logical to physical block map */ + u16 **pba_to_lba; /* physical to logical block map */ +}; + +struct alauda_info { + struct alauda_media_info port[2]; + int wr_ep; /* endpoint to write data out of */ + + unsigned char sense_key; + unsigned long sense_asc; /* additional sense code */ + unsigned long sense_ascq; /* additional sense code qualifier */ +}; #define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) ) #define LSB_of(s) ((s)&0xFF) @@ -52,6 +122,48 @@ #define PBA_HI(pba) (pba >> 3) #define PBA_ZONE(pba) (pba >> 11) +static int init_alauda(struct us_data *us); + + +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +struct usb_device_id alauda_usb_ids[] = { +# include "unusual_alauda.h" + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, alauda_usb_ids); + +#undef UNUSUAL_DEV + +/* + * The flags table + */ +#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ + vendor_name, product_name, use_protocol, use_transport, \ + init_function, Flags) \ +{ \ + .vendorName = vendor_name, \ + .productName = product_name, \ + .useProtocol = use_protocol, \ + .useTransport = use_transport, \ + .initFunction = init_function, \ +} + +static struct us_unusual_dev alauda_unusual_dev_list[] = { +# include "unusual_alauda.h" + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV + + /* * Media handling */ @@ -998,7 +1110,7 @@ static void alauda_info_destructor(void *extra) /* * Initialize alauda_info struct and find the data-write endpoint */ -int init_alauda(struct us_data *us) +static int init_alauda(struct us_data *us) { struct alauda_info *info; struct usb_host_interface *altsetting = us->pusb_intf->cur_altsetting; @@ -1020,7 +1132,7 @@ int init_alauda(struct us_data *us) return USB_STOR_TRANSPORT_GOOD; } -int alauda_transport(struct scsi_cmnd *srb, struct us_data *us) +static int alauda_transport(struct scsi_cmnd *srb, struct us_data *us) { int rc; struct alauda_info *info = (struct alauda_info *) us->extra; @@ -1128,3 +1240,48 @@ int alauda_transport(struct scsi_cmnd *srb, struct us_data *us) return USB_STOR_TRANSPORT_FAILED; } +static int alauda_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct us_data *us; + int result; + + result = usb_stor_probe1(&us, intf, id, + (id - alauda_usb_ids) + alauda_unusual_dev_list); + if (result) + return result; + + us->transport_name = "Alauda Control/Bulk"; + us->transport = alauda_transport; + us->transport_reset = usb_stor_Bulk_reset; + us->max_lun = 1; + + result = usb_stor_probe2(us); + return result; +} + +static struct usb_driver alauda_driver = { + .name = "ums-alauda", + .probe = alauda_probe, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = alauda_usb_ids, + .soft_unbind = 1, +}; + +static int __init alauda_init(void) +{ + return usb_register(&alauda_driver); +} + +static void __exit alauda_exit(void) +{ + usb_deregister(&alauda_driver); +} + +module_init(alauda_init); +module_exit(alauda_exit); diff --git a/drivers/usb/storage/alauda.h b/drivers/usb/storage/alauda.h deleted file mode 100644 index a700f87d0803..000000000000 --- a/drivers/usb/storage/alauda.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Driver for Alauda-based card readers - * - * Current development and maintenance by: - * (c) 2005 Daniel Drake - * - * See alauda.c for more explanation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _USB_ALAUDA_H -#define _USB_ALAUDA_H - -/* - * Status bytes - */ -#define ALAUDA_STATUS_ERROR 0x01 -#define ALAUDA_STATUS_READY 0x40 - -/* - * Control opcodes (for request field) - */ -#define ALAUDA_GET_XD_MEDIA_STATUS 0x08 -#define ALAUDA_GET_SM_MEDIA_STATUS 0x98 -#define ALAUDA_ACK_XD_MEDIA_CHANGE 0x0a -#define ALAUDA_ACK_SM_MEDIA_CHANGE 0x9a -#define ALAUDA_GET_XD_MEDIA_SIG 0x86 -#define ALAUDA_GET_SM_MEDIA_SIG 0x96 - -/* - * Bulk command identity (byte 0) - */ -#define ALAUDA_BULK_CMD 0x40 - -/* - * Bulk opcodes (byte 1) - */ -#define ALAUDA_BULK_GET_REDU_DATA 0x85 -#define ALAUDA_BULK_READ_BLOCK 0x94 -#define ALAUDA_BULK_ERASE_BLOCK 0xa3 -#define ALAUDA_BULK_WRITE_BLOCK 0xb4 -#define ALAUDA_BULK_GET_STATUS2 0xb7 -#define ALAUDA_BULK_RESET_MEDIA 0xe0 - -/* - * Port to operate on (byte 8) - */ -#define ALAUDA_PORT_XD 0x00 -#define ALAUDA_PORT_SM 0x01 - -/* - * LBA and PBA are unsigned ints. Special values. - */ -#define UNDEF 0xffff -#define SPARE 0xfffe -#define UNUSABLE 0xfffd - -int init_alauda(struct us_data *us); -int alauda_transport(struct scsi_cmnd *srb, struct us_data *us); - -struct alauda_media_info { - unsigned long capacity; /* total media size in bytes */ - unsigned int pagesize; /* page size in bytes */ - unsigned int blocksize; /* number of pages per block */ - unsigned int uzonesize; /* number of usable blocks per zone */ - unsigned int zonesize; /* number of blocks per zone */ - unsigned int blockmask; /* mask to get page from address */ - - unsigned char pageshift; - unsigned char blockshift; - unsigned char zoneshift; - - u16 **lba_to_pba; /* logical to physical block map */ - u16 **pba_to_lba; /* physical to logical block map */ -}; - -struct alauda_info { - struct alauda_media_info port[2]; - int wr_ep; /* endpoint to write data out of */ - - unsigned char sense_key; - unsigned long sense_asc; /* additional sense code */ - unsigned long sense_ascq; /* additional sense code qualifier */ -}; - -#endif - diff --git a/drivers/usb/storage/unusual_alauda.h b/drivers/usb/storage/unusual_alauda.h new file mode 100644 index 000000000000..8c412f885dd2 --- /dev/null +++ b/drivers/usb/storage/unusual_alauda.h @@ -0,0 +1,31 @@ +/* Unusual Devices File for the Alauda-based card readers + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if defined(CONFIG_USB_STORAGE_ALAUDA) || \ + defined(CONFIG_USB_STORAGE_ALAUDA_MODULE) + +UNUSUAL_DEV( 0x0584, 0x0008, 0x0102, 0x0102, + "Fujifilm", + "DPC-R1 (Alauda)", + US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0), + +UNUSUAL_DEV( 0x07b4, 0x010a, 0x0102, 0x0102, + "Olympus", + "MAUSB-10 (Alauda)", + US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0), + +#endif /* defined(CONFIG_USB_STORAGE_ALAUDA) || ... */ diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 24e23c29d292..bcdb74dfa3db 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -692,13 +692,6 @@ UNUSUAL_DEV( 0x057b, 0x0022, 0x0000, 0x9999, "Silicon Media R/W", US_SC_DEVICE, US_PR_DEVICE, NULL, 0), -#ifdef CONFIG_USB_STORAGE_ALAUDA -UNUSUAL_DEV( 0x0584, 0x0008, 0x0102, 0x0102, - "Fujifilm", - "DPC-R1 (Alauda)", - US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0 ), -#endif - /* Reported by RTE */ UNUSUAL_DEV( 0x058f, 0x6387, 0x0141, 0x0141, "JetFlash", @@ -977,13 +970,6 @@ UNUSUAL_DEV( 0x07af, 0x0006, 0x0100, 0x0100, US_FL_SINGLE_LUN ), #endif -#ifdef CONFIG_USB_STORAGE_ALAUDA -UNUSUAL_DEV( 0x07b4, 0x010a, 0x0102, 0x0102, - "Olympus", - "MAUSB-10 (Alauda)", - US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0 ), -#endif - /* Datafab KECF-USB / Sagatek DCS-CF / Simpletech Flashlink UCF-100 * Only revision 1.13 tested (same for all of the above devices, * based on the Datafab DF-UG-07 chip). Needed for US_FL_FIX_INQUIRY. diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 2ea57691a7ba..cd039c008462 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -69,9 +69,6 @@ #ifdef CONFIG_USB_STORAGE_ONETOUCH #include "onetouch.h" #endif -#ifdef CONFIG_USB_STORAGE_ALAUDA -#include "alauda.h" -#endif #ifdef CONFIG_USB_STORAGE_KARMA #include "karma.h" #endif @@ -598,15 +595,6 @@ static void get_transport(struct us_data *us) us->transport_reset = usb_stor_Bulk_reset; break; -#ifdef CONFIG_USB_STORAGE_ALAUDA - case US_PR_ALAUDA: - us->transport_name = "Alauda Control/Bulk"; - us->transport = alauda_transport; - us->transport_reset = usb_stor_Bulk_reset; - us->max_lun = 1; - break; -#endif - #ifdef CONFIG_USB_STORAGE_KARMA case US_PR_KARMA: us->transport_name = "Rio Karma/Bulk"; diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index 182a097e0767..ad102e8e191b 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -77,6 +77,7 @@ struct ignore_entry { } static struct ignore_entry ignore_ids[] = { +# include "unusual_alauda.h" # include "unusual_cypress.h" # include "unusual_datafab.h" # include "unusual_freecom.h" -- cgit v1.2.3 From 1e5aac01cf81da28274eb417088f97f893aba856 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:48:26 -0500 Subject: usb-storage: make karma a separate module This patch (as1216) converts usb-storage's karma subdriver into a separate module. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 +- drivers/usb/storage/Makefile | 3 +- drivers/usb/storage/karma.c | 96 +++++++++++++++++++++++++++++++++++-- drivers/usb/storage/karma.h | 7 --- drivers/usb/storage/unusual_devs.h | 7 --- drivers/usb/storage/unusual_karma.h | 26 ++++++++++ drivers/usb/storage/usb.c | 12 ----- drivers/usb/storage/usual-tables.c | 1 + 8 files changed, 123 insertions(+), 33 deletions(-) delete mode 100644 drivers/usb/storage/karma.h create mode 100644 drivers/usb/storage/unusual_karma.h diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index c56c2c6d37b7..8adece1dd294 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -144,7 +144,7 @@ config USB_STORAGE_ONETOUCH cuts) config USB_STORAGE_KARMA - bool "Support for Rio Karma music player" + tristate "Support for Rio Karma music player" depends on USB_STORAGE help Say Y here to include additional code to support the Rio Karma @@ -155,6 +155,8 @@ config USB_STORAGE_KARMA on the resulting scsi device node returns the Karma to normal operation. + If this driver is compiled as a module, it will be named ums-karma. + config USB_STORAGE_CYPRESS_ATACB tristate "SAT emulation on Cypress USB/ATA Bridge with ATACB" depends on USB_STORAGE diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index fea05c0b6765..870680ea3709 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -11,7 +11,6 @@ obj-$(CONFIG_USB_STORAGE) += usb-storage.o usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG) += debug.o usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH) += onetouch.o -usb-storage-obj-$(CONFIG_USB_STORAGE_KARMA) += karma.o usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \ initializers.o sierra_ms.o option_ms.o $(usb-storage-obj-y) @@ -28,6 +27,7 @@ obj-$(CONFIG_USB_STORAGE_DATAFAB) += ums-datafab.o obj-$(CONFIG_USB_STORAGE_FREECOM) += ums-freecom.o obj-$(CONFIG_USB_STORAGE_ISD200) += ums-isd200.o obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += ums-jumpshot.o +obj-$(CONFIG_USB_STORAGE_KARMA) += ums-karma.o obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o obj-$(CONFIG_USB_STORAGE_SDDR55) += ums-sddr55.o obj-$(CONFIG_USB_STORAGE_USBAT) += ums-usbat.o @@ -38,6 +38,7 @@ ums-datafab-objs := datafab.o ums-freecom-objs := freecom.o ums-isd200-objs := isd200.o ums-jumpshot-objs := jumpshot.o +ums-karma-objs := karma.o ums-sddr09-objs := sddr09.o ums-sddr55-objs := sddr55.o ums-usbat-objs := shuttle_usbat.o diff --git a/drivers/usb/storage/karma.c b/drivers/usb/storage/karma.c index 0d79ae5683f7..cfb8e60866b8 100644 --- a/drivers/usb/storage/karma.c +++ b/drivers/usb/storage/karma.c @@ -18,6 +18,8 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include + #include #include #include @@ -25,7 +27,6 @@ #include "usb.h" #include "transport.h" #include "debug.h" -#include "karma.h" #define RIO_PREFIX "RIOP\x00" #define RIO_PREFIX_LEN 5 @@ -36,13 +37,53 @@ #define RIO_LEAVE_STORAGE 0x2 #define RIO_RESET 0xC -extern int usb_stor_Bulk_transport(struct scsi_cmnd *, struct us_data *); - struct karma_data { int in_storage; char *recv; }; +static int rio_karma_init(struct us_data *us); + + +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +struct usb_device_id karma_usb_ids[] = { +# include "unusual_karma.h" + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, karma_usb_ids); + +#undef UNUSUAL_DEV + +/* + * The flags table + */ +#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ + vendor_name, product_name, use_protocol, use_transport, \ + init_function, Flags) \ +{ \ + .vendorName = vendor_name, \ + .productName = product_name, \ + .useProtocol = use_protocol, \ + .useTransport = use_transport, \ + .initFunction = init_function, \ +} + +static struct us_unusual_dev karma_unusual_dev_list[] = { +# include "unusual_karma.h" + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV + + /* * Send commands to Rio Karma. * @@ -104,7 +145,7 @@ err: * Trap START_STOP and READ_10 to leave/re-enter storage mode. * Everything else is propagated to the normal bulk layer. */ -int rio_karma_transport(struct scsi_cmnd *srb, struct us_data *us) +static int rio_karma_transport(struct scsi_cmnd *srb, struct us_data *us) { int ret; struct karma_data *data = (struct karma_data *) us->extra; @@ -133,7 +174,7 @@ static void rio_karma_destructor(void *extra) kfree(data->recv); } -int rio_karma_init(struct us_data *us) +static int rio_karma_init(struct us_data *us) { int ret = 0; struct karma_data *data = kzalloc(sizeof(struct karma_data), GFP_NOIO); @@ -153,3 +194,48 @@ int rio_karma_init(struct us_data *us) out: return ret; } + +static int karma_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct us_data *us; + int result; + + result = usb_stor_probe1(&us, intf, id, + (id - karma_usb_ids) + karma_unusual_dev_list); + if (result) + return result; + + us->transport_name = "Rio Karma/Bulk"; + us->transport = rio_karma_transport; + us->transport_reset = usb_stor_Bulk_reset; + + result = usb_stor_probe2(us); + return result; +} + +static struct usb_driver karma_driver = { + .name = "ums-karma", + .probe = karma_probe, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = karma_usb_ids, + .soft_unbind = 1, +}; + +static int __init karma_init(void) +{ + return usb_register(&karma_driver); +} + +static void __exit karma_exit(void) +{ + usb_deregister(&karma_driver); +} + +module_init(karma_init); +module_exit(karma_exit); diff --git a/drivers/usb/storage/karma.h b/drivers/usb/storage/karma.h deleted file mode 100644 index 8a60972af8c5..000000000000 --- a/drivers/usb/storage/karma.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _KARMA_USB_H -#define _KARMA_USB_H - -extern int rio_karma_init(struct us_data *us); -extern int rio_karma_transport(struct scsi_cmnd *srb, struct us_data *us); - -#endif diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index bcdb74dfa3db..83e34a6ad59d 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -276,13 +276,6 @@ UNUSUAL_DEV( 0x0457, 0x0151, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ), -#ifdef CONFIG_USB_STORAGE_KARMA -UNUSUAL_DEV( 0x045a, 0x5210, 0x0101, 0x0101, - "Rio", - "Rio Karma", - US_SC_SCSI, US_PR_KARMA, rio_karma_init, 0), -#endif - /* Reported by Tamas Kerecsen * Obviously the PROM has not been customized by the VAR; * the Vendor and Product string descriptors are: diff --git a/drivers/usb/storage/unusual_karma.h b/drivers/usb/storage/unusual_karma.h new file mode 100644 index 000000000000..12ae3a03e802 --- /dev/null +++ b/drivers/usb/storage/unusual_karma.h @@ -0,0 +1,26 @@ +/* Unusual Devices File for the Rio Karma + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if defined(CONFIG_USB_STORAGE_KARMA) || \ + defined(CONFIG_USB_STORAGE_KARMA_MODULE) + +UNUSUAL_DEV( 0x045a, 0x5210, 0x0101, 0x0101, + "Rio", + "Rio Karma", + US_SC_SCSI, US_PR_KARMA, rio_karma_init, 0), + +#endif /* defined(CONFIG_USB_STORAGE_KARMA) || ... */ diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index cd039c008462..c5abf9bbce16 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -69,9 +69,6 @@ #ifdef CONFIG_USB_STORAGE_ONETOUCH #include "onetouch.h" #endif -#ifdef CONFIG_USB_STORAGE_KARMA -#include "karma.h" -#endif #include "sierra_ms.h" #include "option_ms.h" @@ -594,15 +591,6 @@ static void get_transport(struct us_data *us) us->transport = usb_stor_Bulk_transport; us->transport_reset = usb_stor_Bulk_reset; break; - -#ifdef CONFIG_USB_STORAGE_KARMA - case US_PR_KARMA: - us->transport_name = "Rio Karma/Bulk"; - us->transport = rio_karma_transport; - us->transport_reset = usb_stor_Bulk_reset; - break; -#endif - } } diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index ad102e8e191b..bce086fcef5e 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -83,6 +83,7 @@ static struct ignore_entry ignore_ids[] = { # include "unusual_freecom.h" # include "unusual_isd200.h" # include "unusual_jumpshot.h" +# include "unusual_karma.h" # include "unusual_sddr09.h" # include "unusual_sddr55.h" # include "unusual_usbat.h" -- cgit v1.2.3 From 8777a46e3367cf4c41e8212057ddd3b4811d8bf8 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:48:33 -0500 Subject: usb-storage: make onetouch a separate module This patch (as1217) converts usb-storage's onetouch subdriver into a separate module. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 +- drivers/usb/storage/Makefile | 3 +- drivers/usb/storage/onetouch.c | 90 +++++++++++++++++++++++++++++++++- drivers/usb/storage/onetouch.h | 9 ---- drivers/usb/storage/unusual_devs.h | 17 ------- drivers/usb/storage/unusual_onetouch.h | 36 ++++++++++++++ drivers/usb/storage/usb.c | 3 -- drivers/usb/storage/usual-tables.c | 1 + 8 files changed, 130 insertions(+), 33 deletions(-) delete mode 100644 drivers/usb/storage/onetouch.h create mode 100644 drivers/usb/storage/unusual_onetouch.h diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 8adece1dd294..8a372bac0e43 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -131,7 +131,7 @@ config USB_STORAGE_ALAUDA If this driver is compiled as a module, it will be named ums-alauda. config USB_STORAGE_ONETOUCH - bool "Support OneTouch Button on Maxtor Hard Drives" + tristate "Support OneTouch Button on Maxtor Hard Drives" depends on USB_STORAGE depends on INPUT=y || INPUT=USB_STORAGE help @@ -143,6 +143,8 @@ config USB_STORAGE_ONETOUCH this input in any keybinding software. (e.g. gnome's keyboard short- cuts) + If this driver is compiled as a module, it will be named ums-onetouch. + config USB_STORAGE_KARMA tristate "Support for Rio Karma music player" depends on USB_STORAGE diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index 870680ea3709..5be54c019662 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -10,7 +10,6 @@ EXTRA_CFLAGS := -Idrivers/scsi obj-$(CONFIG_USB_STORAGE) += usb-storage.o usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG) += debug.o -usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH) += onetouch.o usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \ initializers.o sierra_ms.o option_ms.o $(usb-storage-obj-y) @@ -28,6 +27,7 @@ obj-$(CONFIG_USB_STORAGE_FREECOM) += ums-freecom.o obj-$(CONFIG_USB_STORAGE_ISD200) += ums-isd200.o obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += ums-jumpshot.o obj-$(CONFIG_USB_STORAGE_KARMA) += ums-karma.o +obj-$(CONFIG_USB_STORAGE_ONETOUCH) += ums-onetouch.o obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o obj-$(CONFIG_USB_STORAGE_SDDR55) += ums-sddr55.o obj-$(CONFIG_USB_STORAGE_USBAT) += ums-usbat.o @@ -39,6 +39,7 @@ ums-freecom-objs := freecom.o ums-isd200-objs := isd200.o ums-jumpshot-objs := jumpshot.o ums-karma-objs := karma.o +ums-onetouch-objs := onetouch.o ums-sddr09-objs := sddr09.o ums-sddr55-objs := sddr55.o ums-usbat-objs := shuttle_usbat.o diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c index c7bf8954b4e4..8bd095635a99 100644 --- a/drivers/usb/storage/onetouch.c +++ b/drivers/usb/storage/onetouch.c @@ -35,9 +35,12 @@ #include #include #include "usb.h" -#include "onetouch.h" #include "debug.h" +#define ONETOUCH_PKT_LEN 0x02 +#define ONETOUCH_BUTTON KEY_PROG1 + +static int onetouch_connect_input(struct us_data *ss); static void onetouch_release_input(void *onetouch_); struct usb_onetouch { @@ -52,6 +55,46 @@ struct usb_onetouch { unsigned int is_open:1; }; + +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +struct usb_device_id onetouch_usb_ids[] = { +# include "unusual_onetouch.h" + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, onetouch_usb_ids); + +#undef UNUSUAL_DEV + +/* + * The flags table + */ +#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ + vendor_name, product_name, use_protocol, use_transport, \ + init_function, Flags) \ +{ \ + .vendorName = vendor_name, \ + .productName = product_name, \ + .useProtocol = use_protocol, \ + .useTransport = use_transport, \ + .initFunction = init_function, \ +} + +static struct us_unusual_dev onetouch_unusual_dev_list[] = { +# include "unusual_onetouch.h" + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV + + static void usb_onetouch_irq(struct urb *urb) { struct usb_onetouch *onetouch = urb->context; @@ -127,7 +170,7 @@ static void usb_onetouch_pm_hook(struct us_data *us, int action) } #endif /* CONFIG_PM */ -int onetouch_connect_input(struct us_data *ss) +static int onetouch_connect_input(struct us_data *ss) { struct usb_device *udev = ss->pusb_dev; struct usb_host_interface *interface; @@ -236,3 +279,46 @@ static void onetouch_release_input(void *onetouch_) onetouch->data, onetouch->data_dma); } } + +static int onetouch_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct us_data *us; + int result; + + result = usb_stor_probe1(&us, intf, id, + (id - onetouch_usb_ids) + onetouch_unusual_dev_list); + if (result) + return result; + + /* Use default transport and protocol */ + + result = usb_stor_probe2(us); + return result; +} + +static struct usb_driver onetouch_driver = { + .name = "ums-onetouch", + .probe = onetouch_probe, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = onetouch_usb_ids, + .soft_unbind = 1, +}; + +static int __init onetouch_init(void) +{ + return usb_register(&onetouch_driver); +} + +static void __exit onetouch_exit(void) +{ + usb_deregister(&onetouch_driver); +} + +module_init(onetouch_init); +module_exit(onetouch_exit); diff --git a/drivers/usb/storage/onetouch.h b/drivers/usb/storage/onetouch.h deleted file mode 100644 index 41c7aa8f0446..000000000000 --- a/drivers/usb/storage/onetouch.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef _ONETOUCH_H_ -#define _ONETOUCH_H_ - -#define ONETOUCH_PKT_LEN 0x02 -#define ONETOUCH_BUTTON KEY_PROG1 - -int onetouch_connect_input(struct us_data *ss); - -#endif diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 83e34a6ad59d..1c1f643e8a78 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1182,23 +1182,6 @@ UNUSUAL_DEV( 0x0c45, 0x1060, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_SINGLE_LUN ), -/* Submitted by: Nick Sillik - * Needed for OneTouch extension to usb-storage - * - */ -#ifdef CONFIG_USB_STORAGE_ONETOUCH - UNUSUAL_DEV( 0x0d49, 0x7000, 0x0000, 0x9999, - "Maxtor", - "OneTouch External Harddrive", - US_SC_DEVICE, US_PR_DEVICE, onetouch_connect_input, - 0), - UNUSUAL_DEV( 0x0d49, 0x7010, 0x0000, 0x9999, - "Maxtor", - "OneTouch External Harddrive", - US_SC_DEVICE, US_PR_DEVICE, onetouch_connect_input, - 0), -#endif - /* Submitted by Joris Struyve */ UNUSUAL_DEV( 0x0d96, 0x410a, 0x0001, 0xffff, "Medion", diff --git a/drivers/usb/storage/unusual_onetouch.h b/drivers/usb/storage/unusual_onetouch.h new file mode 100644 index 000000000000..bd9306b637df --- /dev/null +++ b/drivers/usb/storage/unusual_onetouch.h @@ -0,0 +1,36 @@ +/* Unusual Devices File for the Maxtor OneTouch USB hard drive's button + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if defined(CONFIG_USB_STORAGE_ONETOUCH) || \ + defined(CONFIG_USB_STORAGE_ONETOUCH_MODULE) + +/* Submitted by: Nick Sillik + * Needed for OneTouch extension to usb-storage + */ +UNUSUAL_DEV( 0x0d49, 0x7000, 0x0000, 0x9999, + "Maxtor", + "OneTouch External Harddrive", + US_SC_DEVICE, US_PR_DEVICE, onetouch_connect_input, + 0), + +UNUSUAL_DEV( 0x0d49, 0x7010, 0x0000, 0x9999, + "Maxtor", + "OneTouch External Harddrive", + US_SC_DEVICE, US_PR_DEVICE, onetouch_connect_input, + 0), + +#endif /* defined(CONFIG_USB_STORAGE_ONETOUCH) || ... */ diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index c5abf9bbce16..8060b85fe1a3 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -66,9 +66,6 @@ #include "debug.h" #include "initializers.h" -#ifdef CONFIG_USB_STORAGE_ONETOUCH -#include "onetouch.h" -#endif #include "sierra_ms.h" #include "option_ms.h" diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index bce086fcef5e..468bde7d1971 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -84,6 +84,7 @@ static struct ignore_entry ignore_ids[] = { # include "unusual_isd200.h" # include "unusual_jumpshot.h" # include "unusual_karma.h" +# include "unusual_onetouch.h" # include "unusual_sddr09.h" # include "unusual_sddr55.h" # include "unusual_usbat.h" -- cgit v1.2.3 From 4ba8a8f104b35d6b98b8d7c5c0aaf217319b49f3 Mon Sep 17 00:00:00 2001 From: Maciej Grela Date: Sat, 28 Feb 2009 12:39:20 -0800 Subject: USB: usb-storage: added missing MODULE_LICENSE("GPL") for usb-storage ums-* modules The lack of a MODULE_LICENSE macro in ums-* subdrivers prevented them from loading. Needs to be applied after Alan Stern's usb-storage subdriver separation patchset. Also added missing MODULE_DESCRIPTION and MODULE_AUTHOR entries. Signed-off-by: Maciej Grela Acked-by: Alan Stern Acked-by: Matthew Dharm Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/alauda.c | 4 ++++ drivers/usb/storage/cypress_atacb.c | 3 +++ drivers/usb/storage/datafab.c | 4 ++++ drivers/usb/storage/freecom.c | 4 ++++ drivers/usb/storage/isd200.c | 3 +++ drivers/usb/storage/jumpshot.c | 4 ++++ drivers/usb/storage/karma.c | 4 ++++ drivers/usb/storage/onetouch.c | 4 ++++ drivers/usb/storage/sddr09.c | 3 +++ drivers/usb/storage/sddr55.c | 3 +++ drivers/usb/storage/shuttle_usbat.c | 3 +++ 11 files changed, 39 insertions(+) diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c index d3a88ebe690b..67edc65acb8e 100644 --- a/drivers/usb/storage/alauda.c +++ b/drivers/usb/storage/alauda.c @@ -42,6 +42,10 @@ #include "protocol.h" #include "debug.h" +MODULE_DESCRIPTION("Driver for Alauda-based card readers"); +MODULE_AUTHOR("Daniel Drake "); +MODULE_LICENSE("GPL"); + /* * Status bytes */ diff --git a/drivers/usb/storage/cypress_atacb.c b/drivers/usb/storage/cypress_atacb.c index 19306f7b1dae..c84471821183 100644 --- a/drivers/usb/storage/cypress_atacb.c +++ b/drivers/usb/storage/cypress_atacb.c @@ -30,6 +30,9 @@ #include "scsiglue.h" #include "debug.h" +MODULE_DESCRIPTION("SAT support for Cypress USB/ATA bridges with ATACB"); +MODULE_AUTHOR("Matthieu Castet "); +MODULE_LICENSE("GPL"); /* * The table of devices diff --git a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c index 2d8d83519090..2b6e565262c2 100644 --- a/drivers/usb/storage/datafab.c +++ b/drivers/usb/storage/datafab.c @@ -60,6 +60,10 @@ #include "protocol.h" #include "debug.h" +MODULE_DESCRIPTION("Driver for Datafab USB Compact Flash reader"); +MODULE_AUTHOR("Jimmie Mayfield "); +MODULE_LICENSE("GPL"); + struct datafab_info { unsigned long sectors; /* total sector count */ unsigned long ssize; /* sector size in bytes */ diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c index 393047b3890d..54cc94277acb 100644 --- a/drivers/usb/storage/freecom.c +++ b/drivers/usb/storage/freecom.c @@ -35,6 +35,10 @@ #include "protocol.h" #include "debug.h" +MODULE_DESCRIPTION("Driver for Freecom USB/IDE adaptor"); +MODULE_AUTHOR("David Brown "); +MODULE_LICENSE("GPL"); + #ifdef CONFIG_USB_STORAGE_DEBUG static void pdump (void *, int); #endif diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c index df943008538c..882c57b399f7 100644 --- a/drivers/usb/storage/isd200.c +++ b/drivers/usb/storage/isd200.c @@ -59,6 +59,9 @@ #include "debug.h" #include "scsiglue.h" +MODULE_DESCRIPTION("Driver for In-System Design, Inc. ISD200 ASIC"); +MODULE_AUTHOR("Björn Stenberg "); +MODULE_LICENSE("GPL"); static int isd200_Initialization(struct us_data *us); diff --git a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c index a50d6dc1fe64..1c69420e3acf 100644 --- a/drivers/usb/storage/jumpshot.c +++ b/drivers/usb/storage/jumpshot.c @@ -58,6 +58,10 @@ #include "debug.h" +MODULE_DESCRIPTION("Driver for Lexar \"Jumpshot\" Compact Flash reader"); +MODULE_AUTHOR("Jimmie Mayfield "); +MODULE_LICENSE("GPL"); + /* * The table of devices */ diff --git a/drivers/usb/storage/karma.c b/drivers/usb/storage/karma.c index cfb8e60866b8..7953d93a7739 100644 --- a/drivers/usb/storage/karma.c +++ b/drivers/usb/storage/karma.c @@ -28,6 +28,10 @@ #include "transport.h" #include "debug.h" +MODULE_DESCRIPTION("Driver for Rio Karma"); +MODULE_AUTHOR("Bob Copeland , Keith Bennett "); +MODULE_LICENSE("GPL"); + #define RIO_PREFIX "RIOP\x00" #define RIO_PREFIX_LEN 5 #define RIO_SEND_LEN 40 diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c index 8bd095635a99..380233bd6a39 100644 --- a/drivers/usb/storage/onetouch.c +++ b/drivers/usb/storage/onetouch.c @@ -37,6 +37,10 @@ #include "usb.h" #include "debug.h" +MODULE_DESCRIPTION("Maxtor USB OneTouch hard drive button driver"); +MODULE_AUTHOR("Nick Sillik "); +MODULE_LICENSE("GPL"); + #define ONETOUCH_PKT_LEN 0x02 #define ONETOUCH_BUTTON KEY_PROG1 diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c index 170ad86b2d3e..ab5f9f37575a 100644 --- a/drivers/usb/storage/sddr09.c +++ b/drivers/usb/storage/sddr09.c @@ -53,6 +53,9 @@ #include "protocol.h" #include "debug.h" +MODULE_DESCRIPTION("Driver for SanDisk SDDR-09 SmartMedia reader"); +MODULE_AUTHOR("Andries Brouwer , Robert Baruch "); +MODULE_LICENSE("GPL"); static int usb_stor_sddr09_dpcm_init(struct us_data *us); static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us); diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c index e97716f8eb02..44dfed7754ed 100644 --- a/drivers/usb/storage/sddr55.c +++ b/drivers/usb/storage/sddr55.c @@ -35,6 +35,9 @@ #include "protocol.h" #include "debug.h" +MODULE_DESCRIPTION("Driver for SanDisk SDDR-55 SmartMedia reader"); +MODULE_AUTHOR("Simon Munton"); +MODULE_LICENSE("GPL"); /* * The table of devices diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c index d4fe0bb327a7..b62a28814ebe 100644 --- a/drivers/usb/storage/shuttle_usbat.c +++ b/drivers/usb/storage/shuttle_usbat.c @@ -54,6 +54,9 @@ #include "protocol.h" #include "debug.h" +MODULE_DESCRIPTION("Driver for SCM Microsystems (a.k.a. Shuttle) USB-ATAPI cable"); +MODULE_AUTHOR("Daniel Drake , Robert Baruch "); +MODULE_LICENSE("GPL"); /* Supported device types */ #define USBAT_DEV_HP8200 0x01 -- cgit v1.2.3 From 21f46083853e5990a056a74b54556bf4e953e33a Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Wed, 18 Feb 2009 14:43:47 +0000 Subject: USB: allow libusb to talk to unauthenticated WUSB devices To permit a userspace application to associate with WUSB devices using numeric association, control transfers to unauthenticated WUSB devices must be allowed. This requires that wusbcore correctly sets the device state to UNAUTHENTICATED, DEFAULT and ADDRESS and that control transfers can be performed to UNAUTHENTICATED devices. Signed-off-by: David Vrabel Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 3 ++- drivers/usb/core/hub.c | 1 + drivers/usb/core/urb.c | 2 +- drivers/usb/wusbcore/devconnect.c | 2 ++ drivers/usb/wusbcore/security.c | 2 ++ include/linux/usb/ch9.h | 2 +- 6 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 6585f527e381..8f022af2fd7a 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -525,7 +525,8 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, { int ret = 0; - if (ps->dev->state != USB_STATE_ADDRESS + if (ps->dev->state != USB_STATE_UNAUTHENTICATED + && ps->dev->state != USB_STATE_ADDRESS && ps->dev->state != USB_STATE_CONFIGURED) return -EHOSTUNREACH; if (USB_TYPE_VENDOR == (USB_TYPE_MASK & requesttype)) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 7e33d63ab92f..f17d9ebc44af 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1305,6 +1305,7 @@ void usb_set_device_state(struct usb_device *udev, recursively_mark_NOTATTACHED(udev); spin_unlock_irqrestore(&device_state_lock, flags); } +EXPORT_SYMBOL_GPL(usb_set_device_state); /* * WUSB devices are simple: they have no hubs behind, so the mapping diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index 58bc5e3c2560..7025d801f23a 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -295,7 +295,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) if (!urb || urb->hcpriv || !urb->complete) return -EINVAL; dev = urb->dev; - if ((!dev) || (dev->state < USB_STATE_DEFAULT)) + if ((!dev) || (dev->state < USB_STATE_UNAUTHENTICATED)) return -ENODEV; /* For now, get the endpoint from the pipe. Eventually drivers diff --git a/drivers/usb/wusbcore/devconnect.c b/drivers/usb/wusbcore/devconnect.c index 8e18141bb2e0..f0aac0cf315a 100644 --- a/drivers/usb/wusbcore/devconnect.c +++ b/drivers/usb/wusbcore/devconnect.c @@ -889,6 +889,8 @@ static void wusb_dev_add_ncb(struct usb_device *usb_dev) if (usb_dev->wusb == 0 || usb_dev->devnum == 1) return; /* skip non wusb and wusb RHs */ + usb_set_device_state(usb_dev, USB_STATE_UNAUTHENTICATED); + wusbhc = wusbhc_get_by_usb_dev(usb_dev); if (wusbhc == NULL) goto error_nodev; diff --git a/drivers/usb/wusbcore/security.c b/drivers/usb/wusbcore/security.c index f4aa28eca70d..8118db7f1d8d 100644 --- a/drivers/usb/wusbcore/security.c +++ b/drivers/usb/wusbcore/security.c @@ -312,6 +312,7 @@ int wusb_dev_update_address(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev) result = wusb_set_dev_addr(wusbhc, wusb_dev, 0); if (result < 0) goto error_addr0; + usb_set_device_state(usb_dev, USB_STATE_DEFAULT); usb_ep0_reinit(usb_dev); /* Set new (authenticated) address. */ @@ -327,6 +328,7 @@ int wusb_dev_update_address(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev) result = wusb_set_dev_addr(wusbhc, wusb_dev, new_address); if (result < 0) goto error_addr; + usb_set_device_state(usb_dev, USB_STATE_ADDRESS); usb_ep0_reinit(usb_dev); usb_dev->authenticated = 1; error_addr: diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h index fa777db7f7eb..d9d54803dbcb 100644 --- a/include/linux/usb/ch9.h +++ b/include/linux/usb/ch9.h @@ -763,8 +763,8 @@ enum usb_device_state { /* chapter 9 and authentication (wireless) device states */ USB_STATE_ATTACHED, USB_STATE_POWERED, /* wired */ - USB_STATE_UNAUTHENTICATED, /* auth */ USB_STATE_RECONNECTING, /* auth */ + USB_STATE_UNAUTHENTICATED, /* auth */ USB_STATE_DEFAULT, /* limited function */ USB_STATE_ADDRESS, USB_STATE_CONFIGURED, /* most functions */ -- cgit v1.2.3 From 457851adcd8b2165f0e401c56c83d38695c4b288 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 12 Feb 2009 15:09:47 +0200 Subject: USB: composite: avoid inconsistent lock state Avoid the following INFO from lock debugging: [ 369.126112] ================================= [ 369.132063] [ INFO: inconsistent lock state ] [ 369.136457] 2.6.28-maemo1 #1 [ 369.139387] --------------------------------- [ 369.143782] inconsistent {hardirq-on-W} -> {in-hardirq-W} usage. [ 369.149855] swapper/0 [HC1[1]:SC0[0]:HE0:SE1] takes: [ 369.154890] (&cdev->lock){+-..}, at: [] composite_disconnect+0x1c/0] [ 369.163404] {hardirq-on-W} state was registered at: [ 369.168348] [] __lock_acquire+0x5d0/0x7d8 [ 369.173506] [] lock_acquire+0x64/0x78 [ 369.178266] [] _spin_lock+0x4c/0x80 [ 369.182905] [] usb_function_deactivate+0x20/0x70 [g_nokia] [ 369.189527] [] 0xbf1a0a88 [ 369.193281] [] 0xbf19f450 [ 369.197004] [] 0xbf19fa3c [ 369.200758] [] 0xbf1a03a0 [ 369.204481] [] 0xbf19f254 [ 369.208204] [] 0xbf1a0158 [ 369.211927] [] 0xbf1a130c [ 369.215650] [] usb_gadget_register_driver+0x12c/0x28c [ 369.221846] [] 0xbf1a06bc [ 369.225569] [] 0xbf1a06e8 [ 369.229322] [] __exception_text_end+0x64/0x19c [ 369.234877] [] sys_init_module+0x9c/0x194 [ 369.240004] [] ret_fast_syscall+0x0/0x2c [ 369.245039] [] 0xffffffff [ 369.248793] irq event stamp: 218356 [ 369.252302] hardirqs last enabled at (218355): [] omap3_enter_idle+8 [ 369.260420] hardirqs last disabled at (218356): [] __irq_svc+0x34/0x0 [ 369.267927] softirqs last enabled at (218348): [] __do_softirq+0x134 [ 369.275892] softirqs last disabled at (218335): [] irq_exit+0x60/0xb0 [ 369.283308] [ 369.283308] other info that might help us debug this: [ 369.289930] no locks held by swapper/0. Cc: David Brownell Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/composite.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 5d11c291f1ad..40f1da77a006 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -149,16 +149,17 @@ done: int usb_function_deactivate(struct usb_function *function) { struct usb_composite_dev *cdev = function->config->cdev; + unsigned long flags; int status = 0; - spin_lock(&cdev->lock); + spin_lock_irqsave(&cdev->lock, flags); if (cdev->deactivations == 0) status = usb_gadget_disconnect(cdev->gadget); if (status == 0) cdev->deactivations++; - spin_unlock(&cdev->lock); + spin_unlock_irqrestore(&cdev->lock, flags); return status; } -- cgit v1.2.3 From 8c61cf58d617b8294fe1749a48126f217e44885d Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Tue, 24 Feb 2009 15:23:34 -0800 Subject: USB: musb: rewrite host periodic endpoint allocation The current MUSB host code doesn't make use of all the available FIFOs in for periodic transfers since it wrongly assumes the RX and TX sides of any given hw_ep always share one FIFO. Change: use 'in_qh' and 'out_qh' fields of the 'struct musb_hw_ep' to check the endpoint's business; get rid of the now-unused 'periodic' array in the 'struct musb'. Also optimize a loop induction variable in the endpoint lookup code. (Based on a previous patch from Ajay Kumar Gupta ) [ dbrownell@users.sourceforge.net: clarify description and origin of this fix; whitespace ] Signed-off-by: Sergei Shtylyov Signed-off-by: David Brownell Cc: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.h | 1 - drivers/usb/musb/musb_host.c | 28 +++++++++++----------------- 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 630946a2d9fc..adf1806007ff 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -331,7 +331,6 @@ struct musb { struct list_head control; /* of musb_qh */ struct list_head in_bulk; /* of musb_qh */ struct list_head out_bulk; /* of musb_qh */ - struct musb_qh *periodic[32]; /* tree of interrupt+iso */ #endif /* called with IRQs blocked; ON/nonzero implies starting a session, diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 6dbbd0786a6a..9489c8598686 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -395,7 +395,6 @@ musb_giveback(struct musb_qh *qh, struct urb *urb, int status) * de-allocated if it's tracked and allocated; * and where we'd update the schedule tree... */ - musb->periodic[ep->epnum] = NULL; kfree(qh); qh = NULL; break; @@ -1711,31 +1710,27 @@ static int musb_schedule( /* else, periodic transfers get muxed to other endpoints */ - /* FIXME this doesn't consider direction, so it can only - * work for one half of the endpoint hardware, and assumes - * the previous cases handled all non-shared endpoints... - */ - - /* we know this qh hasn't been scheduled, so all we need to do + /* + * We know this qh hasn't been scheduled, so all we need to do * is choose which hardware endpoint to put it on ... * * REVISIT what we really want here is a regular schedule tree - * like e.g. OHCI uses, but for now musb->periodic is just an - * array of the _single_ logical endpoint associated with a - * given physical one (identity mapping logical->physical). - * - * that simplistic approach makes TT scheduling a lot simpler; - * there is none, and thus none of its complexity... + * like e.g. OHCI uses. */ best_diff = 4096; best_end = -1; - for (epnum = 1; epnum < musb->nr_endpoints; epnum++) { + for (epnum = 1, hw_ep = musb->endpoints + 1; + epnum < musb->nr_endpoints; + epnum++, hw_ep++) { int diff; - if (musb->periodic[epnum]) + if (is_in || hw_ep->is_shared_fifo) { + if (hw_ep->in_qh != NULL) + continue; + } else if (hw_ep->out_qh != NULL) continue; - hw_ep = &musb->endpoints[epnum]; + if (hw_ep == musb->bulk_ep) continue; @@ -1764,7 +1759,6 @@ static int musb_schedule( idle = 1; qh->mux = 0; hw_ep = musb->endpoints + best_end; - musb->periodic[best_end] = qh; DBG(4, "qh %p periodic slot %d\n", qh, best_end); success: if (head) { -- cgit v1.2.3 From 321ac38f67d93e7634973e8b08be4f6908d239e9 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Tue, 24 Feb 2009 15:26:13 -0800 Subject: USB: musb: NAK timeout scheme on bulk RX endpoint Fixes endpoint starvation issue when more than one bulk QH is multiplexed on the reserved bulk RX endpoint, which is normal for cases like serial and ethernet adapters. This patch sets the NAK timeout interval for such QHs, and when a timeout triggers the next QH will be scheduled. (This resembles the bulk scheduling done in hardware by EHCI, OHCI, and UHCI.) This scheme doesn't work for devices which are connected to a high to full speed tree (transaction translator) as there is no NAK timeout interrupt from the musb controller from such devices. Tested with PIO, Inventra DMA, CPPI DMA. [ dbrownell@users.sourceforge.net: fold in start_urb() update; clarify only for bulk RX; don't accidentally clear WZC bits ] Signed-off-by: Ajay Kumar Gupta Cc: Felipe Balbi Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_host.c | 112 ++++++++++++++++++++++++++++++++----------- 1 file changed, 85 insertions(+), 27 deletions(-) diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 9489c8598686..499c431a6d62 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -64,11 +64,8 @@ * * - DMA (Mentor/OMAP) ...has at least toggle update problems * - * - Still no traffic scheduling code to make NAKing for bulk or control - * transfers unable to starve other requests; or to make efficient use - * of hardware with periodic transfers. (Note that network drivers - * commonly post bulk reads that stay pending for a long time; these - * would make very visible trouble.) + * - [23-feb-2009] minimal traffic scheduling to avoid bulk RX packet + * starvation ... nothing yet for TX, interrupt, or bulk. * * - Not tested with HNP, but some SRP paths seem to behave. * @@ -88,11 +85,8 @@ * * CONTROL transfers all go through ep0. BULK ones go through dedicated IN * and OUT endpoints ... hardware is dedicated for those "async" queue(s). - * * (Yes, bulk _could_ use more of the endpoints than that, and would even - * benefit from it ... one remote device may easily be NAKing while others - * need to perform transfers in that same direction. The same thing could - * be done in software though, assuming dma cooperates.) + * benefit from it.) * * INTERUPPT and ISOCHRONOUS transfers are scheduled to the other endpoints. * So far that scheduling is both dumb and optimistic: the endpoint will be @@ -201,8 +195,9 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh) len = urb->iso_frame_desc[0].length; break; default: /* bulk, interrupt */ - buf = urb->transfer_buffer; - len = urb->transfer_buffer_length; + /* actual_length may be nonzero on retry paths */ + buf = urb->transfer_buffer + urb->actual_length; + len = urb->transfer_buffer_length - urb->actual_length; } DBG(4, "qh %p urb %p dev%d ep%d%s%s, hw_ep %d, %p/%d\n", @@ -1044,7 +1039,8 @@ irqreturn_t musb_h_ep0_irq(struct musb *musb) /* NOTE: this code path would be a good place to PAUSE a * control transfer, if another one is queued, so that - * ep0 is more likely to stay busy. + * ep0 is more likely to stay busy. That's already done + * for bulk RX transfers. * * if (qh->ring.next != &musb->control), then * we have a candidate... NAKing is *NOT* an error @@ -1196,6 +1192,7 @@ void musb_host_tx(struct musb *musb, u8 epnum) /* NOTE: this code path would be a good place to PAUSE a * transfer, if there's some other (nonperiodic) tx urb * that could use this fifo. (dma complicates it...) + * That's already done for bulk RX transfers. * * if (bulk && qh->ring.next != &musb->out_bulk), then * we have a candidate... NAKing is *NOT* an error @@ -1357,6 +1354,50 @@ finish: #endif +/* Schedule next QH from musb->in_bulk and move the current qh to + * the end; avoids starvation for other endpoints. + */ +static void musb_bulk_rx_nak_timeout(struct musb *musb, struct musb_hw_ep *ep) +{ + struct dma_channel *dma; + struct urb *urb; + void __iomem *mbase = musb->mregs; + void __iomem *epio = ep->regs; + struct musb_qh *cur_qh, *next_qh; + u16 rx_csr; + + musb_ep_select(mbase, ep->epnum); + dma = is_dma_capable() ? ep->rx_channel : NULL; + + /* clear nak timeout bit */ + rx_csr = musb_readw(epio, MUSB_RXCSR); + rx_csr |= MUSB_RXCSR_H_WZC_BITS; + rx_csr &= ~MUSB_RXCSR_DATAERROR; + musb_writew(epio, MUSB_RXCSR, rx_csr); + + cur_qh = first_qh(&musb->in_bulk); + if (cur_qh) { + urb = next_urb(cur_qh); + if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) { + dma->status = MUSB_DMA_STATUS_CORE_ABORT; + musb->dma_controller->channel_abort(dma); + urb->actual_length += dma->actual_len; + dma->actual_len = 0L; + } + musb_save_toggle(ep, 1, urb); + + /* move cur_qh to end of queue */ + list_move_tail(&cur_qh->ring, &musb->in_bulk); + + /* get the next qh from musb->in_bulk */ + next_qh = first_qh(&musb->in_bulk); + + /* set rx_reinit and schedule the next qh */ + ep->rx_reinit = 1; + musb_start_urb(musb, 1, next_qh); + } +} + /* * Service an RX interrupt for the given IN endpoint; docs cover bulk, iso, * and high-bandwidth IN transfer cases. @@ -1420,18 +1461,26 @@ void musb_host_rx(struct musb *musb, u8 epnum) } else if (rx_csr & MUSB_RXCSR_DATAERROR) { if (USB_ENDPOINT_XFER_ISOC != qh->type) { - /* NOTE this code path would be a good place to PAUSE a - * transfer, if there's some other (nonperiodic) rx urb - * that could use this fifo. (dma complicates it...) + DBG(6, "RX end %d NAK timeout\n", epnum); + + /* NOTE: NAKing is *NOT* an error, so we want to + * continue. Except ... if there's a request for + * another QH, use that instead of starving it. * - * if (bulk && qh->ring.next != &musb->in_bulk), then - * we have a candidate... NAKing is *NOT* an error + * Devices like Ethernet and serial adapters keep + * reads posted at all times, which will starve + * other devices without this logic. */ - DBG(6, "RX end %d NAK timeout\n", epnum); + if (usb_pipebulk(urb->pipe) + && qh->mux == 1 + && !list_is_singular(&musb->in_bulk)) { + musb_bulk_rx_nak_timeout(musb, hw_ep); + return; + } musb_ep_select(mbase, epnum); - musb_writew(epio, MUSB_RXCSR, - MUSB_RXCSR_H_WZC_BITS - | MUSB_RXCSR_H_REQPKT); + rx_csr |= MUSB_RXCSR_H_WZC_BITS; + rx_csr &= ~MUSB_RXCSR_DATAERROR; + musb_writew(epio, MUSB_RXCSR, rx_csr); goto finish; } else { @@ -1751,6 +1800,17 @@ static int musb_schedule( head = &musb->in_bulk; else head = &musb->out_bulk; + + /* Enable bulk RX NAK timeout scheme when bulk requests are + * multiplexed. This scheme doen't work in high speed to full + * speed scenario as NAK interrupts are not coming from a + * full speed device connected to a high speed device. + * NAK timeout interval is 8 (128 uframe or 16ms) for HS and + * 4 (8 frame or 8ms) for FS device. + */ + if (is_in && qh->dev) + qh->intv_reg = + (USB_SPEED_HIGH == qh->dev->speed) ? 8 : 4; goto success; } else if (best_end < 0) { return -ENOSPC; @@ -1882,13 +1942,11 @@ static int musb_urb_enqueue( * * The downside of disabling this is that transfer scheduling * gets VERY unfair for nonperiodic transfers; a misbehaving - * peripheral could make that hurt. Or for reads, one that's - * perfectly normal: network and other drivers keep reads - * posted at all times, having one pending for a week should - * be perfectly safe. + * peripheral could make that hurt. That's perfectly normal + * for reads from network or serial adapters ... so we have + * partial NAKlimit support for bulk RX. * - * The upside of disabling it is avoidng transfer scheduling - * code to put this aside for while. + * The upside of disabling it is simpler transfer scheduling. */ interval = 0; } -- cgit v1.2.3 From 57a0bcf295451ab60839ec9e9848f8ab042eecaf Mon Sep 17 00:00:00 2001 From: Giuseppe GORGOGLIONE Date: Tue, 24 Feb 2009 15:27:34 -0800 Subject: USB: musb: fix init oops crash with static FIFO config Correct musb_read_fifosize() and musb_configure_ep0() functions for the #ifndef BLACKFIN branch when the silicon uses static FIFO configuration. (Most current silicon configures this controller to use dynamic FIFO configuration; some parts from ST don't, like the STM STA2062.) Signed-off-by: Giuseppe GORGOGLIONE Signed-off-by: Felipe Balbi Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index adf1806007ff..efb39b5e55b5 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -478,10 +478,11 @@ static inline void musb_configure_ep0(struct musb *musb) static inline int musb_read_fifosize(struct musb *musb, struct musb_hw_ep *hw_ep, u8 epnum) { + void *mbase = musb->mregs; u8 reg = 0; /* read from core using indexed model */ - reg = musb_readb(hw_ep->regs, 0x10 + MUSB_FIFOSIZE); + reg = musb_readb(mbase, MUSB_EP_OFFSET(epnum, MUSB_FIFOSIZE)); /* 0's returned when no more endpoints */ if (!reg) return -ENODEV; @@ -508,6 +509,7 @@ static inline void musb_configure_ep0(struct musb *musb) { musb->endpoints[0].max_packet_sz_tx = MUSB_EP0_FIFOSIZE; musb->endpoints[0].max_packet_sz_rx = MUSB_EP0_FIFOSIZE; + musb->endpoints[0].is_shared_fifo = true; } #endif /* CONFIG_BLACKFIN */ -- cgit v1.2.3 From 45efad3fc2ba14f08c4d6371b324f5dc5a29a88b Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Tue, 24 Feb 2009 15:29:04 -0800 Subject: USB: musb: only turn off vbus in OTG hosts Except on DaVinci, VBUS is now switched off as part of idling the USB link (after a_wait_bcon) whenever a device is disconnected from host. This is correct for OTG hosts, where either SRP or an ID interrupt could turn VBUS on again. However, for non-OTG hosts there's no way to turn VBUS on again, so the host becomes unusable. And the procfs entry which once allowed a manual workaround for this is now gone. This patch adds an is_otg_enabled() check before scheduling the switch-off timer in disconnect path, supporting a "classic host" mode where SRP is unavailable. [ dbrownell@users.sourceforge.net: tweak patch description ] Signed-off-by: Ajay Kumar Gupta Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index af77e4659006..338cd1611ab3 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -769,7 +769,7 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb, case OTG_STATE_A_SUSPEND: usb_hcd_resume_root_hub(musb_to_hcd(musb)); musb_root_disconnect(musb); - if (musb->a_wait_bcon != 0) + if (musb->a_wait_bcon != 0 && is_otg_enabled(musb)) musb_platform_try_idle(musb, jiffies + msecs_to_jiffies(musb->a_wait_bcon)); break; -- cgit v1.2.3 From 3580eff718b71fe22880c9f376fb641f9229bc4a Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 24 Feb 2009 15:31:54 -0800 Subject: USB: musb: partial DaVinci dm355 support Partial support for DaVinci DM355, on the EVM board; peripheral mode should work, once mainline merges DM355 support. Missing: (a) renumbering the GPIO for DRVVBUS on the DM6446 EVM, when DAVINCI_N_GPIO increases; (b) disabling DM355_DEEPSLEEP.DRVVBUS_OVERRIDE so VBUS is driven according to the ID signal, if cpu_is_..._dm355() The new PHY control bits are ignored on DM6446. Signed-off-by: David Brownell Cc: Kevin Hilman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/Kconfig | 6 ++--- drivers/usb/musb/davinci.c | 63 ++++++++++++++++++++++++++++++++-------------- drivers/usb/musb/davinci.h | 23 +++++++++++------ 3 files changed, 62 insertions(+), 30 deletions(-) diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index 9985db08e7db..b66e8544d8b9 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -20,8 +20,8 @@ config USB_MUSB_HDRC it's being used with, including the USB peripheral role, or the USB host role, or both. - Texas Instruments parts using this IP include DaVinci 644x, - OMAP 243x, OMAP 343x, and TUSB 6010. + Texas Instruments familiies using this IP include DaVinci + (35x, 644x ...), OMAP 243x, OMAP 3, and TUSB 6010. Analog Devices parts using this IP include Blackfin BF54x, BF525 and BF527. @@ -40,7 +40,7 @@ config USB_MUSB_SOC default y if (BF54x && !BF544) default y if (BF52x && !BF522 && !BF523) -comment "DaVinci 644x USB support" +comment "DaVinci 35x and 644x USB support" depends on USB_MUSB_HDRC && ARCH_DAVINCI comment "OMAP 243x high speed USB support" diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index 2dc7606f319c..10d11ab113ab 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c @@ -48,6 +48,9 @@ #include "cppi_dma.h" +#define USB_PHY_CTRL IO_ADDRESS(USBPHY_CTL_PADDR) +#define DM355_DEEPSLEEP IO_ADDRESS(DM355_DEEPSLEEP_PADDR) + /* REVISIT (PM) we should be able to keep the PHY in low power mode most * of the time (24 MHZ oscillator and PLL off, etc) by setting POWER.D0 * and, when in host mode, autosuspending idle root ports... PHYPLLON @@ -56,20 +59,26 @@ static inline void phy_on(void) { - /* start the on-chip PHY and its PLL */ - __raw_writel(USBPHY_SESNDEN | USBPHY_VBDTCTEN | USBPHY_PHYPLLON, - (void __force __iomem *) IO_ADDRESS(USBPHY_CTL_PADDR)); - while ((__raw_readl((void __force __iomem *) - IO_ADDRESS(USBPHY_CTL_PADDR)) - & USBPHY_PHYCLKGD) == 0) + u32 phy_ctrl = __raw_readl(USB_PHY_CTRL); + + /* power everything up; start the on-chip PHY and its PLL */ + phy_ctrl &= ~(USBPHY_OSCPDWN | USBPHY_OTGPDWN | USBPHY_PHYPDWN); + phy_ctrl |= USBPHY_SESNDEN | USBPHY_VBDTCTEN | USBPHY_PHYPLLON; + __raw_writel(phy_ctrl, USB_PHY_CTRL); + + /* wait for PLL to lock before proceeding */ + while ((__raw_readl(USB_PHY_CTRL) & USBPHY_PHYCLKGD) == 0) cpu_relax(); } static inline void phy_off(void) { - /* powerdown the on-chip PHY and its oscillator */ - __raw_writel(USBPHY_OSCPDWN | USBPHY_PHYPDWN, (void __force __iomem *) - IO_ADDRESS(USBPHY_CTL_PADDR)); + u32 phy_ctrl = __raw_readl(USB_PHY_CTRL); + + /* powerdown the on-chip PHY, its PLL, and the OTG block */ + phy_ctrl &= ~(USBPHY_SESNDEN | USBPHY_VBDTCTEN | USBPHY_PHYPLLON); + phy_ctrl |= USBPHY_OSCPDWN | USBPHY_OTGPDWN | USBPHY_PHYPDWN; + __raw_writel(phy_ctrl, USB_PHY_CTRL); } static int dma_off = 1; @@ -126,10 +135,6 @@ void musb_platform_disable(struct musb *musb) } -/* REVISIT it's not clear whether DaVinci can support full OTG. */ - -static int vbus_state = -1; - #ifdef CONFIG_USB_MUSB_HDRC_HCD #define portstate(stmt) stmt #else @@ -137,10 +142,19 @@ static int vbus_state = -1; #endif -/* VBUS SWITCHING IS BOARD-SPECIFIC */ +/* + * VBUS SWITCHING IS BOARD-SPECIFIC ... at least for the DM6446 EVM, + * which doesn't wire DRVVBUS to the FET that switches it. Unclear + * if that's a problem with the DM6446 chip or just with that board. + * + * In either case, the DM355 EVM automates DRVVBUS the normal way, + * when J10 is out, and TI documents it as handling OTG. + */ #ifdef CONFIG_MACH_DAVINCI_EVM +static int vbus_state = -1; + /* I2C operations are always synchronous, and require a task context. * With unloaded systems, using the shared workqueue seems to suffice * to satisfy the 100msec A_WAIT_VRISE timeout... @@ -150,12 +164,12 @@ static void evm_deferred_drvvbus(struct work_struct *ignored) gpio_set_value_cansleep(GPIO_nVBUS_DRV, vbus_state); vbus_state = !vbus_state; } -static DECLARE_WORK(evm_vbus_work, evm_deferred_drvvbus); #endif /* EVM */ static void davinci_source_power(struct musb *musb, int is_on, int immediate) { +#ifdef CONFIG_MACH_DAVINCI_EVM if (is_on) is_on = 1; @@ -163,16 +177,17 @@ static void davinci_source_power(struct musb *musb, int is_on, int immediate) return; vbus_state = !is_on; /* 0/1 vs "-1 == unknown/init" */ -#ifdef CONFIG_MACH_DAVINCI_EVM if (machine_is_davinci_evm()) { + static DECLARE_WORK(evm_vbus_work, evm_deferred_drvvbus); + if (immediate) gpio_set_value_cansleep(GPIO_nVBUS_DRV, vbus_state); else schedule_work(&evm_vbus_work); } -#endif if (immediate) vbus_state = is_on; +#endif } static void davinci_set_vbus(struct musb *musb, int is_on) @@ -391,6 +406,17 @@ int __init musb_platform_init(struct musb *musb) musb->board_set_vbus = davinci_set_vbus; davinci_source_power(musb, 0, 1); + /* dm355 EVM swaps D+/D- for signal integrity, and + * is clocked from the main 24 MHz crystal. + */ + if (machine_is_davinci_dm355_evm()) { + u32 phy_ctrl = __raw_readl(USB_PHY_CTRL); + + phy_ctrl &= ~(3 << 9); + phy_ctrl |= USBPHY_DATAPOL; + __raw_writel(phy_ctrl, USB_PHY_CTRL); + } + /* reset the controller */ musb_writel(tibase, DAVINCI_USB_CTRL_REG, 0x1); @@ -401,8 +427,7 @@ int __init musb_platform_init(struct musb *musb) /* NOTE: irqs are in mixed mode, not bypass to pure-musb */ pr_debug("DaVinci OTG revision %08x phy %03x control %02x\n", - revision, __raw_readl((void __force __iomem *) - IO_ADDRESS(USBPHY_CTL_PADDR)), + revision, __raw_readl(USB_PHY_CTRL), musb_readb(tibase, DAVINCI_USB_CTRL_REG)); musb->isr = davinci_interrupt; diff --git a/drivers/usb/musb/davinci.h b/drivers/usb/musb/davinci.h index 7fb6238e270f..046c84433cad 100644 --- a/drivers/usb/musb/davinci.h +++ b/drivers/usb/musb/davinci.h @@ -15,14 +15,21 @@ */ /* Integrated highspeed/otg PHY */ -#define USBPHY_CTL_PADDR (DAVINCI_SYSTEM_MODULE_BASE + 0x34) -#define USBPHY_PHYCLKGD (1 << 8) -#define USBPHY_SESNDEN (1 << 7) /* v(sess_end) comparator */ -#define USBPHY_VBDTCTEN (1 << 6) /* v(bus) comparator */ -#define USBPHY_PHYPLLON (1 << 4) /* override pll suspend */ -#define USBPHY_CLKO1SEL (1 << 3) -#define USBPHY_OSCPDWN (1 << 2) -#define USBPHY_PHYPDWN (1 << 0) +#define USBPHY_CTL_PADDR (DAVINCI_SYSTEM_MODULE_BASE + 0x34) +#define USBPHY_DATAPOL BIT(11) /* (dm355) switch D+/D- */ +#define USBPHY_PHYCLKGD BIT(8) +#define USBPHY_SESNDEN BIT(7) /* v(sess_end) comparator */ +#define USBPHY_VBDTCTEN BIT(6) /* v(bus) comparator */ +#define USBPHY_VBUSSENS BIT(5) /* (dm355,ro) is vbus > 0.5V */ +#define USBPHY_PHYPLLON BIT(4) /* override pll suspend */ +#define USBPHY_CLKO1SEL BIT(3) +#define USBPHY_OSCPDWN BIT(2) +#define USBPHY_OTGPDWN BIT(1) +#define USBPHY_PHYPDWN BIT(0) + +#define DM355_DEEPSLEEP_PADDR (DAVINCI_SYSTEM_MODULE_BASE + 0x48) +#define DRVVBUS_FORCE BIT(2) +#define DRVVBUS_OVERRIDE BIT(1) /* For now include usb OTG module registers here */ #define DAVINCI_USB_VERSION_REG 0x00 -- cgit v1.2.3 From 9312eda7bfbf31b2f211fe8c411fe8ba2f902c95 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Fri, 20 Feb 2009 21:23:09 +0800 Subject: USB: ch341 serial: fix port number changed after resume This patch fixes the following bug: .plug ch341 usb serial port into a hub port; .ch341 driver bound to the device and /dev/ttyUSB0 comes .open /dev/ttyUSB0 by minicom and we can use the serial successfully .suspend the ch341 usb serial device(such as: echo suspend > power/level) .resume the ch341 usb serial device (such as: echo on > power/level) .new port /dev/ttyUSB1 comes ,and the original /dev/ttyUSB0 still exists, but is no longer usable by minicom The patch adds suspend and resume callback to ch341 usb driver to prevent it from unbinding during suspend. The /dev/ttyUSB0 is not released until being closed, so /dev/ttyUSB1 comes after resume, and the original /dev/ttyUSB0 is no longer usable by minicom. It is really a mess for a minicom user. This patch also adds the reset_resume callback to make it usable after resuming from STR or hibernation, for generally STR or hibernation will make the vbus of root-hub lost. Finally enable the driver's supports_autosuspend, for the device is in working order with it. Signed-off-by: Ming Lei Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ch341.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index d5ea679e1698..ab4cc277aa65 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -529,12 +529,34 @@ static int ch341_tiocmget(struct tty_struct *tty, struct file *file) return result; } + +static int ch341_reset_resume(struct usb_interface *intf) +{ + struct usb_device *dev = interface_to_usbdev(intf); + struct usb_serial *serial = NULL; + struct ch341_private *priv; + + serial = usb_get_intfdata(intf); + priv = usb_get_serial_port_data(serial->port[0]); + + /*reconfigure ch341 serial port after bus-reset*/ + ch341_configure(dev, priv); + + usb_serial_resume(intf); + + return 0; +} + static struct usb_driver ch341_driver = { .name = "ch341", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, + .suspend = usb_serial_suspend, + .resume = usb_serial_resume, + .reset_resume = ch341_reset_resume, .id_table = id_table, .no_dynamic_id = 1, + .supports_autosuspend = 1, }; static struct usb_serial_driver ch341_device = { -- cgit v1.2.3 From 0af3e562ba1accc084c0a82674df9607002c976d Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Thu, 19 Feb 2009 22:54:45 -0700 Subject: USB: usbmon: Add binary API v1 This patch adds an extension to the binary API so it reaches parity with existing text API (so-called "1u"). The extension delivers additional data, such as ISO descriptors and the interrupt interval. Signed-Off-By: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman --- Documentation/usb/usbmon.txt | 27 +++++--- drivers/usb/mon/mon_bin.c | 142 +++++++++++++++++++++++++++++++++++-------- 2 files changed, 136 insertions(+), 33 deletions(-) diff --git a/Documentation/usb/usbmon.txt b/Documentation/usb/usbmon.txt index 270481906dc8..6c3c625b7f30 100644 --- a/Documentation/usb/usbmon.txt +++ b/Documentation/usb/usbmon.txt @@ -229,16 +229,26 @@ struct usbmon_packet { int status; /* 28: */ unsigned int length; /* 32: Length of data (submitted or actual) */ unsigned int len_cap; /* 36: Delivered length */ - unsigned char setup[8]; /* 40: Only for Control 'S' */ -}; /* 48 bytes total */ + union { /* 40: */ + unsigned char setup[SETUP_LEN]; /* Only for Control S-type */ + struct iso_rec { /* Only for ISO */ + int error_count; + int numdesc; + } iso; + } s; + int interval; /* 48: Only for Interrupt and ISO */ + int start_frame; /* 52: For ISO */ + unsigned int xfer_flags; /* 56: copy of URB's transfer_flags */ + unsigned int ndesc; /* 60: Actual number of ISO descriptors */ +}; /* 64 total length */ These events can be received from a character device by reading with read(2), -with an ioctl(2), or by accessing the buffer with mmap. +with an ioctl(2), or by accessing the buffer with mmap. However, read(2) +only returns first 48 bytes for compatibility reasons. The character device is usually called /dev/usbmonN, where N is the USB bus number. Number zero (/dev/usbmon0) is special and means "all buses". -However, this feature is not implemented yet. Note that specific naming -policy is set by your Linux distribution. +Note that specific naming policy is set by your Linux distribution. If you create /dev/usbmon0 by hand, make sure that it is owned by root and has mode 0600. Otherwise, unpriviledged users will be able to snoop @@ -279,9 +289,10 @@ size is out of [unspecified] bounds for this kernel, the call fails with This call returns the current size of the buffer in bytes. MON_IOCX_GET, defined as _IOW(MON_IOC_MAGIC, 6, struct mon_get_arg) + MON_IOCX_GETX, defined as _IOW(MON_IOC_MAGIC, 10, struct mon_get_arg) -This call waits for events to arrive if none were in the kernel buffer, -then returns the first event. Its argument is a pointer to the following +These calls wait for events to arrive if none were in the kernel buffer, +then return the first event. The argument is a pointer to the following structure: struct mon_get_arg { @@ -294,6 +305,8 @@ Before the call, hdr, data, and alloc should be filled. Upon return, the area pointed by hdr contains the next event structure, and the data buffer contains the data, if any. The event is removed from the kernel buffer. +The MON_IOCX_GET copies 48 bytes, MON_IOCX_GETX copies 64 bytes. + MON_IOCX_MFETCH, defined as _IOWR(MON_IOC_MAGIC, 7, struct mon_mfetch_arg) This ioctl is primarily used when the application accesses the buffer diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c index 4cf27c72423e..f8d9045d668a 100644 --- a/drivers/usb/mon/mon_bin.c +++ b/drivers/usb/mon/mon_bin.c @@ -37,10 +37,13 @@ #define MON_IOCX_GET _IOW(MON_IOC_MAGIC, 6, struct mon_bin_get) #define MON_IOCX_MFETCH _IOWR(MON_IOC_MAGIC, 7, struct mon_bin_mfetch) #define MON_IOCH_MFLUSH _IO(MON_IOC_MAGIC, 8) +/* #9 was MON_IOCT_SETAPI */ +#define MON_IOCX_GETX _IOW(MON_IOC_MAGIC, 10, struct mon_bin_get) #ifdef CONFIG_COMPAT #define MON_IOCX_GET32 _IOW(MON_IOC_MAGIC, 6, struct mon_bin_get32) #define MON_IOCX_MFETCH32 _IOWR(MON_IOC_MAGIC, 7, struct mon_bin_mfetch32) +#define MON_IOCX_GETX32 _IOW(MON_IOC_MAGIC, 10, struct mon_bin_get32) #endif /* @@ -92,7 +95,29 @@ struct mon_bin_hdr { int status; unsigned int len_urb; /* Length of data (submitted or actual) */ unsigned int len_cap; /* Delivered length */ - unsigned char setup[SETUP_LEN]; /* Only for Control S-type */ + union { + unsigned char setup[SETUP_LEN]; /* Only for Control S-type */ + struct iso_rec { + int error_count; + int numdesc; + } iso; + } s; + int interval; + int start_frame; + unsigned int xfer_flags; + unsigned int ndesc; /* Actual number of ISO descriptors */ +}; + +/* + * ISO vector, packed into the head of data stream. + * This has to take 16 bytes to make sure that the end of buffer + * wrap is not happening in the middle of a descriptor. + */ +struct mon_bin_isodesc { + int iso_status; + unsigned int iso_off; + unsigned int iso_len; + u32 _pad; }; /* per file statistic */ @@ -102,7 +127,7 @@ struct mon_bin_stats { }; struct mon_bin_get { - struct mon_bin_hdr __user *hdr; /* Only 48 bytes, not 64. */ + struct mon_bin_hdr __user *hdr; /* Can be 48 bytes or 64. */ void __user *data; size_t alloc; /* Length of data (can be zero) */ }; @@ -131,6 +156,11 @@ struct mon_bin_mfetch32 { #define PKT_ALIGN 64 #define PKT_SIZE 64 +#define PKT_SZ_API0 48 /* API 0 (2.6.20) size */ +#define PKT_SZ_API1 64 /* API 1 size: extra fields */ + +#define ISODESC_MAX 128 /* Same number as usbfs allows, 2048 bytes. */ + /* max number of USB bus supported */ #define MON_BIN_MAX_MINOR 128 @@ -360,12 +390,8 @@ static inline char mon_bin_get_setup(unsigned char *setupb, const struct urb *urb, char ev_type) { - if (!usb_endpoint_xfer_control(&urb->ep->desc) || ev_type != 'S') - return '-'; - if (urb->setup_packet == NULL) return 'Z'; - memcpy(setupb, urb->setup_packet, SETUP_LEN); return 0; } @@ -387,6 +413,26 @@ static char mon_bin_get_data(const struct mon_reader_bin *rp, return 0; } +static void mon_bin_get_isodesc(const struct mon_reader_bin *rp, + unsigned int offset, struct urb *urb, char ev_type, unsigned int ndesc) +{ + struct mon_bin_isodesc *dp; + struct usb_iso_packet_descriptor *fp; + + fp = urb->iso_frame_desc; + while (ndesc-- != 0) { + dp = (struct mon_bin_isodesc *) + (rp->b_vec[offset / CHUNK_SIZE].ptr + offset % CHUNK_SIZE); + dp->iso_status = fp->status; + dp->iso_off = fp->offset; + dp->iso_len = (ev_type == 'S') ? fp->length : fp->actual_length; + dp->_pad = 0; + if ((offset += sizeof(struct mon_bin_isodesc)) >= rp->b_size) + offset = 0; + fp++; + } +} + static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb, char ev_type, int status) { @@ -396,6 +442,7 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb, unsigned int urb_length; unsigned int offset; unsigned int length; + unsigned int ndesc, lendesc; unsigned char dir; struct mon_bin_hdr *ep; char data_tag = 0; @@ -407,6 +454,19 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb, /* * Find the maximum allowable length, then allocate space. */ + if (usb_endpoint_xfer_isoc(epd)) { + if (urb->number_of_packets < 0) { + ndesc = 0; + } else if (urb->number_of_packets >= ISODESC_MAX) { + ndesc = ISODESC_MAX; + } else { + ndesc = urb->number_of_packets; + } + } else { + ndesc = 0; + } + lendesc = ndesc*sizeof(struct mon_bin_isodesc); + urb_length = (ev_type == 'S') ? urb->transfer_buffer_length : urb->actual_length; length = urb_length; @@ -429,10 +489,12 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb, dir = 0; } - if (rp->mmap_active) - offset = mon_buff_area_alloc_contiguous(rp, length + PKT_SIZE); - else - offset = mon_buff_area_alloc(rp, length + PKT_SIZE); + if (rp->mmap_active) { + offset = mon_buff_area_alloc_contiguous(rp, + length + PKT_SIZE + lendesc); + } else { + offset = mon_buff_area_alloc(rp, length + PKT_SIZE + lendesc); + } if (offset == ~0) { rp->cnt_lost++; spin_unlock_irqrestore(&rp->b_lock, flags); @@ -456,9 +518,31 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb, ep->ts_usec = ts.tv_usec; ep->status = status; ep->len_urb = urb_length; - ep->len_cap = length; + ep->len_cap = length + lendesc; + ep->xfer_flags = urb->transfer_flags; + + if (usb_endpoint_xfer_int(epd)) { + ep->interval = urb->interval; + } else if (usb_endpoint_xfer_isoc(epd)) { + ep->interval = urb->interval; + ep->start_frame = urb->start_frame; + ep->s.iso.error_count = urb->error_count; + ep->s.iso.numdesc = urb->number_of_packets; + } + + if (usb_endpoint_xfer_control(epd) && ev_type == 'S') { + ep->flag_setup = mon_bin_get_setup(ep->s.setup, urb, ev_type); + } else { + ep->flag_setup = '-'; + } + + if (ndesc != 0) { + ep->ndesc = ndesc; + mon_bin_get_isodesc(rp, offset, urb, ev_type, ndesc); + if ((offset += lendesc) >= rp->b_size) + offset -= rp->b_size; + } - ep->flag_setup = mon_bin_get_setup(ep->setup, urb, ev_type); if (length != 0) { ep->flag_data = mon_bin_get_data(rp, offset, urb, length); if (ep->flag_data != 0) { /* Yes, it's 0x00, not '0' */ @@ -592,7 +676,8 @@ err_alloc: * Returns zero or error. */ static int mon_bin_get_event(struct file *file, struct mon_reader_bin *rp, - struct mon_bin_hdr __user *hdr, void __user *data, unsigned int nbytes) + struct mon_bin_hdr __user *hdr, unsigned int hdrbytes, + void __user *data, unsigned int nbytes) { unsigned long flags; struct mon_bin_hdr *ep; @@ -609,7 +694,7 @@ static int mon_bin_get_event(struct file *file, struct mon_reader_bin *rp, ep = MON_OFF2HDR(rp, rp->b_out); - if (copy_to_user(hdr, ep, sizeof(struct mon_bin_hdr))) { + if (copy_to_user(hdr, ep, hdrbytes)) { mutex_unlock(&rp->fetch_lock); return -EFAULT; } @@ -657,6 +742,7 @@ static ssize_t mon_bin_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) { struct mon_reader_bin *rp = file->private_data; + unsigned int hdrbytes = PKT_SZ_API0; unsigned long flags; struct mon_bin_hdr *ep; unsigned int offset; @@ -674,8 +760,8 @@ static ssize_t mon_bin_read(struct file *file, char __user *buf, ep = MON_OFF2HDR(rp, rp->b_out); - if (rp->b_read < sizeof(struct mon_bin_hdr)) { - step_len = min(nbytes, sizeof(struct mon_bin_hdr) - rp->b_read); + if (rp->b_read < hdrbytes) { + step_len = min(nbytes, (size_t)(hdrbytes - rp->b_read)); ptr = ((char *)ep) + rp->b_read; if (step_len && copy_to_user(buf, ptr, step_len)) { mutex_unlock(&rp->fetch_lock); @@ -687,13 +773,13 @@ static ssize_t mon_bin_read(struct file *file, char __user *buf, done += step_len; } - if (rp->b_read >= sizeof(struct mon_bin_hdr)) { + if (rp->b_read >= hdrbytes) { step_len = ep->len_cap; - step_len -= rp->b_read - sizeof(struct mon_bin_hdr); + step_len -= rp->b_read - hdrbytes; if (step_len > nbytes) step_len = nbytes; offset = rp->b_out + PKT_SIZE; - offset += rp->b_read - sizeof(struct mon_bin_hdr); + offset += rp->b_read - hdrbytes; if (offset >= rp->b_size) offset -= rp->b_size; if (copy_from_buf(rp, offset, buf, step_len)) { @@ -709,7 +795,7 @@ static ssize_t mon_bin_read(struct file *file, char __user *buf, /* * Check if whole packet was read, and if so, jump to the next one. */ - if (rp->b_read >= sizeof(struct mon_bin_hdr) + ep->len_cap) { + if (rp->b_read >= hdrbytes + ep->len_cap) { spin_lock_irqsave(&rp->b_lock, flags); mon_buff_area_free(rp, PKT_SIZE + ep->len_cap); spin_unlock_irqrestore(&rp->b_lock, flags); @@ -908,6 +994,7 @@ static int mon_bin_ioctl(struct inode *inode, struct file *file, break; case MON_IOCX_GET: + case MON_IOCX_GETX: { struct mon_bin_get getb; @@ -917,8 +1004,9 @@ static int mon_bin_ioctl(struct inode *inode, struct file *file, if (getb.alloc > 0x10000000) /* Want to cast to u32 */ return -EINVAL; - ret = mon_bin_get_event(file, rp, - getb.hdr, getb.data, (unsigned int)getb.alloc); + ret = mon_bin_get_event(file, rp, getb.hdr, + (cmd == MON_IOCX_GET)? PKT_SZ_API0: PKT_SZ_API1, + getb.data, (unsigned int)getb.alloc); } break; @@ -984,16 +1072,18 @@ static long mon_bin_compat_ioctl(struct file *file, switch (cmd) { - case MON_IOCX_GET32: { + case MON_IOCX_GET32: + case MON_IOCX_GETX32: + { struct mon_bin_get32 getb; if (copy_from_user(&getb, (void __user *)arg, sizeof(struct mon_bin_get32))) return -EFAULT; - ret = mon_bin_get_event(file, rp, - compat_ptr(getb.hdr32), compat_ptr(getb.data32), - getb.alloc32); + ret = mon_bin_get_event(file, rp, compat_ptr(getb.hdr32), + (cmd == MON_IOCX_GET32)? PKT_SZ_API0: PKT_SZ_API1, + compat_ptr(getb.data32), getb.alloc32); if (ret < 0) return ret; } -- cgit v1.2.3 From 88d728d22592fb930467394c242b57585527db86 Mon Sep 17 00:00:00 2001 From: Jouni Hogander Date: Fri, 20 Feb 2009 14:02:31 +0200 Subject: USB: TWL: disable VUSB regulators when cable unplugged This patch disables USB regulators VUSB1V5, VUSB1V8, and VUSB3V1 when the USB cable is unplugged to reduce power consumption. Added a depencency from twl4030 usb driver to TWL_REGULATOR. Signed-off-by: Jouni Hogander Signed-off-by: Kalle Jokiniemi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/otg/Kconfig | 2 +- drivers/usb/otg/twl4030-usb.c | 73 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 65 insertions(+), 10 deletions(-) diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index fc1ca03ce4da..aa884d072f0b 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig @@ -43,7 +43,7 @@ config ISP1301_OMAP config TWL4030_USB tristate "TWL4030 USB Transceiver Driver" - depends on TWL4030_CORE + depends on TWL4030_CORE && REGULATOR_TWL4030 select USB_OTG_UTILS help Enable this to support the USB OTG transceiver on TWL4030 diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c index 416e4410be02..d9478d0e1c8b 100644 --- a/drivers/usb/otg/twl4030-usb.c +++ b/drivers/usb/otg/twl4030-usb.c @@ -34,6 +34,8 @@ #include #include #include +#include +#include /* Register defines */ @@ -246,6 +248,11 @@ struct twl4030_usb { struct otg_transceiver otg; struct device *dev; + /* TWL4030 internal USB regulator supplies */ + struct regulator *usb1v5; + struct regulator *usb1v8; + struct regulator *usb3v1; + /* for vbus reporting with irqs disabled */ spinlock_t lock; @@ -434,6 +441,18 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on) pwr = twl4030_usb_read(twl, PHY_PWR_CTRL); if (on) { + regulator_enable(twl->usb3v1); + regulator_enable(twl->usb1v8); + /* + * Disabling usb3v1 regulator (= writing 0 to VUSB3V1_DEV_GRP + * in twl4030) resets the VUSB_DEDICATED2 register. This reset + * enables VUSB3V1_SLEEP bit that remaps usb3v1 ACTIVE state to + * SLEEP. We work around this by clearing the bit after usv3v1 + * is re-activated. This ensures that VUSB3V1 is really active. + */ + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, + VUSB_DEDICATED2); + regulator_enable(twl->usb1v5); pwr &= ~PHY_PWR_PHYPWD; WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0); twl4030_usb_write(twl, PHY_CLK_CTRL, @@ -443,6 +462,9 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on) } else { pwr |= PHY_PWR_PHYPWD; WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0); + regulator_disable(twl->usb1v5); + regulator_disable(twl->usb1v8); + regulator_disable(twl->usb3v1); } } @@ -468,7 +490,7 @@ static void twl4030_phy_resume(struct twl4030_usb *twl) twl->asleep = 0; } -static void twl4030_usb_ldo_init(struct twl4030_usb *twl) +static int twl4030_usb_ldo_init(struct twl4030_usb *twl) { /* Enable writing to power configuration registers */ twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0xC0, PROTECT_KEY); @@ -480,20 +502,45 @@ static void twl4030_usb_ldo_init(struct twl4030_usb *twl) /* input to VUSB3V1 LDO is from VBAT, not VBUS */ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1); - /* turn on 3.1V regulator */ - twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB3V1_DEV_GRP); + /* Initialize 3.1V regulator */ + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP); + + twl->usb3v1 = regulator_get(twl->dev, "usb3v1"); + if (IS_ERR(twl->usb3v1)) + return -ENODEV; + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE); - /* turn on 1.5V regulator */ - twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB1V5_DEV_GRP); + /* Initialize 1.5V regulator */ + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP); + + twl->usb1v5 = regulator_get(twl->dev, "usb1v5"); + if (IS_ERR(twl->usb1v5)) + goto fail1; + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE); - /* turn on 1.8V regulator */ - twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB1V8_DEV_GRP); + /* Initialize 1.8V regulator */ + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP); + + twl->usb1v8 = regulator_get(twl->dev, "usb1v8"); + if (IS_ERR(twl->usb1v8)) + goto fail2; + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE); /* disable access to power configuration registers */ twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, PROTECT_KEY); + + return 0; + +fail2: + regulator_put(twl->usb1v5); + twl->usb1v5 = NULL; +fail1: + regulator_put(twl->usb3v1); + twl->usb3v1 = NULL; + return -ENODEV; } static ssize_t twl4030_usb_vbus_show(struct device *dev, @@ -598,7 +645,7 @@ static int __init twl4030_usb_probe(struct platform_device *pdev) { struct twl4030_usb_data *pdata = pdev->dev.platform_data; struct twl4030_usb *twl; - int status; + int status, err; if (!pdata) { dev_dbg(&pdev->dev, "platform_data not available\n"); @@ -622,7 +669,12 @@ static int __init twl4030_usb_probe(struct platform_device *pdev) /* init spinlock for workqueue */ spin_lock_init(&twl->lock); - twl4030_usb_ldo_init(twl); + err = twl4030_usb_ldo_init(twl); + if (err) { + dev_err(&pdev->dev, "ldo init failed\n"); + kfree(twl); + return err; + } otg_set_transceiver(&twl->otg); platform_set_drvdata(pdev, twl); @@ -688,6 +740,9 @@ static int __exit twl4030_usb_remove(struct platform_device *pdev) twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB); twl4030_phy_power(twl, 0); + regulator_put(twl->usb1v5); + regulator_put(twl->usb1v8); + regulator_put(twl->usb3v1); kfree(twl); -- cgit v1.2.3 From f058ee35d69d863fdbbb420490539e3581cebdb7 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 5 Mar 2009 11:01:11 -0500 Subject: USB: uhci: don't use pseudo negative values The code in uhci-q.c doesn't have to use pseudo-negative values. I did it that way because it was easy and because it would give the expected output during debugging. But it doesn't have to work that way. Here's another approach. Signed-off-by: Alan Stern Cc: Roel Kluin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-debug.c | 4 +++- drivers/usb/host/uhci-q.c | 11 ++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index 20cc58b97807..e52b954dda47 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c @@ -118,7 +118,9 @@ static int uhci_show_urbp(struct urb_priv *urbp, char *buf, int len, int space) } out += sprintf(out, "%s%s", ptype, (urbp->fsbr ? " FSBR" : "")); - out += sprintf(out, " Actlen=%d", urbp->urb->actual_length); + out += sprintf(out, " Actlen=%d%s", urbp->urb->actual_length, + (urbp->qh->type == USB_ENDPOINT_XFER_CONTROL ? + "-8" : "")); if (urbp->urb->unlinked) out += sprintf(out, " Unlinked=%d", urbp->urb->unlinked); diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 58f873679145..3e5807d14ffb 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -899,8 +899,6 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, } if (qh->state != QH_STATE_ACTIVE) qh->skel = skel; - - urb->actual_length = -8; /* Account for the SETUP packet */ return 0; nomem: @@ -1494,11 +1492,10 @@ __acquires(uhci->lock) if (qh->type == USB_ENDPOINT_XFER_CONTROL) { - /* urb->actual_length < 0 means the setup transaction didn't - * complete successfully. Either it failed or the URB was - * unlinked first. Regardless, don't confuse people with a - * negative length. */ - urb->actual_length = max(urb->actual_length, 0); + /* Subtract off the length of the SETUP packet from + * urb->actual_length. + */ + urb->actual_length -= min_t(u32, 8, urb->actual_length); } /* When giving back the first URB in an Isochronous queue, -- cgit v1.2.3 From 251f78c308c12a5d9605d0c95b4a609341635a2f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 3 Mar 2009 16:44:13 -0800 Subject: USB: make transfer_buffer_lengths in struct urb field u32 Roel Kluin pointed out that transfer_buffer_lengths in struct urb was declared as an 'int'. This patch changes this field to be 'u32' to prevent any potential negative conversion and comparison errors. This triggered a few compiler warning messages when these fields were being used with the min macro, so they have also been fixed up in this patch. Cc: Roel Kluin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/dummy_hcd.c | 2 +- drivers/usb/host/isp116x-hcd.c | 2 +- drivers/usb/host/r8a66597-hcd.c | 2 +- drivers/usb/host/sl811-hcd.c | 4 ++-- drivers/usb/misc/ftdi-elan.c | 6 +++--- include/linux/usb.h | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 3b42888b72f8..a56b24d305f8 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -1437,7 +1437,7 @@ restart: } if (urb->transfer_buffer_length > 1) buf [1] = 0; - urb->actual_length = min (2, + urb->actual_length = min_t(u32, 2, urb->transfer_buffer_length); value = 0; status = 0; diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index 4dda31b26892..a2b305477afe 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c @@ -772,7 +772,7 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd, break; case PIPE_INTERRUPT: urb->interval = ep->period; - ep->length = min((int)ep->maxpacket, + ep->length = min_t(u32, ep->maxpacket, urb->transfer_buffer_length); /* urb submitted for already existing endpoint */ diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 5e942d94aebe..713f4cf0b0dd 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -1394,7 +1394,7 @@ static void packet_write(struct r8a66597 *r8a66597, u16 pipenum) (int)urb->iso_frame_desc[td->iso_cnt].length); } else { buf = (u16 *)(urb->transfer_buffer + urb->actual_length); - size = min((int)bufsize, + size = min_t(u32, bufsize, urb->transfer_buffer_length - urb->actual_length); } diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index e106e9d48d4a..a949259f18b9 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c @@ -230,7 +230,7 @@ static void in_packet( writeb(usb_pipedevice(urb->pipe), data_reg); sl811_write(sl811, bank + SL11H_HOSTCTLREG, control); - ep->length = min((int)len, + ep->length = min_t(u32, len, urb->transfer_buffer_length - urb->actual_length); PACKET("IN%s/%d qh%p len%d\n", ep->nak_count ? "/retry" : "", !!usb_gettoggle(urb->dev, ep->epnum, 0), ep, len); @@ -255,7 +255,7 @@ static void out_packet( buf = urb->transfer_buffer + urb->actual_length; prefetch(buf); - len = min((int)ep->maxpacket, + len = min_t(u32, ep->maxpacket, urb->transfer_buffer_length - urb->actual_length); if (!(control & SL11H_HCTLMASK_ISOCH) diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index 79a7668ef264..9d0675ed0d4c 100644 --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c @@ -1568,7 +1568,7 @@ static int ftdi_elan_edset_input(struct usb_ftdi *ftdi, u8 ed_number, struct u132_target *target = &ftdi->target[ed]; struct u132_command *command = &ftdi->command[ COMMAND_MASK & ftdi->command_next]; - int remaining_length = urb->transfer_buffer_length - + u32 remaining_length = urb->transfer_buffer_length - urb->actual_length; command->header = 0x82 | (ed << 5); if (remaining_length == 0) { @@ -1702,7 +1702,7 @@ static int ftdi_elan_edset_output(struct usb_ftdi *ftdi, u8 ed_number, | (address << 0); command->width = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)); - command->follows = min(1024, + command->follows = min_t(u32, 1024, urb->transfer_buffer_length - urb->actual_length); command->value = 0; @@ -1766,7 +1766,7 @@ static int ftdi_elan_edset_single(struct usb_ftdi *ftdi, u8 ed_number, mutex_lock(&ftdi->u132_lock); command_size = ftdi->command_next - ftdi->command_head; if (command_size < COMMAND_SIZE) { - int remaining_length = urb->transfer_buffer_length - + u32 remaining_length = urb->transfer_buffer_length - urb->actual_length; struct u132_target *target = &ftdi->target[ed]; struct u132_command *command = &ftdi->command[ diff --git a/include/linux/usb.h b/include/linux/usb.h index 0c05ff621192..db8808e05a2a 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -1177,7 +1177,7 @@ struct urb { unsigned int transfer_flags; /* (in) URB_SHORT_NOT_OK | ...*/ void *transfer_buffer; /* (in) associated data buffer */ dma_addr_t transfer_dma; /* (in) dma addr for transfer_buffer */ - int transfer_buffer_length; /* (in) data buffer length */ + u32 transfer_buffer_length; /* (in) data buffer length */ int actual_length; /* (return) actual transfer length */ unsigned char *setup_packet; /* (in) setup packet (control only) */ dma_addr_t setup_dma; /* (in) dma addr for setup_packet */ -- cgit v1.2.3 From 008ea4d96de675746e23e6ea45f9d8eeec61b403 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 6 Mar 2009 21:31:03 -0800 Subject: USB: make actual_length in struct urb field u32 actual_length should also be a u32 and not a signed value. This patch changes this field to be 'u32' to prevent any potential negative conversion and comparison errors. This triggered a few compiler warning messages when these fields were being used with the min macro, so they have also been fixed up in this patch. Cc: Roel Kluin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 2 +- include/linux/usb.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index adeb23fb8003..dcc87aaa8628 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1947,7 +1947,7 @@ static void ftdi_process_read(struct work_struct *work) priv->prev_status = new_status; } - length = min(PKTSZ, urb->actual_length-packet_offset)-2; + length = min_t(u32, PKTSZ, urb->actual_length-packet_offset)-2; if (length < 0) { dev_err(&port->dev, "%s - bad packet length: %d\n", __func__, length+2); diff --git a/include/linux/usb.h b/include/linux/usb.h index db8808e05a2a..c6b2ab41b908 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -1178,7 +1178,7 @@ struct urb { void *transfer_buffer; /* (in) associated data buffer */ dma_addr_t transfer_dma; /* (in) dma addr for transfer_buffer */ u32 transfer_buffer_length; /* (in) data buffer length */ - int actual_length; /* (return) actual transfer length */ + u32 actual_length; /* (return) actual transfer length */ unsigned char *setup_packet; /* (in) setup packet (control only) */ dma_addr_t setup_dma; /* (in) dma addr for setup_packet */ int start_frame; /* (modify) start frame (ISO) */ -- cgit v1.2.3 From 134f63558c87f7b1ebc62cbf774b98f4f42b0924 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 4 Mar 2009 16:23:31 -0800 Subject: USB: remove phidget drivers from kernel tree. These devices are better controlled with the LGPL userspace library found at: http://www.phidgets.com/downloads.php?os_id=3 and full documentation at: http://www.phidgets.com/documentation/web/cdoc/index.html Cc: Chester Fitchett Acked-by: Sean Young Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/Kconfig | 39 -- drivers/usb/misc/Makefile | 4 - drivers/usb/misc/phidget.c | 43 -- drivers/usb/misc/phidget.h | 12 - drivers/usb/misc/phidgetkit.c | 740 --------------------------------- drivers/usb/misc/phidgetmotorcontrol.c | 465 --------------------- drivers/usb/misc/phidgetservo.c | 375 ----------------- 7 files changed, 1678 deletions(-) delete mode 100644 drivers/usb/misc/phidget.c delete mode 100644 drivers/usb/misc/phidget.h delete mode 100644 drivers/usb/misc/phidgetkit.c delete mode 100644 drivers/usb/misc/phidgetmotorcontrol.c delete mode 100644 drivers/usb/misc/phidgetservo.c diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index e463db5d8188..a68d91a11bee 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -135,45 +135,6 @@ config USB_CYTHERM To compile this driver as a module, choose M here: the module will be called cytherm. -config USB_PHIDGET - tristate "USB Phidgets drivers" - depends on USB - help - Say Y here to enable the various drivers for devices from - Phidgets inc. - -config USB_PHIDGETKIT - tristate "USB PhidgetInterfaceKit support" - depends on USB_PHIDGET - help - Say Y here if you want to connect a PhidgetInterfaceKit USB device - from Phidgets Inc. - - To compile this driver as a module, choose M here: the - module will be called phidgetkit. - -config USB_PHIDGETMOTORCONTROL - tristate "USB PhidgetMotorControl support" - depends on USB_PHIDGET - help - Say Y here if you want to connect a PhidgetMotorControl USB device - from Phidgets Inc. - - To compile this driver as a module, choose M here: the - module will be called phidgetmotorcontrol. - -config USB_PHIDGETSERVO - tristate "USB PhidgetServo support" - depends on USB_PHIDGET - help - Say Y here if you want to connect an 1 or 4 Motor PhidgetServo - servo controller version 2.0 or 3.0. - - Phidgets Inc. has a web page at . - - To compile this driver as a module, choose M here: the - module will be called phidgetservo. - config USB_IDMOUSE tristate "Siemens ID USB Mouse Fingerprint sensor support" depends on USB diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index 1334f7bdd7be..0826aab8303f 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile @@ -18,10 +18,6 @@ obj-$(CONFIG_USB_LCD) += usblcd.o obj-$(CONFIG_USB_LD) += ldusb.o obj-$(CONFIG_USB_LED) += usbled.o obj-$(CONFIG_USB_LEGOTOWER) += legousbtower.o -obj-$(CONFIG_USB_PHIDGET) += phidget.o -obj-$(CONFIG_USB_PHIDGETKIT) += phidgetkit.o -obj-$(CONFIG_USB_PHIDGETMOTORCONTROL) += phidgetmotorcontrol.o -obj-$(CONFIG_USB_PHIDGETSERVO) += phidgetservo.o obj-$(CONFIG_USB_RIO500) += rio500.o obj-$(CONFIG_USB_TEST) += usbtest.o obj-$(CONFIG_USB_TRANCEVIBRATOR) += trancevibrator.o diff --git a/drivers/usb/misc/phidget.c b/drivers/usb/misc/phidget.c deleted file mode 100644 index 735ed33f4f7f..000000000000 --- a/drivers/usb/misc/phidget.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * USB Phidgets class - * - * Copyright (C) 2006 Sean Young - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include -#include -#include -#include -#include - -struct class *phidget_class; - -static int __init init_phidget(void) -{ - phidget_class = class_create(THIS_MODULE, "phidget"); - - if (IS_ERR(phidget_class)) - return PTR_ERR(phidget_class); - - return 0; -} - -static void __exit cleanup_phidget(void) -{ - class_destroy(phidget_class); -} - -EXPORT_SYMBOL_GPL(phidget_class); - -module_init(init_phidget); -module_exit(cleanup_phidget); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Sean Young "); -MODULE_DESCRIPTION("Container module for phidget class"); - diff --git a/drivers/usb/misc/phidget.h b/drivers/usb/misc/phidget.h deleted file mode 100644 index c4011907d431..000000000000 --- a/drivers/usb/misc/phidget.h +++ /dev/null @@ -1,12 +0,0 @@ -/* - * USB Phidgets class - * - * Copyright (C) 2006 Sean Young - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -extern struct class *phidget_class; diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c deleted file mode 100644 index cc8e0a926f99..000000000000 --- a/drivers/usb/misc/phidgetkit.c +++ /dev/null @@ -1,740 +0,0 @@ -/* - * USB PhidgetInterfaceKit driver 1.0 - * - * Copyright (C) 2004, 2006 Sean Young - * Copyright (C) 2005 Daniel Saakes - * Copyright (C) 2004 Greg Kroah-Hartman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This is a driver for the USB PhidgetInterfaceKit. - */ - -#include -#include -#include -#include -#include -#include - -#include "phidget.h" - -#define DRIVER_AUTHOR "Sean Young " -#define DRIVER_DESC "USB PhidgetInterfaceKit Driver" - -#define USB_VENDOR_ID_GLAB 0x06c2 -#define USB_DEVICE_ID_INTERFACEKIT004 0x0040 -#define USB_DEVICE_ID_INTERFACEKIT01616 0x0044 -#define USB_DEVICE_ID_INTERFACEKIT888 0x0045 -#define USB_DEVICE_ID_INTERFACEKIT047 0x0051 -#define USB_DEVICE_ID_INTERFACEKIT088 0x0053 - -#define USB_VENDOR_ID_WISEGROUP 0x0925 -#define USB_DEVICE_ID_INTERFACEKIT884 0x8201 - -#define MAX_INTERFACES 16 - -#define URB_INT_SIZE 8 - -struct driver_interfacekit { - int sensors; - int inputs; - int outputs; - int has_lcd; - int amnesiac; -}; - -#define ifkit(_sensors, _inputs, _outputs, _lcd, _amnesiac) \ -{ \ - .sensors = _sensors, \ - .inputs = _inputs, \ - .outputs = _outputs, \ - .has_lcd = _lcd, \ - .amnesiac = _amnesiac \ -}; - -static const struct driver_interfacekit ph_004 = ifkit(0, 0, 4, 0, 0); -static const struct driver_interfacekit ph_888n = ifkit(8, 8, 8, 0, 1); -static const struct driver_interfacekit ph_888o = ifkit(8, 8, 8, 0, 0); -static const struct driver_interfacekit ph_047 = ifkit(0, 4, 7, 1, 0); -static const struct driver_interfacekit ph_884 = ifkit(8, 8, 4, 0, 0); -static const struct driver_interfacekit ph_088 = ifkit(0, 8, 8, 1, 0); -static const struct driver_interfacekit ph_01616 = ifkit(0, 16, 16, 0, 0); - -static unsigned long device_no; - -struct interfacekit { - struct usb_device *udev; - struct usb_interface *intf; - struct driver_interfacekit *ifkit; - struct device *dev; - unsigned long outputs; - int dev_no; - u8 inputs[MAX_INTERFACES]; - u16 sensors[MAX_INTERFACES]; - u8 lcd_files_on; - - struct urb *irq; - unsigned char *data; - dma_addr_t data_dma; - - struct delayed_work do_notify; - struct delayed_work do_resubmit; - unsigned long input_events; - unsigned long sensor_events; -}; - -static struct usb_device_id id_table[] = { - {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT004), - .driver_info = (kernel_ulong_t)&ph_004}, - {USB_DEVICE_VER(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT888, 0, 0x814), - .driver_info = (kernel_ulong_t)&ph_888o}, - {USB_DEVICE_VER(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT888, 0x0815, 0xffff), - .driver_info = (kernel_ulong_t)&ph_888n}, - {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT047), - .driver_info = (kernel_ulong_t)&ph_047}, - {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT088), - .driver_info = (kernel_ulong_t)&ph_088}, - {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT01616), - .driver_info = (kernel_ulong_t)&ph_01616}, - {USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_INTERFACEKIT884), - .driver_info = (kernel_ulong_t)&ph_884}, - {} -}; -MODULE_DEVICE_TABLE(usb, id_table); - -static int set_outputs(struct interfacekit *kit) -{ - u8 *buffer; - int retval; - - buffer = kzalloc(4, GFP_KERNEL); - if (!buffer) { - dev_err(&kit->udev->dev, "%s - out of memory\n", __func__); - return -ENOMEM; - } - buffer[0] = (u8)kit->outputs; - buffer[1] = (u8)(kit->outputs >> 8); - - dev_dbg(&kit->udev->dev, "sending data: 0x%04x\n", (u16)kit->outputs); - - retval = usb_control_msg(kit->udev, - usb_sndctrlpipe(kit->udev, 0), - 0x09, 0x21, 0x0200, 0x0000, buffer, 4, 2000); - - if (retval != 4) - dev_err(&kit->udev->dev, "usb_control_msg returned %d\n", - retval); - kfree(buffer); - - if (kit->ifkit->amnesiac) - schedule_delayed_work(&kit->do_resubmit, HZ / 2); - - return retval < 0 ? retval : 0; -} - -static int change_string(struct interfacekit *kit, const char *display, unsigned char row) -{ - unsigned char *buffer; - unsigned char *form_buffer; - int retval = -ENOMEM; - int i,j, len, buf_ptr; - - buffer = kmalloc(8, GFP_KERNEL); - form_buffer = kmalloc(30, GFP_KERNEL); - if ((!buffer) || (!form_buffer)) { - dev_err(&kit->udev->dev, "%s - out of memory\n", __func__); - goto exit; - } - - len = strlen(display); - if (len > 20) - len = 20; - - dev_dbg(&kit->udev->dev, "Setting LCD line %d to %s\n", row, display); - - form_buffer[0] = row * 0x40 + 0x80; - form_buffer[1] = 0x02; - buf_ptr = 2; - for (i = 0; i 7) - len = 7; - else - len = (buf_ptr - i); - for (j = 0; j < len; j++) - buffer[j] = form_buffer[i + j]; - buffer[7] = len; - - retval = usb_control_msg(kit->udev, - usb_sndctrlpipe(kit->udev, 0), - 0x09, 0x21, 0x0200, 0x0000, buffer, 8, 2000); - if (retval < 0) - goto exit; - } - - retval = 0; -exit: - kfree(buffer); - kfree(form_buffer); - - return retval; -} - -#define set_lcd_line(number) \ -static ssize_t lcd_line_##number(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - struct interfacekit *kit = dev_get_drvdata(dev); \ - change_string(kit, buf, number - 1); \ - return count; \ -} - -#define lcd_line_attr(number) \ - __ATTR(lcd_line_##number, S_IWUGO, NULL, lcd_line_##number) - -set_lcd_line(1); -set_lcd_line(2); - -static ssize_t set_backlight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - struct interfacekit *kit = dev_get_drvdata(dev); - int enabled; - unsigned char *buffer; - int retval = -ENOMEM; - - buffer = kzalloc(8, GFP_KERNEL); - if (!buffer) { - dev_err(&kit->udev->dev, "%s - out of memory\n", __func__); - goto exit; - } - - if (sscanf(buf, "%d", &enabled) < 1) { - retval = -EINVAL; - goto exit; - } - if (enabled) - buffer[0] = 0x01; - buffer[7] = 0x11; - - dev_dbg(&kit->udev->dev, "Setting backlight to %s\n", enabled ? "on" : "off"); - - retval = usb_control_msg(kit->udev, - usb_sndctrlpipe(kit->udev, 0), - 0x09, 0x21, 0x0200, 0x0000, buffer, 8, 2000); - if (retval < 0) - goto exit; - - retval = count; -exit: - kfree(buffer); - return retval; -} - -static struct device_attribute dev_lcd_line_attrs[] = { - lcd_line_attr(1), - lcd_line_attr(2), - __ATTR(backlight, S_IWUGO, NULL, set_backlight) -}; - -static void remove_lcd_files(struct interfacekit *kit) -{ - int i; - - if (kit->lcd_files_on) { - dev_dbg(&kit->udev->dev, "Removing lcd files\n"); - - for (i=0; idev, &dev_lcd_line_attrs[i]); - } -} - -static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - struct interfacekit *kit = dev_get_drvdata(dev); - int enable; - int i, rc; - - if (kit->ifkit->has_lcd == 0) - return -ENODEV; - - if (sscanf(buf, "%d", &enable) < 1) - return -EINVAL; - - if (enable) { - if (!kit->lcd_files_on) { - dev_dbg(&kit->udev->dev, "Adding lcd files\n"); - for (i=0; idev, - &dev_lcd_line_attrs[i]); - if (rc) - goto out; - } - kit->lcd_files_on = 1; - } - } else { - if (kit->lcd_files_on) { - remove_lcd_files(kit); - kit->lcd_files_on = 0; - } - } - - return count; -out: - while (i-- > 0) - device_remove_file(kit->dev, &dev_lcd_line_attrs[i]); - - return rc; -} - -static DEVICE_ATTR(lcd, S_IWUGO, NULL, enable_lcd_files); - -static void interfacekit_irq(struct urb *urb) -{ - struct interfacekit *kit = urb->context; - unsigned char *buffer = kit->data; - int i, level, sensor; - int retval; - int status = urb->status; - - switch (status) { - case 0: /* success */ - break; - case -ECONNRESET: /* unlink */ - case -ENOENT: - case -ESHUTDOWN: - return; - /* -EPIPE: should clear the halt */ - default: /* error */ - goto resubmit; - } - - /* digital inputs */ - if (kit->ifkit->inputs == 16) { - for (i=0; i < 8; i++) { - level = (buffer[0] >> i) & 1; - if (kit->inputs[i] != level) { - kit->inputs[i] = level; - set_bit(i, &kit->input_events); - } - level = (buffer[1] >> i) & 1; - if (kit->inputs[8 + i] != level) { - kit->inputs[8 + i] = level; - set_bit(8 + i, &kit->input_events); - } - } - } - else if (kit->ifkit->inputs == 8) { - for (i=0; i < 8; i++) { - level = (buffer[1] >> i) & 1; - if (kit->inputs[i] != level) { - kit->inputs[i] = level; - set_bit(i, &kit->input_events); - } - } - } - - /* analog inputs */ - if (kit->ifkit->sensors) { - sensor = (buffer[0] & 1) ? 4 : 0; - - level = buffer[2] + (buffer[3] & 0x0f) * 256; - if (level != kit->sensors[sensor]) { - kit->sensors[sensor] = level; - set_bit(sensor, &kit->sensor_events); - } - sensor++; - level = buffer[4] + (buffer[3] & 0xf0) * 16; - if (level != kit->sensors[sensor]) { - kit->sensors[sensor] = level; - set_bit(sensor, &kit->sensor_events); - } - sensor++; - level = buffer[5] + (buffer[6] & 0x0f) * 256; - if (level != kit->sensors[sensor]) { - kit->sensors[sensor] = level; - set_bit(sensor, &kit->sensor_events); - } - sensor++; - level = buffer[7] + (buffer[6] & 0xf0) * 16; - if (level != kit->sensors[sensor]) { - kit->sensors[sensor] = level; - set_bit(sensor, &kit->sensor_events); - } - } - - if (kit->input_events || kit->sensor_events) - schedule_delayed_work(&kit->do_notify, 0); - -resubmit: - retval = usb_submit_urb(urb, GFP_ATOMIC); - if (retval) - err("can't resubmit intr, %s-%s/interfacekit0, retval %d", - kit->udev->bus->bus_name, - kit->udev->devpath, retval); -} - -static void do_notify(struct work_struct *work) -{ - struct interfacekit *kit = - container_of(work, struct interfacekit, do_notify.work); - int i; - char sysfs_file[8]; - - for (i=0; iifkit->inputs; i++) { - if (test_and_clear_bit(i, &kit->input_events)) { - sprintf(sysfs_file, "input%d", i + 1); - sysfs_notify(&kit->dev->kobj, NULL, sysfs_file); - } - } - - for (i=0; iifkit->sensors; i++) { - if (test_and_clear_bit(i, &kit->sensor_events)) { - sprintf(sysfs_file, "sensor%d", i + 1); - sysfs_notify(&kit->dev->kobj, NULL, sysfs_file); - } - } -} - -static void do_resubmit(struct work_struct *work) -{ - struct interfacekit *kit = - container_of(work, struct interfacekit, do_resubmit.work); - set_outputs(kit); -} - -#define show_set_output(value) \ -static ssize_t set_output##value(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - struct interfacekit *kit = dev_get_drvdata(dev); \ - int enable; \ - int retval; \ - \ - if (sscanf(buf, "%d", &enable) < 1) \ - return -EINVAL; \ - \ - if (enable) \ - set_bit(value - 1, &kit->outputs); \ - else \ - clear_bit(value - 1, &kit->outputs); \ - \ - retval = set_outputs(kit); \ - \ - return retval ? retval : count; \ -} \ - \ -static ssize_t show_output##value(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct interfacekit *kit = dev_get_drvdata(dev); \ - \ - return sprintf(buf, "%d\n", !!test_bit(value - 1, &kit->outputs));\ -} - -#define output_attr(value) \ - __ATTR(output##value, S_IWUGO | S_IRUGO, \ - show_output##value, set_output##value) - -show_set_output(1); -show_set_output(2); -show_set_output(3); -show_set_output(4); -show_set_output(5); -show_set_output(6); -show_set_output(7); -show_set_output(8); -show_set_output(9); -show_set_output(10); -show_set_output(11); -show_set_output(12); -show_set_output(13); -show_set_output(14); -show_set_output(15); -show_set_output(16); - -static struct device_attribute dev_output_attrs[] = { - output_attr(1), output_attr(2), output_attr(3), output_attr(4), - output_attr(5), output_attr(6), output_attr(7), output_attr(8), - output_attr(9), output_attr(10), output_attr(11), output_attr(12), - output_attr(13), output_attr(14), output_attr(15), output_attr(16) -}; - -#define show_input(value) \ -static ssize_t show_input##value(struct device *dev, \ - struct device_attribute *attr, char *buf) \ -{ \ - struct interfacekit *kit = dev_get_drvdata(dev); \ - \ - return sprintf(buf, "%d\n", (int)kit->inputs[value - 1]); \ -} - -#define input_attr(value) \ - __ATTR(input##value, S_IRUGO, show_input##value, NULL) - -show_input(1); -show_input(2); -show_input(3); -show_input(4); -show_input(5); -show_input(6); -show_input(7); -show_input(8); -show_input(9); -show_input(10); -show_input(11); -show_input(12); -show_input(13); -show_input(14); -show_input(15); -show_input(16); - -static struct device_attribute dev_input_attrs[] = { - input_attr(1), input_attr(2), input_attr(3), input_attr(4), - input_attr(5), input_attr(6), input_attr(7), input_attr(8), - input_attr(9), input_attr(10), input_attr(11), input_attr(12), - input_attr(13), input_attr(14), input_attr(15), input_attr(16) -}; - -#define show_sensor(value) \ -static ssize_t show_sensor##value(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct interfacekit *kit = dev_get_drvdata(dev); \ - \ - return sprintf(buf, "%d\n", (int)kit->sensors[value - 1]); \ -} - -#define sensor_attr(value) \ - __ATTR(sensor##value, S_IRUGO, show_sensor##value, NULL) - -show_sensor(1); -show_sensor(2); -show_sensor(3); -show_sensor(4); -show_sensor(5); -show_sensor(6); -show_sensor(7); -show_sensor(8); - -static struct device_attribute dev_sensor_attrs[] = { - sensor_attr(1), sensor_attr(2), sensor_attr(3), sensor_attr(4), - sensor_attr(5), sensor_attr(6), sensor_attr(7), sensor_attr(8) -}; - -static int interfacekit_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct usb_host_interface *interface; - struct usb_endpoint_descriptor *endpoint; - struct interfacekit *kit; - struct driver_interfacekit *ifkit; - int pipe, maxp, rc = -ENOMEM; - int bit, value, i; - - ifkit = (struct driver_interfacekit *)id->driver_info; - if (!ifkit) - return -ENODEV; - - interface = intf->cur_altsetting; - if (interface->desc.bNumEndpoints != 1) - return -ENODEV; - - endpoint = &interface->endpoint[0].desc; - if (!usb_endpoint_dir_in(endpoint)) - return -ENODEV; - /* - * bmAttributes - */ - pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); - maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); - - kit = kzalloc(sizeof(*kit), GFP_KERNEL); - if (!kit) - goto out; - - kit->dev_no = -1; - kit->ifkit = ifkit; - kit->data = usb_buffer_alloc(dev, URB_INT_SIZE, GFP_ATOMIC, &kit->data_dma); - if (!kit->data) - goto out; - - kit->irq = usb_alloc_urb(0, GFP_KERNEL); - if (!kit->irq) - goto out; - - kit->udev = usb_get_dev(dev); - kit->intf = intf; - INIT_DELAYED_WORK(&kit->do_notify, do_notify); - INIT_DELAYED_WORK(&kit->do_resubmit, do_resubmit); - usb_fill_int_urb(kit->irq, kit->udev, pipe, kit->data, - maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp, - interfacekit_irq, kit, endpoint->bInterval); - kit->irq->transfer_dma = kit->data_dma; - kit->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - usb_set_intfdata(intf, kit); - - do { - bit = find_first_zero_bit(&device_no, sizeof(device_no)); - value = test_and_set_bit(bit, &device_no); - } while(value); - kit->dev_no = bit; - - kit->dev = device_create(phidget_class, &kit->udev->dev, MKDEV(0, 0), - kit, "interfacekit%d", kit->dev_no); - if (IS_ERR(kit->dev)) { - rc = PTR_ERR(kit->dev); - kit->dev = NULL; - goto out; - } - - if (usb_submit_urb(kit->irq, GFP_KERNEL)) { - rc = -EIO; - goto out; - } - - for (i=0; ioutputs; i++ ) { - rc = device_create_file(kit->dev, &dev_output_attrs[i]); - if (rc) - goto out2; - } - - for (i=0; iinputs; i++ ) { - rc = device_create_file(kit->dev, &dev_input_attrs[i]); - if (rc) - goto out3; - } - - for (i=0; isensors; i++ ) { - rc = device_create_file(kit->dev, &dev_sensor_attrs[i]); - if (rc) - goto out4; - } - - if (ifkit->has_lcd) { - rc = device_create_file(kit->dev, &dev_attr_lcd); - if (rc) - goto out4; - - } - - dev_info(&intf->dev, "USB PhidgetInterfaceKit %d/%d/%d attached\n", - ifkit->sensors, ifkit->inputs, ifkit->outputs); - - return 0; - -out4: - while (i-- > 0) - device_remove_file(kit->dev, &dev_sensor_attrs[i]); - - i = ifkit->inputs; -out3: - while (i-- > 0) - device_remove_file(kit->dev, &dev_input_attrs[i]); - - i = ifkit->outputs; -out2: - while (i-- > 0) - device_remove_file(kit->dev, &dev_output_attrs[i]); -out: - if (kit) { - usb_free_urb(kit->irq); - if (kit->data) - usb_buffer_free(dev, URB_INT_SIZE, kit->data, kit->data_dma); - if (kit->dev) - device_unregister(kit->dev); - if (kit->dev_no >= 0) - clear_bit(kit->dev_no, &device_no); - - kfree(kit); - } - - return rc; -} - -static void interfacekit_disconnect(struct usb_interface *interface) -{ - struct interfacekit *kit; - int i; - - kit = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); - if (!kit) - return; - - usb_kill_urb(kit->irq); - usb_free_urb(kit->irq); - usb_buffer_free(kit->udev, URB_INT_SIZE, kit->data, kit->data_dma); - - cancel_delayed_work(&kit->do_notify); - cancel_delayed_work(&kit->do_resubmit); - - for (i=0; iifkit->outputs; i++) - device_remove_file(kit->dev, &dev_output_attrs[i]); - - for (i=0; iifkit->inputs; i++) - device_remove_file(kit->dev, &dev_input_attrs[i]); - - for (i=0; iifkit->sensors; i++) - device_remove_file(kit->dev, &dev_sensor_attrs[i]); - - if (kit->ifkit->has_lcd) { - device_remove_file(kit->dev, &dev_attr_lcd); - remove_lcd_files(kit); - } - - device_unregister(kit->dev); - - dev_info(&interface->dev, "USB PhidgetInterfaceKit %d/%d/%d detached\n", - kit->ifkit->sensors, kit->ifkit->inputs, kit->ifkit->outputs); - - usb_put_dev(kit->udev); - clear_bit(kit->dev_no, &device_no); - - kfree(kit); -} - -static struct usb_driver interfacekit_driver = { - .name = "phidgetkit", - .probe = interfacekit_probe, - .disconnect = interfacekit_disconnect, - .id_table = id_table -}; - -static int __init interfacekit_init(void) -{ - int retval = 0; - - retval = usb_register(&interfacekit_driver); - if (retval) - err("usb_register failed. Error number %d", retval); - - return retval; -} - -static void __exit interfacekit_exit(void) -{ - usb_deregister(&interfacekit_driver); -} - -module_init(interfacekit_init); -module_exit(interfacekit_exit); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/misc/phidgetmotorcontrol.c b/drivers/usb/misc/phidgetmotorcontrol.c deleted file mode 100644 index 38088b44349e..000000000000 --- a/drivers/usb/misc/phidgetmotorcontrol.c +++ /dev/null @@ -1,465 +0,0 @@ -/* - * USB Phidget MotorControl driver - * - * Copyright (C) 2006 Sean Young - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include -#include -#include -#include -#include - -#include "phidget.h" - -#define DRIVER_AUTHOR "Sean Young " -#define DRIVER_DESC "USB PhidgetMotorControl Driver" - -#define USB_VENDOR_ID_GLAB 0x06c2 -#define USB_DEVICE_ID_MOTORCONTROL 0x0058 - -#define URB_INT_SIZE 8 - -static unsigned long device_no; - -struct motorcontrol { - struct usb_device *udev; - struct usb_interface *intf; - struct device *dev; - int dev_no; - u8 inputs[4]; - s8 desired_speed[2]; - s8 speed[2]; - s16 _current[2]; - s8 acceleration[2]; - struct urb *irq; - unsigned char *data; - dma_addr_t data_dma; - - struct delayed_work do_notify; - unsigned long input_events; - unsigned long speed_events; - unsigned long exceed_events; -}; - -static struct usb_device_id id_table[] = { - { USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_MOTORCONTROL) }, - {} -}; -MODULE_DEVICE_TABLE(usb, id_table); - -static int set_motor(struct motorcontrol *mc, int motor) -{ - u8 *buffer; - int speed, speed2, acceleration; - int retval; - - buffer = kzalloc(8, GFP_KERNEL); - if (!buffer) { - dev_err(&mc->intf->dev, "%s - out of memory\n", __func__); - return -ENOMEM; - } - - acceleration = mc->acceleration[motor] * 10; - /* -127 <= speed <= 127 */ - speed = (mc->desired_speed[motor] * 127) / 100; - /* -0x7300 <= speed2 <= 0x7300 */ - speed2 = (mc->desired_speed[motor] * 230 * 128) / 100; - - buffer[0] = motor; - buffer[1] = speed; - buffer[2] = acceleration >> 8; - buffer[3] = acceleration; - buffer[4] = speed2 >> 8; - buffer[5] = speed2; - - retval = usb_control_msg(mc->udev, - usb_sndctrlpipe(mc->udev, 0), - 0x09, 0x21, 0x0200, 0x0000, buffer, 8, 2000); - - if (retval != 8) - dev_err(&mc->intf->dev, "usb_control_msg returned %d\n", - retval); - kfree(buffer); - - return retval < 0 ? retval : 0; -} - -static void motorcontrol_irq(struct urb *urb) -{ - struct motorcontrol *mc = urb->context; - unsigned char *buffer = mc->data; - int i, level; - int retval; - int status = urb->status;; - - switch (status) { - case 0: /* success */ - break; - case -ECONNRESET: /* unlink */ - case -ENOENT: - case -ESHUTDOWN: - return; - /* -EPIPE: should clear the halt */ - default: /* error */ - goto resubmit; - } - - /* digital inputs */ - for (i=0; i<4; i++) { - level = (buffer[0] >> i) & 1; - if (mc->inputs[i] != level) { - mc->inputs[i] = level; - set_bit(i, &mc->input_events); - } - } - - /* motor speed */ - if (buffer[2] == 0) { - for (i=0; i<2; i++) { - level = ((s8)buffer[4+i]) * 100 / 127; - if (mc->speed[i] != level) { - mc->speed[i] = level; - set_bit(i, &mc->speed_events); - } - } - } else { - int index = buffer[3] & 1; - - level = ((s8)buffer[4] << 8) | buffer[5]; - level = level * 100 / 29440; - if (mc->speed[index] != level) { - mc->speed[index] = level; - set_bit(index, &mc->speed_events); - } - - level = ((s8)buffer[6] << 8) | buffer[7]; - mc->_current[index] = level * 100 / 1572; - } - - if (buffer[1] & 1) - set_bit(0, &mc->exceed_events); - - if (buffer[1] & 2) - set_bit(1, &mc->exceed_events); - - if (mc->input_events || mc->exceed_events || mc->speed_events) - schedule_delayed_work(&mc->do_notify, 0); - -resubmit: - retval = usb_submit_urb(urb, GFP_ATOMIC); - if (retval) - dev_err(&mc->intf->dev, - "can't resubmit intr, %s-%s/motorcontrol0, retval %d\n", - mc->udev->bus->bus_name, - mc->udev->devpath, retval); -} - -static void do_notify(struct work_struct *work) -{ - struct motorcontrol *mc = - container_of(work, struct motorcontrol, do_notify.work); - int i; - char sysfs_file[8]; - - for (i=0; i<4; i++) { - if (test_and_clear_bit(i, &mc->input_events)) { - sprintf(sysfs_file, "input%d", i); - sysfs_notify(&mc->dev->kobj, NULL, sysfs_file); - } - } - - for (i=0; i<2; i++) { - if (test_and_clear_bit(i, &mc->speed_events)) { - sprintf(sysfs_file, "speed%d", i); - sysfs_notify(&mc->dev->kobj, NULL, sysfs_file); - } - } - - for (i=0; i<2; i++) { - if (test_and_clear_bit(i, &mc->exceed_events)) - dev_warn(&mc->intf->dev, - "motor #%d exceeds 1.5 Amp current limit\n", i); - } -} - -#define show_set_speed(value) \ -static ssize_t set_speed##value(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - struct motorcontrol *mc = dev_get_drvdata(dev); \ - int speed; \ - int retval; \ - \ - if (sscanf(buf, "%d", &speed) < 1) \ - return -EINVAL; \ - \ - if (speed < -100 || speed > 100) \ - return -EINVAL; \ - \ - mc->desired_speed[value] = speed; \ - \ - retval = set_motor(mc, value); \ - \ - return retval ? retval : count; \ -} \ - \ -static ssize_t show_speed##value(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct motorcontrol *mc = dev_get_drvdata(dev); \ - \ - return sprintf(buf, "%d\n", mc->speed[value]); \ -} - -#define speed_attr(value) \ - __ATTR(speed##value, S_IWUGO | S_IRUGO, \ - show_speed##value, set_speed##value) - -show_set_speed(0); -show_set_speed(1); - -#define show_set_acceleration(value) \ -static ssize_t set_acceleration##value(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - struct motorcontrol *mc = dev_get_drvdata(dev); \ - int acceleration; \ - int retval; \ - \ - if (sscanf(buf, "%d", &acceleration) < 1) \ - return -EINVAL; \ - \ - if (acceleration < 0 || acceleration > 100) \ - return -EINVAL; \ - \ - mc->acceleration[value] = acceleration; \ - \ - retval = set_motor(mc, value); \ - \ - return retval ? retval : count; \ -} \ - \ -static ssize_t show_acceleration##value(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct motorcontrol *mc = dev_get_drvdata(dev); \ - \ - return sprintf(buf, "%d\n", mc->acceleration[value]); \ -} - -#define acceleration_attr(value) \ - __ATTR(acceleration##value, S_IWUGO | S_IRUGO, \ - show_acceleration##value, set_acceleration##value) - -show_set_acceleration(0); -show_set_acceleration(1); - -#define show_current(value) \ -static ssize_t show_current##value(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct motorcontrol *mc = dev_get_drvdata(dev); \ - \ - return sprintf(buf, "%dmA\n", (int)mc->_current[value]); \ -} - -#define current_attr(value) \ - __ATTR(current##value, S_IRUGO, show_current##value, NULL) - -show_current(0); -show_current(1); - -#define show_input(value) \ -static ssize_t show_input##value(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct motorcontrol *mc = dev_get_drvdata(dev); \ - \ - return sprintf(buf, "%d\n", (int)mc->inputs[value]); \ -} - -#define input_attr(value) \ - __ATTR(input##value, S_IRUGO, show_input##value, NULL) - -show_input(0); -show_input(1); -show_input(2); -show_input(3); - -static struct device_attribute dev_attrs[] = { - input_attr(0), - input_attr(1), - input_attr(2), - input_attr(3), - speed_attr(0), - speed_attr(1), - acceleration_attr(0), - acceleration_attr(1), - current_attr(0), - current_attr(1) -}; - -static int motorcontrol_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct usb_host_interface *interface; - struct usb_endpoint_descriptor *endpoint; - struct motorcontrol *mc; - int pipe, maxp, rc = -ENOMEM; - int bit, value, i; - - interface = intf->cur_altsetting; - if (interface->desc.bNumEndpoints != 1) - return -ENODEV; - - endpoint = &interface->endpoint[0].desc; - if (!usb_endpoint_dir_in(endpoint)) - return -ENODEV; - - /* - * bmAttributes - */ - pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); - maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); - - mc = kzalloc(sizeof(*mc), GFP_KERNEL); - if (!mc) - goto out; - - mc->dev_no = -1; - mc->data = usb_buffer_alloc(dev, URB_INT_SIZE, GFP_ATOMIC, &mc->data_dma); - if (!mc->data) - goto out; - - mc->irq = usb_alloc_urb(0, GFP_KERNEL); - if (!mc->irq) - goto out; - - mc->udev = usb_get_dev(dev); - mc->intf = intf; - mc->acceleration[0] = mc->acceleration[1] = 10; - INIT_DELAYED_WORK(&mc->do_notify, do_notify); - usb_fill_int_urb(mc->irq, mc->udev, pipe, mc->data, - maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp, - motorcontrol_irq, mc, endpoint->bInterval); - mc->irq->transfer_dma = mc->data_dma; - mc->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - usb_set_intfdata(intf, mc); - - do { - bit = find_first_zero_bit(&device_no, sizeof(device_no)); - value = test_and_set_bit(bit, &device_no); - } while(value); - mc->dev_no = bit; - - mc->dev = device_create(phidget_class, &mc->udev->dev, MKDEV(0, 0), mc, - "motorcontrol%d", mc->dev_no); - if (IS_ERR(mc->dev)) { - rc = PTR_ERR(mc->dev); - mc->dev = NULL; - goto out; - } - - if (usb_submit_urb(mc->irq, GFP_KERNEL)) { - rc = -EIO; - goto out; - } - - for (i=0; idev, &dev_attrs[i]); - if (rc) - goto out2; - } - - dev_info(&intf->dev, "USB PhidgetMotorControl attached\n"); - - return 0; -out2: - while (i-- > 0) - device_remove_file(mc->dev, &dev_attrs[i]); -out: - if (mc) { - usb_free_urb(mc->irq); - if (mc->data) - usb_buffer_free(dev, URB_INT_SIZE, mc->data, mc->data_dma); - if (mc->dev) - device_unregister(mc->dev); - if (mc->dev_no >= 0) - clear_bit(mc->dev_no, &device_no); - - kfree(mc); - } - - return rc; -} - -static void motorcontrol_disconnect(struct usb_interface *interface) -{ - struct motorcontrol *mc; - int i; - - mc = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); - if (!mc) - return; - - usb_kill_urb(mc->irq); - usb_free_urb(mc->irq); - usb_buffer_free(mc->udev, URB_INT_SIZE, mc->data, mc->data_dma); - - cancel_delayed_work(&mc->do_notify); - - for (i=0; idev, &dev_attrs[i]); - - device_unregister(mc->dev); - - usb_put_dev(mc->udev); - clear_bit(mc->dev_no, &device_no); - kfree(mc); - - dev_info(&interface->dev, "USB PhidgetMotorControl detached\n"); -} - -static struct usb_driver motorcontrol_driver = { - .name = "phidgetmotorcontrol", - .probe = motorcontrol_probe, - .disconnect = motorcontrol_disconnect, - .id_table = id_table -}; - -static int __init motorcontrol_init(void) -{ - int retval = 0; - - retval = usb_register(&motorcontrol_driver); - if (retval) - err("usb_register failed. Error number %d", retval); - - return retval; -} - -static void __exit motorcontrol_exit(void) -{ - usb_deregister(&motorcontrol_driver); -} - -module_init(motorcontrol_init); -module_exit(motorcontrol_exit); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/misc/phidgetservo.c b/drivers/usb/misc/phidgetservo.c deleted file mode 100644 index bef6fe16364b..000000000000 --- a/drivers/usb/misc/phidgetservo.c +++ /dev/null @@ -1,375 +0,0 @@ -/* - * USB PhidgetServo driver 1.0 - * - * Copyright (C) 2004, 2006 Sean Young - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This is a driver for the USB PhidgetServo version 2.0 and 3.0 servo - * controllers available at: http://www.phidgets.com/ - * - * Note that the driver takes input as: degrees.minutes - * - * CAUTION: Generally you should use 0 < degrees < 180 as anything else - * is probably beyond the range of your servo and may damage it. - */ - -#include -#include -#include -#include -#include -#include - -#include "phidget.h" - -#define DRIVER_AUTHOR "Sean Young " -#define DRIVER_DESC "USB PhidgetServo Driver" - -#define VENDOR_ID_GLAB 0x06c2 -#define DEVICE_ID_GLAB_PHIDGETSERVO_QUAD 0x0038 -#define DEVICE_ID_GLAB_PHIDGETSERVO_UNI 0x0039 - -#define VENDOR_ID_WISEGROUP 0x0925 -#define VENDOR_ID_WISEGROUP_PHIDGETSERVO_QUAD 0x8101 -#define VENDOR_ID_WISEGROUP_PHIDGETSERVO_UNI 0x8104 - -#define SERVO_VERSION_30 0x01 -#define SERVO_COUNT_QUAD 0x02 - -static struct usb_device_id id_table[] = { - { - USB_DEVICE(VENDOR_ID_GLAB, DEVICE_ID_GLAB_PHIDGETSERVO_QUAD), - .driver_info = SERVO_VERSION_30 | SERVO_COUNT_QUAD - }, - { - USB_DEVICE(VENDOR_ID_GLAB, DEVICE_ID_GLAB_PHIDGETSERVO_UNI), - .driver_info = SERVO_VERSION_30 - }, - { - USB_DEVICE(VENDOR_ID_WISEGROUP, - VENDOR_ID_WISEGROUP_PHIDGETSERVO_QUAD), - .driver_info = SERVO_COUNT_QUAD - }, - { - USB_DEVICE(VENDOR_ID_WISEGROUP, - VENDOR_ID_WISEGROUP_PHIDGETSERVO_UNI), - .driver_info = 0 - }, - {} -}; - -MODULE_DEVICE_TABLE(usb, id_table); - -static int unsigned long device_no; - -struct phidget_servo { - struct usb_device *udev; - struct device *dev; - int dev_no; - ulong type; - int pulse[4]; - int degrees[4]; - int minutes[4]; -}; - -static int -change_position_v30(struct phidget_servo *servo, int servo_no, int degrees, - int minutes) -{ - int retval; - unsigned char *buffer; - - if (degrees < -23 || degrees > 362) - return -EINVAL; - - buffer = kmalloc(6, GFP_KERNEL); - if (!buffer) { - dev_err(&servo->udev->dev, "%s - out of memory\n", - __func__); - return -ENOMEM; - } - - /* - * pulse = 0 - 4095 - * angle = 0 - 180 degrees - * - * pulse = angle * 10.6 + 243.8 - */ - servo->pulse[servo_no] = ((degrees*60 + minutes)*106 + 2438*60)/600; - servo->degrees[servo_no]= degrees; - servo->minutes[servo_no]= minutes; - - /* - * The PhidgetServo v3.0 is controlled by sending 6 bytes, - * 4 * 12 bits for each servo. - * - * low = lower 8 bits pulse - * high = higher 4 bits pulse - * - * offset bits - * +---+-----------------+ - * | 0 | low 0 | - * +---+--------+--------+ - * | 1 | high 1 | high 0 | - * +---+--------+--------+ - * | 2 | low 1 | - * +---+-----------------+ - * | 3 | low 2 | - * +---+--------+--------+ - * | 4 | high 3 | high 2 | - * +---+--------+--------+ - * | 5 | low 3 | - * +---+-----------------+ - */ - - buffer[0] = servo->pulse[0] & 0xff; - buffer[1] = (servo->pulse[0] >> 8 & 0x0f) - | (servo->pulse[1] >> 4 & 0xf0); - buffer[2] = servo->pulse[1] & 0xff; - buffer[3] = servo->pulse[2] & 0xff; - buffer[4] = (servo->pulse[2] >> 8 & 0x0f) - | (servo->pulse[3] >> 4 & 0xf0); - buffer[5] = servo->pulse[3] & 0xff; - - dev_dbg(&servo->udev->dev, - "data: %02x %02x %02x %02x %02x %02x\n", - buffer[0], buffer[1], buffer[2], - buffer[3], buffer[4], buffer[5]); - - retval = usb_control_msg(servo->udev, - usb_sndctrlpipe(servo->udev, 0), - 0x09, 0x21, 0x0200, 0x0000, buffer, 6, 2000); - - kfree(buffer); - - return retval; -} - -static int -change_position_v20(struct phidget_servo *servo, int servo_no, int degrees, - int minutes) -{ - int retval; - unsigned char *buffer; - - if (degrees < -23 || degrees > 278) - return -EINVAL; - - buffer = kmalloc(2, GFP_KERNEL); - if (!buffer) { - dev_err(&servo->udev->dev, "%s - out of memory\n", - __func__); - return -ENOMEM; - } - - /* - * angle = 0 - 180 degrees - * pulse = angle + 23 - */ - servo->pulse[servo_no]= degrees + 23; - servo->degrees[servo_no]= degrees; - servo->minutes[servo_no]= 0; - - /* - * The PhidgetServo v2.0 is controlled by sending two bytes. The - * first byte is the servo number xor'ed with 2: - * - * servo 0 = 2 - * servo 1 = 3 - * servo 2 = 0 - * servo 3 = 1 - * - * The second byte is the position. - */ - - buffer[0] = servo_no ^ 2; - buffer[1] = servo->pulse[servo_no]; - - dev_dbg(&servo->udev->dev, "data: %02x %02x\n", buffer[0], buffer[1]); - - retval = usb_control_msg(servo->udev, - usb_sndctrlpipe(servo->udev, 0), - 0x09, 0x21, 0x0200, 0x0000, buffer, 2, 2000); - - kfree(buffer); - - return retval; -} - -#define show_set(value) \ -static ssize_t set_servo##value (struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - int degrees, minutes, retval; \ - struct phidget_servo *servo = dev_get_drvdata(dev); \ - \ - minutes = 0; \ - /* must at least convert degrees */ \ - if (sscanf(buf, "%d.%d", °rees, &minutes) < 1) { \ - return -EINVAL; \ - } \ - \ - if (minutes < 0 || minutes > 59) \ - return -EINVAL; \ - \ - if (servo->type & SERVO_VERSION_30) \ - retval = change_position_v30(servo, value, degrees, \ - minutes); \ - else \ - retval = change_position_v20(servo, value, degrees, \ - minutes); \ - \ - return retval < 0 ? retval : count; \ -} \ - \ -static ssize_t show_servo##value (struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct phidget_servo *servo = dev_get_drvdata(dev); \ - \ - return sprintf(buf, "%d.%02d\n", servo->degrees[value], \ - servo->minutes[value]); \ -} - -#define servo_attr(value) \ - __ATTR(servo##value, S_IWUGO | S_IRUGO, \ - show_servo##value, set_servo##value) -show_set(0); -show_set(1); -show_set(2); -show_set(3); - -static struct device_attribute dev_attrs[] = { - servo_attr(0), servo_attr(1), servo_attr(2), servo_attr(3) -}; - -static int -servo_probe(struct usb_interface *interface, const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(interface); - struct phidget_servo *dev; - int bit, value, rc; - int servo_count, i; - - dev = kzalloc(sizeof (struct phidget_servo), GFP_KERNEL); - if (dev == NULL) { - dev_err(&interface->dev, "%s - out of memory\n", __func__); - rc = -ENOMEM; - goto out; - } - - dev->udev = usb_get_dev(udev); - dev->type = id->driver_info; - dev->dev_no = -1; - usb_set_intfdata(interface, dev); - - do { - bit = find_first_zero_bit(&device_no, sizeof(device_no)); - value = test_and_set_bit(bit, &device_no); - } while (value); - dev->dev_no = bit; - - dev->dev = device_create(phidget_class, &dev->udev->dev, MKDEV(0, 0), - dev, "servo%d", dev->dev_no); - if (IS_ERR(dev->dev)) { - rc = PTR_ERR(dev->dev); - dev->dev = NULL; - goto out; - } - - servo_count = dev->type & SERVO_COUNT_QUAD ? 4 : 1; - - for (i=0; idev, &dev_attrs[i]); - if (rc) - goto out2; - } - - dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 attached\n", - servo_count, dev->type & SERVO_VERSION_30 ? 3 : 2); - - if (!(dev->type & SERVO_VERSION_30)) - dev_info(&interface->dev, - "WARNING: v2.0 not tested! Please report if it works.\n"); - - return 0; -out2: - while (i-- > 0) - device_remove_file(dev->dev, &dev_attrs[i]); -out: - if (dev) { - if (dev->dev) - device_unregister(dev->dev); - if (dev->dev_no >= 0) - clear_bit(dev->dev_no, &device_no); - - kfree(dev); - } - - return rc; -} - -static void -servo_disconnect(struct usb_interface *interface) -{ - struct phidget_servo *dev; - int servo_count, i; - - dev = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); - - if (!dev) - return; - - servo_count = dev->type & SERVO_COUNT_QUAD ? 4 : 1; - - for (i=0; idev, &dev_attrs[i]); - - device_unregister(dev->dev); - usb_put_dev(dev->udev); - - dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 detached\n", - servo_count, dev->type & SERVO_VERSION_30 ? 3 : 2); - - clear_bit(dev->dev_no, &device_no); - kfree(dev); -} - -static struct usb_driver servo_driver = { - .name = "phidgetservo", - .probe = servo_probe, - .disconnect = servo_disconnect, - .id_table = id_table -}; - -static int __init -phidget_servo_init(void) -{ - int retval; - - retval = usb_register(&servo_driver); - if (retval) - err("usb_register failed. Error number %d", retval); - - return retval; -} - -static void __exit -phidget_servo_exit(void) -{ - usb_deregister(&servo_driver); -} - -module_init(phidget_servo_init); -module_exit(phidget_servo_exit); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); -- cgit v1.2.3 From b8ef4ec4a6a3ca34ce141dcca3112bb613f9b643 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 26 Feb 2009 10:21:02 -0500 Subject: USB: don't send Set-Interface after reset This patch (as1221) changes the way usbcore reinitializes a device following a reset or a reset-resume. Currently we call usb_set_interface() for every interface in the active configuration; this is to put the interface into the same altsetting as before the reset and to make sure that the host's endpoint state matches the device's endpoint state. However, sending a Set-Interface request is a waste of time if an interface was already in altsetting 0 before the reset, since it is certainly in altsetting 0 afterward. In addition, many devices can't handle Set-Interface requests -- they crash when they receive them. So instead, the patch adds code to check each interface. If the interface wasn't in altsetting 0 before the reset, we go head with the Set-Interface request as before. But if it was then we skip sending the Set-Interface request, and we clear out the host-side endpoint state by calling usb_disable_interface() followed by usb_enable_interface(). The patch also adds a couple of new comments to explain what's going on. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index f17d9ebc44af..81eb3e6b6592 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3393,10 +3393,10 @@ static int usb_reset_and_verify_device(struct usb_device *udev) udev->descriptor = descriptor; /* for disconnect() calls */ goto re_enumerate; } - + + /* Restore the device's previous configuration */ if (!udev->actconfig) goto done; - ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), USB_REQ_SET_CONFIGURATION, 0, udev->actconfig->desc.bConfigurationValue, 0, @@ -3409,16 +3409,25 @@ static int usb_reset_and_verify_device(struct usb_device *udev) } usb_set_device_state(udev, USB_STATE_CONFIGURED); + /* Put interfaces back into the same altsettings as before. + * Don't bother to send the Set-Interface request for interfaces + * that were already in altsetting 0; besides being unnecessary, + * many devices can't handle it. Instead just reset the host-side + * endpoint state. + */ for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { struct usb_interface *intf = udev->actconfig->interface[i]; struct usb_interface_descriptor *desc; - /* set_interface resets host side toggle even - * for altsetting zero. the interface may have no driver. - */ desc = &intf->cur_altsetting->desc; - ret = usb_set_interface(udev, desc->bInterfaceNumber, - desc->bAlternateSetting); + if (desc->bAlternateSetting == 0) { + usb_disable_interface(udev, intf, true); + usb_enable_interface(udev, intf, true); + ret = 0; + } else { + ret = usb_set_interface(udev, desc->bInterfaceNumber, + desc->bAlternateSetting); + } if (ret < 0) { dev_err(&udev->dev, "failed to restore interface %d " "altsetting %d (error=%d)\n", -- cgit v1.2.3 From 07515d7c9e09e6934c71e384c4722e0044b87a80 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 9 Mar 2009 13:44:48 -0400 Subject: USB: usbfs: remove unneeded "inline" annotations This patch (as1223) removes a bunch of unnecessary "inline" annotations from the usbfs driver. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 8f022af2fd7a..d3883f639604 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -104,7 +104,7 @@ MODULE_PARM_DESC(usbfs_snoop, "true to log all usbfs traffic"); #define MAX_USBFS_BUFFER_SIZE 16384 -static inline int connected(struct dev_state *ps) +static int connected(struct dev_state *ps) { return (!list_empty(&ps->list) && ps->dev->state != USB_STATE_NOTATTACHED); @@ -248,7 +248,7 @@ static void free_async(struct async *as) kfree(as); } -static inline void async_newpending(struct async *as) +static void async_newpending(struct async *as) { struct dev_state *ps = as->ps; unsigned long flags; @@ -258,7 +258,7 @@ static inline void async_newpending(struct async *as) spin_unlock_irqrestore(&ps->lock, flags); } -static inline void async_removepending(struct async *as) +static void async_removepending(struct async *as) { struct dev_state *ps = as->ps; unsigned long flags; @@ -268,7 +268,7 @@ static inline void async_removepending(struct async *as) spin_unlock_irqrestore(&ps->lock, flags); } -static inline struct async *async_getcompleted(struct dev_state *ps) +static struct async *async_getcompleted(struct dev_state *ps) { unsigned long flags; struct async *as = NULL; @@ -283,7 +283,7 @@ static inline struct async *async_getcompleted(struct dev_state *ps) return as; } -static inline struct async *async_getpending(struct dev_state *ps, +static struct async *async_getpending(struct dev_state *ps, void __user *userurb) { unsigned long flags; @@ -376,7 +376,7 @@ static void destroy_async_on_interface(struct dev_state *ps, destroy_async(ps, &hitlist); } -static inline void destroy_all_async(struct dev_state *ps) +static void destroy_all_async(struct dev_state *ps) { destroy_async(ps, &ps->async_pending); } -- cgit v1.2.3 From 64102a2104a9b9828078472de8a4f8cf103d75f5 Mon Sep 17 00:00:00 2001 From: Johannes Weiner Date: Wed, 4 Mar 2009 12:06:15 -0800 Subject: USB: use kzfree() Use kzfree() instead of memset() + kfree(). Signed-off-by: Johannes Weiner Reviewed-by: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/hwa-hc.c | 3 +-- drivers/usb/wusbcore/cbaf.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/hwa-hc.c b/drivers/usb/host/hwa-hc.c index 8582236e4cad..cbf30e515f29 100644 --- a/drivers/usb/host/hwa-hc.c +++ b/drivers/usb/host/hwa-hc.c @@ -464,8 +464,7 @@ static int __hwahc_dev_set_key(struct wusbhc *wusbhc, u8 port_idx, u32 tkid, port_idx << 8 | iface_no, keyd, keyd_len, 1000 /* FIXME: arbitrary */); - memset(keyd, 0, sizeof(*keyd)); /* clear keys etc. */ - kfree(keyd); + kzfree(keyd); /* clear keys etc. */ return result; } diff --git a/drivers/usb/wusbcore/cbaf.c b/drivers/usb/wusbcore/cbaf.c index 1335cbe1191d..25eae405f622 100644 --- a/drivers/usb/wusbcore/cbaf.c +++ b/drivers/usb/wusbcore/cbaf.c @@ -638,8 +638,7 @@ static void cbaf_disconnect(struct usb_interface *iface) usb_put_intf(iface); kfree(cbaf->buffer); /* paranoia: clean up crypto keys */ - memset(cbaf, 0, sizeof(*cbaf)); - kfree(cbaf); + kzfree(cbaf); } static struct usb_device_id cbaf_id_table[] = { -- cgit v1.2.3 From 4222e4c90e13ae7053ab7190ba7b23c94acf03c0 Mon Sep 17 00:00:00 2001 From: Craig Shelley Date: Thu, 26 Feb 2009 22:19:22 +0000 Subject: USB: CP2101 Support AN205 baud rates This patch adds support for the extended range of baud rates supported by CP2102 and CP2103 devices described in SiLabs AN205. An additional function cp2101_quantise_baudrate rounds the baud rate as per AN205 Table 1. A modification to the baud rate calculation removes a rounding error, allowing the full range of baud rates to be used. Signed-off-by: Craig Shelley Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp2101.c | 92 +++++++++++++++++++++++++-------------------- 1 file changed, 52 insertions(+), 40 deletions(-) diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index 9b4082b58c5b..9b56e35aee4d 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c @@ -31,7 +31,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v0.07" +#define DRIVER_VERSION "v0.08" #define DRIVER_DESC "Silicon Labs CP2101/CP2102 RS232 serial adaptor driver" /* @@ -301,6 +301,47 @@ static inline int cp2101_set_config_single(struct usb_serial_port *port, return cp2101_set_config(port, request, &data, 2); } +/* + * cp2101_quantise_baudrate + * Quantises the baud rate as per AN205 Table 1 + */ +static unsigned int cp2101_quantise_baudrate(unsigned int baud) { + if (baud <= 56) baud = 0; + else if (baud <= 300) baud = 300; + else if (baud <= 600) baud = 600; + else if (baud <= 1200) baud = 1200; + else if (baud <= 1800) baud = 1800; + else if (baud <= 2400) baud = 2400; + else if (baud <= 4000) baud = 4000; + else if (baud <= 4803) baud = 4800; + else if (baud <= 7207) baud = 7200; + else if (baud <= 9612) baud = 9600; + else if (baud <= 14428) baud = 14400; + else if (baud <= 16062) baud = 16000; + else if (baud <= 19250) baud = 19200; + else if (baud <= 28912) baud = 28800; + else if (baud <= 38601) baud = 38400; + else if (baud <= 51558) baud = 51200; + else if (baud <= 56280) baud = 56000; + else if (baud <= 58053) baud = 57600; + else if (baud <= 64111) baud = 64000; + else if (baud <= 77608) baud = 76800; + else if (baud <= 117028) baud = 115200; + else if (baud <= 129347) baud = 128000; + else if (baud <= 156868) baud = 153600; + else if (baud <= 237832) baud = 230400; + else if (baud <= 254234) baud = 250000; + else if (baud <= 273066) baud = 256000; + else if (baud <= 491520) baud = 460800; + else if (baud <= 567138) baud = 500000; + else if (baud <= 670254) baud = 576000; + else if (baud <= 1053257) baud = 921600; + else if (baud <= 1474560) baud = 1228800; + else if (baud <= 2457600) baud = 1843200; + else baud = 3686400; + return baud; +} + static int cp2101_open(struct tty_struct *tty, struct usb_serial_port *port, struct file *filp) { @@ -388,7 +429,7 @@ static void cp2101_get_termios (struct tty_struct *tty) cp2101_get_config(port, CP2101_BAUDRATE, &baud, 2); /* Convert to baudrate */ if (baud) - baud = BAUD_RATE_GEN_FREQ / baud; + baud = cp2101_quantise_baudrate((BAUD_RATE_GEN_FREQ + baud/2)/ baud); dbg("%s - baud rate = %d", __func__, baud); @@ -517,46 +558,17 @@ static void cp2101_set_termios(struct tty_struct *tty, tty->termios->c_cflag &= ~CMSPAR; cflag = tty->termios->c_cflag; old_cflag = old_termios->c_cflag; - baud = tty_get_baud_rate(tty); + baud = cp2101_quantise_baudrate(tty_get_baud_rate(tty)); /* If the baud rate is to be updated*/ - if (baud != tty_termios_baud_rate(old_termios)) { - switch (baud) { - case 0: - case 600: - case 1200: - case 1800: - case 2400: - case 4800: - case 7200: - case 9600: - case 14400: - case 19200: - case 28800: - case 38400: - case 55854: - case 57600: - case 115200: - case 127117: - case 230400: - case 460800: - case 921600: - case 3686400: - break; - default: - baud = 9600; - break; - } - - if (baud) { - dbg("%s - Setting baud rate to %d baud", __func__, - baud); - if (cp2101_set_config_single(port, CP2101_BAUDRATE, - (BAUD_RATE_GEN_FREQ / baud))) { - dev_err(&port->dev, "Baud rate requested not " - "supported by device\n"); - baud = tty_termios_baud_rate(old_termios); - } + if (baud != tty_termios_baud_rate(old_termios) && baud != 0) { + dbg("%s - Setting baud rate to %d baud", __func__, + baud); + if (cp2101_set_config_single(port, CP2101_BAUDRATE, + ((BAUD_RATE_GEN_FREQ + baud/2) / baud))) { + dev_err(&port->dev, "Baud rate requested not " + "supported by device\n"); + baud = tty_termios_baud_rate(old_termios); } } /* Report back the resulting baud rate */ -- cgit v1.2.3 From 40bcaf547e07aebddbf6d71593785e972fbcf4cd Mon Sep 17 00:00:00 2001 From: Craig Shelley Date: Thu, 26 Feb 2009 22:21:51 +0000 Subject: USB: CP2101 Reduce Error Logging This patch lowers the logging priority of certain messages to prevent users from flooding the log files. Signed-off-by: Craig Shelley Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp2101.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index 9b56e35aee4d..2f23d0643624 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c @@ -11,10 +11,6 @@ * thanks to Karl Hiramoto karl@hiramoto.org. RTSCTS hardware flow * control thanks to Munir Nassar nassarmu@real-time.com * - * Outstanding Issues: - * Buffers are not flushed when the port is opened. - * Multiple calls to write() may fail with "Resource temporarily unavailable" - * */ #include @@ -225,7 +221,7 @@ static int cp2101_get_config(struct usb_serial_port *port, u8 request, kfree(buf); if (result != size) { - dev_err(&port->dev, "%s - Unable to send config request, " + dbg("%s - Unable to send config request, " "request=0x%x size=%d result=%d\n", __func__, request, size, result); return -EPROTO; @@ -276,7 +272,7 @@ static int cp2101_set_config(struct usb_serial_port *port, u8 request, kfree(buf); if ((size > 2 && result != size) || result < 0) { - dev_err(&port->dev, "%s - Unable to send request, " + dbg("%s - Unable to send request, " "request=0x%x size=%d result=%d\n", __func__, request, size, result); return -EPROTO; @@ -566,8 +562,7 @@ static void cp2101_set_termios(struct tty_struct *tty, baud); if (cp2101_set_config_single(port, CP2101_BAUDRATE, ((BAUD_RATE_GEN_FREQ + baud/2) / baud))) { - dev_err(&port->dev, "Baud rate requested not " - "supported by device\n"); + dbg("Baud rate requested not supported by device\n"); baud = tty_termios_baud_rate(old_termios); } } @@ -600,14 +595,14 @@ static void cp2101_set_termios(struct tty_struct *tty, dbg("%s - data bits = 9", __func__); break;*/ default: - dev_err(&port->dev, "cp2101 driver does not " + dbg("cp2101 driver does not " "support the number of bits requested," " using 8 bit mode\n"); bits |= BITS_DATA_8; break; } if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) - dev_err(&port->dev, "Number of data bits requested " + dbg("Number of data bits requested " "not supported by device\n"); } @@ -624,7 +619,7 @@ static void cp2101_set_termios(struct tty_struct *tty, } } if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) - dev_err(&port->dev, "Parity mode not supported " + dbg("Parity mode not supported " "by device\n"); } @@ -639,7 +634,7 @@ static void cp2101_set_termios(struct tty_struct *tty, dbg("%s - stop bits = 1", __func__); } if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) - dev_err(&port->dev, "Number of stop bits requested " + dbg("Number of stop bits requested " "not supported by device\n"); } -- cgit v1.2.3 From 870e360f520fccdc22a327edc5ac7af8dfe076a9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 11 Mar 2009 11:03:49 -0700 Subject: USB: serial: rename cp2101 driver to cp210x Lots of users are getting confused about the cp2101 driver. It really does support more than just the cp2101 device, so rename it to cp210x to try to prevent confusion. Cc: Craig Shelley Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/Kconfig | 10 +- drivers/usb/serial/Makefile | 2 +- drivers/usb/serial/cp2101.c | 788 -------------------------------------------- drivers/usb/serial/cp210x.c | 788 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 794 insertions(+), 794 deletions(-) delete mode 100644 drivers/usb/serial/cp2101.c create mode 100644 drivers/usb/serial/cp210x.c diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index 4afe73e8ec4a..a65f9196b0a0 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -116,14 +116,14 @@ config USB_SERIAL_DIGI_ACCELEPORT To compile this driver as a module, choose M here: the module will be called digi_acceleport. -config USB_SERIAL_CP2101 - tristate "USB CP2101 UART Bridge Controller" +config USB_SERIAL_CP210X + tristate "USB CP210x family of UART Bridge Controllers" help - Say Y here if you want to use a CP2101/CP2102 based USB to RS232 - converter. + Say Y here if you want to use a CP2101/CP2102/CP2103 based USB + to RS232 converters. To compile this driver as a module, choose M here: the - module will be called cp2101. + module will be called cp210x. config USB_SERIAL_CYPRESS_M8 tristate "USB Cypress M8 USB Serial Driver" diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index 94043babe1d3..66619beb6cc0 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -15,7 +15,7 @@ obj-$(CONFIG_USB_SERIAL_AIRCABLE) += aircable.o obj-$(CONFIG_USB_SERIAL_ARK3116) += ark3116.o obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o obj-$(CONFIG_USB_SERIAL_CH341) += ch341.o -obj-$(CONFIG_USB_SERIAL_CP2101) += cp2101.o +obj-$(CONFIG_USB_SERIAL_CP210X) += cp210x.o obj-$(CONFIG_USB_SERIAL_CYBERJACK) += cyberjack.o obj-$(CONFIG_USB_SERIAL_CYPRESS_M8) += cypress_m8.o obj-$(CONFIG_USB_SERIAL_DEBUG) += usb_debug.o diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c deleted file mode 100644 index 2f23d0643624..000000000000 --- a/drivers/usb/serial/cp2101.c +++ /dev/null @@ -1,788 +0,0 @@ -/* - * Silicon Laboratories CP2101/CP2102 USB to RS232 serial adaptor driver - * - * Copyright (C) 2005 Craig Shelley (craig@microtron.org.uk) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version - * 2 as published by the Free Software Foundation. - * - * Support to set flow control line levels using TIOCMGET and TIOCMSET - * thanks to Karl Hiramoto karl@hiramoto.org. RTSCTS hardware flow - * control thanks to Munir Nassar nassarmu@real-time.com - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Version Information - */ -#define DRIVER_VERSION "v0.08" -#define DRIVER_DESC "Silicon Labs CP2101/CP2102 RS232 serial adaptor driver" - -/* - * Function Prototypes - */ -static int cp2101_open(struct tty_struct *, struct usb_serial_port *, - struct file *); -static void cp2101_cleanup(struct usb_serial_port *); -static void cp2101_close(struct tty_struct *, struct usb_serial_port *, - struct file*); -static void cp2101_get_termios(struct tty_struct *); -static void cp2101_set_termios(struct tty_struct *, struct usb_serial_port *, - struct ktermios*); -static int cp2101_tiocmget(struct tty_struct *, struct file *); -static int cp2101_tiocmset(struct tty_struct *, struct file *, - unsigned int, unsigned int); -static void cp2101_break_ctl(struct tty_struct *, int); -static int cp2101_startup(struct usb_serial *); -static void cp2101_shutdown(struct usb_serial *); - - -static int debug; - -static struct usb_device_id id_table [] = { - { USB_DEVICE(0x0471, 0x066A) }, /* AKTAKOM ACE-1001 cable */ - { USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */ - { USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */ - { USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */ - { USB_DEVICE(0x0FCF, 0x1004) }, /* Dynastream ANT2USB */ - { USB_DEVICE(0x0FCF, 0x1006) }, /* Dynastream ANT development board */ - { USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */ - { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */ - { USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */ - { USB_DEVICE(0x10C4, 0x800A) }, /* SPORTident BSM7-D-USB main station */ - { USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */ - { USB_DEVICE(0x10C4, 0x8053) }, /* Enfora EDG1228 */ - { USB_DEVICE(0x10C4, 0x8054) }, /* Enfora GSM2228 */ - { USB_DEVICE(0x10C4, 0x8066) }, /* Argussoft In-System Programmer */ - { USB_DEVICE(0x10C4, 0x807A) }, /* Crumb128 board */ - { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */ - { USB_DEVICE(0x10C4, 0x80DD) }, /* Tracient RFID */ - { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */ - { USB_DEVICE(0x10C4, 0x8115) }, /* Arygon NFC/Mifare Reader */ - { USB_DEVICE(0x10C4, 0x813D) }, /* Burnside Telecom Deskmobile */ - { USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */ - { USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */ - { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */ - { USB_DEVICE(0x10C4, 0x819F) }, /* MJS USB Toslink Switcher */ - { USB_DEVICE(0x10C4, 0x81A6) }, /* ThinkOptics WavIt */ - { USB_DEVICE(0x10C4, 0x81AC) }, /* MSD Dash Hawk */ - { USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */ - { USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */ - { USB_DEVICE(0x10C4, 0x81E7) }, /* Aerocomm Radio */ - { USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */ - { USB_DEVICE(0x10C4, 0x822B) }, /* Modem EDGE(GSM) Comander 2 */ - { USB_DEVICE(0x10C4, 0x826B) }, /* Cygnal Integrated Products, Inc., Fasttrax GPS demostration module */ - { USB_DEVICE(0x10c4, 0x8293) }, /* Telegesys ETRX2USB */ - { USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */ - { USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */ - { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ - { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ - { USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */ - { USB_DEVICE(0x10C4, 0xF002) }, /* Elan Digital Systems USBwave12 */ - { USB_DEVICE(0x10C4, 0xF003) }, /* Elan Digital Systems USBpulse100 */ - { USB_DEVICE(0x10C4, 0xF004) }, /* Elan Digital Systems USBcount50 */ - { USB_DEVICE(0x10C5, 0xEA61) }, /* Silicon Labs MobiData GPRS USB Modem */ - { USB_DEVICE(0x13AD, 0x9999) }, /* Baltech card reader */ - { USB_DEVICE(0x166A, 0x0303) }, /* Clipsal 5500PCU C-Bus USB interface */ - { USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */ - { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ - { } /* Terminating Entry */ -}; - -MODULE_DEVICE_TABLE(usb, id_table); - -static struct usb_driver cp2101_driver = { - .name = "cp2101", - .probe = usb_serial_probe, - .disconnect = usb_serial_disconnect, - .id_table = id_table, - .no_dynamic_id = 1, -}; - -static struct usb_serial_driver cp2101_device = { - .driver = { - .owner = THIS_MODULE, - .name = "cp2101", - }, - .usb_driver = &cp2101_driver, - .id_table = id_table, - .num_ports = 1, - .open = cp2101_open, - .close = cp2101_close, - .break_ctl = cp2101_break_ctl, - .set_termios = cp2101_set_termios, - .tiocmget = cp2101_tiocmget, - .tiocmset = cp2101_tiocmset, - .attach = cp2101_startup, - .shutdown = cp2101_shutdown, -}; - -/* Config request types */ -#define REQTYPE_HOST_TO_DEVICE 0x41 -#define REQTYPE_DEVICE_TO_HOST 0xc1 - -/* Config SET requests. To GET, add 1 to the request number */ -#define CP2101_UART 0x00 /* Enable / Disable */ -#define CP2101_BAUDRATE 0x01 /* (BAUD_RATE_GEN_FREQ / baudrate) */ -#define CP2101_BITS 0x03 /* 0x(0)(databits)(parity)(stopbits) */ -#define CP2101_BREAK 0x05 /* On / Off */ -#define CP2101_CONTROL 0x07 /* Flow control line states */ -#define CP2101_MODEMCTL 0x13 /* Modem controls */ -#define CP2101_CONFIG_6 0x19 /* 6 bytes of config data ??? */ - -/* CP2101_UART */ -#define UART_ENABLE 0x0001 -#define UART_DISABLE 0x0000 - -/* CP2101_BAUDRATE */ -#define BAUD_RATE_GEN_FREQ 0x384000 - -/* CP2101_BITS */ -#define BITS_DATA_MASK 0X0f00 -#define BITS_DATA_5 0X0500 -#define BITS_DATA_6 0X0600 -#define BITS_DATA_7 0X0700 -#define BITS_DATA_8 0X0800 -#define BITS_DATA_9 0X0900 - -#define BITS_PARITY_MASK 0x00f0 -#define BITS_PARITY_NONE 0x0000 -#define BITS_PARITY_ODD 0x0010 -#define BITS_PARITY_EVEN 0x0020 -#define BITS_PARITY_MARK 0x0030 -#define BITS_PARITY_SPACE 0x0040 - -#define BITS_STOP_MASK 0x000f -#define BITS_STOP_1 0x0000 -#define BITS_STOP_1_5 0x0001 -#define BITS_STOP_2 0x0002 - -/* CP2101_BREAK */ -#define BREAK_ON 0x0000 -#define BREAK_OFF 0x0001 - -/* CP2101_CONTROL */ -#define CONTROL_DTR 0x0001 -#define CONTROL_RTS 0x0002 -#define CONTROL_CTS 0x0010 -#define CONTROL_DSR 0x0020 -#define CONTROL_RING 0x0040 -#define CONTROL_DCD 0x0080 -#define CONTROL_WRITE_DTR 0x0100 -#define CONTROL_WRITE_RTS 0x0200 - -/* - * cp2101_get_config - * Reads from the CP2101 configuration registers - * 'size' is specified in bytes. - * 'data' is a pointer to a pre-allocated array of integers large - * enough to hold 'size' bytes (with 4 bytes to each integer) - */ -static int cp2101_get_config(struct usb_serial_port *port, u8 request, - unsigned int *data, int size) -{ - struct usb_serial *serial = port->serial; - __le32 *buf; - int result, i, length; - - /* Number of integers required to contain the array */ - length = (((size - 1) | 3) + 1)/4; - - buf = kcalloc(length, sizeof(__le32), GFP_KERNEL); - if (!buf) { - dev_err(&port->dev, "%s - out of memory.\n", __func__); - return -ENOMEM; - } - - /* For get requests, the request number must be incremented */ - request++; - - /* Issue the request, attempting to read 'size' bytes */ - result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), - request, REQTYPE_DEVICE_TO_HOST, 0x0000, - 0, buf, size, 300); - - /* Convert data into an array of integers */ - for (i = 0; i < length; i++) - data[i] = le32_to_cpu(buf[i]); - - kfree(buf); - - if (result != size) { - dbg("%s - Unable to send config request, " - "request=0x%x size=%d result=%d\n", - __func__, request, size, result); - return -EPROTO; - } - - return 0; -} - -/* - * cp2101_set_config - * Writes to the CP2101 configuration registers - * Values less than 16 bits wide are sent directly - * 'size' is specified in bytes. - */ -static int cp2101_set_config(struct usb_serial_port *port, u8 request, - unsigned int *data, int size) -{ - struct usb_serial *serial = port->serial; - __le32 *buf; - int result, i, length; - - /* Number of integers required to contain the array */ - length = (((size - 1) | 3) + 1)/4; - - buf = kmalloc(length * sizeof(__le32), GFP_KERNEL); - if (!buf) { - dev_err(&port->dev, "%s - out of memory.\n", - __func__); - return -ENOMEM; - } - - /* Array of integers into bytes */ - for (i = 0; i < length; i++) - buf[i] = cpu_to_le32(data[i]); - - if (size > 2) { - result = usb_control_msg(serial->dev, - usb_sndctrlpipe(serial->dev, 0), - request, REQTYPE_HOST_TO_DEVICE, 0x0000, - 0, buf, size, 300); - } else { - result = usb_control_msg(serial->dev, - usb_sndctrlpipe(serial->dev, 0), - request, REQTYPE_HOST_TO_DEVICE, data[0], - 0, NULL, 0, 300); - } - - kfree(buf); - - if ((size > 2 && result != size) || result < 0) { - dbg("%s - Unable to send request, " - "request=0x%x size=%d result=%d\n", - __func__, request, size, result); - return -EPROTO; - } - - /* Single data value */ - result = usb_control_msg(serial->dev, - usb_sndctrlpipe(serial->dev, 0), - request, REQTYPE_HOST_TO_DEVICE, data[0], - 0, NULL, 0, 300); - return 0; -} - -/* - * cp2101_set_config_single - * Convenience function for calling cp2101_set_config on single data values - * without requiring an integer pointer - */ -static inline int cp2101_set_config_single(struct usb_serial_port *port, - u8 request, unsigned int data) -{ - return cp2101_set_config(port, request, &data, 2); -} - -/* - * cp2101_quantise_baudrate - * Quantises the baud rate as per AN205 Table 1 - */ -static unsigned int cp2101_quantise_baudrate(unsigned int baud) { - if (baud <= 56) baud = 0; - else if (baud <= 300) baud = 300; - else if (baud <= 600) baud = 600; - else if (baud <= 1200) baud = 1200; - else if (baud <= 1800) baud = 1800; - else if (baud <= 2400) baud = 2400; - else if (baud <= 4000) baud = 4000; - else if (baud <= 4803) baud = 4800; - else if (baud <= 7207) baud = 7200; - else if (baud <= 9612) baud = 9600; - else if (baud <= 14428) baud = 14400; - else if (baud <= 16062) baud = 16000; - else if (baud <= 19250) baud = 19200; - else if (baud <= 28912) baud = 28800; - else if (baud <= 38601) baud = 38400; - else if (baud <= 51558) baud = 51200; - else if (baud <= 56280) baud = 56000; - else if (baud <= 58053) baud = 57600; - else if (baud <= 64111) baud = 64000; - else if (baud <= 77608) baud = 76800; - else if (baud <= 117028) baud = 115200; - else if (baud <= 129347) baud = 128000; - else if (baud <= 156868) baud = 153600; - else if (baud <= 237832) baud = 230400; - else if (baud <= 254234) baud = 250000; - else if (baud <= 273066) baud = 256000; - else if (baud <= 491520) baud = 460800; - else if (baud <= 567138) baud = 500000; - else if (baud <= 670254) baud = 576000; - else if (baud <= 1053257) baud = 921600; - else if (baud <= 1474560) baud = 1228800; - else if (baud <= 2457600) baud = 1843200; - else baud = 3686400; - return baud; -} - -static int cp2101_open(struct tty_struct *tty, struct usb_serial_port *port, - struct file *filp) -{ - struct usb_serial *serial = port->serial; - int result; - - dbg("%s - port %d", __func__, port->number); - - if (cp2101_set_config_single(port, CP2101_UART, UART_ENABLE)) { - dev_err(&port->dev, "%s - Unable to enable UART\n", - __func__); - return -EPROTO; - } - - /* Start reading from the device */ - usb_fill_bulk_urb(port->read_urb, serial->dev, - usb_rcvbulkpipe(serial->dev, - port->bulk_in_endpointAddress), - port->read_urb->transfer_buffer, - port->read_urb->transfer_buffer_length, - serial->type->read_bulk_callback, - port); - result = usb_submit_urb(port->read_urb, GFP_KERNEL); - if (result) { - dev_err(&port->dev, "%s - failed resubmitting read urb, " - "error %d\n", __func__, result); - return result; - } - - /* Configure the termios structure */ - cp2101_get_termios(tty); - - /* Set the DTR and RTS pins low */ - cp2101_tiocmset(tty, NULL, TIOCM_DTR | TIOCM_RTS, 0); - - return 0; -} - -static void cp2101_cleanup(struct usb_serial_port *port) -{ - struct usb_serial *serial = port->serial; - - dbg("%s - port %d", __func__, port->number); - - if (serial->dev) { - /* shutdown any bulk reads that might be going on */ - if (serial->num_bulk_out) - usb_kill_urb(port->write_urb); - if (serial->num_bulk_in) - usb_kill_urb(port->read_urb); - } -} - -static void cp2101_close(struct tty_struct *tty, struct usb_serial_port *port, - struct file *filp) -{ - dbg("%s - port %d", __func__, port->number); - - /* shutdown our urbs */ - dbg("%s - shutting down urbs", __func__); - usb_kill_urb(port->write_urb); - usb_kill_urb(port->read_urb); - - mutex_lock(&port->serial->disc_mutex); - if (!port->serial->disconnected) - cp2101_set_config_single(port, CP2101_UART, UART_DISABLE); - mutex_unlock(&port->serial->disc_mutex); -} - -/* - * cp2101_get_termios - * Reads the baud rate, data bits, parity, stop bits and flow control mode - * from the device, corrects any unsupported values, and configures the - * termios structure to reflect the state of the device - */ -static void cp2101_get_termios (struct tty_struct *tty) -{ - struct usb_serial_port *port = tty->driver_data; - unsigned int cflag, modem_ctl[4]; - unsigned int baud; - unsigned int bits; - - dbg("%s - port %d", __func__, port->number); - - cp2101_get_config(port, CP2101_BAUDRATE, &baud, 2); - /* Convert to baudrate */ - if (baud) - baud = cp2101_quantise_baudrate((BAUD_RATE_GEN_FREQ + baud/2)/ baud); - - dbg("%s - baud rate = %d", __func__, baud); - - tty_encode_baud_rate(tty, baud, baud); - cflag = tty->termios->c_cflag; - - cp2101_get_config(port, CP2101_BITS, &bits, 2); - cflag &= ~CSIZE; - switch (bits & BITS_DATA_MASK) { - case BITS_DATA_5: - dbg("%s - data bits = 5", __func__); - cflag |= CS5; - break; - case BITS_DATA_6: - dbg("%s - data bits = 6", __func__); - cflag |= CS6; - break; - case BITS_DATA_7: - dbg("%s - data bits = 7", __func__); - cflag |= CS7; - break; - case BITS_DATA_8: - dbg("%s - data bits = 8", __func__); - cflag |= CS8; - break; - case BITS_DATA_9: - dbg("%s - data bits = 9 (not supported, using 8 data bits)", - __func__); - cflag |= CS8; - bits &= ~BITS_DATA_MASK; - bits |= BITS_DATA_8; - cp2101_set_config(port, CP2101_BITS, &bits, 2); - break; - default: - dbg("%s - Unknown number of data bits, using 8", __func__); - cflag |= CS8; - bits &= ~BITS_DATA_MASK; - bits |= BITS_DATA_8; - cp2101_set_config(port, CP2101_BITS, &bits, 2); - break; - } - - switch (bits & BITS_PARITY_MASK) { - case BITS_PARITY_NONE: - dbg("%s - parity = NONE", __func__); - cflag &= ~PARENB; - break; - case BITS_PARITY_ODD: - dbg("%s - parity = ODD", __func__); - cflag |= (PARENB|PARODD); - break; - case BITS_PARITY_EVEN: - dbg("%s - parity = EVEN", __func__); - cflag &= ~PARODD; - cflag |= PARENB; - break; - case BITS_PARITY_MARK: - dbg("%s - parity = MARK (not supported, disabling parity)", - __func__); - cflag &= ~PARENB; - bits &= ~BITS_PARITY_MASK; - cp2101_set_config(port, CP2101_BITS, &bits, 2); - break; - case BITS_PARITY_SPACE: - dbg("%s - parity = SPACE (not supported, disabling parity)", - __func__); - cflag &= ~PARENB; - bits &= ~BITS_PARITY_MASK; - cp2101_set_config(port, CP2101_BITS, &bits, 2); - break; - default: - dbg("%s - Unknown parity mode, disabling parity", __func__); - cflag &= ~PARENB; - bits &= ~BITS_PARITY_MASK; - cp2101_set_config(port, CP2101_BITS, &bits, 2); - break; - } - - cflag &= ~CSTOPB; - switch (bits & BITS_STOP_MASK) { - case BITS_STOP_1: - dbg("%s - stop bits = 1", __func__); - break; - case BITS_STOP_1_5: - dbg("%s - stop bits = 1.5 (not supported, using 1 stop bit)", - __func__); - bits &= ~BITS_STOP_MASK; - cp2101_set_config(port, CP2101_BITS, &bits, 2); - break; - case BITS_STOP_2: - dbg("%s - stop bits = 2", __func__); - cflag |= CSTOPB; - break; - default: - dbg("%s - Unknown number of stop bits, using 1 stop bit", - __func__); - bits &= ~BITS_STOP_MASK; - cp2101_set_config(port, CP2101_BITS, &bits, 2); - break; - } - - cp2101_get_config(port, CP2101_MODEMCTL, modem_ctl, 16); - if (modem_ctl[0] & 0x0008) { - dbg("%s - flow control = CRTSCTS", __func__); - cflag |= CRTSCTS; - } else { - dbg("%s - flow control = NONE", __func__); - cflag &= ~CRTSCTS; - } - - tty->termios->c_cflag = cflag; -} - -static void cp2101_set_termios(struct tty_struct *tty, - struct usb_serial_port *port, struct ktermios *old_termios) -{ - unsigned int cflag, old_cflag; - unsigned int baud = 0, bits; - unsigned int modem_ctl[4]; - - dbg("%s - port %d", __func__, port->number); - - if (!tty) - return; - - tty->termios->c_cflag &= ~CMSPAR; - cflag = tty->termios->c_cflag; - old_cflag = old_termios->c_cflag; - baud = cp2101_quantise_baudrate(tty_get_baud_rate(tty)); - - /* If the baud rate is to be updated*/ - if (baud != tty_termios_baud_rate(old_termios) && baud != 0) { - dbg("%s - Setting baud rate to %d baud", __func__, - baud); - if (cp2101_set_config_single(port, CP2101_BAUDRATE, - ((BAUD_RATE_GEN_FREQ + baud/2) / baud))) { - dbg("Baud rate requested not supported by device\n"); - baud = tty_termios_baud_rate(old_termios); - } - } - /* Report back the resulting baud rate */ - tty_encode_baud_rate(tty, baud, baud); - - /* If the number of data bits is to be updated */ - if ((cflag & CSIZE) != (old_cflag & CSIZE)) { - cp2101_get_config(port, CP2101_BITS, &bits, 2); - bits &= ~BITS_DATA_MASK; - switch (cflag & CSIZE) { - case CS5: - bits |= BITS_DATA_5; - dbg("%s - data bits = 5", __func__); - break; - case CS6: - bits |= BITS_DATA_6; - dbg("%s - data bits = 6", __func__); - break; - case CS7: - bits |= BITS_DATA_7; - dbg("%s - data bits = 7", __func__); - break; - case CS8: - bits |= BITS_DATA_8; - dbg("%s - data bits = 8", __func__); - break; - /*case CS9: - bits |= BITS_DATA_9; - dbg("%s - data bits = 9", __func__); - break;*/ - default: - dbg("cp2101 driver does not " - "support the number of bits requested," - " using 8 bit mode\n"); - bits |= BITS_DATA_8; - break; - } - if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) - dbg("Number of data bits requested " - "not supported by device\n"); - } - - if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))) { - cp2101_get_config(port, CP2101_BITS, &bits, 2); - bits &= ~BITS_PARITY_MASK; - if (cflag & PARENB) { - if (cflag & PARODD) { - bits |= BITS_PARITY_ODD; - dbg("%s - parity = ODD", __func__); - } else { - bits |= BITS_PARITY_EVEN; - dbg("%s - parity = EVEN", __func__); - } - } - if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) - dbg("Parity mode not supported " - "by device\n"); - } - - if ((cflag & CSTOPB) != (old_cflag & CSTOPB)) { - cp2101_get_config(port, CP2101_BITS, &bits, 2); - bits &= ~BITS_STOP_MASK; - if (cflag & CSTOPB) { - bits |= BITS_STOP_2; - dbg("%s - stop bits = 2", __func__); - } else { - bits |= BITS_STOP_1; - dbg("%s - stop bits = 1", __func__); - } - if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) - dbg("Number of stop bits requested " - "not supported by device\n"); - } - - if ((cflag & CRTSCTS) != (old_cflag & CRTSCTS)) { - cp2101_get_config(port, CP2101_MODEMCTL, modem_ctl, 16); - dbg("%s - read modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x", - __func__, modem_ctl[0], modem_ctl[1], - modem_ctl[2], modem_ctl[3]); - - if (cflag & CRTSCTS) { - modem_ctl[0] &= ~0x7B; - modem_ctl[0] |= 0x09; - modem_ctl[1] = 0x80; - dbg("%s - flow control = CRTSCTS", __func__); - } else { - modem_ctl[0] &= ~0x7B; - modem_ctl[0] |= 0x01; - modem_ctl[1] |= 0x40; - dbg("%s - flow control = NONE", __func__); - } - - dbg("%s - write modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x", - __func__, modem_ctl[0], modem_ctl[1], - modem_ctl[2], modem_ctl[3]); - cp2101_set_config(port, CP2101_MODEMCTL, modem_ctl, 16); - } - -} - -static int cp2101_tiocmset (struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear) -{ - struct usb_serial_port *port = tty->driver_data; - unsigned int control = 0; - - dbg("%s - port %d", __func__, port->number); - - if (set & TIOCM_RTS) { - control |= CONTROL_RTS; - control |= CONTROL_WRITE_RTS; - } - if (set & TIOCM_DTR) { - control |= CONTROL_DTR; - control |= CONTROL_WRITE_DTR; - } - if (clear & TIOCM_RTS) { - control &= ~CONTROL_RTS; - control |= CONTROL_WRITE_RTS; - } - if (clear & TIOCM_DTR) { - control &= ~CONTROL_DTR; - control |= CONTROL_WRITE_DTR; - } - - dbg("%s - control = 0x%.4x", __func__, control); - - return cp2101_set_config(port, CP2101_CONTROL, &control, 2); - -} - -static int cp2101_tiocmget (struct tty_struct *tty, struct file *file) -{ - struct usb_serial_port *port = tty->driver_data; - unsigned int control; - int result; - - dbg("%s - port %d", __func__, port->number); - - cp2101_get_config(port, CP2101_CONTROL, &control, 1); - - result = ((control & CONTROL_DTR) ? TIOCM_DTR : 0) - |((control & CONTROL_RTS) ? TIOCM_RTS : 0) - |((control & CONTROL_CTS) ? TIOCM_CTS : 0) - |((control & CONTROL_DSR) ? TIOCM_DSR : 0) - |((control & CONTROL_RING)? TIOCM_RI : 0) - |((control & CONTROL_DCD) ? TIOCM_CD : 0); - - dbg("%s - control = 0x%.2x", __func__, control); - - return result; -} - -static void cp2101_break_ctl (struct tty_struct *tty, int break_state) -{ - struct usb_serial_port *port = tty->driver_data; - unsigned int state; - - dbg("%s - port %d", __func__, port->number); - if (break_state == 0) - state = BREAK_OFF; - else - state = BREAK_ON; - dbg("%s - turning break %s", __func__, - state == BREAK_OFF ? "off" : "on"); - cp2101_set_config(port, CP2101_BREAK, &state, 2); -} - -static int cp2101_startup(struct usb_serial *serial) -{ - /* CP2101 buffers behave strangely unless device is reset */ - usb_reset_device(serial->dev); - return 0; -} - -static void cp2101_shutdown(struct usb_serial *serial) -{ - int i; - - dbg("%s", __func__); - - /* Stop reads and writes on all ports */ - for (i = 0; i < serial->num_ports; ++i) - cp2101_cleanup(serial->port[i]); -} - -static int __init cp2101_init(void) -{ - int retval; - - retval = usb_serial_register(&cp2101_device); - if (retval) - return retval; /* Failed to register */ - - retval = usb_register(&cp2101_driver); - if (retval) { - /* Failed to register */ - usb_serial_deregister(&cp2101_device); - return retval; - } - - /* Success */ - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; -} - -static void __exit cp2101_exit(void) -{ - usb_deregister(&cp2101_driver); - usb_serial_deregister(&cp2101_device); -} - -module_init(cp2101_init); -module_exit(cp2101_exit); - -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_VERSION(DRIVER_VERSION); -MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Enable verbose debugging messages"); diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c new file mode 100644 index 000000000000..2f23d0643624 --- /dev/null +++ b/drivers/usb/serial/cp210x.c @@ -0,0 +1,788 @@ +/* + * Silicon Laboratories CP2101/CP2102 USB to RS232 serial adaptor driver + * + * Copyright (C) 2005 Craig Shelley (craig@microtron.org.uk) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * Support to set flow control line levels using TIOCMGET and TIOCMSET + * thanks to Karl Hiramoto karl@hiramoto.org. RTSCTS hardware flow + * control thanks to Munir Nassar nassarmu@real-time.com + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Version Information + */ +#define DRIVER_VERSION "v0.08" +#define DRIVER_DESC "Silicon Labs CP2101/CP2102 RS232 serial adaptor driver" + +/* + * Function Prototypes + */ +static int cp2101_open(struct tty_struct *, struct usb_serial_port *, + struct file *); +static void cp2101_cleanup(struct usb_serial_port *); +static void cp2101_close(struct tty_struct *, struct usb_serial_port *, + struct file*); +static void cp2101_get_termios(struct tty_struct *); +static void cp2101_set_termios(struct tty_struct *, struct usb_serial_port *, + struct ktermios*); +static int cp2101_tiocmget(struct tty_struct *, struct file *); +static int cp2101_tiocmset(struct tty_struct *, struct file *, + unsigned int, unsigned int); +static void cp2101_break_ctl(struct tty_struct *, int); +static int cp2101_startup(struct usb_serial *); +static void cp2101_shutdown(struct usb_serial *); + + +static int debug; + +static struct usb_device_id id_table [] = { + { USB_DEVICE(0x0471, 0x066A) }, /* AKTAKOM ACE-1001 cable */ + { USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */ + { USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */ + { USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */ + { USB_DEVICE(0x0FCF, 0x1004) }, /* Dynastream ANT2USB */ + { USB_DEVICE(0x0FCF, 0x1006) }, /* Dynastream ANT development board */ + { USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */ + { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */ + { USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */ + { USB_DEVICE(0x10C4, 0x800A) }, /* SPORTident BSM7-D-USB main station */ + { USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */ + { USB_DEVICE(0x10C4, 0x8053) }, /* Enfora EDG1228 */ + { USB_DEVICE(0x10C4, 0x8054) }, /* Enfora GSM2228 */ + { USB_DEVICE(0x10C4, 0x8066) }, /* Argussoft In-System Programmer */ + { USB_DEVICE(0x10C4, 0x807A) }, /* Crumb128 board */ + { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */ + { USB_DEVICE(0x10C4, 0x80DD) }, /* Tracient RFID */ + { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */ + { USB_DEVICE(0x10C4, 0x8115) }, /* Arygon NFC/Mifare Reader */ + { USB_DEVICE(0x10C4, 0x813D) }, /* Burnside Telecom Deskmobile */ + { USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */ + { USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */ + { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */ + { USB_DEVICE(0x10C4, 0x819F) }, /* MJS USB Toslink Switcher */ + { USB_DEVICE(0x10C4, 0x81A6) }, /* ThinkOptics WavIt */ + { USB_DEVICE(0x10C4, 0x81AC) }, /* MSD Dash Hawk */ + { USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */ + { USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */ + { USB_DEVICE(0x10C4, 0x81E7) }, /* Aerocomm Radio */ + { USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */ + { USB_DEVICE(0x10C4, 0x822B) }, /* Modem EDGE(GSM) Comander 2 */ + { USB_DEVICE(0x10C4, 0x826B) }, /* Cygnal Integrated Products, Inc., Fasttrax GPS demostration module */ + { USB_DEVICE(0x10c4, 0x8293) }, /* Telegesys ETRX2USB */ + { USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */ + { USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */ + { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ + { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ + { USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */ + { USB_DEVICE(0x10C4, 0xF002) }, /* Elan Digital Systems USBwave12 */ + { USB_DEVICE(0x10C4, 0xF003) }, /* Elan Digital Systems USBpulse100 */ + { USB_DEVICE(0x10C4, 0xF004) }, /* Elan Digital Systems USBcount50 */ + { USB_DEVICE(0x10C5, 0xEA61) }, /* Silicon Labs MobiData GPRS USB Modem */ + { USB_DEVICE(0x13AD, 0x9999) }, /* Baltech card reader */ + { USB_DEVICE(0x166A, 0x0303) }, /* Clipsal 5500PCU C-Bus USB interface */ + { USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */ + { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ + { } /* Terminating Entry */ +}; + +MODULE_DEVICE_TABLE(usb, id_table); + +static struct usb_driver cp2101_driver = { + .name = "cp2101", + .probe = usb_serial_probe, + .disconnect = usb_serial_disconnect, + .id_table = id_table, + .no_dynamic_id = 1, +}; + +static struct usb_serial_driver cp2101_device = { + .driver = { + .owner = THIS_MODULE, + .name = "cp2101", + }, + .usb_driver = &cp2101_driver, + .id_table = id_table, + .num_ports = 1, + .open = cp2101_open, + .close = cp2101_close, + .break_ctl = cp2101_break_ctl, + .set_termios = cp2101_set_termios, + .tiocmget = cp2101_tiocmget, + .tiocmset = cp2101_tiocmset, + .attach = cp2101_startup, + .shutdown = cp2101_shutdown, +}; + +/* Config request types */ +#define REQTYPE_HOST_TO_DEVICE 0x41 +#define REQTYPE_DEVICE_TO_HOST 0xc1 + +/* Config SET requests. To GET, add 1 to the request number */ +#define CP2101_UART 0x00 /* Enable / Disable */ +#define CP2101_BAUDRATE 0x01 /* (BAUD_RATE_GEN_FREQ / baudrate) */ +#define CP2101_BITS 0x03 /* 0x(0)(databits)(parity)(stopbits) */ +#define CP2101_BREAK 0x05 /* On / Off */ +#define CP2101_CONTROL 0x07 /* Flow control line states */ +#define CP2101_MODEMCTL 0x13 /* Modem controls */ +#define CP2101_CONFIG_6 0x19 /* 6 bytes of config data ??? */ + +/* CP2101_UART */ +#define UART_ENABLE 0x0001 +#define UART_DISABLE 0x0000 + +/* CP2101_BAUDRATE */ +#define BAUD_RATE_GEN_FREQ 0x384000 + +/* CP2101_BITS */ +#define BITS_DATA_MASK 0X0f00 +#define BITS_DATA_5 0X0500 +#define BITS_DATA_6 0X0600 +#define BITS_DATA_7 0X0700 +#define BITS_DATA_8 0X0800 +#define BITS_DATA_9 0X0900 + +#define BITS_PARITY_MASK 0x00f0 +#define BITS_PARITY_NONE 0x0000 +#define BITS_PARITY_ODD 0x0010 +#define BITS_PARITY_EVEN 0x0020 +#define BITS_PARITY_MARK 0x0030 +#define BITS_PARITY_SPACE 0x0040 + +#define BITS_STOP_MASK 0x000f +#define BITS_STOP_1 0x0000 +#define BITS_STOP_1_5 0x0001 +#define BITS_STOP_2 0x0002 + +/* CP2101_BREAK */ +#define BREAK_ON 0x0000 +#define BREAK_OFF 0x0001 + +/* CP2101_CONTROL */ +#define CONTROL_DTR 0x0001 +#define CONTROL_RTS 0x0002 +#define CONTROL_CTS 0x0010 +#define CONTROL_DSR 0x0020 +#define CONTROL_RING 0x0040 +#define CONTROL_DCD 0x0080 +#define CONTROL_WRITE_DTR 0x0100 +#define CONTROL_WRITE_RTS 0x0200 + +/* + * cp2101_get_config + * Reads from the CP2101 configuration registers + * 'size' is specified in bytes. + * 'data' is a pointer to a pre-allocated array of integers large + * enough to hold 'size' bytes (with 4 bytes to each integer) + */ +static int cp2101_get_config(struct usb_serial_port *port, u8 request, + unsigned int *data, int size) +{ + struct usb_serial *serial = port->serial; + __le32 *buf; + int result, i, length; + + /* Number of integers required to contain the array */ + length = (((size - 1) | 3) + 1)/4; + + buf = kcalloc(length, sizeof(__le32), GFP_KERNEL); + if (!buf) { + dev_err(&port->dev, "%s - out of memory.\n", __func__); + return -ENOMEM; + } + + /* For get requests, the request number must be incremented */ + request++; + + /* Issue the request, attempting to read 'size' bytes */ + result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), + request, REQTYPE_DEVICE_TO_HOST, 0x0000, + 0, buf, size, 300); + + /* Convert data into an array of integers */ + for (i = 0; i < length; i++) + data[i] = le32_to_cpu(buf[i]); + + kfree(buf); + + if (result != size) { + dbg("%s - Unable to send config request, " + "request=0x%x size=%d result=%d\n", + __func__, request, size, result); + return -EPROTO; + } + + return 0; +} + +/* + * cp2101_set_config + * Writes to the CP2101 configuration registers + * Values less than 16 bits wide are sent directly + * 'size' is specified in bytes. + */ +static int cp2101_set_config(struct usb_serial_port *port, u8 request, + unsigned int *data, int size) +{ + struct usb_serial *serial = port->serial; + __le32 *buf; + int result, i, length; + + /* Number of integers required to contain the array */ + length = (((size - 1) | 3) + 1)/4; + + buf = kmalloc(length * sizeof(__le32), GFP_KERNEL); + if (!buf) { + dev_err(&port->dev, "%s - out of memory.\n", + __func__); + return -ENOMEM; + } + + /* Array of integers into bytes */ + for (i = 0; i < length; i++) + buf[i] = cpu_to_le32(data[i]); + + if (size > 2) { + result = usb_control_msg(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + request, REQTYPE_HOST_TO_DEVICE, 0x0000, + 0, buf, size, 300); + } else { + result = usb_control_msg(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + request, REQTYPE_HOST_TO_DEVICE, data[0], + 0, NULL, 0, 300); + } + + kfree(buf); + + if ((size > 2 && result != size) || result < 0) { + dbg("%s - Unable to send request, " + "request=0x%x size=%d result=%d\n", + __func__, request, size, result); + return -EPROTO; + } + + /* Single data value */ + result = usb_control_msg(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + request, REQTYPE_HOST_TO_DEVICE, data[0], + 0, NULL, 0, 300); + return 0; +} + +/* + * cp2101_set_config_single + * Convenience function for calling cp2101_set_config on single data values + * without requiring an integer pointer + */ +static inline int cp2101_set_config_single(struct usb_serial_port *port, + u8 request, unsigned int data) +{ + return cp2101_set_config(port, request, &data, 2); +} + +/* + * cp2101_quantise_baudrate + * Quantises the baud rate as per AN205 Table 1 + */ +static unsigned int cp2101_quantise_baudrate(unsigned int baud) { + if (baud <= 56) baud = 0; + else if (baud <= 300) baud = 300; + else if (baud <= 600) baud = 600; + else if (baud <= 1200) baud = 1200; + else if (baud <= 1800) baud = 1800; + else if (baud <= 2400) baud = 2400; + else if (baud <= 4000) baud = 4000; + else if (baud <= 4803) baud = 4800; + else if (baud <= 7207) baud = 7200; + else if (baud <= 9612) baud = 9600; + else if (baud <= 14428) baud = 14400; + else if (baud <= 16062) baud = 16000; + else if (baud <= 19250) baud = 19200; + else if (baud <= 28912) baud = 28800; + else if (baud <= 38601) baud = 38400; + else if (baud <= 51558) baud = 51200; + else if (baud <= 56280) baud = 56000; + else if (baud <= 58053) baud = 57600; + else if (baud <= 64111) baud = 64000; + else if (baud <= 77608) baud = 76800; + else if (baud <= 117028) baud = 115200; + else if (baud <= 129347) baud = 128000; + else if (baud <= 156868) baud = 153600; + else if (baud <= 237832) baud = 230400; + else if (baud <= 254234) baud = 250000; + else if (baud <= 273066) baud = 256000; + else if (baud <= 491520) baud = 460800; + else if (baud <= 567138) baud = 500000; + else if (baud <= 670254) baud = 576000; + else if (baud <= 1053257) baud = 921600; + else if (baud <= 1474560) baud = 1228800; + else if (baud <= 2457600) baud = 1843200; + else baud = 3686400; + return baud; +} + +static int cp2101_open(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp) +{ + struct usb_serial *serial = port->serial; + int result; + + dbg("%s - port %d", __func__, port->number); + + if (cp2101_set_config_single(port, CP2101_UART, UART_ENABLE)) { + dev_err(&port->dev, "%s - Unable to enable UART\n", + __func__); + return -EPROTO; + } + + /* Start reading from the device */ + usb_fill_bulk_urb(port->read_urb, serial->dev, + usb_rcvbulkpipe(serial->dev, + port->bulk_in_endpointAddress), + port->read_urb->transfer_buffer, + port->read_urb->transfer_buffer_length, + serial->type->read_bulk_callback, + port); + result = usb_submit_urb(port->read_urb, GFP_KERNEL); + if (result) { + dev_err(&port->dev, "%s - failed resubmitting read urb, " + "error %d\n", __func__, result); + return result; + } + + /* Configure the termios structure */ + cp2101_get_termios(tty); + + /* Set the DTR and RTS pins low */ + cp2101_tiocmset(tty, NULL, TIOCM_DTR | TIOCM_RTS, 0); + + return 0; +} + +static void cp2101_cleanup(struct usb_serial_port *port) +{ + struct usb_serial *serial = port->serial; + + dbg("%s - port %d", __func__, port->number); + + if (serial->dev) { + /* shutdown any bulk reads that might be going on */ + if (serial->num_bulk_out) + usb_kill_urb(port->write_urb); + if (serial->num_bulk_in) + usb_kill_urb(port->read_urb); + } +} + +static void cp2101_close(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp) +{ + dbg("%s - port %d", __func__, port->number); + + /* shutdown our urbs */ + dbg("%s - shutting down urbs", __func__); + usb_kill_urb(port->write_urb); + usb_kill_urb(port->read_urb); + + mutex_lock(&port->serial->disc_mutex); + if (!port->serial->disconnected) + cp2101_set_config_single(port, CP2101_UART, UART_DISABLE); + mutex_unlock(&port->serial->disc_mutex); +} + +/* + * cp2101_get_termios + * Reads the baud rate, data bits, parity, stop bits and flow control mode + * from the device, corrects any unsupported values, and configures the + * termios structure to reflect the state of the device + */ +static void cp2101_get_termios (struct tty_struct *tty) +{ + struct usb_serial_port *port = tty->driver_data; + unsigned int cflag, modem_ctl[4]; + unsigned int baud; + unsigned int bits; + + dbg("%s - port %d", __func__, port->number); + + cp2101_get_config(port, CP2101_BAUDRATE, &baud, 2); + /* Convert to baudrate */ + if (baud) + baud = cp2101_quantise_baudrate((BAUD_RATE_GEN_FREQ + baud/2)/ baud); + + dbg("%s - baud rate = %d", __func__, baud); + + tty_encode_baud_rate(tty, baud, baud); + cflag = tty->termios->c_cflag; + + cp2101_get_config(port, CP2101_BITS, &bits, 2); + cflag &= ~CSIZE; + switch (bits & BITS_DATA_MASK) { + case BITS_DATA_5: + dbg("%s - data bits = 5", __func__); + cflag |= CS5; + break; + case BITS_DATA_6: + dbg("%s - data bits = 6", __func__); + cflag |= CS6; + break; + case BITS_DATA_7: + dbg("%s - data bits = 7", __func__); + cflag |= CS7; + break; + case BITS_DATA_8: + dbg("%s - data bits = 8", __func__); + cflag |= CS8; + break; + case BITS_DATA_9: + dbg("%s - data bits = 9 (not supported, using 8 data bits)", + __func__); + cflag |= CS8; + bits &= ~BITS_DATA_MASK; + bits |= BITS_DATA_8; + cp2101_set_config(port, CP2101_BITS, &bits, 2); + break; + default: + dbg("%s - Unknown number of data bits, using 8", __func__); + cflag |= CS8; + bits &= ~BITS_DATA_MASK; + bits |= BITS_DATA_8; + cp2101_set_config(port, CP2101_BITS, &bits, 2); + break; + } + + switch (bits & BITS_PARITY_MASK) { + case BITS_PARITY_NONE: + dbg("%s - parity = NONE", __func__); + cflag &= ~PARENB; + break; + case BITS_PARITY_ODD: + dbg("%s - parity = ODD", __func__); + cflag |= (PARENB|PARODD); + break; + case BITS_PARITY_EVEN: + dbg("%s - parity = EVEN", __func__); + cflag &= ~PARODD; + cflag |= PARENB; + break; + case BITS_PARITY_MARK: + dbg("%s - parity = MARK (not supported, disabling parity)", + __func__); + cflag &= ~PARENB; + bits &= ~BITS_PARITY_MASK; + cp2101_set_config(port, CP2101_BITS, &bits, 2); + break; + case BITS_PARITY_SPACE: + dbg("%s - parity = SPACE (not supported, disabling parity)", + __func__); + cflag &= ~PARENB; + bits &= ~BITS_PARITY_MASK; + cp2101_set_config(port, CP2101_BITS, &bits, 2); + break; + default: + dbg("%s - Unknown parity mode, disabling parity", __func__); + cflag &= ~PARENB; + bits &= ~BITS_PARITY_MASK; + cp2101_set_config(port, CP2101_BITS, &bits, 2); + break; + } + + cflag &= ~CSTOPB; + switch (bits & BITS_STOP_MASK) { + case BITS_STOP_1: + dbg("%s - stop bits = 1", __func__); + break; + case BITS_STOP_1_5: + dbg("%s - stop bits = 1.5 (not supported, using 1 stop bit)", + __func__); + bits &= ~BITS_STOP_MASK; + cp2101_set_config(port, CP2101_BITS, &bits, 2); + break; + case BITS_STOP_2: + dbg("%s - stop bits = 2", __func__); + cflag |= CSTOPB; + break; + default: + dbg("%s - Unknown number of stop bits, using 1 stop bit", + __func__); + bits &= ~BITS_STOP_MASK; + cp2101_set_config(port, CP2101_BITS, &bits, 2); + break; + } + + cp2101_get_config(port, CP2101_MODEMCTL, modem_ctl, 16); + if (modem_ctl[0] & 0x0008) { + dbg("%s - flow control = CRTSCTS", __func__); + cflag |= CRTSCTS; + } else { + dbg("%s - flow control = NONE", __func__); + cflag &= ~CRTSCTS; + } + + tty->termios->c_cflag = cflag; +} + +static void cp2101_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) +{ + unsigned int cflag, old_cflag; + unsigned int baud = 0, bits; + unsigned int modem_ctl[4]; + + dbg("%s - port %d", __func__, port->number); + + if (!tty) + return; + + tty->termios->c_cflag &= ~CMSPAR; + cflag = tty->termios->c_cflag; + old_cflag = old_termios->c_cflag; + baud = cp2101_quantise_baudrate(tty_get_baud_rate(tty)); + + /* If the baud rate is to be updated*/ + if (baud != tty_termios_baud_rate(old_termios) && baud != 0) { + dbg("%s - Setting baud rate to %d baud", __func__, + baud); + if (cp2101_set_config_single(port, CP2101_BAUDRATE, + ((BAUD_RATE_GEN_FREQ + baud/2) / baud))) { + dbg("Baud rate requested not supported by device\n"); + baud = tty_termios_baud_rate(old_termios); + } + } + /* Report back the resulting baud rate */ + tty_encode_baud_rate(tty, baud, baud); + + /* If the number of data bits is to be updated */ + if ((cflag & CSIZE) != (old_cflag & CSIZE)) { + cp2101_get_config(port, CP2101_BITS, &bits, 2); + bits &= ~BITS_DATA_MASK; + switch (cflag & CSIZE) { + case CS5: + bits |= BITS_DATA_5; + dbg("%s - data bits = 5", __func__); + break; + case CS6: + bits |= BITS_DATA_6; + dbg("%s - data bits = 6", __func__); + break; + case CS7: + bits |= BITS_DATA_7; + dbg("%s - data bits = 7", __func__); + break; + case CS8: + bits |= BITS_DATA_8; + dbg("%s - data bits = 8", __func__); + break; + /*case CS9: + bits |= BITS_DATA_9; + dbg("%s - data bits = 9", __func__); + break;*/ + default: + dbg("cp2101 driver does not " + "support the number of bits requested," + " using 8 bit mode\n"); + bits |= BITS_DATA_8; + break; + } + if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) + dbg("Number of data bits requested " + "not supported by device\n"); + } + + if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))) { + cp2101_get_config(port, CP2101_BITS, &bits, 2); + bits &= ~BITS_PARITY_MASK; + if (cflag & PARENB) { + if (cflag & PARODD) { + bits |= BITS_PARITY_ODD; + dbg("%s - parity = ODD", __func__); + } else { + bits |= BITS_PARITY_EVEN; + dbg("%s - parity = EVEN", __func__); + } + } + if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) + dbg("Parity mode not supported " + "by device\n"); + } + + if ((cflag & CSTOPB) != (old_cflag & CSTOPB)) { + cp2101_get_config(port, CP2101_BITS, &bits, 2); + bits &= ~BITS_STOP_MASK; + if (cflag & CSTOPB) { + bits |= BITS_STOP_2; + dbg("%s - stop bits = 2", __func__); + } else { + bits |= BITS_STOP_1; + dbg("%s - stop bits = 1", __func__); + } + if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) + dbg("Number of stop bits requested " + "not supported by device\n"); + } + + if ((cflag & CRTSCTS) != (old_cflag & CRTSCTS)) { + cp2101_get_config(port, CP2101_MODEMCTL, modem_ctl, 16); + dbg("%s - read modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x", + __func__, modem_ctl[0], modem_ctl[1], + modem_ctl[2], modem_ctl[3]); + + if (cflag & CRTSCTS) { + modem_ctl[0] &= ~0x7B; + modem_ctl[0] |= 0x09; + modem_ctl[1] = 0x80; + dbg("%s - flow control = CRTSCTS", __func__); + } else { + modem_ctl[0] &= ~0x7B; + modem_ctl[0] |= 0x01; + modem_ctl[1] |= 0x40; + dbg("%s - flow control = NONE", __func__); + } + + dbg("%s - write modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x", + __func__, modem_ctl[0], modem_ctl[1], + modem_ctl[2], modem_ctl[3]); + cp2101_set_config(port, CP2101_MODEMCTL, modem_ctl, 16); + } + +} + +static int cp2101_tiocmset (struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) +{ + struct usb_serial_port *port = tty->driver_data; + unsigned int control = 0; + + dbg("%s - port %d", __func__, port->number); + + if (set & TIOCM_RTS) { + control |= CONTROL_RTS; + control |= CONTROL_WRITE_RTS; + } + if (set & TIOCM_DTR) { + control |= CONTROL_DTR; + control |= CONTROL_WRITE_DTR; + } + if (clear & TIOCM_RTS) { + control &= ~CONTROL_RTS; + control |= CONTROL_WRITE_RTS; + } + if (clear & TIOCM_DTR) { + control &= ~CONTROL_DTR; + control |= CONTROL_WRITE_DTR; + } + + dbg("%s - control = 0x%.4x", __func__, control); + + return cp2101_set_config(port, CP2101_CONTROL, &control, 2); + +} + +static int cp2101_tiocmget (struct tty_struct *tty, struct file *file) +{ + struct usb_serial_port *port = tty->driver_data; + unsigned int control; + int result; + + dbg("%s - port %d", __func__, port->number); + + cp2101_get_config(port, CP2101_CONTROL, &control, 1); + + result = ((control & CONTROL_DTR) ? TIOCM_DTR : 0) + |((control & CONTROL_RTS) ? TIOCM_RTS : 0) + |((control & CONTROL_CTS) ? TIOCM_CTS : 0) + |((control & CONTROL_DSR) ? TIOCM_DSR : 0) + |((control & CONTROL_RING)? TIOCM_RI : 0) + |((control & CONTROL_DCD) ? TIOCM_CD : 0); + + dbg("%s - control = 0x%.2x", __func__, control); + + return result; +} + +static void cp2101_break_ctl (struct tty_struct *tty, int break_state) +{ + struct usb_serial_port *port = tty->driver_data; + unsigned int state; + + dbg("%s - port %d", __func__, port->number); + if (break_state == 0) + state = BREAK_OFF; + else + state = BREAK_ON; + dbg("%s - turning break %s", __func__, + state == BREAK_OFF ? "off" : "on"); + cp2101_set_config(port, CP2101_BREAK, &state, 2); +} + +static int cp2101_startup(struct usb_serial *serial) +{ + /* CP2101 buffers behave strangely unless device is reset */ + usb_reset_device(serial->dev); + return 0; +} + +static void cp2101_shutdown(struct usb_serial *serial) +{ + int i; + + dbg("%s", __func__); + + /* Stop reads and writes on all ports */ + for (i = 0; i < serial->num_ports; ++i) + cp2101_cleanup(serial->port[i]); +} + +static int __init cp2101_init(void) +{ + int retval; + + retval = usb_serial_register(&cp2101_device); + if (retval) + return retval; /* Failed to register */ + + retval = usb_register(&cp2101_driver); + if (retval) { + /* Failed to register */ + usb_serial_deregister(&cp2101_device); + return retval; + } + + /* Success */ + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); + return 0; +} + +static void __exit cp2101_exit(void) +{ + usb_deregister(&cp2101_driver); + usb_serial_deregister(&cp2101_device); +} + +module_init(cp2101_init); +module_exit(cp2101_exit); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_VERSION(DRIVER_VERSION); +MODULE_LICENSE("GPL"); + +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Enable verbose debugging messages"); -- cgit v1.2.3 From f6727d3b697f8ee2b628473ae6132d63b356e78c Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 26 Feb 2009 23:02:19 +0000 Subject: USB: ohci-s3c2410: remove include Remove the include of , as no definitions from it are used by the OHCI driver. Signed-off-by: Ben Dooks Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-s3c2410.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index f46af7a718d4..0e62d2044f7e 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c @@ -22,7 +22,6 @@ #include #include -#include #include #define valid_port(idx) ((idx) == 1 || (idx) == 2) -- cgit v1.2.3 From 6919d9d315c918000e310ab1fb43431a3ce78781 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 26 Feb 2009 23:03:15 +0000 Subject: USB: ohci-s3c2410: fix name of bus clock The USB bus clock is usb-bus-host, so print the correct name in the dev_err() statement if we cannot find it. Signed-off-by: Ben Dooks Acked-by: David Brownell --- drivers/usb/host/ohci-s3c2410.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index 0e62d2044f7e..a7ddd5d14a51 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c @@ -371,7 +371,7 @@ static int usb_hcd_s3c2410_probe (const struct hc_driver *driver, usb_clk = clk_get(&dev->dev, "usb-bus-host"); if (IS_ERR(usb_clk)) { - dev_err(&dev->dev, "cannot get usb-host clock\n"); + dev_err(&dev->dev, "cannot get usb-bus-host clock\n"); retval = -ENOENT; goto err_clk; } -- cgit v1.2.3 From 46923a50c59ba09b3f34138c9e1dd2cdfee0422c Mon Sep 17 00:00:00 2001 From: Hannes Eder Date: Fri, 27 Feb 2009 02:04:31 +0100 Subject: USB: host: fix sparse warning: Using plain integer as NULL pointer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix this sparse warning:  drivers/usb/host/oxu210hp-hcd.c:2687:42: warning: Using plain integer as NULL pointer Signed-off-by: Hannes Eder Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/oxu210hp-hcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c index 2947c69b3476..5ac489ee3dab 100644 --- a/drivers/usb/host/oxu210hp-hcd.c +++ b/drivers/usb/host/oxu210hp-hcd.c @@ -2684,7 +2684,7 @@ static int oxu_reset(struct usb_hcd *hcd) oxu->urb_len = 0; /* FIMXE */ - hcd->self.controller->dma_mask = 0UL; + hcd->self.controller->dma_mask = NULL; if (oxu->is_otg) { oxu->caps = hcd->regs + OXU_OTG_CAP_OFFSET; -- cgit v1.2.3 From 46543dacf82b776d37601181ecf1f6afdf09ee48 Mon Sep 17 00:00:00 2001 From: "D.J. Capelis" Date: Wed, 4 Mar 2009 10:27:52 -0800 Subject: USB: pedantic: spelling correction in comment for ch9.h Just noticed this during a grep, figured I might as well send it in. From: D.J. Capelis Signed-off-by: Greg Kroah-Hartman --- include/linux/usb/ch9.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h index d9d54803dbcb..b145119a90da 100644 --- a/include/linux/usb/ch9.h +++ b/include/linux/usb/ch9.h @@ -102,7 +102,7 @@ #define USB_REQ_LOOPBACK_DATA_READ 0x16 #define USB_REQ_SET_INTERFACE_DS 0x17 -/* The Link Power Mangement (LPM) ECN defines USB_REQ_TEST_AND_SET command, +/* The Link Power Management (LPM) ECN defines USB_REQ_TEST_AND_SET command, * used by hubs to put ports into a new L1 suspend state, except that it * forgot to define its number ... */ -- cgit v1.2.3 From 9444bbb53c10eacfa8f12e65ae08ba4a516e7338 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Sat, 7 Mar 2009 11:44:10 +0000 Subject: USB: ohci-hcd: Add ARCH_S3C24XX to the ohci-s3c2410.c glue The ohci-s3c2410.c glue supports both CONFIG_ARCH_S3C2410 and CONFIG_ARCH_S3C64XX so add it to the build of ohci-s3c2410.c Signed-off-by: Ben Dooks Cc: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-hcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 5cf5f1eca4f4..d052955439c3 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -997,7 +997,7 @@ MODULE_LICENSE ("GPL"); #define SA1111_DRIVER ohci_hcd_sa1111_driver #endif -#ifdef CONFIG_ARCH_S3C2410 +#if defined(CONFIG_ARCH_S3C2410) || defined(CONFIG_ARCH_S3C64XX) #include "ohci-s3c2410.c" #define PLATFORM_DRIVER ohci_hcd_s3c2410_driver #endif -- cgit v1.2.3 From fc42e0b88fe6ac1f7cae8f1d6aa959d408801f0c Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Sat, 7 Mar 2009 11:44:21 +0000 Subject: USB: S3C: Move usb-control.h to platform include The usb-control.h is needed by ohci-s3c2410.c for both S3C24XX and S3C64XX architectures, so move it to Signed-off-by: Ben Dooks Cc: David Brownell Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-s3c2410/include/mach/usb-control.h | 41 ------------------------ arch/arm/mach-s3c2410/usb-simtec.c | 3 +- arch/arm/plat-s3c/include/plat/usb-control.h | 41 ++++++++++++++++++++++++ drivers/usb/host/ohci-s3c2410.c | 3 +- 4 files changed, 44 insertions(+), 44 deletions(-) delete mode 100644 arch/arm/mach-s3c2410/include/mach/usb-control.h create mode 100644 arch/arm/plat-s3c/include/plat/usb-control.h diff --git a/arch/arm/mach-s3c2410/include/mach/usb-control.h b/arch/arm/mach-s3c2410/include/mach/usb-control.h deleted file mode 100644 index cd91d1591f31..000000000000 --- a/arch/arm/mach-s3c2410/include/mach/usb-control.h +++ /dev/null @@ -1,41 +0,0 @@ -/* arch/arm/mach-s3c2410/include/mach/usb-control.h - * - * Copyright (c) 2004 Simtec Electronics - * Ben Dooks - * - * S3C2410 - usb port information - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#ifndef __ASM_ARCH_USBCONTROL_H -#define __ASM_ARCH_USBCONTROL_H "arch/arm/mach-s3c2410/include/mach/usb-control.h" - -#define S3C_HCDFLG_USED (1) - -struct s3c2410_hcd_port { - unsigned char flags; - unsigned char power; - unsigned char oc_status; - unsigned char oc_changed; -}; - -struct s3c2410_hcd_info { - struct usb_hcd *hcd; - struct s3c2410_hcd_port port[2]; - - void (*power_control)(int port, int to); - void (*enable_oc)(struct s3c2410_hcd_info *, int on); - void (*report_oc)(struct s3c2410_hcd_info *, int ports); -}; - -static void inline s3c2410_usb_report_oc(struct s3c2410_hcd_info *info, int ports) -{ - if (info->report_oc != NULL) { - (info->report_oc)(info, ports); - } -} - -#endif /*__ASM_ARCH_USBCONTROL_H */ diff --git a/arch/arm/mach-s3c2410/usb-simtec.c b/arch/arm/mach-s3c2410/usb-simtec.c index 6078f09b7df5..8331e8d97e20 100644 --- a/arch/arm/mach-s3c2410/usb-simtec.c +++ b/arch/arm/mach-s3c2410/usb-simtec.c @@ -29,13 +29,14 @@ #include #include -#include #include #include #include +#include #include + #include "usb-simtec.h" /* control power and monitor over-current events on various Simtec diff --git a/arch/arm/plat-s3c/include/plat/usb-control.h b/arch/arm/plat-s3c/include/plat/usb-control.h new file mode 100644 index 000000000000..822c87fe948e --- /dev/null +++ b/arch/arm/plat-s3c/include/plat/usb-control.h @@ -0,0 +1,41 @@ +/* arch/arm/plat-s3c/include/plat/usb-control.h + * + * Copyright (c) 2004 Simtec Electronics + * Ben Dooks + * + * S3C - USB host port information + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARCH_USBCONTROL_H +#define __ASM_ARCH_USBCONTROL_H + +#define S3C_HCDFLG_USED (1) + +struct s3c2410_hcd_port { + unsigned char flags; + unsigned char power; + unsigned char oc_status; + unsigned char oc_changed; +}; + +struct s3c2410_hcd_info { + struct usb_hcd *hcd; + struct s3c2410_hcd_port port[2]; + + void (*power_control)(int port, int to); + void (*enable_oc)(struct s3c2410_hcd_info *, int on); + void (*report_oc)(struct s3c2410_hcd_info *, int ports); +}; + +static void inline s3c2410_usb_report_oc(struct s3c2410_hcd_info *info, int ports) +{ + if (info->report_oc != NULL) { + (info->report_oc)(info, ports); + } +} + +#endif /*__ASM_ARCH_USBCONTROL_H */ diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index a7ddd5d14a51..a68af2dd55ca 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c @@ -21,8 +21,7 @@ #include #include - -#include +#include #define valid_port(idx) ((idx) == 1 || (idx) == 2) -- cgit v1.2.3 From 0d3524ef805e7a85822cdfa54bb813227a2df259 Mon Sep 17 00:00:00 2001 From: Mark Ellis Date: Mon, 9 Mar 2009 22:24:29 +0000 Subject: USB: ipaq: handle 4 endpoint devices The ipaq driver currently enforces one port on all devices. This is correct for 2 and 3 endpoint devices, but with 4 endpoint devices meaningful communication occurs on the second pair. This patch allows 2 ports for 4 endpoint devices. Signed-off-by: Mark Ellis Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ipaq.c | 43 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index 132be74d2b89..ef92095b0732 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c @@ -78,6 +78,7 @@ static int ipaq_open(struct tty_struct *tty, struct usb_serial_port *port, struct file *filp); static void ipaq_close(struct tty_struct *tty, struct usb_serial_port *port, struct file *filp); +static int ipaq_calc_num_ports(struct usb_serial *serial); static int ipaq_startup(struct usb_serial *serial); static void ipaq_shutdown(struct usb_serial *serial); static int ipaq_write(struct tty_struct *tty, struct usb_serial_port *port, @@ -572,15 +573,10 @@ static struct usb_serial_driver ipaq_device = { .description = "PocketPC PDA", .usb_driver = &ipaq_driver, .id_table = ipaq_id_table, - /* - * some devices have an extra endpoint, which - * must be ignored as it would make the core - * create a second port which oopses when used - */ - .num_ports = 1, .open = ipaq_open, .close = ipaq_close, .attach = ipaq_startup, + .calc_num_ports = ipaq_calc_num_ports, .shutdown = ipaq_shutdown, .write = ipaq_write, .write_room = ipaq_write_room, @@ -956,14 +952,49 @@ static void ipaq_destroy_lists(struct usb_serial_port *port) } +static int ipaq_calc_num_ports(struct usb_serial *serial) +{ + /* + * some devices have 3 endpoints, the 3rd of which + * must be ignored as it would make the core + * create a second port which oopses when used + */ + int ipaq_num_ports = 1; + + dbg("%s - numberofendpoints: %d", __FUNCTION__, + (int)serial->interface->cur_altsetting->desc.bNumEndpoints); + + /* + * a few devices have 4 endpoints, seemingly Yakuma devices, + * and we need the second pair, so let them have 2 ports + * + * TODO: can we drop port 1 ? + */ + if (serial->interface->cur_altsetting->desc.bNumEndpoints > 3) { + ipaq_num_ports = 2; + } + + return ipaq_num_ports; +} + + static int ipaq_startup(struct usb_serial *serial) { dbg("%s", __func__); if (serial->dev->actconfig->desc.bConfigurationValue != 1) { + /* + * FIXME: HP iPaq rx3715, possibly others, have 1 config that + * is labeled as 2 + */ + dev_err(&serial->dev->dev, "active config #%d != 1 ??\n", serial->dev->actconfig->desc.bConfigurationValue); return -ENODEV; } + + dbg("%s - iPAQ module configured for %d ports", + __FUNCTION__, serial->num_ports); + return usb_reset_configuration(serial->dev); } -- cgit v1.2.3 From 5cc1f42841feda248ad4eca50342e3cedc7ebde7 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Sat, 7 Mar 2009 21:44:30 +0800 Subject: USB: gadget: introduce isochronous source sink configuration driver This patch introduces isochronous source sink configuration driver into zero composite driver. The driver is based on David Brownell's f_sourcesink.c It can be used to evalute isochronous transfer performance of usb host controller or usb host controller driver, also can be used to troubleshoot usb host controller driver(usually some embedded hcd) handily. I have verified the isochronous configuration driver in omap3-based beagle board. Signed-off-by: Ming Lei Cc: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/f_iso.c | 479 +++++++++++++++++++++++++++++++++++++++++++++ drivers/usb/gadget/zero.c | 25 ++- 2 files changed, 501 insertions(+), 3 deletions(-) create mode 100644 drivers/usb/gadget/f_iso.c diff --git a/drivers/usb/gadget/f_iso.c b/drivers/usb/gadget/f_iso.c new file mode 100644 index 000000000000..18e7429c19f9 --- /dev/null +++ b/drivers/usb/gadget/f_iso.c @@ -0,0 +1,479 @@ +/* + * f_iso.c - USB peripheral isochronous source/sink configuration driver + * This driver is based on David Brownell's f_sourcesink.c. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* #define VERBOSE_DEBUG */ + +#include +#include +#include + +#include "g_zero.h" +#include "gadget_chips.h" + + +#define MULTI (0<<11) + +/* + * ISOCHRONOUS SOURCE/SINK FUNCTION ... a primary testing vehicle for + * USB peripheral controller drivers, it can also be used to evalute + * performance of usb host controller or usb host controller diver, + * and can be used to troubleshoot usb host controller driver handily. + * + * This just sinks isochronous packets OUT to the peripheral and sources + * them IN to the host. As such it supports basic functionality and + * load tests. + * + * In terms of control messaging, this supports all the standard requests + * + * This is currently packaged as a configuration driver, which can't be + * combined with other functions to make composite devices. However, it + * can be combined with other independent configurations. + */ +struct f_iso_sourcesink { + struct usb_function function; + + struct usb_ep *in_ep; + struct usb_ep *out_ep; +}; + +static inline struct f_iso_sourcesink *func_to_iso_ss(struct usb_function *f) +{ + return container_of(f, struct f_iso_sourcesink, function); +} + +/*-------------------------------------------------------------------------*/ + +static struct usb_interface_descriptor iso_source_sink_intf = { + .bLength = sizeof iso_source_sink_intf, + .bDescriptorType = USB_DT_INTERFACE, + + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, + /* .iInterface = DYNAMIC */ +}; + +/* full speed support: */ + +static struct usb_endpoint_descriptor fs_iso_source_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_ISOC, + .wMaxPacketSize = __constant_cpu_to_le16(1023) , + .bInterval = 1, +}; + +static struct usb_endpoint_descriptor fs_iso_sink_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_ISOC, + .wMaxPacketSize = __constant_cpu_to_le16(1023) , + .bInterval = 1, +}; + +static struct usb_descriptor_header *fs_iso_source_sink_descs[] = { + (struct usb_descriptor_header *) &iso_source_sink_intf, + (struct usb_descriptor_header *) &fs_iso_sink_desc, + (struct usb_descriptor_header *) &fs_iso_source_desc, + NULL, +}; + +/* high speed support: */ +static struct usb_endpoint_descriptor hs_iso_source_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_DIR_IN, + + .bmAttributes = USB_ENDPOINT_XFER_ISOC, + .wMaxPacketSize = cpu_to_le16(1024|MULTI) , + .bInterval = 1, +}; + +static struct usb_endpoint_descriptor hs_iso_sink_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_DIR_OUT, + + .bmAttributes = USB_ENDPOINT_XFER_ISOC, + .wMaxPacketSize = cpu_to_le16(1024|MULTI), + .bInterval = 1, +}; + +static struct usb_descriptor_header *hs_iso_source_sink_descs[] = { + (struct usb_descriptor_header *) &iso_source_sink_intf, + (struct usb_descriptor_header *) &hs_iso_source_desc, + (struct usb_descriptor_header *) &hs_iso_sink_desc, + NULL, +}; + +/* function-specific strings: */ +static struct usb_string strings_iso_sourcesink[] = { + [0].s = "iso source and sink data", + { } /* end of list */ +}; + +static struct usb_gadget_strings stringtab_iso_sourcesink = { + .language = 0x0409, /* en-us */ + .strings = strings_iso_sourcesink, +}; + +static struct usb_gadget_strings *iso_sourcesink_strings[] = { + &stringtab_iso_sourcesink, + NULL, +}; + +/*-------------------------------------------------------------------------*/ +static int __init +iso_sourcesink_bind(struct usb_configuration *c, struct usb_function *f) +{ + struct usb_composite_dev *cdev = c->cdev; + struct f_iso_sourcesink *ss = func_to_iso_ss(f); + int id; + + /* allocate interface ID(s) */ + id = usb_interface_id(c, f); + if (id < 0) + return id; + iso_source_sink_intf.bInterfaceNumber = id; + + /* allocate endpoints */ + ss->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_iso_source_desc); + if (!ss->in_ep) { +autoconf_fail: + ERROR(cdev, "%s: can't autoconfigure on %s\n", + f->name, cdev->gadget->name); + return -ENODEV; + } + ss->in_ep->driver_data = cdev; /* claim */ + + ss->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_iso_sink_desc); + if (!ss->out_ep) + goto autoconf_fail; + ss->out_ep->driver_data = cdev; /* claim */ + + /* support high speed hardware */ + if (gadget_is_dualspeed(c->cdev->gadget)) { + hs_iso_source_desc.bEndpointAddress = + fs_iso_source_desc.bEndpointAddress; + hs_iso_sink_desc.bEndpointAddress = + fs_iso_sink_desc.bEndpointAddress; + f->hs_descriptors = hs_iso_source_sink_descs; + } + + DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n", + gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", + f->name, ss->in_ep->name, ss->out_ep->name); + return 0; +} + +static void +iso_sourcesink_unbind(struct usb_configuration *c, struct usb_function *f) +{ + kfree(func_to_iso_ss(f)); +} + +static unsigned char iso_count; +static void iso_reinit_write_data(struct usb_ep *ep, struct usb_request *req) +{ + memset(req->buf, iso_count++, req->length); +} + +static void iso_source_sink_complete(struct usb_ep *ep, struct usb_request *req) +{ + struct f_iso_sourcesink *ss = ep->driver_data; + struct usb_composite_dev *cdev = ss->function.config->cdev; + int status = req->status; + + switch (status) { + + case 0: /* normal completion? */ + if (ep == ss->out_ep) + memset(req->buf, 0x55, req->length); + else + iso_reinit_write_data(ep, req); + break; + + /* this endpoint is normally active while we're configured */ + case -ECONNABORTED: /* hardware forced ep reset */ + case -ECONNRESET: /* request dequeued */ + case -ESHUTDOWN: /* disconnect from host */ + VDBG(cdev, "%s gone (%d), %d/%d\n", ep->name, status, + req->actual, req->length); + free_ep_req(ep, req); + return; + + case -EOVERFLOW: /* buffer overrun on read means that + * we didn't provide a big enough + * buffer. + */ + default: +#if 1 + DBG(cdev, "%s complete --> %d, %d/%d\n", ep->name, + status, req->actual, req->length); +#endif + case -EREMOTEIO: /* short read */ + break; + } + + status = usb_ep_queue(ep, req, GFP_ATOMIC); + if (status) { + ERROR(cdev, "kill %s: resubmit %d bytes --> %d\n", + ep->name, req->length, status); + usb_ep_set_halt(ep); + /* FIXME recover later ... somehow */ + } +} + +static int iso_source_sink_start_ep(struct f_iso_sourcesink *ss, bool is_in) +{ + struct usb_ep *ep; + struct usb_request *req; + int status; + + ep = is_in ? ss->in_ep : ss->out_ep; + req = alloc_ep_req(ep); + if (!req) + return -ENOMEM; + + req->complete = iso_source_sink_complete; + if (is_in) + iso_reinit_write_data(ep, req); + else + memset(req->buf, 0x55, req->length); + + status = usb_ep_queue(ep, req, GFP_ATOMIC); + if (status) { + struct usb_composite_dev *cdev; + + cdev = ss->function.config->cdev; + ERROR(cdev, "start %s %s --> %d\n", + is_in ? "IN" : "OUT", + ep->name, status); + free_ep_req(ep, req); + } + + return status; +} + +static void disable_iso_source_sink(struct f_iso_sourcesink *ss) +{ + struct usb_composite_dev *cdev; + + cdev = ss->function.config->cdev; + disable_endpoints(cdev, ss->in_ep, ss->out_ep); + VDBG(cdev, "%s disabled\n", ss->function.name); +} + +static int +enable_iso_source_sink(struct usb_composite_dev *cdev, \ + struct f_iso_sourcesink *ss) +{ + int result = 0; + const struct usb_endpoint_descriptor *src, *sink; + struct usb_ep *ep; + + src = ep_choose(cdev->gadget, &hs_iso_source_desc, &fs_iso_source_desc); + sink = ep_choose(cdev->gadget, &hs_iso_sink_desc, &fs_iso_sink_desc); + + /* one endpoint writes (sources) zeroes IN (to the host) */ + ep = ss->in_ep; + result = usb_ep_enable(ep, src); + if (result < 0) + return result; + + ep->driver_data = ss; + + result = iso_source_sink_start_ep(ss, true); + if (result < 0) { +fail: + ep = ss->in_ep; + usb_ep_disable(ep); + ep->driver_data = NULL; + return result; + } + + /* one endpoint reads (sinks) anything OUT (from the host) */ + ep = ss->out_ep; + result = usb_ep_enable(ep, sink); + if (result < 0) + goto fail; + ep->driver_data = ss; + + result = iso_source_sink_start_ep(ss, false); + if (result < 0) { + usb_ep_disable(ep); + ep->driver_data = NULL; + goto fail; + } + + DBG(cdev, "%s enabled\n", ss->function.name); + return result; +} + +static int iso_sourcesink_set_alt(struct usb_function *f, + unsigned intf, unsigned alt) +{ + struct f_iso_sourcesink *ss = func_to_iso_ss(f); + struct usb_composite_dev *cdev = f->config->cdev; + + /* we know alt is zero */ + if (ss->in_ep->driver_data) + disable_iso_source_sink(ss); + return enable_iso_source_sink(cdev, ss); +} + +static void iso_sourcesink_disable(struct usb_function *f) +{ + struct f_iso_sourcesink *ss = func_to_iso_ss(f); + + disable_iso_source_sink(ss); +} + + +/*-------------------------------------------------------------------------*/ + +static int __init iso_sourcesink_bind_config(struct usb_configuration *c) +{ + struct f_iso_sourcesink *ss; + int status; + + ss = kzalloc(sizeof *ss, GFP_KERNEL); + if (!ss) + return -ENOMEM; + + ss->function.name = "iso source/sink"; + ss->function.descriptors = fs_iso_source_sink_descs; + ss->function.bind = iso_sourcesink_bind; + ss->function.unbind = iso_sourcesink_unbind; + ss->function.set_alt = iso_sourcesink_set_alt; + ss->function.disable = iso_sourcesink_disable; + + status = usb_add_function(c, &ss->function); + if (status) + kfree(ss); + return status; +} + +static int iso_sourcesink_setup(struct usb_configuration *c, + const struct usb_ctrlrequest *ctrl) +{ + struct usb_request *req = c->cdev->req; + int value = -EOPNOTSUPP; + u16 w_index = le16_to_cpu(ctrl->wIndex); + u16 w_value = le16_to_cpu(ctrl->wValue); + u16 w_length = le16_to_cpu(ctrl->wLength); + + /* composite driver infrastructure handles everything except + * the two control test requests. + */ + switch (ctrl->bRequest) { + + /* + * These are the same vendor-specific requests supported by + * Intel's USB 2.0 compliance test devices. We exceed that + * device spec by allowing multiple-packet requests. + * + * NOTE: the Control-OUT data stays in req->buf ... better + * would be copying it into a scratch buffer, so that other + * requests may safely intervene. + */ + case 0x5b: /* control WRITE test -- fill the buffer */ + if (ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR)) + goto unknown; + if (w_value || w_index) + break; + /* just read that many bytes into the buffer */ + if (w_length > req->length) + break; + value = w_length; + break; + case 0x5c: /* control READ test -- return the buffer */ + if (ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR)) + goto unknown; + if (w_value || w_index) + break; + /* expect those bytes are still in the buffer; send back */ + if (w_length > req->length) + break; + value = w_length; + break; + + default: +unknown: + VDBG(c->cdev, + "unknown control req%02x.%02x v%04x i%04x l%d\n", + ctrl->bRequestType, ctrl->bRequest, + w_value, w_index, w_length); + } + + /* respond with data transfer or status phase? */ + if (value >= 0) { + VDBG(c->cdev, "source/sink req%02x.%02x v%04x i%04x l%d\n", + ctrl->bRequestType, ctrl->bRequest, + w_value, w_index, w_length); + req->zero = 0; + req->length = value; + value = usb_ep_queue(c->cdev->gadget->ep0, req, GFP_ATOMIC); + if (value < 0) + ERROR(c->cdev, "source/sinkc response, err %d\n", + value); + } + + /* device either stalls (value < 0) or reports success */ + return value; +} + +static struct usb_configuration iso_sourcesink_driver = { + .label = "iso source/sink", + .strings = iso_sourcesink_strings, + .bind = iso_sourcesink_bind_config, + .setup = iso_sourcesink_setup, + .bConfigurationValue = 4, + .bmAttributes = USB_CONFIG_ATT_SELFPOWER, + /* .iConfiguration = DYNAMIC */ +}; + +/** + * sourcesink_add - add a source/sink testing configuration to a device + * @cdev: the device to support the configuration + */ +int __init iso_sourcesink_add(struct usb_composite_dev *cdev) +{ + int id; + + /* allocate string ID(s) */ + id = usb_string_id(cdev); + if (id < 0) + return id; + strings_iso_sourcesink[0].id = id; + + iso_source_sink_intf.iInterface = id; + iso_sourcesink_driver.iConfiguration = id; + + /* support OTG systems */ + if (gadget_is_otg(cdev->gadget)) { + iso_sourcesink_driver.descriptors = otg_desc; + iso_sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; + } + + return usb_add_config(cdev, &iso_sourcesink_driver); +} diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 20614dce8db9..db2a7b5366ed 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -71,6 +71,7 @@ #include "config.c" #include "epautoconf.c" +#include "f_iso.c" #include "f_sourcesink.c" #include "f_loopback.c" @@ -92,6 +93,14 @@ module_param(buflen, uint, 0); static int loopdefault = 0; module_param(loopdefault, bool, S_IRUGO|S_IWUSR); +/* + * Normally the "iso" configuration is third (index 2) so + * it's not the default. Here's where to change that order, to + * work better with hosts where config changes are problematic or + * controllers (like original superh) that only support one config. + */ +static int isodefault; +module_param(isodefault, bool, S_IRUGO|S_IWUSR); /*-------------------------------------------------------------------------*/ /* Thanks to NetChip Technologies for donating this product ID. @@ -118,7 +127,7 @@ static struct usb_device_descriptor device_desc = { .idVendor = cpu_to_le16(DRIVER_VENDOR_NUM), .idProduct = cpu_to_le16(DRIVER_PRODUCT_NUM), - .bNumConfigurations = 2, + .bNumConfigurations = 3, }; #ifdef CONFIG_USB_OTG @@ -244,12 +253,22 @@ static int __init zero_bind(struct usb_composite_dev *cdev) */ if (loopdefault) { loopback_add(cdev); - if (!gadget_is_sh(gadget)) + if (!gadget_is_sh(gadget)) { sourcesink_add(cdev); + iso_sourcesink_add(cdev); + } + } else if (isodefault) { + iso_sourcesink_add(cdev); + if (!gadget_is_sh(gadget)) { + sourcesink_add(cdev); + loopback_add(cdev); + } } else { sourcesink_add(cdev); - if (!gadget_is_sh(gadget)) + if (!gadget_is_sh(gadget)) { loopback_add(cdev); + iso_sourcesink_add(cdev); + } } gcnum = usb_gadget_controller_number(gadget); -- cgit v1.2.3 From 75f3a9d68ec14057e0e0f66ae1657f0edfb4c7c9 Mon Sep 17 00:00:00 2001 From: Alex Stephens Date: Tue, 17 Mar 2009 00:06:19 +0000 Subject: USB: CP2101 New Device ID One new device ID for CP2101 driver. Signed-off-by: Alex Stephens alex@miranova.com --- drivers/usb/serial/cp210x.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 2f23d0643624..292f0163b92c 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -87,6 +87,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x10c4, 0x8293) }, /* Telegesys ETRX2USB */ { USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */ { USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */ + { USB_DEVICE(0x10C4, 0x846E) }, /* BEI USB Sensor Interface (VCP) */ { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */ -- cgit v1.2.3 From da94b9a8f58f0da06bfca6ab440b4d381e6bd732 Mon Sep 17 00:00:00 2001 From: VomLehn Date: Thu, 12 Mar 2009 14:37:42 -0700 Subject: USB: Fix cp2101 USB serial device driver termios functions for console use This is really a follow up to the modifications Alan Cox made for commit 95da310e66ee8090119596c70ca8432e57f9a97f to pass a tty_struct to various interface functions, which broke the serial configuration (termios) functions when the device is being used as a console. These changes restore the configuration to proper functioning both as a tty and as a console. As Alan notes in that commit, these changes will need to be tweaked when we have a proper console abstraction. Signed-off-by: David VomLehn Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp210x.c | 53 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 10 deletions(-) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 292f0163b92c..e8d5133ce9c8 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -38,17 +38,21 @@ static int cp2101_open(struct tty_struct *, struct usb_serial_port *, static void cp2101_cleanup(struct usb_serial_port *); static void cp2101_close(struct tty_struct *, struct usb_serial_port *, struct file*); -static void cp2101_get_termios(struct tty_struct *); +static void cp2101_get_termios(struct tty_struct *, + struct usb_serial_port *port); +static void cp2101_get_termios_port(struct usb_serial_port *port, + unsigned int *cflagp, unsigned int *baudp); static void cp2101_set_termios(struct tty_struct *, struct usb_serial_port *, struct ktermios*); static int cp2101_tiocmget(struct tty_struct *, struct file *); static int cp2101_tiocmset(struct tty_struct *, struct file *, unsigned int, unsigned int); +static int cp2101_tiocmset_port(struct usb_serial_port *port, struct file *, + unsigned int, unsigned int); static void cp2101_break_ctl(struct tty_struct *, int); static int cp2101_startup(struct usb_serial *); static void cp2101_shutdown(struct usb_serial *); - static int debug; static struct usb_device_id id_table [] = { @@ -369,10 +373,12 @@ static int cp2101_open(struct tty_struct *tty, struct usb_serial_port *port, } /* Configure the termios structure */ - cp2101_get_termios(tty); + cp2101_get_termios(tty, port); /* Set the DTR and RTS pins low */ - cp2101_tiocmset(tty, NULL, TIOCM_DTR | TIOCM_RTS, 0); + cp2101_tiocmset_port(tty ? (struct usb_serial_port *) tty->driver_data + : port, + NULL, TIOCM_DTR | TIOCM_RTS, 0); return 0; } @@ -414,9 +420,31 @@ static void cp2101_close(struct tty_struct *tty, struct usb_serial_port *port, * from the device, corrects any unsupported values, and configures the * termios structure to reflect the state of the device */ -static void cp2101_get_termios (struct tty_struct *tty) +static void cp2101_get_termios(struct tty_struct *tty, + struct usb_serial_port *port) +{ + unsigned int baud; + + if (tty) { + cp2101_get_termios_port(tty->driver_data, + &tty->termios->c_cflag, &baud); + tty_encode_baud_rate(tty, baud, baud); + } + + else { + unsigned int cflag; + cflag = 0; + cp2101_get_termios_port(port, &cflag, &baud); + } +} + +/* + * cp2101_get_termios_port + * This is the heart of cp2101_get_termios which always uses a &usb_serial_port. + */ +static void cp2101_get_termios_port(struct usb_serial_port *port, + unsigned int *cflagp, unsigned int *baudp) { - struct usb_serial_port *port = tty->driver_data; unsigned int cflag, modem_ctl[4]; unsigned int baud; unsigned int bits; @@ -429,9 +457,9 @@ static void cp2101_get_termios (struct tty_struct *tty) baud = cp2101_quantise_baudrate((BAUD_RATE_GEN_FREQ + baud/2)/ baud); dbg("%s - baud rate = %d", __func__, baud); + *baudp = baud; - tty_encode_baud_rate(tty, baud, baud); - cflag = tty->termios->c_cflag; + cflag = *cflagp; cp2101_get_config(port, CP2101_BITS, &bits, 2); cflag &= ~CSIZE; @@ -537,7 +565,7 @@ static void cp2101_get_termios (struct tty_struct *tty) cflag &= ~CRTSCTS; } - tty->termios->c_cflag = cflag; + *cflagp = cflag; } static void cp2101_set_termios(struct tty_struct *tty, @@ -669,6 +697,12 @@ static int cp2101_tiocmset (struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; + return cp2101_tiocmset_port(port, file, set, clear); +} + +static int cp2101_tiocmset_port(struct usb_serial_port *port, struct file *file, + unsigned int set, unsigned int clear) +{ unsigned int control = 0; dbg("%s - port %d", __func__, port->number); @@ -693,7 +727,6 @@ static int cp2101_tiocmset (struct tty_struct *tty, struct file *file, dbg("%s - control = 0x%.4x", __func__, control); return cp2101_set_config(port, CP2101_CONTROL, &control, 2); - } static int cp2101_tiocmget (struct tty_struct *tty, struct file *file) -- cgit v1.2.3 From 186069b5c8c54e3807dcb80ea676d2392a0f8d88 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Fri, 13 Mar 2009 12:19:18 +0100 Subject: USB: more u32 conversion after transfer_buffer_length and actual_length transfer_buffer_length and actual_length have become unsigned, therefore some additional conversion of local variables, function arguments and print specifications is desired. A test for a negative urb->transfer_buffer_length became obsolete; instead we ensure that it does not exceed INT_MAX. Also, urb->actual_length is always less than urb->transfer_buffer_length. rh_string() does no longer return -EPIPE in the case of an unsupported ID. Instead its only caller, rh_call_control() does the check. Signed-off-by: Roel Kluin Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 6 +++--- drivers/usb/core/hcd.c | 31 ++++++++++++------------------- drivers/usb/core/hub.c | 2 +- drivers/usb/core/message.c | 2 +- drivers/usb/core/urb.c | 2 +- 5 files changed, 18 insertions(+), 25 deletions(-) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index d3883f639604..df3c539f652a 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -302,7 +302,7 @@ static struct async *async_getpending(struct dev_state *ps, static void snoop_urb(struct urb *urb, void __user *userurb) { - int j; + unsigned j; unsigned char *data = urb->transfer_buffer; if (!usbfs_snoop) @@ -311,9 +311,9 @@ static void snoop_urb(struct urb *urb, void __user *userurb) dev_info(&urb->dev->dev, "direction=%s\n", usb_urb_dir_in(urb) ? "IN" : "OUT"); dev_info(&urb->dev->dev, "userurb=%p\n", userurb); - dev_info(&urb->dev->dev, "transfer_buffer_length=%d\n", + dev_info(&urb->dev->dev, "transfer_buffer_length=%u\n", urb->transfer_buffer_length); - dev_info(&urb->dev->dev, "actual_length=%d\n", urb->actual_length); + dev_info(&urb->dev->dev, "actual_length=%u\n", urb->actual_length); dev_info(&urb->dev->dev, "data: "); for (j = 0; j < urb->transfer_buffer_length; ++j) printk("%02x ", data[j]); diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 0eee32a65e23..81fa8506825d 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -279,9 +279,9 @@ static const u8 hs_rh_config_descriptor [] = { * helper routine for returning string descriptors in UTF-16LE * input can actually be ISO-8859-1; ASCII is its 7-bit subset */ -static int ascii2utf (char *s, u8 *utf, int utfmax) +static unsigned ascii2utf(char *s, u8 *utf, int utfmax) { - int retval; + unsigned retval; for (retval = 0; *s && utfmax > 1; utfmax -= 2, retval += 2) { *utf++ = *s++; @@ -304,19 +304,15 @@ static int ascii2utf (char *s, u8 *utf, int utfmax) * Produces either a manufacturer, product or serial number string for the * virtual root hub device. */ -static int rh_string ( - int id, - struct usb_hcd *hcd, - u8 *data, - int len -) { +static unsigned rh_string(int id, struct usb_hcd *hcd, u8 *data, unsigned len) +{ char buf [100]; // language ids if (id == 0) { buf[0] = 4; buf[1] = 3; /* 4 bytes string data */ buf[2] = 0x09; buf[3] = 0x04; /* MSFT-speak for "en-us" */ - len = min (len, 4); + len = min_t(unsigned, len, 4); memcpy (data, buf, len); return len; @@ -332,10 +328,7 @@ static int rh_string ( } else if (id == 3) { snprintf (buf, sizeof buf, "%s %s %s", init_utsname()->sysname, init_utsname()->release, hcd->driver->description); - - // unsupported IDs --> "protocol stall" - } else - return -EPIPE; + } switch (len) { /* All cases fall through */ default: @@ -360,9 +353,8 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) u8 tbuf [sizeof (struct usb_hub_descriptor)] __attribute__((aligned(4))); const u8 *bufp = tbuf; - int len = 0; + unsigned len = 0; int status; - int n; u8 patch_wakeup = 0; u8 patch_protocol = 0; @@ -456,10 +448,11 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) patch_wakeup = 1; break; case USB_DT_STRING << 8: - n = rh_string (wValue & 0xff, hcd, ubuf, wLength); - if (n < 0) + if ((wValue & 0xff) < 4) + urb->actual_length = rh_string(wValue & 0xff, + hcd, ubuf, wLength); + else /* unsupported IDs --> "protocol stall" */ goto error; - urb->actual_length = n; break; default: goto error; @@ -629,7 +622,7 @@ static int rh_queue_status (struct usb_hcd *hcd, struct urb *urb) { int retval; unsigned long flags; - int len = 1 + (urb->dev->maxchild / 8); + unsigned len = 1 + (urb->dev->maxchild / 8); spin_lock_irqsave (&hcd_root_hub_lock, flags); if (hcd->status_urb || urb->transfer_buffer_length < len) { diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 81eb3e6b6592..be86ae3f4088 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -392,7 +392,7 @@ static void hub_irq(struct urb *urb) { struct usb_hub *hub = urb->context; int status = urb->status; - int i; + unsigned i; unsigned long bits; switch (status) { diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 3922fa915ed2..293a30d78d24 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -59,7 +59,7 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length) retval = (ctx.status == -ENOENT ? -ETIMEDOUT : ctx.status); dev_dbg(&urb->dev->dev, - "%s timed out on ep%d%s len=%d/%d\n", + "%s timed out on ep%d%s len=%u/%u\n", current->comm, usb_endpoint_num(&urb->ep->desc), usb_urb_dir_in(urb) ? "in" : "out", diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index 7025d801f23a..3376055f36e7 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -370,7 +370,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) } /* the I/O buffer must be mapped/unmapped, except when length=0 */ - if (urb->transfer_buffer_length < 0) + if (urb->transfer_buffer_length > INT_MAX) return -EMSGSIZE; #ifdef DEBUG -- cgit v1.2.3