Commit 99a72d19 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 63ac2a63 7e04539e
......@@ -11,7 +11,7 @@ DOCBOOKS := wanbook.sgml z8530book.sgml mcabook.sgml videobook.sgml \
kernel-locking.sgml via-audio.sgml mousedrivers.sgml \
deviceiobook.sgml procfs-guide.sgml tulip-user.sgml \
writing_usb_driver.sgml scsidrivers.sgml sis900.sgml \
kernel-api.sgml journal-api.sgml lsm.sgml
kernel-api.sgml journal-api.sgml lsm.sgml usb.sgml
###
# The build process is as follows (targets):
......
......@@ -228,102 +228,6 @@ X!Isound/sound_firmware.c
-->
</chapter>
<chapter id="usb">
<title>USB Devices</title>
<para>Drivers for USB devices talk to the "usbcore" APIs, and are
exposed through driver frameworks such as block, character,
or network devices.
There are two types of public "usbcore" APIs: those intended for
general driver use, and those which are only public to drivers that
are part of the core.
The drivers that are part of the core are involved in managing a USB bus.
They include the "hub" driver, which manages trees of USB devices, and
several different kinds of "host controller" driver (HCD), which control
individual busses.
</para>
<para>The device model seen by USB drivers is relatively complex.
</para>
<itemizedlist>
<listitem><para>USB supports four kinds of data transfer
(control, bulk, interrupt, and isochronous). Two transfer
types use bandwidth as it's available (control and bulk),
while the other two types of transfer (interrupt and isochronous)
are scheduled to provide guaranteed bandwidth.
</para></listitem>
<listitem><para>The device description model includes one or more
"configurations" per device, only one of which is active at a time.
</para></listitem>
<listitem><para>Configurations have one or more "interface", each
of which may have "alternate settings". Interfaces may be
standardized by USB "Class" specifications, or may be specific to
a vendor or device.</para>
<para>USB device drivers actually bind to interfaces, not devices.
Think of them as "interface drivers", though you
may not see many devices where the distinction is important.
Most USB devices are simple, with only one configuration,
one interface, and one alternate setting.
</para></listitem>
<listitem><para>Interfaces have one or more "endpoints", each of
which supports one type and direction of data transfer such as
"bulk out" or "interrupt in". The entire configuration may have
up to sixteen endpoints in each direction, allocated as needed
among all the interfaces.
</para></listitem>
<listitem><para>Data transfer on USB is packetized; each endpoint
has a maximum packet size.
Drivers must often be aware of conventions such as flagging the end
of bulk transfers using "short" (including zero length) packets.
</para></listitem>
<listitem><para>The Linux USB API supports synchronous calls for
control and bulk messaging.
It also supports asynchnous calls for all kinds of data transfer,
using request structures called "URBs" (USB Request Blocks).
</para></listitem>
</itemizedlist>
<para>Accordingly, the USB Core API exposed to device drivers
covers quite a lot of territory. You'll probably need to consult
the USB 2.0 specification, available online from www.usb.org at
no cost, as well as class or device specifications.
</para>
<sect1><title>Data Types and Macros</title>
!Iinclude/linux/usb.h
</sect1>
<sect1><title>USB Core APIs</title>
!Edrivers/usb/core/urb.c
<!-- FIXME: Removed for now since no structured comments in source
X!Edrivers/usb/core/config.c
-->
!Edrivers/usb/core/message.c
!Edrivers/usb/core/file.c
!Edrivers/usb/core/usb.c
</sect1>
<sect1><title>Host Controller APIs</title>
<para>These APIs are only for use by host controller drivers,
most of which implement standard register interfaces such as
EHCI, OHCI, or UHCI.
</para>
!Edrivers/usb/core/hcd.c
!Edrivers/usb/core/hcd-pci.c
!Edrivers/usb/core/buffer.c
</sect1>
</chapter>
<chapter id="uart16x50">
<title>16x50 UART Driver</title>
!Edrivers/serial/core.c
......
This diff is collapsed.
......@@ -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);
}
......@@ -254,6 +254,10 @@ extern void usb_set_maxpacket(struct usb_device *dev);
extern void usb_destroy_configuration(struct usb_device *dev);
extern int usb_set_address(struct usb_device *dev);
/* use these only before the device's address has been set */
#define usb_snddefctrl(dev) ((PIPE_CONTROL << 30) | __create_pipe(dev,0))
#define usb_rcvdefctrl(dev) ((PIPE_CONTROL << 30) | __create_pipe(dev,0) | USB_DIR_IN)
/*-------------------------------------------------------------------------*/
/*
......
......@@ -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);
......@@ -332,7 +332,7 @@ write_rio(struct file *file, const char *buffer,
}
interruptible_sleep_on_timeout(&rio-> wait_q, NAK_TIMEOUT);
continue;
} else if (!result & partial) {
} else if (!result && partial) {
obuf += partial;
thistime -= partial;
} else
......
This diff is collapsed.
......@@ -153,7 +153,7 @@ write_lcd(struct file *file, const char *buffer,
}
interruptible_sleep_on_timeout(&lcd-> wait_q, NAK_TIMEOUT);
continue;
} else if (!result & partial) {
} else if (!result && partial) {
obuf += partial;
thistime -= partial;
} else
......
......@@ -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,
......
......@@ -246,6 +246,12 @@ config USB_SERIAL_KEYSPAN
The module will be called keyspan. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
config USB_SERIAL_KEYSPAN_MPR
bool "USB Keyspan MPR Firmware"
depends on USB_SERIAL_KEYSPAN
help
Say Y here to include firmware for the Keyspan MPR converter.
config USB_SERIAL_KEYSPAN_USA28
bool "USB Keyspan USA-28 Firmware"
depends on USB_SERIAL_KEYSPAN
......@@ -312,6 +318,12 @@ config USB_SERIAL_KEYSPAN_USA49W
help
Say Y here to include firmware for the USA-49W converter.
config USB_SERIAL_KEYSPAN_USA49WLC
bool "USB Keyspan USA-49WLC Firmware"
depends on USB_SERIAL_KEYSPAN
help
Say Y here to include firmware for the USA-49WLC converter.
config USB_SERIAL_KLSI
tristate "USB KL5KUSB105 (Palmconnect) Driver (EXPERIMENTAL)"
depends on USB_SERIAL && EXPERIMENTAL
......
......@@ -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
......
......@@ -28,6 +28,24 @@
Change History
Wed Feb 19 22:00:00 PST 2003 (Jeffrey S. Laing <keyspan@jsl.com>)
Merged the current (1/31/03) Keyspan code with the current (2.4.21-pre4)
Linux source tree. The Linux tree lacked support for the 49WLC and
others. The Keyspan patches didn't work with the current kernel.
2003jan30 LPM add support for the 49WLC and MPR
Wed Apr 25 12:00:00 PST 2002 (Keyspan)
Started with Hugh Blemings' code dated Jan 17, 2002. All adapters
now supported (including QI and QW). Modified port open, port
close, and send setup() logic to fix various data and endpoint
synchronization bugs and device LED status bugs. Changed keyspan_
write_room() to accurately return transmit buffer availability.
Changed forwardingLength from 1 to 16 for all adapters.
Fri Oct 12 16:45:00 EST 2001
Preliminary USA-19QI and USA-28 support (both test OK for me, YMMV)
Wed Apr 25 12:00:00 PST 2002 (Keyspan)
Started with Hugh Blemings' code dated Jan 17, 2002. All adapters
now supported (including QI and QW). Modified port open, port
......@@ -103,7 +121,7 @@
/*
* Version Information
*/
#define DRIVER_VERSION "v1.1.3"
#define DRIVER_VERSION "v1.1.4"
#define DRIVER_AUTHOR "Hugh Blemings <hugh@misc.nu"
#define DRIVER_DESC "Keyspan USB to Serial Converter Driver"
......@@ -900,6 +918,9 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp)
/* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), 0); */
}
// if the device is a USA49x, determine whether it is an W or WLC model
// and set the baud clock accordingly
keyspan_send_setup(port, 1);
//mdelay(100);
keyspan_set_termios(port, NULL);
......@@ -1008,6 +1029,11 @@ static int keyspan_fake_startup (struct usb_serial *serial)
fw_name = "USA19QI";
break;
case keyspan_mpr_pre_product_id:
record = &keyspan_mpr_firmware[0];
fw_name = "MPR";
break;
case keyspan_usa19qw_pre_product_id:
record = &keyspan_usa19qw_firmware[0];
fw_name = "USA19QI";
......@@ -1028,6 +1054,11 @@ static int keyspan_fake_startup (struct usb_serial *serial)
fw_name = "USA49W";
break;
case keyspan_usa49wlc_pre_product_id:
record = &keyspan_usa49wlc_firmware[0];
fw_name = "USA49WLC";
break;
default:
record = NULL;
fw_name = "Unknown";
......
......@@ -136,6 +136,12 @@ struct ezusb_hex_record {
static const struct ezusb_hex_record *keyspan_usa19qi_firmware = NULL;
#endif
#ifdef CONFIG_USB_SERIAL_KEYSPAN_MPR
#include "keyspan_mpr_fw.h"
#else
static const struct ezusb_hex_record *keyspan_mpr_firmware = NULL;
#endif
#ifdef CONFIG_USB_SERIAL_KEYSPAN_USA19QW
#include "keyspan_usa19qw_fw.h"
#else
......@@ -160,6 +166,12 @@ struct ezusb_hex_record {
static const struct ezusb_hex_record *keyspan_usa49w_firmware = NULL;
#endif
#ifdef CONFIG_USB_SERIAL_KEYSPAN_USA49WLC
#include "keyspan_usa49wlc_fw.h"
#else
static const struct ezusb_hex_record *keyspan_usa49wlc_firmware = NULL;
#endif
/* Values used for baud rate calculation - device specific */
#define KEYSPAN_INVALID_BAUD_RATE (-1)
#define KEYSPAN_BAUD_RATE_OK (0)
......@@ -182,6 +194,7 @@ struct ezusb_hex_record {
#define keyspan_usa18x_pre_product_id 0x0105
#define keyspan_usa19_pre_product_id 0x0103
#define keyspan_usa19qi_pre_product_id 0x010b
#define keyspan_mpr_pre_product_id 0x011b
#define keyspan_usa19qw_pre_product_id 0x0118
#define keyspan_usa19w_pre_product_id 0x0106
#define keyspan_usa28_pre_product_id 0x0101
......@@ -189,6 +202,7 @@ struct ezusb_hex_record {
#define keyspan_usa28xa_pre_product_id 0x0114
#define keyspan_usa28xb_pre_product_id 0x0113
#define keyspan_usa49w_pre_product_id 0x0109
#define keyspan_usa49wlc_pre_product_id 0x011a
/* Product IDs post-renumeration. Note that the 28x and 28xb
have the same id's post-renumeration but behave identically
......@@ -196,6 +210,7 @@ struct ezusb_hex_record {
#define keyspan_usa18x_product_id 0x0112
#define keyspan_usa19_product_id 0x0107
#define keyspan_usa19qi_product_id 0x010c
#define keyspan_mpr_product_id 0x011c
#define keyspan_usa19qw_product_id 0x0119
#define keyspan_usa19w_product_id 0x0108
#define keyspan_usa28_product_id 0x010f
......@@ -203,6 +218,7 @@ struct ezusb_hex_record {
#define keyspan_usa28xa_product_id 0x0115
#define keyspan_usa28xb_product_id 0x0110
#define keyspan_usa49w_product_id 0x010a
#define keyspan_usa49wlc_product_id 0x012a
struct keyspan_device_details {
......@@ -394,6 +410,22 @@ static const struct keyspan_device_details usa49w_device_details = {
.baudclk = KEYSPAN_USA49W_BAUDCLK,
};
static const struct keyspan_device_details usa49wlc_device_details = {
product_id: keyspan_usa49wlc_product_id,
msg_format: msg_usa49,
num_ports: 4,
indat_endp_flip: 0,
outdat_endp_flip: 0,
indat_endpoints: {0x81, 0x82, 0x83, 0x84},
outdat_endpoints: {0x01, 0x02, 0x03, 0x04},
inack_endpoints: {-1, -1, -1, -1},
outcont_endpoints: {-1, -1, -1, -1},
instat_endpoint: 0x87,
glocont_endpoint: 0x07,
calculate_baud_rate: keyspan_usa19w_calc_baud,
baudclk: KEYSPAN_USA19W_BAUDCLK,
};
static const struct keyspan_device_details *keyspan_devices[] = {
&usa18x_device_details,
&usa19_device_details,
......@@ -405,6 +437,7 @@ static const struct keyspan_device_details *keyspan_devices[] = {
&usa28xa_device_details,
/* 28xb not required as it renumerates as a 28x */
&usa49w_device_details,
&usa49wlc_device_details,
NULL,
};
......@@ -414,21 +447,25 @@ static struct usb_device_id keyspan_ids_combined[] = {
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19w_pre_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qi_pre_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qw_pre_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_mpr_pre_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_pre_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_pre_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_pre_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_pre_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_pre_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_pre_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa18x_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19w_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qi_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qw_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_mpr_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id)},
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)},
{ } /* Terminating entry */
};
......@@ -448,11 +485,13 @@ static struct usb_device_id keyspan_pre_ids[] = {
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qi_pre_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qw_pre_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19w_pre_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_mpr_pre_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_pre_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_pre_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_pre_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_pre_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_pre_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_pre_product_id) },
{ } /* Terminating entry */
};
......@@ -462,6 +501,7 @@ static struct usb_device_id keyspan_1port_ids[] = {
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qi_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qw_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19w_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_mpr_pre_product_id) },
{ } /* Terminating entry */
};
......@@ -469,11 +509,13 @@ static struct usb_device_id keyspan_2port_ids[] = {
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_product_id) },
{ } /* Terminating entry */
};
static struct usb_device_id keyspan_4port_ids[] = {
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)},
{ } /* Terminating entry */
};
......
This diff is collapsed.
This diff is collapsed.
......@@ -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.
......
......@@ -960,8 +960,6 @@ static inline unsigned int __create_pipe(struct usb_device *dev, unsigned int en
#define usb_rcvbulkpipe(dev,endpoint) ((PIPE_BULK << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
#define usb_sndintpipe(dev,endpoint) ((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint))
#define usb_rcvintpipe(dev,endpoint) ((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
#define usb_snddefctrl(dev) ((PIPE_CONTROL << 30))
#define usb_rcvdefctrl(dev) ((PIPE_CONTROL << 30) | USB_DIR_IN)
/* -------------------------------------------------------------------------- */
......
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