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 \ ...@@ -11,7 +11,7 @@ DOCBOOKS := wanbook.sgml z8530book.sgml mcabook.sgml videobook.sgml \
kernel-locking.sgml via-audio.sgml mousedrivers.sgml \ kernel-locking.sgml via-audio.sgml mousedrivers.sgml \
deviceiobook.sgml procfs-guide.sgml tulip-user.sgml \ deviceiobook.sgml procfs-guide.sgml tulip-user.sgml \
writing_usb_driver.sgml scsidrivers.sgml sis900.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): # The build process is as follows (targets):
......
...@@ -228,102 +228,6 @@ X!Isound/sound_firmware.c ...@@ -228,102 +228,6 @@ X!Isound/sound_firmware.c
--> -->
</chapter> </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"> <chapter id="uart16x50">
<title>16x50 UART Driver</title> <title>16x50 UART Driver</title>
!Edrivers/serial/core.c !Edrivers/serial/core.c
......
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[]>
<book id="Linux-USB-API">
<bookinfo>
<title>The Linux-USB Host Side API</title>
<legalnotice>
<para>
This documentation is free software; you can redistribute
it and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later
version.
</para>
<para>
This program is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
</para>
<para>
You should have received a copy of the GNU General Public
License along with this program; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
MA 02111-1307 USA
</para>
<para>
For more details see the file COPYING in the source
distribution of Linux.
</para>
</legalnotice>
</bookinfo>
<toc></toc>
<chapter id="intro">
<title>Introduction to USB on Linux</title>
<para>A Universal Serial Bus (USB) is used to connect a host,
such as a PC or workstation, to a number of peripheral
devices. USB uses a tree structure, with the host at the
root (the system's master), hubs as interior nodes, and
peripheral devices as leaves (and slaves).
Modern PCs support several such trees of USB devices, usually
one USB 2.0 tree (480 Mbit/sec each) with
a few USB 1.1 trees (12 Mbit/sec each) that are used when you
connect a USB 1.1 device directly to the machine's "root hub".
</para>
<para>That master/slave asymmetry was designed in part for
ease of use. It is not physically possible to assemble
(legal) USB cables incorrectly: all upstream "to-the-host"
connectors are the rectangular type, matching the sockets on
root hubs, and the downstream type are the squarish type
(or they are built in to the peripheral).
Software doesn't need to deal with distributed autoconfiguration
since the pre-designated master node manages all that.
At the electrical level, bus protocol overhead is reduced by
eliminating arbitration and moving scheduling into host software.
</para>
<para>USB 1.0 was announced in January 1996, and was revised
as USB 1.1 (with improvements in hub specification and
support for interrupt-out transfers) in September 1998.
USB 2.0 was released in April 2000, including high speed
transfers and transaction translating hubs (used for USB 1.1
and 1.0 backward compatibility).
</para>
<para>USB support was added to Linux early in the 2.2 kernel series
shortly before the 2.3 development forked off. Updates
from 2.3 were regularly folded back into 2.2 releases, bringing
new features such as <filename>/sbin/hotplug</filename> support,
more drivers, and more robustness.
The 2.5 kernel series continued such improvements, and also
worked on USB 2.0 support,
higher performance,
better consistency between host controller drivers,
API simplification (to make bugs less likely),
and providing internal "kerneldoc" documentation.
</para>
<para>Linux can run inside USB devices as well as on
the hosts that control the devices.
Because the Linux 2.x USB support evolved to support mass market
platforms such as Apple Macintosh or PC-compatible systems,
it didn't address design concerns for those types of USB systems.
So it can't be used inside mass-market PDAs, or other peripherals.
USB device drivers running inside those Linux peripherals
don't do the same things as the ones running inside hosts,
and so they've been given a different name:
they're called <emphasis>gadget drivers</emphasis>.
This document does not present gadget drivers.
</para>
</chapter>
<chapter id="host">
<title>USB Host-Side API Model</title>
<para>Host-side drivers for USB devices talk to the "usbcore" APIs.
There are two types of public "usbcore" APIs, targetted at two different
layers of USB driver. Those are
<emphasis>general purpose</emphasis> drivers, exposed through
driver frameworks such as block, character, or network devices;
and drivers that are <emphasis>part of the core</emphasis>,
which are involved in managing a USB bus.
Such core drivers include the <emphasis>hub</emphasis> driver,
which manages trees of USB devices, and several different kinds
of <emphasis>host controller driver (HCD)</emphasis>,
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.
Devices that are capable of high speed operation must also support
full speed configurations, along with a way to ask about the
"other speed" configurations that might be used.
</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.
<emphasis>Most USB devices are simple, with only one configuration,
one interface, and one alternate setting.</emphasis>
</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>
<para>The only host-side drivers that actually touch hardware
(reading/writing registers, handling IRQs, and so on) are the HCDs.
In theory, all HCDs provide the same functionality through the same
API. In practice, that's becoming more true on the 2.5 kernels,
but there are still differences that crop up especially with
fault handling. Different controllers don't necessarily report
the same aspects of failures, and recovery from faults (including
software-induced ones like unlinking an URB) isn't yet fully
consistent.
Device driver authors should make a point of doing disconnect
testing (while the device is active) with each different host
controller driver, to make sure drivers don't have bugs of
their own as well as to make sure they aren't relying on some
HCD-specific behavior.
(You will need external USB 1.1 and/or
USB 2.0 hubs to perform all those tests.)
</para>
</chapter>
<chapter><title>USB-Standard Types</title>
<para>In <filename>&lt;linux/usb_ch9.h&gt;</filename> you will find
the USB data types defined in chapter 9 of the USB specification.
These data types are used throughout USB, and in APIs including
this host side API, gadget APIs, and usbfs.
</para>
!Iinclude/linux/usb_ch9.h
</chapter>
<chapter><title>Host-Side Data Types and Macros</title>
<para>The host side API exposes several layers to drivers, some of
which are more necessary than others.
These support lifecycle models for host side drivers
and devices, and support passing buffers through usbcore to
some HCD that performs the I/O for the device driver.
</para>
!Iinclude/linux/usb.h
</chapter>
<chapter><title>USB Core APIs</title>
<para>There are two basic I/O models in the USB API.
The most elemental one is asynchronous: drivers submit requests
in the form of an URB, and the URB's completion callback
handle the next step.
All USB transfer types support that model, although there
are special cases for control URBs (which always have setup
and status stages, but may not have a data stage) and
isochronous URBs (which allow large packets and include
per-packet fault reports).
Built on top of that is synchronous API support, where a
driver calls a routine that allocates one or more URBs,
submits them, and waits until they complete.
There are synchronous wrappers for single-buffer control
and bulk transfers (which are awkward to use in some
driver disconnect scenarios), and for scatterlist based
streaming i/o (bulk or interrupt).
</para>
<para>USB drivers need to provide buffers that can be
used for DMA, although they don't necessarily need to
provide the DMA mapping themselves.
There are APIs to use used when allocating DMA buffers,
which can prevent use of bounce buffers on some systems.
In some cases, drivers may be able to rely on 64bit DMA
to eliminate another kind of bounce buffer.
</para>
!Edrivers/usb/core/urb.c
!Edrivers/usb/core/message.c
!Edrivers/usb/core/file.c
!Edrivers/usb/core/usb.c
</chapter>
<chapter><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.
UHCI was one of the first interfaces, designed by Intel and
also used by VIA; it doesn't do much in hardware.
OHCI was designed later, to have the hardware do more work
(bigger transfers, tracking protocol state, and so on).
EHCI was designed with USB 2.0; its design has features that
resemble OHCI (hardware does much more work) as well as
UHCI (some parts of ISO support, TD list processing).
</para>
<para>There are host controllers other than the "big three",
although most PCI based controllers (and a few non-PCI based
ones) use one of those interfaces.
Not all host controllers use DMA; some use PIO, and there
is also a simulator.
</para>
<para>The same basic APIs are available to drivers for all
those controllers.
For historical reasons they are in two layers:
<structname>struct usb_bus</structname> is a rather thin
layer that became available in the 2.2 kernels, while
<structname>struct usb_hcd</structname> is a more featureful
layer (available in later 2.4 kernels and in 2.5) that
lets HCDs share common code, to shrink driver size
and significantly reduce hcd-specific behaviors.
</para>
!Edrivers/usb/core/hcd.c
!Edrivers/usb/core/hcd-pci.c
!Edrivers/usb/core/buffer.c
</chapter>
</book>
<!-- vim:syntax=sgml:sw=4
-->
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#define USBMIDI_ROLAND_UA100G 0x0000 #define USBMIDI_ROLAND_UA100G 0x0000
#define USBMIDI_ROLAND_MPU64 0x0002 #define USBMIDI_ROLAND_MPU64 0x0002
#define USBMIDI_ROLAND_SC8850 0x0003 #define USBMIDI_ROLAND_SC8850 0x0003
#define USBMIDI_ROLAND_SC8820 0x0007
#define USBMIDI_ROLAND_UM2 0x0005 #define USBMIDI_ROLAND_UM2 0x0005
#define USBMIDI_ROLAND_UM1 0x0009 #define USBMIDI_ROLAND_UM1 0x0009
#define USBMIDI_ROLAND_PC300 0x0008 #define USBMIDI_ROLAND_PC300 0x0008
...@@ -104,6 +105,13 @@ static struct usb_midi_device usb_midi_devices[] = { ...@@ -104,6 +105,13 @@ static struct usb_midi_device usb_midi_devices[] = {
{ { 0x01, 15 }, {-1, -1} }, { { 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 */
"YAMAHA MU1000", "YAMAHA MU1000",
USB_VENDOR_ID_YAMAHA, USBMIDI_YAMAHA_MU1000, 0, -1, USB_VENDOR_ID_YAMAHA, USBMIDI_YAMAHA_MU1000, 0, -1,
......
...@@ -183,15 +183,21 @@ show_##field (struct device *dev, char *buf) \ ...@@ -183,15 +183,21 @@ show_##field (struct device *dev, char *buf) \
} \ } \
static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL); static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
usb_intf_attr (bInterfaceNumber, "%02x\n")
usb_intf_attr (bAlternateSetting, "%2d\n") usb_intf_attr (bAlternateSetting, "%2d\n")
usb_intf_attr (bNumEndpoints, "%02x\n")
usb_intf_attr (bInterfaceClass, "%02x\n") usb_intf_attr (bInterfaceClass, "%02x\n")
usb_intf_attr (bInterfaceSubClass, "%02x\n") usb_intf_attr (bInterfaceSubClass, "%02x\n")
usb_intf_attr (bInterfaceProtocol, "%02x\n") usb_intf_attr (bInterfaceProtocol, "%02x\n")
usb_intf_attr (iInterface, "%02x\n")
void usb_create_driverfs_intf_files (struct usb_interface *intf) 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_bAlternateSetting);
device_create_file (&intf->dev, &dev_attr_bNumEndpoints);
device_create_file (&intf->dev, &dev_attr_bInterfaceClass); device_create_file (&intf->dev, &dev_attr_bInterfaceClass);
device_create_file (&intf->dev, &dev_attr_bInterfaceSubClass); device_create_file (&intf->dev, &dev_attr_bInterfaceSubClass);
device_create_file (&intf->dev, &dev_attr_bInterfaceProtocol); 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); ...@@ -254,6 +254,10 @@ extern void usb_set_maxpacket(struct usb_device *dev);
extern void usb_destroy_configuration(struct usb_device *dev); extern void usb_destroy_configuration(struct usb_device *dev);
extern int usb_set_address(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) ...@@ -1148,7 +1148,7 @@ void usb_hub_cleanup(void)
int ret; int ret;
/* Kill the thread */ /* Kill the thread */
ret = kill_proc(khubd_pid, SIGTERM, 1); ret = kill_proc(khubd_pid, SIGKILL, 1);
wait_for_completion(&khubd_exited); wait_for_completion(&khubd_exited);
......
...@@ -605,8 +605,10 @@ show_registers (struct device *dev, char *buf) ...@@ -605,8 +605,10 @@ show_registers (struct device *dev, char *buf)
} }
#ifdef EHCI_STATS #ifdef EHCI_STATS
temp = snprintf (next, size, "irq normal %ld err %ld reclaim %ld\n", temp = snprintf (next, size,
ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim); "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; size -= temp;
next += temp; next += temp;
......
...@@ -260,6 +260,7 @@ static void ehci_watchdog (unsigned long param) ...@@ -260,6 +260,7 @@ static void ehci_watchdog (unsigned long param)
if (status & STS_IAA) { if (status & STS_IAA) {
ehci_vdbg (ehci, "lost IAA\n"); ehci_vdbg (ehci, "lost IAA\n");
COUNT (ehci->stats.lost_iaa);
writel (STS_IAA, &ehci->regs->status); writel (STS_IAA, &ehci->regs->status);
ehci->reclaim_ready = 1; ehci->reclaim_ready = 1;
} }
...@@ -547,8 +548,9 @@ static void ehci_stop (struct usb_hcd *hcd) ...@@ -547,8 +548,9 @@ static void ehci_stop (struct usb_hcd *hcd)
ehci_mem_cleanup (ehci); ehci_mem_cleanup (ehci);
#ifdef EHCI_STATS #ifdef EHCI_STATS
ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld\n", ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld (lost %ld)\n",
ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim); ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim,
ehci->stats.lost_iaa);
ehci_dbg (ehci, "complete %ld unlink %ld\n", ehci_dbg (ehci, "complete %ld unlink %ld\n",
ehci->stats.complete, ehci->stats.unlink); ehci->stats.complete, ehci->stats.unlink);
#endif #endif
......
...@@ -800,6 +800,7 @@ static struct ehci_qh *qh_append_tds ( ...@@ -800,6 +800,7 @@ static struct ehci_qh *qh_append_tds (
&& !usb_pipecontrol (urb->pipe)) { && !usb_pipecontrol (urb->pipe)) {
/* "never happens": drivers do stall cleanup right */ /* "never happens": drivers do stall cleanup right */
if (qh->qh_state != QH_STATE_IDLE if (qh->qh_state != QH_STATE_IDLE
&& !list_empty (&qh->qtd_list)
&& qh->qh_state != QH_STATE_COMPLETING) && qh->qh_state != QH_STATE_COMPLETING)
ehci_warn (ehci, "clear toggle dev%d " ehci_warn (ehci, "clear toggle dev%d "
"ep%d%s: not idle\n", "ep%d%s: not idle\n",
...@@ -1014,6 +1015,7 @@ static void ...@@ -1014,6 +1015,7 @@ static void
scan_async (struct ehci_hcd *ehci, struct pt_regs *regs) scan_async (struct ehci_hcd *ehci, struct pt_regs *regs)
{ {
struct ehci_qh *qh; struct ehci_qh *qh;
int unlink_delay = 0;
if (!++(ehci->stamp)) if (!++(ehci->stamp))
ehci->stamp++; ehci->stamp++;
...@@ -1040,17 +1042,25 @@ scan_async (struct ehci_hcd *ehci, struct pt_regs *regs) ...@@ -1040,17 +1042,25 @@ scan_async (struct ehci_hcd *ehci, struct pt_regs *regs)
} }
} }
/* unlink idle entries, reducing HC PCI usage as /* unlink idle entries, reducing HC PCI usage as well
* well as HCD schedule-scanning costs. * as HCD schedule-scanning costs. delay for any qh
* * we just scanned, there's a not-unusual case that it
* FIXME don't unlink idle entries so quickly; it * doesn't stay idle for long.
* can penalize (common) half duplex protocols. * (plus, avoids some kind of re-activation race.)
*/ */
if (list_empty (&qh->qtd_list) && !ehci->reclaim) { if (list_empty (&qh->qtd_list)) {
if (qh->stamp == ehci->stamp)
unlink_delay = 1;
else if (!ehci->reclaim) {
start_unlink_async (ehci, qh); start_unlink_async (ehci, qh);
unlink_delay = 0;
}
} }
qh = qh->qh_next.qh; qh = qh->qh_next.qh;
} while (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 { ...@@ -27,6 +27,7 @@ struct ehci_stats {
unsigned long normal; unsigned long normal;
unsigned long error; unsigned long error;
unsigned long reclaim; unsigned long reclaim;
unsigned long lost_iaa;
/* termination of urbs from core */ /* termination of urbs from core */
unsigned long complete; unsigned long complete;
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
* *
* This file is licenced under the GPL. * This file is licenced under the GPL.
* $Id: ohci-dbg.c,v 1.4 2002/03/27 20:40:40 dbrownell Exp $
*/ */
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
...@@ -14,10 +13,10 @@ ...@@ -14,10 +13,10 @@
#define edstring(ed_type) ({ char *temp; \ #define edstring(ed_type) ({ char *temp; \
switch (ed_type) { \ switch (ed_type) { \
case PIPE_CONTROL: temp = "CTRL"; break; \ case PIPE_CONTROL: temp = "ctrl"; break; \
case PIPE_BULK: temp = "BULK"; break; \ case PIPE_BULK: temp = "bulk"; break; \
case PIPE_INTERRUPT: temp = "INTR"; break; \ case PIPE_INTERRUPT: temp = "intr"; break; \
default: temp = "ISOC"; break; \ default: temp = "isoc"; break; \
}; temp;}) }; temp;})
#define pipestring(pipe) edstring(usb_pipetype(pipe)) #define pipestring(pipe) edstring(usb_pipetype(pipe))
...@@ -37,12 +36,12 @@ urb_print (struct urb * urb, char * str, int small) ...@@ -37,12 +36,12 @@ urb_print (struct urb * urb, char * str, int small)
#ifndef OHCI_VERBOSE_DEBUG #ifndef OHCI_VERBOSE_DEBUG
if (urb->status != 0) if (urb->status != 0)
#endif #endif
dbg("%s %p dev:%d,ep=%d-%c,%s,flags:%x,len:%d/%d,stat:%d", dbg("%s %p dev=%d ep=%d%s-%s flags=%x len=%d/%d stat=%d",
str, str,
urb, urb,
usb_pipedevice (pipe), usb_pipedevice (pipe),
usb_pipeendpoint (pipe), usb_pipeendpoint (pipe),
usb_pipeout (pipe)? 'O': 'I', usb_pipeout (pipe)? "out" : "in",
pipestring (pipe), pipestring (pipe),
urb->transfer_flags, urb->transfer_flags,
urb->actual_length, urb->actual_length,
...@@ -73,9 +72,25 @@ urb_print (struct urb * urb, char * str, int small) ...@@ -73,9 +72,25 @@ urb_print (struct urb * urb, char * str, int small)
#endif #endif
} }
static void ohci_dump_intr_mask (struct device *dev, char *label, __u32 mask) #define ohci_dbg_sw(ohci, next, size, format, arg...) \
do { \
if (next) { \
unsigned s_len; \
s_len = snprintf (*next, *size, format, ## arg ); \
*size -= s_len; *next += s_len; \
} else \
ohci_dbg(ohci,format, ## arg ); \
} while (0);
static void ohci_dump_intr_mask (
struct ohci_hcd *ohci,
char *label,
u32 mask,
char **next,
unsigned *size)
{ {
dev_dbg (dev, "%s: 0x%08x%s%s%s%s%s%s%s%s%s\n", ohci_dbg_sw (ohci, next, size, "%s 0x%08x%s%s%s%s%s%s%s%s%s\n",
label, label,
mask, mask,
(mask & OHCI_INTR_MIE) ? " MIE" : "", (mask & OHCI_INTR_MIE) ? " MIE" : "",
...@@ -90,10 +105,15 @@ static void ohci_dump_intr_mask (struct device *dev, char *label, __u32 mask) ...@@ -90,10 +105,15 @@ static void ohci_dump_intr_mask (struct device *dev, char *label, __u32 mask)
); );
} }
static void maybe_print_eds (struct device *dev, char *label, __u32 value) static void maybe_print_eds (
struct ohci_hcd *ohci,
char *label,
u32 value,
char **next,
unsigned *size)
{ {
if (value) if (value)
dev_dbg (dev, "%s %08x\n", label, value); ohci_dbg_sw (ohci, next, size, "%s %08x\n", label, value);
} }
static char *hcfs2string (int state) static char *hcfs2string (int state)
...@@ -108,19 +128,22 @@ static char *hcfs2string (int state) ...@@ -108,19 +128,22 @@ static char *hcfs2string (int state)
} }
// dump control and status registers // dump control and status registers
static void ohci_dump_status (struct ohci_hcd *controller) static void
ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size)
{ {
struct ohci_regs *regs = controller->regs; struct ohci_regs *regs = controller->regs;
struct device *dev = controller->hcd.controller; u32 temp;
__u32 temp;
temp = readl (&regs->revision) & 0xff; temp = readl (&regs->revision) & 0xff;
dev_dbg (dev, "OHCI %d.%d, %s legacy support registers\n", ohci_dbg_sw (controller, next, size,
"OHCI %d.%d, %s legacy support registers\n",
0x03 & (temp >> 4), (temp & 0x0f), 0x03 & (temp >> 4), (temp & 0x0f),
(temp & 0x10) ? "with" : "NO"); (temp & 0x10) ? "with" : "NO");
temp = readl (&regs->control); temp = readl (&regs->control);
dev_dbg (dev, "control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d\n", temp, ohci_dbg_sw (controller, next, size,
"control 0x%03x%s%s%s HCFS=%s%s%s%s%s CBSR=%d\n",
temp,
(temp & OHCI_CTRL_RWE) ? " RWE" : "", (temp & OHCI_CTRL_RWE) ? " RWE" : "",
(temp & OHCI_CTRL_RWC) ? " RWC" : "", (temp & OHCI_CTRL_RWC) ? " RWC" : "",
(temp & OHCI_CTRL_IR) ? " IR" : "", (temp & OHCI_CTRL_IR) ? " IR" : "",
...@@ -133,7 +156,8 @@ static void ohci_dump_status (struct ohci_hcd *controller) ...@@ -133,7 +156,8 @@ static void ohci_dump_status (struct ohci_hcd *controller)
); );
temp = readl (&regs->cmdstatus); temp = readl (&regs->cmdstatus);
dev_dbg (dev, "cmdstatus: 0x%08x SOC=%d%s%s%s%s\n", temp, ohci_dbg_sw (controller, next, size,
"cmdstatus 0x%05x SOC=%d%s%s%s%s\n", temp,
(temp & OHCI_SOC) >> 16, (temp & OHCI_SOC) >> 16,
(temp & OHCI_OCR) ? " OCR" : "", (temp & OHCI_OCR) ? " OCR" : "",
(temp & OHCI_BLF) ? " BLF" : "", (temp & OHCI_BLF) ? " BLF" : "",
...@@ -141,25 +165,59 @@ static void ohci_dump_status (struct ohci_hcd *controller) ...@@ -141,25 +165,59 @@ static void ohci_dump_status (struct ohci_hcd *controller)
(temp & OHCI_HCR) ? " HCR" : "" (temp & OHCI_HCR) ? " HCR" : ""
); );
ohci_dump_intr_mask (dev, "intrstatus", readl (&regs->intrstatus)); ohci_dump_intr_mask (controller, "intrstatus",
ohci_dump_intr_mask (dev, "intrenable", readl (&regs->intrenable)); readl (&regs->intrstatus), next, size);
ohci_dump_intr_mask (controller, "intrenable",
readl (&regs->intrenable), next, size);
// intrdisable always same as intrenable // intrdisable always same as intrenable
// ohci_dump_intr_mask (dev, "intrdisable", readl (&regs->intrdisable));
maybe_print_eds (dev, "ed_periodcurrent", readl (&regs->ed_periodcurrent)); maybe_print_eds (controller, "ed_periodcurrent",
readl (&regs->ed_periodcurrent), next, size);
maybe_print_eds (dev, "ed_controlhead", readl (&regs->ed_controlhead)); maybe_print_eds (controller, "ed_controlhead",
maybe_print_eds (dev, "ed_controlcurrent", readl (&regs->ed_controlcurrent)); readl (&regs->ed_controlhead), next, size);
maybe_print_eds (controller, "ed_controlcurrent",
readl (&regs->ed_controlcurrent), next, size);
maybe_print_eds (dev, "ed_bulkhead", readl (&regs->ed_bulkhead)); maybe_print_eds (controller, "ed_bulkhead",
maybe_print_eds (dev, "ed_bulkcurrent", readl (&regs->ed_bulkcurrent)); readl (&regs->ed_bulkhead), next, size);
maybe_print_eds (controller, "ed_bulkcurrent",
readl (&regs->ed_bulkcurrent), next, size);
maybe_print_eds (dev, "donehead", readl (&regs->donehead)); maybe_print_eds (controller, "donehead",
readl (&regs->donehead), next, size);
} }
static void ohci_dump_roothub (struct ohci_hcd *controller, int verbose) #define dbg_port_sw(hc,num,value,next,size) \
ohci_dbg_sw (hc, next, size, \
"roothub.portstatus [%d] " \
"0x%08x%s%s%s%s%s%s%s%s%s%s%s%s\n", \
num, temp, \
(temp & RH_PS_PRSC) ? " PRSC" : "", \
(temp & RH_PS_OCIC) ? " OCIC" : "", \
(temp & RH_PS_PSSC) ? " PSSC" : "", \
(temp & RH_PS_PESC) ? " PESC" : "", \
(temp & RH_PS_CSC) ? " CSC" : "", \
\
(temp & RH_PS_LSDA) ? " LSDA" : "", \
(temp & RH_PS_PPS) ? " PPS" : "", \
(temp & RH_PS_PRS) ? " PRS" : "", \
(temp & RH_PS_POCI) ? " POCI" : "", \
(temp & RH_PS_PSS) ? " PSS" : "", \
\
(temp & RH_PS_PES) ? " PES" : "", \
(temp & RH_PS_CCS) ? " CCS" : "" \
);
static void
ohci_dump_roothub (
struct ohci_hcd *controller,
int verbose,
char **next,
unsigned *size)
{ {
__u32 temp, ndp, i; u32 temp, ndp, i;
temp = roothub_a (controller); temp = roothub_a (controller);
if (temp == ~(u32)0) if (temp == ~(u32)0)
...@@ -167,8 +225,8 @@ static void ohci_dump_roothub (struct ohci_hcd *controller, int verbose) ...@@ -167,8 +225,8 @@ static void ohci_dump_roothub (struct ohci_hcd *controller, int verbose)
ndp = (temp & RH_A_NDP); ndp = (temp & RH_A_NDP);
if (verbose) { if (verbose) {
dev_dbg (controller->hcd.controller, ohci_dbg_sw (controller, next, size,
"roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d\n", temp, "roothub.a %08x POTPGT=%d%s%s%s%s%s NDP=%d\n", temp,
((temp & RH_A_POTPGT) >> 24) & 0xff, ((temp & RH_A_POTPGT) >> 24) & 0xff,
(temp & RH_A_NOCP) ? " NOCP" : "", (temp & RH_A_NOCP) ? " NOCP" : "",
(temp & RH_A_OCPM) ? " OCPM" : "", (temp & RH_A_OCPM) ? " OCPM" : "",
...@@ -178,15 +236,15 @@ static void ohci_dump_roothub (struct ohci_hcd *controller, int verbose) ...@@ -178,15 +236,15 @@ static void ohci_dump_roothub (struct ohci_hcd *controller, int verbose)
ndp ndp
); );
temp = roothub_b (controller); temp = roothub_b (controller);
dev_dbg (controller->hcd.controller, ohci_dbg_sw (controller, next, size,
"roothub.b: %08x PPCM=%04x DR=%04x\n", "roothub.b %08x PPCM=%04x DR=%04x\n",
temp, temp,
(temp & RH_B_PPCM) >> 16, (temp & RH_B_PPCM) >> 16,
(temp & RH_B_DR) (temp & RH_B_DR)
); );
temp = roothub_status (controller); temp = roothub_status (controller);
dev_dbg (controller->hcd.controller, ohci_dbg_sw (controller, next, size,
"roothub.status: %08x%s%s%s%s%s%s\n", "roothub.status %08x%s%s%s%s%s%s\n",
temp, temp,
(temp & RH_HS_CRWE) ? " CRWE" : "", (temp & RH_HS_CRWE) ? " CRWE" : "",
(temp & RH_HS_OCIC) ? " OCIC" : "", (temp & RH_HS_OCIC) ? " OCIC" : "",
...@@ -199,31 +257,30 @@ static void ohci_dump_roothub (struct ohci_hcd *controller, int verbose) ...@@ -199,31 +257,30 @@ static void ohci_dump_roothub (struct ohci_hcd *controller, int verbose)
for (i = 0; i < ndp; i++) { for (i = 0; i < ndp; i++) {
temp = roothub_portstatus (controller, i); temp = roothub_portstatus (controller, i);
dbg_port (controller, "", i, temp); dbg_port_sw (controller, i, temp, next, size);
} }
} }
static void ohci_dump (struct ohci_hcd *controller, int verbose) static void ohci_dump (struct ohci_hcd *controller, int verbose)
{ {
dev_dbg (controller->hcd.controller, ohci_dbg (controller, "OHCI controller state\n");
"OHCI controller state\n");
// dumps some of the state we know about // dumps some of the state we know about
ohci_dump_status (controller); ohci_dump_status (controller, NULL, 0);
if (controller->hcca) if (controller->hcca)
dev_dbg (controller->hcd.controller, ohci_dbg (controller,
"hcca frame #%04x\n", controller->hcca->frame_no); "hcca frame #%04x\n", controller->hcca->frame_no);
ohci_dump_roothub (controller, 1); ohci_dump_roothub (controller, 1, NULL, 0);
} }
static const char data0 [] = "DATA0"; static const char data0 [] = "DATA0";
static const char data1 [] = "DATA1"; static const char data1 [] = "DATA1";
static void ohci_dump_td (char *label, struct td *td) static void ohci_dump_td (struct ohci_hcd *ohci, char *label, struct td *td)
{ {
u32 tmp = le32_to_cpup (&td->hwINFO); u32 tmp = le32_to_cpup (&td->hwINFO);
dbg ("%s td %p%s; urb %p index %d; hw next td %08x", ohci_dbg (ohci, "%s td %p%s; urb %p index %d; hw next td %08x",
label, td, label, td,
(tmp & TD_DONE) ? " (DONE)" : "", (tmp & TD_DONE) ? " (DONE)" : "",
td->urb, td->index, td->urb, td->index,
...@@ -244,28 +301,28 @@ static void ohci_dump_td (char *label, struct td *td) ...@@ -244,28 +301,28 @@ static void ohci_dump_td (char *label, struct td *td)
case TD_DP_OUT: pid = "OUT"; break; case TD_DP_OUT: pid = "OUT"; break;
default: pid = "(bad pid)"; break; default: pid = "(bad pid)"; break;
} }
dbg (" info %08x CC=%x %s DI=%d %s %s", tmp, ohci_dbg (ohci, " info %08x CC=%x %s DI=%d %s %s", tmp,
TD_CC_GET(tmp), /* EC, */ toggle, TD_CC_GET(tmp), /* EC, */ toggle,
(tmp & TD_DI) >> 21, pid, (tmp & TD_DI) >> 21, pid,
(tmp & TD_R) ? "R" : ""); (tmp & TD_R) ? "R" : "");
cbp = le32_to_cpup (&td->hwCBP); cbp = le32_to_cpup (&td->hwCBP);
be = le32_to_cpup (&td->hwBE); be = le32_to_cpup (&td->hwBE);
dbg (" cbp %08x be %08x (len %d)", cbp, be, ohci_dbg (ohci, " cbp %08x be %08x (len %d)", cbp, be,
cbp ? (be + 1 - cbp) : 0); cbp ? (be + 1 - cbp) : 0);
} else { } else {
unsigned i; unsigned i;
dbg (" info %08x CC=%x FC=%d DI=%d SF=%04x", tmp, ohci_dbg (ohci, " info %08x CC=%x FC=%d DI=%d SF=%04x", tmp,
TD_CC_GET(tmp), TD_CC_GET(tmp),
(tmp >> 24) & 0x07, (tmp >> 24) & 0x07,
(tmp & TD_DI) >> 21, (tmp & TD_DI) >> 21,
tmp & 0x0000ffff); tmp & 0x0000ffff);
dbg (" bp0 %08x be %08x", ohci_dbg (ohci, " bp0 %08x be %08x",
le32_to_cpup (&td->hwCBP) & ~0x0fff, le32_to_cpup (&td->hwCBP) & ~0x0fff,
le32_to_cpup (&td->hwBE)); le32_to_cpup (&td->hwBE));
for (i = 0; i < MAXPSW; i++) { for (i = 0; i < MAXPSW; i++) {
u16 psw = le16_to_cpup (&td->hwPSW [i]); u16 psw = le16_to_cpup (&td->hwPSW [i]);
int cc = (psw >> 12) & 0x0f; int cc = (psw >> 12) & 0x0f;
dbg (" psw [%d] = %2x, CC=%x %s=%d", i, ohci_dbg (ohci, " psw [%d] = %2x, CC=%x %s=%d", i,
psw, cc, psw, cc,
(cc >= 0x0e) ? "OFFSET" : "SIZE", (cc >= 0x0e) ? "OFFSET" : "SIZE",
psw & 0x0fff); psw & 0x0fff);
...@@ -280,8 +337,8 @@ ohci_dump_ed (struct ohci_hcd *ohci, char *label, struct ed *ed, int verbose) ...@@ -280,8 +337,8 @@ ohci_dump_ed (struct ohci_hcd *ohci, char *label, struct ed *ed, int verbose)
u32 tmp = ed->hwINFO; u32 tmp = ed->hwINFO;
char *type = ""; char *type = "";
dbg ("%s: %s, ed %p state 0x%x type %s; next ed %08x", ohci_dbg (ohci, "%s, ed %p state 0x%x type %s; next ed %08x",
ohci->hcd.self.bus_name, label, label,
ed, ed->state, edstring (ed->type), ed, ed->state, edstring (ed->type),
le32_to_cpup (&ed->hwNextED)); le32_to_cpup (&ed->hwNextED));
switch (tmp & (ED_IN|ED_OUT)) { switch (tmp & (ED_IN|ED_OUT)) {
...@@ -289,7 +346,8 @@ ohci_dump_ed (struct ohci_hcd *ohci, char *label, struct ed *ed, int verbose) ...@@ -289,7 +346,8 @@ ohci_dump_ed (struct ohci_hcd *ohci, char *label, struct ed *ed, int verbose)
case ED_IN: type = "-IN"; break; case ED_IN: type = "-IN"; break;
/* else from TDs ... control */ /* else from TDs ... control */
} }
dbg (" info %08x MAX=%d%s%s%s%s EP=%d%s DEV=%d", le32_to_cpu (tmp), ohci_dbg (ohci,
" info %08x MAX=%d%s%s%s%s EP=%d%s DEV=%d", le32_to_cpu (tmp),
0x03ff & (le32_to_cpu (tmp) >> 16), 0x03ff & (le32_to_cpu (tmp) >> 16),
(tmp & ED_DEQUEUE) ? " DQ" : "", (tmp & ED_DEQUEUE) ? " DQ" : "",
(tmp & ED_ISO) ? " ISO" : "", (tmp & ED_ISO) ? " ISO" : "",
...@@ -298,7 +356,7 @@ ohci_dump_ed (struct ohci_hcd *ohci, char *label, struct ed *ed, int verbose) ...@@ -298,7 +356,7 @@ ohci_dump_ed (struct ohci_hcd *ohci, char *label, struct ed *ed, int verbose)
0x000f & (le32_to_cpu (tmp) >> 7), 0x000f & (le32_to_cpu (tmp) >> 7),
type, type,
0x007f & le32_to_cpu (tmp)); 0x007f & le32_to_cpu (tmp));
dbg (" tds: head %08x %s%s tail %08x%s", ohci_dbg (ohci, " tds: head %08x %s%s tail %08x%s",
tmp = le32_to_cpup (&ed->hwHeadP), tmp = le32_to_cpup (&ed->hwHeadP),
(ed->hwHeadP & ED_C) ? data1 : data0, (ed->hwHeadP & ED_C) ? data1 : data0,
(ed->hwHeadP & ED_H) ? " HALT" : "", (ed->hwHeadP & ED_H) ? " HALT" : "",
...@@ -313,21 +371,33 @@ ohci_dump_ed (struct ohci_hcd *ohci, char *label, struct ed *ed, int verbose) ...@@ -313,21 +371,33 @@ ohci_dump_ed (struct ohci_hcd *ohci, char *label, struct ed *ed, int verbose)
list_for_each (tmp, &ed->td_list) { list_for_each (tmp, &ed->td_list) {
struct td *td; struct td *td;
td = list_entry (tmp, struct td, td_list); td = list_entry (tmp, struct td, td_list);
ohci_dump_td (" ->", td); ohci_dump_td (ohci, " ->", td);
} }
} }
} }
#define DRIVERFS_DEBUG_FILES /* only on 2.5 versions */
#else #else
static inline void ohci_dump (struct ohci_hcd *controller, int verbose) {} static inline void ohci_dump (struct ohci_hcd *controller, int verbose) {}
#undef OHCI_VERBOSE_DEBUG
#endif /* DEBUG */ #endif /* DEBUG */
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
#ifdef DRIVERFS_DEBUG_FILES #ifdef STUB_DEBUG_FILES
static inline void create_debug_files (struct ohci_hcd *bus) { }
static inline void remove_debug_files (struct ohci_hcd *bus) { }
#else
static inline struct ohci_hcd *dev_to_ohci (struct device *dev)
{
struct usb_hcd *hcd = dev_get_drvdata (dev);
return hcd_to_ohci (hcd);
}
static ssize_t static ssize_t
show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed) show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed)
...@@ -349,7 +419,7 @@ show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed) ...@@ -349,7 +419,7 @@ show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed)
struct td *td; struct td *td;
temp = snprintf (buf, size, temp = snprintf (buf, size,
"ed/%p %cs dev%d ep%d-%s max %d %08x%s%s %s", "ed/%p %cs dev%d ep%d%s max %d %08x%s%s %s",
ed, ed,
(info & ED_LOWSPEED) ? 'l' : 'f', (info & ED_LOWSPEED) ? 'l' : 'f',
scratch & 0x7f, scratch & 0x7f,
...@@ -465,7 +535,7 @@ show_periodic (struct device *dev, char *buf) ...@@ -465,7 +535,7 @@ show_periodic (struct device *dev, char *buf)
u32 scratch = cpu_to_le32p (&ed->hwINFO); u32 scratch = cpu_to_le32p (&ed->hwINFO);
temp = snprintf (next, size, temp = snprintf (next, size,
" (%cs dev%d%s ep%d-%s" " (%cs dev%d%s ep%d%s"
" max %d %08x%s%s)", " max %d %08x%s%s)",
(info & ED_LOWSPEED) ? 'l' : 'f', (info & ED_LOWSPEED) ? 'l' : 'f',
scratch & 0x7f, scratch & 0x7f,
...@@ -508,26 +578,89 @@ static DEVICE_ATTR (periodic, S_IRUGO, show_periodic, NULL); ...@@ -508,26 +578,89 @@ static DEVICE_ATTR (periodic, S_IRUGO, show_periodic, NULL);
#undef DBG_SCHED_LIMIT #undef DBG_SCHED_LIMIT
static ssize_t
show_registers (struct device *dev, char *buf)
{
struct ohci_hcd *ohci;
struct ohci_regs *regs;
unsigned long flags;
unsigned temp, size;
char *next;
u32 rdata;
ohci = dev_to_ohci(dev);
regs = ohci->regs;
next = buf;
size = PAGE_SIZE;
spin_lock_irqsave (&ohci->lock, flags);
/* dump driver info, then registers in spec order */
ohci_dbg_sw (ohci, &next, &size,
"%s version " DRIVER_VERSION "\n", hcd_name);
ohci_dump_status(ohci, &next, &size);
/* hcca */
if (ohci->hcca)
ohci_dbg_sw (ohci, &next, &size,
"hcca frame 0x%04x\n", ohci->hcca->frame_no);
/* other registers mostly affect frame timings */
rdata = readl (&regs->fminterval);
temp = snprintf (next, size,
"fmintvl 0x%08x %sFSMPS=0x%04x FI=0x%04x\n",
rdata, (rdata >> 31) ? " FIT" : "",
(rdata >> 16) & 0xefff, rdata & 0xffff);
size -= temp;
next += temp;
rdata = readl (&regs->fmremaining);
temp = snprintf (next, size, "fmremaining 0x%08x %sFR=0x%04x\n",
rdata, (rdata >> 31) ? " FRT" : "",
rdata & 0x3fff);
size -= temp;
next += temp;
rdata = readl (&regs->periodicstart);
temp = snprintf (next, size, "periodicstart 0x%04x\n",
rdata & 0x3fff);
size -= temp;
next += temp;
rdata = readl (&regs->lsthresh);
temp = snprintf (next, size, "lsthresh 0x%04x\n",
rdata & 0x3fff);
size -= temp;
next += temp;
/* roothub */
ohci_dump_roothub (ohci, 1, &next, &size);
spin_unlock_irqrestore (&ohci->lock, flags);
return PAGE_SIZE - size;
}
static DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL);
static inline void create_debug_files (struct ohci_hcd *bus) static inline void create_debug_files (struct ohci_hcd *bus)
{ {
device_create_file (bus->hcd.controller, &dev_attr_async); device_create_file (bus->hcd.controller, &dev_attr_async);
device_create_file (bus->hcd.controller, &dev_attr_periodic); device_create_file (bus->hcd.controller, &dev_attr_periodic);
// registers device_create_file (bus->hcd.controller, &dev_attr_registers);
dev_dbg (bus->hcd.controller, "created debug files\n"); ohci_dbg (bus, "created debug files\n");
} }
static inline void remove_debug_files (struct ohci_hcd *bus) static inline void remove_debug_files (struct ohci_hcd *bus)
{ {
device_remove_file (bus->hcd.controller, &dev_attr_async); device_remove_file (bus->hcd.controller, &dev_attr_async);
device_remove_file (bus->hcd.controller, &dev_attr_periodic); device_remove_file (bus->hcd.controller, &dev_attr_periodic);
device_remove_file (bus->hcd.controller, &dev_attr_registers);
} }
#else /* empty stubs for creating those files */ #endif
static inline void create_debug_files (struct ohci_hcd *bus) { }
static inline void remove_debug_files (struct ohci_hcd *bus) { }
#endif /* DRIVERFS_DEBUG_FILES */
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
* *
* History: * History:
* *
* 2003/02/24 show registers in sysfs (Kevin Brosius)
*
* 2002/09/03 get rid of ed hashtables, rework periodic scheduling and * 2002/09/03 get rid of ed hashtables, rework periodic scheduling and
* bandwidth accounting; if debugging, show schedules in driverfs * bandwidth accounting; if debugging, show schedules in driverfs
* 2002/07/19 fixes to management of ED and schedule state. * 2002/07/19 fixes to management of ED and schedule state.
...@@ -105,11 +107,10 @@ ...@@ -105,11 +107,10 @@
* TO DO: * TO DO:
* *
* - "disabled" and "sleeping" should be in hcd->state * - "disabled" and "sleeping" should be in hcd->state
* - bandwidth alloc to generic code
* - lots more testing!! * - lots more testing!!
*/ */
#define DRIVER_VERSION "2002-Sep-17" #define DRIVER_VERSION "2003 Feb 24"
#define DRIVER_AUTHOR "Roman Weissgaerber, David Brownell" #define DRIVER_AUTHOR "Roman Weissgaerber, David Brownell"
#define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver" #define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver"
...@@ -125,6 +126,8 @@ ...@@ -125,6 +126,8 @@
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static const char hcd_name [] = "ohci-hcd";
#include "ohci.h" #include "ohci.h"
static inline void disable (struct ohci_hcd *ohci) static inline void disable (struct ohci_hcd *ohci)
...@@ -275,6 +278,7 @@ static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) ...@@ -275,6 +278,7 @@ static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
urb_print (urb, "UNLINK", 1); urb_print (urb, "UNLINK", 1);
#endif #endif
spin_lock_irqsave (&ohci->lock, flags);
if (!ohci->disabled) { if (!ohci->disabled) {
urb_priv_t *urb_priv; urb_priv_t *urb_priv;
...@@ -282,21 +286,24 @@ static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) ...@@ -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 * handed to us, flag it for unlink and giveback, and force
* some upcoming INTR_SF to call finish_unlinks() * some upcoming INTR_SF to call finish_unlinks()
*/ */
spin_lock_irqsave (&ohci->lock, flags);
urb_priv = urb->hcpriv; urb_priv = urb->hcpriv;
if (urb_priv) { if (urb_priv) {
urb_priv->state = URB_DEL; urb_priv->state = URB_DEL;
if (urb_priv->ed->state == ED_OPER) if (urb_priv->ed->state == ED_OPER)
start_urb_unlink (ohci, urb_priv->ed); start_urb_unlink (ohci, urb_priv->ed);
} }
spin_unlock_irqrestore (&ohci->lock, flags);
} else { } else {
/* /*
* with HC dead, we won't respect hc queue pointers * with HC dead, we won't respect hc queue pointers
* any more ... just clean up every urb's memory. * any more ... just clean up every urb's memory.
*/ */
if (urb->hcpriv) {
spin_unlock (&ohci->lock);
finish_urb (ohci, urb, NULL); finish_urb (ohci, urb, NULL);
spin_lock (&ohci->lock);
} }
}
spin_unlock_irqrestore (&ohci->lock, flags);
return 0; return 0;
} }
...@@ -332,9 +339,11 @@ ohci_free_config (struct usb_hcd *hcd, struct usb_device *udev) ...@@ -332,9 +339,11 @@ ohci_free_config (struct usb_hcd *hcd, struct usb_device *udev)
td_free (ohci, ed->dummy); td_free (ohci, ed->dummy);
break; break;
default: default:
err ("%s-%s ed %p (#%d) not unlinked; disconnect() bug? %d", ohci_err (ohci,
ohci->hcd.self.bus_name, udev->devpath, ed, "dev %s ep%d-%s linked; disconnect() bug?\n",
i, ed->state); udev->devpath,
(i >> 1) & 0x0f, (i & 1) ? "out" : "in");
/* ED_OPER: some driver disconnect() is broken, /* ED_OPER: some driver disconnect() is broken,
* it didn't even start its unlinks much less wait * it didn't even start its unlinks much less wait
* for their completions. * for their completions.
...@@ -354,8 +363,10 @@ ohci_free_config (struct usb_hcd *hcd, struct usb_device *udev) ...@@ -354,8 +363,10 @@ ohci_free_config (struct usb_hcd *hcd, struct usb_device *udev)
#ifdef DEBUG #ifdef DEBUG
/* a driver->disconnect() returned before its unlinks completed? */ /* a driver->disconnect() returned before its unlinks completed? */
if (in_interrupt ()) { if (in_interrupt ()) {
warn ("disconnect() bug for dev usb-%s-%s ep 0x%x", ohci_warn (ohci,
ohci->hcd.self.bus_name, udev->devpath, i); "driver disconnect() bug %s ep%d-%s\n",
udev->devpath,
(i >> 1) & 0x0f, (i & 1) ? "out" : "in");
} }
#endif #endif
...@@ -381,9 +392,12 @@ static int hc_reset (struct ohci_hcd *ohci) ...@@ -381,9 +392,12 @@ static int hc_reset (struct ohci_hcd *ohci)
{ {
u32 temp; 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) { 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 /* this timeout is arbitrary. we make it long, so systems
* depending on usb keyboards may be usable even if the * depending on usb keyboards may be usable even if the
...@@ -396,17 +410,18 @@ static int hc_reset (struct ohci_hcd *ohci) ...@@ -396,17 +410,18 @@ static int hc_reset (struct ohci_hcd *ohci)
while (readl (&ohci->regs->control) & OHCI_CTRL_IR) { while (readl (&ohci->regs->control) & OHCI_CTRL_IR) {
wait_ms (10); wait_ms (10);
if (--temp == 0) { if (--temp == 0) {
dev_err (ohci->hcd.controller, "USB HC TakeOver failed!\n"); ohci_err (ohci, "USB HC TakeOver failed!\n");
return -1; return -1;
} }
} }
} }
#endif
/* Disable HC interrupts */ /* Disable HC interrupts */
writel (OHCI_INTR_MIE, &ohci->regs->intrdisable); writel (OHCI_INTR_MIE, &ohci->regs->intrdisable);
dev_dbg (ohci->hcd.controller, "USB HC reset_hc %s: ctrl = 0x%x ;\n", ohci_dbg (ohci, "USB HC reset_hc %s: ctrl = 0x%x ;\n",
ohci->hcd.self.bus_name, hcd_to_bus (&ohci->hcd)->bus_name,
readl (&ohci->regs->control)); readl (&ohci->regs->control));
/* Reset USB (needed by some controllers); RemoteWakeupConnected /* Reset USB (needed by some controllers); RemoteWakeupConnected
...@@ -422,7 +437,7 @@ static int hc_reset (struct ohci_hcd *ohci) ...@@ -422,7 +437,7 @@ static int hc_reset (struct ohci_hcd *ohci)
temp = 30; /* ... allow extra time */ temp = 30; /* ... allow extra time */
while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) { while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) {
if (--temp == 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; return -1;
} }
udelay (1); udelay (1);
...@@ -451,8 +466,9 @@ static int hc_reset (struct ohci_hcd *ohci) ...@@ -451,8 +466,9 @@ static int hc_reset (struct ohci_hcd *ohci)
*/ */
static int hc_start (struct ohci_hcd *ohci) static int hc_start (struct ohci_hcd *ohci)
{ {
u32 mask; u32 mask, tmp;
struct usb_device *udev; struct usb_device *udev;
struct usb_bus *bus;
spin_lock_init (&ohci->lock); spin_lock_init (&ohci->lock);
ohci->disabled = 1; ohci->disabled = 1;
...@@ -478,7 +494,7 @@ static int hc_start (struct ohci_hcd *ohci) ...@@ -478,7 +494,7 @@ static int hc_start (struct ohci_hcd *ohci)
*/ */
if ((readl (&ohci->regs->fminterval) & 0x3fff0000) == 0 if ((readl (&ohci->regs->fminterval) & 0x3fff0000) == 0
|| !readl (&ohci->regs->periodicstart)) { || !readl (&ohci->regs->periodicstart)) {
err ("%s init err", ohci->hcd.self.bus_name); ohci_err (ohci, "init err\n");
return -EOVERFLOW; return -EOVERFLOW;
} }
...@@ -493,9 +509,20 @@ static int hc_start (struct ohci_hcd *ohci) ...@@ -493,9 +509,20 @@ static int hc_start (struct ohci_hcd *ohci)
writel (mask, &ohci->regs->intrstatus); writel (mask, &ohci->regs->intrstatus);
writel (mask, &ohci->regs->intrenable); writel (mask, &ohci->regs->intrenable);
/* hub power always on: required for AMD-756 and some Mac platforms */ /* handle root hub init quirks ... */
writel ((roothub_a (ohci) | RH_A_NPS) & ~(RH_A_PSM | RH_A_OCPM), tmp = roothub_a (ohci);
&ohci->regs->roothub.a); 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 (RH_HS_LPSC, &ohci->regs->roothub.status);
writel (0, &ohci->regs->roothub.b); writel (0, &ohci->regs->roothub.b);
...@@ -503,7 +530,8 @@ static int hc_start (struct ohci_hcd *ohci) ...@@ -503,7 +530,8 @@ static int hc_start (struct ohci_hcd *ohci)
mdelay ((roothub_a (ohci) >> 23) & 0x1fe); mdelay ((roothub_a (ohci) >> 23) & 0x1fe);
/* connect the virtual root hub */ /* 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; ohci->hcd.state = USB_STATE_READY;
if (!udev) { if (!udev) {
disable (ohci); disable (ohci);
...@@ -514,9 +542,9 @@ static int hc_start (struct ohci_hcd *ohci) ...@@ -514,9 +542,9 @@ static int hc_start (struct ohci_hcd *ohci)
usb_connect (udev); usb_connect (udev);
udev->speed = USB_SPEED_FULL; 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); usb_put_dev (udev);
ohci->hcd.self.root_hub = NULL; bus->root_hub = NULL;
disable (ohci); disable (ohci);
ohci->hc_control &= ~OHCI_CTRL_HCFS; ohci->hc_control &= ~OHCI_CTRL_HCFS;
writel (ohci->hc_control, &ohci->regs->control); writel (ohci->hc_control, &ohci->regs->control);
...@@ -545,7 +573,7 @@ static void ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs) ...@@ -545,7 +573,7 @@ static void ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
/* cardbus/... hardware gone before remove() */ /* cardbus/... hardware gone before remove() */
} else if ((ints = readl (&regs->intrstatus)) == ~(u32)0) { } else if ((ints = readl (&regs->intrstatus)) == ~(u32)0) {
disable (ohci); disable (ohci);
dbg ("%s device removed!", hcd->self.bus_name); ohci_dbg (ohci, "device removed!\n");
return; return;
/* interrupt for some other device? */ /* interrupt for some other device? */
...@@ -553,13 +581,9 @@ static void ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs) ...@@ -553,13 +581,9 @@ static void ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
return; return;
} }
// dbg ("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no));
if (ints & OHCI_INTR_UE) { if (ints & OHCI_INTR_UE) {
disable (ohci); disable (ohci);
err ("OHCI Unrecoverable Error, %s disabled", ohci_err (ohci, "OHCI Unrecoverable Error, disabled\n");
hcd->self.bus_name);
// e.g. due to PCI Master/Target Abort // e.g. due to PCI Master/Target Abort
ohci_dump (ohci, 1); ohci_dump (ohci, 1);
...@@ -579,7 +603,8 @@ static void ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs) ...@@ -579,7 +603,8 @@ static void ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
*/ */
spin_lock (&ohci->lock); spin_lock (&ohci->lock);
if (ohci->ed_rm_list) 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) if ((ints & OHCI_INTR_SF) != 0 && !ohci->ed_rm_list)
writel (OHCI_INTR_SF, &regs->intrdisable); writel (OHCI_INTR_SF, &regs->intrdisable);
spin_unlock (&ohci->lock); spin_unlock (&ohci->lock);
...@@ -594,7 +619,7 @@ static void ohci_stop (struct usb_hcd *hcd) ...@@ -594,7 +619,7 @@ static void ohci_stop (struct usb_hcd *hcd)
{ {
struct ohci_hcd *ohci = hcd_to_ohci (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), hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS),
ohci->disabled ? " (disabled)" : "" ohci->disabled ? " (disabled)" : ""
); );
...@@ -629,8 +654,8 @@ static int hc_restart (struct ohci_hcd *ohci) ...@@ -629,8 +654,8 @@ static int hc_restart (struct ohci_hcd *ohci)
ohci->disabled = 1; ohci->disabled = 1;
ohci->sleeping = 0; ohci->sleeping = 0;
if (ohci->hcd.self.root_hub) if (hcd_to_bus (&ohci->hcd)->root_hub)
usb_disconnect (&ohci->hcd.self.root_hub); usb_disconnect (&hcd_to_bus (&ohci->hcd)->root_hub);
/* empty the interrupt branches */ /* empty the interrupt branches */
for (i = 0; i < NUM_INTS; i++) ohci->load [i] = 0; for (i = 0; i < NUM_INTS; i++) ohci->load [i] = 0;
...@@ -644,18 +669,16 @@ static int hc_restart (struct ohci_hcd *ohci) ...@@ -644,18 +669,16 @@ static int hc_restart (struct ohci_hcd *ohci)
ohci->ed_bulktail = NULL; ohci->ed_bulktail = NULL;
if ((temp = hc_reset (ohci)) < 0 || (temp = hc_start (ohci)) < 0) { 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; return temp;
} else } else
dbg ("restart %s completed", ohci->hcd.self.bus_name); ohci_dbg (ohci, "restart complete\n");
return 0; return 0;
} }
#endif #endif
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static const char hcd_name [] = "ohci-hcd";
#define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC #define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC
MODULE_AUTHOR (DRIVER_AUTHOR); MODULE_AUTHOR (DRIVER_AUTHOR);
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
* *
* This file is licenced under GPL * 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) ...@@ -41,7 +40,7 @@ static u32 roothub_portstatus (struct ohci_hcd *hc, int i)
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
#define dbg_port(hc,label,num,value) \ #define dbg_port(hc,label,num,value) \
dev_dbg (hc->hcd.controller, \ ohci_dbg (hc, \
"%s roothub.portstatus [%d] " \ "%s roothub.portstatus [%d] " \
"= 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s\n", \ "= 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s\n", \
label, num, temp, \ label, num, temp, \
...@@ -76,9 +75,8 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) ...@@ -76,9 +75,8 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
if (ports > MAX_ROOT_PORTS) { if (ports > MAX_ROOT_PORTS) {
if (ohci->disabled) if (ohci->disabled)
return -ESHUTDOWN; return -ESHUTDOWN;
err ("%s bogus NDP=%d, rereads as NDP=%d", ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n",
hcd->self.bus_name, ports, ports, readl (&ohci->regs->roothub.a) & RH_A_NDP);
readl (&ohci->regs->roothub.a) & RH_A_NDP);
/* retry later; "should not happen" */ /* retry later; "should not happen" */
return 0; return 0;
} }
...@@ -159,7 +157,7 @@ static int ohci_hub_control ( ...@@ -159,7 +157,7 @@ static int ohci_hub_control (
u16 wLength u16 wLength
) { ) {
struct ohci_hcd *ohci = hcd_to_ohci (hcd); 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; u32 temp;
int retval = 0; int retval = 0;
......
...@@ -115,8 +115,8 @@ td_free (struct ohci_hcd *hc, struct td *td) ...@@ -115,8 +115,8 @@ td_free (struct ohci_hcd *hc, struct td *td)
prev = &(*prev)->td_hash; prev = &(*prev)->td_hash;
if (*prev) if (*prev)
*prev = td->td_hash; *prev = td->td_hash;
else else if ((td->hwINFO & TD_DONE) != 0)
dev_dbg (hc->hcd.controller, "bad hash for td %p\n", td); ohci_dbg (hc, "no hash for td %p\n", td);
pci_pool_free (hc->td_cache, td, td->td_dma); pci_pool_free (hc->td_cache, td, td->td_dma);
} }
......
...@@ -29,17 +29,6 @@ ...@@ -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 static int __devinit
ohci_pci_start (struct usb_hcd *hcd) ohci_pci_start (struct usb_hcd *hcd)
{ {
...@@ -55,22 +44,43 @@ 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 /* AMD 756, for most chips (early revs), corrupts register
* values on read ... so enable the vendor workaround. * 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) { && hcd->pdev->device == 0x740c) {
ohci->flags = OHCI_QUIRK_AMD756; ohci->flags = OHCI_QUIRK_AMD756;
info ("%s: AMD756 erratum 4 workaround", ohci_info (ohci, "AMD756 erratum 4 workaround\n");
hcd->self.bus_name);
} }
/* 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 /* Apple's OHCI driver has a lot of bizarre workarounds
* for this chip. Evidently control and bulk lists * for this chip. Evidently control and bulk lists
* can get confused. (B&W G3 models, and ...) * 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) { && hcd->pdev->device == 0xc861) {
info ("%s: WARNING: OPTi workarounds unavailable", ohci_info (ohci,
hcd->self.bus_name); "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)); memset (ohci->hcca, 0, sizeof (struct ohci_hcca));
...@@ -86,7 +96,7 @@ ohci_pci_start (struct usb_hcd *hcd) ...@@ -86,7 +96,7 @@ ohci_pci_start (struct usb_hcd *hcd)
} }
if (hc_start (ohci) < 0) { 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); ohci_stop (hcd);
return -EBUSY; return -EBUSY;
} }
...@@ -106,13 +116,13 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, u32 state) ...@@ -106,13 +116,13 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, u32 state)
u16 cmd; u16 cmd;
if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) { 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)); hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS));
return -EIO; return -EIO;
} }
/* act as if usb suspend can always be used */ /* 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; ohci->sleeping = 1;
/* First stop processing */ /* First stop processing */
...@@ -147,16 +157,16 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, u32 state) ...@@ -147,16 +157,16 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, u32 state)
switch (readl (&ohci->regs->control) & OHCI_CTRL_HCFS) { switch (readl (&ohci->regs->control) & OHCI_CTRL_HCFS) {
case OHCI_USB_RESET: case OHCI_USB_RESET:
dbg ("%s suspend->reset ?", hcd->self.bus_name); ohci_dbg (ohci, "suspend->reset ?\n");
break; break;
case OHCI_USB_RESUME: case OHCI_USB_RESUME:
dbg ("%s suspend->resume ?", hcd->self.bus_name); ohci_dbg (ohci, "suspend->resume ?\n");
break; break;
case OHCI_USB_OPER: case OHCI_USB_OPER:
dbg ("%s suspend->operational ?", hcd->self.bus_name); ohci_dbg (ohci, "suspend->operational ?\n");
break; break;
case OHCI_USB_SUSPEND: case OHCI_USB_SUSPEND:
dbg ("%s suspended", hcd->self.bus_name); ohci_dbg (ohci, "suspended\n");
break; break;
} }
...@@ -204,7 +214,7 @@ static int ohci_pci_resume (struct usb_hcd *hcd) ...@@ -204,7 +214,7 @@ static int ohci_pci_resume (struct usb_hcd *hcd)
#ifdef DEBUG #ifdef DEBUG
/* the registers may look crazy here */ /* the registers may look crazy here */
ohci_dump_status (ohci); ohci_dump_status (ohci, 0, 0);
#endif #endif
/* Re-enable bus mastering */ /* Re-enable bus mastering */
...@@ -213,13 +223,13 @@ static int ohci_pci_resume (struct usb_hcd *hcd) ...@@ -213,13 +223,13 @@ static int ohci_pci_resume (struct usb_hcd *hcd)
switch (temp) { switch (temp) {
case OHCI_USB_RESET: // lost power case OHCI_USB_RESET: // lost power
info ("USB restart: %s", hcd->self.bus_name); ohci_info (ohci, "USB restart\n");
retval = hc_restart (ohci); retval = hc_restart (ohci);
break; break;
case OHCI_USB_SUSPEND: // host wakeup case OHCI_USB_SUSPEND: // host wakeup
case OHCI_USB_RESUME: // remote 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) (temp == OHCI_USB_SUSPEND)
? "host" : "remote"); ? "host" : "remote");
ohci->hc_control = OHCI_USB_RESUME; ohci->hc_control = OHCI_USB_RESUME;
...@@ -232,7 +242,7 @@ static int ohci_pci_resume (struct usb_hcd *hcd) ...@@ -232,7 +242,7 @@ static int ohci_pci_resume (struct usb_hcd *hcd)
temp = readl (&ohci->regs->control); temp = readl (&ohci->regs->control);
temp = ohci->hc_control & OHCI_CTRL_HCFS; temp = ohci->hc_control & OHCI_CTRL_HCFS;
if (temp != OHCI_USB_RESUME) { 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; ohci->disabled = 1;
retval = -EIO; retval = -EIO;
break; break;
...@@ -278,11 +288,12 @@ static int ohci_pci_resume (struct usb_hcd *hcd) ...@@ -278,11 +288,12 @@ static int ohci_pci_resume (struct usb_hcd *hcd)
writel (OHCI_BLF | OHCI_CLF, &ohci->regs->cmdstatus); writel (OHCI_BLF | OHCI_CLF, &ohci->regs->cmdstatus);
// ohci_dump_status (ohci); // 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; break;
default: default:
warn ("odd PCI resume for %s", hcd->self.bus_name); ohci_warn (ohci, "odd PCI resume\n");
} }
return retval; return retval;
} }
...@@ -373,11 +384,11 @@ static struct pci_driver ohci_pci_driver = { ...@@ -373,11 +384,11 @@ static struct pci_driver ohci_pci_driver = {
static int __init ohci_hcd_pci_init (void) 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()) if (usb_disabled())
return -ENODEV; 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)); sizeof (struct ed), sizeof (struct td));
return pci_module_init (&ohci_pci_driver); 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) ...@@ -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. * URB goes back to driver, and isn't reissued.
* It's completely gone from HC data structures. * 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); // ASSERT (urb->hcpriv != 0);
urb_free_priv (ohci, urb->hcpriv); urb_free_priv (ohci, urb->hcpriv);
urb->hcpriv = NULL; urb->hcpriv = NULL;
spin_lock_irqsave (&urb->lock, flags); spin_lock (&urb->lock);
if (likely (urb->status == -EINPROGRESS)) if (likely (urb->status == -EINPROGRESS))
urb->status = 0; urb->status = 0;
spin_unlock_irqrestore (&urb->lock, flags); spin_unlock (&urb->lock);
// what lock protects these? // what lock protects these?
switch (usb_pipetype (urb->pipe)) { switch (usb_pipetype (urb->pipe)) {
case PIPE_ISOCHRONOUS: case PIPE_ISOCHRONOUS:
ohci->hcd.self.bandwidth_isoc_reqs--; hcd_to_bus (&ohci->hcd)->bandwidth_isoc_reqs--;
break; break;
case PIPE_INTERRUPT: case PIPE_INTERRUPT:
ohci->hcd.self.bandwidth_int_reqs--; hcd_to_bus (&ohci->hcd)->bandwidth_int_reqs--;
break; break;
} }
...@@ -110,12 +109,9 @@ static void periodic_link (struct ohci_hcd *ohci, struct ed *ed) ...@@ -110,12 +109,9 @@ static void periodic_link (struct ohci_hcd *ohci, struct ed *ed)
{ {
unsigned i; unsigned i;
#ifdef OHCI_VERBOSE_DEBUG ohci_vdbg (ohci, "link %sed %p branch %d [%dus.], interval %d\n",
dbg ("%s: link %sed %p branch %d [%dus.], interval %d",
ohci->hcd.self.bus_name,
(ed->hwINFO & ED_ISO) ? "iso " : "", (ed->hwINFO & ED_ISO) ? "iso " : "",
ed, ed->branch, ed->load, ed->interval); ed, ed->branch, ed->load, ed->interval);
#endif
for (i = ed->branch; i < NUM_INTS; i += ed->interval) { for (i = ed->branch; i < NUM_INTS; i += ed->interval) {
struct ed **prev = &ohci->periodic [i]; struct ed **prev = &ohci->periodic [i];
...@@ -143,7 +139,7 @@ static void periodic_link (struct ohci_hcd *ohci, struct ed *ed) ...@@ -143,7 +139,7 @@ static void periodic_link (struct ohci_hcd *ohci, struct ed *ed)
} }
ohci->load [i] += ed->load; 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 */ /* link an ed into one of the HC chains */
...@@ -206,7 +202,7 @@ static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed) ...@@ -206,7 +202,7 @@ static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed)
default: default:
branch = balance (ohci, ed->interval, ed->load); branch = balance (ohci, ed->interval, ed->load);
if (branch < 0) { if (branch < 0) {
dev_dbg (ohci->hcd.controller, ohci_dbg (ohci,
"ERR %d, interval %d msecs, load %d\n", "ERR %d, interval %d msecs, load %d\n",
branch, ed->interval, ed->load); branch, ed->interval, ed->load);
// FIXME if there are TDs queued, fail them! // FIXME if there are TDs queued, fail them!
...@@ -244,14 +240,11 @@ static void periodic_unlink (struct ohci_hcd *ohci, struct ed *ed) ...@@ -244,14 +240,11 @@ static void periodic_unlink (struct ohci_hcd *ohci, struct ed *ed)
} }
ohci->load [i] -= ed->load; 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 ohci_vdbg (ohci, "unlink %sed %p branch %d [%dus.], interval %d\n",
dbg ("%s: unlink %sed %p branch %d [%dus.], interval %d",
ohci->hcd.self.bus_name,
(ed->hwINFO & ED_ISO) ? "iso " : "", (ed->hwINFO & ED_ISO) ? "iso " : "",
ed, ed->branch, ed->load, ed->interval); ed, ed->branch, ed->load, ed->interval);
#endif
} }
/* unlink an ed from one of the HC chains. /* unlink an ed from one of the HC chains.
...@@ -576,7 +569,7 @@ static void td_submit_urb ( ...@@ -576,7 +569,7 @@ static void td_submit_urb (
*/ */
case PIPE_INTERRUPT: case PIPE_INTERRUPT:
/* ... and periodic urbs have extra accounting */ /* ... and periodic urbs have extra accounting */
ohci->hcd.self.bandwidth_int_reqs++; hcd_to_bus (&ohci->hcd)->bandwidth_int_reqs++;
/* FALLTHROUGH */ /* FALLTHROUGH */
case PIPE_BULK: case PIPE_BULK:
info = is_out info = is_out
...@@ -644,7 +637,7 @@ static void td_submit_urb ( ...@@ -644,7 +637,7 @@ static void td_submit_urb (
data + urb->iso_frame_desc [cnt].offset, data + urb->iso_frame_desc [cnt].offset,
urb->iso_frame_desc [cnt].length, urb, cnt); urb->iso_frame_desc [cnt].length, urb, cnt);
} }
ohci->hcd.self.bandwidth_isoc_reqs++; hcd_to_bus (&ohci->hcd)->bandwidth_isoc_reqs++;
break; break;
} }
// ASSERT (urb_priv->length == cnt); // ASSERT (urb_priv->length == cnt);
...@@ -687,11 +680,10 @@ static void td_done (struct urb *urb, struct td *td) ...@@ -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].actual_length = dlen;
urb->iso_frame_desc [td->index].status = cc_to_error [cc]; urb->iso_frame_desc [td->index].status = cc_to_error [cc];
#ifdef VERBOSE_DEBUG
if (cc != TD_CC_NOERROR) 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); urb, td, 1 + td->index, dlen, cc);
#endif
/* BULK, INT, CONTROL ... drivers see aggregate length/status, /* BULK, INT, CONTROL ... drivers see aggregate length/status,
* except that "setup" bytes aren't counted and "short" transfers * except that "setup" bytes aren't counted and "short" transfers
...@@ -730,13 +722,12 @@ static void td_done (struct urb *urb, struct td *td) ...@@ -730,13 +722,12 @@ static void td_done (struct urb *urb, struct td *td)
- td->data_dma; - td->data_dma;
} }
#ifdef VERBOSE_DEBUG
if (cc != TD_CC_NOERROR && cc < 0x0E) 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, td, 1 + td->index, cc,
urb->actual_length, urb->actual_length,
urb->transfer_buffer_length); urb->transfer_buffer_length);
#endif
} }
} }
...@@ -791,13 +782,17 @@ ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev) ...@@ -791,13 +782,17 @@ ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev)
ed->hwHeadP = next->hwNextTD | toggle; ed->hwHeadP = next->hwNextTD | toggle;
} }
/* help for troubleshooting: */ /* help for troubleshooting: report anything that
dev_dbg (&urb->dev->dev, * looks odd ... that doesn't include protocol stalls
"urb %p usb-%s-%s ep-%d-%s cc %d --> status %d\n", * (or maybe some other things)
urb, */
urb->dev->bus->bus_name, urb->dev->devpath, 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_pipeendpoint (urb->pipe),
usb_pipein (urb->pipe) ? "IN" : "OUT", usb_pipein (urb->pipe) ? "in" : "out",
le32_to_cpu (td->hwINFO),
cc, cc_to_error [cc]); cc, cc_to_error [cc]);
return rev; return rev;
...@@ -826,8 +821,7 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci) ...@@ -826,8 +821,7 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci)
td = dma_to_td (ohci, td_dma); td = dma_to_td (ohci, td_dma);
if (!td) { if (!td) {
err ("%s bad entry %8x", ohci_err (ohci, "bad entry %8x\n", td_dma);
ohci->hcd.self.bus_name, td_dma);
break; break;
} }
...@@ -855,7 +849,8 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci) ...@@ -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) #define tick_before(t1,t2) ((((s16)(t1))-((s16)(t2))) < 0)
/* there are some urbs/eds to unlink; called in_irq(), with HCD locked */ /* 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; struct ed *ed, **last;
...@@ -983,7 +978,8 @@ static void finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *reg ...@@ -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 * path is finish_unlinks(), which unlinks URBs using ed_rm_list, instead of
* scanning the (re-reversed) donelist as this does. * 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; unsigned long flags;
...@@ -1000,9 +996,9 @@ static void dl_done_list (struct ohci_hcd *ohci, struct td *td, struct pt_regs * ...@@ -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 all this urb's TDs are done, call complete() */
if (urb_priv->td_cnt == urb_priv->length) { if (urb_priv->td_cnt == urb_priv->length) {
spin_unlock_irqrestore (&ohci->lock, flags); spin_unlock (&ohci->lock);
finish_urb (ohci, urb, regs); finish_urb (ohci, urb, regs);
spin_lock_irqsave (&ohci->lock, flags); spin_lock (&ohci->lock);
} }
/* clean schedule: unlink EDs that are no longer busy */ /* clean schedule: unlink EDs that are no longer busy */
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
* (C) Hewlett-Packard Company * (C) Copyright 2002 Hewlett-Packard Company
* *
* SA1111 Bus Glue * SA1111 Bus Glue
* *
...@@ -27,14 +27,6 @@ extern int usb_disabled(void); ...@@ -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) static void sa1111_start_hc(struct sa1111_dev *dev)
{ {
unsigned int usb_rst = 0; unsigned int usb_rst = 0;
......
...@@ -372,6 +372,7 @@ struct ohci_hcd { ...@@ -372,6 +372,7 @@ struct ohci_hcd {
unsigned long flags; /* for HC bugs */ unsigned long flags; /* for HC bugs */
#define OHCI_QUIRK_AMD756 0x01 /* erratum #4 */ #define OHCI_QUIRK_AMD756 0x01 /* erratum #4 */
#define OHCI_QUIRK_SUPERIO 0x02 /* natsemi */
// there are also chip quirks/bugs in init logic // there are also chip quirks/bugs in init logic
/* /*
...@@ -382,4 +383,24 @@ struct ohci_hcd { ...@@ -382,4 +383,24 @@ struct ohci_hcd {
#define hcd_to_ohci(hcd_ptr) container_of(hcd_ptr, struct ohci_hcd, 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 -*- */ /* -*- 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) 1999, 2000, 2001, 2002 David E. Nelson
* Copyright (C) 2002, 2003 Henning Meier-Geinitz * Copyright (C) 2002, 2003 Henning Meier-Geinitz
...@@ -346,6 +346,11 @@ ...@@ -346,6 +346,11 @@
* - Print ids and device number when a device was detected. * - Print ids and device number when a device was detected.
* - Don't print errors when the device is busy. * - 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 * TODO
* - Performance * - Performance
* - Select/poll methods * - Select/poll methods
...@@ -1052,7 +1057,7 @@ probe_scanner(struct usb_interface *intf, ...@@ -1052,7 +1057,7 @@ probe_scanner(struct usb_interface *intf,
scn->scn_minor = scn_minor; scn->scn_minor = scn_minor;
scn->isopen = 0; 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, scn->devfs = devfs_register(usb_devfs_handle, name,
DEVFS_FL_DEFAULT, USB_MAJOR, 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 * Copyright (C) 1999, 2000, 2001, 2002 David E. Nelson
* Previously maintained by Brian Beattie * Previously maintained by Brian Beattie
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
// #define DEBUG // #define DEBUG
#define DRIVER_VERSION "0.4.10" #define DRIVER_VERSION "0.4.11"
#define DRIVER_DESC "USB Scanner Driver" #define DRIVER_DESC "USB Scanner Driver"
#include <linux/usb.h> #include <linux/usb.h>
...@@ -99,7 +99,13 @@ static struct usb_device_id scanner_device_ids [] = { ...@@ -99,7 +99,13 @@ static struct usb_device_id scanner_device_ids [] = {
/* Artec */ /* Artec */
{ USB_DEVICE(0x05d8, 0x4001) }, /* Ultima 2000 */ { USB_DEVICE(0x05d8, 0x4001) }, /* Ultima 2000 */
{ USB_DEVICE(0x05d8, 0x4002) }, /* Ultima 2000 (GT6801 based) */ { 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 */ /* Benq: see Acer */
/* Brother */
{ USB_DEVICE(0x04f9, 0x0111) }, /* MFC 6800 */
/* Canon */ /* Canon */
{ USB_DEVICE(0x04a9, 0x2201) }, /* CanoScan FB320U */ { USB_DEVICE(0x04a9, 0x2201) }, /* CanoScan FB320U */
{ USB_DEVICE(0x04a9, 0x2202) }, /* CanoScan FB620U */ { USB_DEVICE(0x04a9, 0x2202) }, /* CanoScan FB620U */
...@@ -117,6 +123,10 @@ static struct usb_device_id scanner_device_ids [] = { ...@@ -117,6 +123,10 @@ static struct usb_device_id scanner_device_ids [] = {
/* Compaq */ /* Compaq */
{ USB_DEVICE(0x049f, 0x0021) }, /* S200 */ { USB_DEVICE(0x049f, 0x0021) }, /* S200 */
/* Epson -- See Seiko/Epson below */ /* 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 */ /* Genius */
{ USB_DEVICE(0x0458, 0x2001) }, /* ColorPage Vivid Pro */ { USB_DEVICE(0x0458, 0x2001) }, /* ColorPage Vivid Pro */
{ USB_DEVICE(0x0458, 0x2007) }, /* ColorPage HR6 V2 */ { USB_DEVICE(0x0458, 0x2007) }, /* ColorPage HR6 V2 */
...@@ -149,6 +159,8 @@ static struct usb_device_id scanner_device_ids [] = { ...@@ -149,6 +159,8 @@ static struct usb_device_id scanner_device_ids [] = {
{ USB_DEVICE(0x0638, 0x0268) }, /* 1200U */ { USB_DEVICE(0x0638, 0x0268) }, /* 1200U */
/* Lexmark */ /* Lexmark */
{ USB_DEVICE(0x043d, 0x002d) }, /* X70/X73 */ { USB_DEVICE(0x043d, 0x002d) }, /* X70/X73 */
/* Medion */
{ USB_DEVICE(0x0461, 0x0377) }, /* MD 5345 - repackaged Primax? */
/* Memorex */ /* Memorex */
{ USB_DEVICE(0x0461, 0x0346) }, /* 6136u - repackaged Primax ? */ { USB_DEVICE(0x0461, 0x0346) }, /* 6136u - repackaged Primax ? */
/* Microtek */ /* Microtek */
...@@ -202,7 +214,8 @@ static struct usb_device_id scanner_device_ids [] = { ...@@ -202,7 +214,8 @@ static struct usb_device_id scanner_device_ids [] = {
{ USB_DEVICE(0x07b3, 0x0015) }, /* OpticPro U24 */ { USB_DEVICE(0x07b3, 0x0015) }, /* OpticPro U24 */
{ USB_DEVICE(0x07b3, 0x0016) }, /* Unknown */ { USB_DEVICE(0x07b3, 0x0016) }, /* Unknown */
{ USB_DEVICE(0x07b3, 0x0017) }, /* OpticPro UT12/UT16/UT24 */ { 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 */ /* Primax/Colorado */
{ USB_DEVICE(0x0461, 0x0300) }, /* G2-300 #1 */ { USB_DEVICE(0x0461, 0x0300) }, /* G2-300 #1 */
{ USB_DEVICE(0x0461, 0x0301) }, /* G2E-300 #1 */ { USB_DEVICE(0x0461, 0x0301) }, /* G2E-300 #1 */
...@@ -210,12 +223,15 @@ static struct usb_device_id scanner_device_ids [] = { ...@@ -210,12 +223,15 @@ static struct usb_device_id scanner_device_ids [] = {
{ USB_DEVICE(0x0461, 0x0303) }, /* G2E-300 #2 */ { USB_DEVICE(0x0461, 0x0303) }, /* G2E-300 #2 */
{ USB_DEVICE(0x0461, 0x0340) }, /* Colorado USB 9600 */ { USB_DEVICE(0x0461, 0x0340) }, /* Colorado USB 9600 */
{ USB_DEVICE(0x0461, 0x0341) }, /* Colorado 600u */ { USB_DEVICE(0x0461, 0x0341) }, /* Colorado 600u */
{ USB_DEVICE(0x0461, 0x0347) }, /* Primascan Colorado 2600u */
{ USB_DEVICE(0x0461, 0x0360) }, /* Colorado USB 19200 */ { USB_DEVICE(0x0461, 0x0360) }, /* Colorado USB 19200 */
{ USB_DEVICE(0x0461, 0x0361) }, /* Colorado 1200u */ { USB_DEVICE(0x0461, 0x0361) }, /* Colorado 1200u */
{ USB_DEVICE(0x0461, 0x0380) }, /* G2-600 #1 */ { USB_DEVICE(0x0461, 0x0380) }, /* G2-600 #1 */
{ USB_DEVICE(0x0461, 0x0381) }, /* ReadyScan 636i */ { USB_DEVICE(0x0461, 0x0381) }, /* ReadyScan 636i */
{ USB_DEVICE(0x0461, 0x0382) }, /* G2-600 #2 */ { USB_DEVICE(0x0461, 0x0382) }, /* G2-600 #2 */
{ USB_DEVICE(0x0461, 0x0383) }, /* G2E-600 */ { USB_DEVICE(0x0461, 0x0383) }, /* G2E-600 */
/* Prolink */
{ USB_DEVICE(0x06dc, 0x0014) }, /* Winscan Pro 2448U */
/* Relisis */ /* Relisis */
// { USB_DEVICE(0x0475, 0x0103) }, /* Episode - undetected endpoint */ // { USB_DEVICE(0x0475, 0x0103) }, /* Episode - undetected endpoint */
/* Seiko/Epson Corp. */ /* Seiko/Epson Corp. */
...@@ -241,6 +257,8 @@ static struct usb_device_id scanner_device_ids [] = { ...@@ -241,6 +257,8 @@ static struct usb_device_id scanner_device_ids [] = {
{ USB_DEVICE(0x04b8, 0x011e) }, /* Perfection 1660 Photo */ { USB_DEVICE(0x04b8, 0x011e) }, /* Perfection 1660 Photo */
{ USB_DEVICE(0x04b8, 0x0801) }, /* Stylus CX5200 */ { USB_DEVICE(0x04b8, 0x0801) }, /* Stylus CX5200 */
{ USB_DEVICE(0x04b8, 0x0802) }, /* Stylus CX3200 */ { USB_DEVICE(0x04b8, 0x0802) }, /* Stylus CX3200 */
/* SYSCAN */
{ USB_DEVICE(0x0a82, 0x4600) }, /* TravelScan 460/464 */
/* Umax */ /* Umax */
{ USB_DEVICE(0x1606, 0x0010) }, /* Astra 1220U */ { USB_DEVICE(0x1606, 0x0010) }, /* Astra 1220U */
{ USB_DEVICE(0x1606, 0x0030) }, /* Astra 2000U */ { USB_DEVICE(0x1606, 0x0030) }, /* Astra 2000U */
......
...@@ -159,6 +159,20 @@ config USB_WACOM ...@@ -159,6 +159,20 @@ config USB_WACOM
The module will be called wacom. If you want to compile it as a The module will be called wacom. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>. 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 config USB_POWERMATE
tristate "Griffin PowerMate and Contour Jog support" tristate "Griffin PowerMate and Contour Jog support"
depends on USB && INPUT depends on USB && INPUT
......
...@@ -31,5 +31,6 @@ obj-$(CONFIG_USB_HID) += hid.o ...@@ -31,5 +31,6 @@ obj-$(CONFIG_USB_HID) += hid.o
obj-$(CONFIG_USB_KBD) += usbkbd.o obj-$(CONFIG_USB_KBD) += usbkbd.o
obj-$(CONFIG_USB_MOUSE) += usbmouse.o obj-$(CONFIG_USB_MOUSE) += usbmouse.o
obj-$(CONFIG_USB_WACOM) += wacom.o obj-$(CONFIG_USB_WACOM) += wacom.o
obj-$(CONFIG_USB_KBTAB) += kbtab.o
obj-$(CONFIG_USB_POWERMATE) += powermate.o obj-$(CONFIG_USB_POWERMATE) += powermate.o
obj-$(CONFIG_USB_XPAD) += xpad.o obj-$(CONFIG_USB_XPAD) += xpad.o
...@@ -1304,6 +1304,10 @@ void hid_init_reports(struct hid_device *hid) ...@@ -1304,6 +1304,10 @@ void hid_init_reports(struct hid_device *hid)
#define USB_DEVICE_ID_WACOM_PL 0x0030 #define USB_DEVICE_ID_WACOM_PL 0x0030
#define USB_DEVICE_ID_WACOM_INTUOS2 0x0040 #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_VENDOR_ID_AIPTEK 0x08ca
#define USB_DEVICE_ID_AIPTEK_6000 0x0020 #define USB_DEVICE_ID_AIPTEK_6000 0x0020
...@@ -1355,6 +1359,7 @@ struct hid_blacklist { ...@@ -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 + 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 + 4, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 5, 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_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_POWERMATE, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, 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, ...@@ -332,7 +332,7 @@ write_rio(struct file *file, const char *buffer,
} }
interruptible_sleep_on_timeout(&rio-> wait_q, NAK_TIMEOUT); interruptible_sleep_on_timeout(&rio-> wait_q, NAK_TIMEOUT);
continue; continue;
} else if (!result & partial) { } else if (!result && partial) {
obuf += partial; obuf += partial;
thistime -= partial; thistime -= partial;
} else } else
......
...@@ -56,7 +56,6 @@ ...@@ -56,7 +56,6 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/list.h> #include <linux/list.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/usb.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/atm.h> #include <linux/atm.h>
...@@ -69,11 +68,7 @@ ...@@ -69,11 +68,7 @@
#define DEBUG_PACKET 1 #define DEBUG_PACKET 1
*/ */
#ifdef DEBUG #include <linux/usb.h>
#define PDEBUG(arg...) printk(KERN_DEBUG __FILE__ ": " arg)
#else
#define PDEBUG(arg...)
#endif
#ifdef DEBUG_PACKET #ifdef DEBUG_PACKET
...@@ -161,6 +156,7 @@ struct udsl_instance_data { ...@@ -161,6 +156,7 @@ struct udsl_instance_data {
/* usb device part */ /* usb device part */
struct usb_device *usb_dev; struct usb_device *usb_dev;
char description [64];
int firmware_loaded; int firmware_loaded;
/* atm device part */ /* atm device part */
...@@ -324,16 +320,16 @@ static void udsl_complete_receive (struct urb *urb, struct pt_regs *regs) ...@@ -324,16 +320,16 @@ static void udsl_complete_receive (struct urb *urb, struct pt_regs *regs)
unsigned long flags; unsigned long flags;
if (!urb || !(rcv = urb->context) || !(instance = rcv->instance)) { if (!urb || !(rcv = urb->context) || !(instance = rcv->instance)) {
PDEBUG ("udsl_complete_receive: bad urb!\n"); dbg ("udsl_complete_receive: bad urb!");
return; return;
} }
PDEBUG ("udsl_complete_receive entered (urb 0x%p, status %d)\n", urb, urb->status); dbg ("udsl_complete_receive entered (urb 0x%p, status %d)", urb, urb->status);
tasklet_schedule (&instance->receive_tasklet);
/* may not be in_interrupt() */ /* may not be in_interrupt() */
spin_lock_irqsave (&instance->completed_receivers_lock, flags); spin_lock_irqsave (&instance->completed_receivers_lock, flags);
list_add_tail (&rcv->list, &instance->completed_receivers); list_add_tail (&rcv->list, &instance->completed_receivers);
tasklet_schedule (&instance->receive_tasklet);
spin_unlock_irqrestore (&instance->completed_receivers_lock, flags); spin_unlock_irqrestore (&instance->completed_receivers_lock, flags);
} }
...@@ -349,7 +345,7 @@ static void udsl_process_receive (unsigned long data) ...@@ -349,7 +345,7 @@ static void udsl_process_receive (unsigned long data)
struct sk_buff *new = NULL, *tmp = NULL; struct sk_buff *new = NULL, *tmp = NULL;
int err; int err;
PDEBUG ("udsl_process_receive entered\n"); dbg ("udsl_process_receive entered");
spin_lock_irqsave (&instance->completed_receivers_lock, flags); spin_lock_irqsave (&instance->completed_receivers_lock, flags);
while (!list_empty (&instance->completed_receivers)) { while (!list_empty (&instance->completed_receivers)) {
...@@ -358,11 +354,11 @@ static void udsl_process_receive (unsigned long data) ...@@ -358,11 +354,11 @@ static void udsl_process_receive (unsigned long data)
spin_unlock_irqrestore (&instance->completed_receivers_lock, flags); spin_unlock_irqrestore (&instance->completed_receivers_lock, flags);
urb = rcv->urb; urb = rcv->urb;
PDEBUG ("udsl_process_receive: got packet %p with length %d and status %d\n", urb, urb->actual_length, urb->status); dbg ("udsl_process_receive: got packet %p with length %d and status %d", urb, urb->actual_length, urb->status);
switch (urb->status) { switch (urb->status) {
case 0: case 0:
PDEBUG ("udsl_process_receive: processing urb with rcv %p, urb %p, skb %p\n", rcv, urb, rcv->skb); dbg ("udsl_process_receive: processing urb with rcv %p, urb %p, skb %p", rcv, urb, rcv->skb);
/* update the skb structure */ /* update the skb structure */
skb = rcv->skb; skb = rcv->skb;
...@@ -370,13 +366,13 @@ static void udsl_process_receive (unsigned long data) ...@@ -370,13 +366,13 @@ static void udsl_process_receive (unsigned long data)
skb_put (skb, urb->actual_length); skb_put (skb, urb->actual_length);
data_start = skb->data; data_start = skb->data;
PDEBUG ("skb->len = %d\n", skb->len); dbg ("skb->len = %d", skb->len);
PACKETDEBUG (skb->data, skb->len); PACKETDEBUG (skb->data, skb->len);
while ((new = while ((new =
atmsar_decode_rawcell (instance->atmsar_vcc_list, skb, atmsar_decode_rawcell (instance->atmsar_vcc_list, skb,
&atmsar_vcc)) != NULL) { &atmsar_vcc)) != NULL) {
PDEBUG ("(after cell processing)skb->len = %d\n", new->len); dbg ("(after cell processing)skb->len = %d", new->len);
switch (atmsar_vcc->type) { switch (atmsar_vcc->type) {
case ATMSAR_TYPE_AAL5: case ATMSAR_TYPE_AAL5:
...@@ -385,19 +381,19 @@ static void udsl_process_receive (unsigned long data) ...@@ -385,19 +381,19 @@ static void udsl_process_receive (unsigned long data)
/* we can't send NULL skbs upstream, the ATM layer would try to close the vcc... */ /* we can't send NULL skbs upstream, the ATM layer would try to close the vcc... */
if (new) { if (new) {
PDEBUG ("(after aal5 decap) skb->len = %d\n", new->len); dbg ("(after aal5 decap) skb->len = %d", new->len);
if (new->len && atm_charge (atmsar_vcc->vcc, new->truesize)) { if (new->len && atm_charge (atmsar_vcc->vcc, new->truesize)) {
PACKETDEBUG (new->data, new->len); PACKETDEBUG (new->data, new->len);
atmsar_vcc->vcc->push (atmsar_vcc->vcc, new); atmsar_vcc->vcc->push (atmsar_vcc->vcc, new);
} else { } else {
PDEBUG dbg
("dropping incoming packet : rx_inuse = %d, vcc->sk->rcvbuf = %d, skb->true_size = %d\n", ("dropping incoming packet : rx_inuse = %d, vcc->sk->rcvbuf = %d, skb->true_size = %d",
atomic_read (&atmsar_vcc->vcc->rx_inuse), atomic_read (&atmsar_vcc->vcc->rx_inuse),
atmsar_vcc->vcc->sk->rcvbuf, new->truesize); atmsar_vcc->vcc->sk->rcvbuf, new->truesize);
dev_kfree_skb (new); dev_kfree_skb (new);
} }
} else { } else {
PDEBUG ("atmsar_decode_aal5 returned NULL!\n"); dbg ("atmsar_decode_aal5 returned NULL!");
dev_kfree_skb (tmp); dev_kfree_skb (tmp);
} }
break; break;
...@@ -422,10 +418,10 @@ static void udsl_process_receive (unsigned long data) ...@@ -422,10 +418,10 @@ static void udsl_process_receive (unsigned long data)
rcv); rcv);
if (!(err = usb_submit_urb (urb, GFP_ATOMIC))) if (!(err = usb_submit_urb (urb, GFP_ATOMIC)))
break; break;
PDEBUG ("udsl_process_receive: submission failed (%d)\n", err); dbg ("udsl_process_receive: submission failed (%d)", err);
/* fall through */ /* fall through */
default: /* error or urb unlinked */ default: /* error or urb unlinked */
PDEBUG ("udsl_process_receive: adding to spare_receivers\n"); dbg ("udsl_process_receive: adding to spare_receivers");
spin_lock_irqsave (&instance->spare_receivers_lock, flags); spin_lock_irqsave (&instance->spare_receivers_lock, flags);
list_add (&rcv->list, &instance->spare_receivers); list_add (&rcv->list, &instance->spare_receivers);
spin_unlock_irqrestore (&instance->spare_receivers_lock, flags); spin_unlock_irqrestore (&instance->spare_receivers_lock, flags);
...@@ -435,7 +431,7 @@ static void udsl_process_receive (unsigned long data) ...@@ -435,7 +431,7 @@ static void udsl_process_receive (unsigned long data)
spin_lock_irqsave (&instance->completed_receivers_lock, flags); spin_lock_irqsave (&instance->completed_receivers_lock, flags);
} /* while */ } /* while */
spin_unlock_irqrestore (&instance->completed_receivers_lock, flags); spin_unlock_irqrestore (&instance->completed_receivers_lock, flags);
PDEBUG ("udsl_process_receive successful\n"); dbg ("udsl_process_receive successful");
} }
static void udsl_fire_receivers (struct udsl_instance_data *instance) static void udsl_fire_receivers (struct udsl_instance_data *instance)
...@@ -454,7 +450,7 @@ static void udsl_fire_receivers (struct udsl_instance_data *instance) ...@@ -454,7 +450,7 @@ static void udsl_fire_receivers (struct udsl_instance_data *instance)
list_for_each_safe (pos, n, &receivers) { list_for_each_safe (pos, n, &receivers) {
struct udsl_receiver *rcv = list_entry (pos, struct udsl_receiver, list); struct udsl_receiver *rcv = list_entry (pos, struct udsl_receiver, list);
PDEBUG ("udsl_fire_receivers: firing urb %p\n", rcv->urb); dbg ("udsl_fire_receivers: firing urb %p", rcv->urb);
usb_fill_bulk_urb (rcv->urb, usb_fill_bulk_urb (rcv->urb,
instance->usb_dev, instance->usb_dev,
...@@ -465,7 +461,7 @@ static void udsl_fire_receivers (struct udsl_instance_data *instance) ...@@ -465,7 +461,7 @@ static void udsl_fire_receivers (struct udsl_instance_data *instance)
rcv); rcv);
if (usb_submit_urb (rcv->urb, GFP_KERNEL) < 0) { if (usb_submit_urb (rcv->urb, GFP_KERNEL) < 0) {
PDEBUG ("udsl_fire_receivers: submit failed!\n"); dbg ("udsl_fire_receivers: submit failed!");
spin_lock_irqsave (&instance->spare_receivers_lock, flags); spin_lock_irqsave (&instance->spare_receivers_lock, flags);
list_move (pos, &instance->spare_receivers); list_move (pos, &instance->spare_receivers);
spin_unlock_irqrestore (&instance->spare_receivers_lock, flags); spin_unlock_irqrestore (&instance->spare_receivers_lock, flags);
...@@ -487,17 +483,17 @@ static void udsl_complete_send (struct urb *urb, struct pt_regs *regs) ...@@ -487,17 +483,17 @@ static void udsl_complete_send (struct urb *urb, struct pt_regs *regs)
unsigned long flags; unsigned long flags;
if (!urb || !(snd = urb->context) || !(instance = snd->instance)) { if (!urb || !(snd = urb->context) || !(instance = snd->instance)) {
PDEBUG ("udsl_complete_send: bad urb!\n"); dbg ("udsl_complete_send: bad urb!");
return; return;
} }
PDEBUG ("udsl_complete_send entered (urb 0x%p, status %d)\n", urb, urb->status); dbg ("udsl_complete_send entered (urb 0x%p, status %d)", urb, urb->status);
tasklet_schedule (&instance->send_tasklet);
/* may not be in_interrupt() */ /* may not be in_interrupt() */
spin_lock_irqsave (&instance->send_lock, flags); spin_lock_irqsave (&instance->send_lock, flags);
list_add (&snd->list, &instance->spare_senders); list_add (&snd->list, &instance->spare_senders);
list_add (&snd->buffer->list, &instance->spare_buffers); list_add (&snd->buffer->list, &instance->spare_buffers);
tasklet_schedule (&instance->send_tasklet);
spin_unlock_irqrestore (&instance->send_lock, flags); spin_unlock_irqrestore (&instance->send_lock, flags);
} }
...@@ -513,7 +509,7 @@ static void udsl_process_send (unsigned long data) ...@@ -513,7 +509,7 @@ static void udsl_process_send (unsigned long data)
struct udsl_sender *snd; struct udsl_sender *snd;
unsigned char *target; unsigned char *target;
PDEBUG ("udsl_process_send entered\n"); dbg ("udsl_process_send entered");
made_progress: made_progress:
spin_lock_irqsave (&instance->send_lock, flags); spin_lock_irqsave (&instance->send_lock, flags);
...@@ -521,10 +517,10 @@ static void udsl_process_send (unsigned long data) ...@@ -521,10 +517,10 @@ static void udsl_process_send (unsigned long data)
if (!list_empty (&instance->filled_buffers)) { if (!list_empty (&instance->filled_buffers)) {
buf = list_entry (instance->filled_buffers.next, struct udsl_send_buffer, list); buf = list_entry (instance->filled_buffers.next, struct udsl_send_buffer, list);
list_del (&buf->list); list_del (&buf->list);
PDEBUG ("sending filled buffer (0x%p)\n", buf); dbg ("sending filled buffer (0x%p)", buf);
} else if ((buf = instance->current_buffer)) { } else if ((buf = instance->current_buffer)) {
instance->current_buffer = NULL; instance->current_buffer = NULL;
PDEBUG ("sending current buffer (0x%p)\n", buf); dbg ("sending current buffer (0x%p)", buf);
} else /* all buffers empty */ } else /* all buffers empty */
break; break;
...@@ -541,10 +537,10 @@ static void udsl_process_send (unsigned long data) ...@@ -541,10 +537,10 @@ static void udsl_process_send (unsigned long data)
udsl_complete_send, udsl_complete_send,
snd); snd);
PDEBUG ("submitting urb 0x%p, contains %d cells\n", snd->urb, UDSL_SND_BUFFER_SIZE - buf->free_cells); dbg ("submitting urb 0x%p, contains %d cells", snd->urb, UDSL_SND_BUFFER_SIZE - buf->free_cells);
if ((err = usb_submit_urb(snd->urb, GFP_ATOMIC)) < 0) { if ((err = usb_submit_urb(snd->urb, GFP_ATOMIC)) < 0) {
PDEBUG ("submission failed (%d)!\n", err); dbg ("submission failed (%d)!", err);
spin_lock_irqsave (&instance->send_lock, flags); spin_lock_irqsave (&instance->send_lock, flags);
list_add (&snd->list, &instance->spare_senders); list_add (&snd->list, &instance->spare_senders);
spin_unlock_irqrestore (&instance->send_lock, flags); spin_unlock_irqrestore (&instance->send_lock, flags);
...@@ -557,7 +553,7 @@ static void udsl_process_send (unsigned long data) ...@@ -557,7 +553,7 @@ static void udsl_process_send (unsigned long data)
spin_unlock_irqrestore (&instance->send_lock, flags); spin_unlock_irqrestore (&instance->send_lock, flags);
if (!instance->current_skb && !(instance->current_skb = skb_dequeue (&instance->sndqueue))) { if (!instance->current_skb && !(instance->current_skb = skb_dequeue (&instance->sndqueue))) {
PDEBUG ("done - no more skbs\n"); dbg ("done - no more skbs");
return; return;
} }
...@@ -568,7 +564,7 @@ static void udsl_process_send (unsigned long data) ...@@ -568,7 +564,7 @@ static void udsl_process_send (unsigned long data)
if (list_empty (&instance->spare_buffers)) { if (list_empty (&instance->spare_buffers)) {
instance->current_buffer = NULL; instance->current_buffer = NULL;
spin_unlock_irqrestore (&instance->send_lock, flags); spin_unlock_irqrestore (&instance->send_lock, flags);
PDEBUG ("done - no more buffers\n"); dbg ("done - no more buffers");
return; return;
} }
buf = list_entry (instance->spare_buffers.next, struct udsl_send_buffer, list); buf = list_entry (instance->spare_buffers.next, struct udsl_send_buffer, list);
...@@ -584,7 +580,7 @@ static void udsl_process_send (unsigned long data) ...@@ -584,7 +580,7 @@ static void udsl_process_send (unsigned long data)
cells_to_write = min (buf->free_cells, UDSL_SKB (skb)->num_cells); cells_to_write = min (buf->free_cells, UDSL_SKB (skb)->num_cells);
target = buf->free_start; target = buf->free_start;
PDEBUG ("writing %u cells from skb 0x%p to buffer 0x%p\n", cells_to_write, skb, buf); dbg ("writing %u cells from skb 0x%p to buffer 0x%p", cells_to_write, skb, buf);
for (i = 0; i < cells_to_write; i++) for (i = 0; i < cells_to_write; i++)
target = udsl_write_cell (skb, target); target = udsl_write_cell (skb, target);
...@@ -593,15 +589,15 @@ static void udsl_process_send (unsigned long data) ...@@ -593,15 +589,15 @@ static void udsl_process_send (unsigned long data)
if (!(buf->free_cells -= cells_to_write)) { if (!(buf->free_cells -= cells_to_write)) {
list_add_tail (&buf->list, &instance->filled_buffers); list_add_tail (&buf->list, &instance->filled_buffers);
instance->current_buffer = NULL; instance->current_buffer = NULL;
PDEBUG ("queued filled buffer\n"); dbg ("queued filled buffer");
} }
PDEBUG ("buffer contains %d cells, %d left\n", UDSL_SND_BUFFER_SIZE - buf->free_cells, buf->free_cells); dbg ("buffer contains %d cells, %d left", UDSL_SND_BUFFER_SIZE - buf->free_cells, buf->free_cells);
if (!UDSL_SKB (skb)->num_cells) { if (!UDSL_SKB (skb)->num_cells) {
struct atm_vcc *vcc = UDSL_SKB (skb)->atm_data.vcc; struct atm_vcc *vcc = UDSL_SKB (skb)->atm_data.vcc;
PDEBUG ("discarding empty skb\n"); dbg ("discarding empty skb");
if (vcc->pop) if (vcc->pop)
vcc->pop (vcc, skb); vcc->pop (vcc, skb);
else else
...@@ -620,11 +616,11 @@ static void udsl_cancel_send (struct udsl_instance_data *instance, struct atm_vc ...@@ -620,11 +616,11 @@ static void udsl_cancel_send (struct udsl_instance_data *instance, struct atm_vc
unsigned long flags; unsigned long flags;
struct sk_buff *skb, *n; struct sk_buff *skb, *n;
PDEBUG ("udsl_cancel_send entered\n"); dbg ("udsl_cancel_send entered");
spin_lock_irqsave (&instance->sndqueue.lock, flags); spin_lock_irqsave (&instance->sndqueue.lock, flags);
for (skb = instance->sndqueue.next, n = skb->next; skb != (struct sk_buff *)&instance->sndqueue; skb = n, n = skb->next) for (skb = instance->sndqueue.next, n = skb->next; skb != (struct sk_buff *)&instance->sndqueue; skb = n, n = skb->next)
if (UDSL_SKB (skb)->atm_data.vcc == vcc) { if (UDSL_SKB (skb)->atm_data.vcc == vcc) {
PDEBUG ("popping skb 0x%p\n", skb); dbg ("popping skb 0x%p", skb);
__skb_unlink (skb, &instance->sndqueue); __skb_unlink (skb, &instance->sndqueue);
if (vcc->pop) if (vcc->pop)
vcc->pop (vcc, skb); vcc->pop (vcc, skb);
...@@ -635,7 +631,7 @@ static void udsl_cancel_send (struct udsl_instance_data *instance, struct atm_vc ...@@ -635,7 +631,7 @@ static void udsl_cancel_send (struct udsl_instance_data *instance, struct atm_vc
tasklet_disable (&instance->send_tasklet); tasklet_disable (&instance->send_tasklet);
if ((skb = instance->current_skb) && (UDSL_SKB (skb)->atm_data.vcc == vcc)) { if ((skb = instance->current_skb) && (UDSL_SKB (skb)->atm_data.vcc == vcc)) {
PDEBUG ("popping current skb (0x%p)\n", skb); dbg ("popping current skb (0x%p)", skb);
instance->current_skb = NULL; instance->current_skb = NULL;
if (vcc->pop) if (vcc->pop)
vcc->pop (vcc, skb); vcc->pop (vcc, skb);
...@@ -643,30 +639,30 @@ static void udsl_cancel_send (struct udsl_instance_data *instance, struct atm_vc ...@@ -643,30 +639,30 @@ static void udsl_cancel_send (struct udsl_instance_data *instance, struct atm_vc
kfree_skb (skb); kfree_skb (skb);
} }
tasklet_enable (&instance->send_tasklet); tasklet_enable (&instance->send_tasklet);
PDEBUG ("udsl_cancel_send done\n"); dbg ("udsl_cancel_send done");
} }
static int udsl_atm_send (struct atm_vcc *vcc, struct sk_buff *skb) static int udsl_atm_send (struct atm_vcc *vcc, struct sk_buff *skb)
{ {
struct udsl_instance_data *instance = vcc->dev->dev_data; struct udsl_instance_data *instance = vcc->dev->dev_data;
PDEBUG ("udsl_atm_send called (skb 0x%p, len %u)\n", skb, skb->len); dbg ("udsl_atm_send called (skb 0x%p, len %u)", skb, skb->len);
if (!instance) { if (!instance || !instance->usb_dev) {
PDEBUG ("NULL instance!\n"); dbg ("NULL data!");
return -EINVAL; return -ENODEV;
} }
if (!instance->firmware_loaded) if (!instance->firmware_loaded)
return -EAGAIN; return -EAGAIN;
if (vcc->qos.aal != ATM_AAL5) { if (vcc->qos.aal != ATM_AAL5) {
PDEBUG ("unsupported ATM type %d!\n", vcc->qos.aal); dbg ("unsupported ATM type %d!", vcc->qos.aal);
return -EINVAL; return -EINVAL;
} }
if (skb->len > ATM_MAX_AAL5_PDU) { if (skb->len > ATM_MAX_AAL5_PDU) {
PDEBUG ("packet too long (%d vs %d)!\n", skb->len, ATM_MAX_AAL5_PDU); dbg ("packet too long (%d vs %d)!", skb->len, ATM_MAX_AAL5_PDU);
return -EINVAL; return -EINVAL;
} }
...@@ -695,16 +691,17 @@ static void udsl_atm_dev_close (struct atm_dev *dev) ...@@ -695,16 +691,17 @@ static void udsl_atm_dev_close (struct atm_dev *dev)
struct udsl_instance_data *instance = dev->dev_data; struct udsl_instance_data *instance = dev->dev_data;
if (!instance) { if (!instance) {
PDEBUG ("udsl_atm_dev_close: NULL instance!\n"); dbg ("udsl_atm_dev_close: NULL instance!");
return; return;
} }
PDEBUG ("udsl_atm_dev_close: queue has %u elements\n", instance->sndqueue.qlen); dbg ("udsl_atm_dev_close: queue has %u elements", instance->sndqueue.qlen);
PDEBUG ("udsl_atm_dev_close: killing tasklet\n"); dbg ("udsl_atm_dev_close: killing tasklet");
tasklet_kill (&instance->send_tasklet); tasklet_kill (&instance->send_tasklet);
PDEBUG ("udsl_atm_dev_close: freeing instance\n"); dbg ("udsl_atm_dev_close: freeing instance");
kfree (instance); kfree (instance);
dev->dev_data = NULL;
} }
...@@ -720,13 +717,15 @@ static int udsl_atm_proc_read (struct atm_dev *atm_dev, loff_t *pos, char *page) ...@@ -720,13 +717,15 @@ static int udsl_atm_proc_read (struct atm_dev *atm_dev, loff_t *pos, char *page)
int left = *pos; int left = *pos;
if (!instance) { if (!instance) {
PDEBUG ("NULL instance!\n"); dbg ("NULL instance!");
return -ENODEV; return -ENODEV;
} }
if (!left--) if (!left--)
return sprintf (page, "SpeedTouch USB %s-%s (%02x:%02x:%02x:%02x:%02x:%02x)\n", return sprintf (page, "%s\n", instance->description);
instance->usb_dev->bus->bus_name, instance->usb_dev->devpath,
if (!left--)
return sprintf (page, "MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
atm_dev->esi[0], atm_dev->esi[1], atm_dev->esi[2], atm_dev->esi[0], atm_dev->esi[1], atm_dev->esi[2],
atm_dev->esi[3], atm_dev->esi[4], atm_dev->esi[5]); atm_dev->esi[3], atm_dev->esi[4], atm_dev->esi[5]);
...@@ -738,6 +737,30 @@ static int udsl_atm_proc_read (struct atm_dev *atm_dev, loff_t *pos, char *page) ...@@ -738,6 +737,30 @@ static int udsl_atm_proc_read (struct atm_dev *atm_dev, loff_t *pos, char *page)
atomic_read (&atm_dev->stats.aal5.rx_err), atomic_read (&atm_dev->stats.aal5.rx_err),
atomic_read (&atm_dev->stats.aal5.rx_drop)); atomic_read (&atm_dev->stats.aal5.rx_drop));
if (!left--) {
switch (atm_dev->signal) {
case ATM_PHY_SIG_FOUND:
sprintf (page, "Line up");
break;
case ATM_PHY_SIG_LOST:
sprintf (page, "Line down");
break;
default:
sprintf (page, "Line state unknown");
break;
}
if (instance->usb_dev) {
if (!instance->firmware_loaded)
strcat (page, ", no firmware\n");
else
strcat (page, ", firmware loaded\n");
} else
strcat (page, ", disconnected\n");
return strlen (page);
}
return 0; return 0;
} }
...@@ -752,10 +775,10 @@ static int udsl_atm_open (struct atm_vcc *vcc, short vpi, int vci) ...@@ -752,10 +775,10 @@ static int udsl_atm_open (struct atm_vcc *vcc, short vpi, int vci)
{ {
struct udsl_instance_data *instance = vcc->dev->dev_data; struct udsl_instance_data *instance = vcc->dev->dev_data;
PDEBUG ("udsl_atm_open called\n"); dbg ("udsl_atm_open called");
if (!instance) { if (!instance || !instance->usb_dev) {
PDEBUG ("NULL instance!\n"); dbg ("NULL data!");
return -ENODEV; return -ENODEV;
} }
...@@ -784,7 +807,7 @@ static int udsl_atm_open (struct atm_vcc *vcc, short vpi, int vci) ...@@ -784,7 +807,7 @@ static int udsl_atm_open (struct atm_vcc *vcc, short vpi, int vci)
if (instance->firmware_loaded) if (instance->firmware_loaded)
udsl_fire_receivers (instance); udsl_fire_receivers (instance);
PDEBUG ("udsl_atm_open successfull\n"); dbg ("udsl_atm_open successful");
return 0; return 0;
} }
...@@ -792,10 +815,10 @@ static void udsl_atm_close (struct atm_vcc *vcc) ...@@ -792,10 +815,10 @@ static void udsl_atm_close (struct atm_vcc *vcc)
{ {
struct udsl_instance_data *instance = vcc->dev->dev_data; struct udsl_instance_data *instance = vcc->dev->dev_data;
PDEBUG ("udsl_atm_close called\n"); dbg ("udsl_atm_close called");
if (!instance) { if (!instance) {
PDEBUG ("NULL instance!\n"); dbg ("NULL instance!");
return; return;
} }
...@@ -814,7 +837,7 @@ static void udsl_atm_close (struct atm_vcc *vcc) ...@@ -814,7 +837,7 @@ static void udsl_atm_close (struct atm_vcc *vcc)
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
PDEBUG ("udsl_atm_close successfull\n"); dbg ("udsl_atm_close successful");
return; return;
} }
...@@ -837,10 +860,10 @@ static int udsl_usb_ioctl (struct usb_interface *intf, unsigned int code, void * ...@@ -837,10 +860,10 @@ static int udsl_usb_ioctl (struct usb_interface *intf, unsigned int code, void *
{ {
struct udsl_instance_data *instance = usb_get_intfdata (intf); struct udsl_instance_data *instance = usb_get_intfdata (intf);
PDEBUG ("udsl_usb_ioctl entered\n"); dbg ("udsl_usb_ioctl entered");
if (!instance) { if (!instance) {
PDEBUG ("NULL instance!\n"); dbg ("NULL instance!");
return -ENODEV; return -ENODEV;
} }
...@@ -869,10 +892,10 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i ...@@ -869,10 +892,10 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i
int ifnum = intf->altsetting->desc.bInterfaceNumber; int ifnum = intf->altsetting->desc.bInterfaceNumber;
struct udsl_instance_data *instance; struct udsl_instance_data *instance;
unsigned char mac_str [13]; unsigned char mac_str [13];
unsigned char mac [6]; int i, length;
int i; char *buf;
PDEBUG ("Trying device with Vendor=0x%x, Product=0x%x, ifnum %d\n", dbg ("Trying device with Vendor=0x%x, Product=0x%x, ifnum %d",
dev->descriptor.idVendor, dev->descriptor.idProduct, ifnum); dev->descriptor.idVendor, dev->descriptor.idProduct, ifnum);
if ((dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) || if ((dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) ||
...@@ -880,11 +903,11 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i ...@@ -880,11 +903,11 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i
(dev->descriptor.idProduct != SPEEDTOUCH_PRODUCTID) || (ifnum != 1)) (dev->descriptor.idProduct != SPEEDTOUCH_PRODUCTID) || (ifnum != 1))
return -ENODEV; return -ENODEV;
PDEBUG ("Device Accepted\n"); dbg ("Device Accepted");
/* instance init */ /* instance init */
if (!(instance = kmalloc (sizeof (struct udsl_instance_data), GFP_KERNEL))) { if (!(instance = kmalloc (sizeof (struct udsl_instance_data), GFP_KERNEL))) {
PDEBUG ("No memory for Instance data!\n"); dbg ("No memory for Instance data!");
return -ENOMEM; return -ENOMEM;
} }
...@@ -916,12 +939,12 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i ...@@ -916,12 +939,12 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i
struct udsl_receiver *rcv = &(instance->all_receivers[i]); struct udsl_receiver *rcv = &(instance->all_receivers[i]);
if (!(rcv->skb = dev_alloc_skb (UDSL_RCV_BUFFER_SIZE * ATM_CELL_SIZE))) { if (!(rcv->skb = dev_alloc_skb (UDSL_RCV_BUFFER_SIZE * ATM_CELL_SIZE))) {
PDEBUG ("No memory for skb %d!\n", i); dbg ("No memory for skb %d!", i);
goto fail; goto fail;
} }
if (!(rcv->urb = usb_alloc_urb (0, GFP_KERNEL))) { if (!(rcv->urb = usb_alloc_urb (0, GFP_KERNEL))) {
PDEBUG ("No memory for receive urb %d!\n", i); dbg ("No memory for receive urb %d!", i);
goto fail; goto fail;
} }
...@@ -929,7 +952,7 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i ...@@ -929,7 +952,7 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i
list_add (&rcv->list, &instance->spare_receivers); list_add (&rcv->list, &instance->spare_receivers);
PDEBUG ("skb->truesize = %d (asked for %d)\n", rcv->skb->truesize, UDSL_RCV_BUFFER_SIZE * ATM_CELL_SIZE); dbg ("skb->truesize = %d (asked for %d)", rcv->skb->truesize, UDSL_RCV_BUFFER_SIZE * ATM_CELL_SIZE);
} }
/* send init */ /* send init */
...@@ -937,7 +960,7 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i ...@@ -937,7 +960,7 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i
struct udsl_sender *snd = &(instance->all_senders[i]); struct udsl_sender *snd = &(instance->all_senders[i]);
if (!(snd->urb = usb_alloc_urb (0, GFP_KERNEL))) { if (!(snd->urb = usb_alloc_urb (0, GFP_KERNEL))) {
PDEBUG ("No memory for send urb %d!\n", i); dbg ("No memory for send urb %d!", i);
goto fail; goto fail;
} }
...@@ -950,7 +973,7 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i ...@@ -950,7 +973,7 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i
struct udsl_send_buffer *buf = &(instance->all_buffers[i]); struct udsl_send_buffer *buf = &(instance->all_buffers[i]);
if (!(buf->base = kmalloc (UDSL_SND_BUFFER_SIZE * ATM_CELL_SIZE, GFP_KERNEL))) { if (!(buf->base = kmalloc (UDSL_SND_BUFFER_SIZE * ATM_CELL_SIZE, GFP_KERNEL))) {
PDEBUG ("No memory for send buffer %d!\n", i); dbg ("No memory for send buffer %d!", i);
goto fail; goto fail;
} }
...@@ -959,28 +982,47 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i ...@@ -959,28 +982,47 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i
/* atm init */ /* atm init */
if (!(instance->atm_dev = atm_dev_register (udsl_driver_name, &udsl_atm_devops, -1, 0))) { if (!(instance->atm_dev = atm_dev_register (udsl_driver_name, &udsl_atm_devops, -1, 0))) {
PDEBUG ("failed to register ATM device!\n"); dbg ("failed to register ATM device!");
goto fail; goto fail;
} }
instance->atm_dev->ci_range.vpi_bits = ATM_CI_MAX; instance->atm_dev->ci_range.vpi_bits = ATM_CI_MAX;
instance->atm_dev->ci_range.vci_bits = ATM_CI_MAX; instance->atm_dev->ci_range.vci_bits = ATM_CI_MAX;
instance->atm_dev->signal = ATM_PHY_SIG_LOST; instance->atm_dev->signal = ATM_PHY_SIG_UNKNOWN;
/* tmp init atm device, set to 128kbit */ /* tmp init atm device, set to 128kbit */
instance->atm_dev->link_rate = 128 * 1000 / 424; instance->atm_dev->link_rate = 128 * 1000 / 424;
/* set MAC address, it is stored in the serial number */ /* set MAC address, it is stored in the serial number */
usb_string (instance->usb_dev, instance->usb_dev->descriptor.iSerialNumber, mac_str, 13); memset (instance->atm_dev->esi, 0, sizeof (instance->atm_dev->esi));
if (usb_string (dev, dev->descriptor.iSerialNumber, mac_str, sizeof (mac_str)) == 12)
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
mac[i] = (hex2int (mac_str[i * 2]) * 16) + (hex2int (mac_str[i * 2 + 1])); instance->atm_dev->esi[i] = (hex2int (mac_str[i * 2]) * 16) + (hex2int (mac_str[i * 2 + 1]));
/* device description */
buf = instance->description;
length = sizeof (instance->description);
if ((i = usb_string (dev, dev->descriptor.iProduct, buf, length)) < 0)
goto finish;
PDEBUG ("MAC is %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); buf += i;
length -= i;
memcpy (instance->atm_dev->esi, mac, 6); i = snprintf (buf, length, " (");
buf += i;
length -= i;
wmb (); if (length <= 0 || (i = usb_make_path (dev, buf, length)) < 0)
goto finish;
buf += i;
length -= i;
snprintf (buf, length, ")");
finish:
/* ready for ATM callbacks */
instance->atm_dev->dev_data = instance; instance->atm_dev->dev_data = instance;
usb_set_intfdata (intf, instance); usb_set_intfdata (intf, instance);
...@@ -1016,12 +1058,12 @@ static void udsl_usb_disconnect (struct usb_interface *intf) ...@@ -1016,12 +1058,12 @@ static void udsl_usb_disconnect (struct usb_interface *intf)
unsigned int count = 0; unsigned int count = 0;
int result, i; int result, i;
PDEBUG ("disconnecting\n"); dbg ("disconnecting");
usb_set_intfdata (intf, NULL); usb_set_intfdata (intf, NULL);
if (!instance) { if (!instance) {
PDEBUG ("NULL instance!\n"); dbg ("NULL instance!");
return; return;
} }
...@@ -1036,13 +1078,13 @@ static void udsl_usb_disconnect (struct usb_interface *intf) ...@@ -1036,13 +1078,13 @@ static void udsl_usb_disconnect (struct usb_interface *intf)
INIT_LIST_HEAD (&instance->spare_receivers); INIT_LIST_HEAD (&instance->spare_receivers);
up (&instance->serialize); up (&instance->serialize);
PDEBUG ("udsl_usb_disconnect: flushed %u spare receivers\n", count); dbg ("udsl_usb_disconnect: flushed %u spare receivers", count);
count = UDSL_NUMBER_RCV_URBS - count; count = UDSL_NUMBER_RCV_URBS - count;
for (i = 0; i < UDSL_NUMBER_RCV_URBS; i++) for (i = 0; i < UDSL_NUMBER_RCV_URBS; i++)
if ((result = usb_unlink_urb (instance->all_receivers[i].urb)) < 0) if ((result = usb_unlink_urb (instance->all_receivers[i].urb)) < 0)
PDEBUG ("udsl_usb_disconnect: usb_unlink_urb on receive urb %d returned %d\n", i, result); dbg ("udsl_usb_disconnect: usb_unlink_urb on receive urb %d returned %d", i, result);
/* wait for completion handlers to finish */ /* wait for completion handlers to finish */
do { do {
...@@ -1054,7 +1096,7 @@ static void udsl_usb_disconnect (struct usb_interface *intf) ...@@ -1054,7 +1096,7 @@ static void udsl_usb_disconnect (struct usb_interface *intf)
panic (__FILE__ ": memory corruption detected at line %d!\n", __LINE__); panic (__FILE__ ": memory corruption detected at line %d!\n", __LINE__);
spin_unlock_irqrestore (&instance->completed_receivers_lock, flags); spin_unlock_irqrestore (&instance->completed_receivers_lock, flags);
PDEBUG ("udsl_usb_disconnect: found %u completed receivers\n", completed); dbg ("udsl_usb_disconnect: found %u completed receivers", completed);
if (completed == count) if (completed == count)
break; break;
...@@ -1062,14 +1104,14 @@ static void udsl_usb_disconnect (struct usb_interface *intf) ...@@ -1062,14 +1104,14 @@ static void udsl_usb_disconnect (struct usb_interface *intf)
yield (); yield ();
} while (1); } while (1);
PDEBUG ("udsl_usb_disconnect: flushing\n"); dbg ("udsl_usb_disconnect: flushing");
/* no need to take the spinlock */ /* no need to take the spinlock */
INIT_LIST_HEAD (&instance->completed_receivers); INIT_LIST_HEAD (&instance->completed_receivers);
tasklet_enable (&instance->receive_tasklet); tasklet_enable (&instance->receive_tasklet);
tasklet_kill (&instance->receive_tasklet); tasklet_kill (&instance->receive_tasklet);
PDEBUG ("udsl_usb_disconnect: freeing receivers\n"); dbg ("udsl_usb_disconnect: freeing receivers");
for (i = 0; i < UDSL_NUMBER_RCV_URBS; i++) { for (i = 0; i < UDSL_NUMBER_RCV_URBS; i++) {
struct udsl_receiver *rcv = &(instance->all_receivers[i]); struct udsl_receiver *rcv = &(instance->all_receivers[i]);
...@@ -1082,7 +1124,7 @@ static void udsl_usb_disconnect (struct usb_interface *intf) ...@@ -1082,7 +1124,7 @@ static void udsl_usb_disconnect (struct usb_interface *intf)
for (i = 0; i < UDSL_NUMBER_SND_URBS; i++) for (i = 0; i < UDSL_NUMBER_SND_URBS; i++)
if ((result = usb_unlink_urb (instance->all_senders[i].urb)) < 0) if ((result = usb_unlink_urb (instance->all_senders[i].urb)) < 0)
PDEBUG ("udsl_usb_disconnect: usb_unlink_urb on send urb %d returned %d\n", i, result); dbg ("udsl_usb_disconnect: usb_unlink_urb on send urb %d returned %d", i, result);
/* wait for completion handlers to finish */ /* wait for completion handlers to finish */
do { do {
...@@ -1093,7 +1135,7 @@ static void udsl_usb_disconnect (struct usb_interface *intf) ...@@ -1093,7 +1135,7 @@ static void udsl_usb_disconnect (struct usb_interface *intf)
panic (__FILE__ ": memory corruption detected at line %d!\n", __LINE__); panic (__FILE__ ": memory corruption detected at line %d!\n", __LINE__);
spin_unlock_irqrestore (&instance->send_lock, flags); spin_unlock_irqrestore (&instance->send_lock, flags);
PDEBUG ("udsl_usb_disconnect: found %u spare senders\n", count); dbg ("udsl_usb_disconnect: found %u spare senders", count);
if (count == UDSL_NUMBER_SND_URBS) if (count == UDSL_NUMBER_SND_URBS)
break; break;
...@@ -1101,7 +1143,7 @@ static void udsl_usb_disconnect (struct usb_interface *intf) ...@@ -1101,7 +1143,7 @@ static void udsl_usb_disconnect (struct usb_interface *intf)
yield (); yield ();
} while (1); } while (1);
PDEBUG ("udsl_usb_disconnect: flushing\n"); dbg ("udsl_usb_disconnect: flushing");
/* no need to take the spinlock */ /* no need to take the spinlock */
INIT_LIST_HEAD (&instance->spare_senders); INIT_LIST_HEAD (&instance->spare_senders);
INIT_LIST_HEAD (&instance->spare_buffers); INIT_LIST_HEAD (&instance->spare_buffers);
...@@ -1109,16 +1151,18 @@ static void udsl_usb_disconnect (struct usb_interface *intf) ...@@ -1109,16 +1151,18 @@ static void udsl_usb_disconnect (struct usb_interface *intf)
tasklet_enable (&instance->send_tasklet); tasklet_enable (&instance->send_tasklet);
PDEBUG ("udsl_usb_disconnect: freeing senders\n"); dbg ("udsl_usb_disconnect: freeing senders");
for (i = 0; i < UDSL_NUMBER_SND_URBS; i++) for (i = 0; i < UDSL_NUMBER_SND_URBS; i++)
usb_free_urb (instance->all_senders[i].urb); usb_free_urb (instance->all_senders[i].urb);
PDEBUG ("udsl_usb_disconnect: freeing buffers\n"); dbg ("udsl_usb_disconnect: freeing buffers");
for (i = 0; i < UDSL_NUMBER_SND_BUFS; i++) for (i = 0; i < UDSL_NUMBER_SND_BUFS; i++)
kfree (instance->all_buffers[i].base); kfree (instance->all_buffers[i].base);
instance->usb_dev = NULL;
/* atm finalize */ /* atm finalize */
shutdown_atm_dev (instance->atm_dev); shutdown_atm_dev (instance->atm_dev); /* frees instance */
} }
...@@ -1132,7 +1176,7 @@ static int __init udsl_usb_init (void) ...@@ -1132,7 +1176,7 @@ static int __init udsl_usb_init (void)
{ {
struct sk_buff *skb; /* dummy for sizeof */ struct sk_buff *skb; /* dummy for sizeof */
PDEBUG ("udsl_usb_init: driver version " DRIVER_VERSION "\n"); dbg ("udsl_usb_init: driver version " DRIVER_VERSION);
if (sizeof (struct udsl_control) > sizeof (skb->cb)) { if (sizeof (struct udsl_control) > sizeof (skb->cb)) {
printk (KERN_ERR __FILE__ ": unusable with this kernel!\n"); printk (KERN_ERR __FILE__ ": unusable with this kernel!\n");
...@@ -1144,7 +1188,7 @@ static int __init udsl_usb_init (void) ...@@ -1144,7 +1188,7 @@ static int __init udsl_usb_init (void)
static void __exit udsl_usb_cleanup (void) static void __exit udsl_usb_cleanup (void)
{ {
PDEBUG ("udsl_usb_cleanup\n"); dbg ("udsl_usb_cleanup");
usb_deregister (&udsl_usb_driver); usb_deregister (&udsl_usb_driver);
} }
...@@ -1175,7 +1219,7 @@ static int udsl_print_packet (const unsigned char *data, int len) ...@@ -1175,7 +1219,7 @@ static int udsl_print_packet (const unsigned char *data, int len)
for (j = 0; (j < 16) && (i < len); j++, i++) { for (j = 0; (j < 16) && (i < len); j++, i++) {
sprintf (buffer, "%s %2.2x", buffer, data[i]); sprintf (buffer, "%s %2.2x", buffer, data[i]);
} }
PDEBUG ("%s\n", buffer); dbg ("%s", buffer);
} }
return i; return i;
} }
......
...@@ -153,7 +153,7 @@ write_lcd(struct file *file, const char *buffer, ...@@ -153,7 +153,7 @@ write_lcd(struct file *file, const char *buffer,
} }
interruptible_sleep_on_timeout(&lcd-> wait_q, NAK_TIMEOUT); interruptible_sleep_on_timeout(&lcd-> wait_q, NAK_TIMEOUT);
continue; continue;
} else if (!result & partial) { } else if (!result && partial) {
obuf += partial; obuf += partial;
thistime -= partial; thistime -= partial;
} else } else
......
...@@ -552,6 +552,7 @@ static int ch9_postconfig (struct usbtest_dev *dev) ...@@ -552,6 +552,7 @@ static int ch9_postconfig (struct usbtest_dev *dev)
* (b) protocol stalls (control-only) will autorecover. * (b) protocol stalls (control-only) will autorecover.
* it's quite not like bulk/intr; no halt clearing. * it's quite not like bulk/intr; no halt clearing.
* (c) short control reads are reported and handled. * (c) short control reads are reported and handled.
* (d) queues are always processed in-order
*/ */
struct ctrl_ctx { struct ctrl_ctx {
...@@ -563,66 +564,68 @@ struct ctrl_ctx { ...@@ -563,66 +564,68 @@ struct ctrl_ctx {
int status; int status;
struct urb **urb; struct urb **urb;
struct usbtest_param *param; 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) static void ctrl_complete (struct urb *urb, struct pt_regs *regs)
{ {
struct ctrl_ctx *ctx = urb->context; struct ctrl_ctx *ctx = urb->context;
struct usb_ctrlrequest *reqp; struct usb_ctrlrequest *reqp;
struct subcase *subcase;
int status = urb->status; int status = urb->status;
reqp = (struct usb_ctrlrequest *)urb->setup_packet; reqp = (struct usb_ctrlrequest *)urb->setup_packet;
subcase = container_of (reqp, struct subcase, setup);
spin_lock (&ctx->lock); spin_lock (&ctx->lock);
ctx->count--; ctx->count--;
ctx->pending--; ctx->pending--;
/* FIXME verify that the completions are in the right sequence. /* queue must transfer and complete in fifo order, unless
* we could store the test number with the setup packet, that * usb_unlink_urb() is used to unlink something not at the
* buffer has extra space. * physical queue head (not tested).
*/ */
if (subcase->number > 0) {
switch (status) { if ((subcase->number - ctx->last) != 1) {
case 0: /* success */ dbg ("subcase %d completed out of order, last %d",
case -EREMOTEIO: /* short read */ subcase->number, ctx->last);
if (reqp->bRequestType == (USB_DIR_IN|USB_RECIP_DEVICE) status = -EDOM;
&& 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; goto error;
} }
break; }
case -ECONNRESET: /* async unlink */ ctx->last = subcase->number;
break;
case -EPIPE: /* (protocol) stall */ /* succeed or fault in only one way? */
if (reqp->bRequestType == (USB_DIR_IN|USB_RECIP_INTERFACE) if (status == subcase->expected)
&& reqp->bRequest == USB_REQ_GET_INTERFACE)
status = 0; status = 0;
else if (reqp->bRequestType == (USB_DIR_IN|USB_RECIP_DEVICE)
&& reqp->bRequest == USB_REQ_GET_DESCRIPTOR) { /* async unlink for cleanup? */
switch (le16_to_cpu (reqp->wValue) >> 8) { else if (status != -ECONNRESET) {
case USB_DT_DEVICE_QUALIFIER:
case USB_DT_OTHER_SPEED_CONFIG: /* some faults are allowed, not required */
case USB_DT_INTERFACE: if (subcase->expected > 0 && (
case USB_DT_ENDPOINT: ((urb->status == -subcase->expected /* happened */
|| urb->status == 0)))) /* didn't */
status = 0; status = 0;
} /* sometimes more than one fault is allowed */
} else if (reqp->bRequestType == USB_RECIP_ENDPOINT else if (subcase->number == 12 && status == -EPIPE)
&& reqp->bRequest == USB_REQ_CLEAR_FEATURE)
status = 0; status = 0;
/* some stalls we plan on; others would be errors */ else
if (status == 0) dbg ("subtest %d error, status %d",
break; subcase->number, status);
/* else FALLTHROUGH */ }
/* unexpected status codes mean errors; ideally, in hardware */
if (status) {
error: error:
default: /* this fault's an error */
if (ctx->status == 0) { if (ctx->status == 0) {
int i; int i;
...@@ -631,10 +634,8 @@ static void ctrl_complete (struct urb *urb, struct pt_regs *regs) ...@@ -631,10 +634,8 @@ static void ctrl_complete (struct urb *urb, struct pt_regs *regs)
reqp->bRequestType, reqp->bRequest, reqp->bRequestType, reqp->bRequest,
status, ctx->count); status, ctx->count);
/* FIXME use this "unlink everything" exit route /* FIXME this "unlink everything" exit route should
* in all cases, not just for fault cleanup. * be a separate test case.
* it'll be another test mode, but one that makes
* testing be more consistent.
*/ */
/* unlink whatever's still pending */ /* unlink whatever's still pending */
...@@ -688,6 +689,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param) ...@@ -688,6 +689,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
context.pending = 0; context.pending = 0;
context.status = -ENOMEM; context.status = -ENOMEM;
context.param = param; context.param = param;
context.last = -1;
/* allocate and init the urbs we'll queue. /* allocate and init the urbs we'll queue.
* as with bulk/intr sglists, sglen is the queue depth; it also * 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) ...@@ -701,7 +703,9 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
int pipe = usb_rcvctrlpipe (udev, 0); int pipe = usb_rcvctrlpipe (udev, 0);
unsigned len; unsigned len;
struct urb *u; 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 /* requests here are mostly expected to succeed on any
* device, but some are chosen to trigger protocol stalls * device, but some are chosen to trigger protocol stalls
...@@ -711,7 +715,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param) ...@@ -711,7 +715,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
req.bRequest = USB_REQ_GET_DESCRIPTOR; req.bRequest = USB_REQ_GET_DESCRIPTOR;
req.bRequestType = USB_DIR_IN|USB_RECIP_DEVICE; 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 case 0: // get device descriptor
req.wValue = cpu_to_le16 (USB_DT_DEVICE << 8); req.wValue = cpu_to_le16 (USB_DT_DEVICE << 8);
len = sizeof (struct usb_device_descriptor); len = sizeof (struct usb_device_descriptor);
...@@ -725,6 +729,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param) ...@@ -725,6 +729,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
req.bRequestType = USB_DIR_IN|USB_RECIP_INTERFACE; req.bRequestType = USB_DIR_IN|USB_RECIP_INTERFACE;
// index = 0 means first interface // index = 0 means first interface
len = 1; len = 1;
expected = EPIPE;
break; break;
case 3: // get interface status case 3: // get interface status
req.bRequest = USB_REQ_GET_STATUS; req.bRequest = USB_REQ_GET_STATUS;
...@@ -740,6 +745,8 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param) ...@@ -740,6 +745,8 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
case 5: // get device qualifier (MAY STALL) case 5: // get device qualifier (MAY STALL)
req.wValue = cpu_to_le16 (USB_DT_DEVICE_QUALIFIER << 8); req.wValue = cpu_to_le16 (USB_DT_DEVICE_QUALIFIER << 8);
len = sizeof (struct usb_qualifier_descriptor); len = sizeof (struct usb_qualifier_descriptor);
if (udev->speed != USB_SPEED_HIGH)
expected = EPIPE;
break; break;
case 6: // get first config descriptor, plus interface case 6: // get first config descriptor, plus interface
req.wValue = cpu_to_le16 ((USB_DT_CONFIG << 8) | 0); 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) ...@@ -750,6 +757,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
req.wValue = cpu_to_le16 (USB_DT_INTERFACE << 8); req.wValue = cpu_to_le16 (USB_DT_INTERFACE << 8);
// interface == 0 // interface == 0
len = sizeof (struct usb_interface_descriptor); len = sizeof (struct usb_interface_descriptor);
expected = -EPIPE;
break; break;
// NOTE: two consecutive stalls in the queue here. // NOTE: two consecutive stalls in the queue here.
// that tests fault recovery a bit more aggressively. // that tests fault recovery a bit more aggressively.
...@@ -760,6 +768,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param) ...@@ -760,6 +768,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
// wIndex 0 == ep0 (shouldn't halt!) // wIndex 0 == ep0 (shouldn't halt!)
len = 0; len = 0;
pipe = usb_sndctrlpipe (udev, 0); pipe = usb_sndctrlpipe (udev, 0);
expected = EPIPE;
break; break;
case 9: // get endpoint status case 9: // get endpoint status
req.bRequest = USB_REQ_GET_STATUS; req.bRequest = USB_REQ_GET_STATUS;
...@@ -770,18 +779,21 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param) ...@@ -770,18 +779,21 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
case 10: // trigger short read (EREMOTEIO) case 10: // trigger short read (EREMOTEIO)
req.wValue = cpu_to_le16 ((USB_DT_CONFIG << 8) | 0); req.wValue = cpu_to_le16 ((USB_DT_CONFIG << 8) | 0);
len = 1024; len = 1024;
expected = -EREMOTEIO;
break; break;
// NOTE: two consecutive _different_ faults in the queue. // NOTE: two consecutive _different_ faults in the queue.
case 11: // get endpoint descriptor (ALWAYS STALLS) case 11: // get endpoint descriptor (ALWAYS STALLS)
req.wValue = cpu_to_le16 (USB_DT_ENDPOINT << 8); req.wValue = cpu_to_le16 (USB_DT_ENDPOINT << 8);
// endpoint == 0 // endpoint == 0
len = sizeof (struct usb_interface_descriptor); len = sizeof (struct usb_interface_descriptor);
expected = -EPIPE;
break; break;
// NOTE: sometimes even a third fault in the queue! // NOTE: sometimes even a third fault in the queue!
case 12: // get string 0 descriptor (MAY STALL) case 12: // get string 0 descriptor (MAY STALL)
req.wValue = cpu_to_le16 (USB_DT_STRING << 8); req.wValue = cpu_to_le16 (USB_DT_STRING << 8);
// string == 0, for language IDs // string == 0, for language IDs
len = sizeof (struct usb_interface_descriptor); len = sizeof (struct usb_interface_descriptor);
expected = EREMOTEIO; // or EPIPE, if no strings
break; break;
default: default:
err ("bogus number of ctrl queue testcases!"); err ("bogus number of ctrl queue testcases!");
...@@ -793,12 +805,14 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param) ...@@ -793,12 +805,14 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
if (!u) if (!u)
goto cleanup; goto cleanup;
reqp = usb_buffer_alloc (udev, sizeof req, SLAB_KERNEL, reqp = usb_buffer_alloc (udev, sizeof *reqp, SLAB_KERNEL,
&u->setup_dma); &u->setup_dma);
if (!reqp) if (!reqp)
goto cleanup; goto cleanup;
*reqp = req; reqp->setup = req;
u->setup_packet = (char *) reqp; reqp->number = i % NUM_SUBCASES;
reqp->expected = expected;
u->setup_packet = (char *) &reqp->setup;
u->context = &context; u->context = &context;
u->complete = ctrl_complete; u->complete = ctrl_complete;
...@@ -839,6 +853,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param) ...@@ -839,6 +853,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
kfree (urb); kfree (urb);
return context.status; return context.status;
} }
#undef NUM_SUBCASES
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
...@@ -886,7 +901,16 @@ static int unlink1 (struct usbtest_dev *dev, int pipe, int size, int async) ...@@ -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. * hcd states and code paths, even with little other system load.
*/ */
wait_ms (jiffies % (2 * INTERRUPT_RATE)); wait_ms (jiffies % (2 * INTERRUPT_RATE));
retry:
retval = usb_unlink_urb (urb); 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)) { if (!(retval == 0 || retval == -EINPROGRESS)) {
dbg ("submit/unlink fail %d", retval); dbg ("submit/unlink fail %d", retval);
return retval; return retval;
...@@ -1309,7 +1333,13 @@ static struct usbtest_info ez2_info = { ...@@ -1309,7 +1333,13 @@ static struct usbtest_info ez2_info = {
.alt = 1, .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 = { static struct usbtest_info fw_info = {
.name = "usb test device", .name = "usb test device",
.ep_in = 2, .ep_in = 2,
......
...@@ -246,6 +246,12 @@ config USB_SERIAL_KEYSPAN ...@@ -246,6 +246,12 @@ config USB_SERIAL_KEYSPAN
The module will be called keyspan. If you want to compile it as a The module will be called keyspan. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>. 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 config USB_SERIAL_KEYSPAN_USA28
bool "USB Keyspan USA-28 Firmware" bool "USB Keyspan USA-28 Firmware"
depends on USB_SERIAL_KEYSPAN depends on USB_SERIAL_KEYSPAN
...@@ -312,6 +318,12 @@ config USB_SERIAL_KEYSPAN_USA49W ...@@ -312,6 +318,12 @@ config USB_SERIAL_KEYSPAN_USA49W
help help
Say Y here to include firmware for the USA-49W converter. 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 config USB_SERIAL_KLSI
tristate "USB KL5KUSB105 (Palmconnect) Driver (EXPERIMENTAL)" tristate "USB KL5KUSB105 (Palmconnect) Driver (EXPERIMENTAL)"
depends on USB_SERIAL && EXPERIMENTAL depends on USB_SERIAL && EXPERIMENTAL
......
...@@ -144,6 +144,7 @@ static struct usb_serial_device_type belkin_device = { ...@@ -144,6 +144,7 @@ static struct usb_serial_device_type belkin_device = {
struct belkin_sa_private { struct belkin_sa_private {
spinlock_t lock;
unsigned long control_state; unsigned long control_state;
unsigned char last_lsr; unsigned char last_lsr;
unsigned char last_msr; unsigned char last_msr;
...@@ -175,6 +176,7 @@ static int belkin_sa_startup (struct usb_serial *serial) ...@@ -175,6 +176,7 @@ static int belkin_sa_startup (struct usb_serial *serial)
if (!priv) if (!priv)
return (-1); /* error */ return (-1); /* error */
/* set initial values for control structures */ /* set initial values for control structures */
spin_lock_init(&priv->lock);
priv->control_state = 0; priv->control_state = 0;
priv->last_lsr = 0; priv->last_lsr = 0;
priv->last_msr = 0; priv->last_msr = 0;
...@@ -262,6 +264,7 @@ static void belkin_sa_read_int_callback (struct urb *urb, struct pt_regs *regs) ...@@ -262,6 +264,7 @@ static void belkin_sa_read_int_callback (struct urb *urb, struct pt_regs *regs)
struct usb_serial *serial; struct usb_serial *serial;
unsigned char *data = urb->transfer_buffer; unsigned char *data = urb->transfer_buffer;
int retval; int retval;
unsigned long flags;
switch (urb->status) { switch (urb->status) {
case 0: case 0:
...@@ -289,6 +292,7 @@ static void belkin_sa_read_int_callback (struct urb *urb, struct pt_regs *regs) ...@@ -289,6 +292,7 @@ static void belkin_sa_read_int_callback (struct urb *urb, struct pt_regs *regs)
/* ignore data[0] and data[1] */ /* ignore data[0] and data[1] */
priv = usb_get_serial_port_data(port); priv = usb_get_serial_port_data(port);
spin_lock_irqsave(&priv->lock, flags);
priv->last_msr = data[BELKIN_SA_MSR_INDEX]; priv->last_msr = data[BELKIN_SA_MSR_INDEX];
/* Record Control Line states */ /* Record Control Line states */
...@@ -336,6 +340,7 @@ static void belkin_sa_read_int_callback (struct urb *urb, struct pt_regs *regs) ...@@ -336,6 +340,7 @@ static void belkin_sa_read_int_callback (struct urb *urb, struct pt_regs *regs)
} }
} }
#endif #endif
spin_unlock_irqrestore(&priv->lock, flags);
exit: exit:
retval = usb_submit_urb (urb, GFP_ATOMIC); retval = usb_submit_urb (urb, GFP_ATOMIC);
if (retval) if (retval)
...@@ -352,6 +357,9 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct termios ...@@ -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_iflag = 0;
unsigned int old_cflag = 0; unsigned int old_cflag = 0;
__u16 urb_value = 0; /* Will hold the new flags */ __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)) { if ((!port->tty) || (!port->tty->termios)) {
dbg ("%s - no tty or termios structure", __FUNCTION__); 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 ...@@ -361,6 +369,12 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct termios
iflag = port->tty->termios->c_iflag; iflag = port->tty->termios->c_iflag;
cflag = port->tty->termios->c_cflag; 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 */ /* check that they really want us to change something */
if (old_termios) { if (old_termios) {
if ((cflag == old_termios->c_cflag) && if ((cflag == old_termios->c_cflag) &&
...@@ -376,7 +390,7 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct termios ...@@ -376,7 +390,7 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct termios
if( (cflag&CBAUD) != (old_cflag&CBAUD) ) { if( (cflag&CBAUD) != (old_cflag&CBAUD) ) {
/* reassert DTR and (maybe) RTS on transition from B0 */ /* reassert DTR and (maybe) RTS on transition from B0 */
if( (old_cflag&CBAUD) == 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) if (BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, 1) < 0)
err("Set DTR error"); err("Set DTR error");
/* don't set RTS if using hardware flow control */ /* 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 ...@@ -410,7 +424,7 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct termios
err("Disable flowcontrol error"); err("Disable flowcontrol error");
/* Drop RTS and DTR */ /* 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) if (BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, 0) < 0)
err("DTR LOW error"); err("DTR LOW error");
if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, 0) < 0) 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 ...@@ -465,12 +479,17 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct termios
else else
urb_value &= ~(BELKIN_SA_FLOW_OCTS | BELKIN_SA_FLOW_IRTS); 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); urb_value &= ~(BELKIN_SA_FLOW_IRTS);
if (BSA_USB_CMD(BELKIN_SA_SET_FLOW_CTRL_REQUEST, urb_value) < 0) if (BSA_USB_CMD(BELKIN_SA_SET_FLOW_CTRL_REQUEST, urb_value) < 0)
err("Set flow control error"); 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 */ } /* belkin_sa_set_termios */
...@@ -488,12 +507,19 @@ static int belkin_sa_ioctl (struct usb_serial_port *port, struct file * file, un ...@@ -488,12 +507,19 @@ static int belkin_sa_ioctl (struct usb_serial_port *port, struct file * file, un
struct usb_serial *serial = port->serial; struct usb_serial *serial = port->serial;
__u16 urb_value; /* Will hold the new flags */ __u16 urb_value; /* Will hold the new flags */
struct belkin_sa_private *priv = usb_get_serial_port_data(port); 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 */ /* Based on code from acm.c and others */
switch (cmd) { switch (cmd) {
case TIOCMGET: case TIOCMGET:
return put_user(priv->control_state, (unsigned long *) arg); return put_user(control_state, (unsigned long *) arg);
break; break;
case TIOCMSET: /* Turns on and off the lines as specified by the mask */ 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 ...@@ -506,13 +532,13 @@ static int belkin_sa_ioctl (struct usb_serial_port *port, struct file * file, un
/* RTS needs set */ /* RTS needs set */
urb_value = ((cmd == TIOCMSET) && (mask & TIOCM_RTS)) || (cmd == TIOCMBIS) ? 1 : 0; urb_value = ((cmd == TIOCMSET) && (mask & TIOCM_RTS)) || (cmd == TIOCMBIS) ? 1 : 0;
if (urb_value) if (urb_value)
priv->control_state |= TIOCM_RTS; control_state |= TIOCM_RTS;
else else
priv->control_state &= ~TIOCM_RTS; control_state &= ~TIOCM_RTS;
if ((ret = BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, urb_value)) < 0) { if ((ret = BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, urb_value)) < 0) {
err("Set RTS error %d", ret); 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 ...@@ -520,14 +546,19 @@ static int belkin_sa_ioctl (struct usb_serial_port *port, struct file * file, un
/* DTR needs set */ /* DTR needs set */
urb_value = ((cmd == TIOCMSET) && (mask & TIOCM_DTR)) || (cmd == TIOCMBIS) ? 1 : 0; urb_value = ((cmd == TIOCMSET) && (mask & TIOCM_DTR)) || (cmd == TIOCMBIS) ? 1 : 0;
if (urb_value) if (urb_value)
priv->control_state |= TIOCM_DTR; control_state |= TIOCM_DTR;
else else
priv->control_state &= ~TIOCM_DTR; control_state &= ~TIOCM_DTR;
if ((ret = BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, urb_value)) < 0) { if ((ret = BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, urb_value)) < 0) {
err("Set DTR error %d", ret); 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; break;
case TIOCMIWAIT: case TIOCMIWAIT:
......
...@@ -107,6 +107,7 @@ static struct usb_device_id ipaq_id_table [] = { ...@@ -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_IPAQ_ID) },
{ USB_DEVICE(COMPAQ_VENDOR_ID, COMPAQ_0032_ID) }, { USB_DEVICE(COMPAQ_VENDOR_ID, COMPAQ_0032_ID) },
{ USB_DEVICE(DELL_VENDOR_ID, DELL_AXIM_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_548_ID) },
{ USB_DEVICE(HP_VENDOR_ID, HP_JORNADA_568_ID) }, { USB_DEVICE(HP_VENDOR_ID, HP_JORNADA_568_ID) },
{ USB_DEVICE(HP_VENDOR_ID, HP_2016_ID) }, { USB_DEVICE(HP_VENDOR_ID, HP_2016_ID) },
......
...@@ -33,6 +33,9 @@ ...@@ -33,6 +33,9 @@
#define DELL_VENDOR_ID 0x413c #define DELL_VENDOR_ID 0x413c
#define DELL_AXIM_ID 0x4001 #define DELL_AXIM_ID 0x4001
#define FSC_VENDOR_ID 0x0bf8
#define FSC_LOOX_ID 0x1001
#define HP_VENDOR_ID 0x03f0 #define HP_VENDOR_ID 0x03f0
#define HP_JORNADA_548_ID 0x1016 #define HP_JORNADA_548_ID 0x1016
#define HP_JORNADA_568_ID 0x1116 #define HP_JORNADA_568_ID 0x1116
......
...@@ -28,6 +28,24 @@ ...@@ -28,6 +28,24 @@
Change History 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) Wed Apr 25 12:00:00 PST 2002 (Keyspan)
Started with Hugh Blemings' code dated Jan 17, 2002. All adapters Started with Hugh Blemings' code dated Jan 17, 2002. All adapters
now supported (including QI and QW). Modified port open, port now supported (including QI and QW). Modified port open, port
...@@ -103,7 +121,7 @@ ...@@ -103,7 +121,7 @@
/* /*
* Version Information * Version Information
*/ */
#define DRIVER_VERSION "v1.1.3" #define DRIVER_VERSION "v1.1.4"
#define DRIVER_AUTHOR "Hugh Blemings <hugh@misc.nu" #define DRIVER_AUTHOR "Hugh Blemings <hugh@misc.nu"
#define DRIVER_DESC "Keyspan USB to Serial Converter Driver" #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) ...@@ -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); */ /* 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); keyspan_send_setup(port, 1);
//mdelay(100); //mdelay(100);
keyspan_set_termios(port, NULL); keyspan_set_termios(port, NULL);
...@@ -1008,6 +1029,11 @@ static int keyspan_fake_startup (struct usb_serial *serial) ...@@ -1008,6 +1029,11 @@ static int keyspan_fake_startup (struct usb_serial *serial)
fw_name = "USA19QI"; fw_name = "USA19QI";
break; break;
case keyspan_mpr_pre_product_id:
record = &keyspan_mpr_firmware[0];
fw_name = "MPR";
break;
case keyspan_usa19qw_pre_product_id: case keyspan_usa19qw_pre_product_id:
record = &keyspan_usa19qw_firmware[0]; record = &keyspan_usa19qw_firmware[0];
fw_name = "USA19QI"; fw_name = "USA19QI";
...@@ -1028,6 +1054,11 @@ static int keyspan_fake_startup (struct usb_serial *serial) ...@@ -1028,6 +1054,11 @@ static int keyspan_fake_startup (struct usb_serial *serial)
fw_name = "USA49W"; fw_name = "USA49W";
break; break;
case keyspan_usa49wlc_pre_product_id:
record = &keyspan_usa49wlc_firmware[0];
fw_name = "USA49WLC";
break;
default: default:
record = NULL; record = NULL;
fw_name = "Unknown"; fw_name = "Unknown";
......
...@@ -136,6 +136,12 @@ struct ezusb_hex_record { ...@@ -136,6 +136,12 @@ struct ezusb_hex_record {
static const struct ezusb_hex_record *keyspan_usa19qi_firmware = NULL; static const struct ezusb_hex_record *keyspan_usa19qi_firmware = NULL;
#endif #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 #ifdef CONFIG_USB_SERIAL_KEYSPAN_USA19QW
#include "keyspan_usa19qw_fw.h" #include "keyspan_usa19qw_fw.h"
#else #else
...@@ -160,6 +166,12 @@ struct ezusb_hex_record { ...@@ -160,6 +166,12 @@ struct ezusb_hex_record {
static const struct ezusb_hex_record *keyspan_usa49w_firmware = NULL; static const struct ezusb_hex_record *keyspan_usa49w_firmware = NULL;
#endif #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 */ /* Values used for baud rate calculation - device specific */
#define KEYSPAN_INVALID_BAUD_RATE (-1) #define KEYSPAN_INVALID_BAUD_RATE (-1)
#define KEYSPAN_BAUD_RATE_OK (0) #define KEYSPAN_BAUD_RATE_OK (0)
...@@ -182,6 +194,7 @@ struct ezusb_hex_record { ...@@ -182,6 +194,7 @@ struct ezusb_hex_record {
#define keyspan_usa18x_pre_product_id 0x0105 #define keyspan_usa18x_pre_product_id 0x0105
#define keyspan_usa19_pre_product_id 0x0103 #define keyspan_usa19_pre_product_id 0x0103
#define keyspan_usa19qi_pre_product_id 0x010b #define keyspan_usa19qi_pre_product_id 0x010b
#define keyspan_mpr_pre_product_id 0x011b
#define keyspan_usa19qw_pre_product_id 0x0118 #define keyspan_usa19qw_pre_product_id 0x0118
#define keyspan_usa19w_pre_product_id 0x0106 #define keyspan_usa19w_pre_product_id 0x0106
#define keyspan_usa28_pre_product_id 0x0101 #define keyspan_usa28_pre_product_id 0x0101
...@@ -189,6 +202,7 @@ struct ezusb_hex_record { ...@@ -189,6 +202,7 @@ struct ezusb_hex_record {
#define keyspan_usa28xa_pre_product_id 0x0114 #define keyspan_usa28xa_pre_product_id 0x0114
#define keyspan_usa28xb_pre_product_id 0x0113 #define keyspan_usa28xb_pre_product_id 0x0113
#define keyspan_usa49w_pre_product_id 0x0109 #define keyspan_usa49w_pre_product_id 0x0109
#define keyspan_usa49wlc_pre_product_id 0x011a
/* Product IDs post-renumeration. Note that the 28x and 28xb /* Product IDs post-renumeration. Note that the 28x and 28xb
have the same id's post-renumeration but behave identically have the same id's post-renumeration but behave identically
...@@ -196,6 +210,7 @@ struct ezusb_hex_record { ...@@ -196,6 +210,7 @@ struct ezusb_hex_record {
#define keyspan_usa18x_product_id 0x0112 #define keyspan_usa18x_product_id 0x0112
#define keyspan_usa19_product_id 0x0107 #define keyspan_usa19_product_id 0x0107
#define keyspan_usa19qi_product_id 0x010c #define keyspan_usa19qi_product_id 0x010c
#define keyspan_mpr_product_id 0x011c
#define keyspan_usa19qw_product_id 0x0119 #define keyspan_usa19qw_product_id 0x0119
#define keyspan_usa19w_product_id 0x0108 #define keyspan_usa19w_product_id 0x0108
#define keyspan_usa28_product_id 0x010f #define keyspan_usa28_product_id 0x010f
...@@ -203,6 +218,7 @@ struct ezusb_hex_record { ...@@ -203,6 +218,7 @@ struct ezusb_hex_record {
#define keyspan_usa28xa_product_id 0x0115 #define keyspan_usa28xa_product_id 0x0115
#define keyspan_usa28xb_product_id 0x0110 #define keyspan_usa28xb_product_id 0x0110
#define keyspan_usa49w_product_id 0x010a #define keyspan_usa49w_product_id 0x010a
#define keyspan_usa49wlc_product_id 0x012a
struct keyspan_device_details { struct keyspan_device_details {
...@@ -394,6 +410,22 @@ static const struct keyspan_device_details usa49w_device_details = { ...@@ -394,6 +410,22 @@ static const struct keyspan_device_details usa49w_device_details = {
.baudclk = KEYSPAN_USA49W_BAUDCLK, .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[] = { static const struct keyspan_device_details *keyspan_devices[] = {
&usa18x_device_details, &usa18x_device_details,
&usa19_device_details, &usa19_device_details,
...@@ -405,6 +437,7 @@ static const struct keyspan_device_details *keyspan_devices[] = { ...@@ -405,6 +437,7 @@ static const struct keyspan_device_details *keyspan_devices[] = {
&usa28xa_device_details, &usa28xa_device_details,
/* 28xb not required as it renumerates as a 28x */ /* 28xb not required as it renumerates as a 28x */
&usa49w_device_details, &usa49w_device_details,
&usa49wlc_device_details,
NULL, NULL,
}; };
...@@ -414,21 +447,25 @@ static struct usb_device_id keyspan_ids_combined[] = { ...@@ -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_usa19w_pre_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qi_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_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_usa28_pre_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_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_usa28xa_pre_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_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_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_usa18x_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19_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_usa19w_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qi_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_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_usa28_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_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_usa28xa_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_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_usa49w_product_id)},
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)},
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
...@@ -448,11 +485,13 @@ static struct usb_device_id keyspan_pre_ids[] = { ...@@ -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_usa19qi_pre_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qw_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_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_usa28_pre_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_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_usa28xa_pre_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_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_usa49w_pre_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_pre_product_id) },
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
...@@ -462,6 +501,7 @@ static struct usb_device_id keyspan_1port_ids[] = { ...@@ -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_usa19qi_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa19qw_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_usa19w_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_mpr_pre_product_id) },
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
...@@ -469,11 +509,13 @@ static struct usb_device_id keyspan_2port_ids[] = { ...@@ -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_usa28_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_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_usa28xa_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_product_id) },
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
static struct usb_device_id keyspan_4port_ids[] = { static struct usb_device_id keyspan_4port_ids[] = {
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id) }, { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)},
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
......
/* keyspan_mpr_fw.h
The firmware contained herein as keyspan_mpr_fw.h is
Copyright (C) 1999-2001
Keyspan, A division of InnoSys Incorporated ("Keyspan")
as an unpublished work. This notice does not imply unrestricted or
public access to the source code from which this firmware image is
derived. Except as noted below this firmware image may not be
reproduced, used, sold or transferred to any third party without
Keyspan's prior written consent. All Rights Reserved.
Permission is hereby granted for the distribution of this firmware
image as part of a Linux or other Open Source operating system kernel
in text or binary form as required.
This firmware may not be modified and may only be used with
Keyspan hardware. Distribution and/or Modification of the
keyspan.c driver which includes this firmware, in whole or in
part, requires the inclusion of this statement."
static char theFirmwareDate53[] =
"04/26/2002 02:47p 11,570 USA53";
*/
static const struct ezusb_hex_record keyspan_mpr_firmware[] = {
{0x0033, 3, { 0x02, 0x00, 0x1a}},
{0x001a, 4, { 0x53, 0xd8, 0xef, 0x32}},
{0x0003, 16, { 0x8e, 0x56, 0x8f, 0x57, 0xe5, 0x57, 0x15, 0x57, 0xae, 0x56, 0x70, 0x02, 0x15, 0x56, 0x4e, 0x60}},
{0x0013, 7, { 0x05, 0x12, 0x0f, 0xa2, 0x80, 0xee, 0x22}},
{0x0023, 3, { 0x02, 0x00, 0x46}},
{0x0046, 16, { 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xc0, 0xd0, 0x75, 0xd0, 0x08}},
{0x0056, 16, { 0x30, 0x99, 0x0e, 0x30, 0x0b, 0x07, 0xa2, 0x0e, 0x92, 0x9b, 0x85, 0x36, 0x99, 0xc2, 0x99, 0xd2}},
{0x0066, 16, { 0x12, 0x20, 0x12, 0x03, 0x02, 0x02, 0xf9, 0xc2, 0x12, 0x30, 0x03, 0x19, 0x7e, 0x7e, 0x7f, 0x40}},
{0x0076, 16, { 0x75, 0x1a, 0x7e, 0x75, 0x1b, 0x40, 0x75, 0x17, 0x00, 0x7e, 0x7d, 0x7f, 0xc0, 0x75, 0x18, 0x7d}},
{0x0086, 16, { 0x75, 0x19, 0xc0, 0x80, 0x17, 0x7e, 0x7d, 0x7f, 0xc0, 0x75, 0x1a, 0x7d, 0x75, 0x1b, 0xc0, 0x75}},
{0x0096, 16, { 0x17, 0x01, 0x7e, 0x7e, 0x7f, 0x40, 0x75, 0x18, 0x7e, 0x75, 0x19, 0x40, 0x20, 0x0b, 0x03, 0x02}},
{0x00a6, 16, { 0x01, 0x84, 0xe5, 0x3a, 0xc3, 0x95, 0x53, 0x50, 0x3c, 0x20, 0x0c, 0x34, 0x20, 0x09, 0x31, 0x90}},
{0x00b6, 16, { 0x7f, 0x9b, 0xe0, 0x55, 0x38, 0x70, 0x29, 0x30, 0x10, 0x12, 0xaf, 0x3a, 0x05, 0x3a, 0xe5, 0x1b}},
{0x00c6, 16, { 0x2f, 0xf5, 0x82, 0xe4, 0x35, 0x1a, 0xf5, 0x83, 0xe0, 0x13, 0x92, 0x0e, 0xaf, 0x3a, 0x05, 0x3a}},
{0x00d6, 16, { 0xe5, 0x1b, 0x2f, 0xf5, 0x82, 0xe4, 0x35, 0x1a, 0xf5, 0x83, 0xe0, 0xf5, 0x36, 0x02, 0x02, 0xf7}},
{0x00e6, 16, { 0xc2, 0x0b, 0x02, 0x02, 0xf7, 0x30, 0x03, 0x11, 0x90, 0x7f, 0xc7, 0xe4, 0xf0, 0xa3, 0xe0, 0x54}},
{0x00f6, 16, { 0x02, 0xf5, 0x1d, 0xa3, 0xe0, 0xf5, 0x1c, 0x80, 0x11, 0x90, 0x7f, 0xc9, 0xe4, 0xf0, 0x90, 0x7f}},
{0x0043, 3, { 0x02, 0x0f, 0x00}},
{0x0000, 3, { 0x02, 0x00, 0x26}},
{0x0026, 12, { 0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x5a, 0x02, 0x0a, 0x33}},
{0x0106, 64, { 0xc6, 0xe0, 0x54, 0x02, 0xf5, 0x1d, 0xa3, 0xe0, 0xf5, 0x1c, 0xe5, 0x17, 0x24, 0xff, 0x92, 0x03, 0x30,
0x0d, 0x0d, 0xc2, 0x0d, 0x90, 0x7f, 0xbb, 0x74, 0x01, 0xf0, 0xc2, 0x0b, 0x02, 0x02, 0xf7, 0xe5,
0x1d, 0x60, 0x05, 0xc2, 0x0b, 0x02, 0x02, 0xf7, 0x85, 0x1c, 0x53, 0x85, 0x19, 0x82, 0x85, 0x18,
0x83, 0xe0, 0x13, 0x92, 0x0d, 0x75, 0x12, 0xff, 0x20, 0x0c, 0x3a, 0x20, 0x09, 0x37, 0x90}},
{0x0146, 64, { 0x7f, 0x9b, 0xe0, 0x55, 0x38, 0x70, 0x2f, 0x30, 0x10, 0x1c, 0x85, 0x19, 0x82, 0x85, 0x18, 0x83, 0xa3,
0xe0, 0x13, 0x92, 0x0e, 0x85, 0x19, 0x82, 0x85, 0x18, 0x83, 0xa3, 0xa3, 0xe0, 0xf5, 0x36, 0x75,
0x3a, 0x03, 0x02, 0x02, 0xf7, 0x75, 0x3a, 0x02, 0x85, 0x19, 0x82, 0x85, 0x18, 0x83, 0xa3, 0xe0,
0xf5, 0x36, 0x02, 0x02, 0xf7, 0x75, 0x3a, 0x01, 0xc2, 0x0b, 0x02, 0x02, 0xf7, 0x30, 0x03}},
{0x0186, 64, { 0x0e, 0x90, 0x7f, 0xc6, 0xe0, 0x54, 0x02, 0xf5, 0x1d, 0xa3, 0xe0, 0xf5, 0x1c, 0x80, 0x0c, 0x90, 0x7f,
0xc8, 0xe0, 0x54, 0x02, 0xf5, 0x1d, 0xa3, 0xe0, 0xf5, 0x1c, 0xe5, 0x3a, 0xc3, 0x95, 0x53, 0x50,
0x03, 0x02, 0x02, 0x68, 0xe5, 0x1d, 0x60, 0x07, 0xc2, 0x14, 0xc2, 0x05, 0x02, 0x02, 0xf7, 0x85,
0x1c, 0x53, 0x85, 0x1b, 0x82, 0x85, 0x1a, 0x83, 0xe0, 0x13, 0x92, 0x0d, 0x75, 0x12, 0xff}},
{0x01c6, 64, { 0x30, 0x0c, 0x03, 0x02, 0x02, 0x60, 0x30, 0x09, 0x03, 0x02, 0x02, 0x60, 0x90, 0x7f, 0x9b, 0xe0, 0x55,
0x38, 0x60, 0x03, 0x02, 0x02, 0x60, 0x30, 0x10, 0x1b, 0x85, 0x1b, 0x82, 0x85, 0x1a, 0x83, 0xa3,
0xe0, 0x13, 0x92, 0x9b, 0x85, 0x1b, 0x82, 0x85, 0x1a, 0x83, 0xa3, 0xa3, 0xe0, 0xf5, 0x99, 0x75,
0x3a, 0x03, 0x80, 0x0d, 0x85, 0x1b, 0x82, 0x85, 0x1a, 0x83, 0xa3, 0xe0, 0xf5, 0x99, 0x75}},
{0x0206, 64, { 0x3a, 0x02, 0xe5, 0x3a, 0xc3, 0x95, 0x53, 0x40, 0x26, 0x30, 0x03, 0x07, 0x90, 0x7f, 0xc7, 0xe4, 0xf0,
0x80, 0x05, 0x90, 0x7f, 0xc9, 0xe4, 0xf0, 0xe5, 0x17, 0x24, 0xff, 0x92, 0x03, 0x20, 0x0d, 0x03,
0x02, 0x02, 0xf7, 0xc2, 0x0d, 0x90, 0x7f, 0xbb, 0x74, 0x01, 0xf0, 0x02, 0x02, 0xf7, 0x30, 0x10,
0x12, 0xaf, 0x3a, 0x05, 0x3a, 0xe5, 0x1b, 0x2f, 0xf5, 0x82, 0xe4, 0x35, 0x1a, 0xf5, 0x83}},
{0x0246, 64, { 0xe0, 0x13, 0x92, 0x0e, 0xaf, 0x3a, 0x05, 0x3a, 0xe5, 0x1b, 0x2f, 0xf5, 0x82, 0xe4, 0x35, 0x1a, 0xf5,
0x83, 0xe0, 0xf5, 0x36, 0xd2, 0x0b, 0x02, 0x02, 0xf7, 0x75, 0x3a, 0x01, 0xc2, 0x14, 0x02, 0x02,
0xf7, 0x30, 0x0c, 0x03, 0x02, 0x02, 0xf5, 0x30, 0x09, 0x03, 0x02, 0x02, 0xf5, 0x90, 0x7f, 0x9b,
0xe0, 0x55, 0x38, 0x70, 0x79, 0x30, 0x10, 0x12, 0xaf, 0x3a, 0x05, 0x3a, 0xe5, 0x1b, 0x2f}},
{0x0286, 64, { 0xf5, 0x82, 0xe4, 0x35, 0x1a, 0xf5, 0x83, 0xe0, 0x13, 0x92, 0x9b, 0xaf, 0x3a, 0x05, 0x3a, 0xe5, 0x1b,
0x2f, 0xf5, 0x82, 0xe4, 0x35, 0x1a, 0xf5, 0x83, 0xe0, 0xf5, 0x99, 0xe5, 0x3a, 0xc3, 0x95, 0x53,
0x40, 0x22, 0x30, 0x03, 0x07, 0x90, 0x7f, 0xc7, 0xe4, 0xf0, 0x80, 0x05, 0x90, 0x7f, 0xc9, 0xe4,
0xf0, 0xe5, 0x17, 0x24, 0xff, 0x92, 0x03, 0x30, 0x0d, 0x36, 0xc2, 0x0d, 0x90, 0x7f, 0xbb}},
{0x02c6, 64, { 0x74, 0x01, 0xf0, 0x80, 0x2c, 0x30, 0x10, 0x12, 0xaf, 0x3a, 0x05, 0x3a, 0xe5, 0x1b, 0x2f, 0xf5, 0x82,
0xe4, 0x35, 0x1a, 0xf5, 0x83, 0xe0, 0x13, 0x92, 0x0e, 0xaf, 0x3a, 0x05, 0x3a, 0xe5, 0x1b, 0x2f,
0xf5, 0x82, 0xe4, 0x35, 0x1a, 0xf5, 0x83, 0xe0, 0xf5, 0x36, 0xd2, 0x0b, 0x80, 0x02, 0xc2, 0x14,
0xd2, 0x01, 0x20, 0x98, 0x03, 0x02, 0x04, 0x35, 0xc2, 0x98, 0x20, 0x02, 0x03, 0x02, 0x03}},
{0x0306, 64, { 0xa2, 0x20, 0x15, 0x27, 0xaf, 0x39, 0x05, 0x39, 0x74, 0x80, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5,
0x83, 0xe5, 0x99, 0xf0, 0x30, 0x10, 0x4d, 0xaf, 0x39, 0x05, 0x39, 0x74, 0x80, 0x2f, 0xf5, 0x82,
0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe5, 0x98, 0xf0, 0x80, 0x3a, 0x85, 0x99, 0x55, 0xe5, 0x55, 0xb5,
0x47, 0x04, 0xd2, 0x09, 0x80, 0x2e, 0xe5, 0x55, 0xb5, 0x46, 0x04, 0xc2, 0x09, 0x80, 0x25}},
{0x0346, 64, { 0xaf, 0x39, 0x05, 0x39, 0x74, 0x80, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe5, 0x55, 0xf0,
0x30, 0x10, 0x11, 0xaf, 0x39, 0x05, 0x39, 0x74, 0x80, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5,
0x83, 0xe5, 0x98, 0xf0, 0xd2, 0x0f, 0xe5, 0x39, 0xc3, 0x95, 0x43, 0x50, 0x03, 0x02, 0x04, 0x33,
0x90, 0x7f, 0xb8, 0xe0, 0x30, 0xe1, 0x16, 0xe5, 0x39, 0xc3, 0x94, 0x40, 0x50, 0x03, 0x02}},
{0x0386, 64, { 0x04, 0x33, 0x15, 0x39, 0x15, 0x39, 0x05, 0x2b, 0x43, 0x34, 0x01, 0x02, 0x04, 0x33, 0x90, 0x7f, 0xb7,
0xe5, 0x39, 0xf0, 0x75, 0x39, 0x00, 0xc2, 0x02, 0x02, 0x04, 0x33, 0x20, 0x15, 0x27, 0xaf, 0x39,
0x05, 0x39, 0x74, 0x00, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe5, 0x99, 0xf0, 0x30,
0x10, 0x4d, 0xaf, 0x39, 0x05, 0x39, 0x74, 0x00, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5}},
{0x03c6, 64, { 0x83, 0xe5, 0x98, 0xf0, 0x80, 0x3a, 0x85, 0x99, 0x55, 0xe5, 0x55, 0xb5, 0x47, 0x04, 0xd2, 0x09, 0x80,
0x2e, 0xe5, 0x55, 0xb5, 0x46, 0x04, 0xc2, 0x09, 0x80, 0x25, 0xaf, 0x39, 0x05, 0x39, 0x74, 0x00,
0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe5, 0x55, 0xf0, 0x30, 0x10, 0x11, 0xaf, 0x39,
0x05, 0x39, 0x74, 0x00, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe5, 0x98, 0xf0}},
{0x0406, 64, { 0xd2, 0x0f, 0xe5, 0x39, 0xc3, 0x95, 0x43, 0x40, 0x24, 0x90, 0x7f, 0xb6, 0xe0, 0x30, 0xe1, 0x12, 0xe5,
0x39, 0xc3, 0x94, 0x40, 0x40, 0x16, 0x15, 0x39, 0x15, 0x39, 0x05, 0x2b, 0x43, 0x34, 0x01, 0x80,
0x0b, 0x90, 0x7f, 0xb9, 0xe5, 0x39, 0xf0, 0x75, 0x39, 0x00, 0xd2, 0x02, 0xd2, 0x01, 0x30, 0x01,
0x05, 0xc2, 0x01, 0x02, 0x00, 0x56, 0xd0, 0xd0, 0xd0, 0x86, 0xd0, 0x82, 0xd0, 0x83, 0xd0}},
{0x0446, 64, { 0xe0, 0x32, 0x90, 0x7f, 0xbc, 0xe0, 0x20, 0xe1, 0x54, 0xe5, 0x34, 0x60, 0x50, 0xe5, 0x31, 0x70, 0x4c,
0xe5, 0x34, 0x30, 0xe1, 0x0b, 0xe4, 0xf5, 0x2f, 0x75, 0x34, 0x01, 0x75, 0x31, 0x02, 0x80, 0x0e,
0xa2, 0x08, 0xe4, 0x33, 0xf5, 0x2f, 0xc2, 0x08, 0xe4, 0xf5, 0x34, 0x75, 0x31, 0x10, 0xe4, 0xf5,
0x56, 0x7e, 0x00, 0x7b, 0x00, 0x74, 0x24, 0x25, 0x56, 0xf9, 0xee, 0x34, 0x00, 0xfa, 0x12}},
{0x0486, 64, { 0x0c, 0x79, 0xff, 0x74, 0x00, 0x25, 0x56, 0xf5, 0x82, 0xe4, 0x34, 0x7d, 0xf5, 0x83, 0xef, 0xf0, 0x05,
0x56, 0xe5, 0x56, 0xb4, 0x0c, 0xdb, 0x90, 0x7f, 0xbd, 0x74, 0x0c, 0xf0, 0x90, 0x7f, 0xca, 0xe0,
0x30, 0xe1, 0x03, 0x02, 0x05, 0xd1, 0xe4, 0xf5, 0x56, 0x74, 0x40, 0x25, 0x56, 0xf5, 0x82, 0xe4,
0x34, 0x7d, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x56, 0x7c, 0x00, 0x7b, 0x00, 0x24, 0x3b, 0xf9}},
{0x04c6, 64, { 0xec, 0x34, 0x00, 0xfa, 0xef, 0x12, 0x0c, 0x92, 0x05, 0x56, 0xe5, 0x56, 0xb4, 0x18, 0xdb, 0xe5, 0x3b,
0x60, 0x11, 0x75, 0xc9, 0x20, 0x75, 0xc8, 0x36, 0x85, 0x3c, 0xca, 0x85, 0x3d, 0xcb, 0xe4, 0x90,
0x7f, 0x9f, 0xf0, 0xe5, 0x3e, 0x13, 0x92, 0x10, 0x92, 0x9f, 0x85, 0x3f, 0x38, 0xe5, 0x40, 0x13,
0x92, 0x15, 0xe5, 0x41, 0x60, 0x09, 0x90, 0x7f, 0x98, 0xe0, 0x54, 0xfb, 0xf0, 0x80, 0x07}},
{0x0506, 64, { 0x90, 0x7f, 0x98, 0xe0, 0x44, 0x04, 0xf0, 0xe5, 0x42, 0x60, 0x09, 0x90, 0x7f, 0x98, 0xe0, 0x54, 0x7f,
0xf0, 0x80, 0x07, 0x90, 0x7f, 0x98, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x48, 0x60, 0x0b, 0xc2, 0x0c,
0xc2, 0x09, 0x90, 0x7f, 0x95, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x49, 0x60, 0x0c, 0xd2, 0x09, 0x43,
0x34, 0x01, 0x90, 0x7f, 0x95, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x4a, 0x60, 0x0d, 0xc2, 0xaf}},
{0x0546, 64, { 0xc2, 0x0b, 0xd2, 0x00, 0xe4, 0xf5, 0x53, 0xf5, 0x3a, 0xd2, 0xaf, 0xe5, 0x4b, 0x60, 0x05, 0x30, 0x15,
0x02, 0xd2, 0x09, 0xe5, 0x4c, 0x60, 0x15, 0x90, 0x7f, 0x95, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0x7f,
0x9e, 0xe0, 0x44, 0x02, 0xf0, 0x90, 0x7f, 0x98, 0xe0, 0x54, 0xfd, 0xf0, 0xe5, 0x4d, 0x60, 0x0a,
0xd2, 0x9c, 0xc2, 0x98, 0x75, 0x2c, 0x01, 0x75, 0x31, 0x1e, 0xe5, 0x4e, 0x60, 0x07, 0xc2}},
{0x0586, 64, { 0x9c, 0xe4, 0xf5, 0x39, 0xf5, 0x2c, 0xe5, 0x4f, 0x60, 0x03, 0xe4, 0xf5, 0x39, 0xe5, 0x50, 0x60, 0x02,
0xd2, 0x07, 0xe5, 0x51, 0x60, 0x0a, 0xe5, 0x4d, 0x70, 0x02, 0xf5, 0x31, 0xe5, 0x51, 0x42, 0x34,
0xe5, 0x52, 0x60, 0x1f, 0x90, 0x7f, 0xd7, 0x74, 0x11, 0xf0, 0x74, 0x31, 0xf0, 0x74, 0x12, 0xf0,
0x74, 0x32, 0xf0, 0x74, 0x13, 0xf0, 0x74, 0x33, 0xf0, 0x74, 0x14, 0xf0, 0x74, 0x34, 0xf0}},
{0x05c6, 64, { 0xd2, 0x03, 0xd2, 0x02, 0xd2, 0x08, 0xe4, 0x90, 0x7f, 0xcb, 0xf0, 0xa2, 0x0c, 0xe4, 0x33, 0xff, 0x65,
0x29, 0x60, 0x05, 0x8f, 0x29, 0x43, 0x34, 0x01, 0xa2, 0x09, 0xe4, 0x33, 0xff, 0x65, 0x2a, 0x60,
0x05, 0x8f, 0x2a, 0x43, 0x34, 0x01, 0x90, 0x7f, 0x9b, 0xe0, 0xff, 0x54, 0x08, 0x64, 0x08, 0xf5,
0x57, 0x65, 0x25, 0x60, 0x06, 0x85, 0x57, 0x25, 0x43, 0x34, 0x01, 0xef, 0x54, 0x10, 0x64}},
{0x0606, 64, { 0x10, 0xf5, 0x57, 0x65, 0x26, 0x60, 0x06, 0x85, 0x57, 0x26, 0x43, 0x34, 0x01, 0xef, 0x54, 0x40, 0x64,
0x40, 0xf5, 0x57, 0x65, 0x27, 0x60, 0x06, 0x85, 0x57, 0x27, 0x43, 0x34, 0x01, 0xef, 0x54, 0x20,
0x64, 0x20, 0xf5, 0x57, 0x65, 0x28, 0x60, 0x06, 0x85, 0x57, 0x28, 0x43, 0x34, 0x01, 0x90, 0x7f,
0x9a, 0xe0, 0x54, 0x40, 0x64, 0x40, 0xf5, 0x57, 0x65, 0x2e, 0x60, 0x06, 0x85, 0x57, 0x2e}},
{0x0646, 64, { 0x43, 0x34, 0x01, 0x30, 0x07, 0x35, 0xc2, 0xaf, 0x30, 0x02, 0x18, 0x90, 0x7f, 0xb8, 0xe0, 0x20, 0xe1,
0x27, 0xe5, 0x39, 0x60, 0x09, 0x90, 0x7f, 0xb7, 0xf0, 0xe4, 0xf5, 0x39, 0xc2, 0x02, 0xc2, 0x07,
0x80, 0x16, 0x90, 0x7f, 0xb6, 0xe0, 0x20, 0xe1, 0x0f, 0xe5, 0x39, 0x60, 0x09, 0x90, 0x7f, 0xb9,
0xf0, 0xe4, 0xf5, 0x39, 0xd2, 0x02, 0xc2, 0x07, 0xd2, 0xaf, 0x20, 0x05, 0x3d, 0x30, 0x03}},
{0x0686, 64, { 0x1e, 0x90, 0x7f, 0xc6, 0xe0, 0x20, 0xe1, 0x33, 0x90, 0x7e, 0x40, 0xe0, 0x13, 0x92, 0x0d, 0x75, 0x3a,
0x01, 0x90, 0x7f, 0xc7, 0xe0, 0xf5, 0x53, 0xd2, 0x05, 0x75, 0x12, 0xff, 0x80, 0x1c, 0x90, 0x7f,
0xc8, 0xe0, 0x20, 0xe1, 0x15, 0x90, 0x7d, 0xc0, 0xe0, 0x13, 0x92, 0x0d, 0x75, 0x3a, 0x01, 0x90,
0x7f, 0xc9, 0xe0, 0xf5, 0x53, 0xd2, 0x05, 0x75, 0x12, 0xff, 0x20, 0x14, 0x33, 0x20, 0x00}},
{0x06c6, 64, { 0x06, 0xe5, 0x3a, 0x65, 0x53, 0x70, 0x2a, 0x30, 0x05, 0x1a, 0x30, 0x03, 0x09, 0xe4, 0x90, 0x7f, 0xc7,
0xf0, 0xc2, 0x03, 0x80, 0x07, 0xe4, 0x90, 0x7f, 0xc9, 0xf0, 0xd2, 0x03, 0xc2, 0x05, 0xe4, 0xf5,
0x53, 0xf5, 0x3a, 0x30, 0x0d, 0x0a, 0xc2, 0x0d, 0xc2, 0x00, 0x90, 0x7f, 0xbb, 0x74, 0x01, 0xf0,
0x30, 0x14, 0x03, 0x02, 0x07, 0xbf, 0x20, 0x05, 0x03, 0x02, 0x07, 0xbf, 0x30, 0x0c, 0x03}},
{0x0706, 64, { 0x02, 0x07, 0xbf, 0x30, 0x09, 0x03, 0x02, 0x07, 0xbf, 0x90, 0x7f, 0x9b, 0xe0, 0x55, 0x38, 0x60, 0x03,
0x02, 0x07, 0xbf, 0x30, 0x03, 0x0c, 0x7e, 0x7e, 0x7f, 0x40, 0x75, 0x58, 0x7e, 0x75, 0x59, 0x40,
0x80, 0x0a, 0x7e, 0x7d, 0x7f, 0xc0, 0x75, 0x58, 0x7d, 0x75, 0x59, 0xc0, 0x30, 0x10, 0x12, 0xaf,
0x3a, 0x05, 0x3a, 0xe5, 0x59, 0x2f, 0xf5, 0x82, 0xe4, 0x35, 0x58, 0xf5, 0x83, 0xe0, 0x13}},
{0x0746, 64, { 0x92, 0x1a, 0xaf, 0x3a, 0x05, 0x3a, 0xe5, 0x59, 0x2f, 0xf5, 0x82, 0xe4, 0x35, 0x58, 0xf5, 0x83, 0xe0,
0xf5, 0x57, 0xe5, 0x3a, 0xc3, 0x95, 0x53, 0x50, 0x2a, 0x30, 0x10, 0x12, 0xaf, 0x3a, 0x05, 0x3a,
0xe5, 0x59, 0x2f, 0xf5, 0x82, 0xe4, 0x35, 0x58, 0xf5, 0x83, 0xe0, 0x13, 0x92, 0x0e, 0xaf, 0x3a,
0x05, 0x3a, 0xe5, 0x59, 0x2f, 0xf5, 0x82, 0xe4, 0x35, 0x58, 0xf5, 0x83, 0xe0, 0xf5, 0x36}},
{0x0786, 64, { 0xd2, 0x0b, 0x80, 0x15, 0xc2, 0x0b, 0x30, 0x03, 0x09, 0xe4, 0x90, 0x7f, 0xc7, 0xf0, 0xc2, 0x03, 0x80,
0x07, 0xe4, 0x90, 0x7f, 0xc9, 0xf0, 0xd2, 0x03, 0x30, 0x10, 0x04, 0xa2, 0x1a, 0x92, 0x9b, 0xd2,
0x14, 0xc2, 0xaf, 0x85, 0x57, 0x99, 0x20, 0x0b, 0x0d, 0x30, 0x0d, 0x0a, 0xc2, 0x0d, 0xc2, 0x00,
0x90, 0x7f, 0xbb, 0x74, 0x01, 0xf0, 0xd2, 0xaf, 0x22, 0x90, 0x7f, 0xe9, 0xe0, 0x12, 0x0c}},
{0x07c6, 64, { 0xa4, 0x09, 0x1c, 0x00, 0x09, 0x89, 0x01, 0x09, 0xe6, 0x03, 0x07, 0xe3, 0x06, 0x09, 0x0d, 0x08, 0x09,
0x01, 0x09, 0x08, 0xe9, 0x0a, 0x08, 0xf8, 0x0b, 0x00, 0x00, 0x0a, 0x24, 0x90, 0x7f, 0xeb, 0xe0,
0x24, 0xfe, 0x60, 0x1c, 0x14, 0x70, 0x03, 0x02, 0x08, 0x79, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0a,
0x24, 0x74, 0x0d, 0x90, 0x7f, 0xd4, 0xf0, 0x74, 0x87, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x0a}},
{0x0806, 64, { 0x2b, 0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x04, 0x7f, 0x02, 0x80, 0x02, 0x7f, 0x03, 0x75, 0x82, 0xd8,
0x75, 0x83, 0x0d, 0xef, 0xf0, 0x75, 0x82, 0xd1, 0x75, 0x83, 0x0d, 0xf0, 0x75, 0x82, 0xca, 0x75,
0x83, 0x0d, 0xf0, 0x75, 0x82, 0xc3, 0x75, 0x83, 0x0d, 0xf0, 0x90, 0x7f, 0xea, 0xe0, 0x04, 0x75,
0x82, 0x9e, 0x75, 0x83, 0x0d, 0xf0, 0x90, 0x7f, 0xef, 0xe0, 0xfe, 0x90, 0x7f, 0xee, 0xe0}},
{0x0846, 64, { 0x7c, 0x00, 0x24, 0x00, 0xf5, 0x5a, 0xec, 0x3e, 0xf5, 0x59, 0x75, 0x15, 0x0d, 0x75, 0x16, 0x99, 0x75,
0x82, 0x9b, 0x75, 0x83, 0x0d, 0xe0, 0x75, 0x13, 0x00, 0xf5, 0x14, 0xd3, 0xe5, 0x14, 0x95, 0x5a,
0xe5, 0x13, 0x95, 0x59, 0x40, 0x06, 0x85, 0x59, 0x13, 0x85, 0x5a, 0x14, 0x12, 0x0b, 0xba, 0x02,
0x0a, 0x2b, 0x90, 0x7f, 0xea, 0xe0, 0x70, 0x0b, 0x75, 0x56, 0xff, 0x75, 0x57, 0x0d, 0x75}},
{0x0886, 64, { 0x58, 0xdc, 0x80, 0x2d, 0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x0b, 0x75, 0x56, 0xff, 0x75, 0x57, 0x0d,
0x75, 0x58, 0xe0, 0x80, 0x1b, 0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x02, 0x0b, 0x75, 0x56, 0xff, 0x75,
0x57, 0x0d, 0x75, 0x58, 0xf0, 0x80, 0x09, 0x75, 0x56, 0xff, 0x75, 0x57, 0x0e, 0x75, 0x58, 0x1e,
0x90, 0x7f, 0xee, 0xe0, 0x75, 0x59, 0x00, 0xf5, 0x5a, 0xae, 0x57, 0xaf, 0x58, 0x8e, 0x15}},
{0x08c6, 64, { 0x8f, 0x16, 0x8f, 0x82, 0x8e, 0x83, 0xe0, 0xfe, 0xa3, 0xe0, 0x8e, 0x13, 0xf5, 0x14, 0xd3, 0x95, 0x5a,
0xe5, 0x13, 0x95, 0x59, 0x40, 0x06, 0x85, 0x59, 0x13, 0x85, 0x5a, 0x14, 0x12, 0x0b, 0xba, 0x02,
0x0a, 0x2b, 0x90, 0x7f, 0x00, 0xe5, 0x11, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x02, 0x0a,
0x2b, 0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x11, 0x02, 0x0a, 0x2b, 0x12, 0x0c, 0x24, 0x90, 0x7f}},
{0x0906, 64, { 0xea, 0xe0, 0xf5, 0x10, 0x02, 0x0a, 0x2b, 0x90, 0x7f, 0x00, 0xe5, 0x10, 0xf0, 0x90, 0x7f, 0xb5, 0x74,
0x01, 0xf0, 0x02, 0x0a, 0x2b, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0x7f, 0x60, 0x27, 0x14, 0x60, 0x34,
0x24, 0x02, 0x60, 0x03, 0x02, 0x0a, 0x24, 0xa2, 0x16, 0xe4, 0x33, 0xff, 0x25, 0xe0, 0xff, 0xa2,
0x18, 0xe4, 0x33, 0x4f, 0x90, 0x7f, 0x00, 0xf0, 0xe4, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74}},
{0x0946, 64, { 0x02, 0xf0, 0x02, 0x0a, 0x2b, 0xe4, 0x90, 0x7f, 0x00, 0xf0, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02,
0xf0, 0x02, 0x0a, 0x2b, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff,
0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe0,
0x54, 0xfd, 0x90, 0x7f, 0x00, 0xf0, 0xe4, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0}},
{0x0986, 64, { 0x02, 0x0a, 0x2b, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0xfe, 0x60, 0x17, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0a,
0x2b, 0x90, 0x7f, 0xea, 0xe0, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0a, 0x24, 0xc2, 0x16, 0x02, 0x0a,
0x2b, 0x90, 0x7f, 0xea, 0xe0, 0x70, 0x76, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4,
0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34}},
{0x09c6, 64, { 0x7f, 0xf5, 0x83, 0xe4, 0xf0, 0x90, 0x7f, 0xec, 0xe0, 0x54, 0x80, 0xff, 0x13, 0x13, 0x13, 0x54, 0x1f,
0xff, 0xe0, 0x54, 0x07, 0x2f, 0x90, 0x7f, 0xd7, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x45, 0x90,
0x7f, 0xe8, 0xe0, 0x24, 0xfe, 0x60, 0x10, 0x24, 0x02, 0x70, 0x39, 0x90, 0x7f, 0xea, 0xe0, 0x64,
0x01, 0x70, 0x2a, 0xd2, 0x16, 0x80, 0x2d, 0x90, 0x7f, 0xea, 0xe0, 0x70, 0x20, 0x90, 0x7f}},
{0x0a06, 64, { 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24,
0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0x74, 0x01, 0xf0, 0x80, 0x07, 0x90, 0x7f, 0xb4,
0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x22, 0xc2, 0x10, 0xe4, 0xf5,
0x10, 0xf5, 0x34, 0xc2, 0x09, 0xc2, 0x0c, 0xc2, 0x0b, 0xc2, 0x14, 0xc2, 0x0d, 0xc2, 0x15}},
{0x0a46, 64, { 0xc2, 0x11, 0xc2, 0x07, 0xc2, 0x12, 0xc2, 0x0f, 0xc2, 0x08, 0xf5, 0x35, 0xf5, 0x39, 0xf5, 0x53, 0xf5,
0x3a, 0xf5, 0x33, 0xf5, 0x30, 0xf5, 0x2f, 0xf5, 0x2e, 0xf5, 0x2d, 0xf5, 0x2c, 0xf5, 0x2b, 0xf5,
0x2a, 0xf5, 0x29, 0xf5, 0x28, 0xf5, 0x27, 0xf5, 0x26, 0xf5, 0x25, 0xf5, 0x24, 0xc2, 0x05, 0xc2,
0x17, 0xc2, 0x19, 0xc2, 0x16, 0xc2, 0x18, 0xc2, 0x04, 0xd2, 0x13, 0xc2, 0x06, 0xc2, 0x01}},
{0x0a86, 64, { 0x90, 0x7f, 0x92, 0xe0, 0x54, 0xfd, 0xf0, 0xd2, 0xe8, 0x43, 0xd8, 0x20, 0x90, 0x7f, 0xde, 0x74, 0x01,
0xf0, 0x90, 0x7f, 0xdf, 0xf0, 0x90, 0x7f, 0xab, 0x74, 0xff, 0xf0, 0x90, 0x7f, 0xa9, 0xf0, 0x90,
0x7f, 0xaa, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xaf, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xae,
0xe0, 0x44, 0x0f, 0xf0, 0x90, 0x7f, 0xac, 0x74, 0x0e, 0xf0, 0xd2, 0xaf, 0xd2, 0xbc, 0xd2}},
{0x0ac6, 64, { 0x1a, 0x12, 0x0f, 0x7d, 0xc2, 0x17, 0x30, 0x04, 0x03, 0x12, 0x04, 0x48, 0x30, 0x04, 0x2a, 0x30, 0x06,
0x27, 0xc2, 0x06, 0xe5, 0x12, 0x60, 0x16, 0x15, 0x12, 0x90, 0x7f, 0xd8, 0xe0, 0x30, 0xe6, 0x04,
0x7f, 0x00, 0x80, 0x02, 0x7f, 0x20, 0x90, 0x7f, 0x96, 0xef, 0xf0, 0x80, 0x06, 0x90, 0x7f, 0x96,
0x74, 0x20, 0xf0, 0x12, 0x0b, 0x14, 0x80, 0xcd, 0x30, 0x17, 0x07, 0xc2, 0x17, 0x12, 0x07}},
{0x0b06, 64, { 0xc0, 0x80, 0xc3, 0x30, 0x19, 0xc0, 0xc2, 0x19, 0x12, 0x0e, 0xdc, 0x80, 0xb9, 0x22, 0xe5, 0x31, 0x60,
0x02, 0x15, 0x31, 0xe5, 0x39, 0x60, 0x55, 0x65, 0x35, 0x70, 0x4b, 0xe5, 0x33, 0xf4, 0x60, 0x02,
0x05, 0x33, 0xe5, 0x33, 0xc3, 0x95, 0x44, 0x40, 0x43, 0xc2, 0xaf, 0x30, 0x02, 0x1b, 0x90, 0x7f,
0xb8, 0xe0, 0x20, 0xe1, 0x2d, 0x90, 0x7f, 0xb7, 0xe5, 0x39, 0xf0, 0xc2, 0x02, 0xe4, 0xf5}},
{0x0b46, 64, { 0x39, 0xf5, 0x33, 0xf5, 0x35, 0x75, 0x12, 0xff, 0x80, 0x19, 0x90, 0x7f, 0xb6, 0xe0, 0x20, 0xe1, 0x12,
0x90, 0x7f, 0xb9, 0xe5, 0x39, 0xf0, 0xd2, 0x02, 0xe4, 0xf5, 0x39, 0xf5, 0x33, 0xf5, 0x35, 0x75,
0x12, 0xff, 0xd2, 0xaf, 0x80, 0x06, 0x85, 0x39, 0x35, 0xe4, 0xf5, 0x33, 0xe5, 0x2c, 0x60, 0x30,
0x20, 0x0f, 0x07, 0x90, 0x7f, 0x9b, 0xe0, 0x30, 0xe0, 0x0f, 0xe5, 0x2d, 0x60, 0x06, 0xe4}},
{0x0b86, 64, { 0xf5, 0x2d, 0x43, 0x34, 0x01, 0xe4, 0xf5, 0x30, 0x80, 0x14, 0xe5, 0x30, 0xd3, 0x95, 0x45, 0x50, 0x0d,
0xe5, 0x30, 0xb5, 0x45, 0x06, 0x75, 0x2d, 0x01, 0x43, 0x34, 0x01, 0x05, 0x30, 0xc2, 0x0f, 0x22,
0x90, 0x7f, 0xd9, 0xe0, 0x30, 0xe2, 0x04, 0x7f, 0x00, 0x80, 0x02, 0x7f, 0x20, 0x90, 0x7f, 0x96,
0xef, 0xf0, 0x22, 0xe5, 0x14, 0x45, 0x13, 0x60, 0x57, 0xae, 0x13, 0xaf, 0x14, 0xd3, 0xef}},
{0x0bc6, 64, { 0x94, 0x40, 0xee, 0x94, 0x00, 0x40, 0x04, 0x7e, 0x00, 0x7f, 0x40, 0xc3, 0xe5, 0x14, 0x9f, 0xf5, 0x14,
0xe5, 0x13, 0x9e, 0xf5, 0x13, 0xe4, 0xfd, 0xed, 0xc3, 0x9f, 0xe4, 0x9e, 0x50, 0x1f, 0x85, 0x16,
0x82, 0x85, 0x15, 0x83, 0xe0, 0xfc, 0x74, 0x00, 0x2d, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83,
0xec, 0xf0, 0x0d, 0x05, 0x16, 0xe5, 0x16, 0x70, 0x02, 0x05, 0x15, 0x80, 0xda, 0x90, 0x7f}},
{0x0c06, 64, { 0xa9, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xac, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xb5, 0xef, 0xf0, 0x22,
0x90, 0x7f, 0xac, 0xe0, 0x54, 0xfe, 0xf0, 0xe4, 0x90, 0x7f, 0xb5, 0xf0, 0x22, 0xe4, 0x90, 0x7f,
0x93, 0xf0, 0x90, 0x7f, 0x9c, 0x74, 0x30, 0xf0, 0x90, 0x7f, 0x96, 0x74, 0x20, 0xf0, 0x90, 0x7f,
0x94, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0x9d, 0x74, 0xff, 0xf0, 0x90, 0x7f, 0x97, 0x74, 0x86}},
{0x0c46, 64, { 0xf0, 0x90, 0x7f, 0x95, 0x74, 0x03, 0xf0, 0x90, 0x7f, 0x9e, 0x74, 0x84, 0xf0, 0x90, 0x7f, 0x98, 0xf0,
0xe4, 0x90, 0x7f, 0xc7, 0xf0, 0x90, 0x7f, 0xc9, 0xf0, 0x90, 0x7f, 0xcb, 0xf0, 0x75, 0x98, 0x40,
0x43, 0xa8, 0x10, 0x90, 0x7f, 0xde, 0x74, 0x1f, 0xf0, 0x90, 0x7f, 0xdf, 0x74, 0x0f, 0xf0, 0xd2,
0x04, 0x22, 0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22}},
{0x0c86, 64, { 0xbb, 0xfe, 0x02, 0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22, 0xbb, 0x01, 0x06, 0x89, 0x82,
0x8a, 0x83, 0xf0, 0x22, 0x50, 0x02, 0xf7, 0x22, 0xbb, 0xfe, 0x01, 0xf3, 0x22, 0xd0, 0x83, 0xd0,
0x82, 0xf8, 0xe4, 0x93, 0x70, 0x12, 0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, 0xa3, 0x93, 0xf8, 0x74,
0x01, 0x93, 0xf5, 0x82, 0x88, 0x83, 0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60, 0xef, 0xa3}},
{0x0cc6, 64, { 0xa3, 0xa3, 0x80, 0xdf, 0xe4, 0x90, 0x7f, 0x95, 0xf0, 0x90, 0x7f, 0x94, 0xf0, 0x90, 0x7f, 0x93, 0xf0,
0x90, 0x7f, 0x9d, 0xe0, 0x44, 0x02, 0xf0, 0x90, 0x7f, 0x97, 0xe0, 0x44, 0x42, 0xf0, 0x90, 0x7f,
0x9c, 0x74, 0x10, 0xf0, 0xe4, 0x90, 0x7f, 0x96, 0xf0, 0x90, 0x7f, 0x9d, 0x74, 0xbe, 0xf0, 0x30,
0x16, 0x04, 0x7f, 0x80, 0x80, 0x02, 0x7f, 0x00, 0x90, 0x7f, 0x97, 0xef, 0xf0, 0xe4, 0x90}},
{0x0d06, 64, { 0x7f, 0x95, 0xf0, 0x90, 0x7f, 0x9e, 0xf0, 0x90, 0x7f, 0x98, 0xf0, 0x22, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0,
0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xc0, 0xd0, 0x75, 0xd0,
0x08, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xa9, 0x74, 0x01, 0xf0, 0x12, 0x0b, 0xba, 0xd0, 0xd0, 0xd0,
0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0xc0}},
{0x0d46, 64, { 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x90, 0x7f, 0xc4,
0xe4, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x04, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0,
0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
{0x0d86, 64, { 0x00, 0x12, 0x01, 0x10, 0x01, 0xff, 0xff, 0xff, 0x40, 0xcd, 0x06, 0x1c, 0x01, 0x01, 0x00, 0x01, 0x02,
0x00, 0x02, 0x09, 0x02, 0x43, 0x00, 0x01, 0x01, 0x00, 0x80, 0x32, 0x09, 0x04, 0x00, 0x00, 0x07,
0xff, 0x00, 0x00, 0x00, 0x07, 0x05, 0x01, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x02, 0x02, 0x40,
0x00, 0x00, 0x07, 0x05, 0x03, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x81, 0x02, 0x40, 0x00}},
{0x0dc6, 64, { 0x01, 0x07, 0x05, 0x82, 0x02, 0x40, 0x00, 0x01, 0x07, 0x05, 0x83, 0x02, 0x40, 0x00, 0x01, 0x07, 0x05,
0x84, 0x02, 0x40, 0x00, 0x01, 0x04, 0x03, 0x09, 0x04, 0x10, 0x03, 0x4b, 0x00, 0x65, 0x00, 0x79,
0x00, 0x73, 0x00, 0x70, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x2e, 0x03, 0x4b, 0x00, 0x65, 0x00, 0x79,
0x00, 0x73, 0x00, 0x70, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x55, 0x00, 0x50, 0x00}},
{0x0e06, 64, { 0x53, 0x00, 0x48, 0x00, 0x31, 0x00, 0x31, 0x00, 0x32, 0x00, 0x2d, 0x00, 0x53, 0x00, 0x65, 0x00, 0x72,
0x00, 0x69, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x22, 0x03, 0x55, 0x00, 0x53, 0x00, 0x41, 0x00, 0x2d,
0x00, 0x35, 0x00, 0x33, 0x00, 0x20, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x32, 0x00, 0x61,
0x00, 0x70, 0x00, 0x72, 0x00, 0x32, 0x00, 0x36, 0x00, 0x00, 0x00, 0xc0, 0xe0, 0xc0, 0x83}},
{0x0e46, 64, { 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab,
0x74, 0x02, 0xf0, 0xd2, 0x06, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0,
0xe0, 0x32, 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86,
0x00, 0xd2, 0x17, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x01, 0xf0, 0xd0, 0x86, 0xd0}},
{0x0e86, 64, { 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32, 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0,
0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xd2, 0x19, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab,
0x74, 0x08, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32,
0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00}},
{0x0ec6, 64, { 0x53, 0x91, 0xef, 0x90, 0x7f, 0xa9, 0x74, 0x02, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82,
0xd0, 0x83, 0xd0, 0xe0, 0x32, 0x12, 0x0c, 0xca, 0x12, 0x0f, 0xb3, 0x90, 0x7f, 0xd6, 0xe0, 0x30,
0xe7, 0x12, 0xe0, 0x44, 0x01, 0xf0, 0x7f, 0x0d, 0x7e, 0x00, 0x12, 0x00, 0x03, 0x90, 0x7f, 0xd6,
0xe0, 0x54, 0xfe, 0xf0, 0x12, 0x0c, 0x24, 0x22, 0x00, 0x02, 0x0e, 0x69, 0x00, 0x02, 0x0e}},
{0x0f06, 64, { 0x42, 0x00, 0x02, 0x0d, 0x45, 0x00, 0x02, 0x0e, 0x90, 0x00, 0x02, 0x0f, 0x10, 0x00, 0x02, 0x0f, 0x14,
0x00, 0x02, 0x0d, 0x12, 0x00, 0x02, 0x0f, 0x1c, 0x00, 0x02, 0x0e, 0xb7, 0x00, 0x02, 0x0f, 0x24,
0x00, 0x02, 0x0f, 0x33, 0x00, 0x02, 0x0f, 0x2c, 0x00, 0x02, 0x0f, 0x58, 0xc0, 0xe0, 0xc0, 0x83,
0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x53, 0x91, 0xef, 0x90}},
{0x0f46, 64, { 0x7f, 0xa9, 0x74, 0x04, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0,
0x32, 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00,
0x53, 0x91, 0xef, 0x90, 0x7f, 0xa9, 0x74, 0x08, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0,
0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32, 0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xfb, 0xf0, 0xe0, 0x44}},
{0x0f86, 61, { 0x08, 0xf0, 0x30, 0x1a, 0x04, 0xe0, 0x44, 0x02, 0xf0, 0x7f, 0xf4, 0x7e, 0x01, 0x12, 0x00, 0x03, 0x90,
0x7f, 0xd6, 0xe0, 0x54, 0xf7, 0xf0, 0xe0, 0x44, 0x04, 0xf0, 0x22, 0x74, 0x00, 0xf5, 0x86, 0x90,
0xfd, 0xa5, 0x7c, 0x05, 0xa3, 0xe5, 0x82, 0x45, 0x83, 0x70, 0xf9, 0x22, 0x90, 0x7f, 0xd6, 0xe0,
0x44, 0x80, 0xf0, 0x43, 0x87, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22}},
{0xffff, 0, {0x00}}
};
/* keyspan_usa49w_fw.h
The firmware contained herein as keyspan_usa49w_fw.h is
Copyright (C) 1999-2003
Keyspan, A division of InnoSys Incorporated ("Keyspan")
as an unpublished work. This notice does not imply unrestricted or
public access to the source code from which this firmware image is
derived. Except as noted below this firmware image may not be
reproduced, used, sold or transferred to any third party without
Keyspan's prior written consent. All Rights Reserved.
Permission is hereby granted for the distribution of this firmware
image as part of a Linux or other Open Source operating system kernel
in text or binary form as required.
This firmware may not be modified and may only be used with
Keyspan hardware. Distribution and/or Modification of the
keyspan.c driver which includes this firmware, in whole or in
part, requires the inclusion of this statement."
static char theFirmwareDate49[] =
"02/14/2002 02:37p 19,347 USA49";
static char theFirmwareDate65[] =
"01/31/2003 09:34a 19,331 USA65";
*/
static const struct ezusb_hex_record keyspan_usa49wlc_firmware[] = {
{0x7f92, 1, { 0x01}},
{0x0033, 3, { 0x02, 0x18, 0xfb}},
{0x0036, 13, { 0xe5, 0x11, 0x04, 0x90, 0x78, 0x41, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22}},
{0x0046, 16, { 0xe4, 0xff, 0x74, 0x40, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7b, 0xf5, 0x83, 0xe0, 0xfe, 0xe5, 0x15}},
{0x0056, 16, { 0x24, 0x04, 0xfd, 0xe4, 0x35, 0x14, 0xfa, 0xa9, 0x05, 0x7b, 0x01, 0xef, 0x7c, 0x00, 0x29, 0xf9}},
{0x0066, 16, { 0xec, 0x3a, 0xfa, 0xee, 0x12, 0x11, 0xec, 0x0f, 0xbf, 0x22, 0xd7, 0xe5, 0x15, 0x24, 0x05, 0xf5}},
{0x0076, 16, { 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x70, 0x03, 0x02, 0x01, 0x34, 0xe5, 0x15, 0x24, 0x09}},
{0x0086, 16, { 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x70, 0x0e, 0xe5, 0x15, 0x24, 0x0a, 0xf5, 0x82}},
{0x0096, 16, { 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x60, 0x18, 0x7f, 0x01, 0xe4, 0xfd, 0x12, 0x16, 0x6b, 0xe5}},
{0x00a6, 16, { 0x15, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0xcf, 0xf0, 0x80, 0x41}},
{0x00b6, 16, { 0xe5, 0x15, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0xff, 0x12, 0x00, 0x03}},
{0x00c6, 16, { 0xe5, 0x15, 0x24, 0x07, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0xff, 0x12, 0x15, 0xab}},
{0x00d6, 16, { 0x7f, 0x01, 0xe5, 0x15, 0x24, 0x08, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0xfd, 0x12}},
{0x00e6, 16, { 0x16, 0x6b, 0xe5, 0x15, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x44, 0x30}},
{0x00f6, 16, { 0xf0, 0xe5, 0x15, 0x24, 0x39, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x44, 0x80, 0xf0}},
{0x0003, 16, { 0x90, 0x78, 0x41, 0x74, 0xf3, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0x90, 0x78, 0x41, 0x74}},
{0x0013, 16, { 0xf0, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x78, 0x41, 0x74, 0xf3, 0xf0, 0xe5, 0x15, 0x24}},
{0x0023, 16, { 0x37, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22}},
{0x0043, 3, { 0x02, 0x1b, 0x00}},
{0x0000, 3, { 0x02, 0x10, 0x90}},
{0x0106, 64, { 0x90, 0x78, 0x41, 0x74, 0xf4, 0xf0, 0xe5, 0x15, 0x24, 0x39, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83,
0xe0, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x78, 0x41, 0x74, 0xf2, 0xf0, 0xe5, 0x15, 0x24, 0x36, 0xf5,
0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x44, 0x06, 0x90, 0xc0, 0x00, 0xf0, 0xe5, 0x15, 0x24,
0x0b, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x60, 0x32, 0xe5, 0x15, 0x24, 0x0c}},
{0x0146, 64, { 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0x3f, 0xff, 0xe5, 0x15, 0x24, 0x37, 0xf5, 0x82,
0xe4, 0x35, 0x14, 0xf5, 0x83, 0xef, 0xf0, 0x90, 0x78, 0x41, 0x74, 0xf3, 0xf0, 0xe5, 0x15, 0x24,
0x37, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x90, 0xc0, 0x00, 0xf0, 0xe5, 0x15, 0x24,
0x0d, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x70, 0x03, 0x02, 0x02, 0x4f, 0xe5}},
{0x0186, 64, { 0x15, 0x24, 0x17, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x60, 0x11, 0xe5, 0x15, 0x24, 0x32,
0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x44, 0x04, 0xf0, 0x80, 0x0f, 0xe5, 0x15, 0x24,
0x32, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0xfb, 0xf0, 0xe4, 0xff, 0xe5, 0x15,
0x24, 0x32, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0xfd, 0x12, 0x16, 0x6b, 0xe5}},
{0x01c6, 64, { 0x15, 0x24, 0x0e, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x60, 0x11, 0xe5, 0x15, 0x24, 0x33,
0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0x80, 0x0f, 0xe5, 0x15, 0x24,
0x33, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0x7f, 0xf0, 0xe5, 0x15, 0x24, 0x33,
0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0xfc, 0xf0, 0xe5, 0x15, 0x24, 0x0f}},
{0x0206, 64, { 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x60, 0x2f, 0xe5, 0x15, 0x24, 0x33, 0xf5, 0x82, 0xe4,
0x35, 0x14, 0xf5, 0x83, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x15, 0x24, 0x10, 0xf5, 0x82, 0xe4, 0x35,
0x14, 0xf5, 0x83, 0xe0, 0xff, 0x12, 0x16, 0x0b, 0xe5, 0x15, 0x24, 0x11, 0xf5, 0x82, 0xe4, 0x35,
0x14, 0xf5, 0x83, 0xe0, 0xff, 0x12, 0x16, 0x3b, 0xe5, 0x15, 0x24, 0x33, 0xf5, 0x82, 0xe4}},
{0x0246, 64, { 0x35, 0x14, 0xf5, 0x83, 0xe0, 0xff, 0x12, 0x15, 0xdb, 0xe5, 0x15, 0x24, 0x14, 0xf5, 0x82, 0xe4, 0x35,
0x14, 0xf5, 0x83, 0xe0, 0x60, 0x44, 0xe5, 0x15, 0x24, 0x15, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5,
0x83, 0xe0, 0x60, 0x11, 0xe5, 0x15, 0x24, 0x39, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0,
0x44, 0x01, 0xf0, 0x80, 0x0f, 0xe5, 0x15, 0x24, 0x39, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5}},
{0x0286, 64, { 0x83, 0xe0, 0x54, 0xfe, 0xf0, 0x90, 0x78, 0x41, 0x74, 0xf4, 0xf0, 0xe5, 0x15, 0x24, 0x39, 0xf5, 0x82,
0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x90, 0xc0, 0x00, 0xf0, 0xe5, 0x15, 0x24, 0x12, 0xf5, 0x82,
0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x60, 0x44, 0xe5, 0x15, 0x24, 0x13, 0xf5, 0x82, 0xe4, 0x35,
0x14, 0xf5, 0x83, 0xe0, 0x60, 0x11, 0xe5, 0x15, 0x24, 0x39, 0xf5, 0x82, 0xe4, 0x35, 0x14}},
{0x02c6, 64, { 0xf5, 0x83, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x0f, 0xe5, 0x15, 0x24, 0x39, 0xf5, 0x82, 0xe4, 0x35, 0x14,
0xf5, 0x83, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0x78, 0x41, 0x74, 0xf4, 0xf0, 0xe5, 0x15, 0x24, 0x39,
0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x90, 0xc0, 0x00, 0xf0, 0xe5, 0x15, 0x24, 0x16,
0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x15, 0x24, 0x35, 0xf5, 0x82}},
{0x0306, 64, { 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xef, 0xf0, 0xe5, 0x15, 0x24, 0x17, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5,
0x83, 0xe0, 0x30, 0xe0, 0x11, 0xe5, 0x15, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83,
0xe0, 0x44, 0x40, 0xf0, 0x80, 0x0f, 0xe5, 0x15, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5,
0x83, 0xe0, 0x54, 0xbf, 0xf0, 0xe5, 0x15, 0x24, 0x18, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5}},
{0x0346, 64, { 0x83, 0xe0, 0xff, 0xe5, 0x15, 0x24, 0x3b, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xef, 0xf0, 0xe5,
0x15, 0x24, 0x19, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x60, 0x11, 0xe5, 0x15, 0x24,
0x39, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x0f, 0xe5, 0x15,
0x24, 0x39, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0xef, 0xf0, 0x90, 0x78}},
{0x0386, 64, { 0x41, 0x74, 0xf4, 0xf0, 0xe5, 0x15, 0x24, 0x39, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x90,
0xc0, 0x00, 0xf0, 0xe5, 0x15, 0x24, 0x1a, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x60,
0x6b, 0xe5, 0x15, 0x24, 0x37, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0xbf, 0xf0,
0x90, 0x78, 0x41, 0x74, 0xf3, 0xf0, 0xe5, 0x15, 0x24, 0x37, 0xf5, 0x82, 0xe4, 0x35, 0x14}},
{0x03c6, 64, { 0xf5, 0x83, 0xe0, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x78, 0x41, 0x74, 0xf1, 0xf0, 0x12, 0x00,
0x36, 0xef, 0x54, 0xfe, 0x90, 0xc0, 0x00, 0xf0, 0xe5, 0x15, 0x24, 0x32, 0xf5, 0x82, 0xe4, 0x35,
0x14, 0xf5, 0x83, 0xe0, 0x54, 0xfd, 0xff, 0xf0, 0xfd, 0xe4, 0xff, 0x12, 0x16, 0x6b, 0xe5, 0x15,
0x24, 0x2c, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x15, 0x24, 0x2b}},
{0x0406, 64, { 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x16, 0x42, 0x13, 0xe5, 0x15, 0x24, 0x1b,
0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x70, 0x0e, 0xe5, 0x15, 0x24, 0x25, 0xf5, 0x82,
0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x60, 0x28, 0xe5, 0x15, 0x24, 0x32, 0xf5, 0x82, 0xe4, 0x35,
0x14, 0xf5, 0x83, 0xe0, 0x44, 0x02, 0xff, 0xf0, 0xfd, 0xe4, 0xff, 0x12, 0x16, 0x6b, 0xe5}},
{0x0446, 64, { 0x15, 0x24, 0x2b, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0x74, 0x01, 0xf0, 0xe5, 0x16, 0x42, 0x13,
0xe5, 0x15, 0x24, 0x1c, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0xff, 0x70, 0x0e, 0xe5,
0x15, 0x24, 0x25, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x60, 0x2a, 0x90, 0x78, 0x41,
0x74, 0xf2, 0xf0, 0xe5, 0x15, 0x24, 0x36, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0}},
{0x0486, 64, { 0x44, 0x04, 0x90, 0xc0, 0x00, 0xf0, 0xef, 0x60, 0x0f, 0xe5, 0x15, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35,
0x14, 0xf5, 0x83, 0xe0, 0x44, 0x04, 0xf0, 0xe5, 0x15, 0x24, 0x1d, 0xf5, 0x82, 0xe4, 0x35, 0x14,
0xf5, 0x83, 0xe0, 0x60, 0x27, 0xe5, 0x15, 0x24, 0x37, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83,
0xe0, 0x44, 0x40, 0xf0, 0x90, 0x78, 0x41, 0x74, 0xf3, 0xf0, 0xe5, 0x15, 0x24, 0x37, 0xf5}},
{0x04c6, 64, { 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0xe5, 0x15, 0x24, 0x1e,
0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x60, 0x28, 0xe5, 0x15, 0x24, 0x32, 0xf5, 0x82,
0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0xfe, 0xff, 0xf0, 0xfd, 0xe4, 0xff, 0x12, 0x16, 0x6b,
0xe5, 0x15, 0x24, 0x2d, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0x74, 0x01, 0xf0, 0xe5}},
{0x0506, 64, { 0x16, 0x42, 0x13, 0xe5, 0x15, 0x24, 0x1f, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x70, 0x0e,
0xe5, 0x15, 0x24, 0x25, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x60, 0x27, 0xe5, 0x15,
0x24, 0x32, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x44, 0x01, 0xff, 0xf0, 0xfd, 0xe4,
0xff, 0x12, 0x16, 0x6b, 0xe5, 0x15, 0x24, 0x2d, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83}},
{0x0546, 64, { 0xe4, 0xf0, 0xe5, 0x16, 0x42, 0x13, 0xe5, 0x15, 0x24, 0x20, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83,
0xe0, 0x70, 0x0e, 0xe5, 0x15, 0x24, 0x25, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x60,
0x18, 0x90, 0x78, 0x41, 0x74, 0xf2, 0xf0, 0xe5, 0x15, 0x24, 0x36, 0xf5, 0x82, 0xe4, 0x35, 0x14,
0xf5, 0x83, 0xe0, 0x44, 0x02, 0x90, 0xc0, 0x00, 0xf0, 0xe5, 0x15, 0x24, 0x21, 0xf5, 0x82}},
{0x0586, 64, { 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x60, 0x0f, 0xe5, 0x15, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x14,
0xf5, 0x83, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x15, 0x24, 0x22, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5,
0x83, 0xe0, 0x60, 0x1f, 0xe5, 0x15, 0x24, 0x2e, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0x74,
0x01, 0xf0, 0xe5, 0x15, 0x24, 0x3a, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe4, 0xf0}},
{0x05c6, 64, { 0xe5, 0x16, 0x42, 0x13, 0xe5, 0x15, 0x24, 0x23, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x60,
0x03, 0x12, 0x18, 0x7a, 0xe5, 0x15, 0x24, 0x24, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0,
0x60, 0x23, 0xe5, 0x15, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x44, 0x08,
0xf0, 0xe5, 0x16, 0xc4, 0x54, 0xf0, 0xff, 0x42, 0x11, 0x90, 0x7f, 0x96, 0xe0, 0x4f, 0xf0}},
{0x0606, 64, { 0x90, 0x78, 0x41, 0xe0, 0x4f, 0xf0, 0xe5, 0x15, 0x24, 0x25, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83,
0xe0, 0x60, 0x24, 0xe5, 0x15, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54,
0xf7, 0xf0, 0xe5, 0x16, 0xc4, 0x54, 0xf0, 0xf4, 0xff, 0x52, 0x11, 0x90, 0x7f, 0x96, 0xe0, 0x5f,
0xf0, 0x90, 0x78, 0x41, 0xe0, 0x5f, 0xf0, 0x22, 0x90, 0x7f, 0xe9, 0xe0, 0x12, 0x11, 0xfe}},
{0x0646, 64, { 0x07, 0x99, 0x00, 0x08, 0x0d, 0x01, 0x08, 0x79, 0x03, 0x06, 0x62, 0x06, 0x07, 0x8a, 0x08, 0x07, 0x7e,
0x09, 0x07, 0x66, 0x0a, 0x07, 0x75, 0x0b, 0x00, 0x00, 0x08, 0xc8, 0x90, 0x7f, 0xeb, 0xe0, 0x24,
0xfe, 0x60, 0x1c, 0x14, 0x70, 0x03, 0x02, 0x07, 0x14, 0x24, 0x02, 0x60, 0x03, 0x02, 0x07, 0x5c,
0x74, 0x19, 0x90, 0x7f, 0xd4, 0xf0, 0x74, 0x00, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x08, 0xcf}},
{0x0686, 64, { 0x90, 0x7f, 0xea, 0xe0, 0x04, 0x75, 0x82, 0x17, 0x75, 0x83, 0x19, 0xf0, 0x90, 0x7f, 0xea, 0xe0, 0x30,
0xe0, 0x04, 0x7f, 0x02, 0x80, 0x02, 0x7f, 0x03, 0x75, 0x82, 0x82, 0x75, 0x83, 0x19, 0xef, 0xf0,
0x75, 0x82, 0x6d, 0x75, 0x83, 0x19, 0xf0, 0x75, 0x82, 0x66, 0x75, 0x83, 0x19, 0xf0, 0x75, 0x82,
0x5f, 0x75, 0x83, 0x19, 0xf0, 0x75, 0x82, 0x58, 0x75, 0x83, 0x19, 0xf0, 0x90, 0x7f, 0xea}},
{0x06c6, 64, { 0xe0, 0x30, 0xe1, 0x04, 0x7f, 0x64, 0x80, 0x02, 0x7f, 0x32, 0x75, 0x82, 0x1a, 0x75, 0x83, 0x19, 0xef,
0xf0, 0x90, 0x7f, 0xef, 0xe0, 0xfe, 0x90, 0x7f, 0xee, 0xe0, 0x7c, 0x00, 0x24, 0x00, 0xf5, 0x18,
0xec, 0x3e, 0xf5, 0x17, 0x75, 0x33, 0x19, 0x75, 0x34, 0x12, 0x75, 0x82, 0x14, 0x75, 0x83, 0x19,
0xe0, 0x75, 0x27, 0x00, 0xf5, 0x28, 0xd3, 0xe5, 0x28, 0x95, 0x18, 0xe5, 0x27, 0x95, 0x17}},
{0x0706, 64, { 0x40, 0x06, 0x85, 0x17, 0x27, 0x85, 0x18, 0x28, 0x12, 0x13, 0x0d, 0x02, 0x08, 0xcf, 0x90, 0x7f, 0xea,
0xe0, 0xff, 0x12, 0x14, 0x5f, 0xea, 0x49, 0x60, 0x32, 0x90, 0x7f, 0xee, 0xe0, 0x75, 0x17, 0x00,
0xf5, 0x18, 0xae, 0x02, 0xaf, 0x01, 0x8e, 0x33, 0x8f, 0x34, 0x8f, 0x82, 0x8e, 0x83, 0xe0, 0xfe,
0xa3, 0xe0, 0x8e, 0x27, 0xf5, 0x28, 0xd3, 0x95, 0x18, 0xe5, 0x27, 0x95, 0x17, 0x40, 0x06}},
{0x0746, 64, { 0x85, 0x17, 0x27, 0x85, 0x18, 0x28, 0x12, 0x13, 0x0d, 0x02, 0x08, 0xcf, 0x90, 0x7f, 0xb4, 0xe0, 0x44,
0x01, 0xf0, 0x02, 0x08, 0xcf, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x08, 0xcf, 0x90,
0x7f, 0x00, 0xe5, 0x25, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x02, 0x08, 0xcf, 0x90, 0x7f,
0xea, 0xe0, 0xf5, 0x25, 0x02, 0x08, 0xcf, 0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x22, 0x12, 0x0a}},
{0x0786, 64, { 0xce, 0x02, 0x08, 0xcf, 0x90, 0x7f, 0x00, 0xe5, 0x22, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x02,
0x08, 0xcf, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0x7f, 0x60, 0x24, 0x14, 0x60, 0x31, 0x24, 0x02, 0x70,
0x5b, 0xa2, 0x00, 0xe4, 0x33, 0xff, 0x25, 0xe0, 0xff, 0xa2, 0x06, 0xe4, 0x33, 0x4f, 0x90, 0x7f,
0x00, 0xf0, 0xe4, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x08, 0xcf, 0xe4}},
{0x07c6, 64, { 0x90, 0x7f, 0x00, 0xf0, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x08, 0xcf, 0x90, 0x7f,
0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0,
0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe0, 0x54, 0xfd, 0x90, 0x7f, 0x00, 0xf0,
0xe4, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x08, 0xcf, 0x90, 0x7f, 0xb4}},
{0x0806, 64, { 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x08, 0xcf, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0xfe, 0x60, 0x1d, 0x24, 0x02,
0x60, 0x03, 0x02, 0x08, 0xcf, 0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x05, 0xc2, 0x00, 0x02, 0x08,
0xcf, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x08, 0xcf, 0x90, 0x7f, 0xea, 0xe0, 0x70,
0x38, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54}},
{0x0846, 64, { 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe4, 0xf0, 0x90, 0x7f,
0xec, 0xe0, 0x54, 0x80, 0xff, 0x13, 0x13, 0x13, 0x54, 0x1f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x90,
0x7f, 0xd7, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x5f, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0,
0x80, 0x56, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0xfe, 0x60, 0x18, 0x24, 0x02, 0x70, 0x4a, 0x90}},
{0x0886, 64, { 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x04, 0xd2, 0x00, 0x80, 0x3f, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0,
0x80, 0x36, 0x90, 0x7f, 0xea, 0xe0, 0x70, 0x20, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff,
0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34,
0x7f, 0xf5, 0x83, 0x74, 0x01, 0xf0, 0x80, 0x10, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0}},
{0x08c6, 64, { 0x80, 0x07, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x22,
0xe5, 0x12, 0x54, 0x0f, 0x70, 0x03, 0x02, 0x09, 0xc8, 0x12, 0x16, 0x9a, 0xef, 0x20, 0xe1, 0x75,
0x12, 0x16, 0xf8, 0xef, 0x14, 0xf5, 0x18, 0x12, 0x18, 0xc5, 0xef, 0x25, 0x18, 0xff, 0xe4, 0x33,
0xfe, 0xc3, 0xef, 0x94, 0x80, 0xee, 0x64, 0x80, 0x94, 0x80, 0x50, 0x59, 0x85, 0x15, 0x82}},
{0x0906, 64, { 0x85, 0x14, 0x83, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xf5, 0x82, 0x8e, 0x83, 0xe0, 0x30, 0xe0, 0x11, 0xe5,
0x15, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0x80, 0x0f,
0xe5, 0x15, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0x7f, 0xf0, 0xe5,
0x15, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x20, 0xe2, 0x12, 0xe5}},
{0x0946, 64, { 0x18, 0x60, 0x0e, 0xf5, 0x23, 0xef, 0x24, 0x01, 0xf5, 0x2d, 0xe4, 0x3e, 0xf5, 0x2c, 0x12, 0x14, 0xa0,
0xe4, 0xff, 0x12, 0x14, 0xd7, 0xe5, 0x15, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83,
0xe0, 0x30, 0xe7, 0x5d, 0x12, 0x18, 0xc5, 0xe5, 0x15, 0x24, 0x3b, 0xf5, 0x82, 0xe4, 0x35, 0x14,
0xf5, 0x83, 0xe0, 0xfe, 0xef, 0xc3, 0x9e, 0x50, 0x48, 0xe5, 0x15, 0x24, 0x2f, 0xf5, 0x82}},
{0x0986, 64, { 0xe4, 0x35, 0x14, 0xf5, 0x83, 0x74, 0x01, 0xf0, 0xe5, 0x15, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x14,
0xf5, 0x83, 0xe0, 0x54, 0x7b, 0xf0, 0xe5, 0x15, 0x24, 0x3a, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5,
0x83, 0xe4, 0xf0, 0xe5, 0x16, 0x42, 0x13, 0x90, 0x7f, 0xc2, 0xe0, 0x30, 0xe1, 0x10, 0xe5, 0x15,
0x24, 0x26, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0xf5, 0x24, 0x80, 0x03, 0x12}},
{0x09c6, 64, { 0x12, 0x9c, 0x12, 0x16, 0xc9, 0xef, 0x30, 0xe1, 0x03, 0x02, 0x0a, 0xcd, 0x12, 0x17, 0xc7, 0x8f, 0x18,
0x12, 0x18, 0xd3, 0xe5, 0x15, 0x24, 0x38, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xef, 0xf0,
0xe5, 0x15, 0x24, 0x35, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x18, 0xc3,
0x9f, 0x50, 0x28, 0x12, 0x18, 0xa9, 0xef, 0x30, 0xe0, 0x21, 0xe5, 0x15, 0x24, 0x38, 0xf5}},
{0x0a06, 64, { 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x20, 0xe7, 0x12, 0xe5, 0x15, 0x24, 0x31, 0xf5, 0x82, 0xe4,
0x35, 0x14, 0xf5, 0x83, 0xe0, 0x20, 0xe1, 0x03, 0x02, 0x0a, 0xcd, 0xe5, 0x15, 0x24, 0x31, 0xf5,
0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0xfd, 0xf0, 0xe5, 0x18, 0x70, 0x03, 0x02, 0x0a,
0xcd, 0xb4, 0x80, 0x0f, 0xe5, 0x15, 0x24, 0x38, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83}},
{0x0a46, 64, { 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x15, 0x24, 0x38, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0xff,
0x30, 0xe7, 0x29, 0xe5, 0x18, 0xd3, 0x94, 0x20, 0x40, 0x03, 0x75, 0x18, 0x20, 0x85, 0x18, 0x23,
0x85, 0x15, 0x82, 0x85, 0x14, 0x83, 0xa3, 0xa3, 0xe0, 0xfc, 0xa3, 0xe0, 0x8c, 0x2c, 0xf5, 0x2d,
0x12, 0x13, 0xcf, 0xe5, 0x18, 0x25, 0xe0, 0xff, 0x12, 0x15, 0x0d, 0x22, 0xe5, 0x18, 0xd3}},
{0x0a86, 64, { 0x94, 0x3f, 0x40, 0x03, 0x75, 0x18, 0x3f, 0x85, 0x18, 0x23, 0xe5, 0x15, 0x24, 0x38, 0xf5, 0x82, 0xe4,
0x35, 0x14, 0xf5, 0x83, 0xe0, 0xff, 0x85, 0x15, 0x82, 0x85, 0x14, 0x83, 0xa3, 0xa3, 0xe0, 0xfc,
0xa3, 0xe0, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x85, 0x15, 0x82, 0x85, 0x14, 0x83, 0xa3, 0xa3,
0xe0, 0xfe, 0xa3, 0xe0, 0x24, 0x01, 0xf5, 0x2d, 0xe4, 0x3e, 0xf5, 0x2c, 0x12, 0x14, 0x1d}},
{0x0ac6, 64, { 0xe5, 0x18, 0x04, 0xff, 0x12, 0x15, 0x0d, 0x22, 0xe4, 0x90, 0x7f, 0x93, 0xf0, 0x90, 0x7f, 0x9c, 0x74,
0xff, 0xf0, 0xe4, 0x90, 0x7f, 0x96, 0xf0, 0x90, 0x7f, 0x94, 0xf0, 0x90, 0x78, 0x4a, 0x04, 0xf0,
0xf5, 0x8e, 0x90, 0x7f, 0x95, 0x74, 0xc0, 0xf0, 0x90, 0x7f, 0x9e, 0x74, 0x3f, 0xf0, 0x90, 0x7f,
0x98, 0x74, 0x2f, 0xf0, 0x90, 0x78, 0x43, 0x74, 0xf7, 0xf0, 0xe4, 0x90, 0x78, 0x41, 0xf0}},
{0x0b06, 64, { 0x90, 0x7f, 0xdf, 0x74, 0x9f, 0xf0, 0x90, 0x7f, 0xde, 0xf0, 0x90, 0x7f, 0x92, 0xe0, 0x44, 0x02, 0xf0,
0x7e, 0x7b, 0x7f, 0xc0, 0x75, 0x14, 0x7b, 0x75, 0x15, 0xc0, 0x90, 0x7f, 0x98, 0x74, 0x2e, 0xf0,
0x75, 0x16, 0x01, 0x12, 0x0f, 0x28, 0x7e, 0x7b, 0x7f, 0xc0, 0x75, 0x14, 0x7b, 0x75, 0x15, 0xc0,
0x90, 0x7f, 0x98, 0x74, 0x2e, 0xf0, 0x75, 0x16, 0x01, 0xe5, 0x15, 0x24, 0x26, 0xf5, 0x82}},
{0x0b46, 64, { 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe4, 0xf0, 0x7e, 0x7e, 0x7f, 0x40, 0x85, 0x15, 0x82, 0x85, 0x14, 0x83,
0x74, 0x7e, 0xf0, 0xa3, 0x74, 0x40, 0xf0, 0x7e, 0x7e, 0x7f, 0x80, 0x85, 0x15, 0x82, 0x85, 0x14,
0x83, 0xa3, 0xa3, 0x74, 0x7e, 0xf0, 0xa3, 0x74, 0x80, 0xf0, 0x7e, 0x7c, 0x7f, 0x00, 0x75, 0x14,
0x7c, 0x75, 0x15, 0x00, 0x90, 0x7f, 0x98, 0x74, 0x2d, 0xf0, 0x75, 0x16, 0x02, 0x12, 0x0f}},
{0x0b86, 64, { 0x28, 0x7e, 0x7c, 0x7f, 0x00, 0x75, 0x14, 0x7c, 0x75, 0x15, 0x00, 0x90, 0x7f, 0x98, 0x74, 0x2d, 0xf0,
0x75, 0x16, 0x02, 0xe5, 0x15, 0x24, 0x26, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0x74, 0x01,
0xf0, 0x7e, 0x7d, 0x7f, 0xc0, 0x85, 0x15, 0x82, 0x85, 0x14, 0x83, 0x74, 0x7d, 0xf0, 0xa3, 0x74,
0xc0, 0xf0, 0x7e, 0x7e, 0x7f, 0x00, 0x85, 0x15, 0x82, 0x85, 0x14, 0x83, 0xa3, 0xa3, 0x74}},
{0x0bc6, 64, { 0x7e, 0xf0, 0xa3, 0x74, 0x00, 0xf0, 0x7e, 0x7c, 0x7f, 0x40, 0x75, 0x14, 0x7c, 0x75, 0x15, 0x40, 0x90,
0x7f, 0x98, 0x74, 0x2b, 0xf0, 0x75, 0x16, 0x04, 0x12, 0x0f, 0x28, 0x7e, 0x7c, 0x7f, 0x40, 0x75,
0x14, 0x7c, 0x75, 0x15, 0x40, 0x90, 0x7f, 0x98, 0x74, 0x2b, 0xf0, 0x75, 0x16, 0x04, 0xe5, 0x15,
0x24, 0x26, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0x74, 0x02, 0xf0, 0x7e, 0x7d, 0x7f}},
{0x0c06, 64, { 0x40, 0x85, 0x15, 0x82, 0x85, 0x14, 0x83, 0x74, 0x7d, 0xf0, 0xa3, 0x74, 0x40, 0xf0, 0x7e, 0x7d, 0x7f,
0x80, 0x85, 0x15, 0x82, 0x85, 0x14, 0x83, 0xa3, 0xa3, 0x74, 0x7d, 0xf0, 0xa3, 0x74, 0x80, 0xf0,
0x7e, 0x7c, 0x7f, 0x80, 0x75, 0x14, 0x7c, 0x75, 0x15, 0x80, 0x90, 0x7f, 0x98, 0x74, 0x27, 0xf0,
0x75, 0x16, 0x08, 0x12, 0x0f, 0x28, 0x7e, 0x7c, 0x7f, 0x80, 0x75, 0x14, 0x7c, 0x75, 0x15}},
{0x0c46, 64, { 0x80, 0x90, 0x7f, 0x98, 0x74, 0x27, 0xf0, 0x75, 0x16, 0x08, 0xe5, 0x15, 0x24, 0x26, 0xf5, 0x82, 0xe4,
0x35, 0x14, 0xf5, 0x83, 0x74, 0x03, 0xf0, 0x7e, 0x7c, 0x7f, 0xc0, 0x85, 0x15, 0x82, 0x85, 0x14,
0x83, 0x74, 0x7c, 0xf0, 0xa3, 0x74, 0xc0, 0xf0, 0x7e, 0x7d, 0x7f, 0x00, 0x85, 0x15, 0x82, 0x85,
0x14, 0x83, 0xa3, 0xa3, 0x74, 0x7d, 0xf0, 0xa3, 0x74, 0x00, 0xf0, 0xc2, 0x0a, 0xc2, 0x09}},
{0x0c86, 64, { 0xe4, 0xf5, 0x11, 0xd2, 0x02, 0x22, 0xe5, 0x10, 0x04, 0x54, 0x03, 0xf5, 0x10, 0x14, 0x60, 0x1f, 0x14,
0x60, 0x31, 0x14, 0x60, 0x43, 0x24, 0x03, 0x70, 0x52, 0x7e, 0x7b, 0x7f, 0xc0, 0x75, 0x14, 0x7b,
0x75, 0x15, 0xc0, 0x90, 0x7f, 0x98, 0x74, 0x2e, 0xf0, 0x75, 0x16, 0x01, 0x80, 0x3d, 0x7e, 0x7c,
0x7f, 0x00, 0x75, 0x14, 0x7c, 0x75, 0x15, 0x00, 0x90, 0x7f, 0x98, 0x74, 0x2d, 0xf0, 0x75}},
{0x0cc6, 64, { 0x16, 0x02, 0x80, 0x28, 0x7e, 0x7c, 0x7f, 0x40, 0x75, 0x14, 0x7c, 0x75, 0x15, 0x40, 0x90, 0x7f, 0x98,
0x74, 0x2b, 0xf0, 0x75, 0x16, 0x04, 0x80, 0x13, 0x7e, 0x7c, 0x7f, 0x80, 0x75, 0x14, 0x7c, 0x75,
0x15, 0x80, 0x90, 0x7f, 0x98, 0x74, 0x27, 0xf0, 0x75, 0x16, 0x08, 0xe5, 0x32, 0x55, 0x16, 0x70,
0x03, 0x02, 0x0e, 0x27, 0xe5, 0x16, 0xf4, 0x52, 0x32, 0xe5, 0x26, 0x54, 0x7f, 0xff, 0x70}},
{0x0d06, 64, { 0x17, 0xe5, 0x2a, 0x55, 0x16, 0x60, 0x34, 0x90, 0x7f, 0x96, 0xe0, 0xfe, 0xe5, 0x16, 0xc4, 0x54, 0xf0,
0xf4, 0xfd, 0xee, 0x5d, 0xf0, 0x80, 0x23, 0xbf, 0x20, 0x20, 0xe5, 0x15, 0x24, 0x31, 0xf5, 0x82,
0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x30, 0xe3, 0x11, 0xe4, 0xf5, 0x2a, 0x90, 0x7f, 0x96, 0xe0,
0xff, 0xe5, 0x16, 0xc4, 0x54, 0xf0, 0xfe, 0xef, 0x4e, 0xf0, 0xe5, 0x15, 0x24, 0x3a, 0xf5}},
{0x0d46, 64, { 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x60, 0x03, 0xe0, 0x14, 0xf0, 0xe5, 0x15, 0x24, 0x34, 0xf5,
0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x60, 0x03, 0xe0, 0x14, 0xf0, 0xe0, 0x60, 0x03, 0x02,
0x0e, 0x27, 0x74, 0x0a, 0xf0, 0x12, 0x00, 0x36, 0xef, 0x54, 0x01, 0xff, 0xf5, 0x18, 0xe5, 0x15,
0x24, 0x2c, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x6f, 0x60, 0x07, 0xe5, 0x18}},
{0x0d86, 64, { 0xf0, 0xe5, 0x16, 0x42, 0x13, 0x12, 0x18, 0xe1, 0x8f, 0x18, 0xe5, 0x15, 0x24, 0x27, 0xf5, 0x82, 0xe4,
0x35, 0x14, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x18, 0x54, 0x10, 0xfe, 0x6f, 0x60, 0x06, 0xee, 0xf0,
0xe5, 0x16, 0x42, 0x13, 0xe5, 0x15, 0x24, 0x28, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0,
0xff, 0xe5, 0x18, 0x54, 0x80, 0xfe, 0x6f, 0x60, 0x06, 0xee, 0xf0, 0xe5, 0x16, 0x42, 0x13}},
{0x0dc6, 64, { 0xe5, 0x15, 0x24, 0x29, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x18, 0x54, 0x20,
0xfe, 0x6f, 0x60, 0x15, 0xee, 0xf0, 0xe5, 0x15, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5,
0x83, 0xe0, 0x30, 0xe4, 0x04, 0xe5, 0x16, 0x42, 0x13, 0xe5, 0x15, 0x24, 0x2a, 0xf5, 0x82, 0xe4,
0x35, 0x14, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x18, 0x54, 0x40, 0xfe, 0x6f, 0x60, 0x15, 0xee}},
{0x0e06, 64, { 0xf0, 0xe5, 0x15, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x30, 0xe5, 0x04, 0xe5,
0x16, 0x42, 0x13, 0xe5, 0x15, 0x24, 0x30, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe4, 0xf0,
0x22, 0x30, 0x09, 0x03, 0x02, 0x0f, 0x27, 0xe5, 0x24, 0x14, 0x60, 0x2a, 0x14, 0x60, 0x41, 0x14,
0x60, 0x58, 0x14, 0x60, 0x6f, 0x24, 0x04, 0x60, 0x03, 0x02, 0x0e, 0xe5, 0x7e, 0x7b, 0x7f}},
{0x0e46, 64, { 0xc0, 0x75, 0x14, 0x7b, 0x75, 0x15, 0xc0, 0x90, 0x7f, 0x98, 0x74, 0x2e, 0xf0, 0x75, 0x16, 0x01, 0x12,
0x12, 0x9c, 0x75, 0x24, 0x01, 0x22, 0x7e, 0x7c, 0x7f, 0x00, 0x75, 0x14, 0x7c, 0x75, 0x15, 0x00,
0x90, 0x7f, 0x98, 0x74, 0x2d, 0xf0, 0x75, 0x16, 0x02, 0x12, 0x12, 0x9c, 0x75, 0x24, 0x02, 0x22,
0x7e, 0x7c, 0x7f, 0x40, 0x75, 0x14, 0x7c, 0x75, 0x15, 0x40, 0x90, 0x7f, 0x98, 0x74, 0x2b}},
{0x0e86, 64, { 0xf0, 0x75, 0x16, 0x04, 0x12, 0x12, 0x9c, 0x75, 0x24, 0x03, 0x22, 0x7e, 0x7c, 0x7f, 0x80, 0x75, 0x14,
0x7c, 0x75, 0x15, 0x80, 0x90, 0x7f, 0x98, 0x74, 0x27, 0xf0, 0x75, 0x16, 0x08, 0x12, 0x12, 0x9c,
0x75, 0x24, 0x04, 0x22, 0x30, 0x04, 0x33, 0xc2, 0x04, 0x53, 0x13, 0xdf, 0xe4, 0xf5, 0x18, 0x7e,
0x00, 0x7b, 0x00, 0x74, 0x2e, 0x25, 0x18, 0xf9, 0xee, 0x34, 0x00, 0xfa, 0x12, 0x11, 0xa6}},
{0x0ec6, 64, { 0xff, 0x74, 0x80, 0x25, 0x18, 0xf5, 0x82, 0xe4, 0x34, 0x7b, 0xf5, 0x83, 0xef, 0xf0, 0x05, 0x18, 0xe5,
0x18, 0xb4, 0x03, 0xdb, 0x90, 0x7f, 0xc3, 0x74, 0x03, 0xf0, 0x75, 0x24, 0x05, 0x22, 0xe5, 0x36,
0x60, 0x3b, 0xd5, 0x36, 0x0a, 0x53, 0x13, 0xef, 0x30, 0x0a, 0x04, 0xd2, 0x09, 0xc2, 0x0a, 0xe4,
0xf5, 0x18, 0x7e, 0x00, 0x7b, 0x00, 0x74, 0x35, 0x25, 0x18, 0xf9, 0xee, 0x34, 0x00, 0xfa}},
{0x0f06, 64, { 0x12, 0x11, 0xa6, 0xff, 0x74, 0x80, 0x25, 0x18, 0xf5, 0x82, 0xe4, 0x34, 0x7b, 0xf5, 0x83, 0xef, 0xf0,
0x05, 0x18, 0xe5, 0x18, 0xb4, 0x03, 0xdb, 0x90, 0x7f, 0xc3, 0x74, 0x03, 0xf0, 0xe4, 0xf5, 0x24,
0x22, 0xe4, 0xf5, 0x19, 0x7e, 0x00, 0x7b, 0x01, 0xe5, 0x15, 0x25, 0x19, 0xf9, 0xee, 0x35, 0x14,
0xfa, 0xe4, 0x12, 0x11, 0xec, 0x05, 0x19, 0xe5, 0x19, 0xb4, 0x3c, 0xe8, 0xe5, 0x15, 0x24}},
{0x0f46, 64, { 0x35, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0x74, 0x01, 0xf0, 0x90, 0x78, 0x41, 0x74, 0xf3, 0xf0,
0xe5, 0x15, 0x24, 0x37, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0x74, 0x03, 0xf0, 0x90, 0xc0,
0x00, 0xf0, 0x7f, 0x0c, 0xe4, 0xfd, 0x12, 0x16, 0x6b, 0x7f, 0x10, 0xe5, 0x15, 0x24, 0x33, 0xf5,
0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xef, 0xf0, 0x12, 0x15, 0xdb, 0x90, 0x78, 0x41, 0x74}},
{0x0f86, 64, { 0xf2, 0xf0, 0x7f, 0x01, 0xe5, 0x15, 0x24, 0x36, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xef, 0xf0,
0x44, 0x06, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x78, 0x41, 0x74, 0xf4, 0xf0, 0xe5, 0x15, 0x24, 0x39,
0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0x74, 0x80, 0xf0, 0x90, 0xc0, 0x00, 0xf0, 0x0f, 0xe4,
0xfd, 0x12, 0x16, 0x6b, 0xe4, 0xff, 0x7e, 0xa3, 0xe5, 0x15, 0x24, 0x32, 0xf5, 0x82, 0xe4}},
{0x0fc6, 64, { 0x35, 0x14, 0xf5, 0x83, 0xee, 0xf0, 0xfd, 0x12, 0x16, 0x6b, 0x90, 0x78, 0x41, 0x74, 0xf1, 0xf0, 0x90,
0xc0, 0x00, 0xe4, 0xf0, 0x7f, 0x05, 0x7d, 0x7f, 0x12, 0x16, 0x6b, 0x7f, 0x01, 0x12, 0x15, 0x43,
0x7f, 0x03, 0x7d, 0x07, 0x12, 0x16, 0x6b, 0x22, 0x53, 0x13, 0x3f, 0x90, 0x7b, 0xf1, 0xe0, 0x30,
0xe3, 0x16, 0x7e, 0x7b, 0x7f, 0xc0, 0x75, 0x14, 0x7b, 0x75, 0x15, 0xc0, 0x90, 0x7f, 0x98}},
{0x1006, 64, { 0x74, 0x2e, 0xf0, 0x75, 0x16, 0x01, 0x12, 0x08, 0xd7, 0x90, 0x7c, 0x31, 0xe0, 0x30, 0xe3, 0x16, 0x7e,
0x7c, 0x7f, 0x00, 0x75, 0x14, 0x7c, 0x75, 0x15, 0x00, 0x90, 0x7f, 0x98, 0x74, 0x2d, 0xf0, 0x75,
0x16, 0x02, 0x12, 0x08, 0xd7, 0x90, 0x7c, 0x71, 0xe0, 0x30, 0xe3, 0x16, 0x7e, 0x7c, 0x7f, 0x40,
0x75, 0x14, 0x7c, 0x75, 0x15, 0x40, 0x90, 0x7f, 0x98, 0x74, 0x2b, 0xf0, 0x75, 0x16, 0x04}},
{0x1046, 64, { 0x12, 0x08, 0xd7, 0x90, 0x7c, 0xb1, 0xe0, 0x30, 0xe3, 0x16, 0x7e, 0x7c, 0x7f, 0x80, 0x75, 0x14, 0x7c,
0x75, 0x15, 0x80, 0x90, 0x7f, 0x98, 0x74, 0x27, 0xf0, 0x75, 0x16, 0x08, 0x12, 0x08, 0xd7, 0x05,
0x12, 0xe5, 0x12, 0x54, 0x0f, 0xf5, 0x17, 0x70, 0x04, 0x12, 0x11, 0x1c, 0x22, 0xe5, 0x17, 0xb4,
0x01, 0x04, 0x12, 0x0c, 0x8c, 0x22, 0x90, 0x7f, 0xc2, 0xe0, 0x20, 0xe1, 0x08, 0xe5, 0x13}},
{0x1086, 64, { 0x60, 0x04, 0x12, 0x0e, 0x28, 0x22, 0x12, 0x0c, 0x8c, 0x22, 0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75,
0x81, 0x37, 0x02, 0x10, 0xd7, 0x02, 0x12, 0x24, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40,
0x03, 0xf6, 0x80, 0x01, 0xf2, 0x08, 0xdf, 0xf4, 0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07,
0x24, 0x0c, 0xc8, 0xc3, 0x33, 0xc4, 0x54, 0x0f, 0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4}},
{0x10c6, 64, { 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf, 0xe4, 0x80, 0x0b, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
0x90, 0x18, 0x45, 0xe4, 0x7e, 0x01, 0x93, 0x60, 0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09,
0x54, 0x1f, 0xfe, 0xe4, 0x93, 0xa3, 0x60, 0x01, 0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8,
0x40, 0xb8, 0xe4, 0x93, 0xa3, 0xfa, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5}},
{0x1106, 64, { 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf,
0xe9, 0xde, 0xe7, 0x80, 0xbe, 0x90, 0x7f, 0xd2, 0xe0, 0x30, 0xe1, 0x03, 0x02, 0x11, 0xa5, 0xc2,
0x09, 0x90, 0x7b, 0x40, 0xe0, 0x14, 0x60, 0x26, 0x14, 0x60, 0x3b, 0x14, 0x60, 0x50, 0x24, 0x83,
0x60, 0x64, 0x24, 0x80, 0x70, 0x63, 0x7e, 0x7b, 0x7f, 0xc0, 0x75, 0x14, 0x7b, 0x75, 0x15}},
{0x1146, 64, { 0xc0, 0x90, 0x7f, 0x98, 0x74, 0x2e, 0xf0, 0x75, 0x16, 0x01, 0x12, 0x00, 0x46, 0x80, 0x4b, 0x7e, 0x7c,
0x7f, 0x00, 0x75, 0x14, 0x7c, 0x75, 0x15, 0x00, 0x90, 0x7f, 0x98, 0x74, 0x2d, 0xf0, 0x75, 0x16,
0x02, 0x12, 0x00, 0x46, 0x80, 0x33, 0x7e, 0x7c, 0x7f, 0x40, 0x75, 0x14, 0x7c, 0x75, 0x15, 0x40,
0x90, 0x7f, 0x98, 0x74, 0x2b, 0xf0, 0x75, 0x16, 0x04, 0x12, 0x00, 0x46, 0x80, 0x1b, 0x7e}},
{0x1186, 64, { 0x7c, 0x7f, 0x80, 0x75, 0x14, 0x7c, 0x75, 0x15, 0x80, 0x90, 0x7f, 0x98, 0x74, 0x27, 0xf0, 0x75, 0x16,
0x08, 0x12, 0x00, 0x46, 0x80, 0x03, 0x12, 0x17, 0x51, 0xe4, 0x90, 0x7f, 0xd3, 0xf0, 0x22, 0xbb,
0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb, 0xfe, 0x02, 0xe3,
0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22, 0xbb, 0x01, 0x0c, 0xe5, 0x82, 0x29, 0xf5}},
{0x11c6, 64, { 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe6, 0x22, 0xbb,
0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a,
0xf5, 0x83, 0xe4, 0x93, 0x22, 0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xf0, 0x22, 0x50, 0x02,
0xf7, 0x22, 0xbb, 0xfe, 0x01, 0xf3, 0x22, 0xd0, 0x83, 0xd0, 0x82, 0xf8, 0xe4, 0x93, 0x70}},
{0x1206, 64, { 0x12, 0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, 0xa3, 0x93, 0xf8, 0x74, 0x01, 0x93, 0xf5, 0x82, 0x88, 0x83,
0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60, 0xef, 0xa3, 0xa3, 0xa3, 0x80, 0xdf, 0x90, 0x7f, 0xae,
0xe0, 0xff, 0xd3, 0x92, 0x00, 0xe4, 0x33, 0xfe, 0xef, 0x4e, 0xf0, 0xd2, 0xe8, 0x43, 0xd8, 0x20,
0x90, 0x7f, 0xde, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xdf, 0xf0, 0x90, 0x7f, 0xab, 0x74, 0xff}},
{0x1246, 64, { 0xf0, 0x90, 0x7f, 0xa9, 0xf0, 0x90, 0x7f, 0xaa, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xaf, 0x74, 0x01,
0xf0, 0x90, 0x7f, 0xae, 0x74, 0x0d, 0xf0, 0xd2, 0xaf, 0xd2, 0x0b, 0x12, 0x18, 0x09, 0xc2, 0x01,
0xe4, 0xf5, 0x2b, 0xf5, 0x31, 0xc2, 0x07, 0xc2, 0x02, 0x75, 0x29, 0x0f, 0x90, 0x7f, 0xd8, 0xe0,
0x65, 0x26, 0x60, 0x06, 0x75, 0x32, 0x0f, 0xe0, 0xf5, 0x26, 0x30, 0x02, 0x03, 0x12, 0x0f}},
{0x1286, 64, { 0xef, 0x30, 0x01, 0x07, 0xc2, 0x01, 0x12, 0x06, 0x3f, 0x80, 0xe2, 0x30, 0x08, 0xdf, 0xc2, 0x08, 0x12,
0x18, 0x2a, 0x80, 0xd8, 0x22, 0xe5, 0x13, 0x55, 0x16, 0x60, 0x6a, 0xe5, 0x15, 0x24, 0x3a, 0xf5,
0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x70, 0x5c, 0xe5, 0x16, 0xf4, 0x52, 0x13, 0xe5, 0x15,
0x24, 0x26, 0xff, 0xe4, 0x35, 0x14, 0xfe, 0xe4, 0xfd, 0x0f, 0xef, 0xaa, 0x06, 0x70, 0x01}},
{0x12c6, 64, { 0x0e, 0x14, 0xf5, 0x82, 0x8a, 0x83, 0xe0, 0xfc, 0x74, 0x80, 0x2d, 0xf5, 0x82, 0xe4, 0x34, 0x7b, 0xf5,
0x83, 0xec, 0xf0, 0x0d, 0xbd, 0x0b, 0xe2, 0x90, 0x7f, 0xc3, 0x74, 0x0b, 0xf0, 0xe5, 0x15, 0x24,
0x3a, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0x74, 0x10, 0xf0, 0xe5, 0x15, 0x24, 0x2e, 0xf5,
0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x15, 0x24, 0x2f, 0xf5, 0x82, 0xe4}},
{0x1306, 64, { 0x35, 0x14, 0xf5, 0x83, 0xe4, 0xf0, 0x22, 0xe5, 0x28, 0x45, 0x27, 0x60, 0x57, 0xae, 0x27, 0xaf, 0x28,
0xd3, 0xef, 0x94, 0x40, 0xee, 0x94, 0x00, 0x40, 0x04, 0x7e, 0x00, 0x7f, 0x40, 0xc3, 0xe5, 0x28,
0x9f, 0xf5, 0x28, 0xe5, 0x27, 0x9e, 0xf5, 0x27, 0xe4, 0xfd, 0xed, 0xc3, 0x9f, 0xe4, 0x9e, 0x50,
0x1f, 0x85, 0x34, 0x82, 0x85, 0x33, 0x83, 0xe0, 0xfc, 0x74, 0x00, 0x2d, 0xf5, 0x82, 0xe4}},
{0x1346, 64, { 0x34, 0x7f, 0xf5, 0x83, 0xec, 0xf0, 0x0d, 0x05, 0x34, 0xe5, 0x34, 0x70, 0x02, 0x05, 0x33, 0x80, 0xda,
0x90, 0x7f, 0xa9, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xac, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xb5,
0xef, 0xf0, 0x22, 0x90, 0x7f, 0xac, 0xe0, 0x54, 0xfe, 0xf0, 0xe4, 0x90, 0x7f, 0xb5, 0xf0, 0x22,
0x90, 0x7f, 0x98, 0x74, 0x0f, 0xf0, 0xe4, 0x90, 0x78, 0x4a, 0xf0, 0x90, 0x7f, 0x94, 0xf0}},
{0x1386, 64, { 0x90, 0x7f, 0x9d, 0x74, 0xff, 0xf0, 0xe4, 0x90, 0x7f, 0x97, 0xf0, 0x90, 0x78, 0x41, 0xf0, 0x90, 0x7f,
0x93, 0xf0, 0x90, 0x7f, 0x9c, 0x74, 0xff, 0xf0, 0x30, 0x00, 0x07, 0xe5, 0x29, 0x54, 0x0f, 0xff,
0x80, 0x02, 0x7f, 0x00, 0x90, 0x7f, 0x96, 0xef, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x1f, 0xf0, 0xe4,
0x90, 0x7f, 0x95, 0xf0, 0x90, 0x7f, 0x9e, 0x74, 0x3f, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0xdf}},
{0x13c6, 64, { 0xf0, 0x90, 0x7f, 0x92, 0xe0, 0x54, 0xfd, 0xf0, 0x22, 0x8f, 0x19, 0x05, 0x2d, 0xe5, 0x2d, 0xae, 0x2c,
0x70, 0x02, 0x05, 0x2c, 0x14, 0xf5, 0x82, 0x8e, 0x83, 0xe5, 0x19, 0xf0, 0x12, 0x18, 0xef, 0x05,
0x2d, 0xe5, 0x2d, 0xac, 0x2c, 0x70, 0x02, 0x05, 0x2c, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0,
0x15, 0x23, 0xe5, 0x23, 0x60, 0x1f, 0xe5, 0x15, 0x24, 0x38, 0xf5, 0x82, 0xe4, 0x35, 0x14}},
{0x1406, 64, { 0xf5, 0x83, 0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfe, 0x12, 0x18, 0xd3, 0x8f, 0x19, 0xee, 0x4f, 0xd0, 0x82,
0xd0, 0x83, 0xf0, 0x80, 0xb5, 0x22, 0x90, 0x78, 0x41, 0xe5, 0x11, 0xf0, 0x90, 0x78, 0x4f, 0x74,
0xc0, 0xf0, 0xe4, 0x90, 0x78, 0x50, 0xf0, 0xe5, 0x2c, 0x90, 0x78, 0x51, 0xf0, 0xae, 0x2c, 0xe5,
0x2d, 0x90, 0x78, 0x52, 0xf0, 0x90, 0x78, 0x54, 0xe5, 0x23, 0xf0, 0x90, 0x78, 0x57, 0x74}},
{0x1446, 64, { 0x04, 0xf0, 0x90, 0x7f, 0xe2, 0xe0, 0x44, 0x10, 0xf0, 0xe0, 0x54, 0xf7, 0xf0, 0xe4, 0x90, 0x78, 0x55,
0xf0, 0x90, 0x78, 0x55, 0xe0, 0x60, 0xfa, 0x22, 0x8f, 0x19, 0xe4, 0xf5, 0x1a, 0x75, 0x1b, 0xff,
0x75, 0x1c, 0x19, 0x75, 0x1d, 0x86, 0xab, 0x1b, 0xaa, 0x1c, 0xa9, 0x1d, 0x90, 0x00, 0x01, 0x12,
0x11, 0xbf, 0xb4, 0x03, 0x1d, 0xaf, 0x1a, 0x05, 0x1a, 0xef, 0xb5, 0x19, 0x01, 0x22, 0x12}},
{0x1486, 64, { 0x11, 0xa6, 0x7e, 0x00, 0x29, 0xff, 0xee, 0x3a, 0xa9, 0x07, 0x75, 0x1b, 0xff, 0xf5, 0x1c, 0x89, 0x1d,
0x80, 0xd4, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00, 0x22, 0x90, 0x78, 0x41, 0xe5, 0x11, 0xf0, 0xe5,
0x2c, 0x90, 0x78, 0x4f, 0xf0, 0xae, 0x2c, 0xe5, 0x2d, 0x90, 0x78, 0x50, 0xf0, 0x90, 0x78, 0x51,
0x74, 0xc0, 0xf0, 0xe4, 0x90, 0x78, 0x52, 0xf0, 0x90, 0x78, 0x54, 0xe5, 0x23, 0xf0, 0x90}},
{0x14c6, 64, { 0x78, 0x57, 0x74, 0x04, 0xf0, 0xe4, 0x90, 0x78, 0x55, 0xf0, 0x90, 0x78, 0x55, 0xe0, 0x60, 0xfa, 0x22,
0xe5, 0x15, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x14, 0x60, 0x0f, 0x14,
0x60, 0x13, 0x14, 0x60, 0x17, 0x80, 0x00, 0x90, 0x7f, 0xc7, 0xef, 0xf0, 0x80, 0x13, 0x90, 0x7f,
0xc9, 0xef, 0xf0, 0x80, 0x0c, 0x90, 0x7f, 0xcb, 0xef, 0xf0, 0x80, 0x05, 0x90, 0x7f, 0xcd}},
{0x1506, 64, { 0xef, 0xf0, 0xe5, 0x16, 0x42, 0x2a, 0x22, 0xe5, 0x15, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5,
0x83, 0xe0, 0x14, 0x60, 0x0f, 0x14, 0x60, 0x13, 0x14, 0x60, 0x17, 0x80, 0x00, 0x90, 0x7f, 0xb7,
0xef, 0xf0, 0x80, 0x13, 0x90, 0x7f, 0xb9, 0xef, 0xf0, 0x80, 0x0c, 0x90, 0x7f, 0xbb, 0xef, 0xf0,
0x80, 0x05, 0x90, 0x7f, 0xbd, 0xef, 0xf0, 0xe5, 0x16, 0x42, 0x2a, 0x22, 0xae, 0x07, 0xe4}},
{0x1546, 64, { 0xff, 0xe5, 0x15, 0x24, 0x32, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0x7f, 0xfd, 0x12,
0x16, 0x6b, 0x90, 0x78, 0x41, 0x74, 0xf1, 0xf0, 0x90, 0xc0, 0x00, 0xee, 0xf0, 0xe4, 0xe5, 0x15,
0x24, 0x32, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x44, 0x80, 0xfd, 0x12, 0x16, 0x6b,
0x22, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86}},
{0x1586, 64, { 0x75, 0x86, 0x00, 0xc0, 0xd0, 0x75, 0xd0, 0x08, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xa9, 0x74, 0x01, 0xf0,
0x12, 0x13, 0x0d, 0xd0, 0xd0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0,
0xf0, 0xd0, 0xe0, 0x32, 0x90, 0x78, 0x41, 0x74, 0xf3, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0,
0x90, 0x78, 0x41, 0x74, 0xf1, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x78, 0x41, 0x74}},
{0x15c6, 64, { 0xf3, 0xf0, 0xe5, 0x15, 0x24, 0x37, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0x7f, 0x90,
0xc0, 0x00, 0xf0, 0x22, 0x90, 0x78, 0x41, 0x74, 0xf3, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0,
0x90, 0x78, 0x41, 0x74, 0xf2, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x78, 0x41, 0x74, 0xf3,
0xf0, 0xe5, 0x15, 0x24, 0x37, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0x7f}},
{0x1606, 64, { 0x90, 0xc0, 0x00, 0xf0, 0x22, 0x90, 0x78, 0x41, 0x74, 0xf3, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0,
0x90, 0x78, 0x41, 0x74, 0xf4, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x78, 0x41, 0x74, 0xf3,
0xf0, 0xe5, 0x15, 0x24, 0x37, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0x7f, 0x90,
0xc0, 0x00, 0xf0, 0x22, 0x90, 0x78, 0x41, 0x74, 0xf3, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf}},
{0x1646, 64, { 0xf0, 0x90, 0x78, 0x41, 0x74, 0xf6, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x78, 0x41, 0x74, 0xf3,
0xf0, 0xe5, 0x15, 0x24, 0x37, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0x7f, 0x90,
0xc0, 0x00, 0xf0, 0x22, 0x90, 0x78, 0x41, 0x74, 0xf3, 0xf0, 0xe5, 0x15, 0x24, 0x37, 0xf5, 0x82,
0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x78, 0x41}},
{0x1686, 64, { 0x74, 0xf7, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x78, 0x41, 0x74, 0xf5, 0xf0, 0x90, 0xc0, 0x00,
0xed, 0xf0, 0x22, 0xe5, 0x15, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x14,
0x60, 0x0e, 0x14, 0x60, 0x11, 0x14, 0x60, 0x14, 0x80, 0x00, 0x90, 0x7f, 0xc6, 0xe0, 0xff, 0x22,
0x90, 0x7f, 0xc8, 0xe0, 0xff, 0x22, 0x90, 0x7f, 0xca, 0xe0, 0xff, 0x22, 0x90, 0x7f, 0xcc}},
{0x16c6, 64, { 0xe0, 0xff, 0x22, 0xe5, 0x15, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x14, 0x60,
0x0e, 0x14, 0x60, 0x11, 0x14, 0x60, 0x14, 0x80, 0x00, 0x90, 0x7f, 0xb6, 0xe0, 0xff, 0x22, 0x90,
0x7f, 0xb8, 0xe0, 0xff, 0x22, 0x90, 0x7f, 0xba, 0xe0, 0xff, 0x22, 0x90, 0x7f, 0xbc, 0xe0, 0xff,
0x22, 0xe5, 0x15, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0, 0x14, 0x60}},
{0x1706, 64, { 0x0e, 0x14, 0x60, 0x11, 0x14, 0x60, 0x14, 0x80, 0x00, 0x90, 0x7f, 0xc7, 0xe0, 0xff, 0x22, 0x90, 0x7f,
0xc9, 0xe0, 0xff, 0x22, 0x90, 0x7f, 0xcb, 0xe0, 0xff, 0x22, 0x90, 0x7f, 0xcd, 0xe0, 0xff, 0x22,
0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x90,
0x7f, 0xc4, 0xe4, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x04, 0xf0, 0xd0, 0x86}},
{0x1746, 64, { 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32, 0x90, 0x7b, 0x41, 0xe0, 0xf5, 0x36,
0x43, 0x13, 0x10, 0xa3, 0xe0, 0x60, 0x09, 0x90, 0x7f, 0xd7, 0x74, 0x17, 0xf0, 0x74, 0x37, 0xf0,
0x90, 0x7b, 0x43, 0xe0, 0xf5, 0x37, 0xa3, 0xe0, 0x54, 0xf0, 0xf5, 0x29, 0xe0, 0x60, 0x02, 0xd2,
0x0a, 0x22, 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75}},
{0x1786, 64, { 0x86, 0x00, 0xd2, 0x01, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x01, 0xf0, 0xd0, 0x86, 0xd0, 0x84,
0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32, 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0,
0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xd2, 0x08, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab,
0x74, 0x08, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0}},
{0x17c6, 64, { 0x32, 0x12, 0x18, 0xb7, 0xae, 0x07, 0x12, 0x18, 0xb7, 0xad, 0x07, 0xee, 0x6d, 0x60, 0x10, 0x12, 0x18,
0xb7, 0xae, 0x07, 0xee, 0x6d, 0x60, 0x07, 0x12, 0x18, 0xb7, 0xad, 0x07, 0x80, 0xec, 0xaf, 0x06,
0x22, 0x74, 0x00, 0xf5, 0x86, 0x90, 0xfd, 0xa5, 0x7c, 0x05, 0xa3, 0xe5, 0x82, 0x45, 0x83, 0x70,
0xf9, 0x22, 0x90, 0x7f, 0xd6, 0xe0, 0x44, 0x80, 0xf0, 0x43, 0x87, 0x01, 0x00, 0x00, 0x00}},
{0x1806, 64, { 0x00, 0x00, 0x22, 0x90, 0x7f, 0xd6, 0xe0, 0x44, 0x04, 0xf0, 0xe0, 0x44, 0x08, 0xf0, 0x30, 0x0b, 0x04,
0xe0, 0x44, 0x02, 0xf0, 0x7f, 0xf4, 0x7e, 0x01, 0x12, 0x18, 0x60, 0x90, 0x7f, 0xd6, 0xe0, 0x54,
0xf7, 0xf0, 0x22, 0x12, 0x13, 0x77, 0x12, 0x17, 0xf9, 0x90, 0x7f, 0xd6, 0xe0, 0x30, 0xe7, 0x0a,
0x7f, 0x05, 0x7e, 0x00, 0x12, 0x18, 0x60, 0x12, 0x18, 0x93, 0x12, 0x0a, 0xce, 0x22, 0x03}},
{0x1846, 64, { 0x35, 0x80, 0x00, 0x00, 0x03, 0x2e, 0x81, 0x00, 0x00, 0xc1, 0x85, 0xc1, 0x81, 0xc1, 0x08, 0xc1, 0x00,
0xc1, 0x06, 0x01, 0x22, 0x00, 0x01, 0x24, 0x00, 0x00, 0x8e, 0x17, 0x8f, 0x18, 0xe5, 0x18, 0x15,
0x18, 0xae, 0x17, 0x70, 0x02, 0x15, 0x17, 0x4e, 0x60, 0x08, 0x12, 0x17, 0xe8, 0x12, 0x17, 0xe8,
0x80, 0xeb, 0x22, 0xe5, 0x15, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x14, 0xf5, 0x83, 0xe0}},
{0x1886, 64, { 0x04, 0xff, 0x44, 0x10, 0x90, 0x7f, 0xd7, 0xf0, 0xef, 0x44, 0x30, 0xf0, 0x22, 0x90, 0x7f, 0xd6, 0xe0,
0x44, 0x01, 0xf0, 0x7f, 0x0d, 0x7e, 0x00, 0x12, 0x18, 0x60, 0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xfe,
0xf0, 0x22, 0xe5, 0x11, 0x24, 0x02, 0x90, 0x78, 0x41, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22,
0xe5, 0x11, 0x24, 0x03, 0x90, 0x78, 0x41, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22, 0xe5}},
{0x18c6, 64, { 0x11, 0x24, 0x04, 0x90, 0x78, 0x41, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22, 0xe5, 0x11, 0x24, 0x05,
0x90, 0x78, 0x41, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22, 0xe5, 0x11, 0x24, 0x06, 0x90, 0x78,
0x41, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22, 0x90, 0x78, 0x41, 0xe5, 0x11, 0xf0, 0x90, 0xc0,
0x00, 0xe0, 0xff, 0x22, 0x53, 0xd8, 0xef, 0x32, 0x00, 0x12, 0x01, 0x10, 0x01, 0xff, 0xff}},
{0x1906, 64, { 0xff, 0x40, 0xcd, 0x06, 0x2a, 0x01, 0x00, 0x00, 0x01, 0x02, 0x00, 0x04, 0x09, 0x02, 0x74, 0x00, 0x01,
0x01, 0x00, 0xa0, 0x32, 0x09, 0x04, 0x00, 0x00, 0x0e, 0xff, 0x00, 0x00, 0x00, 0x07, 0x05, 0x01,
0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x02, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x03, 0x02, 0x40,
0x00, 0x00, 0x07, 0x05, 0x04, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x05, 0x02, 0x40, 0x00}},
{0x1946, 64, { 0x00, 0x07, 0x05, 0x06, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x07, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05,
0x81, 0x02, 0x40, 0x00, 0x01, 0x07, 0x05, 0x82, 0x02, 0x40, 0x00, 0x01, 0x07, 0x05, 0x83, 0x02,
0x40, 0x00, 0x01, 0x07, 0x05, 0x84, 0x02, 0x40, 0x00, 0x01, 0x07, 0x05, 0x85, 0x02, 0x40, 0x00,
0x01, 0x07, 0x05, 0x86, 0x02, 0x40, 0x00, 0x01, 0x07, 0x05, 0x87, 0x02, 0x40, 0x00, 0x01}},
{0x1986, 64, { 0x04, 0x03, 0x09, 0x04, 0x48, 0x03, 0x4b, 0x00, 0x65, 0x00, 0x79, 0x00, 0x73, 0x00, 0x70, 0x00, 0x61,
0x00, 0x6e, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x61, 0x00, 0x20, 0x00, 0x64, 0x00, 0x69, 0x00, 0x76,
0x00, 0x69, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66,
0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x53, 0x00, 0x79, 0x00}},
{0x19c6, 64, { 0x73, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x2e, 0x00, 0x24, 0x03, 0x4b, 0x00, 0x65,
0x00, 0x79, 0x00, 0x73, 0x00, 0x70, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x55, 0x00, 0x53,
0x00, 0x41, 0x00, 0x2d, 0x00, 0x34, 0x00, 0x39, 0x00, 0x57, 0x00, 0x4c, 0x00, 0x43, 0x00, 0x22,
0x03, 0x55, 0x00, 0x53, 0x00, 0x41, 0x00, 0x2d, 0x00, 0x36, 0x00, 0x35, 0x00, 0x20, 0x00}},
{0x1a06, 64, { 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x6a, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x33, 0x00, 0x31,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
{0x1a46, 64, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
{0x1a86, 64, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
{0x1ac6, 64, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x17, 0x79, 0x00, 0x02, 0x1b}},
{0x1b06, 21, { 0x04, 0x00, 0x02, 0x17, 0x27, 0x00, 0x02, 0x17, 0xa0, 0x00, 0x02, 0x1b, 0x10, 0x00, 0x02, 0x1b, 0x14,
0x00, 0x02, 0x15, 0x78}},
{0xffff, 0, { 0x00}},
};
...@@ -166,7 +166,7 @@ struct klsi_105_private { ...@@ -166,7 +166,7 @@ struct klsi_105_private {
unsigned long line_state; /* modem line settings */ unsigned long line_state; /* modem line settings */
/* write pool */ /* write pool */
struct urb * write_urb_pool[NUM_URBS]; struct urb * write_urb_pool[NUM_URBS];
spinlock_t write_urb_pool_lock; spinlock_t lock;
unsigned long bytes_in; unsigned long bytes_in;
unsigned long bytes_out; unsigned long bytes_out;
}; };
...@@ -284,7 +284,7 @@ static int klsi_105_startup (struct usb_serial *serial) ...@@ -284,7 +284,7 @@ static int klsi_105_startup (struct usb_serial *serial)
priv->bytes_out = 0; priv->bytes_out = 0;
usb_set_serial_port_data(&serial->port[i], priv); 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++) { for (i=0; i<NUM_URBS; i++) {
struct urb* urb = usb_alloc_urb(0, GFP_KERNEL); struct urb* urb = usb_alloc_urb(0, GFP_KERNEL);
...@@ -326,7 +326,7 @@ static void klsi_105_shutdown (struct usb_serial *serial) ...@@ -326,7 +326,7 @@ static void klsi_105_shutdown (struct usb_serial *serial)
/* kill our write urb pool */ /* kill our write urb pool */
int j; int j;
struct urb **write_urbs = priv->write_urb_pool; 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++) { for (j = 0; j < NUM_URBS; j++) {
if (write_urbs[j]) { if (write_urbs[j]) {
...@@ -343,8 +343,7 @@ static void klsi_105_shutdown (struct usb_serial *serial) ...@@ -343,8 +343,7 @@ static void klsi_105_shutdown (struct usb_serial *serial)
} }
} }
spin_unlock_irqrestore (&priv->write_urb_pool_lock, spin_unlock_irqrestore (&priv->lock, flags);
flags);
kfree(priv); kfree(priv);
usb_set_serial_port_data(&serial->port[i], NULL); 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) ...@@ -360,6 +359,8 @@ static int klsi_105_open (struct usb_serial_port *port, struct file *filp)
int rc; int rc;
int i; int i;
unsigned long line_state; unsigned long line_state;
struct klsi_105_port_settings cfg;
unsigned long flags;
dbg("%s port %d", __FUNCTION__, port->number); dbg("%s port %d", __FUNCTION__, port->number);
...@@ -374,21 +375,27 @@ static int klsi_105_open (struct usb_serial_port *port, struct file *filp) ...@@ -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 * Then read the modem line control and store values in
* priv->line_state. * priv->line_state.
*/ */
priv->cfg.pktlen = 5; cfg.pktlen = 5;
priv->cfg.baudrate = kl5kusb105a_sio_b9600; cfg.baudrate = kl5kusb105a_sio_b9600;
priv->cfg.databits = kl5kusb105a_dtb_8; cfg.databits = kl5kusb105a_dtb_8;
priv->cfg.unknown1 = 0; cfg.unknown1 = 0;
priv->cfg.unknown2 = 1; cfg.unknown2 = 1;
klsi_105_chg_port_settings(serial, &(priv->cfg)); klsi_105_chg_port_settings(serial, &cfg);
/* set up termios structure */ /* set up termios structure */
spin_lock_irqsave (&priv->lock, flags);
priv->termios.c_iflag = port->tty->termios->c_iflag; priv->termios.c_iflag = port->tty->termios->c_iflag;
priv->termios.c_oflag = port->tty->termios->c_oflag; priv->termios.c_oflag = port->tty->termios->c_oflag;
priv->termios.c_cflag = port->tty->termios->c_cflag; priv->termios.c_cflag = port->tty->termios->c_cflag;
priv->termios.c_lflag = port->tty->termios->c_lflag; priv->termios.c_lflag = port->tty->termios->c_lflag;
for (i=0; i<NCCS; i++) for (i=0; i<NCCS; i++)
priv->termios.c_cc[i] = port->tty->termios->c_cc[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 */ /* READ_ON and urb submission */
usb_fill_bulk_urb(port->read_urb, serial->dev, 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) ...@@ -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); rc = klsi_105_get_line_state(serial, &line_state);
if (rc >= 0) { if (rc >= 0) {
spin_lock_irqsave (&priv->lock, flags);
priv->line_state = line_state; priv->line_state = line_state;
spin_unlock_irqrestore (&priv->lock, flags);
dbg("%s - read line state 0x%lx", __FUNCTION__, line_state); dbg("%s - read line state 0x%lx", __FUNCTION__, line_state);
retval = 0; retval = 0;
} else } else
...@@ -492,7 +501,7 @@ static int klsi_105_write (struct usb_serial_port *port, int from_user, ...@@ -492,7 +501,7 @@ static int klsi_105_write (struct usb_serial_port *port, int from_user,
unsigned long flags; unsigned long flags;
int i; int i;
/* since the pool is per-port we might not need the spin lock !? */ /* 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++) { for (i=0; i<NUM_URBS; i++) {
if (priv->write_urb_pool[i]->status != -EINPROGRESS) { if (priv->write_urb_pool[i]->status != -EINPROGRESS) {
urb = priv->write_urb_pool[i]; urb = priv->write_urb_pool[i];
...@@ -500,7 +509,7 @@ static int klsi_105_write (struct usb_serial_port *port, int from_user, ...@@ -500,7 +509,7 @@ static int klsi_105_write (struct usb_serial_port *port, int from_user,
break; break;
} }
} }
spin_unlock_irqrestore (&priv->write_urb_pool_lock, flags); spin_unlock_irqrestore (&priv->lock, flags);
if (urb==NULL) { if (urb==NULL) {
dbg("%s - no more free urbs", __FUNCTION__); dbg("%s - no more free urbs", __FUNCTION__);
...@@ -552,6 +561,7 @@ static int klsi_105_write (struct usb_serial_port *port, int from_user, ...@@ -552,6 +561,7 @@ static int klsi_105_write (struct usb_serial_port *port, int from_user,
count -= size; count -= size;
} }
exit: exit:
/* lockless, but it's for debug info only... */
priv->bytes_out+=bytes_sent; priv->bytes_out+=bytes_sent;
return bytes_sent; /* that's how much we wrote */ 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) ...@@ -588,7 +598,7 @@ static int klsi_105_chars_in_buffer (struct usb_serial_port *port)
unsigned long flags; unsigned long flags;
struct klsi_105_private *priv = usb_get_serial_port_data(port); 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) { for (i = 0; i < NUM_URBS; ++i) {
if (priv->write_urb_pool[i]->status == -EINPROGRESS) { if (priv->write_urb_pool[i]->status == -EINPROGRESS) {
...@@ -596,7 +606,7 @@ static int klsi_105_chars_in_buffer (struct usb_serial_port *port) ...@@ -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); dbg("%s - returns %d", __FUNCTION__, chars);
return (chars); return (chars);
...@@ -609,14 +619,14 @@ static int klsi_105_write_room (struct usb_serial_port *port) ...@@ -609,14 +619,14 @@ static int klsi_105_write_room (struct usb_serial_port *port)
int room = 0; int room = 0;
struct klsi_105_private *priv = usb_get_serial_port_data(port); 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) { for (i = 0; i < NUM_URBS; ++i) {
if (priv->write_urb_pool[i]->status != -EINPROGRESS) { if (priv->write_urb_pool[i]->status != -EINPROGRESS) {
room += URB_TRANSFER_BUFFER_SIZE; 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); dbg("%s - returns %d", __FUNCTION__, room);
return (room); return (room);
...@@ -690,6 +700,8 @@ static void klsi_105_read_bulk_callback (struct urb *urb, struct pt_regs *regs) ...@@ -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_insert_flip_char(tty, ((__u8*) data)[i], 0);
} }
tty_flip_buffer_push(tty); tty_flip_buffer_push(tty);
/* again lockless, but debug info only */
priv->bytes_in += bytes_sent; priv->bytes_in += bytes_sent;
} }
/* Continue trying to always read */ /* Continue trying to always read */
...@@ -715,6 +727,11 @@ static void klsi_105_set_termios (struct usb_serial_port *port, ...@@ -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 old_iflag = old_termios->c_iflag;
unsigned int cflag = port->tty->termios->c_cflag; unsigned int cflag = port->tty->termios->c_cflag;
unsigned int old_cflag = old_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 * Update baud rate
...@@ -838,9 +855,11 @@ static void klsi_105_set_termios (struct usb_serial_port *port, ...@@ -838,9 +855,11 @@ static void klsi_105_set_termios (struct usb_serial_port *port,
#endif #endif
; ;
} }
memcpy (&cfg, &priv->cfg, sizeof(cfg));
spin_unlock_irqrestore (&priv->lock, flags);
/* now commit changes to device */ /* now commit changes to device */
klsi_105_chg_port_settings(serial, &(priv->cfg)); klsi_105_chg_port_settings(serial, &cfg);
} /* klsi_105_set_termios */ } /* klsi_105_set_termios */
...@@ -866,6 +885,7 @@ static int klsi_105_ioctl (struct usb_serial_port *port, struct file * file, ...@@ -866,6 +885,7 @@ static int klsi_105_ioctl (struct usb_serial_port *port, struct file * file,
struct usb_serial *serial = port->serial; struct usb_serial *serial = port->serial;
struct klsi_105_private *priv = usb_get_serial_port_data(port); struct klsi_105_private *priv = usb_get_serial_port_data(port);
int mask; int mask;
unsigned long flags;
dbg("%scmd=0x%x", __FUNCTION__, cmd); dbg("%scmd=0x%x", __FUNCTION__, cmd);
...@@ -881,11 +901,12 @@ static int klsi_105_ioctl (struct usb_serial_port *port, struct file * file, ...@@ -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); err("Reading line control failed (error = %d)", rc);
/* better return value? EAGAIN? */ /* better return value? EAGAIN? */
return -ENOIOCTLCMD; return -ENOIOCTLCMD;
} else { }
spin_lock_irqsave (&priv->lock, flags);
priv->line_state = line_state; priv->line_state = line_state;
spin_unlock_irqrestore (&priv->lock, flags);
dbg("%s - read line state 0x%lx", __FUNCTION__, line_state); dbg("%s - read line state 0x%lx", __FUNCTION__, line_state);
} return put_user(line_state, (unsigned long *) arg);
return put_user(priv->line_state, (unsigned long *) arg);
}; };
case TIOCMSET: /* Turns on and off the lines as specified by the mask */ 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 = { ...@@ -171,6 +171,7 @@ static struct usb_serial_device_type mct_u232_device = {
struct mct_u232_private { struct mct_u232_private {
spinlock_t lock;
unsigned long control_state; /* Modem Line Setting (TIOCM) */ unsigned long control_state; /* Modem Line Setting (TIOCM) */
unsigned char last_lcr; /* Line Control Register */ unsigned char last_lcr; /* Line Control Register */
unsigned char last_lsr; /* Line Status Register */ unsigned char last_lsr; /* Line Status Register */
...@@ -306,8 +307,9 @@ static int mct_u232_startup (struct usb_serial *serial) ...@@ -306,8 +307,9 @@ static int mct_u232_startup (struct usb_serial *serial)
/* allocate the private data structure */ /* allocate the private data structure */
priv = kmalloc(sizeof(struct mct_u232_private), GFP_KERNEL); priv = kmalloc(sizeof(struct mct_u232_private), GFP_KERNEL);
if (!priv) if (!priv)
return (-1); /* error */ return -ENOMEM;
/* set initial values for control structures */ /* set initial values for control structures */
spin_lock_init(&priv->lock);
priv->control_state = 0; priv->control_state = 0;
priv->last_lsr = 0; priv->last_lsr = 0;
priv->last_msr = 0; priv->last_msr = 0;
...@@ -339,6 +341,10 @@ static int mct_u232_open (struct usb_serial_port *port, struct file *filp) ...@@ -339,6 +341,10 @@ static int mct_u232_open (struct usb_serial_port *port, struct file *filp)
struct usb_serial *serial = port->serial; struct usb_serial *serial = port->serial;
struct mct_u232_private *priv = usb_get_serial_port_data(port); struct mct_u232_private *priv = usb_get_serial_port_data(port);
int retval = 0; 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); dbg("%s port %d", __FUNCTION__, port->number);
...@@ -355,20 +361,27 @@ static int mct_u232_open (struct usb_serial_port *port, struct file *filp) ...@@ -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 * sure if this is really necessary. But it should not harm
* either. * either.
*/ */
spin_lock_irqsave(&priv->lock, flags);
if (port->tty->termios->c_cflag & CBAUD) if (port->tty->termios->c_cflag & CBAUD)
priv->control_state = TIOCM_DTR | TIOCM_RTS; priv->control_state = TIOCM_DTR | TIOCM_RTS;
else else
priv->control_state = 0; priv->control_state = 0;
mct_u232_set_modem_ctrl(serial, priv->control_state);
priv->last_lcr = (MCT_U232_DATA_BITS_8 | priv->last_lcr = (MCT_U232_DATA_BITS_8 |
MCT_U232_PARITY_NONE | MCT_U232_PARITY_NONE |
MCT_U232_STOP_BITS_1); 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 */ /* 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); mct_u232_msr_to_state(&priv->control_state, priv->last_msr);
spin_unlock_irqrestore(&priv->lock, flags);
{ {
/* Puh, that's dirty */ /* Puh, that's dirty */
...@@ -523,6 +536,7 @@ static void mct_u232_read_int_callback (struct urb *urb, struct pt_regs *regs) ...@@ -523,6 +536,7 @@ static void mct_u232_read_int_callback (struct urb *urb, struct pt_regs *regs)
struct tty_struct *tty; struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer; unsigned char *data = urb->transfer_buffer;
int status; int status;
unsigned long flags;
dbg("%s - port %d", __FUNCTION__, port->number); 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) ...@@ -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 * The interrupt-in pipe signals exceptional conditions (modem line
* signal changes and errors). data[0] holds MSR, data[1] holds LSR. * 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]; priv->last_msr = data[MCT_U232_MSR_INDEX];
/* Record Control Line states */ /* Record Control Line states */
...@@ -597,6 +612,7 @@ static void mct_u232_read_int_callback (struct urb *urb, struct pt_regs *regs) ...@@ -597,6 +612,7 @@ static void mct_u232_read_int_callback (struct urb *urb, struct pt_regs *regs)
} }
} }
#endif #endif
spin_unlock_irqrestore(&priv->lock, flags);
exit: exit:
status = usb_submit_urb (urb, GFP_ATOMIC); status = usb_submit_urb (urb, GFP_ATOMIC);
if (status) if (status)
...@@ -614,6 +630,15 @@ static void mct_u232_set_termios (struct usb_serial_port *port, ...@@ -614,6 +630,15 @@ static void mct_u232_set_termios (struct usb_serial_port *port,
unsigned int old_iflag = old_termios->c_iflag; unsigned int old_iflag = old_termios->c_iflag;
unsigned int cflag = port->tty->termios->c_cflag; unsigned int cflag = port->tty->termios->c_cflag;
unsigned int old_cflag = old_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 * Update baud rate
...@@ -622,12 +647,12 @@ static void mct_u232_set_termios (struct usb_serial_port *port, ...@@ -622,12 +647,12 @@ static void mct_u232_set_termios (struct usb_serial_port *port,
/* reassert DTR and (maybe) RTS on transition from B0 */ /* reassert DTR and (maybe) RTS on transition from B0 */
if( (old_cflag & CBAUD) == B0 ) { if( (old_cflag & CBAUD) == B0 ) {
dbg("%s: baud was B0", __FUNCTION__); dbg("%s: baud was B0", __FUNCTION__);
priv->control_state |= TIOCM_DTR; control_state |= TIOCM_DTR;
/* don't set RTS if using hardware flow control */ /* don't set RTS if using hardware flow control */
if (!(old_cflag & CRTSCTS)) { 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) { switch(cflag & CBAUD) {
...@@ -659,8 +684,8 @@ static void mct_u232_set_termios (struct usb_serial_port *port, ...@@ -659,8 +684,8 @@ static void mct_u232_set_termios (struct usb_serial_port *port,
if ((cflag & CBAUD) == B0 ) { if ((cflag & CBAUD) == B0 ) {
dbg("%s: baud is B0", __FUNCTION__); dbg("%s: baud is B0", __FUNCTION__);
/* Drop RTS and DTR */ /* Drop RTS and DTR */
priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS); control_state &= ~(TIOCM_DTR | TIOCM_RTS);
mct_u232_set_modem_ctrl(serial, priv->control_state); mct_u232_set_modem_ctrl(serial, control_state);
} }
} }
...@@ -672,36 +697,36 @@ static void mct_u232_set_termios (struct usb_serial_port *port, ...@@ -672,36 +697,36 @@ static void mct_u232_set_termios (struct usb_serial_port *port,
|| (cflag & CSTOPB) != (old_cflag & CSTOPB) ) { || (cflag & CSTOPB) != (old_cflag & CSTOPB) ) {
priv->last_lcr = 0; last_lcr = 0;
/* set the parity */ /* set the parity */
if (cflag & PARENB) if (cflag & PARENB)
priv->last_lcr |= (cflag & PARODD) ? last_lcr |= (cflag & PARODD) ?
MCT_U232_PARITY_ODD : MCT_U232_PARITY_EVEN; MCT_U232_PARITY_ODD : MCT_U232_PARITY_EVEN;
else else
priv->last_lcr |= MCT_U232_PARITY_NONE; last_lcr |= MCT_U232_PARITY_NONE;
/* set the number of data bits */ /* set the number of data bits */
switch (cflag & CSIZE) { switch (cflag & CSIZE) {
case CS5: case CS5:
priv->last_lcr |= MCT_U232_DATA_BITS_5; break; last_lcr |= MCT_U232_DATA_BITS_5; break;
case CS6: case CS6:
priv->last_lcr |= MCT_U232_DATA_BITS_6; break; last_lcr |= MCT_U232_DATA_BITS_6; break;
case CS7: case CS7:
priv->last_lcr |= MCT_U232_DATA_BITS_7; break; last_lcr |= MCT_U232_DATA_BITS_7; break;
case CS8: case CS8:
priv->last_lcr |= MCT_U232_DATA_BITS_8; break; last_lcr |= MCT_U232_DATA_BITS_8; break;
default: default:
err("CSIZE was not CS5-CS8, using default of 8"); 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; break;
} }
/* set the number of stop bits */ /* 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_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, ...@@ -714,11 +739,17 @@ static void mct_u232_set_termios (struct usb_serial_port *port,
/* Drop DTR/RTS if no flow control otherwise assert */ /* Drop DTR/RTS if no flow control otherwise assert */
if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS) ) if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS) )
priv->control_state |= TIOCM_DTR | TIOCM_RTS; control_state |= TIOCM_DTR | TIOCM_RTS;
else else
priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS); control_state &= ~(TIOCM_DTR | TIOCM_RTS);
mct_u232_set_modem_ctrl(serial, priv->control_state); 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 */ } /* mct_u232_set_termios */
...@@ -726,10 +757,15 @@ static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state ) ...@@ -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 usb_serial *serial = port->serial;
struct mct_u232_private *priv = usb_get_serial_port_data(port); 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); 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) if (break_state)
lcr |= MCT_U232_SET_BREAK; lcr |= MCT_U232_SET_BREAK;
...@@ -743,13 +779,19 @@ static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file, ...@@ -743,13 +779,19 @@ static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file,
struct usb_serial *serial = port->serial; struct usb_serial *serial = port->serial;
struct mct_u232_private *priv = usb_get_serial_port_data(port); struct mct_u232_private *priv = usb_get_serial_port_data(port);
int mask; int mask;
unsigned long control_state;
unsigned long flags;
dbg("%scmd=0x%x", __FUNCTION__, cmd); 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 */ /* Based on code from acm.c and others */
switch (cmd) { switch (cmd) {
case TIOCMGET: case TIOCMGET:
return put_user(priv->control_state, (unsigned long *) arg); return put_user(control_state, (unsigned long *) arg);
break; break;
case TIOCMSET: /* Turns on and off the lines as specified by the mask */ 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, ...@@ -762,20 +804,24 @@ static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file,
/* RTS needs set */ /* RTS needs set */
if( ((cmd == TIOCMSET) && (mask & TIOCM_RTS)) || if( ((cmd == TIOCMSET) && (mask & TIOCM_RTS)) ||
(cmd == TIOCMBIS) ) (cmd == TIOCMBIS) )
priv->control_state |= TIOCM_RTS; control_state |= TIOCM_RTS;
else else
priv->control_state &= ~TIOCM_RTS; control_state &= ~TIOCM_RTS;
} }
if ((cmd == TIOCMSET) || (mask & TIOCM_DTR)) { if ((cmd == TIOCMSET) || (mask & TIOCM_DTR)) {
/* DTR needs set */ /* DTR needs set */
if( ((cmd == TIOCMSET) && (mask & TIOCM_DTR)) || if( ((cmd == TIOCMSET) && (mask & TIOCM_DTR)) ||
(cmd == TIOCMBIS) ) (cmd == TIOCMBIS) )
priv->control_state |= TIOCM_DTR; control_state |= TIOCM_DTR;
else 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; break;
case TIOCMIWAIT: case TIOCMIWAIT:
......
...@@ -149,6 +149,7 @@ static struct usb_serial_device_type pl2303_device = { ...@@ -149,6 +149,7 @@ static struct usb_serial_device_type pl2303_device = {
}; };
struct pl2303_private { struct pl2303_private {
spinlock_t lock;
u8 line_control; u8 line_control;
u8 termios_initialized; u8 termios_initialized;
}; };
...@@ -164,6 +165,7 @@ static int pl2303_startup (struct usb_serial *serial) ...@@ -164,6 +165,7 @@ static int pl2303_startup (struct usb_serial *serial)
if (!priv) if (!priv)
return -ENOMEM; return -ENOMEM;
memset (priv, 0x00, sizeof (struct pl2303_private)); memset (priv, 0x00, sizeof (struct pl2303_private));
spin_lock_init(&priv->lock);
usb_set_serial_port_data(&serial->port[i], priv); usb_set_serial_port_data(&serial->port[i], priv);
} }
return 0; return 0;
...@@ -223,18 +225,21 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol ...@@ -223,18 +225,21 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol
int baud; int baud;
int i; 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)) { if ((!port->tty) || (!port->tty->termios)) {
dbg("%s - no tty structures", __FUNCTION__); dbg("%s - no tty structures", __FUNCTION__);
return; return;
} }
spin_lock(&priv->lock);
if (!priv->termios_initialized) { if (!priv->termios_initialized) {
*(port->tty->termios) = tty_std_termios; *(port->tty->termios) = tty_std_termios;
port->tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; port->tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
priv->termios_initialized = 1; priv->termios_initialized = 1;
} }
spin_unlock(&priv->lock);
cflag = port->tty->termios->c_cflag; cflag = port->tty->termios->c_cflag;
/* check that they really want us to change something */ /* check that they really want us to change something */
if (old_termios) { if (old_termios) {
...@@ -341,11 +346,16 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol ...@@ -341,11 +346,16 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol
dbg ("0x21:0x20:0:0 %d", i); dbg ("0x21:0x20:0:0 %d", i);
if (cflag && CBAUD) { if (cflag && CBAUD) {
u8 control;
spin_lock (&priv->lock);
if ((cflag && CBAUD) == B0) if ((cflag && CBAUD) == B0)
priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS); priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
else else
priv->line_control |= (CONTROL_DTR | CONTROL_RTS); 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; buf[0] = buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0;
...@@ -444,18 +454,6 @@ static void pl2303_close (struct usb_serial_port *port, struct file *filp) ...@@ -444,18 +454,6 @@ static void pl2303_close (struct usb_serial_port *port, struct file *filp)
dbg("%s - port %d", __FUNCTION__, port->number); 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 */ /* shutdown our urbs */
dbg("%s - shutting down urbs", __FUNCTION__); dbg("%s - shutting down urbs", __FUNCTION__);
result = usb_unlink_urb (port->write_urb); result = usb_unlink_urb (port->write_urb);
...@@ -475,17 +473,31 @@ static void pl2303_close (struct usb_serial_port *port, struct file *filp) ...@@ -475,17 +473,31 @@ static void pl2303_close (struct usb_serial_port *port, struct file *filp)
dbg("%s - usb_unlink_urb (interrupt_in_urb)" dbg("%s - usb_unlink_urb (interrupt_in_urb)"
" failed with reason: %d", __FUNCTION__, " failed with reason: %d", __FUNCTION__,
result); 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) 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); struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned int arg; unsigned int arg;
u8 control;
if (copy_from_user(&arg, value, sizeof(int))) if (copy_from_user(&arg, value, sizeof(int)))
return -EFAULT; return -EFAULT;
spin_lock (&priv->lock);
switch (cmd) { switch (cmd) {
case TIOCMBIS: case TIOCMBIS:
if (arg & TIOCM_RTS) if (arg & TIOCM_RTS)
...@@ -509,16 +521,22 @@ static int set_modem_info (struct usb_serial_port *port, unsigned int cmd, unsig ...@@ -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); priv->line_control |= ((arg & TIOCM_DTR) ? CONTROL_DTR : 0);
break; 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) static int get_modem_info (struct usb_serial_port *port, unsigned int *value)
{ {
struct pl2303_private *priv = usb_get_serial_port_data(port); struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned int mcr = priv->line_control; unsigned int mcr;
unsigned int result; unsigned int result;
spin_lock (&priv->lock);
mcr = priv->line_control;
spin_unlock (&priv->lock);
result = ((mcr & CONTROL_DTR) ? TIOCM_DTR : 0) result = ((mcr & CONTROL_DTR) ? TIOCM_DTR : 0)
| ((mcr & CONTROL_RTS) ? TIOCM_RTS : 0); | ((mcr & CONTROL_RTS) ? TIOCM_RTS : 0);
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* USB HandSpring Visor, Palm m50x, and Sony Clie driver * USB HandSpring Visor, Palm m50x, and Sony Clie driver
* (supports all of the Palm OS USB devices) * (supports all of the Palm OS USB devices)
* *
* Copyright (C) 1999 - 2002 * Copyright (C) 1999 - 2003
* Greg Kroah-Hartman (greg@kroah.com) * Greg Kroah-Hartman (greg@kroah.com)
* *
* This program is free software; you can redistribute it and/or modify * 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 ...@@ -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 [] = { static struct usb_device_id id_table [] = {
{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID), { 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), { 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), { 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), { 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), { 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), { 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), { 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), { 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), { 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), { 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), { 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), { 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), { 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_4_1_ID) },
{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NX60_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 */ { } /* Terminating entry */
}; };
...@@ -374,14 +374,14 @@ static void visor_close (struct usb_serial_port *port, struct file * filp) ...@@ -374,14 +374,14 @@ static void visor_close (struct usb_serial_port *port, struct file * filp)
if (!serial) if (!serial)
return; return;
if (serial->dev) { /* shutdown our urbs */
/* only send a shutdown message if the usb_unlink_urb (port->read_urb);
* device is still here */ 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); transfer_buffer = kmalloc (0x12, GFP_KERNEL);
if (!transfer_buffer) { 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_control_msg (serial->dev,
usb_rcvctrlpipe(serial->dev, 0), usb_rcvctrlpipe(serial->dev, 0),
VISOR_CLOSE_NOTIFICATION, 0xc2, VISOR_CLOSE_NOTIFICATION, 0xc2,
...@@ -389,12 +389,7 @@ static void visor_close (struct usb_serial_port *port, struct file * filp) ...@@ -389,12 +389,7 @@ static void visor_close (struct usb_serial_port *port, struct file * filp)
transfer_buffer, 0x12, 300); transfer_buffer, 0x12, 300);
kfree (transfer_buffer); 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);
}
/* Uncomment the following line if you want to see some statistics in your syslog */ /* 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); */ /* 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, ...@@ -137,12 +137,12 @@ UNUSUAL_DEV( 0x04da, 0x0901, 0x0100, 0x0200,
"LS-120 Camera", "LS-120 Camera",
US_SC_UFI, US_PR_CBI, NULL, 0), US_SC_UFI, US_PR_CBI, NULL, 0),
/* Reported by Peter Wchtler <pwaechtler@loewe-komp.de> */ /* From Yukihiro Nakai, via zaitcev@yahoo.com.
UNUSUAL_DEV( 0x04ce, 0x0002, 0x0074, 0x0074, * This is needed for CB instead of CBI */
"ScanLogic", UNUSUAL_DEV( 0x04da, 0x0d05, 0x0000, 0x0000,
"SL11R-IDE 0049SQFP-1.2 A002", "Sharp CE-CW05",
US_SC_SCSI, US_PR_BULK, NULL, "CD-R/RW Drive",
US_FL_FIX_INQUIRY ), US_SC_8070, US_PR_CB, NULL, 0),
/* Most of the following entries were developed with the help of /* Most of the following entries were developed with the help of
* Shuttle/SCM directly. * Shuttle/SCM directly.
......
...@@ -960,8 +960,6 @@ static inline unsigned int __create_pipe(struct usb_device *dev, unsigned int en ...@@ -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_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_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_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