Commit 69d42f24 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge kroah.com:/home/greg/linux/BK/bleed-2.5

into kroah.com:/home/greg/linux/BK/gregkh-2.5
parents 1a1b6495 db186469
......@@ -41,6 +41,7 @@
#define USBMIDI_ROLAND_UA100G 0x0000
#define USBMIDI_ROLAND_MPU64 0x0002
#define USBMIDI_ROLAND_SC8850 0x0003
#define USBMIDI_ROLAND_SC8820 0x0007
#define USBMIDI_ROLAND_UM2 0x0005
#define USBMIDI_ROLAND_UM1 0x0009
#define USBMIDI_ROLAND_PC300 0x0008
......@@ -104,6 +105,13 @@ static struct usb_midi_device usb_midi_devices[] = {
{ { 0x01, 15 }, {-1, -1} },
},
{ /* Roland SC8820 */
"Roland SC8820",
USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8820, 2, -1,
{ { 0x81, 17 }, {-1, -1} },
{ { 0x01, 17 }, {-1, -1} },
},
{ /* YAMAHA MU1000 */
"YAMAHA MU1000",
USB_VENDOR_ID_YAMAHA, USBMIDI_YAMAHA_MU1000, 0, -1,
......
......@@ -183,15 +183,21 @@ show_##field (struct device *dev, char *buf) \
} \
static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
usb_intf_attr (bInterfaceNumber, "%02x\n")
usb_intf_attr (bAlternateSetting, "%2d\n")
usb_intf_attr (bNumEndpoints, "%02x\n")
usb_intf_attr (bInterfaceClass, "%02x\n")
usb_intf_attr (bInterfaceSubClass, "%02x\n")
usb_intf_attr (bInterfaceProtocol, "%02x\n")
usb_intf_attr (iInterface, "%02x\n")
void usb_create_driverfs_intf_files (struct usb_interface *intf)
{
device_create_file (&intf->dev, &dev_attr_bInterfaceNumber);
device_create_file (&intf->dev, &dev_attr_bAlternateSetting);
device_create_file (&intf->dev, &dev_attr_bNumEndpoints);
device_create_file (&intf->dev, &dev_attr_bInterfaceClass);
device_create_file (&intf->dev, &dev_attr_bInterfaceSubClass);
device_create_file (&intf->dev, &dev_attr_bInterfaceProtocol);
device_create_file (&intf->dev, &dev_attr_iInterface);
}
......@@ -1148,7 +1148,7 @@ void usb_hub_cleanup(void)
int ret;
/* Kill the thread */
ret = kill_proc(khubd_pid, SIGTERM, 1);
ret = kill_proc(khubd_pid, SIGKILL, 1);
wait_for_completion(&khubd_exited);
......
......@@ -605,8 +605,10 @@ show_registers (struct device *dev, char *buf)
}
#ifdef EHCI_STATS
temp = snprintf (next, size, "irq normal %ld err %ld reclaim %ld\n",
ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim);
temp = snprintf (next, size,
"irq normal %ld err %ld reclaim %ld (lost %ld)\n",
ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim,
ehci->stats.lost_iaa);
size -= temp;
next += temp;
......
......@@ -260,6 +260,7 @@ static void ehci_watchdog (unsigned long param)
if (status & STS_IAA) {
ehci_vdbg (ehci, "lost IAA\n");
COUNT (ehci->stats.lost_iaa);
writel (STS_IAA, &ehci->regs->status);
ehci->reclaim_ready = 1;
}
......@@ -547,8 +548,9 @@ static void ehci_stop (struct usb_hcd *hcd)
ehci_mem_cleanup (ehci);
#ifdef EHCI_STATS
ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld\n",
ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim);
ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld (lost %ld)\n",
ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim,
ehci->stats.lost_iaa);
ehci_dbg (ehci, "complete %ld unlink %ld\n",
ehci->stats.complete, ehci->stats.unlink);
#endif
......
......@@ -800,6 +800,7 @@ static struct ehci_qh *qh_append_tds (
&& !usb_pipecontrol (urb->pipe)) {
/* "never happens": drivers do stall cleanup right */
if (qh->qh_state != QH_STATE_IDLE
&& !list_empty (&qh->qtd_list)
&& qh->qh_state != QH_STATE_COMPLETING)
ehci_warn (ehci, "clear toggle dev%d "
"ep%d%s: not idle\n",
......@@ -1014,6 +1015,7 @@ static void
scan_async (struct ehci_hcd *ehci, struct pt_regs *regs)
{
struct ehci_qh *qh;
int unlink_delay = 0;
if (!++(ehci->stamp))
ehci->stamp++;
......@@ -1040,17 +1042,25 @@ scan_async (struct ehci_hcd *ehci, struct pt_regs *regs)
}
}
/* unlink idle entries, reducing HC PCI usage as
* well as HCD schedule-scanning costs.
*
* FIXME don't unlink idle entries so quickly; it
* can penalize (common) half duplex protocols.
/* unlink idle entries, reducing HC PCI usage as well
* as HCD schedule-scanning costs. delay for any qh
* we just scanned, there's a not-unusual case that it
* doesn't stay idle for long.
* (plus, avoids some kind of re-activation race.)
*/
if (list_empty (&qh->qtd_list) && !ehci->reclaim) {
start_unlink_async (ehci, qh);
if (list_empty (&qh->qtd_list)) {
if (qh->stamp == ehci->stamp)
unlink_delay = 1;
else if (!ehci->reclaim) {
start_unlink_async (ehci, qh);
unlink_delay = 0;
}
}
qh = qh->qh_next.qh;
} while (qh);
}
if (unlink_delay && !timer_pending (&ehci->watchdog))
mod_timer (&ehci->watchdog, jiffies + EHCI_WATCHDOG_JIFFIES/2);
}
......@@ -27,6 +27,7 @@ struct ehci_stats {
unsigned long normal;
unsigned long error;
unsigned long reclaim;
unsigned long lost_iaa;
/* termination of urbs from core */
unsigned long complete;
......
This diff is collapsed.
......@@ -17,6 +17,8 @@
*
* History:
*
* 2003/02/24 show registers in sysfs (Kevin Brosius)
*
* 2002/09/03 get rid of ed hashtables, rework periodic scheduling and
* bandwidth accounting; if debugging, show schedules in driverfs
* 2002/07/19 fixes to management of ED and schedule state.
......@@ -105,11 +107,10 @@
* TO DO:
*
* - "disabled" and "sleeping" should be in hcd->state
* - bandwidth alloc to generic code
* - lots more testing!!
*/
#define DRIVER_VERSION "2002-Sep-17"
#define DRIVER_VERSION "2003 Feb 24"
#define DRIVER_AUTHOR "Roman Weissgaerber, David Brownell"
#define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver"
......@@ -125,6 +126,8 @@
/*-------------------------------------------------------------------------*/
static const char hcd_name [] = "ohci-hcd";
#include "ohci.h"
static inline void disable (struct ohci_hcd *ohci)
......@@ -275,6 +278,7 @@ static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
urb_print (urb, "UNLINK", 1);
#endif
spin_lock_irqsave (&ohci->lock, flags);
if (!ohci->disabled) {
urb_priv_t *urb_priv;
......@@ -282,21 +286,24 @@ static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
* handed to us, flag it for unlink and giveback, and force
* some upcoming INTR_SF to call finish_unlinks()
*/
spin_lock_irqsave (&ohci->lock, flags);
urb_priv = urb->hcpriv;
if (urb_priv) {
urb_priv->state = URB_DEL;
if (urb_priv->ed->state == ED_OPER)
start_urb_unlink (ohci, urb_priv->ed);
}
spin_unlock_irqrestore (&ohci->lock, flags);
} else {
/*
* with HC dead, we won't respect hc queue pointers
* any more ... just clean up every urb's memory.
*/
finish_urb (ohci, urb, NULL);
if (urb->hcpriv) {
spin_unlock (&ohci->lock);
finish_urb (ohci, urb, NULL);
spin_lock (&ohci->lock);
}
}
spin_unlock_irqrestore (&ohci->lock, flags);
return 0;
}
......@@ -332,9 +339,11 @@ ohci_free_config (struct usb_hcd *hcd, struct usb_device *udev)
td_free (ohci, ed->dummy);
break;
default:
err ("%s-%s ed %p (#%d) not unlinked; disconnect() bug? %d",
ohci->hcd.self.bus_name, udev->devpath, ed,
i, ed->state);
ohci_err (ohci,
"dev %s ep%d-%s linked; disconnect() bug?\n",
udev->devpath,
(i >> 1) & 0x0f, (i & 1) ? "out" : "in");
/* ED_OPER: some driver disconnect() is broken,
* it didn't even start its unlinks much less wait
* for their completions.
......@@ -354,8 +363,10 @@ ohci_free_config (struct usb_hcd *hcd, struct usb_device *udev)
#ifdef DEBUG
/* a driver->disconnect() returned before its unlinks completed? */
if (in_interrupt ()) {
warn ("disconnect() bug for dev usb-%s-%s ep 0x%x",
ohci->hcd.self.bus_name, udev->devpath, i);
ohci_warn (ohci,
"driver disconnect() bug %s ep%d-%s\n",
udev->devpath,
(i >> 1) & 0x0f, (i & 1) ? "out" : "in");
}
#endif
......@@ -381,9 +392,12 @@ static int hc_reset (struct ohci_hcd *ohci)
{
u32 temp;
/* SMM owns the HC? not for long! */
/* SMM owns the HC? not for long!
* On PA-RISC, PDC can leave IR set incorrectly; ignore it there.
*/
#ifndef __hppa__
if (readl (&ohci->regs->control) & OHCI_CTRL_IR) {
dev_dbg (ohci->hcd.controller, "USB HC TakeOver from BIOS/SMM\n");
ohci_dbg (ohci, "USB HC TakeOver from BIOS/SMM\n");
/* this timeout is arbitrary. we make it long, so systems
* depending on usb keyboards may be usable even if the
......@@ -396,17 +410,18 @@ static int hc_reset (struct ohci_hcd *ohci)
while (readl (&ohci->regs->control) & OHCI_CTRL_IR) {
wait_ms (10);
if (--temp == 0) {
dev_err (ohci->hcd.controller, "USB HC TakeOver failed!\n");
ohci_err (ohci, "USB HC TakeOver failed!\n");
return -1;
}
}
}
#endif
/* Disable HC interrupts */
writel (OHCI_INTR_MIE, &ohci->regs->intrdisable);
dev_dbg (ohci->hcd.controller, "USB HC reset_hc %s: ctrl = 0x%x ;\n",
ohci->hcd.self.bus_name,
ohci_dbg (ohci, "USB HC reset_hc %s: ctrl = 0x%x ;\n",
hcd_to_bus (&ohci->hcd)->bus_name,
readl (&ohci->regs->control));
/* Reset USB (needed by some controllers); RemoteWakeupConnected
......@@ -422,7 +437,7 @@ static int hc_reset (struct ohci_hcd *ohci)
temp = 30; /* ... allow extra time */
while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) {
if (--temp == 0) {
dev_err (ohci->hcd.controller, "USB HC reset timed out!");
ohci_err (ohci, "USB HC reset timed out!\n");
return -1;
}
udelay (1);
......@@ -451,8 +466,9 @@ static int hc_reset (struct ohci_hcd *ohci)
*/
static int hc_start (struct ohci_hcd *ohci)
{
u32 mask;
u32 mask, tmp;
struct usb_device *udev;
struct usb_bus *bus;
spin_lock_init (&ohci->lock);
ohci->disabled = 1;
......@@ -478,7 +494,7 @@ static int hc_start (struct ohci_hcd *ohci)
*/
if ((readl (&ohci->regs->fminterval) & 0x3fff0000) == 0
|| !readl (&ohci->regs->periodicstart)) {
err ("%s init err", ohci->hcd.self.bus_name);
ohci_err (ohci, "init err\n");
return -EOVERFLOW;
}
......@@ -493,9 +509,20 @@ static int hc_start (struct ohci_hcd *ohci)
writel (mask, &ohci->regs->intrstatus);
writel (mask, &ohci->regs->intrenable);
/* hub power always on: required for AMD-756 and some Mac platforms */
writel ((roothub_a (ohci) | RH_A_NPS) & ~(RH_A_PSM | RH_A_OCPM),
&ohci->regs->roothub.a);
/* handle root hub init quirks ... */
tmp = roothub_a (ohci);
tmp &= ~(RH_A_PSM | RH_A_OCPM);
if (ohci->flags & OHCI_QUIRK_SUPERIO) {
/* NSC 87560 and maybe others */
tmp |= RH_A_NOCP;
tmp &= ~(RH_A_POTPGT | RH_A_NPS);
} else {
/* hub power always on; required for AMD-756 and some
* Mac platforms, use this mode everywhere by default
*/
tmp |= RH_A_NPS;
}
writel (tmp, &ohci->regs->roothub.a);
writel (RH_HS_LPSC, &ohci->regs->roothub.status);
writel (0, &ohci->regs->roothub.b);
......@@ -503,7 +530,8 @@ static int hc_start (struct ohci_hcd *ohci)
mdelay ((roothub_a (ohci) >> 23) & 0x1fe);
/* connect the virtual root hub */
ohci->hcd.self.root_hub = udev = usb_alloc_dev (NULL, &ohci->hcd.self);
bus = hcd_to_bus (&ohci->hcd);
bus->root_hub = udev = usb_alloc_dev (NULL, bus);
ohci->hcd.state = USB_STATE_READY;
if (!udev) {
disable (ohci);
......@@ -514,9 +542,9 @@ static int hc_start (struct ohci_hcd *ohci)
usb_connect (udev);
udev->speed = USB_SPEED_FULL;
if (usb_register_root_hub (udev, ohci->hcd.controller) != 0) {
if (hcd_register_root (&ohci->hcd) != 0) {
usb_put_dev (udev);
ohci->hcd.self.root_hub = NULL;
bus->root_hub = NULL;
disable (ohci);
ohci->hc_control &= ~OHCI_CTRL_HCFS;
writel (ohci->hc_control, &ohci->regs->control);
......@@ -545,7 +573,7 @@ static void ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
/* cardbus/... hardware gone before remove() */
} else if ((ints = readl (&regs->intrstatus)) == ~(u32)0) {
disable (ohci);
dbg ("%s device removed!", hcd->self.bus_name);
ohci_dbg (ohci, "device removed!\n");
return;
/* interrupt for some other device? */
......@@ -553,13 +581,9 @@ static void ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
return;
}
// dbg ("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no));
if (ints & OHCI_INTR_UE) {
disable (ohci);
err ("OHCI Unrecoverable Error, %s disabled",
hcd->self.bus_name);
ohci_err (ohci, "OHCI Unrecoverable Error, disabled\n");
// e.g. due to PCI Master/Target Abort
ohci_dump (ohci, 1);
......@@ -579,7 +603,8 @@ static void ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
*/
spin_lock (&ohci->lock);
if (ohci->ed_rm_list)
finish_unlinks (ohci, le16_to_cpu (ohci->hcca->frame_no), ptregs);
finish_unlinks (ohci, le16_to_cpu (ohci->hcca->frame_no),
ptregs);
if ((ints & OHCI_INTR_SF) != 0 && !ohci->ed_rm_list)
writel (OHCI_INTR_SF, &regs->intrdisable);
spin_unlock (&ohci->lock);
......@@ -594,7 +619,7 @@ static void ohci_stop (struct usb_hcd *hcd)
{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
dev_dbg (hcd->controller, "stop %s controller%s\n",
ohci_dbg (ohci, "stop %s controller%s\n",
hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS),
ohci->disabled ? " (disabled)" : ""
);
......@@ -629,8 +654,8 @@ static int hc_restart (struct ohci_hcd *ohci)
ohci->disabled = 1;
ohci->sleeping = 0;
if (ohci->hcd.self.root_hub)
usb_disconnect (&ohci->hcd.self.root_hub);
if (hcd_to_bus (&ohci->hcd)->root_hub)
usb_disconnect (&hcd_to_bus (&ohci->hcd)->root_hub);
/* empty the interrupt branches */
for (i = 0; i < NUM_INTS; i++) ohci->load [i] = 0;
......@@ -644,18 +669,16 @@ static int hc_restart (struct ohci_hcd *ohci)
ohci->ed_bulktail = NULL;
if ((temp = hc_reset (ohci)) < 0 || (temp = hc_start (ohci)) < 0) {
err ("can't restart %s, %d", ohci->hcd.self.bus_name, temp);
ohci_err (ohci, "can't restart, %d\n", temp);
return temp;
} else
dbg ("restart %s completed", ohci->hcd.self.bus_name);
ohci_dbg (ohci, "restart complete\n");
return 0;
}
#endif
/*-------------------------------------------------------------------------*/
static const char hcd_name [] = "ohci-hcd";
#define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC
MODULE_AUTHOR (DRIVER_AUTHOR);
......
......@@ -5,7 +5,6 @@
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
*
* This file is licenced under GPL
* $Id: ohci-hub.c,v 1.3 2002/03/22 16:04:54 dbrownell Exp $
*/
/*-------------------------------------------------------------------------*/
......@@ -41,7 +40,7 @@ static u32 roothub_portstatus (struct ohci_hcd *hc, int i)
/*-------------------------------------------------------------------------*/
#define dbg_port(hc,label,num,value) \
dev_dbg (hc->hcd.controller, \
ohci_dbg (hc, \
"%s roothub.portstatus [%d] " \
"= 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s\n", \
label, num, temp, \
......@@ -76,9 +75,8 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
if (ports > MAX_ROOT_PORTS) {
if (ohci->disabled)
return -ESHUTDOWN;
err ("%s bogus NDP=%d, rereads as NDP=%d",
hcd->self.bus_name, ports,
readl (&ohci->regs->roothub.a) & RH_A_NDP);
ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n",
ports, readl (&ohci->regs->roothub.a) & RH_A_NDP);
/* retry later; "should not happen" */
return 0;
}
......@@ -159,7 +157,7 @@ static int ohci_hub_control (
u16 wLength
) {
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
int ports = hcd->self.root_hub->maxchild;
int ports = hcd_to_bus (hcd)->root_hub->maxchild;
u32 temp;
int retval = 0;
......
......@@ -115,8 +115,8 @@ td_free (struct ohci_hcd *hc, struct td *td)
prev = &(*prev)->td_hash;
if (*prev)
*prev = td->td_hash;
else
dev_dbg (hc->hcd.controller, "bad hash for td %p\n", td);
else if ((td->hwINFO & TD_DONE) != 0)
ohci_dbg (hc, "no hash for td %p\n", td);
pci_pool_free (hc->td_cache, td, td->td_dma);
}
......
......@@ -29,17 +29,6 @@
/*-------------------------------------------------------------------------*/
struct ohci_hcd *dev_to_ohci(struct device *dev) {
struct pci_dev *pdev =
container_of (dev, struct pci_dev, dev);
struct ohci_hcd *ohci =
container_of (pci_get_drvdata (pdev), struct ohci_hcd, hcd);
return ohci;
}
/*-------------------------------------------------------------------------*/
static int __devinit
ohci_pci_start (struct usb_hcd *hcd)
{
......@@ -55,22 +44,43 @@ ohci_pci_start (struct usb_hcd *hcd)
/* AMD 756, for most chips (early revs), corrupts register
* values on read ... so enable the vendor workaround.
*/
if (hcd->pdev->vendor == 0x1022
if (hcd->pdev->vendor == PCI_VENDOR_ID_AMD
&& hcd->pdev->device == 0x740c) {
ohci->flags = OHCI_QUIRK_AMD756;
info ("%s: AMD756 erratum 4 workaround",
hcd->self.bus_name);
ohci_info (ohci, "AMD756 erratum 4 workaround\n");
}
/* FIXME for some of the early AMD 760 southbridges, OHCI
* won't work at all. blacklist them.
*/
/* Apple's OHCI driver has a lot of bizarre workarounds
* for this chip. Evidently control and bulk lists
* can get confused. (B&W G3 models, and ...)
*/
else if (hcd->pdev->vendor == 0x1045
else if (hcd->pdev->vendor == PCI_VENDOR_ID_OPTI
&& hcd->pdev->device == 0xc861) {
info ("%s: WARNING: OPTi workarounds unavailable",
hcd->self.bus_name);
ohci_info (ohci,
"WARNING: OPTi workarounds unavailable\n");
}
/* Check for NSC87560. We have to look at the bridge (fn1) to
* identify the USB (fn2). This quirk might apply to more or
* even all NSC stuff.
*/
else if (hcd->pdev->vendor == PCI_VENDOR_ID_NS) {
struct pci_dev *b, *hc;
hc = hcd->pdev;
b = pci_find_slot (hc->bus->number,
PCI_DEVFN (PCI_SLOT (hc->devfn), 1));
if (b && b->device == PCI_DEVICE_ID_NS_87560_LIO
&& b->vendor == PCI_VENDOR_ID_NS) {
ohci->flags |= OHCI_QUIRK_SUPERIO;
ohci_info (ohci, "Using NSC SuperIO setup\n");
}
}
}
memset (ohci->hcca, 0, sizeof (struct ohci_hcca));
......@@ -86,7 +96,7 @@ ohci_pci_start (struct usb_hcd *hcd)
}
if (hc_start (ohci) < 0) {
err ("can't start %s", ohci->hcd.self.bus_name);
ohci_err (ohci, "can't start\n");
ohci_stop (hcd);
return -EBUSY;
}
......@@ -106,13 +116,13 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, u32 state)
u16 cmd;
if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) {
dbg ("can't suspend %s (state is %s)", hcd->self.bus_name,
ohci_dbg (ohci, "can't suspend (state is %s)\n",
hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS));
return -EIO;
}
/* act as if usb suspend can always be used */
dbg ("%s: suspend to %d", hcd->self.bus_name, state);
ohci_dbg (ohci, "suspend to %d\n", state);
ohci->sleeping = 1;
/* First stop processing */
......@@ -147,16 +157,16 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, u32 state)
switch (readl (&ohci->regs->control) & OHCI_CTRL_HCFS) {
case OHCI_USB_RESET:
dbg ("%s suspend->reset ?", hcd->self.bus_name);
ohci_dbg (ohci, "suspend->reset ?\n");
break;
case OHCI_USB_RESUME:
dbg ("%s suspend->resume ?", hcd->self.bus_name);
ohci_dbg (ohci, "suspend->resume ?\n");
break;
case OHCI_USB_OPER:
dbg ("%s suspend->operational ?", hcd->self.bus_name);
ohci_dbg (ohci, "suspend->operational ?\n");
break;
case OHCI_USB_SUSPEND:
dbg ("%s suspended", hcd->self.bus_name);
ohci_dbg (ohci, "suspended\n");
break;
}
......@@ -204,7 +214,7 @@ static int ohci_pci_resume (struct usb_hcd *hcd)
#ifdef DEBUG
/* the registers may look crazy here */
ohci_dump_status (ohci);
ohci_dump_status (ohci, 0, 0);
#endif
/* Re-enable bus mastering */
......@@ -213,13 +223,13 @@ static int ohci_pci_resume (struct usb_hcd *hcd)
switch (temp) {
case OHCI_USB_RESET: // lost power
info ("USB restart: %s", hcd->self.bus_name);
ohci_info (ohci, "USB restart\n");
retval = hc_restart (ohci);
break;
case OHCI_USB_SUSPEND: // host wakeup
case OHCI_USB_RESUME: // remote wakeup
info ("USB continue: %s from %s wakeup", hcd->self.bus_name,
ohci_info (ohci, "USB continue from %s wakeup\n",
(temp == OHCI_USB_SUSPEND)
? "host" : "remote");
ohci->hc_control = OHCI_USB_RESUME;
......@@ -232,7 +242,7 @@ static int ohci_pci_resume (struct usb_hcd *hcd)
temp = readl (&ohci->regs->control);
temp = ohci->hc_control & OHCI_CTRL_HCFS;
if (temp != OHCI_USB_RESUME) {
err ("controller %s won't resume", hcd->self.bus_name);
ohci_err (ohci, "controller won't resume\n");
ohci->disabled = 1;
retval = -EIO;
break;
......@@ -278,11 +288,12 @@ static int ohci_pci_resume (struct usb_hcd *hcd)
writel (OHCI_BLF | OHCI_CLF, &ohci->regs->cmdstatus);
// ohci_dump_status (ohci);
dbg ("sleeping = %d, disabled = %d", ohci->sleeping, ohci->disabled);
ohci_dbg (ohci, "sleeping = %d, disabled = %d\n",
ohci->sleeping, ohci->disabled);
break;
default:
warn ("odd PCI resume for %s", hcd->self.bus_name);
ohci_warn (ohci, "odd PCI resume\n");
}
return retval;
}
......@@ -373,11 +384,11 @@ static struct pci_driver ohci_pci_driver = {
static int __init ohci_hcd_pci_init (void)
{
dbg (DRIVER_INFO " (PCI)");
printk (KERN_DEBUG "%s: " DRIVER_INFO " (PCI)\n", hcd_name);
if (usb_disabled())
return -ENODEV;
dbg ("block sizes: ed %d td %d",
printk (KERN_DEBUG "%s: block sizes: ed %d td %d\n", hcd_name,
sizeof (struct ed), sizeof (struct td));
return pci_module_init (&ohci_pci_driver);
}
......
......@@ -30,29 +30,28 @@ static void urb_free_priv (struct ohci_hcd *hc, urb_priv_t *urb_priv)
/*
* URB goes back to driver, and isn't reissued.
* It's completely gone from HC data structures.
* PRECONDITION: no locks held (Giveback can call into HCD.)
* PRECONDITION: no locks held, irqs blocked (Giveback can call into HCD.)
*/
static void finish_urb (struct ohci_hcd *ohci, struct urb *urb, struct pt_regs *regs)
static void
finish_urb (struct ohci_hcd *ohci, struct urb *urb, struct pt_regs *regs)
{
unsigned long flags;
// ASSERT (urb->hcpriv != 0);
urb_free_priv (ohci, urb->hcpriv);
urb->hcpriv = NULL;
spin_lock_irqsave (&urb->lock, flags);
spin_lock (&urb->lock);
if (likely (urb->status == -EINPROGRESS))
urb->status = 0;
spin_unlock_irqrestore (&urb->lock, flags);
spin_unlock (&urb->lock);
// what lock protects these?
switch (usb_pipetype (urb->pipe)) {
case PIPE_ISOCHRONOUS:
ohci->hcd.self.bandwidth_isoc_reqs--;
hcd_to_bus (&ohci->hcd)->bandwidth_isoc_reqs--;
break;
case PIPE_INTERRUPT:
ohci->hcd.self.bandwidth_int_reqs--;
hcd_to_bus (&ohci->hcd)->bandwidth_int_reqs--;
break;
}
......@@ -110,12 +109,9 @@ static void periodic_link (struct ohci_hcd *ohci, struct ed *ed)
{
unsigned i;
#ifdef OHCI_VERBOSE_DEBUG
dbg ("%s: link %sed %p branch %d [%dus.], interval %d",
ohci->hcd.self.bus_name,
ohci_vdbg (ohci, "link %sed %p branch %d [%dus.], interval %d\n",
(ed->hwINFO & ED_ISO) ? "iso " : "",
ed, ed->branch, ed->load, ed->interval);
#endif
for (i = ed->branch; i < NUM_INTS; i += ed->interval) {
struct ed **prev = &ohci->periodic [i];
......@@ -143,7 +139,7 @@ static void periodic_link (struct ohci_hcd *ohci, struct ed *ed)
}
ohci->load [i] += ed->load;
}
ohci->hcd.self.bandwidth_allocated += ed->load / ed->interval;
hcd_to_bus (&ohci->hcd)->bandwidth_allocated += ed->load / ed->interval;
}
/* link an ed into one of the HC chains */
......@@ -206,7 +202,7 @@ static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed)
default:
branch = balance (ohci, ed->interval, ed->load);
if (branch < 0) {
dev_dbg (ohci->hcd.controller,
ohci_dbg (ohci,
"ERR %d, interval %d msecs, load %d\n",
branch, ed->interval, ed->load);
// FIXME if there are TDs queued, fail them!
......@@ -244,14 +240,11 @@ static void periodic_unlink (struct ohci_hcd *ohci, struct ed *ed)
}
ohci->load [i] -= ed->load;
}
ohci->hcd.self.bandwidth_allocated -= ed->load / ed->interval;
hcd_to_bus (&ohci->hcd)->bandwidth_allocated -= ed->load / ed->interval;
#ifdef OHCI_VERBOSE_DEBUG
dbg ("%s: unlink %sed %p branch %d [%dus.], interval %d",
ohci->hcd.self.bus_name,
ohci_vdbg (ohci, "unlink %sed %p branch %d [%dus.], interval %d\n",
(ed->hwINFO & ED_ISO) ? "iso " : "",
ed, ed->branch, ed->load, ed->interval);
#endif
}
/* unlink an ed from one of the HC chains.
......@@ -576,7 +569,7 @@ static void td_submit_urb (
*/
case PIPE_INTERRUPT:
/* ... and periodic urbs have extra accounting */
ohci->hcd.self.bandwidth_int_reqs++;
hcd_to_bus (&ohci->hcd)->bandwidth_int_reqs++;
/* FALLTHROUGH */
case PIPE_BULK:
info = is_out
......@@ -644,7 +637,7 @@ static void td_submit_urb (
data + urb->iso_frame_desc [cnt].offset,
urb->iso_frame_desc [cnt].length, urb, cnt);
}
ohci->hcd.self.bandwidth_isoc_reqs++;
hcd_to_bus (&ohci->hcd)->bandwidth_isoc_reqs++;
break;
}
// ASSERT (urb_priv->length == cnt);
......@@ -687,11 +680,10 @@ static void td_done (struct urb *urb, struct td *td)
urb->iso_frame_desc [td->index].actual_length = dlen;
urb->iso_frame_desc [td->index].status = cc_to_error [cc];
#ifdef VERBOSE_DEBUG
if (cc != TD_CC_NOERROR)
dbg (" urb %p iso TD %p (%d) len %d CC %d",
ohci_vdbg (ohci,
"urb %p iso td %p (%d) len %d cc %d\n",
urb, td, 1 + td->index, dlen, cc);
#endif
/* BULK, INT, CONTROL ... drivers see aggregate length/status,
* except that "setup" bytes aren't counted and "short" transfers
......@@ -730,13 +722,12 @@ static void td_done (struct urb *urb, struct td *td)
- td->data_dma;
}
#ifdef VERBOSE_DEBUG
if (cc != TD_CC_NOERROR && cc < 0x0E)
dbg (" urb %p TD %p (%d) CC %d, len=%d/%d",
ohci_vdbg (ohci,
"urb %p td %p (%d) cc %d, len=%d/%d\n",
urb, td, 1 + td->index, cc,
urb->actual_length,
urb->transfer_buffer_length);
#endif
}
}
......@@ -791,14 +782,18 @@ ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev)
ed->hwHeadP = next->hwNextTD | toggle;
}
/* help for troubleshooting: */
dev_dbg (&urb->dev->dev,
"urb %p usb-%s-%s ep-%d-%s cc %d --> status %d\n",
urb,
urb->dev->bus->bus_name, urb->dev->devpath,
usb_pipeendpoint (urb->pipe),
usb_pipein (urb->pipe) ? "IN" : "OUT",
cc, cc_to_error [cc]);
/* help for troubleshooting: report anything that
* looks odd ... that doesn't include protocol stalls
* (or maybe some other things)
*/
if (cc != TD_CC_STALL || !usb_pipecontrol (urb->pipe))
ohci_dbg (ohci,
"urb %p path %s ep%d%s %08x cc %d --> status %d\n",
urb, urb->dev->devpath,
usb_pipeendpoint (urb->pipe),
usb_pipein (urb->pipe) ? "in" : "out",
le32_to_cpu (td->hwINFO),
cc, cc_to_error [cc]);
return rev;
}
......@@ -826,8 +821,7 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci)
td = dma_to_td (ohci, td_dma);
if (!td) {
err ("%s bad entry %8x",
ohci->hcd.self.bus_name, td_dma);
ohci_err (ohci, "bad entry %8x\n", td_dma);
break;
}
......@@ -855,7 +849,8 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci)
#define tick_before(t1,t2) ((((s16)(t1))-((s16)(t2))) < 0)
/* there are some urbs/eds to unlink; called in_irq(), with HCD locked */
static void finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *regs)
static void
finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *regs)
{
struct ed *ed, **last;
......@@ -983,7 +978,8 @@ static void finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *reg
* path is finish_unlinks(), which unlinks URBs using ed_rm_list, instead of
* scanning the (re-reversed) donelist as this does.
*/
static void dl_done_list (struct ohci_hcd *ohci, struct td *td, struct pt_regs *regs)
static void
dl_done_list (struct ohci_hcd *ohci, struct td *td, struct pt_regs *regs)
{
unsigned long flags;
......@@ -1000,9 +996,9 @@ static void dl_done_list (struct ohci_hcd *ohci, struct td *td, struct pt_regs *
/* If all this urb's TDs are done, call complete() */
if (urb_priv->td_cnt == urb_priv->length) {
spin_unlock_irqrestore (&ohci->lock, flags);
spin_unlock (&ohci->lock);
finish_urb (ohci, urb, regs);
spin_lock_irqsave (&ohci->lock, flags);
spin_lock (&ohci->lock);
}
/* clean schedule: unlink EDs that are no longer busy */
......
......@@ -3,7 +3,7 @@
*
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
* (C) Hewlett-Packard Company
* (C) Copyright 2002 Hewlett-Packard Company
*
* SA1111 Bus Glue
*
......@@ -27,14 +27,6 @@ extern int usb_disabled(void);
/*-------------------------------------------------------------------------*/
struct ohci_hcd *dev_to_ohci(struct device *dev) {
struct usb_hcd *hcd = dev->driver_data;
return hcd_to_ohci(hcd);
}
/*-------------------------------------------------------------------------*/
static void sa1111_start_hc(struct sa1111_dev *dev)
{
unsigned int usb_rst = 0;
......
......@@ -372,6 +372,7 @@ struct ohci_hcd {
unsigned long flags; /* for HC bugs */
#define OHCI_QUIRK_AMD756 0x01 /* erratum #4 */
#define OHCI_QUIRK_SUPERIO 0x02 /* natsemi */
// there are also chip quirks/bugs in init logic
/*
......@@ -382,4 +383,24 @@ struct ohci_hcd {
#define hcd_to_ohci(hcd_ptr) container_of(hcd_ptr, struct ohci_hcd, hcd)
struct ohci_hcd *dev_to_ohci(struct device *);
/*-------------------------------------------------------------------------*/
#ifndef DEBUG
#define STUB_DEBUG_FILES
#endif /* DEBUG */
#define ohci_dbg(ohci, fmt, args...) \
dev_dbg ((ohci)->hcd.controller , fmt , ## args )
#define ohci_err(ohci, fmt, args...) \
dev_err ((ohci)->hcd.controller , fmt , ## args )
#define ohci_info(ohci, fmt, args...) \
dev_info ((ohci)->hcd.controller , fmt , ## args )
#define ohci_warn(ohci, fmt, args...) \
dev_warn ((ohci)->hcd.controller , fmt , ## args )
#ifdef OHCI_VERBOSE_DEBUG
# define ohci_vdbg ohci_dbg
#else
# define ohci_vdbg(ohci, fmt, args...) do { } while (0)
#endif
/* -*- linux-c -*- */
/*
* Driver for USB Scanners (linux-2.5.60)
* Driver for USB Scanners (linux-2.5.64)
*
* Copyright (C) 1999, 2000, 2001, 2002 David E. Nelson
* Copyright (C) 2002, 2003 Henning Meier-Geinitz
......@@ -346,6 +346,11 @@
* - Print ids and device number when a device was detected.
* - Don't print errors when the device is busy.
*
* 0.4.11 2003-02-25
* - Added vendor/product ids for Artec, Avision, Brother, Medion, Primax,
* Prolink, Fujitsu, Plustek, and SYSCAN scanners.
* - Fixed generation of devfs names if dynamic minors are disabled.
*
* TODO
* - Performance
* - Select/poll methods
......@@ -1052,7 +1057,7 @@ probe_scanner(struct usb_interface *intf,
scn->scn_minor = scn_minor;
scn->isopen = 0;
sprintf(name, "scanner%d", scn->scn_minor);
sprintf(name, "scanner%d", scn->scn_minor - SCN_BASE_MNR);
scn->devfs = devfs_register(usb_devfs_handle, name,
DEVFS_FL_DEFAULT, USB_MAJOR,
......
/*
* Driver for USB Scanners (linux-2.5.60)
* Driver for USB Scanners (linux-2.5.64)
*
* Copyright (C) 1999, 2000, 2001, 2002 David E. Nelson
* Previously maintained by Brian Beattie
......@@ -44,7 +44,7 @@
// #define DEBUG
#define DRIVER_VERSION "0.4.10"
#define DRIVER_VERSION "0.4.11"
#define DRIVER_DESC "USB Scanner Driver"
#include <linux/usb.h>
......@@ -99,7 +99,13 @@ static struct usb_device_id scanner_device_ids [] = {
/* Artec */
{ USB_DEVICE(0x05d8, 0x4001) }, /* Ultima 2000 */
{ USB_DEVICE(0x05d8, 0x4002) }, /* Ultima 2000 (GT6801 based) */
{ USB_DEVICE(0x05d8, 0x4003) }, /* E+ 48U */
{ USB_DEVICE(0x05d8, 0x4004) }, /* E+ Pro */
/* Avision */
{ USB_DEVICE(0x0638, 0x0a10) }, /* iVina FB1600 (=Umax Astra 4500) */
/* Benq: see Acer */
/* Brother */
{ USB_DEVICE(0x04f9, 0x0111) }, /* MFC 6800 */
/* Canon */
{ USB_DEVICE(0x04a9, 0x2201) }, /* CanoScan FB320U */
{ USB_DEVICE(0x04a9, 0x2202) }, /* CanoScan FB620U */
......@@ -117,6 +123,10 @@ static struct usb_device_id scanner_device_ids [] = {
/* Compaq */
{ USB_DEVICE(0x049f, 0x0021) }, /* S200 */
/* Epson -- See Seiko/Epson below */
/* Fujitsu */
{ USB_DEVICE(0x04c5, 0x1041) }, /* fi-4220c USB/SCSI info:mza@mu-tec.de */
{ USB_DEVICE(0x04c5, 0x1042) }, /* fi-4120c USB/SCSI info:mza@mu-tec.de */
{ USB_DEVICE(0x04c5, 0x1029) }, /* fi-4010c USB AVision info:mza@mu-tec.de */
/* Genius */
{ USB_DEVICE(0x0458, 0x2001) }, /* ColorPage Vivid Pro */
{ USB_DEVICE(0x0458, 0x2007) }, /* ColorPage HR6 V2 */
......@@ -149,6 +159,8 @@ static struct usb_device_id scanner_device_ids [] = {
{ USB_DEVICE(0x0638, 0x0268) }, /* 1200U */
/* Lexmark */
{ USB_DEVICE(0x043d, 0x002d) }, /* X70/X73 */
/* Medion */
{ USB_DEVICE(0x0461, 0x0377) }, /* MD 5345 - repackaged Primax? */
/* Memorex */
{ USB_DEVICE(0x0461, 0x0346) }, /* 6136u - repackaged Primax ? */
/* Microtek */
......@@ -202,7 +214,8 @@ static struct usb_device_id scanner_device_ids [] = {
{ USB_DEVICE(0x07b3, 0x0015) }, /* OpticPro U24 */
{ USB_DEVICE(0x07b3, 0x0016) }, /* Unknown */
{ USB_DEVICE(0x07b3, 0x0017) }, /* OpticPro UT12/UT16/UT24 */
{ USB_DEVICE(0x07b3, 0x0401) }, /* OpticPro 1248U */
{ USB_DEVICE(0x07b3, 0x0400) }, /* OpticPro 1248U */
{ USB_DEVICE(0x07b3, 0x0401) }, /* OpticPro 1248U (another one) */
/* Primax/Colorado */
{ USB_DEVICE(0x0461, 0x0300) }, /* G2-300 #1 */
{ USB_DEVICE(0x0461, 0x0301) }, /* G2E-300 #1 */
......@@ -210,12 +223,15 @@ static struct usb_device_id scanner_device_ids [] = {
{ USB_DEVICE(0x0461, 0x0303) }, /* G2E-300 #2 */
{ USB_DEVICE(0x0461, 0x0340) }, /* Colorado USB 9600 */
{ USB_DEVICE(0x0461, 0x0341) }, /* Colorado 600u */
{ USB_DEVICE(0x0461, 0x0347) }, /* Primascan Colorado 2600u */
{ USB_DEVICE(0x0461, 0x0360) }, /* Colorado USB 19200 */
{ USB_DEVICE(0x0461, 0x0361) }, /* Colorado 1200u */
{ USB_DEVICE(0x0461, 0x0380) }, /* G2-600 #1 */
{ USB_DEVICE(0x0461, 0x0381) }, /* ReadyScan 636i */
{ USB_DEVICE(0x0461, 0x0382) }, /* G2-600 #2 */
{ USB_DEVICE(0x0461, 0x0383) }, /* G2E-600 */
/* Prolink */
{ USB_DEVICE(0x06dc, 0x0014) }, /* Winscan Pro 2448U */
/* Relisis */
// { USB_DEVICE(0x0475, 0x0103) }, /* Episode - undetected endpoint */
/* Seiko/Epson Corp. */
......@@ -241,6 +257,8 @@ static struct usb_device_id scanner_device_ids [] = {
{ USB_DEVICE(0x04b8, 0x011e) }, /* Perfection 1660 Photo */
{ USB_DEVICE(0x04b8, 0x0801) }, /* Stylus CX5200 */
{ USB_DEVICE(0x04b8, 0x0802) }, /* Stylus CX3200 */
/* SYSCAN */
{ USB_DEVICE(0x0a82, 0x4600) }, /* TravelScan 460/464 */
/* Umax */
{ USB_DEVICE(0x1606, 0x0010) }, /* Astra 1220U */
{ USB_DEVICE(0x1606, 0x0030) }, /* Astra 2000U */
......
......@@ -159,6 +159,20 @@ config USB_WACOM
The module will be called wacom. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
config USB_KBTAB
tristate "KB Gear JamStudio tablet support"
depends on USB && INPUT
help
Say Y here if you want to use the USB version of the KB Gear
JamStudio tablet. Make sure to say Y to "Mouse support"
(CONFIG_INPUT_MOUSEDEV) and/or "Event interface support"
(CONFIG_INPUT_EVDEV) as well.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called kbtab.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
config USB_POWERMATE
tristate "Griffin PowerMate and Contour Jog support"
depends on USB && INPUT
......
......@@ -31,5 +31,6 @@ obj-$(CONFIG_USB_HID) += hid.o
obj-$(CONFIG_USB_KBD) += usbkbd.o
obj-$(CONFIG_USB_MOUSE) += usbmouse.o
obj-$(CONFIG_USB_WACOM) += wacom.o
obj-$(CONFIG_USB_KBTAB) += kbtab.o
obj-$(CONFIG_USB_POWERMATE) += powermate.o
obj-$(CONFIG_USB_XPAD) += xpad.o
......@@ -1304,6 +1304,10 @@ void hid_init_reports(struct hid_device *hid)
#define USB_DEVICE_ID_WACOM_PL 0x0030
#define USB_DEVICE_ID_WACOM_INTUOS2 0x0040
#define USB_VENDOR_ID_KBGEAR 0x084e
#define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001
#define USB_VENDOR_ID_AIPTEK 0x08ca
#define USB_DEVICE_ID_AIPTEK_6000 0x0020
......@@ -1355,6 +1359,7 @@ struct hid_blacklist {
{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 3, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 4, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 5, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_6000, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE },
......
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/usb.h>
/*
* Version Information
* v0.0.1 - Original, extremely basic version, 2.4.xx only
* v0.0.2 - Updated, works with 2.5.62 and 2.4.20;
* - added pressure-threshold modules param code from
* Alex Perry <alex.perry@ieee.org>
*/
#define DRIVER_VERSION "v0.0.2"
#define DRIVER_AUTHOR "Josh Myer <josh@joshisanerd.com>"
#define DRIVER_DESC "USB KB Gear JamStudio Tablet driver"
#define DRIVER_LICENSE "GPL"
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE(DRIVER_LICENSE);
#define USB_VENDOR_ID_KBGEAR 0x084e
static int kb_pressure_click = 0x10;
MODULE_PARM (kb_pressure_click,"i");
MODULE_PARM_DESC(kb_pressure_click,
"pressure threshold for clicks");
struct kbtab {
signed char *data;
dma_addr_t data_dma;
struct input_dev dev;
struct usb_device *usbdev;
struct urb *irq;
int open;
int x, y;
int button;
int pressure;
__u32 serial[2];
char phys[32];
};
static void kbtab_irq(struct urb *urb, struct pt_regs *regs)
{
struct kbtab *kbtab = urb->context;
unsigned char *data = kbtab->data;
struct input_dev *dev = &kbtab->dev;
int retval;
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", __FUNCTION__, urb->status);
return;
default:
dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
goto exit;
}
kbtab->x = (data[2] << 8) + data[1];
kbtab->y = (data[4] << 8) + data[3];
kbtab->pressure = (data[5]);
input_report_key(dev, BTN_TOOL_PEN, 1);
input_report_abs(dev, ABS_X, kbtab->x);
input_report_abs(dev, ABS_Y, kbtab->y);
/*input_report_abs(dev, ABS_PRESSURE, kbtab->pressure);*/
/*input_report_key(dev, BTN_TOUCH , data[0] & 0x01);*/
input_report_key(dev, BTN_RIGHT, data[0] & 0x02);
input_report_key(dev, BTN_LEFT, (kbtab->pressure > kb_pressure_click) ? 1 : 0);
input_sync(dev);
exit:
retval = usb_submit_urb (urb, GFP_ATOMIC);
if (retval)
err ("%s - usb_submit_urb failed with result %d",
__FUNCTION__, retval);
}
struct usb_device_id kbtab_ids[] = {
{ USB_DEVICE(USB_VENDOR_ID_KBGEAR, 0x1001), driver_info : 0 },
{ }
};
MODULE_DEVICE_TABLE(usb, kbtab_ids);
static int kbtab_open(struct input_dev *dev)
{
struct kbtab *kbtab = dev->private;
if (kbtab->open++)
return 0;
kbtab->irq->dev = kbtab->usbdev;
if (usb_submit_urb(kbtab->irq, GFP_KERNEL))
return -EIO;
return 0;
}
static void kbtab_close(struct input_dev *dev)
{
struct kbtab *kbtab = dev->private;
if (!--kbtab->open)
usb_unlink_urb(kbtab->irq);
}
static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_device *dev = interface_to_usbdev(intf);
struct usb_endpoint_descriptor *endpoint;
struct kbtab *kbtab;
char path[64];
if (!(kbtab = kmalloc(sizeof(struct kbtab), GFP_KERNEL)))
return -ENOMEM;
memset(kbtab, 0, sizeof(struct kbtab));
kbtab->data = usb_buffer_alloc(dev, 8, SLAB_ATOMIC, &kbtab->data_dma);
if (!kbtab->data) {
kfree(kbtab);
return -ENOMEM;
}
kbtab->irq = usb_alloc_urb(0, GFP_KERNEL);
if (!kbtab->irq) {
usb_buffer_free(dev, 10, kbtab->data, kbtab->data_dma);
kfree(kbtab);
return -ENOMEM;
}
kbtab->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_MSC);
kbtab->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
kbtab->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
kbtab->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH);
kbtab->dev.mscbit[0] |= BIT(MSC_SERIAL);
kbtab->dev.absmax[ABS_X] = 0x2000;
kbtab->dev.absmax[ABS_Y] = 0x1750;
kbtab->dev.absmax[ABS_PRESSURE] = 0xff;
kbtab->dev.absfuzz[ABS_X] = 4;
kbtab->dev.absfuzz[ABS_Y] = 4;
kbtab->dev.private = kbtab;
kbtab->dev.open = kbtab_open;
kbtab->dev.close = kbtab_close;
usb_make_path(dev, path, 64);
sprintf(kbtab->phys, "%s/input0", path);
kbtab->dev.name = "KB Gear Tablet";
kbtab->dev.phys = kbtab->phys;
kbtab->dev.id.bustype = BUS_USB;
kbtab->dev.id.vendor = dev->descriptor.idVendor;
kbtab->dev.id.product = dev->descriptor.idProduct;
kbtab->dev.id.version = dev->descriptor.bcdDevice;
kbtab->usbdev = dev;
endpoint = &intf->altsetting[0].endpoint[0].desc;
usb_fill_int_urb(kbtab->irq, dev,
usb_rcvintpipe(dev, endpoint->bEndpointAddress),
kbtab->data, 8,
kbtab_irq, kbtab, endpoint->bInterval);
kbtab->irq->transfer_dma = kbtab->data_dma;
kbtab->irq->transfer_flags |= URB_NO_DMA_MAP;
input_register_device(&kbtab->dev);
printk(KERN_INFO "input: KB Gear Tablet on %s\n", path);
usb_set_intfdata(intf, kbtab);
return 0;
}
static void kbtab_disconnect(struct usb_interface *intf)
{
struct kbtab *kbtab = usb_get_intfdata (intf);
usb_set_intfdata(intf, NULL);
if (kbtab) {
usb_unlink_urb(kbtab->irq);
input_unregister_device(&kbtab->dev);
usb_free_urb(kbtab->irq);
usb_buffer_free(interface_to_usbdev(intf), 10, kbtab->data, kbtab->data_dma);
kfree(kbtab);
}
}
static struct usb_driver kbtab_driver = {
.name = "kbtab",
.probe = kbtab_probe,
.disconnect = kbtab_disconnect,
.id_table = kbtab_ids,
};
static int __init kbtab_init(void)
{
usb_register(&kbtab_driver);
info(DRIVER_VERSION ":" DRIVER_DESC);
return 0;
}
static void __exit kbtab_exit(void)
{
usb_deregister(&kbtab_driver);
}
module_init(kbtab_init);
module_exit(kbtab_exit);
This diff is collapsed.
......@@ -552,6 +552,7 @@ static int ch9_postconfig (struct usbtest_dev *dev)
* (b) protocol stalls (control-only) will autorecover.
* it's quite not like bulk/intr; no halt clearing.
* (c) short control reads are reported and handled.
* (d) queues are always processed in-order
*/
struct ctrl_ctx {
......@@ -563,66 +564,68 @@ struct ctrl_ctx {
int status;
struct urb **urb;
struct usbtest_param *param;
int last;
};
#define NUM_SUBCASES 13 /* how many test subcases here? */
struct subcase {
struct usb_ctrlrequest setup;
int number;
int expected;
};
static void ctrl_complete (struct urb *urb, struct pt_regs *regs)
{
struct ctrl_ctx *ctx = urb->context;
struct usb_ctrlrequest *reqp;
struct subcase *subcase;
int status = urb->status;
reqp = (struct usb_ctrlrequest *)urb->setup_packet;
subcase = container_of (reqp, struct subcase, setup);
spin_lock (&ctx->lock);
ctx->count--;
ctx->pending--;
/* FIXME verify that the completions are in the right sequence.
* we could store the test number with the setup packet, that
* buffer has extra space.
/* queue must transfer and complete in fifo order, unless
* usb_unlink_urb() is used to unlink something not at the
* physical queue head (not tested).
*/
switch (status) {
case 0: /* success */
case -EREMOTEIO: /* short read */
if (reqp->bRequestType == (USB_DIR_IN|USB_RECIP_DEVICE)
&& reqp->bRequest == USB_REQ_GET_DESCRIPTOR
&& ((le16_to_cpu (reqp->wValue) >> 8)
== USB_DT_DEVICE)) {
if (reqp->wLength > USB_DT_DEVICE_SIZE
&& status == -EREMOTEIO)
status = 0;
else if (reqp->wLength == USB_DT_DEVICE_SIZE
&& status != 0)
status = -EIO;
if (status)
goto error;
if (subcase->number > 0) {
if ((subcase->number - ctx->last) != 1) {
dbg ("subcase %d completed out of order, last %d",
subcase->number, ctx->last);
status = -EDOM;
goto error;
}
break;
case -ECONNRESET: /* async unlink */
break;
case -EPIPE: /* (protocol) stall */
if (reqp->bRequestType == (USB_DIR_IN|USB_RECIP_INTERFACE)
&& reqp->bRequest == USB_REQ_GET_INTERFACE)
}
ctx->last = subcase->number;
/* succeed or fault in only one way? */
if (status == subcase->expected)
status = 0;
/* async unlink for cleanup? */
else if (status != -ECONNRESET) {
/* some faults are allowed, not required */
if (subcase->expected > 0 && (
((urb->status == -subcase->expected /* happened */
|| urb->status == 0)))) /* didn't */
status = 0;
else if (reqp->bRequestType == (USB_DIR_IN|USB_RECIP_DEVICE)
&& reqp->bRequest == USB_REQ_GET_DESCRIPTOR) {
switch (le16_to_cpu (reqp->wValue) >> 8) {
case USB_DT_DEVICE_QUALIFIER:
case USB_DT_OTHER_SPEED_CONFIG:
case USB_DT_INTERFACE:
case USB_DT_ENDPOINT:
status = 0;
}
} else if (reqp->bRequestType == USB_RECIP_ENDPOINT
&& reqp->bRequest == USB_REQ_CLEAR_FEATURE)
/* sometimes more than one fault is allowed */
else if (subcase->number == 12 && status == -EPIPE)
status = 0;
/* some stalls we plan on; others would be errors */
if (status == 0)
break;
/* else FALLTHROUGH */
else
dbg ("subtest %d error, status %d",
subcase->number, status);
}
/* unexpected status codes mean errors; ideally, in hardware */
if (status) {
error:
default: /* this fault's an error */
if (ctx->status == 0) {
int i;
......@@ -631,10 +634,8 @@ static void ctrl_complete (struct urb *urb, struct pt_regs *regs)
reqp->bRequestType, reqp->bRequest,
status, ctx->count);
/* FIXME use this "unlink everything" exit route
* in all cases, not just for fault cleanup.
* it'll be another test mode, but one that makes
* testing be more consistent.
/* FIXME this "unlink everything" exit route should
* be a separate test case.
*/
/* unlink whatever's still pending */
......@@ -688,6 +689,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
context.pending = 0;
context.status = -ENOMEM;
context.param = param;
context.last = -1;
/* allocate and init the urbs we'll queue.
* as with bulk/intr sglists, sglen is the queue depth; it also
......@@ -701,7 +703,9 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
int pipe = usb_rcvctrlpipe (udev, 0);
unsigned len;
struct urb *u;
struct usb_ctrlrequest req, *reqp;
struct usb_ctrlrequest req;
struct subcase *reqp;
int expected = 0;
/* requests here are mostly expected to succeed on any
* device, but some are chosen to trigger protocol stalls
......@@ -711,7 +715,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
req.bRequest = USB_REQ_GET_DESCRIPTOR;
req.bRequestType = USB_DIR_IN|USB_RECIP_DEVICE;
switch (i % 12 /* number of subtest cases here */) {
switch (i % NUM_SUBCASES) {
case 0: // get device descriptor
req.wValue = cpu_to_le16 (USB_DT_DEVICE << 8);
len = sizeof (struct usb_device_descriptor);
......@@ -725,6 +729,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
req.bRequestType = USB_DIR_IN|USB_RECIP_INTERFACE;
// index = 0 means first interface
len = 1;
expected = EPIPE;
break;
case 3: // get interface status
req.bRequest = USB_REQ_GET_STATUS;
......@@ -740,6 +745,8 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
case 5: // get device qualifier (MAY STALL)
req.wValue = cpu_to_le16 (USB_DT_DEVICE_QUALIFIER << 8);
len = sizeof (struct usb_qualifier_descriptor);
if (udev->speed != USB_SPEED_HIGH)
expected = EPIPE;
break;
case 6: // get first config descriptor, plus interface
req.wValue = cpu_to_le16 ((USB_DT_CONFIG << 8) | 0);
......@@ -750,6 +757,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
req.wValue = cpu_to_le16 (USB_DT_INTERFACE << 8);
// interface == 0
len = sizeof (struct usb_interface_descriptor);
expected = -EPIPE;
break;
// NOTE: two consecutive stalls in the queue here.
// that tests fault recovery a bit more aggressively.
......@@ -760,6 +768,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
// wIndex 0 == ep0 (shouldn't halt!)
len = 0;
pipe = usb_sndctrlpipe (udev, 0);
expected = EPIPE;
break;
case 9: // get endpoint status
req.bRequest = USB_REQ_GET_STATUS;
......@@ -770,18 +779,21 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
case 10: // trigger short read (EREMOTEIO)
req.wValue = cpu_to_le16 ((USB_DT_CONFIG << 8) | 0);
len = 1024;
expected = -EREMOTEIO;
break;
// NOTE: two consecutive _different_ faults in the queue.
case 11: // get endpoint descriptor (ALWAYS STALLS)
req.wValue = cpu_to_le16 (USB_DT_ENDPOINT << 8);
// endpoint == 0
len = sizeof (struct usb_interface_descriptor);
expected = -EPIPE;
break;
// NOTE: sometimes even a third fault in the queue!
case 12: // get string 0 descriptor (MAY STALL)
req.wValue = cpu_to_le16 (USB_DT_STRING << 8);
// string == 0, for language IDs
len = sizeof (struct usb_interface_descriptor);
expected = EREMOTEIO; // or EPIPE, if no strings
break;
default:
err ("bogus number of ctrl queue testcases!");
......@@ -793,12 +805,14 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
if (!u)
goto cleanup;
reqp = usb_buffer_alloc (udev, sizeof req, SLAB_KERNEL,
reqp = usb_buffer_alloc (udev, sizeof *reqp, SLAB_KERNEL,
&u->setup_dma);
if (!reqp)
goto cleanup;
*reqp = req;
u->setup_packet = (char *) reqp;
reqp->setup = req;
reqp->number = i % NUM_SUBCASES;
reqp->expected = expected;
u->setup_packet = (char *) &reqp->setup;
u->context = &context;
u->complete = ctrl_complete;
......@@ -839,6 +853,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
kfree (urb);
return context.status;
}
#undef NUM_SUBCASES
/*-------------------------------------------------------------------------*/
......@@ -886,7 +901,16 @@ static int unlink1 (struct usbtest_dev *dev, int pipe, int size, int async)
* hcd states and code paths, even with little other system load.
*/
wait_ms (jiffies % (2 * INTERRUPT_RATE));
retry:
retval = usb_unlink_urb (urb);
if (retval == -EBUSY) {
/* we can't unlink urbs while they're completing.
* "normal" drivers would prevent resubmission, but
* since we're testing unlink paths, we can't.
*/
dbg ("unlink retry");
goto retry;
}
if (!(retval == 0 || retval == -EINPROGRESS)) {
dbg ("submit/unlink fail %d", retval);
return retval;
......@@ -1309,7 +1333,13 @@ static struct usbtest_info ez2_info = {
.alt = 1,
};
/* ezusb family device with dedicated usb test firmware*/
/* ezusb family device with dedicated usb test firmware,
* or a peripheral running Linux and 'zero.c' test firmware.
*
* FIXME usbtest should read the descriptors, since compatible
* test firmware might run on hardware (pxa250 for one) that
* can't configure an ep2in-bulk.
*/
static struct usbtest_info fw_info = {
.name = "usb test device",
.ep_in = 2,
......
......@@ -144,6 +144,7 @@ static struct usb_serial_device_type belkin_device = {
struct belkin_sa_private {
spinlock_t lock;
unsigned long control_state;
unsigned char last_lsr;
unsigned char last_msr;
......@@ -175,6 +176,7 @@ static int belkin_sa_startup (struct usb_serial *serial)
if (!priv)
return (-1); /* error */
/* set initial values for control structures */
spin_lock_init(&priv->lock);
priv->control_state = 0;
priv->last_lsr = 0;
priv->last_msr = 0;
......@@ -262,6 +264,7 @@ static void belkin_sa_read_int_callback (struct urb *urb, struct pt_regs *regs)
struct usb_serial *serial;
unsigned char *data = urb->transfer_buffer;
int retval;
unsigned long flags;
switch (urb->status) {
case 0:
......@@ -289,6 +292,7 @@ static void belkin_sa_read_int_callback (struct urb *urb, struct pt_regs *regs)
/* ignore data[0] and data[1] */
priv = usb_get_serial_port_data(port);
spin_lock_irqsave(&priv->lock, flags);
priv->last_msr = data[BELKIN_SA_MSR_INDEX];
/* Record Control Line states */
......@@ -336,6 +340,7 @@ static void belkin_sa_read_int_callback (struct urb *urb, struct pt_regs *regs)
}
}
#endif
spin_unlock_irqrestore(&priv->lock, flags);
exit:
retval = usb_submit_urb (urb, GFP_ATOMIC);
if (retval)
......@@ -352,6 +357,9 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct termios
unsigned int old_iflag = 0;
unsigned int old_cflag = 0;
__u16 urb_value = 0; /* Will hold the new flags */
unsigned long flags;
unsigned long control_state;
int bad_flow_control;
if ((!port->tty) || (!port->tty->termios)) {
dbg ("%s - no tty or termios structure", __FUNCTION__);
......@@ -361,6 +369,12 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct termios
iflag = port->tty->termios->c_iflag;
cflag = port->tty->termios->c_cflag;
/* get a local copy of the current port settings */
spin_lock_irqsave(&priv->lock, flags);
control_state = priv->control_state;
bad_flow_control = priv->bad_flow_control;
spin_unlock_irqrestore(&priv->lock, flags);
/* check that they really want us to change something */
if (old_termios) {
if ((cflag == old_termios->c_cflag) &&
......@@ -376,7 +390,7 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct termios
if( (cflag&CBAUD) != (old_cflag&CBAUD) ) {
/* reassert DTR and (maybe) RTS on transition from B0 */
if( (old_cflag&CBAUD) == B0 ) {
priv->control_state |= (TIOCM_DTR|TIOCM_RTS);
control_state |= (TIOCM_DTR|TIOCM_RTS);
if (BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, 1) < 0)
err("Set DTR error");
/* don't set RTS if using hardware flow control */
......@@ -410,7 +424,7 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct termios
err("Disable flowcontrol error");
/* Drop RTS and DTR */
priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
control_state &= ~(TIOCM_DTR | TIOCM_RTS);
if (BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, 0) < 0)
err("DTR LOW error");
if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, 0) < 0)
......@@ -465,12 +479,17 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct termios
else
urb_value &= ~(BELKIN_SA_FLOW_OCTS | BELKIN_SA_FLOW_IRTS);
if (priv->bad_flow_control)
if (bad_flow_control)
urb_value &= ~(BELKIN_SA_FLOW_IRTS);
if (BSA_USB_CMD(BELKIN_SA_SET_FLOW_CTRL_REQUEST, urb_value) < 0)
err("Set flow control error");
}
/* save off the modified port settings */
spin_lock_irqsave(&priv->lock, flags);
priv->control_state = control_state;
spin_unlock_irqrestore(&priv->lock, flags);
} /* belkin_sa_set_termios */
......@@ -488,12 +507,19 @@ static int belkin_sa_ioctl (struct usb_serial_port *port, struct file * file, un
struct usb_serial *serial = port->serial;
__u16 urb_value; /* Will hold the new flags */
struct belkin_sa_private *priv = usb_get_serial_port_data(port);
int ret, mask;
int ret = 0;
int mask;
unsigned long control_state;
unsigned long flags;
spin_lock_irqsave(&priv->lock, flags);
control_state = priv->control_state;
spin_unlock_irqrestore(&priv->lock, flags);
/* Based on code from acm.c and others */
switch (cmd) {
case TIOCMGET:
return put_user(priv->control_state, (unsigned long *) arg);
return put_user(control_state, (unsigned long *) arg);
break;
case TIOCMSET: /* Turns on and off the lines as specified by the mask */
......@@ -506,13 +532,13 @@ static int belkin_sa_ioctl (struct usb_serial_port *port, struct file * file, un
/* RTS needs set */
urb_value = ((cmd == TIOCMSET) && (mask & TIOCM_RTS)) || (cmd == TIOCMBIS) ? 1 : 0;
if (urb_value)
priv->control_state |= TIOCM_RTS;
control_state |= TIOCM_RTS;
else
priv->control_state &= ~TIOCM_RTS;
control_state &= ~TIOCM_RTS;
if ((ret = BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, urb_value)) < 0) {
err("Set RTS error %d", ret);
return(ret);
goto cmerror;
}
}
......@@ -520,14 +546,19 @@ static int belkin_sa_ioctl (struct usb_serial_port *port, struct file * file, un
/* DTR needs set */
urb_value = ((cmd == TIOCMSET) && (mask & TIOCM_DTR)) || (cmd == TIOCMBIS) ? 1 : 0;
if (urb_value)
priv->control_state |= TIOCM_DTR;
control_state |= TIOCM_DTR;
else
priv->control_state &= ~TIOCM_DTR;
control_state &= ~TIOCM_DTR;
if ((ret = BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, urb_value)) < 0) {
err("Set DTR error %d", ret);
return(ret);
goto cmerror;
}
}
cmerror:
spin_lock_irqsave(&priv->lock, flags);
priv->control_state = control_state;
spin_unlock_irqrestore(&priv->lock, flags);
return ret;
break;
case TIOCMIWAIT:
......
......@@ -107,6 +107,7 @@ static struct usb_device_id ipaq_id_table [] = {
{ USB_DEVICE(COMPAQ_VENDOR_ID, COMPAQ_IPAQ_ID) },
{ USB_DEVICE(COMPAQ_VENDOR_ID, COMPAQ_0032_ID) },
{ USB_DEVICE(DELL_VENDOR_ID, DELL_AXIM_ID) },
{ USB_DEVICE(FSC_VENDOR_ID, FSC_LOOX_ID) },
{ USB_DEVICE(HP_VENDOR_ID, HP_JORNADA_548_ID) },
{ USB_DEVICE(HP_VENDOR_ID, HP_JORNADA_568_ID) },
{ USB_DEVICE(HP_VENDOR_ID, HP_2016_ID) },
......
......@@ -33,6 +33,9 @@
#define DELL_VENDOR_ID 0x413c
#define DELL_AXIM_ID 0x4001
#define FSC_VENDOR_ID 0x0bf8
#define FSC_LOOX_ID 0x1001
#define HP_VENDOR_ID 0x03f0
#define HP_JORNADA_548_ID 0x1016
#define HP_JORNADA_568_ID 0x1116
......
......@@ -166,7 +166,7 @@ struct klsi_105_private {
unsigned long line_state; /* modem line settings */
/* write pool */
struct urb * write_urb_pool[NUM_URBS];
spinlock_t write_urb_pool_lock;
spinlock_t lock;
unsigned long bytes_in;
unsigned long bytes_out;
};
......@@ -284,7 +284,7 @@ static int klsi_105_startup (struct usb_serial *serial)
priv->bytes_out = 0;
usb_set_serial_port_data(&serial->port[i], priv);
spin_lock_init (&priv->write_urb_pool_lock);
spin_lock_init (&priv->lock);
for (i=0; i<NUM_URBS; i++) {
struct urb* urb = usb_alloc_urb(0, GFP_KERNEL);
......@@ -326,7 +326,7 @@ static void klsi_105_shutdown (struct usb_serial *serial)
/* kill our write urb pool */
int j;
struct urb **write_urbs = priv->write_urb_pool;
spin_lock_irqsave(&priv->write_urb_pool_lock,flags);
spin_lock_irqsave(&priv->lock,flags);
for (j = 0; j < NUM_URBS; j++) {
if (write_urbs[j]) {
......@@ -343,8 +343,7 @@ static void klsi_105_shutdown (struct usb_serial *serial)
}
}
spin_unlock_irqrestore (&priv->write_urb_pool_lock,
flags);
spin_unlock_irqrestore (&priv->lock, flags);
kfree(priv);
usb_set_serial_port_data(&serial->port[i], NULL);
......@@ -360,6 +359,8 @@ static int klsi_105_open (struct usb_serial_port *port, struct file *filp)
int rc;
int i;
unsigned long line_state;
struct klsi_105_port_settings cfg;
unsigned long flags;
dbg("%s port %d", __FUNCTION__, port->number);
......@@ -374,21 +375,27 @@ static int klsi_105_open (struct usb_serial_port *port, struct file *filp)
* Then read the modem line control and store values in
* priv->line_state.
*/
priv->cfg.pktlen = 5;
priv->cfg.baudrate = kl5kusb105a_sio_b9600;
priv->cfg.databits = kl5kusb105a_dtb_8;
priv->cfg.unknown1 = 0;
priv->cfg.unknown2 = 1;
klsi_105_chg_port_settings(serial, &(priv->cfg));
cfg.pktlen = 5;
cfg.baudrate = kl5kusb105a_sio_b9600;
cfg.databits = kl5kusb105a_dtb_8;
cfg.unknown1 = 0;
cfg.unknown2 = 1;
klsi_105_chg_port_settings(serial, &cfg);
/* set up termios structure */
spin_lock_irqsave (&priv->lock, flags);
priv->termios.c_iflag = port->tty->termios->c_iflag;
priv->termios.c_oflag = port->tty->termios->c_oflag;
priv->termios.c_cflag = port->tty->termios->c_cflag;
priv->termios.c_lflag = port->tty->termios->c_lflag;
for (i=0; i<NCCS; i++)
priv->termios.c_cc[i] = port->tty->termios->c_cc[i];
priv->cfg.pktlen = cfg.pktlen;
priv->cfg.baudrate = cfg.baudrate;
priv->cfg.databits = cfg.databits;
priv->cfg.unknown1 = cfg.unknown1;
priv->cfg.unknown2 = cfg.unknown2;
spin_unlock_irqrestore (&priv->lock, flags);
/* READ_ON and urb submission */
usb_fill_bulk_urb(port->read_urb, serial->dev,
......@@ -422,7 +429,9 @@ static int klsi_105_open (struct usb_serial_port *port, struct file *filp)
rc = klsi_105_get_line_state(serial, &line_state);
if (rc >= 0) {
spin_lock_irqsave (&priv->lock, flags);
priv->line_state = line_state;
spin_unlock_irqrestore (&priv->lock, flags);
dbg("%s - read line state 0x%lx", __FUNCTION__, line_state);
retval = 0;
} else
......@@ -492,7 +501,7 @@ static int klsi_105_write (struct usb_serial_port *port, int from_user,
unsigned long flags;
int i;
/* since the pool is per-port we might not need the spin lock !? */
spin_lock_irqsave (&priv->write_urb_pool_lock, flags);
spin_lock_irqsave (&priv->lock, flags);
for (i=0; i<NUM_URBS; i++) {
if (priv->write_urb_pool[i]->status != -EINPROGRESS) {
urb = priv->write_urb_pool[i];
......@@ -500,7 +509,7 @@ static int klsi_105_write (struct usb_serial_port *port, int from_user,
break;
}
}
spin_unlock_irqrestore (&priv->write_urb_pool_lock, flags);
spin_unlock_irqrestore (&priv->lock, flags);
if (urb==NULL) {
dbg("%s - no more free urbs", __FUNCTION__);
......@@ -552,6 +561,7 @@ static int klsi_105_write (struct usb_serial_port *port, int from_user,
count -= size;
}
exit:
/* lockless, but it's for debug info only... */
priv->bytes_out+=bytes_sent;
return bytes_sent; /* that's how much we wrote */
......@@ -588,7 +598,7 @@ static int klsi_105_chars_in_buffer (struct usb_serial_port *port)
unsigned long flags;
struct klsi_105_private *priv = usb_get_serial_port_data(port);
spin_lock_irqsave (&priv->write_urb_pool_lock, flags);
spin_lock_irqsave (&priv->lock, flags);
for (i = 0; i < NUM_URBS; ++i) {
if (priv->write_urb_pool[i]->status == -EINPROGRESS) {
......@@ -596,7 +606,7 @@ static int klsi_105_chars_in_buffer (struct usb_serial_port *port)
}
}
spin_unlock_irqrestore (&priv->write_urb_pool_lock, flags);
spin_unlock_irqrestore (&priv->lock, flags);
dbg("%s - returns %d", __FUNCTION__, chars);
return (chars);
......@@ -609,14 +619,14 @@ static int klsi_105_write_room (struct usb_serial_port *port)
int room = 0;
struct klsi_105_private *priv = usb_get_serial_port_data(port);
spin_lock_irqsave (&priv->write_urb_pool_lock, flags);
spin_lock_irqsave (&priv->lock, flags);
for (i = 0; i < NUM_URBS; ++i) {
if (priv->write_urb_pool[i]->status != -EINPROGRESS) {
room += URB_TRANSFER_BUFFER_SIZE;
}
}
spin_unlock_irqrestore (&priv->write_urb_pool_lock, flags);
spin_unlock_irqrestore (&priv->lock, flags);
dbg("%s - returns %d", __FUNCTION__, room);
return (room);
......@@ -690,6 +700,8 @@ static void klsi_105_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
tty_insert_flip_char(tty, ((__u8*) data)[i], 0);
}
tty_flip_buffer_push(tty);
/* again lockless, but debug info only */
priv->bytes_in += bytes_sent;
}
/* Continue trying to always read */
......@@ -715,6 +727,11 @@ static void klsi_105_set_termios (struct usb_serial_port *port,
unsigned int old_iflag = old_termios->c_iflag;
unsigned int cflag = port->tty->termios->c_cflag;
unsigned int old_cflag = old_termios->c_cflag;
struct klsi_105_port_settings cfg;
unsigned long flags;
/* lock while we are modifying the settings */
spin_lock_irqsave (&priv->lock, flags);
/*
* Update baud rate
......@@ -838,9 +855,11 @@ static void klsi_105_set_termios (struct usb_serial_port *port,
#endif
;
}
memcpy (&cfg, &priv->cfg, sizeof(cfg));
spin_unlock_irqrestore (&priv->lock, flags);
/* now commit changes to device */
klsi_105_chg_port_settings(serial, &(priv->cfg));
klsi_105_chg_port_settings(serial, &cfg);
} /* klsi_105_set_termios */
......@@ -866,6 +885,7 @@ static int klsi_105_ioctl (struct usb_serial_port *port, struct file * file,
struct usb_serial *serial = port->serial;
struct klsi_105_private *priv = usb_get_serial_port_data(port);
int mask;
unsigned long flags;
dbg("%scmd=0x%x", __FUNCTION__, cmd);
......@@ -881,11 +901,12 @@ static int klsi_105_ioctl (struct usb_serial_port *port, struct file * file,
err("Reading line control failed (error = %d)", rc);
/* better return value? EAGAIN? */
return -ENOIOCTLCMD;
} else {
priv->line_state = line_state;
dbg("%s - read line state 0x%lx", __FUNCTION__, line_state);
}
return put_user(priv->line_state, (unsigned long *) arg);
spin_lock_irqsave (&priv->lock, flags);
priv->line_state = line_state;
spin_unlock_irqrestore (&priv->lock, flags);
dbg("%s - read line state 0x%lx", __FUNCTION__, line_state);
return put_user(line_state, (unsigned long *) arg);
};
case TIOCMSET: /* Turns on and off the lines as specified by the mask */
......
......@@ -171,6 +171,7 @@ static struct usb_serial_device_type mct_u232_device = {
struct mct_u232_private {
spinlock_t lock;
unsigned long control_state; /* Modem Line Setting (TIOCM) */
unsigned char last_lcr; /* Line Control Register */
unsigned char last_lsr; /* Line Status Register */
......@@ -306,8 +307,9 @@ static int mct_u232_startup (struct usb_serial *serial)
/* allocate the private data structure */
priv = kmalloc(sizeof(struct mct_u232_private), GFP_KERNEL);
if (!priv)
return (-1); /* error */
return -ENOMEM;
/* set initial values for control structures */
spin_lock_init(&priv->lock);
priv->control_state = 0;
priv->last_lsr = 0;
priv->last_msr = 0;
......@@ -339,6 +341,10 @@ static int mct_u232_open (struct usb_serial_port *port, struct file *filp)
struct usb_serial *serial = port->serial;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
int retval = 0;
unsigned long control_state;
unsigned long flags;
unsigned char last_lcr;
unsigned char last_msr;
dbg("%s port %d", __FUNCTION__, port->number);
......@@ -355,20 +361,27 @@ static int mct_u232_open (struct usb_serial_port *port, struct file *filp)
* sure if this is really necessary. But it should not harm
* either.
*/
spin_lock_irqsave(&priv->lock, flags);
if (port->tty->termios->c_cflag & CBAUD)
priv->control_state = TIOCM_DTR | TIOCM_RTS;
else
priv->control_state = 0;
mct_u232_set_modem_ctrl(serial, priv->control_state);
priv->last_lcr = (MCT_U232_DATA_BITS_8 |
MCT_U232_PARITY_NONE |
MCT_U232_STOP_BITS_1);
mct_u232_set_line_ctrl(serial, priv->last_lcr);
control_state = priv->control_state;
last_lcr = priv->last_lcr;
spin_unlock_irqrestore(&priv->lock, flags);
mct_u232_set_modem_ctrl(serial, control_state);
mct_u232_set_line_ctrl(serial, last_lcr);
/* Read modem status and update control state */
mct_u232_get_modem_stat(serial, &priv->last_msr);
mct_u232_get_modem_stat(serial, &last_msr);
spin_lock_irqsave(&priv->lock, flags);
priv->last_msr = last_msr;
mct_u232_msr_to_state(&priv->control_state, priv->last_msr);
spin_unlock_irqrestore(&priv->lock, flags);
{
/* Puh, that's dirty */
......@@ -523,6 +536,7 @@ static void mct_u232_read_int_callback (struct urb *urb, struct pt_regs *regs)
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
int status;
unsigned long flags;
dbg("%s - port %d", __FUNCTION__, port->number);
......@@ -567,6 +581,7 @@ static void mct_u232_read_int_callback (struct urb *urb, struct pt_regs *regs)
* The interrupt-in pipe signals exceptional conditions (modem line
* signal changes and errors). data[0] holds MSR, data[1] holds LSR.
*/
spin_lock_irqsave(&priv->lock, flags);
priv->last_msr = data[MCT_U232_MSR_INDEX];
/* Record Control Line states */
......@@ -597,6 +612,7 @@ static void mct_u232_read_int_callback (struct urb *urb, struct pt_regs *regs)
}
}
#endif
spin_unlock_irqrestore(&priv->lock, flags);
exit:
status = usb_submit_urb (urb, GFP_ATOMIC);
if (status)
......@@ -614,7 +630,16 @@ static void mct_u232_set_termios (struct usb_serial_port *port,
unsigned int old_iflag = old_termios->c_iflag;
unsigned int cflag = port->tty->termios->c_cflag;
unsigned int old_cflag = old_termios->c_cflag;
unsigned long flags;
unsigned long control_state;
unsigned char last_lcr;
/* get a local copy of the current port settings */
spin_lock_irqsave(&priv->lock, flags);
control_state = priv->control_state;
last_lcr = priv->last_lcr;
spin_unlock_irqrestore(&priv->lock, flags);
/*
* Update baud rate
*/
......@@ -622,12 +647,12 @@ static void mct_u232_set_termios (struct usb_serial_port *port,
/* reassert DTR and (maybe) RTS on transition from B0 */
if( (old_cflag & CBAUD) == B0 ) {
dbg("%s: baud was B0", __FUNCTION__);
priv->control_state |= TIOCM_DTR;
control_state |= TIOCM_DTR;
/* don't set RTS if using hardware flow control */
if (!(old_cflag & CRTSCTS)) {
priv->control_state |= TIOCM_RTS;
control_state |= TIOCM_RTS;
}
mct_u232_set_modem_ctrl(serial, priv->control_state);
mct_u232_set_modem_ctrl(serial, control_state);
}
switch(cflag & CBAUD) {
......@@ -659,8 +684,8 @@ static void mct_u232_set_termios (struct usb_serial_port *port,
if ((cflag & CBAUD) == B0 ) {
dbg("%s: baud is B0", __FUNCTION__);
/* Drop RTS and DTR */
priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
mct_u232_set_modem_ctrl(serial, priv->control_state);
control_state &= ~(TIOCM_DTR | TIOCM_RTS);
mct_u232_set_modem_ctrl(serial, control_state);
}
}
......@@ -672,36 +697,36 @@ static void mct_u232_set_termios (struct usb_serial_port *port,
|| (cflag & CSTOPB) != (old_cflag & CSTOPB) ) {
priv->last_lcr = 0;
last_lcr = 0;
/* set the parity */
if (cflag & PARENB)
priv->last_lcr |= (cflag & PARODD) ?
last_lcr |= (cflag & PARODD) ?
MCT_U232_PARITY_ODD : MCT_U232_PARITY_EVEN;
else
priv->last_lcr |= MCT_U232_PARITY_NONE;
last_lcr |= MCT_U232_PARITY_NONE;
/* set the number of data bits */
switch (cflag & CSIZE) {
case CS5:
priv->last_lcr |= MCT_U232_DATA_BITS_5; break;
last_lcr |= MCT_U232_DATA_BITS_5; break;
case CS6:
priv->last_lcr |= MCT_U232_DATA_BITS_6; break;
last_lcr |= MCT_U232_DATA_BITS_6; break;
case CS7:
priv->last_lcr |= MCT_U232_DATA_BITS_7; break;
last_lcr |= MCT_U232_DATA_BITS_7; break;
case CS8:
priv->last_lcr |= MCT_U232_DATA_BITS_8; break;
last_lcr |= MCT_U232_DATA_BITS_8; break;
default:
err("CSIZE was not CS5-CS8, using default of 8");
priv->last_lcr |= MCT_U232_DATA_BITS_8;
last_lcr |= MCT_U232_DATA_BITS_8;
break;
}
/* set the number of stop bits */
priv->last_lcr |= (cflag & CSTOPB) ?
last_lcr |= (cflag & CSTOPB) ?
MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1;
mct_u232_set_line_ctrl(serial, priv->last_lcr);
mct_u232_set_line_ctrl(serial, last_lcr);
}
/*
......@@ -714,11 +739,17 @@ static void mct_u232_set_termios (struct usb_serial_port *port,
/* Drop DTR/RTS if no flow control otherwise assert */
if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS) )
priv->control_state |= TIOCM_DTR | TIOCM_RTS;
control_state |= TIOCM_DTR | TIOCM_RTS;
else
priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
mct_u232_set_modem_ctrl(serial, priv->control_state);
control_state &= ~(TIOCM_DTR | TIOCM_RTS);
mct_u232_set_modem_ctrl(serial, control_state);
}
/* save off the modified port settings */
spin_lock_irqsave(&priv->lock, flags);
priv->control_state = control_state;
priv->last_lcr = last_lcr;
spin_unlock_irqrestore(&priv->lock, flags);
} /* mct_u232_set_termios */
......@@ -726,10 +757,15 @@ static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state )
{
struct usb_serial *serial = port->serial;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
unsigned char lcr = priv->last_lcr;
unsigned char lcr;
unsigned long flags;
dbg("%sstate=%d", __FUNCTION__, break_state);
spin_lock_irqsave(&priv->lock, flags);
lcr = priv->last_lcr;
spin_unlock_irqrestore(&priv->lock, flags);
if (break_state)
lcr |= MCT_U232_SET_BREAK;
......@@ -743,13 +779,19 @@ static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file,
struct usb_serial *serial = port->serial;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
int mask;
unsigned long control_state;
unsigned long flags;
dbg("%scmd=0x%x", __FUNCTION__, cmd);
spin_lock_irqsave(&priv->lock, flags);
control_state = priv->control_state;
spin_unlock_irqrestore(&priv->lock, flags);
/* Based on code from acm.c and others */
switch (cmd) {
case TIOCMGET:
return put_user(priv->control_state, (unsigned long *) arg);
return put_user(control_state, (unsigned long *) arg);
break;
case TIOCMSET: /* Turns on and off the lines as specified by the mask */
......@@ -762,20 +804,24 @@ static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file,
/* RTS needs set */
if( ((cmd == TIOCMSET) && (mask & TIOCM_RTS)) ||
(cmd == TIOCMBIS) )
priv->control_state |= TIOCM_RTS;
control_state |= TIOCM_RTS;
else
priv->control_state &= ~TIOCM_RTS;
control_state &= ~TIOCM_RTS;
}
if ((cmd == TIOCMSET) || (mask & TIOCM_DTR)) {
/* DTR needs set */
if( ((cmd == TIOCMSET) && (mask & TIOCM_DTR)) ||
(cmd == TIOCMBIS) )
priv->control_state |= TIOCM_DTR;
control_state |= TIOCM_DTR;
else
priv->control_state &= ~TIOCM_DTR;
control_state &= ~TIOCM_DTR;
}
mct_u232_set_modem_ctrl(serial, priv->control_state);
mct_u232_set_modem_ctrl(serial, control_state);
spin_lock_irqsave(&priv->lock, flags);
priv->control_state = control_state;
spin_unlock_irqrestore(&priv->lock, flags);
break;
case TIOCMIWAIT:
......
......@@ -148,7 +148,8 @@ static struct usb_serial_device_type pl2303_device = {
.shutdown = pl2303_shutdown,
};
struct pl2303_private {
struct pl2303_private {
spinlock_t lock;
u8 line_control;
u8 termios_initialized;
};
......@@ -164,6 +165,7 @@ static int pl2303_startup (struct usb_serial *serial)
if (!priv)
return -ENOMEM;
memset (priv, 0x00, sizeof (struct pl2303_private));
spin_lock_init(&priv->lock);
usb_set_serial_port_data(&serial->port[i], priv);
}
return 0;
......@@ -223,18 +225,21 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol
int baud;
int i;
dbg("%s - port %d, initialized = %d", __FUNCTION__, port->number, priv->termios_initialized);
dbg("%s - port %d", __FUNCTION__, port->number);
if ((!port->tty) || (!port->tty->termios)) {
dbg("%s - no tty structures", __FUNCTION__);
return;
}
spin_lock(&priv->lock);
if (!priv->termios_initialized) {
*(port->tty->termios) = tty_std_termios;
port->tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
priv->termios_initialized = 1;
}
spin_unlock(&priv->lock);
cflag = port->tty->termios->c_cflag;
/* check that they really want us to change something */
if (old_termios) {
......@@ -341,11 +346,16 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol
dbg ("0x21:0x20:0:0 %d", i);
if (cflag && CBAUD) {
u8 control;
spin_lock (&priv->lock);
if ((cflag && CBAUD) == B0)
priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
else
priv->line_control |= (CONTROL_DTR | CONTROL_RTS);
set_control_lines (serial->dev, priv->line_control);
control = priv->line_control;
spin_unlock (&priv->lock);
set_control_lines (serial->dev, control);
}
buf[0] = buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0;
......@@ -444,48 +454,50 @@ static void pl2303_close (struct usb_serial_port *port, struct file *filp)
dbg("%s - port %d", __FUNCTION__, port->number);
if (serial->dev) {
if (port->tty) {
c_cflag = port->tty->termios->c_cflag;
if (c_cflag & HUPCL) {
/* drop DTR and RTS */
priv = usb_get_serial_port_data(port);
priv->line_control = 0;
set_control_lines (port->serial->dev,
priv->line_control);
}
}
/* shutdown our urbs */
dbg("%s - shutting down urbs", __FUNCTION__);
result = usb_unlink_urb (port->write_urb);
if (result)
dbg("%s - usb_unlink_urb (write_urb)"
" failed with reason: %d", __FUNCTION__,
result);
/* shutdown our urbs */
dbg("%s - shutting down urbs", __FUNCTION__);
result = usb_unlink_urb (port->write_urb);
if (result)
dbg("%s - usb_unlink_urb (write_urb)"
" failed with reason: %d", __FUNCTION__,
result);
result = usb_unlink_urb (port->read_urb);
if (result)
dbg("%s - usb_unlink_urb (read_urb) "
"failed with reason: %d", __FUNCTION__,
result);
result = usb_unlink_urb (port->read_urb);
if (result)
dbg("%s - usb_unlink_urb (read_urb) "
"failed with reason: %d", __FUNCTION__,
result);
result = usb_unlink_urb (port->interrupt_in_urb);
if (result)
dbg("%s - usb_unlink_urb (interrupt_in_urb)"
" failed with reason: %d", __FUNCTION__,
result);
result = usb_unlink_urb (port->interrupt_in_urb);
if (result)
dbg("%s - usb_unlink_urb (interrupt_in_urb)"
" failed with reason: %d", __FUNCTION__,
result);
if (port->tty) {
c_cflag = port->tty->termios->c_cflag;
if (c_cflag & HUPCL) {
/* drop DTR and RTS */
priv = usb_get_serial_port_data(port);
spin_lock (&priv->lock);
priv->line_control = 0;
spin_unlock (&priv->lock);
set_control_lines (port->serial->dev, 0);
}
}
}
static int set_modem_info (struct usb_serial_port *port, unsigned int cmd, unsigned int *value)
{
struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned int arg;
u8 control;
if (copy_from_user(&arg, value, sizeof(int)))
return -EFAULT;
spin_lock (&priv->lock);
switch (cmd) {
case TIOCMBIS:
if (arg & TIOCM_RTS)
......@@ -509,16 +521,22 @@ static int set_modem_info (struct usb_serial_port *port, unsigned int cmd, unsig
priv->line_control |= ((arg & TIOCM_DTR) ? CONTROL_DTR : 0);
break;
}
control = priv->line_control;
spin_unlock (&priv->lock);
return set_control_lines (port->serial->dev, priv->line_control);
return set_control_lines (port->serial->dev, control);
}
static int get_modem_info (struct usb_serial_port *port, unsigned int *value)
{
struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned int mcr = priv->line_control;
unsigned int mcr;
unsigned int result;
spin_lock (&priv->lock);
mcr = priv->line_control;
spin_unlock (&priv->lock);
result = ((mcr & CONTROL_DTR) ? TIOCM_DTR : 0)
| ((mcr & CONTROL_RTS) ? TIOCM_RTS : 0);
......
......@@ -2,7 +2,7 @@
* USB HandSpring Visor, Palm m50x, and Sony Clie driver
* (supports all of the Palm OS USB devices)
*
* Copyright (C) 1999 - 2002
* Copyright (C) 1999 - 2003
* Greg Kroah-Hartman (greg@kroah.com)
*
* This program is free software; you can redistribute it and/or modify
......@@ -183,34 +183,34 @@ static int palm_os_4_probe (struct usb_serial *serial, const struct usb_device_i
static struct usb_device_id id_table [] = {
{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID),
.driver_info = (unsigned int)&palm_os_3_probe },
.driver_info = (kernel_ulong_t)&palm_os_3_probe },
{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_TREO_ID),
.driver_info = (unsigned int)&palm_os_4_probe },
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID),
.driver_info = (unsigned int)&palm_os_4_probe },
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID),
.driver_info = (unsigned int)&palm_os_4_probe },
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M515_ID),
.driver_info = (unsigned int)&palm_os_4_probe },
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_I705_ID),
.driver_info = (unsigned int)&palm_os_4_probe },
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID),
.driver_info = (unsigned int)&palm_os_4_probe },
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M130_ID),
.driver_info = (unsigned int)&palm_os_4_probe },
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_T_ID),
.driver_info = (unsigned int)&palm_os_4_probe },
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_Z_ID),
.driver_info = (unsigned int)&palm_os_4_probe },
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE_ID),
.driver_info = (unsigned int)&palm_os_4_probe },
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID),
.driver_info = (unsigned int)&palm_os_4_probe },
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_S360_ID),
.driver_info = (unsigned int)&palm_os_4_probe },
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_1_ID) },
{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NX60_ID),
.driver_info = (unsigned int)&palm_os_4_probe },
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ } /* Terminating entry */
};
......@@ -374,27 +374,22 @@ static void visor_close (struct usb_serial_port *port, struct file * filp)
if (!serial)
return;
if (serial->dev) {
/* only send a shutdown message if the
* device is still here */
transfer_buffer = kmalloc (0x12, GFP_KERNEL);
if (!transfer_buffer) {
dev_err(&port->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, 0x12);
} else {
/* send a shutdown message to the device */
usb_control_msg (serial->dev,
usb_rcvctrlpipe(serial->dev, 0),
VISOR_CLOSE_NOTIFICATION, 0xc2,
0x0000, 0x0000,
transfer_buffer, 0x12, 300);
kfree (transfer_buffer);
}
/* shutdown our bulk read */
usb_unlink_urb (port->read_urb);
if (port->interrupt_in_urb)
usb_unlink_urb (port->interrupt_in_urb);
/* shutdown our urbs */
usb_unlink_urb (port->read_urb);
if (port->interrupt_in_urb)
usb_unlink_urb (port->interrupt_in_urb);
/* Try to send shutdown message, if the device is gone, this will just fail. */
transfer_buffer = kmalloc (0x12, GFP_KERNEL);
if (transfer_buffer) {
usb_control_msg (serial->dev,
usb_rcvctrlpipe(serial->dev, 0),
VISOR_CLOSE_NOTIFICATION, 0xc2,
0x0000, 0x0000,
transfer_buffer, 0x12, 300);
kfree (transfer_buffer);
}
/* Uncomment the following line if you want to see some statistics in your syslog */
/* dev_info (&port->dev, "Bytes In = %d Bytes Out = %d\n", bytes_in, bytes_out); */
}
......
......@@ -137,12 +137,12 @@ UNUSUAL_DEV( 0x04da, 0x0901, 0x0100, 0x0200,
"LS-120 Camera",
US_SC_UFI, US_PR_CBI, NULL, 0),
/* Reported by Peter Wchtler <pwaechtler@loewe-komp.de> */
UNUSUAL_DEV( 0x04ce, 0x0002, 0x0074, 0x0074,
"ScanLogic",
"SL11R-IDE 0049SQFP-1.2 A002",
US_SC_SCSI, US_PR_BULK, NULL,
US_FL_FIX_INQUIRY ),
/* From Yukihiro Nakai, via zaitcev@yahoo.com.
* This is needed for CB instead of CBI */
UNUSUAL_DEV( 0x04da, 0x0d05, 0x0000, 0x0000,
"Sharp CE-CW05",
"CD-R/RW Drive",
US_SC_8070, US_PR_CB, NULL, 0),
/* Most of the following entries were developed with the help of
* Shuttle/SCM directly.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment