summaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/Config.in20
-rw-r--r--drivers/usb/Makefile7
-rw-r--r--drivers/usb/acm.c206
-rw-r--r--drivers/usb/dc2xx.c210
-rw-r--r--drivers/usb/devices.c526
-rw-r--r--drivers/usb/devio.c1021
-rw-r--r--drivers/usb/drivers.c126
-rw-r--r--drivers/usb/ezusb.c1096
-rw-r--r--drivers/usb/ezusb.h126
-rw-r--r--drivers/usb/graphire.c186
-rw-r--r--drivers/usb/hid-debug.h4
-rw-r--r--drivers/usb/hid.c158
-rw-r--r--drivers/usb/hid.h66
-rw-r--r--drivers/usb/hub.c31
-rw-r--r--drivers/usb/hub.h7
-rw-r--r--drivers/usb/inode.c729
-rw-r--r--drivers/usb/joydev.c6
-rw-r--r--drivers/usb/keybdev.c29
-rw-r--r--drivers/usb/mousedev.c4
-rw-r--r--drivers/usb/ohci-hcd.c109
-rw-r--r--drivers/usb/ohci-hcd.h7
-rw-r--r--drivers/usb/ov511.c709
-rw-r--r--drivers/usb/ov511.h53
-rw-r--r--drivers/usb/printer.c713
-rw-r--r--drivers/usb/proc_usb.c1189
-rw-r--r--drivers/usb/scanner.c11
-rw-r--r--drivers/usb/usb-core.c22
-rw-r--r--drivers/usb/usb-debug.c28
-rw-r--r--drivers/usb/usb-serial.c854
-rw-r--r--drivers/usb/usb.c160
-rw-r--r--drivers/usb/usb.h201
-rw-r--r--drivers/usb/usb_scsi.c47
-rw-r--r--drivers/usb/usbdevice_fs.h168
-rw-r--r--drivers/usb/usbkbd.c31
-rw-r--r--drivers/usb/whiteheat.h1542
-rw-r--r--drivers/usb/wmforce.c165
36 files changed, 6659 insertions, 3908 deletions
diff --git a/drivers/usb/Config.in b/drivers/usb/Config.in
index cd614ba1c..b0a372455 100644
--- a/drivers/usb/Config.in
+++ b/drivers/usb/Config.in
@@ -8,20 +8,25 @@ tristate 'Support for USB' CONFIG_USB
if [ ! "$CONFIG_USB" = "n" ]; then
comment 'USB Controllers'
- dep_tristate ' UHCI (Intel PIIX4, VIA, and others) support' CONFIG_USB_UHCI $CONFIG_USB
- dep_tristate ' OHCI-HCD (Compaq, iMacs, OPTi, SiS, ALi, and others) support' CONFIG_USB_OHCI_HCD $CONFIG_USB
+ dep_tristate ' UHCI (Intel PIIX4, VIA, ...) support' CONFIG_USB_UHCI $CONFIG_USB
+ dep_tristate ' OHCI-HCD (Compaq, iMacs, OPTi, SiS, ALi, ...) support' CONFIG_USB_OHCI_HCD $CONFIG_USB
comment 'Miscellaneous USB options'
- if [ "$CONFIG_PROC_FS" != "n" ]; then
- bool ' /proc/bus/usb support' CONFIG_USB_PROC
- fi
+ bool ' Preliminary USB device filesystem' CONFIG_USB_DEVICEFS
comment 'USB Devices'
dep_tristate ' USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB
dep_tristate ' USB Scanner support' CONFIG_USB_SCANNER $CONFIG_USB
dep_tristate ' USB Audio support' CONFIG_USB_AUDIO $CONFIG_USB
- dep_tristate ' USB Communications Device Class (ACM) support' CONFIG_USB_ACM $CONFIG_USB
+ dep_tristate ' USB Modem (CDC ACM) support' CONFIG_USB_ACM $CONFIG_USB
dep_tristate ' USB Serial Converter support' CONFIG_USB_SERIAL $CONFIG_USB
+ if [ "$CONFIG_USB_SERIAL" != "n" ]; then
+ bool ' USB Generic Serial Driver' CONFIG_USB_SERIAL_GENERIC
+ bool ' USB ConnectTech WhiteHEAT Serial Driver' CONFIG_USB_SERIAL_WHITEHEAT
+ bool ' USB Handspring Visor Driver' CONFIG_USB_SERIAL_VISOR
+ bool ' USB Belkin Single Port Serial Driver' CONFIG_USB_SERIAL_BELKIN
+ bool ' USB Peracom Single Port Serial Driver' CONFIG_USB_SERIAL_PERACOM
+ fi
dep_tristate ' USB CPiA Camera support' CONFIG_USB_CPIA $CONFIG_USB
dep_tristate ' USB OV511 Camera support' CONFIG_USB_OV511 $CONFIG_USB
dep_tristate ' USB Kodak DC-2xx Camera support' CONFIG_USB_DC2XX $CONFIG_USB
@@ -29,7 +34,6 @@ comment 'USB Devices'
if [ "$CONFIG_USB_SCSI" != "n" ]; then
bool ' USB SCSI verbose debug' CONFIG_USB_SCSI_DEBUG
fi
- dep_tristate ' EZUSB Firmware downloader' CONFIG_USB_EZUSB $CONFIG_USB
dep_tristate ' USS720 parport driver' CONFIG_USB_USS720 $CONFIG_USB $CONFIG_PARPORT
dep_tristate ' DABUSB driver' CONFIG_USB_DABUSB $CONFIG_USB
@@ -39,6 +43,8 @@ comment 'USB HID'
dep_tristate ' USB HIDBP Keyboard support' CONFIG_USB_KBD $CONFIG_USB
dep_tristate ' USB HIDBP Mouse support' CONFIG_USB_MOUSE $CONFIG_USB
fi
+ dep_tristate ' Wacom Graphire tablet support' CONFIG_USB_GRAPHIRE $CONFIG_USB
+ dep_tristate ' Logitech WingMan Force joystick support' CONFIG_USB_WMFORCE $CONFIG_USB
dep_tristate ' Keyboard support' CONFIG_INPUT_KEYBDEV $CONFIG_USB
dep_tristate ' Mouse support' CONFIG_INPUT_MOUSEDEV $CONFIG_USB
if [ "$CONFIG_INPUT_MOUSEDEV" != "n" ]; then
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index be2c90a3f..9eb62b6a1 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -29,8 +29,8 @@ usb-scsi-objs := usb_scsi.o
# Optional parts of multipart objects.
-ifeq ($(CONFIG_USB_PROC),y)
- usbcore-objs += proc_usb.o
+ifeq ($(CONFIG_USB_DEVICEFS),y)
+ usbcore-objs += devio.o inode.o drivers.o devices.o
endif
ifeq ($(CONFIG_USB_SCSI_DEBUG),y)
usb-scsi-objs += usb_scsi_debug.o
@@ -52,6 +52,8 @@ obj-$(CONFIG_USB_OHCI_HCD) += usb-ohci-hcd.o
obj-$(CONFIG_USB_MOUSE) += usbmouse.o input.o
obj-$(CONFIG_USB_HID) += hid.o input.o
obj-$(CONFIG_USB_KBD) += usbkbd.o input.o
+obj-$(CONFIG_USB_GRAPHIRE) += graphire.o input.o
+obj-$(CONFIG_USB_WMFORCE) += wmforce.o input.o
obj-$(CONFIG_INPUT_KEYBDEV) += keybdev.o input.o
obj-$(CONFIG_INPUT_MOUSEDEV) += mousedev.o input.o
obj-$(CONFIG_INPUT_JOYDEV) += joydev.o input.o
@@ -65,7 +67,6 @@ obj-$(CONFIG_USB_AUDIO) += audio.o
obj-$(CONFIG_USB_CPIA) += cpia.o
obj-$(CONFIG_USB_DC2XX) += dc2xx.o
obj-$(CONFIG_USB_SCSI) += usb-scsi.o
-obj-$(CONFIG_USB_EZUSB) += ezusb.o
obj-$(CONFIG_USB_USS720) += uss720.o
obj-$(CONFIG_USB_DABUSB) += dabusb.o
obj-$(CONFIG_USB_OV511) += ov511.o
diff --git a/drivers/usb/acm.c b/drivers/usb/acm.c
index c14d53d06..154d5cd22 100644
--- a/drivers/usb/acm.c
+++ b/drivers/usb/acm.c
@@ -1,10 +1,10 @@
/*
- * acm.c Version 0.11
+ * acm.c Version 0.14
*
* Copyright (c) 1999 Armin Fuerst <fuerst@in.tum.de>
* Copyright (c) 1999 Pavel Machek <pavel@suse.cz>
* Copyright (c) 1999 Johannes Erdfelt <jerdfelt@valinux.com>
- * Copyright (c) 1999 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2000 Vojtech Pavlik <vojtech@suse.cz>
*
* USB Abstract Control Model driver for USB modems and ISDN adapters
*
@@ -15,6 +15,8 @@
* v0.10 - some more cleanups
* v0.11 - fixed flow control, read error doesn't stop reads
* v0.12 - added TIOCM ioctls, added break handling, made struct acm kmalloced
+ * v0.13 - added termios, added hangup
+ * v0.14 - sized down struct acm
*/
/*
@@ -51,6 +53,14 @@
#include "usb.h"
/*
+ * CMSPAR, some architectures can't have space and mark parity.
+ */
+
+#ifndef CMSPAR
+#define CMSPAR 0
+#endif
+
+/*
* Major and minor numbers.
*/
@@ -75,7 +85,7 @@
#define ACM_REQ_SEND_BREAK 0x23
/*
- * IRQs
+ * IRQs.
*/
#define ACM_IRQ_NETWORK 0x00
@@ -105,7 +115,7 @@
* Line speed and caracter encoding.
*/
-struct acm_coding {
+struct acm_line {
__u32 speed;
__u8 stopbits;
__u8 parity;
@@ -118,23 +128,22 @@ struct acm_coding {
struct acm {
struct usb_device *dev; /* the coresponding usb device */
- struct usb_config_descriptor *cfg; /* configuration number on this device */
+ struct usb_interface *iface; /* the interfaces - +0 control +1 data */
struct tty_struct *tty; /* the coresponding tty */
- unsigned int ctrlif; /* interface number for acm control messages */
+ struct urb ctrlurb, readurb, writeurb; /* urbs */
+ struct acm_line line; /* line coding (bits, stop, parity) */
unsigned int ctrlin; /* input control lines (DCD, DSR, RI, break, overruns) */
unsigned int ctrlout; /* output control lines (DTR, RTS) */
- struct acm_coding linecoding; /* line coding (bits, stop, parity) */
unsigned int writesize; /* max packet size for the output bulk endpoint */
- struct urb ctrlurb, readurb, writeurb; /* urbs */
- unsigned int minor; /* acm minor number */
- unsigned int present; /* this device is connected to the usb bus */
unsigned int used; /* someone has this acm's device open */
+ unsigned int minor; /* acm minor number */
+ unsigned char clocal; /* termios CLOCAL */
};
static struct usb_driver acm_driver;
-static struct acm *acm_table[ACM_TTY_MINORS] = { NULL, NULL, NULL, /* .... */ };
+static struct acm *acm_table[ACM_TTY_MINORS] = { NULL, /* .... */ };
-#define ACM_READY(acm) (acm && acm->present && acm->used)
+#define ACM_READY(acm) (acm && acm->dev && acm->used)
/*
* Functions for ACM control messages.
@@ -143,13 +152,13 @@ static struct acm *acm_table[ACM_TTY_MINORS] = { NULL, NULL, NULL, /* .... */ };
static int acm_ctrl_msg(struct acm *acm, int request, int value, void *buf, int len)
{
int retval = usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0),
- request, USB_RT_ACM, value, acm->ctrlif, buf, len, HZ * 5);
+ request, USB_RT_ACM, value, acm->iface[0].altsetting[0].bInterfaceNumber, buf, len, HZ * 5);
dbg("acm_control_msg: rq: 0x%02x val: %#x len: %#x result: %d", request, value, len, retval);
return retval < 0 ? retval : 0;
}
-#define acm_set_control(acm, control) acm_ctrl_msg(acm, ACM_REQ_SET_CONTROL, control, NULL, 0)
-#define acm_set_coding(acm, coding) acm_ctrl_msg(acm, ACM_REQ_SET_LINE, 0, coding, sizeof(struct acm_coding))
+#define acm_set_control(acm, control) acm_ctrl_msg(acm, ACM_REQ_SET_CONTROL, control, NULL, 0)
+#define acm_set_line(acm, line) acm_ctrl_msg(acm, ACM_REQ_SET_LINE, 0, line, sizeof(struct acm_line))
#define acm_send_break(acm, ms) acm_ctrl_msg(acm, ACM_REQ_SEND_BREAK, ms, NULL, 0)
/*
@@ -161,6 +170,7 @@ static void acm_ctrl_irq(struct urb *urb)
struct acm *acm = urb->context;
devrequest *dr = urb->transfer_buffer;
unsigned char *data = (unsigned char *)(dr + 1);
+ int newctrl;
if (!ACM_READY(acm)) return;
@@ -178,7 +188,14 @@ static void acm_ctrl_irq(struct urb *urb)
case ACM_IRQ_LINE_STATE:
- acm->ctrlin = data[0] | (((unsigned int) data[1]) << 8);
+ newctrl = le16_to_cpup((__u16 *) data);
+
+ if (acm->tty && !acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) {
+ dbg("calling hangup");
+ tty_hangup(acm->tty);
+ }
+
+ acm->ctrlin = newctrl;
dbg("input control lines: dcd%c dsr%c break%c ring%c framing%c parity%c overrun%c",
acm->ctrlin & ACM_CTRL_DCD ? '+' : '-', acm->ctrlin & ACM_CTRL_DSR ? '+' : '-',
@@ -248,7 +265,7 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
{
struct acm *acm = acm_table[MINOR(tty->device)];
- if (!acm || !acm->present) return -EINVAL;
+ if (!acm || !acm->dev) return -EINVAL;
tty->driver_data = acm;
acm->tty = tty;
@@ -278,7 +295,7 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp)
if (--acm->used) return;
- if (acm->present) {
+ if (acm->dev) {
acm_set_control(acm, acm->ctrlout = 0);
usb_unlink_urb(&acm->ctrlurb);
usb_unlink_urb(&acm->writeurb);
@@ -352,7 +369,7 @@ static void acm_tty_break_ctl(struct tty_struct *tty, int state)
static int acm_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
{
struct acm *acm = tty->driver_data;
- unsigned int retval, ctrl, old;
+ unsigned int retval, mask, newctrl;
if (!ACM_READY(acm)) return -EINVAL;
@@ -371,26 +388,68 @@ static int acm_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int
case TIOCMBIS:
case TIOCMBIC:
- if ((retval = get_user(ctrl, (unsigned long *) arg))) return retval;
+ if ((retval = get_user(mask, (unsigned long *) arg))) return retval;
- ctrl = (ctrl & TIOCM_DTR ? ACM_CTRL_DTR : 0) | (ctrl & TIOCM_RTS ? ACM_CTRL_RTS : 0);
- old = acm->ctrlout;
+ newctrl = acm->ctrlout;
+ mask = (mask & TIOCM_DTR ? ACM_CTRL_DTR : 0) | (mask & TIOCM_RTS ? ACM_CTRL_RTS : 0);
switch (cmd) {
- case TIOCMSET: acm->ctrlout = ctrl; break;
- case TIOCMBIS: acm->ctrlout |= ctrl; break;
- case TIOCMBIC: acm->ctrlout &= ~ctrl; break;
+ case TIOCMSET: newctrl = mask; break;
+ case TIOCMBIS: newctrl |= mask; break;
+ case TIOCMBIC: newctrl &= ~mask; break;
}
- if (acm->ctrlout == old) return 0;
- return acm_set_control(acm, acm->ctrlout);
+ if (acm->ctrlout == newctrl) return 0;
+ return acm_set_control(acm, acm->ctrlout = newctrl);
}
- dbg("unknown ioctl %#x", cmd);
-
return -ENOIOCTLCMD;
}
+static __u32 acm_tty_speed[] = {
+ 0, 50, 75, 110, 134, 150, 200, 300, 600,
+ 1200, 1800, 2400, 4800, 9600, 19200, 38400,
+ 57600, 115200, 230400, 460800, 500000, 576000,
+ 921600, 1000000, 1152000, 1500000, 2000000,
+ 2500000, 3000000, 3500000, 4000000
+};
+
+static __u8 acm_tty_size[] = {
+ 5, 6, 7, 8
+};
+
+static void acm_tty_set_termios(struct tty_struct *tty, struct termios *termios_old)
+{
+ struct acm *acm = tty->driver_data;
+ struct termios *termios = tty->termios;
+ struct acm_line newline;
+
+ if (!ACM_READY(acm)) return;
+
+ newline.speed = cpu_to_le32p(acm_tty_speed +
+ (termios->c_cflag & CBAUD & ~CBAUDEX) + (termios->c_cflag & CBAUDEX ? 15 : 0));
+ newline.stopbits = termios->c_cflag & CSTOPB ? 2 : 0;
+ newline.parity = termios->c_cflag & PARENB ?
+ (termios->c_cflag & PARODD ? 1 : 2) + (termios->c_cflag & CMSPAR ? 2 : 0) : 0;
+ newline.databits = acm_tty_size[(termios->c_cflag & CSIZE) >> 4];
+
+ acm->clocal = termios->c_cflag & CLOCAL;
+
+ if (!memcmp(&acm->line, &newline, sizeof(struct acm_line)))
+ return;
+
+ memcpy(&acm->line, &newline, sizeof(struct acm_line));
+
+ if (!newline.speed) {
+ if (acm->ctrlout) acm_set_control(acm, acm->ctrlout = 0);
+ return;
+ }
+
+ acm_set_line(acm, &acm->line);
+
+ dbg("set line: %d %d %d %d", newline.speed, newline.stopbits, newline.parity, newline.databits);
+}
+
/*
* USB probe and disconnect routines.
*/
@@ -398,36 +457,21 @@ static int acm_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int
static void *acm_probe(struct usb_device *dev, unsigned int ifnum)
{
struct acm *acm;
+ struct usb_config_descriptor *cfacm;
struct usb_interface_descriptor *ifcom, *ifdata;
struct usb_endpoint_descriptor *epctrl, *epread, *epwrite;
int readsize, ctrlsize, minor, i;
unsigned char *buf;
- for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++);
-
- if (acm_table[minor]) {
- dbg("no more free acm devices");
- return NULL;
- }
-
- if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) return NULL;
- memset(acm, 0, sizeof(struct acm));
-
- acm_table[minor] = acm;
- acm->minor = minor;
- acm->dev = dev;
-
if (dev->descriptor.bDeviceClass != 2 || dev->descriptor.bDeviceSubClass != 0
- || dev->descriptor.bDeviceProtocol != 0) {
- return NULL;
- }
+ || dev->descriptor.bDeviceProtocol != 0) return NULL;
for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
- acm->cfg = dev->config + i;
- dbg("probing config %d", acm->cfg->bConfigurationValue);
+ cfacm = dev->config + i;
+ dbg("probing config %d", cfacm->bConfigurationValue);
- ifcom = acm->cfg->interface[0].altsetting + 0;
+ ifcom = cfacm->interface[0].altsetting + 0;
if (ifcom->bInterfaceClass != 2 || ifcom->bInterfaceSubClass != 2 ||
ifcom->bInterfaceProtocol != 1 || ifcom->bNumEndpoints != 1)
continue;
@@ -436,12 +480,12 @@ static void *acm_probe(struct usb_device *dev, unsigned int ifnum)
if ((epctrl->bEndpointAddress & 0x80) != 0x80 || (epctrl->bmAttributes & 3) != 3)
continue;
- ifdata = acm->cfg->interface[1].altsetting + 0;
+ ifdata = cfacm->interface[1].altsetting + 0;
if (ifdata->bInterfaceClass != 10 || ifdata->bNumEndpoints != 2)
continue;
- if (usb_interface_claimed(acm->cfg->interface + 0) ||
- usb_interface_claimed(acm->cfg->interface + 1))
+ if (usb_interface_claimed(cfacm->interface + 0) ||
+ usb_interface_claimed(cfacm->interface + 1))
continue;
epread = ifdata->endpoint + 0;
@@ -456,13 +500,32 @@ static void *acm_probe(struct usb_device *dev, unsigned int ifnum)
epwrite = ifdata->endpoint + 0;
}
- usb_set_configuration(dev, acm->cfg->bConfigurationValue);
+ usb_set_configuration(dev, cfacm->bConfigurationValue);
+
+ for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++);
+ if (acm_table[minor]) {
+ err("no more free acm devices");
+ return NULL;
+ }
+
+ if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) {
+ err("out of memory");
+ return NULL;
+ }
+ memset(acm, 0, sizeof(struct acm));
ctrlsize = epctrl->wMaxPacketSize;
readsize = epread->wMaxPacketSize;
acm->writesize = epwrite->wMaxPacketSize;
-
- if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL))) return NULL;
+ acm->iface = cfacm->interface;
+ acm->minor = minor;
+ acm->dev = dev;
+
+ if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL))) {
+ err("out of memory");
+ kfree(acm);
+ return NULL;
+ }
FILL_INT_URB(&acm->ctrlurb, dev, usb_rcvintpipe(dev, epctrl->bEndpointAddress),
buf, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval);
@@ -471,24 +534,20 @@ static void *acm_probe(struct usb_device *dev, unsigned int ifnum)
buf += ctrlsize, readsize, acm_read_bulk, acm);
FILL_BULK_URB(&acm->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress),
- buf += readsize , acm->writesize, acm_write_bulk, acm);
-
- acm->ctrlif = ifcom->bInterfaceNumber;
+ buf += readsize, acm->writesize, acm_write_bulk, acm);
printk(KERN_INFO "ttyACM%d: USB ACM device\n", minor);
acm_set_control(acm, acm->ctrlout);
- acm->linecoding.speed = 115200;
- acm->linecoding.databits = 8;
- acm_set_coding(acm, &acm->linecoding);
+ acm->line.speed = cpu_to_le32(9600);
+ acm->line.databits = 8;
+ acm_set_line(acm, &acm->line);
- usb_driver_claim_interface(&acm_driver, acm->cfg->interface + 0, acm);
- usb_driver_claim_interface(&acm_driver, acm->cfg->interface + 1, acm);
+ usb_driver_claim_interface(&acm_driver, acm->iface + 0, acm);
+ usb_driver_claim_interface(&acm_driver, acm->iface + 1, acm);
- acm->present = 1;
-
- return acm;
+ return acm_table[minor] = acm;
}
return NULL;
@@ -498,12 +557,12 @@ static void acm_disconnect(struct usb_device *dev, void *ptr)
{
struct acm *acm = ptr;
- if (!acm || !acm->present) {
+ if (!acm || !acm->dev) {
dbg("disconnect on nonexisting interface");
return;
}
- acm->present = 0;
+ acm->dev = NULL;
usb_unlink_urb(&acm->ctrlurb);
usb_unlink_urb(&acm->readurb);
@@ -511,13 +570,17 @@ static void acm_disconnect(struct usb_device *dev, void *ptr)
kfree(acm->ctrlurb.transfer_buffer);
- usb_driver_release_interface(&acm_driver, acm->cfg->interface + 0);
- usb_driver_release_interface(&acm_driver, acm->cfg->interface + 1);
+ usb_driver_release_interface(&acm_driver, acm->iface + 0);
+ usb_driver_release_interface(&acm_driver, acm->iface + 1);
if (!acm->used) {
acm_table[acm->minor] = NULL;
kfree(acm);
+ return;
}
+
+ if (acm->tty)
+ tty_hangup(acm->tty);
}
/*
@@ -565,7 +628,8 @@ static struct tty_driver acm_tty_driver = {
throttle: acm_tty_throttle,
unthrottle: acm_tty_unthrottle,
chars_in_buffer: acm_tty_chars_in_buffer,
- break_ctl: acm_tty_break_ctl
+ break_ctl: acm_tty_break_ctl,
+ set_termios: acm_tty_set_termios
};
/*
diff --git a/drivers/usb/dc2xx.c b/drivers/usb/dc2xx.c
index b94670c70..a290f7c4d 100644
--- a/drivers/usb/dc2xx.c
+++ b/drivers/usb/dc2xx.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1999 by David Brownell <david-b@pacbell.net>
+ * Copyright (C) 1999-2000 by David Brownell <david-b@pacbell.net>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -41,6 +41,7 @@
* 12 Oct, 1999 -- handle DC-280 interface class (0xff not 0x0);
* added timeouts to bulk_msg calls. Minor updates, docs.
* 03 Nov, 1999 -- update for 2.3.25 kernel API changes.
+ * 08 Jan, 2000 .. multiple camera support
*
* Thanks to: the folk who've provided USB product IDs, sent in
* patches, and shared their sucesses!
@@ -61,11 +62,17 @@
#include "usb.h"
-/* XXX need to get registered minor number, cdev 10/MINOR */
-/* XXX or: cdev USB_MAJOR(180)/USB_CAMERA_MINOR */
-#define USB_CAMERA_MINOR 170
+/* current USB framework handles max of 16 USB devices per driver */
+#define MAX_CAMERAS 8
+
+/* USB char devs use USB_MAJOR and from USB_CAMERA_MINOR_BASE up */
+#define USB_CAMERA_MINOR_BASE 80
+
+
+// XXX remove packet size limit, now that bulk transfers seem fixed
+
/* Application protocol limit is 0x8002; USB has disliked that limit! */
#define MAX_PACKET_SIZE 0x2000 /* e.g. image downloading */
@@ -80,39 +87,35 @@ static const struct camera {
short idProduct;
/* plus hooks for camera-specific info if needed */
} cameras [] = {
+ /* These have the same application level protocol */
{ 0x040a, 0x0120 }, // Kodak DC-240
{ 0x040a, 0x0130 }, // Kodak DC-280
- /* Kodak has several other USB-enabled devices, which (along with
- * models from other vendors) all use the Flashpoint "Digita
- * OS" and its wire protocol. These use a different application
- * level protocol from the DC-240/280 models. Note that Digita
- * isn't just for cameras -- Epson has a non-USB Digita printer.
- */
-// { 0x040a, 0x0100 }, // Kodak DC-220
+ /* These have a different application level protocol which
+ * is part of the Flashpoint "DigitaOS". That supports some
+ * non-camera devices, and some non-Kodak cameras.
+ */
+ { 0x040a, 0x0100 }, // Kodak DC-220
{ 0x040a, 0x0110 }, // Kodak DC-260
{ 0x040a, 0x0111 }, // Kodak DC-265
{ 0x040a, 0x0112 }, // Kodak DC-290
-
// { 0x03f0, 0xffff }, // HP PhotoSmart C500
- /* Other USB cameras may well work here too, so long as they
- * just stick to half duplex packet exchanges and bulk messages.
- * Some non-camera devices have also been shown to work.
+ /* Other USB devices may well work here too, so long as they
+ * just stick to half duplex bulk packet exchanges.
*/
};
struct camera_state {
- /* these fields valid (dev != 0) iff camera connected */
struct usb_device *dev; /* USB device handle */
char inEP; /* read endpoint */
char outEP; /* write endpoint */
const struct camera *info; /* DC-240, etc */
-
- /* valid iff isOpen */
- int isOpen; /* device opened? */
+ int subminor; /* which minor dev #? */
int isActive; /* I/O taking place? */
+
+ /* this is non-null iff the device is open */
char *buf; /* buffer for I/O */
/* always valid */
@@ -120,11 +123,8 @@ struct camera_state {
};
-/* For now, we only support one camera at a time: there's one
- * application-visible device (e.g. /dev/kodak) and the second
- * (to Nth) camera detected on the bus is ignored.
- */
-static struct camera_state static_camera_state;
+/* Support multiple cameras, possibly of different types. */
+static struct camera_state *minor_data [MAX_CAMERAS];
static ssize_t camera_read (struct file *file,
@@ -133,9 +133,12 @@ static ssize_t camera_read (struct file *file,
struct camera_state *camera;
int retries;
- camera = (struct camera_state *) file->private_data;
if (len > MAX_PACKET_SIZE)
return -EINVAL;
+
+ camera = (struct camera_state *) file->private_data;
+ if (!camera->dev)
+ return -ENODEV;
if (camera->isActive++)
return -EBUSY;
@@ -161,7 +164,7 @@ static ssize_t camera_read (struct file *file,
usb_rcvbulkpipe (camera->dev, camera->inEP),
camera->buf, len, &count, HZ*10);
- dbg("read (%d) - 0x%x %ld", len, result, count);
+ dbg ("read (%d) - 0x%x %ld", len, result, count);
if (!result) {
if (copy_to_user (buf, camera->buf, count))
@@ -173,7 +176,7 @@ static ssize_t camera_read (struct file *file,
break;
interruptible_sleep_on_timeout (&camera->wait, RETRY_TIMEOUT);
- dbg("read (%d) - retry", len);
+ dbg ("read (%d) - retry", len);
}
camera->isActive = 0;
return -EIO;
@@ -185,9 +188,12 @@ static ssize_t camera_write (struct file *file,
struct camera_state *camera;
ssize_t bytes_written = 0;
- camera = (struct camera_state *) file->private_data;
if (len > MAX_PACKET_SIZE)
return -EINVAL;
+
+ camera = (struct camera_state *) file->private_data;
+ if (!camera->dev)
+ return -ENODEV;
if (camera->isActive++)
return -EBUSY;
@@ -228,7 +234,7 @@ static ssize_t camera_write (struct file *file,
obuf, thistime, &count, HZ*10);
if (result)
- dbg("write USB err - %x", result);
+ dbg ("write USB err - %x", result);
if (count) {
obuf += count;
@@ -258,26 +264,26 @@ static ssize_t camera_write (struct file *file,
}
done:
camera->isActive = 0;
-
- dbg("write %d", bytes_written);
-
+ dbg ("wrote %d", bytes_written);
return bytes_written;
}
static int camera_open (struct inode *inode, struct file *file)
{
- struct camera_state *camera = &static_camera_state;
+ struct camera_state *camera;
+ int subminor;
- /* ignore camera->dev so it can be turned on "late" */
+ subminor = MINOR (inode->i_rdev) - USB_CAMERA_MINOR_BASE;
+ if (subminor < 0 || subminor >= MAX_CAMERAS
+ || !(camera = minor_data [subminor])) {
+ return -ENODEV;
+ }
- if (camera->isOpen++)
- return -EBUSY;
if (!(camera->buf = (char *) kmalloc (MAX_PACKET_SIZE, GFP_KERNEL))) {
- camera->isOpen = 0;
return -ENOMEM;
}
- dbg("open");
+ dbg ("open");
/* Keep driver from being unloaded while it's in use */
MOD_INC_USE_COUNT;
@@ -293,10 +299,16 @@ static int camera_release (struct inode *inode, struct file *file)
camera = (struct camera_state *) file->private_data;
kfree (camera->buf);
- camera->isOpen = 0;
+
+ /* If camera was unplugged with open file ... */
+ if (!camera->dev) {
+ minor_data [camera->subminor] = NULL;
+ kfree (camera);
+ }
+
MOD_DEC_USE_COUNT;
- dbg("close");
+ dbg ("close");
return 0;
}
@@ -306,26 +318,11 @@ static int camera_release (struct inode *inode, struct file *file)
* apps should be able to see the camera type.
*/
static /* const */ struct file_operations usb_camera_fops = {
- NULL, /* llseek */
- camera_read,
- camera_write,
- NULL, /* readdir */
- NULL, /* poll */
- NULL, /* ioctl */
- NULL, /* mmap */
- camera_open,
- NULL, /* flush */
- camera_release,
- NULL, /* async */
- NULL, /* fasync */
- NULL, /* lock */
-};
-
-static struct miscdevice usb_camera = {
- USB_CAMERA_MINOR,
- "USB camera (Kodak DC-2xx)",
- &usb_camera_fops
- // next, prev
+ /* Uses GCC initializer extension; simpler to maintain */
+ read: camera_read,
+ write: camera_write,
+ open: camera_open,
+ release: camera_release,
};
@@ -337,8 +334,7 @@ static void * camera_probe(struct usb_device *dev, unsigned int ifnum)
struct usb_interface_descriptor *interface;
struct usb_endpoint_descriptor *endpoint;
int direction, ep;
-
- struct camera_state *camera = &static_camera_state;
+ struct camera_state *camera;
/* Is it a supported camera? */
for (i = 0; i < sizeof (cameras) / sizeof (struct camera); i++) {
@@ -355,7 +351,7 @@ static void * camera_probe(struct usb_device *dev, unsigned int ifnum)
/* these have one config, one interface */
if (dev->descriptor.bNumConfigurations != 1
|| dev->config[0].bNumInterfaces != 1) {
- dbg("Bogus camera config info");
+ dbg ("Bogus camera config info");
return NULL;
}
@@ -367,18 +363,34 @@ static void * camera_probe(struct usb_device *dev, unsigned int ifnum)
|| interface->bInterfaceProtocol != 0
|| interface->bNumEndpoints != 2
) {
- dbg("Bogus camera interface info");
+ dbg ("Bogus camera interface info");
return NULL;
}
- /* can only show one camera at a time through /dev ... */
- if (!camera->dev) {
- camera->dev = dev;
- info("USB Camera is connected");
- } else {
- info("Ignoring additional USB Camera");
+
+ /* select "subminor" number (part of a minor number) */
+ for (i = 0; i < MAX_CAMERAS; i++) {
+ if (!minor_data [i])
+ break;
+ }
+ if (i >= MAX_CAMERAS) {
+ info ("Ignoring additional USB Camera");
+ return NULL;
+ }
+
+ /* allocate & init camera state */
+ camera = minor_data [i] = kmalloc (sizeof *camera, GFP_KERNEL);
+ if (!camera) {
+ err ("no memory!");
return NULL;
}
+ camera->dev = dev;
+ camera->subminor = i;
+ camera->isActive = 0;
+ camera->buf = NULL;
+ init_waitqueue_head (&camera->wait);
+ info ("USB Camera #%d connected", camera->subminor);
+
/* get input and output endpoints (either order) */
endpoint = interface->endpoint;
@@ -402,14 +414,14 @@ static void * camera_probe(struct usb_device *dev, unsigned int ifnum)
|| endpoint [0].bmAttributes != USB_ENDPOINT_XFER_BULK
|| endpoint [1].bmAttributes != USB_ENDPOINT_XFER_BULK
) {
- dbg("Bogus camera endpoints");
+ dbg ("Bogus endpoints");
camera->dev = NULL;
return NULL;
}
if (usb_set_configuration (dev, dev->config[0].bConfigurationValue)) {
- err("Failed usb_set_configuration");
+ err ("Failed usb_set_configuration");
camera->dev = NULL;
return NULL;
}
@@ -421,21 +433,18 @@ static void * camera_probe(struct usb_device *dev, unsigned int ifnum)
static void camera_disconnect(struct usb_device *dev, void *ptr)
{
struct camera_state *camera = (struct camera_state *) ptr;
+ int subminor = camera->subminor;
- if (camera->dev != dev)
- return;
-
- /* Currently not reflecting this up to userland; at one point
- * it got called on bus reconfig, which we clearly don't want.
- * A good consequence is the ability to remove camera for
- * a while without apps needing to do much more than ignore
- * some particular error returns. On the bad side, if one
- * camera is swapped for another one, we won't be telling.
+ /* If camera's not opened, we can clean up right away.
+ * Else apps see a disconnect on next I/O; the release cleans.
*/
- camera->info = NULL;
- camera->dev = NULL;
+ if (!camera->buf) {
+ minor_data [subminor] = NULL;
+ kfree (camera);
+ } else
+ camera->dev = NULL;
- info("USB Camera disconnected");
+ info ("USB Camera #%d disconnected", subminor);
}
static /* const */ struct usb_driver camera_driver = {
@@ -443,47 +452,26 @@ static /* const */ struct usb_driver camera_driver = {
camera_probe,
camera_disconnect,
{ NULL, NULL },
-
- NULL, /* &usb_camera_fops, */
- 0 /* USB_CAMERA_MINOR */
+ &usb_camera_fops,
+ USB_CAMERA_MINOR_BASE
};
-#ifdef MODULE
-static __init
-#endif
-int usb_dc2xx_init(void)
+int __init usb_dc2xx_init(void)
{
- struct camera_state *camera = &static_camera_state;
-
- camera->dev = NULL;
- camera->isOpen = 0;
- camera->isActive = 0;
- init_waitqueue_head (&camera->wait);
-
- if (usb_register (&camera_driver) < 0)
- return -1;
- misc_register (&usb_camera);
-
+ if (usb_register (&camera_driver) < 0)
+ return -1;
return 0;
}
-#ifdef MODULE
-static __exit
-#endif
-void usb_dc2xx_cleanup(void)
+void __exit usb_dc2xx_cleanup(void)
{
usb_deregister (&camera_driver);
- misc_deregister (&usb_camera);
}
-#ifdef MODULE
-
MODULE_AUTHOR("David Brownell, david-b@pacbell.net");
MODULE_DESCRIPTION("USB Camera Driver for Kodak DC-2xx series cameras");
module_init (usb_dc2xx_init);
module_exit (usb_dc2xx_cleanup);
-
-#endif /* MODULE */
diff --git a/drivers/usb/devices.c b/drivers/usb/devices.c
new file mode 100644
index 000000000..1fc6d5001
--- /dev/null
+++ b/drivers/usb/devices.c
@@ -0,0 +1,526 @@
+/*
+ * devices.c
+ * (C) Copyright 1999 Randy Dunlap.
+ * (C) Copyright 1999,2000 Thomas Sailer <sailer@ife.ee.ethz.ch>. (proc file per device)
+ * (C) Copyright 1999 Deti Fliegl (new USB architecture)
+ *
+ * $id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ *************************************************************
+ *
+ * <mountpoint>/devices contains USB topology, device, config, class,
+ * interface, & endpoint data.
+ *
+ * I considered using /proc/bus/usb/devices/device# for each device
+ * as it is attached or detached, but I didn't like this for some
+ * reason -- maybe it's just too deep of a directory structure.
+ * I also don't like looking in multiple places to gather and view
+ * the data. Having only one file for ./devices also prevents race
+ * conditions that could arise if a program was reading device info
+ * for devices that are being removed (unplugged). (That is, the
+ * program may find a directory for devnum_12 then try to open it,
+ * but it was just unplugged, so the directory is now deleted.
+ * But programs would just have to be prepared for situations like
+ * this in any plug-and-play environment.)
+ *
+ * 1999-12-16: Thomas Sailer <sailer@ife.ee.ethz.ch>
+ * Converted the whole proc stuff to real
+ * read methods. Now not the whole device list needs to fit
+ * into one page, only the device list for one bus.
+ * Added a poll method to /proc/bus/usb/devices, to wake
+ * up an eventual usbd
+ * 2000-01-04: Thomas Sailer <sailer@ife.ee.ethz.ch>
+ * Turned into its own filesystem
+ *
+ * $Id: devices.c,v 1.5 2000/01/11 13:58:21 tom Exp $
+ */
+
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <asm/uaccess.h>
+
+#include "usb.h"
+#include "usbdevice_fs.h"
+
+#define MAX_TOPO_LEVEL 6
+
+/* Define ALLOW_SERIAL_NUMBER if you want to see the serial number of devices */
+#define ALLOW_SERIAL_NUMBER
+
+static char *format_topo =
+/* T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd */
+ "T: Bus=%2.2d Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%3s MxCh=%2d\n";
+
+static char *format_string_manufacturer =
+/* S: Manufacturer=xxxx */
+ "S: Manufacturer=%.100s\n";
+
+static char *format_string_product =
+/* S: Product=xxxx */
+ "S: Product=%.100s\n";
+
+#ifdef ALLOW_SERIAL_NUMBER
+static char *format_string_serialnumber =
+/* S: SerialNumber=xxxx */
+ "S: SerialNumber=%.100s\n";
+#endif
+
+static char *format_bandwidth =
+/* B: Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd */
+ "B: Alloc=%3d/%3d us (%2d%%), #Int=%3d, #Iso=%3d\n";
+
+static char *format_device1 =
+/* D: Ver=xx.xx Cls=xx(sssss) Sub=xx Prot=xx MxPS=dd #Cfgs=dd */
+ "D: Ver=%2x.%02x Cls=%02x(%-5s) Sub=%02x Prot=%02x MxPS=%2d #Cfgs=%3d\n";
+
+static char *format_device2 =
+/* P: Vendor=xxxx ProdID=xxxx Rev=xx.xx */
+ "P: Vendor=%04x ProdID=%04x Rev=%2x.%02x\n";
+
+static char *format_config =
+/* C: #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA */
+ "C:%c #Ifs=%2d Cfg#=%2d Atr=%02x MxPwr=%3dmA\n";
+
+static char *format_iface =
+/* I: If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=xxxx*/
+ "I: If#=%2d Alt=%2d #EPs=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x Driver=%s\n";
+
+static char *format_endpt =
+/* E: Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=dddms */
+ "E: Ad=%02x(%c) Atr=%02x(%-4s) MxPS=%4d Ivl=%3dms\n";
+
+
+/*
+ * Need access to the driver and USB bus lists.
+ * extern struct list_head usb_driver_list;
+ * extern struct list_head usb_bus_list;
+ * However, these will come from functions that return ptrs to each of them.
+ */
+
+static DECLARE_WAIT_QUEUE_HEAD(deviceconndiscwq);
+static unsigned int conndiscevcnt = 0;
+
+/* this struct stores the poll state for <mountpoint>/devices pollers */
+struct usb_device_status {
+ unsigned int lastev;
+};
+
+struct class_info {
+ int class;
+ char *class_name;
+};
+
+static const struct class_info clas_info[] =
+{ /* max. 5 chars. per name string */
+ {USB_CLASS_PER_INTERFACE, ">ifc"},
+ {USB_CLASS_AUDIO, "audio"},
+ {USB_CLASS_COMM, "comm."},
+ {USB_CLASS_HID, "HID"},
+ {USB_CLASS_HUB, "hub"},
+ {USB_CLASS_PRINTER, "print"},
+ {USB_CLASS_MASS_STORAGE, "stor."},
+ {USB_CLASS_DATA, "data"},
+ {USB_CLASS_VENDOR_SPEC, "vend."},
+ {-1, "unk."} /* leave as last */
+};
+
+/*****************************************************************/
+
+void usbdevfs_conn_disc_event(void)
+{
+ wake_up(&deviceconndiscwq);
+ conndiscevcnt++;
+}
+
+static const char *class_decode(const int class)
+{
+ int ix;
+
+ for (ix = 0; clas_info[ix].class != -1; ix++)
+ if (clas_info[ix].class == class)
+ break;
+ return (clas_info[ix].class_name);
+}
+
+static char *usb_dump_endpoint_descriptor(char *start, char *end, const struct usb_endpoint_descriptor *desc)
+{
+ char *EndpointType [4] = {"Ctrl", "Isoc", "Bulk", "Int."};
+
+ if (start > end)
+ return start;
+ start += sprintf(start, format_endpt, desc->bEndpointAddress,
+ (desc->bEndpointAddress & USB_DIR_IN) ? 'I' : 'O',
+ desc->bmAttributes, EndpointType[desc->bmAttributes & 3],
+ desc->wMaxPacketSize, desc->bInterval);
+ return start;
+}
+
+static char *usb_dump_endpoint(char *start, char *end, const struct usb_endpoint_descriptor *endpoint)
+{
+ return usb_dump_endpoint_descriptor(start, end, endpoint);
+}
+
+static char *usb_dump_interface_descriptor(char *start, char *end, const struct usb_interface *iface, int setno)
+{
+ struct usb_interface_descriptor *desc = &iface->altsetting[setno];
+
+ if (start > end)
+ return start;
+ start += sprintf(start, format_iface,
+ desc->bInterfaceNumber,
+ desc->bAlternateSetting,
+ desc->bNumEndpoints,
+ desc->bInterfaceClass,
+ class_decode(desc->bInterfaceClass),
+ desc->bInterfaceSubClass,
+ desc->bInterfaceProtocol,
+ iface->driver ? iface->driver->name : "(none)");
+ return start;
+}
+
+static char *usb_dump_interface(char *start, char *end, const struct usb_interface *iface, int setno)
+{
+ struct usb_interface_descriptor *desc = &iface->altsetting[setno];
+ int i;
+
+ start = usb_dump_interface_descriptor(start, end, iface, setno);
+ for (i = 0; i < desc->bNumEndpoints; i++) {
+ if (start > end)
+ return start;
+ start = usb_dump_endpoint(start, end, desc->endpoint + i);
+ }
+ return start;
+}
+
+/* TBD:
+ * 0. TBDs
+ * 1. marking active config and ifaces (code lists all, but should mark
+ * which ones are active, if any)
+ * 2. add <halted> status to each endpoint line
+ */
+
+static char *usb_dump_config_descriptor(char *start, char *end, const struct usb_config_descriptor *desc, int active)
+{
+ if (start > end)
+ return start;
+ start += sprintf(start, format_config,
+ active ? '*' : ' ', /* mark active/actual/current cfg. */
+ desc->bNumInterfaces,
+ desc->bConfigurationValue,
+ desc->bmAttributes,
+ desc->MaxPower * 2);
+ return start;
+}
+
+static char *usb_dump_config(char *start, char *end, const struct usb_config_descriptor *config, int active)
+{
+ int i, j;
+ struct usb_interface *interface;
+
+ if (start > end)
+ return start;
+ if (!config) /* getting these some in 2.3.7; none in 2.3.6 */
+ return start + sprintf(start, "(null Cfg. desc.)\n");
+ start = usb_dump_config_descriptor(start, end, config, active);
+ for (i = 0; i < config->bNumInterfaces; i++) {
+ interface = config->interface + i;
+ if (!interface)
+ break;
+ for (j = 0; j < interface->num_altsetting; j++) {
+ if (start > end)
+ return start;
+ start = usb_dump_interface(start, end, interface, j);
+ }
+ }
+ return start;
+}
+
+/*
+ * Dump the different USB descriptors.
+ */
+static char *usb_dump_device_descriptor(char *start, char *end, const struct usb_device_descriptor *desc)
+{
+ if (start > end)
+ return start;
+ start += sprintf (start, format_device1,
+ desc->bcdUSB >> 8, desc->bcdUSB & 0xff,
+ desc->bDeviceClass,
+ class_decode (desc->bDeviceClass),
+ desc->bDeviceSubClass,
+ desc->bDeviceProtocol,
+ desc->bMaxPacketSize0,
+ desc->bNumConfigurations);
+ if (start > end)
+ return start;
+ start += sprintf(start, format_device2,
+ desc->idVendor, desc->idProduct,
+ desc->bcdDevice >> 8, desc->bcdDevice & 0xff);
+ return start;
+}
+
+/*
+ * Dump the different strings that this device holds.
+ */
+static char *usb_dump_device_strings (char *start, char *end, struct usb_device *dev)
+{
+ char *buf;
+
+ if (start > end)
+ return start;
+ buf = kmalloc(128, GFP_KERNEL);
+ if (!buf)
+ return start;
+ if (dev->descriptor.iManufacturer) {
+ if (usb_string(dev, dev->descriptor.iManufacturer, buf, 128) > 0)
+ start += sprintf(start, format_string_manufacturer, buf);
+ }
+ if (start > end)
+ goto out;
+ if (dev->descriptor.iProduct) {
+ if (usb_string(dev, dev->descriptor.iProduct, buf, 128) > 0)
+ start += sprintf(start, format_string_product, buf);
+ }
+ if (start > end)
+ goto out;
+#ifdef ALLOW_SERIAL_NUMBER
+ if (dev->descriptor.iSerialNumber) {
+ if (usb_string(dev, dev->descriptor.iSerialNumber, buf, 128) > 0)
+ start += sprintf(start, format_string_serialnumber, buf);
+ }
+#endif
+ out:
+ kfree(buf);
+ return start;
+}
+
+static char *usb_dump_desc(char *start, char *end, const struct usb_device *dev)
+{
+ int i;
+
+ if (start > end)
+ return start;
+
+ start = usb_dump_device_descriptor(start, end, &dev->descriptor);
+
+ if (start > end)
+ return start;
+
+ start = usb_dump_device_strings (start, end, dev);
+
+ for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
+ if (start > end)
+ return start;
+ start = usb_dump_config(start, end, dev->config + i,
+ (dev->config + i) == dev->actconfig); /* active ? */
+ }
+ return start;
+}
+
+
+#ifdef PROC_EXTRA /* TBD: may want to add this code later */
+
+static char *usb_dump_hub_descriptor(char *start, char *end, const struct usb_hub_descriptor * desc)
+{
+ int leng = USB_DT_HUB_NONVAR_SIZE;
+ unsigned char *ptr = (unsigned char *)desc;
+
+ if (start > end)
+ return start;
+ start += sprintf(start, "Interface:");
+ while (leng && start <= end) {
+ start += sprintf(start, " %02x", *ptr);
+ ptr++; leng--;
+ }
+ *start++ = '\n';
+ return start;
+}
+
+static char *usb_dump_string(char *start, char *end, const struct usb_device *dev, char *id, int index)
+{
+ if (start > end)
+ return start;
+ start += sprintf(start, "Interface:");
+ if (index <= dev->maxstring && dev->stringindex && dev->stringindex[index])
+ start += sprintf(start, "%s: %.100s ", id, dev->stringindex[index]);
+ return start;
+}
+
+#endif /* PROC_EXTRA */
+
+/*****************************************************************/
+
+static char *usb_device_dump(char *start, char *end, const struct usb_device *usbdev,
+ int bus, int level, int index, int count)
+{
+ int chix;
+ int cnt = 0;
+ int parent_devnum = 0;
+
+ if (level > MAX_TOPO_LEVEL)
+ return start;
+ if (usbdev->parent && usbdev->parent->devnum != -1)
+ parent_devnum = usbdev->parent->devnum;
+ /*
+ * So the root hub's parent is 0 and any device that is
+ * plugged into the root hub has a parent of 0.
+ */
+ start += sprintf(start, format_topo, bus, level, parent_devnum, index, count,
+ usbdev->devnum, usbdev->slow ? "1.5" : "12 ", usbdev->maxchild);
+ /*
+ * level = topology-tier level;
+ * parent_devnum = parent device number;
+ * index = parent's connector number;
+ * count = device count at this level
+ */
+ /* do not dump descriptors for root hub */
+ if (usbdev->devnum >= 0)
+ start = usb_dump_desc(start, end, usbdev);
+ if (start > end)
+ return start + sprintf(start, "(truncated)\n");
+ /* Now look at all of this device's children. */
+ for (chix = 0; chix < usbdev->maxchild; chix++) {
+ if (start > end)
+ return start;
+ if (usbdev->children[chix])
+ start = usb_device_dump(start, end, usbdev->children[chix], bus, level + 1, chix, ++cnt);
+ }
+ return start;
+}
+
+static ssize_t usb_device_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
+{
+ struct list_head *buslist;
+ struct usb_bus *bus;
+ char *page, *end;
+ ssize_t ret = 0;
+ unsigned int pos, len;
+
+ if (*ppos < 0)
+ return -EINVAL;
+ if (nbytes <= 0)
+ return 0;
+ if (!access_ok(VERIFY_WRITE, buf, nbytes))
+ return -EFAULT;
+ if (!(page = (char*) __get_free_pages(GFP_KERNEL,1)))
+ return -ENOMEM;
+ pos = *ppos;
+ /* enumerate busses */
+ for (buslist = usb_bus_list.next; buslist != &usb_bus_list; buslist = buslist->next) {
+ /* print bandwidth allocation */
+ bus = list_entry(buslist, struct usb_bus, bus_list);
+ len = sprintf(page, format_bandwidth, bus->bandwidth_allocated, FRAME_TIME_MAX_USECS_ALLOC,
+ (100 * bus->bandwidth_allocated + FRAME_TIME_MAX_USECS_ALLOC / 2) / FRAME_TIME_MAX_USECS_ALLOC,
+ bus->bandwidth_int_reqs, bus->bandwidth_isoc_reqs);
+ end = usb_device_dump(page + len, page + (2*PAGE_SIZE - 256), bus->root_hub, bus->busnum, 0, 0, 0);
+ len = end - page;
+ if (len > pos) {
+ len -= pos;
+ if (len > nbytes)
+ len = nbytes;
+ if (copy_to_user(buf, page + pos, len)) {
+ if (!ret)
+ ret = -EFAULT;
+ break;
+ }
+ nbytes -= len;
+ buf += len;
+ ret += len;
+ pos = 0;
+ *ppos += len;
+ } else
+ pos -= len;
+ }
+ free_pages((unsigned long)page, 1);
+ return ret;
+}
+
+static unsigned int usb_device_poll(struct file *file, struct poll_table_struct *wait)
+{
+ struct usb_device_status *st = (struct usb_device_status *)file->private_data;
+ unsigned int mask = 0;
+
+ if (!st) {
+ st = kmalloc(sizeof(struct usb_device_status), GFP_KERNEL);
+ if (!st)
+ return POLLIN;
+ /*
+ * need to prevent the module from being unloaded, since
+ * proc_unregister does not call the release method and
+ * we would have a memory leak
+ */
+ st->lastev = conndiscevcnt;
+ file->private_data = st;
+ mask = POLLIN;
+ }
+ if (file->f_mode & FMODE_READ)
+ poll_wait(file, &deviceconndiscwq, wait);
+ if (st->lastev != conndiscevcnt)
+ mask |= POLLIN;
+ st->lastev = conndiscevcnt;
+ return mask;
+}
+
+static int usb_device_open(struct inode *inode, struct file *file)
+{
+ file->private_data = NULL;
+ return 0;
+}
+
+static int usb_device_release(struct inode *inode, struct file *file)
+{
+ if (file->private_data) {
+ kfree(file->private_data);
+ file->private_data = NULL;
+ }
+
+ return 0;
+}
+
+static long long usb_device_lseek(struct file * file, long long offset, int orig)
+{
+ switch (orig) {
+ case 0:
+ file->f_pos = offset;
+ return file->f_pos;
+
+ case 1:
+ file->f_pos += offset;
+ return file->f_pos;
+
+ case 2:
+ return -EINVAL;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+struct file_operations usbdevfs_devices_fops = {
+ usb_device_lseek, /* lseek */
+ usb_device_read, /* read */
+ NULL, /* write */
+ NULL, /* readdir */
+ usb_device_poll, /* poll */
+ NULL, /* ioctl */
+ NULL, /* mmap */
+ usb_device_open, /* open */
+ NULL, /* flush */
+ usb_device_release, /* release */
+ NULL /* fsync */
+};
diff --git a/drivers/usb/devio.c b/drivers/usb/devio.c
new file mode 100644
index 000000000..5fb51d93c
--- /dev/null
+++ b/drivers/usb/devio.c
@@ -0,0 +1,1021 @@
+/*****************************************************************************/
+
+/*
+ * devio.c -- User space communication with USB devices.
+ *
+ * Copyright (C) 1999-2000 Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: devio.c,v 1.6 2000/01/11 23:26:33 tom Exp $
+ *
+ * This file implements the usbdevfs/x/y files, where
+ * x is the bus number and y the device number.
+ *
+ * It allows user space programs/"drivers" to communicate directly
+ * with USB devices without intervening kernel driver.
+ *
+ * Revision history
+ * 22.12.1999 0.1 Initial release (split from proc_usb.c)
+ * 04.01.2000 0.2 Turned into its own filesystem
+ */
+
+/*****************************************************************************/
+
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/signal.h>
+#include <linux/poll.h>
+#include <asm/uaccess.h>
+
+#include "usb.h"
+#include "usbdevice_fs.h"
+
+struct async {
+ struct list_head asynclist;
+ struct dev_state *ps;
+ struct task_struct *task;
+ unsigned int signr;
+ void *userbuffer;
+ void *userurb;
+ urb_t urb;
+};
+
+/*
+ * my own sync control and bulk methods. Here to experiment
+ * and because the kernel ones set the process to TASK_UNINTERRUPTIBLE.
+ */
+
+struct sync {
+ wait_queue_head_t wait;
+};
+
+static void sync_completed(purb_t urb)
+{
+ struct sync *s = (struct sync *)urb->context;
+
+ wake_up(&s->wait);
+}
+
+static int do_sync(purb_t urb, int timeout)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ unsigned long tm;
+ signed long tmdiff;
+ struct sync s;
+ int ret;
+
+ tm = jiffies+timeout;
+ init_waitqueue_head(&s.wait);
+ add_wait_queue(&s.wait, &wait);
+ urb->context = &s;
+ urb->complete = sync_completed;
+ set_current_state(TASK_INTERRUPTIBLE);
+ if ((ret = usb_submit_urb(urb)))
+ goto out;
+ while (urb->status == -EINPROGRESS) {
+ tmdiff = tm - jiffies;
+ if (tmdiff <= 0) {
+ ret = -ETIMEDOUT;
+ goto out;
+ }
+ if (signal_pending(current)) {
+ ret = -EINTR;
+ goto out;
+ }
+ schedule_timeout(tmdiff);
+ }
+ ret = urb->status;
+ out:
+ set_current_state(TASK_RUNNING);
+ usb_unlink_urb(urb);
+ remove_wait_queue(&s.wait, &wait);
+ return ret;
+}
+
+static int my_usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype,
+ __u16 value, __u16 index, void *data, __u16 size, int timeout)
+{
+ urb_t *urb;
+ int ret;
+
+ if (!(urb = usb_alloc_urb(0)))
+ return -ENOMEM;
+ if (!(urb->setup_packet = kmalloc(8, GFP_KERNEL))) {
+ usb_free_urb(urb);
+ return -ENOMEM;
+ }
+ urb->setup_packet[0] = requesttype;
+ urb->setup_packet[1] = request;
+ urb->setup_packet[2] = value;
+ urb->setup_packet[3] = value >> 8;
+ urb->setup_packet[4] = index;
+ urb->setup_packet[5] = index >> 8;
+ urb->setup_packet[6] = size;
+ urb->setup_packet[7] = size >> 8;
+ urb->dev = dev;
+ urb->pipe = pipe;
+ urb->transfer_buffer = data;
+ urb->transfer_buffer_length = size;
+ ret = do_sync(urb, timeout);
+ if (ret >= 0)
+ ret = urb->status;
+ if (ret >= 0)
+ ret = urb->actual_length;
+ kfree(urb->setup_packet);
+ usb_free_urb(urb);
+ return ret;
+}
+
+static int my_usb_bulk_msg(struct usb_device *dev, unsigned int pipe,
+ void *data, int len, int *actual_length, int timeout)
+{
+ urb_t *urb;
+ int ret;
+
+ if (!(urb = usb_alloc_urb(0)))
+ return -ENOMEM;
+ urb->dev = dev;
+ urb->pipe = pipe;
+ urb->transfer_buffer = data;
+ urb->transfer_buffer_length = len;
+ ret = do_sync(urb, timeout);
+ if (ret >= 0)
+ ret = urb->status;
+ if (ret >= 0 && actual_length != NULL)
+ *actual_length = urb->actual_length;
+ usb_free_urb(urb);
+ return ret;
+}
+
+static long long usbdev_lseek(struct file *file, long long offset, int orig)
+{
+ switch (orig) {
+ case 0:
+ file->f_pos = offset;
+ return file->f_pos;
+
+ case 1:
+ file->f_pos += offset;
+ return file->f_pos;
+
+ case 2:
+ return -EINVAL;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static ssize_t usbdev_read(struct file *file, char * buf, size_t nbytes, loff_t *ppos)
+{
+ struct dev_state *ps = (struct dev_state *)file->private_data;
+ ssize_t ret = 0;
+ unsigned len;
+ loff_t pos;
+
+ pos = *ppos;
+ down_read(&ps->devsem);
+ if (!ps->dev)
+ ret = -ENODEV;
+ else if (pos < 0)
+ ret = -EINVAL;
+ else if (pos < sizeof(struct usb_device_descriptor)) {
+ len = sizeof(struct usb_device_descriptor) - pos;
+ if (len > nbytes)
+ len = nbytes;
+ if (copy_to_user(buf, ((char *)&ps->dev->descriptor) + pos, len))
+ ret = -EFAULT;
+ else {
+ *ppos += len;
+ buf += len;
+ nbytes -= len;
+ ret += len;
+ }
+ }
+ up_read(&ps->devsem);
+ return ret;
+}
+
+extern inline unsigned int ld2(unsigned int x)
+{
+ unsigned int r = 0;
+
+ if (x >= 0x10000) {
+ x >>= 16;
+ r += 16;
+ }
+ if (x >= 0x100) {
+ x >>= 8;
+ r += 8;
+ }
+ if (x >= 0x10) {
+ x >>= 4;
+ r += 4;
+ }
+ if (x >= 4) {
+ x >>= 2;
+ r += 2;
+ }
+ if (x >= 2)
+ r++;
+ return r;
+}
+
+/*
+ * async list handling
+ */
+
+static struct async *alloc_async(unsigned int numisoframes)
+{
+ unsigned int assize = sizeof(struct async) + numisoframes * sizeof(iso_packet_descriptor_t);
+ struct async *as = kmalloc(assize, GFP_KERNEL);
+ if (!as)
+ return NULL;
+ memset(as, 0, assize);
+ as->urb.number_of_packets = numisoframes;
+ return as;
+}
+
+static void free_async(struct async *as)
+{
+ if (as->urb.transfer_buffer)
+ kfree(as->urb.transfer_buffer);
+ kfree(as);
+}
+
+extern __inline__ void async_newpending(struct async *as)
+{
+ struct dev_state *ps = as->ps;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ps->lock, flags);
+ list_add_tail(&as->asynclist, &ps->async_pending);
+ spin_unlock_irqrestore(&ps->lock, flags);
+}
+
+extern __inline__ void async_removepending(struct async *as)
+{
+ struct dev_state *ps = as->ps;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ps->lock, flags);
+ list_del(&as->asynclist);
+ INIT_LIST_HEAD(&as->asynclist);
+ spin_unlock_irqrestore(&ps->lock, flags);
+}
+
+extern __inline__ struct async *async_getcompleted(struct dev_state *ps)
+{
+ unsigned long flags;
+ struct async *as = NULL;
+
+ spin_lock_irqsave(&ps->lock, flags);
+ if (!list_empty(&ps->async_completed)) {
+ as = list_entry(ps->async_completed.next, struct async, asynclist);
+ list_del(&as->asynclist);
+ INIT_LIST_HEAD(&as->asynclist);
+ }
+ spin_unlock_irqrestore(&ps->lock, flags);
+ return as;
+}
+
+extern __inline__ struct async *async_getpending(struct dev_state *ps, void *userurb)
+{
+ unsigned long flags;
+ struct async *as;
+ struct list_head *p;
+
+ spin_lock_irqsave(&ps->lock, flags);
+ for (p = ps->async_pending.next; p != &ps->async_pending; ) {
+ as = list_entry(p, struct async, asynclist);
+ p = p->next;
+ if (as->userurb != userurb)
+ continue;
+ list_del(&as->asynclist);
+ INIT_LIST_HEAD(&as->asynclist);
+ spin_unlock_irqrestore(&ps->lock, flags);
+ return as;
+ }
+ spin_unlock_irqrestore(&ps->lock, flags);
+ return NULL;
+}
+
+static void async_completed(purb_t urb)
+{
+ struct async *as = (struct async *)urb->context;
+ struct dev_state *ps = as->ps;
+ struct siginfo sinfo;
+
+#if 0
+ printk(KERN_DEBUG "usbdevfs: async_completed: status %d errcount %d actlen %d pipe 0x%x\n",
+ urb->status, urb->error_count, urb->actual_length, urb->pipe);
+#endif
+ spin_lock(&ps->lock);
+ list_del(&as->asynclist);
+ list_add_tail(&as->asynclist, &ps->async_completed);
+ spin_unlock(&ps->lock);
+ wake_up(&ps->wait);
+ if (as->signr) {
+ sinfo.si_signo = as->signr;
+ sinfo.si_errno = as->urb.status;
+ sinfo.si_code = SI_ASYNCIO;
+ sinfo.si_addr = as->userurb;
+ send_sig_info(as->signr, &sinfo, as->task);
+ }
+}
+
+static void destroy_all_async(struct dev_state *ps)
+{
+ struct async *as;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ps->lock, flags);
+ if (!list_empty(&ps->async_pending)) {
+ as = list_entry(ps->async_pending.next, struct async, asynclist);
+ list_del(&as->asynclist);
+ INIT_LIST_HEAD(&as->asynclist);
+ spin_unlock_irqrestore(&ps->lock, flags);
+ /* usb_unlink_urb calls the completion handler with status == USB_ST_URB_KILLED */
+ usb_unlink_urb(&as->urb);
+ spin_lock_irqsave(&ps->lock, flags);
+ }
+ spin_unlock_irqrestore(&ps->lock, flags);
+ while ((as = async_getcompleted(ps)))
+ free_async(as);
+}
+
+/*
+ * interface claiming
+ */
+
+static void *driver_probe(struct usb_device *dev, unsigned int intf)
+{
+ return NULL;
+}
+
+static void driver_disconnect(struct usb_device *dev, void *context)
+{
+ struct dev_state *ps = (struct dev_state *)context;
+
+ ps->ifclaimed = 0;
+}
+
+struct usb_driver usbdevfs_driver = {
+ "usbdevfs",
+ driver_probe,
+ driver_disconnect,
+ LIST_HEAD_INIT(usbdevfs_driver.driver_list),
+ NULL,
+ 0
+};
+
+static int claimintf(struct dev_state *ps, unsigned int intf)
+{
+ struct usb_device *dev = ps->dev;
+ struct usb_interface *iface;
+ int err;
+
+ if (intf >= 8*sizeof(ps->ifclaimed) || !dev || intf >= dev->actconfig->bNumInterfaces)
+ return -EINVAL;
+ /* already claimed */
+ if (test_bit(intf, &ps->ifclaimed))
+ return 0;
+ iface = &dev->actconfig->interface[intf];
+ err = -EBUSY;
+ lock_kernel();
+ if (!usb_interface_claimed(iface)) {
+ usb_driver_claim_interface(&usbdevfs_driver, iface, ps);
+ set_bit(intf, &ps->ifclaimed);
+ err = 0;
+ }
+ unlock_kernel();
+ return err;
+}
+
+static int releaseintf(struct dev_state *ps, unsigned int intf)
+{
+ struct usb_device *dev;
+ struct usb_interface *iface;
+ int err;
+
+ if (intf >= 8*sizeof(ps->ifclaimed))
+ return -EINVAL;
+ err = -EINVAL;
+ lock_kernel();
+ dev = ps->dev;
+ if (dev && test_and_clear_bit(intf, &ps->ifclaimed)) {
+ iface = &dev->actconfig->interface[intf];
+ usb_driver_release_interface(&usbdevfs_driver, iface);
+ err = 0;
+ }
+ unlock_kernel();
+ return err;
+}
+
+static int checkintf(struct dev_state *ps, unsigned int intf)
+{
+ if (intf >= 8*sizeof(ps->ifclaimed))
+ return -EINVAL;
+ if (test_bit(intf, &ps->ifclaimed))
+ return 0;
+ /* if not yet claimed, claim it for the driver */
+ printk(KERN_WARNING "usbdevfs: process %d (%s) did not claim interface %u before use\n",
+ current->pid, current->comm, intf);
+ return claimintf(ps, intf);
+}
+
+static int findintfep(struct usb_device *dev, unsigned int ep)
+{
+ unsigned int i, j, e;
+ struct usb_interface *iface;
+ struct usb_interface_descriptor *alts;
+ struct usb_endpoint_descriptor *endpt;
+
+ if (ep & ~(USB_DIR_IN|0xf))
+ return -EINVAL;
+ for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {
+ iface = &dev->actconfig->interface[i];
+ for (j = 0; j < iface->num_altsetting; j++) {
+ alts = &iface->altsetting[j];
+ for (e = 0; e < alts->bNumEndpoints; e++) {
+ endpt = &alts->endpoint[e];
+ if (endpt->bEndpointAddress == ep)
+ return i;
+ }
+ }
+ }
+ return -ENOENT;
+}
+
+static int findintfif(struct usb_device *dev, unsigned int ifn)
+{
+ unsigned int i, j;
+ struct usb_interface *iface;
+ struct usb_interface_descriptor *alts;
+
+ if (ifn & ~0xff)
+ return -EINVAL;
+ for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {
+ iface = &dev->actconfig->interface[i];
+ for (j = 0; j < iface->num_altsetting; j++) {
+ alts = &iface->altsetting[j];
+ if (alts->bInterfaceNumber == ifn)
+ return i;
+ }
+ }
+ return -ENOENT;
+}
+
+/*
+ * file operations
+ */
+static int usbdev_open(struct inode *inode, struct file *file)
+{
+ struct usb_device *dev;
+ struct dev_state *ps;
+ int ret;
+
+ /*
+ * no locking necessary here, as both sys_open (actually filp_open)
+ * and the hub thread have the kernel lock
+ * (still acquire the kernel lock for safety)
+ */
+ lock_kernel();
+ ret = -ENOENT;
+ if (ITYPE(inode->i_ino) != IDEVICE)
+ goto out;
+ dev = inode->u.usbdev_i.p.dev;
+ if (!dev)
+ goto out;
+ ret = -ENOMEM;
+ if (!(ps = kmalloc(sizeof(struct dev_state), GFP_KERNEL)))
+ goto out;
+ ret = 0;
+ ps->dev = dev;
+ ps->file = file;
+ spin_lock_init(&ps->lock);
+ INIT_LIST_HEAD(&ps->async_pending);
+ INIT_LIST_HEAD(&ps->async_completed);
+ init_waitqueue_head(&ps->wait);
+ init_rwsem(&ps->devsem);
+ ps->discsignr = 0;
+ ps->disctask = current;
+ ps->disccontext = NULL;
+ ps->ifclaimed = 0;
+ wmb();
+ list_add_tail(&ps->list, &dev->filelist);
+ file->private_data = ps;
+ out:
+ unlock_kernel();
+ return ret;
+}
+
+static int usbdev_release(struct inode *inode, struct file *file)
+{
+ struct dev_state *ps = (struct dev_state *)file->private_data;
+ unsigned int i;
+
+ lock_kernel();
+ list_del(&ps->list);
+ INIT_LIST_HEAD(&ps->list);
+ if (ps->dev) {
+ for (i = 0; ps->ifclaimed && i < 8*sizeof(ps->ifclaimed); i++)
+ if (test_bit(i, &ps->ifclaimed))
+ releaseintf(ps, i);
+ }
+ unlock_kernel();
+ destroy_all_async(ps);
+ kfree(ps);
+ return 0;
+}
+
+static int proc_control(struct dev_state *ps, void *arg)
+{
+ struct usb_device *dev = ps->dev;
+ struct usbdevfs_ctrltransfer ctrl;
+ unsigned int tmo;
+ unsigned char *tbuf;
+ int i, ret;
+
+ copy_from_user_ret(&ctrl, (void *)arg, sizeof(ctrl), -EFAULT);
+ switch (ctrl.requesttype & 0x1f) {
+ case USB_RECIP_ENDPOINT:
+ if ((ret = findintfep(ps->dev, ctrl.index & 0xff)) < 0)
+ return ret;
+ if ((ret = checkintf(ps, ret)))
+ return ret;
+ break;
+
+ case USB_RECIP_INTERFACE:
+ if ((ret = findintfif(ps->dev, ctrl.index & 0xff)) < 0)
+ return ret;
+ if ((ret = checkintf(ps, ret)))
+ return ret;
+ break;
+ }
+ if (ctrl.length > PAGE_SIZE)
+ return -EINVAL;
+ if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
+ return -ENOMEM;
+ tmo = (ctrl.timeout * HZ + 999) / 1000;
+ if (ctrl.requesttype & 0x80) {
+ if (ctrl.length && !access_ok(VERIFY_WRITE, ctrl.data, ctrl.length)) {
+ free_page((unsigned long)tbuf);
+ return -EINVAL;
+ }
+ i = my_usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.request, ctrl.requesttype,
+ ctrl.value, ctrl.index, tbuf, ctrl.length, tmo);
+ if ((i > 0) && ctrl.length) {
+ copy_to_user_ret(ctrl.data, tbuf, ctrl.length, -EFAULT);
+ }
+ } else {
+ if (ctrl.length) {
+ copy_from_user_ret(tbuf, ctrl.data, ctrl.length, -EFAULT);
+ }
+ i = my_usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.request, ctrl.requesttype,
+ ctrl.value, ctrl.index, tbuf, ctrl.length, tmo);
+ }
+ free_page((unsigned long)tbuf);
+ if (i<0) {
+ printk(KERN_DEBUG "usbdevfs: USBDEVFS_CONTROL failed dev %d rqt %u rq %u len %u ret %d\n",
+ dev->devnum, ctrl.requesttype, ctrl.request, ctrl.length, i);
+ }
+ return i;
+}
+
+static int proc_bulk(struct dev_state *ps, void *arg)
+{
+ struct usb_device *dev = ps->dev;
+ struct usbdevfs_bulktransfer bulk;
+ unsigned int tmo, len1, pipe;
+ int len2;
+ unsigned char *tbuf;
+ int i, ret;
+
+ copy_from_user_ret(&bulk, (void *)arg, sizeof(bulk), -EFAULT);
+ if ((ret = findintfep(ps->dev, bulk.ep)) < 0)
+ return ret;
+ if ((ret = checkintf(ps, ret)))
+ return ret;
+ if (bulk.ep & USB_DIR_IN)
+ pipe = usb_rcvbulkpipe(dev, bulk.ep & 0x7f);
+ else
+ pipe = usb_sndbulkpipe(dev, bulk.ep & 0x7f);
+ if (!usb_maxpacket(dev, pipe, !(bulk.ep & USB_DIR_IN)))
+ return -EINVAL;
+ len1 = bulk.len;
+ if (len1 > PAGE_SIZE)
+ len1 = PAGE_SIZE;
+ if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
+ return -ENOMEM;
+ tmo = (bulk.timeout * HZ + 999) / 1000;
+ if (bulk.ep & 0x80) {
+ if (len1 && !access_ok(VERIFY_WRITE, bulk.data, len1)) {
+ free_page((unsigned long)tbuf);
+ return -EINVAL;
+ }
+ i = my_usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
+ if (!i && len2) {
+ copy_to_user_ret(bulk.data, tbuf, len2, -EFAULT);
+ }
+ } else {
+ if (len1) {
+ copy_from_user_ret(tbuf, bulk.data, len1, -EFAULT);
+ }
+ i = my_usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
+ }
+ free_page((unsigned long)tbuf);
+ if (i < 0) {
+ printk(KERN_WARNING "usbdevfs: USBDEVFS_BULK failed dev %d ep 0x%x len %u ret %d\n",
+ dev->devnum, bulk.ep, bulk.len, i);
+ return i;
+ }
+ return len2;
+}
+
+static int proc_resetep(struct dev_state *ps, void *arg)
+{
+ unsigned int ep;
+ int ret;
+
+ get_user_ret(ep, (unsigned int *)arg, -EFAULT);
+ if ((ret = findintfep(ps->dev, ep)) < 0)
+ return ret;
+ if ((ret = checkintf(ps, ret)))
+ return ret;
+ usb_settoggle(ps->dev, ep & 0xf, !(ep & USB_DIR_IN), 0);
+ return 0;
+}
+
+static int proc_setintf(struct dev_state *ps, void *arg)
+{
+ struct usbdevfs_setinterface setintf;
+ int ret;
+
+ copy_from_user_ret(&setintf, arg, sizeof(setintf), -EFAULT);
+ if ((ret = findintfif(ps->dev, setintf.interface)) < 0)
+ return ret;
+ if ((ret = checkintf(ps, ret)))
+ return ret;
+ if (usb_set_interface(ps->dev, setintf.interface, setintf.altsetting))
+ return -EINVAL;
+ return 0;
+}
+
+static int proc_setconfig(struct dev_state *ps, void *arg)
+{
+ unsigned int u;
+
+ get_user_ret(u, (unsigned int *)arg, -EFAULT);
+ if (usb_set_configuration(ps->dev, u) < 0)
+ return -EINVAL;
+ return 0;
+}
+
+static int proc_submiturb(struct dev_state *ps, void *arg)
+{
+ struct usbdevfs_urb uurb;
+ struct usbdevfs_iso_packet_desc *isopkt = NULL;
+ struct async *as;
+ unsigned int u, totlen, isofrmlen;
+ int ret;
+
+ copy_from_user_ret(&uurb, arg, sizeof(uurb), -EFAULT);
+ if (uurb.flags & ~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_DISABLE_SPD))
+ return -EINVAL;
+ if (!uurb.buffer)
+ return -EINVAL;
+ if (uurb.signr != 0 && (uurb.signr < SIGRTMIN || uurb.signr > SIGRTMAX))
+ return -EINVAL;
+ if ((ret = findintfep(ps->dev, uurb.endpoint)) < 0)
+ return ret;
+ if ((ret = checkintf(ps, ret)))
+ return ret;
+ switch(uurb.type) {
+ case USBDEVFS_URB_TYPE_BULK:
+ uurb.number_of_packets = 0;
+ if (uurb.buffer_length > 16384)
+ return -EINVAL;
+ if (!access_ok((uurb.endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb.buffer, uurb.buffer_length))
+ return -EFAULT;
+ break;
+
+ case USBDEVFS_URB_TYPE_ISO:
+ /* arbitrary limit */
+ if (uurb.number_of_packets < 1 || uurb.number_of_packets > 128)
+ return -EINVAL;
+ isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * uurb.number_of_packets;
+ if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL)))
+ return -ENOMEM;
+ if (copy_from_user(isopkt, &((struct usbdevfs_urb *)arg)->iso_frame_desc, isofrmlen)) {
+ kfree(isopkt);
+ return -EFAULT;
+ }
+ for (totlen = u = 0; u < uurb.number_of_packets; u++) {
+ if (isopkt[u].length > 1023) {
+ kfree(isopkt);
+ return -EINVAL;
+ }
+ totlen += isopkt[u].length;
+ }
+ if (totlen > 32768) {
+ kfree(isopkt);
+ return -ENOMEM;
+ }
+ uurb.buffer_length = totlen;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ if (!(as = alloc_async(uurb.number_of_packets))) {
+ if (isopkt)
+ kfree(isopkt);
+ return -ENOMEM;
+ }
+ if (!(as->urb.transfer_buffer = kmalloc(uurb.buffer_length, GFP_KERNEL))) {
+ if (isopkt)
+ kfree(isopkt);
+ free_async(as);
+ return -ENOMEM;
+ }
+ as->urb.next = NULL;
+ as->urb.dev = ps->dev;
+ as->urb.pipe = (uurb.type << 30) | __create_pipe(ps->dev, uurb.endpoint & 0xf) | (uurb.endpoint & USB_DIR_IN);
+ as->urb.transfer_flags = uurb.flags;
+ as->urb.transfer_buffer_length = uurb.buffer_length;
+ as->urb.start_frame = uurb.start_frame;
+ as->urb.number_of_packets = uurb.number_of_packets;
+ as->urb.context = as;
+ as->urb.complete = async_completed;
+ for (totlen = u = 0; u < uurb.number_of_packets; u++) {
+ as->urb.iso_frame_desc[u].offset = totlen;
+ as->urb.iso_frame_desc[u].length = isopkt[u].length;
+ totlen += isopkt[u].length;
+ }
+ if (isopkt)
+ kfree(isopkt);
+ as->ps = ps;
+ as->userurb = arg;
+ if (uurb.endpoint & USB_DIR_IN)
+ as->userbuffer = uurb.buffer;
+ else
+ as->userbuffer = NULL;
+ as->signr = uurb.signr;
+ as->task = current;
+ if (!(uurb.endpoint & USB_DIR_IN)) {
+ if (copy_from_user(as->urb.transfer_buffer, uurb.buffer, as->urb.transfer_buffer_length)) {
+ free_async(as);
+ return -EFAULT;
+ }
+ }
+ async_newpending(as);
+ if ((ret = usb_submit_urb(&as->urb))) {
+ printk(KERN_DEBUG "usbdevfs: usb_submit_urb returned %d\n", ret);
+ async_removepending(as);
+ free_async(as);
+ return ret;
+ }
+ return 0;
+}
+
+static int proc_unlinkurb(struct dev_state *ps, void *arg)
+{
+ struct async *as;
+
+ as = async_getpending(ps, arg);
+ if (!as)
+ return -EINVAL;
+ usb_unlink_urb(&as->urb);
+ return 0;
+}
+
+static int processcompl(struct async *as)
+{
+ unsigned int i;
+
+ if (as->userbuffer)
+ if (copy_to_user(as->userbuffer, as->urb.transfer_buffer, as->urb.transfer_buffer_length))
+ return -EFAULT;
+ put_user_ret(as->urb.status, &((struct usbdevfs_urb *)as->userurb)->status, -EFAULT);
+ put_user_ret(as->urb.actual_length, &((struct usbdevfs_urb *)as->userurb)->actual_length, -EFAULT);
+ put_user_ret(as->urb.error_count, &((struct usbdevfs_urb *)as->userurb)->error_count, -EFAULT);
+ if (!(usb_pipeisoc(as->urb.pipe)))
+ return 0;
+ for (i = 0; i < as->urb.number_of_packets; i++) {
+ put_user_ret(as->urb.iso_frame_desc[i].actual_length,
+ &((struct usbdevfs_urb *)as->userurb)->iso_frame_desc[i].actual_length,
+ -EFAULT);
+ put_user_ret(as->urb.iso_frame_desc[i].status,
+ &((struct usbdevfs_urb *)as->userurb)->iso_frame_desc[i].status,
+ -EFAULT);
+ }
+ return 0;
+}
+
+static int proc_reapurb(struct dev_state *ps, void *arg)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ struct async *as = NULL;
+ void *addr;
+ int ret;
+
+ add_wait_queue(&ps->wait, &wait);
+ while (ps->dev) {
+ __set_current_state(TASK_INTERRUPTIBLE);
+ if ((as = async_getcompleted(ps)))
+ break;
+ if (signal_pending(current))
+ break;
+ up_read(&ps->devsem);
+ schedule();
+ down_read(&ps->devsem);
+ }
+ remove_wait_queue(&ps->wait, &wait);
+ set_current_state(TASK_RUNNING);
+ if (as) {
+ ret = processcompl(as);
+ addr = as->userurb;
+ free_async(as);
+ if (ret)
+ return ret;
+ put_user_ret(addr, (void **)arg, -EFAULT);
+ return 0;
+ }
+ if (signal_pending(current))
+ return -EINTR;
+ return -EIO;
+}
+
+static int proc_reapurbnonblock(struct dev_state *ps, void *arg)
+{
+ struct async *as;
+ void *addr;
+ int ret;
+
+ if (!(as = async_getcompleted(ps)))
+ return -EAGAIN;
+ ret = processcompl(as);
+ addr = as->userurb;
+ free_async(as);
+ if (ret)
+ return ret;
+ put_user_ret(addr, (void **)arg, -EFAULT);
+ return 0;
+}
+
+static int proc_disconnectsignal(struct dev_state *ps, void *arg)
+{
+ struct usbdevfs_disconnectsignal ds;
+
+ copy_from_user_ret(&ds, arg, sizeof(ds), -EFAULT);
+ if (ds.signr != 0 && (ds.signr < SIGRTMIN || ds.signr > SIGRTMAX))
+ return -EINVAL;
+ ps->discsignr = ds.signr;
+ ps->disccontext = ds.context;
+ return 0;
+}
+
+static int proc_claiminterface(struct dev_state *ps, void *arg)
+{
+ unsigned int intf;
+ int ret;
+
+ get_user_ret(intf, (unsigned int *)arg, -EFAULT);
+ if ((ret = findintfif(ps->dev, intf)) < 0)
+ return ret;
+ return claimintf(ps, ret);
+}
+
+static int proc_releaseinterface(struct dev_state *ps, void *arg)
+{
+ unsigned int intf;
+ int ret;
+
+ get_user_ret(intf, (unsigned int *)arg, -EFAULT);
+ if ((ret = findintfif(ps->dev, intf)) < 0)
+ return ret;
+ return releaseintf(ps, intf);
+}
+
+static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct dev_state *ps = (struct dev_state *)file->private_data;
+ int ret = -ENOIOCTLCMD;
+
+ if (!(file->f_mode & FMODE_WRITE))
+ return -EPERM;
+ down_read(&ps->devsem);
+ if (!ps->dev) {
+ up_read(&ps->devsem);
+ return -ENODEV;
+ }
+ switch (cmd) {
+ case USBDEVFS_CONTROL:
+ ret = proc_control(ps, (void *)arg);
+ if (ret >= 0)
+ inode->i_mtime = CURRENT_TIME;
+ break;
+
+ case USBDEVFS_BULK:
+ ret = proc_bulk(ps, (void *)arg);
+ if (ret >= 0)
+ inode->i_mtime = CURRENT_TIME;
+ break;
+
+ case USBDEVFS_RESETEP:
+ ret = proc_resetep(ps, (void *)arg);
+ if (ret >= 0)
+ inode->i_mtime = CURRENT_TIME;
+ break;
+
+ case USBDEVFS_SETINTERFACE:
+ ret = proc_setintf(ps, (void *)arg);
+ break;
+
+ case USBDEVFS_SETCONFIGURATION:
+ ret = proc_setconfig(ps, (void *)arg);
+ break;
+
+ case USBDEVFS_SUBMITURB:
+ ret = proc_submiturb(ps, (void *)arg);
+ if (ret >= 0)
+ inode->i_mtime = CURRENT_TIME;
+ break;
+
+ case USBDEVFS_DISCARDURB:
+ ret = proc_unlinkurb(ps, (void *)arg);
+ break;
+
+ case USBDEVFS_REAPURB:
+ ret = proc_reapurb(ps, (void *)arg);
+ break;
+
+ case USBDEVFS_REAPURBNDELAY:
+ ret = proc_reapurbnonblock(ps, (void *)arg);
+ break;
+
+ case USBDEVFS_DISCSIGNAL:
+ ret = proc_disconnectsignal(ps, (void *)arg);
+ break;
+
+ case USBDEVFS_CLAIMINTERFACE:
+ ret = proc_claiminterface(ps, (void *)arg);
+ break;
+
+ case USBDEVFS_RELEASEINTERFACE:
+ ret = proc_releaseinterface(ps, (void *)arg);
+ break;
+
+ }
+ up_read(&ps->devsem);
+ if (ret >= 0)
+ inode->i_atime = CURRENT_TIME;
+ return ret;
+}
+
+static unsigned int usbdev_poll(struct file *file, struct poll_table_struct *wait)
+{
+ struct dev_state *ps = (struct dev_state *)file->private_data;
+ unsigned int mask = 0;
+
+ poll_wait(file, &ps->wait, wait);
+ if (file->f_mode & FMODE_WRITE && !list_empty(&ps->async_completed))
+ mask |= POLLOUT | POLLWRNORM;
+ if (!ps->dev)
+ mask |= POLLERR | POLLHUP;
+ return mask;
+}
+
+static struct file_operations usbdevfs_device_file_operations = {
+ usbdev_lseek, /* lseek */
+ usbdev_read, /* read */
+ NULL, /* write */
+ NULL, /* readdir */
+ usbdev_poll, /* poll */
+ usbdev_ioctl, /* ioctl */
+ NULL, /* mmap */
+ usbdev_open, /* open */
+ NULL, /* flush */
+ usbdev_release, /* release */
+ NULL /* fsync */
+};
+
+struct inode_operations usbdevfs_device_inode_operations = {
+ &usbdevfs_device_file_operations, /* file-ops */
+};
diff --git a/drivers/usb/drivers.c b/drivers/usb/drivers.c
new file mode 100644
index 000000000..454130006
--- /dev/null
+++ b/drivers/usb/drivers.c
@@ -0,0 +1,126 @@
+/*
+ * drivers.c
+ * (C) Copyright 1999 Randy Dunlap.
+ * (C) Copyright 1999, 2000 Thomas Sailer <sailer@ife.ee.ethz.ch>. (proc file per device)
+ * (C) Copyright 1999 Deti Fliegl (new USB architecture)
+ *
+ * $id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ *************************************************************
+ *
+ * 1999-12-16: Thomas Sailer <sailer@ife.ee.ethz.ch>
+ * Converted the whole proc stuff to real
+ * read methods. Now not the whole device list needs to fit
+ * into one page, only the device list for one bus.
+ * Added a poll method to /proc/bus/usb/devices, to wake
+ * up an eventual usbd
+ * 2000-01-04: Thomas Sailer <sailer@ife.ee.ethz.ch>
+ * Turned into its own filesystem
+ *
+ * $Id: drivers.c,v 1.3 2000/01/11 13:58:24 tom Exp $
+ */
+
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <asm/uaccess.h>
+
+#include "usb.h"
+#include "usbdevice_fs.h"
+
+
+/*****************************************************************/
+
+/*
+ * Dump usb_driver_list.
+ *
+ * We now walk the list of registered USB drivers.
+ */
+static ssize_t usb_driver_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
+{
+ struct list_head *tmp = usb_driver_list.next;
+ char *page, *start, *end;
+ ssize_t ret = 0;
+ unsigned int pos, len;
+
+ if (*ppos < 0)
+ return -EINVAL;
+ if (nbytes <= 0)
+ return 0;
+ if (!access_ok(VERIFY_WRITE, buf, nbytes))
+ return -EFAULT;
+ if (!(page = (char*) __get_free_page(GFP_KERNEL)))
+ return -ENOMEM;
+ start = page;
+ end = page + (PAGE_SIZE - 100);
+ pos = *ppos;
+ for (; tmp != &usb_driver_list; tmp = tmp->next) {
+ struct usb_driver *driver = list_entry(tmp, struct usb_driver, driver_list);
+ start += sprintf (start, "%s\n", driver->name);
+ if (start > end) {
+ start += sprintf(start, "(truncated)\n");
+ break;
+ }
+ }
+ if (start == page)
+ start += sprintf(start, "(none)\n");
+ len = start - page;
+ if (len > pos) {
+ len -= pos;
+ if (len > nbytes)
+ len = nbytes;
+ ret = len;
+ if (copy_to_user(buf, page + pos, len))
+ ret = -EFAULT;
+ else
+ *ppos += len;
+ }
+ free_page((unsigned long)page);
+ return ret;
+}
+
+static long long usb_driver_lseek(struct file * file, long long offset, int orig)
+{
+ switch (orig) {
+ case 0:
+ file->f_pos = offset;
+ return file->f_pos;
+
+ case 1:
+ file->f_pos += offset;
+ return file->f_pos;
+
+ case 2:
+ return -EINVAL;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+struct file_operations usbdevfs_drivers_fops = {
+ usb_driver_lseek, /* lseek */
+ usb_driver_read, /* read */
+ NULL, /* write */
+ NULL, /* readdir */
+ NULL, /* poll */
+ NULL, /* ioctl */
+ NULL, /* mmap */
+ NULL, /* open */
+ NULL, /* flush */
+ NULL, /* release */
+ NULL /* fsync */
+};
diff --git a/drivers/usb/ezusb.c b/drivers/usb/ezusb.c
deleted file mode 100644
index eb6b23927..000000000
--- a/drivers/usb/ezusb.c
+++ /dev/null
@@ -1,1096 +0,0 @@
-/*****************************************************************************/
-
-/*
- * ezusb.c -- Firmware download miscdevice for Anchorchips EZUSB microcontrollers.
- *
- * Copyright (C) 1999
- * Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * History:
- * 0.1 26.05.99 Created
- * 0.2 23.07.99 Removed EZUSB_INTERRUPT. Interrupt pipes may be polled with
- * bulk reads.
- * Implemented EZUSB_SETINTERFACE, more sanity checks for EZUSB_BULK.
- * Preliminary ISO support
- * 0.3 01.09.99 Async Bulk and ISO support
- * 0.4 01.09.99 Set callback_frames to the total number of frames to make
- * it work with OHCI-HCD
- * 03.12.99 Now that USB error codes are negative, return them to application
- * instead of ENXIO
- * $Id: ezusb.c,v 1.22 1999/12/03 15:06:28 tom Exp $
- */
-
-/*****************************************************************************/
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/socket.h>
-#include <linux/miscdevice.h>
-#include <linux/list.h>
-#include <linux/vmalloc.h>
-#include <linux/slab.h>
-#include <asm/uaccess.h>
-
-//#include <linux/spinlock.h>
-
-#include "usb.h"
-#include "ezusb.h"
-
-/* --------------------------------------------------------------------- */
-
-#define NREZUSB 1
-
-static struct ezusb {
- struct semaphore mutex;
- struct usb_device *usbdev;
- struct list_head async_pending;
- struct list_head async_completed;
- wait_queue_head_t wait;
- spinlock_t lock;
-} ezusb[NREZUSB];
-
-struct async {
- struct list_head asynclist;
- struct ezusb *ez;
- void *userdata;
- unsigned datalen;
- void *context;
- urb_t urb;
-};
-
-/*-------------------------------------------------------------------*/
-
-static struct async *alloc_async(unsigned int numisoframes)
-{
- unsigned int assize = sizeof(struct async) + numisoframes * sizeof(iso_packet_descriptor_t);
- struct async *as = kmalloc(assize, GFP_KERNEL);
- if (!as)
- return NULL;
- memset(as, 0, assize);
- as->urb.number_of_packets = numisoframes;
- return as;
-}
-
-static void free_async(struct async *as)
-{
- if (as->urb.transfer_buffer)
- kfree(as->urb.transfer_buffer);
- kfree(as);
-}
-
-/* --------------------------------------------------------------------- */
-
-extern inline unsigned int ld2(unsigned int x)
-{
- unsigned int r = 0;
-
- if (x >= 0x10000) {
- x >>= 16;
- r += 16;
- }
- if (x >= 0x100) {
- x >>= 8;
- r += 8;
- }
- if (x >= 0x10) {
- x >>= 4;
- r += 4;
- }
- if (x >= 4) {
- x >>= 2;
- r += 2;
- }
- if (x >= 2)
- r++;
- return r;
-}
-
-#if 0
-/* why doesn't this work properly on i386? */
-extern inline unsigned int ld2(unsigned int x)
-{
- unsigned int r;
-
- __asm__("bsrl %1,%0" : "=r" (r) : "g" (x));
- return r;
-}
-#endif
-
-/* --------------------------------------------------------------------- */
-
-extern __inline__ void async_removelist(struct async *as)
-{
- struct ezusb *ez = as->ez;
- unsigned long flags;
-
- spin_lock_irqsave(&ez->lock, flags);
- list_del(&as->asynclist);
- INIT_LIST_HEAD(&as->asynclist);
- spin_unlock_irqrestore(&ez->lock, flags);
-}
-
-extern __inline__ void async_newpending(struct async *as)
-{
- struct ezusb *ez = as->ez;
- unsigned long flags;
-
- spin_lock_irqsave(&ez->lock, flags);
- list_add_tail(&as->asynclist, &ez->async_pending);
- spin_unlock_irqrestore(&ez->lock, flags);
-}
-
-extern __inline__ void async_removepending(struct async *as)
-{
- struct ezusb *ez = as->ez;
- unsigned long flags;
-
- spin_lock_irqsave(&ez->lock, flags);
- list_del(&as->asynclist);
- INIT_LIST_HEAD(&as->asynclist);
- spin_unlock_irqrestore(&ez->lock, flags);
-}
-
-extern __inline__ struct async *async_getcompleted(struct ezusb *ez)
-{
- unsigned long flags;
- struct async *as = NULL;
-
- spin_lock_irqsave(&ez->lock, flags);
- if (!list_empty(&ez->async_completed)) {
- as = list_entry(ez->async_completed.next, struct async, asynclist);
- list_del(&as->asynclist);
- INIT_LIST_HEAD(&as->asynclist);
- }
- spin_unlock_irqrestore(&ez->lock, flags);
- return as;
-}
-
-extern __inline__ struct async *async_getpending(struct ezusb *ez, void *context)
-{
- unsigned long flags;
- struct async *as;
- struct list_head *p;
-
- spin_lock_irqsave(&ez->lock, flags);
- for (p = ez->async_pending.next; p != &ez->async_pending; ) {
- as = list_entry(p, struct async, asynclist);
- p = p->next;
- if (as->context != context)
- continue;
- list_del(&as->asynclist);
- INIT_LIST_HEAD(&as->asynclist);
- spin_unlock_irqrestore(&ez->lock, flags);
- return as;
- }
- spin_unlock_irqrestore(&ez->lock, flags);
- return NULL;
-}
-
-/* --------------------------------------------------------------------- */
-
-static void async_completed(purb_t urb)
-{
- struct async *as = (struct async *)urb->context;
- struct ezusb *ez = as->ez;
- unsigned cnt;
-
-printk(KERN_DEBUG "ezusb: async_completed: status %d errcount %d actlen %d pipe 0x%x\n",
- urb->status, urb->error_count, urb->actual_length, urb->pipe);
- spin_lock(&ez->lock);
- list_del(&as->asynclist);
- list_add_tail(&as->asynclist, &ez->async_completed);
- spin_unlock(&ez->lock);
- wake_up(&ez->wait);
-}
-
-static void destroy_all_async(struct ezusb *ez)
-{
- struct async *as;
- unsigned long flags;
-
- spin_lock_irqsave(&ez->lock, flags);
- if (!list_empty(&ez->async_pending)) {
- as = list_entry(ez->async_pending.next, struct async, asynclist);
- list_del(&as->asynclist);
- INIT_LIST_HEAD(&as->asynclist);
- spin_unlock_irqrestore(&ez->lock, flags);
- /* discard_urb calls the completion handler with status == USB_ST_URB_KILLED */
- usb_unlink_urb(&as->urb);
- spin_lock_irqsave(&ez->lock, flags);
- }
- spin_unlock_irqrestore(&ez->lock, flags);
- while ((as = async_getcompleted(ez)))
- free_async(as);
-}
-
-/* --------------------------------------------------------------------- */
-
-static loff_t ezusb_llseek(struct file *file, loff_t offset, int origin)
-{
- struct ezusb *ez = (struct ezusb *)file->private_data;
-
- switch(origin) {
- case 1:
- offset += file->f_pos;
- break;
- case 2:
- offset += 0x10000;
- break;
- }
- if (offset < 0 || offset >= 0x10000)
- return -EINVAL;
- return (file->f_pos = offset);
-}
-
-static ssize_t ezusb_read(struct file *file, char *buf, size_t sz, loff_t *ppos)
-{
- struct ezusb *ez = (struct ezusb *)file->private_data;
- unsigned pos = *ppos;
- unsigned ret = 0;
- unsigned len;
- unsigned char b[64];
- int i;
-
- if (*ppos < 0 || *ppos >= 0x10000)
- return -EINVAL;
- down(&ez->mutex);
- if (!ez->usbdev) {
- up(&ez->mutex);
- return -EIO;
- }
- while (sz > 0 && pos < 0x10000) {
- len = sz;
- if (len > sizeof(b))
- len = sizeof(b);
- if (pos + len > 0x10000)
- len = 0x10000 - pos;
- i = usb_control_msg(ez->usbdev, usb_rcvctrlpipe(ez->usbdev, 0), 0xa0, 0xc0, pos, 0, b, len, HZ);
- if (i < 0) {
- up(&ez->mutex);
- printk(KERN_WARNING "ezusb: upload failed pos %u len %u ret %d\n", pos, len, i);
- *ppos = pos;
- if (ret)
- return ret;
- return i;
- }
- if (copy_to_user(buf, b, len)) {
- up(&ez->mutex);
- *ppos = pos;
- if (ret)
- return ret;
- return -EFAULT;
- }
- pos += len;
- buf += len;
- sz -= len;
- ret += len;
- }
- up(&ez->mutex);
- *ppos = pos;
- return ret;
-}
-
-static ssize_t ezusb_write(struct file *file, const char *buf, size_t sz, loff_t *ppos)
-{
- struct ezusb *ez = (struct ezusb *)file->private_data;
- unsigned pos = *ppos;
- unsigned ret = 0;
- unsigned len;
- unsigned char b[64];
- int i;
-
- if (*ppos < 0 || *ppos >= 0x10000)
- return -EINVAL;
- down(&ez->mutex);
- if (!ez->usbdev) {
- up(&ez->mutex);
- return -EIO;
- }
- while (sz > 0 && pos < 0x10000) {
- len = sz;
- if (len > sizeof(b))
- len = sizeof(b);
- if (pos + len > 0x10000)
- len = 0x10000 - pos;
- if (copy_from_user(b, buf, len)) {
- up(&ez->mutex);
- *ppos = pos;
- if (ret)
- return ret;
- return -EFAULT;
- }
- printk("writemem: %d %p %d\n",pos,b,len);
- i = usb_control_msg(ez->usbdev, usb_sndctrlpipe(ez->usbdev, 0), 0xa0, 0x40, pos, 0, b, len, HZ);
- if (i < 0) {
- up(&ez->mutex);
- printk(KERN_WARNING "ezusb: download failed pos %u len %u ret %d\n", pos, len, i);
- *ppos = pos;
- if (ret)
- return ret;
- return i;
- }
- pos += len;
- buf += len;
- sz -= len;
- ret += len;
- }
- up(&ez->mutex);
- *ppos = pos;
- return ret;
-}
-
-static int ezusb_open(struct inode *inode, struct file *file)
-{
- struct ezusb *ez = &ezusb[0];
-
- down(&ez->mutex);
- while (!ez->usbdev) {
- up(&ez->mutex);
- if (!(file->f_flags & O_NONBLOCK)) {
- return -EIO;
- }
- schedule_timeout(HZ/2);
- if (signal_pending(current))
- return -EAGAIN;
- down(&ez->mutex);
- }
- up(&ez->mutex);
- file->f_pos = 0;
- file->private_data = ez;
- MOD_INC_USE_COUNT;
- return 0;
-}
-
-static int ezusb_release(struct inode *inode, struct file *file)
-{
- struct ezusb *ez = (struct ezusb *)file->private_data;
-
- down(&ez->mutex);
- destroy_all_async(ez);
- up(&ez->mutex);
- MOD_DEC_USE_COUNT;
- return 0;
-}
-
-static int ezusb_control(struct usb_device *usbdev, unsigned char requesttype,
- unsigned char request, unsigned short value,
- unsigned short index, unsigned short length,
- unsigned int timeout, void *data)
-{
- unsigned char *tbuf = NULL;
- unsigned int pipe;
- int i;
-
- if (length > PAGE_SIZE)
- return -EINVAL;
- /* __range_ok is broken;
- with unsigned short size, it gave
- addl %si,%edx ; sbbl %ecx,%ecx; cmpl %edx,12(%eax); sbbl $0,%ecx
- */
- if (requesttype & 0x80) {
- pipe = usb_rcvctrlpipe(usbdev, 0);
- if (length > 0 && !access_ok(VERIFY_WRITE, data, (unsigned int)length))
- return -EFAULT;
- } else
- pipe = usb_sndctrlpipe(usbdev, 0);
- if (length > 0) {
- if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
- return -ENOMEM;
- if (!(requesttype & 0x80)) {
- if (copy_from_user(tbuf, data, length)) {
- free_page((unsigned long)tbuf);
- return -EFAULT;
- }
- }
- }
- i = usb_control_msg(usbdev, pipe, request, requesttype, value, index, tbuf, length, timeout);
- if (i < 0) {
- if (length > 0)
- free_page((unsigned long)tbuf);
- printk(KERN_WARNING "ezusb: EZUSB_CONTROL failed rqt %u rq %u len %u ret %d\n",
- requesttype, request, length, i);
- return i;
- }
- if (requesttype & 0x80 && length > 0 && copy_to_user(data, tbuf, length))
- i = -EFAULT;
- if (length > 0)
- free_page((unsigned long)tbuf);
- return i;
-}
-
-static int ezusb_bulk(struct usb_device *usbdev, unsigned int ep, unsigned int length, unsigned int timeout, void *data)
-{
- unsigned char *tbuf = NULL;
- unsigned int pipe;
- unsigned long len2 = 0;
- int ret = 0;
-
- if (length > PAGE_SIZE)
- return -EINVAL;
- if ((ep & ~0x80) >= 16)
- return -EINVAL;
- if (ep & 0x80) {
- pipe = usb_rcvbulkpipe(usbdev, ep & 0x7f);
- if (length > 0 && !access_ok(VERIFY_WRITE, data, length))
- return -EFAULT;
- } else
- pipe = usb_sndbulkpipe(usbdev, ep & 0x7f);
- if (!usb_maxpacket(usbdev, pipe, !(ep & 0x80)))
- return -EINVAL;
- if (length > 0) {
- if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
- return -ENOMEM;
- if (!(ep & 0x80)) {
- if (copy_from_user(tbuf, data, length)) {
- free_page((unsigned long)tbuf);
- return -EFAULT;
- }
- }
- }
- ret = usb_bulk_msg(usbdev, pipe, tbuf, length, &len2, timeout);
- if (ret < 0) {
- if (length > 0)
- free_page((unsigned long)tbuf);
- printk(KERN_WARNING "ezusb: EZUSB_BULK failed ep 0x%x len %u ret %d\n",
- ep, length, ret);
- return -ENXIO;
- }
- if (len2 > length)
- len2 = length;
- ret = len2;
- if (ep & 0x80 && len2 > 0 && copy_to_user(data, tbuf, len2))
- ret = -EFAULT;
- if (length > 0)
- free_page((unsigned long)tbuf);
- return ret;
-}
-
-static int ezusb_resetep(struct usb_device *usbdev, unsigned int ep)
-{
- if ((ep & ~0x80) >= 16)
- return -EINVAL;
- usb_settoggle(usbdev, ep & 0xf, !(ep & 0x80), 0);
- return 0;
-}
-
-static int ezusb_setinterface(struct usb_device *usbdev, unsigned int interface, unsigned int altsetting)
-{
- if (usb_set_interface(usbdev, interface, altsetting) < 0)
- return -EINVAL;
- return 0;
-}
-
-static int ezusb_setconfiguration(struct usb_device *usbdev, unsigned int config)
-{
- if (usb_set_configuration(usbdev, config) < 0)
- return -EINVAL;
- return 0;
-}
-
-#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)
-
-char* stuff[512];
-
-static void int_compl(purb_t purb)
-{
- printk("INT_COMPL\n");
-
-}
-
-static int ezusb_interrupt(struct ezusb *ez, struct ezusb_interrupt *ab)
-{
- urb_t *urb;
- unsigned int pipe;
-
- urb=(urb_t*)kmalloc(sizeof(urb_t),GFP_KERNEL);
- if (!urb)
- {
- return -ENOMEM;
- }
- memset(urb,0,sizeof(urb_t));
-
-
- if ((ab->ep & ~0x80) >= 16)
- return -EINVAL;
- if (ab->ep & 0x80)
- {
- pipe = usb_rcvintpipe(ez->usbdev, ab->ep & 0x7f);
- if (ab->len > 0 && !access_ok(VERIFY_WRITE, ab->data, ab->len))
- return -EFAULT;
- }
- else
- pipe = usb_sndintpipe(ez->usbdev, ab->ep & 0x7f);
-
- memcpy(stuff,ab->data,64);
- urb->transfer_buffer=stuff;
- urb->transfer_buffer_length=ab->len;
- urb->complete=int_compl;
- urb->pipe=pipe;
- urb->dev=ez->usbdev;
- urb->interval=ab->interval;
- return usb_submit_urb(urb);
-}
-
-static int ezusb_requestbulk(struct ezusb *ez, struct ezusb_asyncbulk *ab)
-{
- struct async *as = NULL;
- void *data = NULL;
- unsigned int pipe;
- int ret;
-
- if (ab->len > PAGE_SIZE)
- return -EINVAL;
- if ((ab->ep & ~0x80) >= 16)
- return -EINVAL;
- if (ab->ep & 0x80) {
- pipe = usb_rcvbulkpipe(ez->usbdev, ab->ep & 0x7f);
- if (ab->len > 0 && !access_ok(VERIFY_WRITE, ab->data, ab->len))
- return -EFAULT;
- } else
- pipe = usb_sndbulkpipe(ez->usbdev, ab->ep & 0x7f);
- if (!usb_maxpacket(ez->usbdev, pipe, !(ab->ep & 0x80)))
- return -EINVAL;
- if (ab->len > 0 && !(data = kmalloc(ab->len, GFP_KERNEL)))
- return -ENOMEM;
- if (!(as = alloc_async(0))) {
- if (data)
- kfree(data);
- return -ENOMEM;
- }
- INIT_LIST_HEAD(&as->asynclist);
- as->ez = ez;
- as->userdata = ab->data;
- as->datalen = ab->len;
- as->context = ab->context;
- as->urb.dev = ez->usbdev;
- as->urb.pipe = pipe;
- as->urb.transfer_flags = 0;
- as->urb.transfer_buffer = data;
- as->urb.transfer_buffer_length = ab->len;
- as->urb.context = as;
- as->urb.complete = (usb_complete_t)async_completed;
- if (ab->len > 0 && !(ab->ep & 0x80)) {
- if (copy_from_user(data, ab->data, ab->len)) {
- free_async(as);
- return -EFAULT;
- }
- as->userdata = NULL; /* no need to copy back at completion */
- }
- async_newpending(as);
- if ((ret = usb_submit_urb(&as->urb))) {
- printk(KERN_DEBUG "ezusb: bulk: usb_submit_urb returned %d\n", ret);
- async_removepending(as);
- free_async(as);
- return -EINVAL; /* return ret; */
- }
- return 0;
-}
-
-static int ezusb_requestiso(struct ezusb *ez, struct ezusb_asynciso *ai, unsigned char *cmd)
-{
- struct async *as;
- void *data = NULL;
- unsigned int maxpkt, pipe, dsize, totsize, i, j;
- int ret;
-
- if ((ai->ep & ~0x80) >= 16 || ai->framecnt < 1 || ai->framecnt > 128)
- return -EINVAL;
- if (ai->ep & 0x80)
- pipe = usb_rcvisocpipe(ez->usbdev, ai->ep & 0x7f);
- else
- pipe = usb_sndisocpipe(ez->usbdev, ai->ep & 0x7f);
- if (!(maxpkt = usb_maxpacket(ez->usbdev, pipe, !(ai->ep & 0x80))))
- return -EINVAL;
- dsize = maxpkt * ai->framecnt;
-//printk(KERN_DEBUG "ezusb: iso: dsize %d\n", dsize);
- if (dsize > 65536)
- return -EINVAL;
- if (ai->ep & 0x80)
- if (dsize > 0 && !access_ok(VERIFY_WRITE, ai->data, dsize))
- return -EFAULT;
- if (dsize > 0 && !(data = kmalloc(dsize, GFP_KERNEL)))
- {
- printk("dsize: %d failed\n",dsize);
- return -ENOMEM;
- }
- if (!(as = alloc_async(ai->framecnt))) {
- if (data)
- kfree(data);
- printk("alloc_async failed\n");
- return -ENOMEM;
- }
- INIT_LIST_HEAD(&as->asynclist);
-
- as->ez = ez;
- as->userdata = ai->data;
- as->datalen = dsize;
- as->context = ai->context;
-
- as->urb.dev = ez->usbdev;
- as->urb.pipe = pipe;
- as->urb.transfer_flags = USB_ISO_ASAP;
- as->urb.transfer_buffer = data;
- as->urb.transfer_buffer_length = dsize;
- as->urb.context = as;
- as->urb.complete = (usb_complete_t)async_completed;
-
- for (i = totsize = 0; i < as->urb.number_of_packets; i++) {
- as->urb.iso_frame_desc[i].offset = totsize;
- if (get_user(j, (int *)(cmd + i * sizeof(struct ezusb_isoframestat)))) {
- free_async(as);
- return -EFAULT;
- }
- as->urb.iso_frame_desc[i].length = j;
- totsize += j;
- }
- if (dsize > 0 && totsize > 0 && !(ai->ep & 0x80)) {
- if (copy_from_user(data, ai->data, totsize)) {
- free_async(as);
- return -EFAULT;
- }
- as->userdata = NULL; /* no need to copy back at completion */
- }
- async_newpending(as);
- if ((ret = usb_submit_urb(&as->urb))) {
- printk(KERN_DEBUG "ezusb: iso: usb_submit_urb returned %d\n", ret);
- async_removepending(as);
- free_async(as);
- return -EINVAL; /* return ret; */
- }
- return 0;
-}
-
-static int ezusb_terminateasync(struct ezusb *ez, void *context)
-{
- struct async *as;
- int ret = 0;
-
- while ((as = async_getpending(ez, context))) {
- usb_unlink_urb(&as->urb);
- ret++;
- }
- return ret;
-}
-
-static int ezusb_asynccompl(struct async *as, void *arg)
-{
- struct ezusb_asynccompleted *cpl;
- unsigned int numframes, cplsize, i;
-
- if (as->userdata) {
- if (copy_to_user(as->userdata, as->urb.transfer_buffer, as->datalen)) {
- free_async(as);
- return -EFAULT;
- }
- }
- numframes = as->urb.number_of_packets;
- cplsize = sizeof(struct ezusb_asynccompleted) + numframes * sizeof(struct ezusb_isoframestat);
- if (!(cpl = kmalloc(cplsize, GFP_KERNEL))) {
- free_async(as);
- return -ENOMEM;
- }
- cpl->status = as->urb.status;
- cpl->length = as->urb.actual_length;
- cpl->context = as->context;
- for (i = 0; i < numframes; i++) {
- cpl->isostat[i].length = as->urb.iso_frame_desc[i].length;
- cpl->isostat[i].status = as->urb.iso_frame_desc[i].status;
- }
- free_async(as);
- if (copy_to_user(arg, cpl, cplsize)) {
- kfree(cpl);
- return -EFAULT;
- }
- kfree(cpl);
- return 0;
-}
-
-static int ezusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
- struct ezusb *ez = (struct ezusb *)file->private_data;
- DECLARE_WAITQUEUE(wait, current);
- struct usb_proc_ctrltransfer pctrl;
- struct usb_proc_bulktransfer pbulk;
- struct usb_proc_old_ctrltransfer opctrl;
- struct usb_proc_old_bulktransfer opbulk;
- struct usb_proc_setinterface psetintf;
- struct ezusb_ctrltransfer ctrl;
- struct ezusb_bulktransfer bulk;
- struct ezusb_old_ctrltransfer octrl;
- struct ezusb_old_bulktransfer obulk;
- struct ezusb_setinterface setintf;
- struct ezusb_asyncbulk abulk;
- struct ezusb_asynciso aiso;
- struct ezusb_interrupt ezint;
- struct async *as;
- void *context;
- unsigned int ep, cfg;
- int i, ret = 0;
-
- down(&ez->mutex);
- if (!ez->usbdev) {
- up(&ez->mutex);
- return -EIO;
- }
- switch (cmd) {
- case USB_PROC_CONTROL:
- if (copy_from_user(&pctrl, (void *)arg, sizeof(pctrl))) {
- ret = -EFAULT;
- break;
- }
- ret = ezusb_control(ez->usbdev, pctrl.requesttype, pctrl.request,
- pctrl.value, pctrl.index, pctrl.length,
- (pctrl.timeout * HZ + 500) / 1000, pctrl.data);
- break;
-
- case USB_PROC_BULK:
- if (copy_from_user(&pbulk, (void *)arg, sizeof(pbulk))) {
- ret = -EFAULT;
- break;
- }
- ret = ezusb_bulk(ez->usbdev, pbulk.ep, pbulk.len,
- (pbulk.timeout * HZ + 500) / 1000, pbulk.data);
- break;
-
- case USB_PROC_OLD_CONTROL:
- if (copy_from_user(&opctrl, (void *)arg, sizeof(opctrl))) {
- ret = -EFAULT;
- break;
- }
- ret = ezusb_control(ez->usbdev, opctrl.requesttype, opctrl.request,
- opctrl.value, opctrl.index, opctrl.length, HZ, opctrl.data);
- break;
-
- case USB_PROC_OLD_BULK:
- if (copy_from_user(&opbulk, (void *)arg, sizeof(opbulk))) {
- ret = -EFAULT;
- break;
- }
- ret = ezusb_bulk(ez->usbdev, opbulk.ep, opbulk.len, 5*HZ, opbulk.data);
- break;
-
- case USB_PROC_RESETEP:
- if (get_user(ep, (unsigned int *)arg)) {
- ret = -EFAULT;
- break;
- }
- ret = ezusb_resetep(ez->usbdev, ep);
- break;
-
- case USB_PROC_SETINTERFACE:
- if (copy_from_user(&psetintf, (void *)arg, sizeof(psetintf))) {
- ret = -EFAULT;
- break;
- }
- ret = ezusb_setinterface(ez->usbdev, psetintf.interface, psetintf.altsetting);
- break;
-
- case USB_PROC_SETCONFIGURATION:
- if (get_user(cfg, (unsigned int *)arg)) {
- ret = -EFAULT;
- break;
- }
- ret = ezusb_setconfiguration(ez->usbdev, cfg);
- break;
-
- case EZUSB_CONTROL:
- if (copy_from_user(&ctrl, (void *)arg, sizeof(ctrl))) {
- ret = -EFAULT;
- break;
- }
- ret = ezusb_control(ez->usbdev, ctrl.requesttype, ctrl.request,
- ctrl.value, ctrl.index, ctrl.length,
- (ctrl.timeout * HZ + 500) / 1000, ctrl.data);
- break;
-
- case EZUSB_BULK:
- if (copy_from_user(&bulk, (void *)arg, sizeof(bulk))) {
- ret = -EFAULT;
- break;
- }
- ret = ezusb_bulk(ez->usbdev, bulk.ep, bulk.len,
- (bulk.timeout * HZ + 500) / 1000, bulk.data);
- break;
-
- case EZUSB_OLD_CONTROL:
- if (copy_from_user(&octrl, (void *)arg, sizeof(octrl))) {
- ret = -EFAULT;
- break;
- }
- if (octrl.dlen != octrl.length) {
- ret = -EINVAL;
- break;
- }
- ret = ezusb_control(ez->usbdev, octrl.requesttype, octrl.request,
- octrl.value, octrl.index, octrl.length, HZ, octrl.data);
- break;
-
- case EZUSB_OLD_BULK:
- if (copy_from_user(&obulk, (void *)arg, sizeof(obulk))) {
- ret = -EFAULT;
- break;
- }
- ret = ezusb_bulk(ez->usbdev, obulk.ep, obulk.len, 5*HZ, obulk.data);
- break;
-
- case EZUSB_RESETEP:
- if (get_user(ep, (unsigned int *)arg)) {
- ret = -EFAULT;
- break;
- }
- ret = ezusb_resetep(ez->usbdev, ep);
- break;
-
- case EZUSB_SETINTERFACE:
- if (copy_from_user(&setintf, (void *)arg, sizeof(setintf))) {
- ret = -EFAULT;
- break;
- }
- ret = ezusb_setinterface(ez->usbdev, setintf.interface, setintf.altsetting);
- break;
-
- case EZUSB_SETCONFIGURATION:
- if (get_user(cfg, (unsigned int *)arg)) {
- ret = -EFAULT;
- break;
- }
- ret = ezusb_setconfiguration(ez->usbdev, cfg);
- break;
-
- case EZUSB_ASYNCCOMPLETED:
- as = NULL;
- current->state = TASK_INTERRUPTIBLE;
- add_wait_queue(&ez->wait, &wait);
- for (;;) {
- if (!ez->usbdev)
- break;
- if ((as = async_getcompleted(ez)))
- break;
- if (signal_pending(current))
- break;
- up(&ez->mutex);
- schedule();
- down(&ez->mutex);
- }
- remove_wait_queue(&ez->wait, &wait);
- current->state = TASK_RUNNING;
- if (as) {
- ret = ezusb_asynccompl(as, (void *)arg);
- break;
- }
- if (signal_pending(current)) {
- ret = -EINTR;
- break;
- }
- ret = -EIO;
- break;
-
- case EZUSB_ASYNCCOMPLETEDNB:
- if ((as = async_getcompleted(ez))) {
- ret = ezusb_asynccompl(as, (void *)arg);
- break;
- }
- ret = -EAGAIN;
- break;
-
- case EZUSB_REQUESTBULK:
- if (copy_from_user(&abulk, (void *)arg, sizeof(abulk))) {
- ret = -EFAULT;
- break;
- }
- ret = ezusb_requestbulk(ez, &abulk);
- break;
-
- case EZUSB_REQUESTISO:
- if (copy_from_user(&aiso, (void *)arg, sizeof(aiso))) {
- ret = -EFAULT;
- break;
- }
- ret = ezusb_requestiso(ez, &aiso, ((unsigned char *)arg)+sizeof(aiso));
- break;
-
- case EZUSB_TERMINATEASYNC:
- if (get_user(context, (void **)arg)) {
- ret = -EFAULT;
- break;
- }
- ret = ezusb_terminateasync(ez, context);
- break;
-
- case EZUSB_GETFRAMENUMBER:
- i = usb_get_current_frame_number(ez->usbdev);
- ret = put_user(i, (int *)arg);
- break;
-
- case EZUSB_INTERRUPT:
- printk("INT START\n");
- if (copy_from_user(&ezint, (void *)arg, sizeof(ezint))) {
- ret = -EFAULT;
- break;
- }
- ret=ezusb_interrupt(ez,&ezint);
- break;
- default:
- ret = -ENOIOCTLCMD;
- break;
- }
- up(&ez->mutex);
- return ret;
-}
-
-static struct file_operations ezusb_fops = {
- ezusb_llseek,
- ezusb_read,
- ezusb_write,
- NULL, /* readdir */
- NULL, /* poll */
- ezusb_ioctl,
- NULL, /* mmap */
- ezusb_open,
- NULL, /* flush */
- ezusb_release,
- NULL, /* fsync */
- NULL, /* fasync */
- NULL /* lock */
-};
-
-/* --------------------------------------------------------------------- */
-
-static void * ezusb_probe(struct usb_device *usbdev, unsigned int ifnum)
-{
- struct ezusb *ez = &ezusb[0];
- struct usb_interface_descriptor *interface;
- struct usb_endpoint_descriptor *endpoint;
-
-#undef KERN_DEBUG
-#define KERN_DEBUG ""
- printk(KERN_DEBUG "ezusb: probe: vendor id 0x%x, device id 0x%x\n",
- usbdev->descriptor.idVendor, usbdev->descriptor.idProduct);
-
- /* the 1234:5678 is just a self assigned test ID */
- if ((usbdev->descriptor.idVendor != 0x0547 || usbdev->descriptor.idProduct != 0x2131)
- #if 1
- &&
- (usbdev->descriptor.idVendor != 0x0547 || usbdev->descriptor.idProduct != 0x9999) &&
- (usbdev->descriptor.idVendor != 0x1234 || usbdev->descriptor.idProduct != 0x5678)
- #endif
- )
- return NULL;
-
- /* We don't handle multiple configurations */
- if (usbdev->descriptor.bNumConfigurations != 1)
- return NULL;
-
-#if 0
- /* We don't handle multiple interfaces */
- if (usbdev->config[0].bNumInterfaces != 1)
- return NULL;
-#endif
-
- down(&ez->mutex);
- if (ez->usbdev) {
- up(&ez->mutex);
- printk(KERN_INFO "ezusb: device already used\n");
- return NULL;
- }
- ez->usbdev = usbdev;
- if (usb_set_configuration(usbdev, usbdev->config[0].bConfigurationValue) < 0) {
- printk(KERN_ERR "ezusb: set_configuration failed\n");
- goto err;
- }
-
- interface = &usbdev->config[0].interface[0].altsetting[1];
- if (usb_set_interface(usbdev, 0, 1) < 0) {
- printk(KERN_ERR "ezusb: set_interface failed\n");
- goto err;
- }
- up(&ez->mutex);
- MOD_INC_USE_COUNT;
- return ez;
-
- err:
- up(&ez->mutex);
- ez->usbdev = NULL;
- return NULL;
-}
-
-static void ezusb_disconnect(struct usb_device *usbdev, void *ptr)
-{
- struct ezusb *ez = (struct ezusb *)ptr;
-
- down(&ez->mutex);
- destroy_all_async(ez);
- ez->usbdev = NULL;
- up(&ez->mutex);
- wake_up(&ez->wait);
- MOD_DEC_USE_COUNT;
-}
-
-static struct usb_driver ezusb_driver = {
- "ezusb",
- ezusb_probe,
- ezusb_disconnect,
- { NULL, NULL },
- &ezusb_fops,
- 192
-};
-
-/* --------------------------------------------------------------------- */
-
-int ezusb_init(void)
-{
- unsigned u;
-
- /* initialize struct */
- for (u = 0; u < NREZUSB; u++) {
- init_MUTEX(&ezusb[u].mutex);
- ezusb[u].usbdev = NULL;
- INIT_LIST_HEAD(&ezusb[u].async_pending);
- INIT_LIST_HEAD(&ezusb[u].async_completed);
- init_waitqueue_head(&ezusb[u].wait);
- spin_lock_init(&ezusb[u].lock);
- }
- /* register misc device */
- usb_register(&ezusb_driver);
- printk(KERN_INFO "ezusb: Anchorchip firmware download driver registered\n");
- return 0;
-}
-
-void ezusb_cleanup(void)
-{
- usb_deregister(&ezusb_driver);
-}
-
-/* --------------------------------------------------------------------- */
-
-#ifdef MODULE
-
-int minor = 192;
-
-int init_module(void)
-{
- return ezusb_init();
-}
-
-void cleanup_module(void)
-{
- ezusb_cleanup();
-}
-
-#endif
-
-/* --------------------------------------------------------------------- */
diff --git a/drivers/usb/ezusb.h b/drivers/usb/ezusb.h
deleted file mode 100644
index b7d480558..000000000
--- a/drivers/usb/ezusb.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*****************************************************************************/
-
-/*
- * ezusb.h -- Firmware download miscdevice for Anchorchips EZUSB microcontrollers.
- *
- * Copyright (C) 1999
- * Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-/*****************************************************************************/
-
-#ifndef _LINUX_EZUSB_H
-#define _LINUX_EZUSB_H
-
-#include <linux/ioctl.h>
-
-/* --------------------------------------------------------------------- */
-
-struct ezusb_old_ctrltransfer {
- /* keep in sync with usb.h:devrequest */
- unsigned char requesttype;
- unsigned char request;
- unsigned short value;
- unsigned short index;
- unsigned short length;
- unsigned int dlen;
- void *data;
-};
-
-struct ezusb_old_bulktransfer {
- unsigned int ep;
- unsigned int len;
- void *data;
-};
-
-struct ezusb_ctrltransfer {
- /* keep in sync with usb.h:devrequest */
- unsigned char requesttype;
- unsigned char request;
- unsigned short value;
- unsigned short index;
- unsigned short length;
- unsigned int timeout; /* in milliseconds */
- void *data;
-};
-
-struct ezusb_bulktransfer {
- unsigned int ep;
- unsigned int len;
- unsigned int timeout; /* in milliseconds */
- void *data;
-};
-
-struct ezusb_interrupt {
- unsigned int ep;
- unsigned int len;
- unsigned int interval; /* in milliseconds */
- void *data;
-};
-struct ezusb_setinterface {
- unsigned int interface;
- unsigned int altsetting;
-};
-
-struct ezusb_isoframestat {
- unsigned int length;
- unsigned int status;
-};
-
-struct ezusb_asynccompleted {
- int status;
- unsigned length;
- void *context;
- struct ezusb_isoframestat isostat[0];
-};
-
-struct ezusb_asyncbulk {
- unsigned int ep;
- unsigned int len;
- void *context;
- void *data;
-};
-
-struct ezusb_asynciso {
- unsigned int ep;
-
- unsigned int framecnt;
- unsigned int startframe;
-
- void *context;
- void *data;
- struct ezusb_isoframestat isostat[0];
-};
-
-#define EZUSB_CONTROL _IOWR('E', 1, struct ezusb_ctrltransfer)
-#define EZUSB_BULK _IOWR('E', 2, struct ezusb_bulktransfer)
-#define EZUSB_OLD_CONTROL _IOWR('E', 0, struct ezusb_old_ctrltransfer)
-#define EZUSB_OLD_BULK _IOWR('E', 2, struct ezusb_old_bulktransfer)
-#define EZUSB_RESETEP _IOR('E', 3, unsigned int)
-#define EZUSB_SETINTERFACE _IOR('E', 4, struct ezusb_setinterface)
-#define EZUSB_SETCONFIGURATION _IOR('E', 5, unsigned int)
-#define EZUSB_ASYNCCOMPLETED _IOW('E', 8, struct ezusb_asynccompleted)
-#define EZUSB_ASYNCCOMPLETEDNB _IOW('E', 9, struct ezusb_asynccompleted)
-#define EZUSB_REQUESTBULK _IOR('E', 16, struct ezusb_asyncbulk)
-#define EZUSB_REQUESTISO _IOR('E', 17, struct ezusb_asynciso)
-#define EZUSB_TERMINATEASYNC _IOR('E', 18, void *)
-#define EZUSB_GETFRAMENUMBER _IOW('E', 19, unsigned int)
-#define EZUSB_INTERRUPT _IOWR('E', 20, struct ezusb_interrupt)
-
-/* --------------------------------------------------------------------- */
-#endif /* _LINUX_EZUSB_H */
diff --git a/drivers/usb/graphire.c b/drivers/usb/graphire.c
new file mode 100644
index 000000000..cfda14d5c
--- /dev/null
+++ b/drivers/usb/graphire.c
@@ -0,0 +1,186 @@
+/*
+ * graphire.c Version 0.1
+ *
+ * Copyright (c) 1999 Vojtech Pavlik
+ *
+ * USB Wacom Graphire tablet support
+ *
+ * Sponsored by SuSE
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include <linux/kernel.h>
+#include <linux/malloc.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include "usb.h"
+
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
+
+/*
+ * Thanks for the following information to: Andreas Bach Aaen <abach@mail1.stofanet.dk>
+ *
+ * The input report:
+ *
+ * byte 0: report ID (2)
+ * byte 1: bit7 mouse/pen/rubber near
+ * bit5-6 0 - pen, 1 - rubber, 2 - mouse
+ * bit4 1 ?
+ * bit3 0 ?
+ * bit2 mouse middle button / pen button2
+ * bit1 mouse right button / pen button1
+ * bit0 mouse left button / pen tip / rubber
+ * byte 2: X low bits
+ * byte 3: X high bits
+ * byte 4: Y low bits
+ * byte 5: Y high bits
+ * byte 6: pen pressure low bits / mouse wheel
+ * byte 7: pen presure high bits / mouse distance
+ *
+ * There are also two single-byte feature reports (2 and 3).
+ */
+
+#define USB_VENDOR_ID_WACOM 0xffff /* FIXME */
+#define USB_DEVICE_ID_WACOM_GRAPHIRE 0xffff /* FIXME */
+
+struct graphire {
+ signed char data[8];
+ int oldx, oldy;
+ struct input_dev dev;
+ struct urb irq;
+};
+
+static void graphire_irq(struct urb *urb)
+{
+ struct graphire *graphire = urb->context;
+ unsigned char *data = graphire->data;
+ struct input_dev *dev = &graphire->dev;
+
+ if (urb->status) return;
+
+ if (data[0] != 2)
+ dbg("received unknown report #%d", data[0]);
+
+ input_report_abs(dev, ABS_X, data[2] | ((__u32)data[3] << 8));
+ input_report_abs(dev, ABS_Y, data[4] | ((__u32)data[5] << 8));
+
+ input_report_key(dev, BTN_NEAR, !!(data[1] & 0x80));
+
+ switch ((data[1] >> 5) & 3) {
+
+ case 0: /* Pen */
+ input_report_key(dev, BTN_PEN, !!(data[1] & 0x01));
+ input_report_key(dev, BTN_PEN_SIDE, !!(data[1] & 0x02));
+ input_report_key(dev, BTN_PEN_SIDE2, !!(data[1] & 0x04));
+ input_report_abs(dev, ABS_PRESSURE, data[6] | ((__u32)data[7] << 8));
+ break;
+
+ case 1: /* Rubber */
+ input_report_key(dev, BTN_RUBBER, !!(data[1] & 0x01));
+ input_report_key(dev, BTN_PEN_SIDE, !!(data[1] & 0x02));
+ input_report_key(dev, BTN_PEN_SIDE2, !!(data[1] & 0x04));
+ input_report_abs(dev, ABS_PRESSURE, data[6] | ((__u32)data[7] << 8));
+ break;
+
+ case 2: /* Mouse */
+ input_report_key(dev, BTN_LEFT, !!(data[0] & 0x01));
+ input_report_key(dev, BTN_RIGHT, !!(data[0] & 0x02));
+ input_report_key(dev, BTN_MIDDLE, !!(data[0] & 0x04));
+ input_report_abs(dev, ABS_DISTANCE, data[7]);
+
+ if (data[1] & 0x80) {
+ input_report_rel(dev, REL_X, dev->abs[ABS_X] - graphire->oldx);
+ input_report_rel(dev, REL_Y, dev->abs[ABS_Y] - graphire->oldy);
+ }
+
+ input_report_rel(dev, REL_WHEEL, (signed char) data[6]);
+ break;
+ }
+
+ graphire->oldx = dev->abs[ABS_X];
+ graphire->oldy = dev->abs[ABS_Y];
+}
+
+static void *graphire_probe(struct usb_device *dev, unsigned int ifnum)
+{
+ struct usb_endpoint_descriptor *endpoint;
+ struct graphire *graphire;
+
+ if (dev->descriptor.idVendor != USB_VENDOR_ID_WACOM ||
+ dev->descriptor.idProduct != USB_DEVICE_ID_WACOM_GRAPHIRE)
+ return NULL;
+
+ endpoint = dev->config[0].interface[ifnum].altsetting[0].endpoint + 0;
+
+ if (!(graphire = kmalloc(sizeof(struct graphire), GFP_KERNEL))) return NULL;
+ memset(graphire, 0, sizeof(struct graphire));
+
+ graphire->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);
+ graphire->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
+ graphire->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_PEN) | BIT(BTN_RUBBER);
+ graphire->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_PEN_SIDE) | BIT(BTN_PEN_SIDE2) | BIT(BTN_NEAR);
+ graphire->dev.relbit[0] |= BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL);
+ graphire->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | BIT(ABS_DISTANCE);
+
+ FILL_INT_URB(&graphire->irq, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress),
+ graphire->data, 8, graphire_irq, graphire, endpoint->bInterval);
+
+ if (usb_submit_urb(&graphire->irq)) {
+ kfree(graphire);
+ return NULL;
+ }
+
+ input_register_device(&graphire->dev);
+
+ printk(KERN_INFO "input%d: Wacom Graphire USB\n", graphire->dev.number);
+
+ return graphire;
+}
+
+static void graphire_disconnect(struct usb_device *dev, void *ptr)
+{
+ struct graphire *graphire = ptr;
+ usb_unlink_urb(&graphire->irq);
+ input_unregister_device(&graphire->dev);
+ kfree(graphire);
+}
+
+static struct usb_driver graphire_driver = {
+ name: "graphire",
+ probe: graphire_probe,
+ disconnect: graphire_disconnect,
+};
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+ usb_deregister(&graphire_driver);
+}
+
+int init_module(void)
+#else
+int graphire_init(void)
+#endif
+{
+ usb_register(&graphire_driver);
+ return 0;
+}
diff --git a/drivers/usb/hid-debug.h b/drivers/usb/hid-debug.h
index a31c2910f..52fc94adb 100644
--- a/drivers/usb/hid-debug.h
+++ b/drivers/usb/hid-debug.h
@@ -1,8 +1,8 @@
/*
* driver/usb/hid-debug.h
*
- * (c) 1999 Andreas Gal <gal@cs.uni-magdeburg.de>
- * (c) 1999 Vojtech Pavlik <vojtech@suse.cz>
+ * (c) 1999 Andreas Gal <gal@cs.uni-magdeburg.de>
+ * (c) 2000 Vojtech Pavlik <vojtech@suse.cz>
*
* Some debug stuff for the HID parser.
*
diff --git a/drivers/usb/hid.c b/drivers/usb/hid.c
index bdd540ac2..ec1a4639d 100644
--- a/drivers/usb/hid.c
+++ b/drivers/usb/hid.c
@@ -2,7 +2,7 @@
* hid.c Version 0.8
*
* Copyright (c) 1999 Andreas Gal
- * Copyright (c) 1999 Vojtech Pavlik
+ * Copyright (c) 2000 Vojtech Pavlik
*
* USB HID support for the Linux input drivers
*
@@ -38,10 +38,10 @@
#include <linux/list.h>
#include <linux/mm.h>
#include <linux/smp_lock.h>
-#include <linux/config.h>
#include <linux/spinlock.h>
#undef DEBUG
+#undef DEBUG_DATA
#include "usb.h"
#include "hid.h"
@@ -710,7 +710,7 @@ static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n)
static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value)
{
report += (offset >> 5) << 2; offset &= 31;
- *(__u64*)report &= cpu_to_le64(~((1ULL << n) - 1) << offset);
+ *(__u64*)report &= cpu_to_le64(~((((__u64) 1 << n) - 1) << offset));
*(__u64*)report |= cpu_to_le64((__u64)value << offset);
}
@@ -763,6 +763,12 @@ static void hid_configure_usage(struct hid_device *device, struct hid_field *fie
}
break;
+ case HID_UP_LED:
+
+ usage->code = (usage->hid - 1) & 0xf;
+ usage->type = EV_LED; bit = input->ledbit; max = LED_MAX;
+ break;
+
default:
if (field->flags & HID_MAIN_ITEM_RELATIVE) {
@@ -905,7 +911,7 @@ static void hid_irq(struct urb *urb)
return;
}
-#ifdef DEBUG
+#ifdef DEBUG_DATA
printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered) = ", len, report_enum->numbered ? "" : "un");
for (n = 0; n < len; n++)
printk(" %02x", data[n]);
@@ -953,10 +959,10 @@ static void hid_irq(struct urb *urb)
static void hid_read_report(struct hid_device *hid, struct hid_report *report)
{
#if 0
- int rlen = ((report->size - 1) >> 3) + 1 + report_enum->numbered;
+ int rlen = ((report->size - 1) >> 3) + 1 + hid->report_enum[HID_INPUT_REPORT].numbered;
char rdata[rlen];
struct urb urb;
- int read;
+ int read, j;
memset(&urb, 0, sizeof(struct urb));
memset(rdata, 0, rlen);
@@ -974,7 +980,7 @@ static void hid_read_report(struct hid_device *hid, struct hid_report *report)
for (j = 0; j < rlen; j++) printk(" %02x", rdata[j]);
printk("\n");
#endif
- continue;
+ return;
}
hid_irq(&urb);
@@ -982,33 +988,6 @@ static void hid_read_report(struct hid_device *hid, struct hid_report *report)
}
/*
- * Configure the input layer interface
- * Read all reports and initalize the absoulte field values.
- */
-
-static void hid_init_input(struct hid_device *hid)
-{
- struct hid_report_enum *report_enum = hid->report_enum + HID_INPUT_REPORT;
- struct list_head *list;
- int i, j;
-
- list = report_enum->report_list.next;
-
- while (list != &report_enum->report_list) {
-
- struct hid_report *report = (struct hid_report *) list;
-
- list = list->next;
-
- for (i = 0; i < report->maxfield; i++)
- for (j = 0; j < report->field[i]->maxusage; j++)
- hid_configure_usage(hid, report->field[i], report->field[i]->usage + j);
-
- hid_read_report(hid, report);
- }
-}
-
-/*
* Output the field into the report.
*/
@@ -1035,9 +1014,11 @@ void hid_output_report(struct hid_report *report, __u8 *data)
{
unsigned n;
+#if 0
/* skip the ID if we have a single report */
if (report->device->report_enum[report->type].numbered)
*data++ = report->id;
+#endif
for (n = 0; n < report->maxfield; n++)
hid_output_field(report->field[n], data);
@@ -1052,6 +1033,8 @@ void hid_output_report(struct hid_report *report, __u8 *data)
int hid_set_field(struct hid_field *field, unsigned offset, __s32 value)
{
unsigned size = field->report_size;
+
+ hid_dump_input(field->usage + offset, value);
if (offset >= field->report_count) {
dbg("offset exceeds report_count");
@@ -1072,10 +1055,104 @@ int hid_set_field(struct hid_field *field, unsigned offset, __s32 value)
return 0;
}
+static int hid_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field)
+{
+ struct hid_report_enum *report_enum = hid->report_enum + HID_OUTPUT_REPORT;
+ struct list_head *list = report_enum->report_list.next;
+ int i, j;
+
+ while (list != &report_enum->report_list) {
+ struct hid_report *report = (struct hid_report *) list;
+ list = list->next;
+ for (i = 0; i < report->maxfield; i++) {
+ *field = report->field[i];
+ for (j = 0; j < (*field)->maxusage; j++)
+ if ((*field)->usage[j].type == type && (*field)->usage[j].code == code)
+ return j;
+ }
+ }
+ return -1;
+}
+
+static void hid_ctrl(struct urb *urb)
+{
+ if (urb->status)
+ warn("ctrl urb status %d received", urb->status);
+}
+
+static int hid_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
+{
+ struct hid_device *hid = dev->private;
+ struct hid_field *field = NULL;
+ int offset;
+
+ if ((offset = hid_find_field(hid, type, code, &field)) == -1) {
+ warn("event field not found");
+ return -1;
+ }
+
+ hid_set_field(field, offset, value);
+
+ if (hid->urbout.status == -EINPROGRESS) {
+ warn("had to kill output urb");
+ usb_unlink_urb(&hid->urbout);
+ }
+
+ hid_output_report(field->report, hid->bufout);
+
+ hid->dr.value = 0x200 | field->report->id;
+ hid->dr.length = ((field->report->size - 1) >> 3) + 1;
+ hid->urbout.transfer_buffer_length = hid->dr.length;
+
+ if (usb_submit_urb(&hid->urbout)) {
+ err("usb_submit_urb(out) failed");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Configure the input layer interface
+ * Read all reports and initalize the absoulte field values.
+ */
+
+static void hid_init_input(struct hid_device *hid)
+{
+ struct hid_report_enum *report_enum;
+ struct list_head *list;
+ int i, j, k;
+
+ hid->input.private = hid;
+ hid->input.event = hid_event;
+
+ for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
+
+ report_enum = hid->report_enum + k;
+ list = report_enum->report_list.next;
+
+ while (list != &report_enum->report_list) {
+
+ struct hid_report *report = (struct hid_report *) list;
+
+ list = list->next;
+
+ for (i = 0; i < report->maxfield; i++)
+ for (j = 0; j < report->field[i]->maxusage; j++)
+ hid_configure_usage(hid, report->field[i], report->field[i]->usage + j);
+
+ if (k == HID_INPUT_REPORT) {
+ usb_set_idle(hid->dev, 0, report->id);
+ hid_read_report(hid, report);
+ }
+ }
+ }
+}
+
static struct hid_device *usb_hid_configure(struct usb_device *dev, int ifnum)
{
struct usb_interface_descriptor *interface = &dev->actconfig->interface[ifnum].altsetting[0];
- struct usb_hid_descriptor *hdesc;
+ struct hid_descriptor *hdesc;
struct hid_device *hid;
unsigned rsize = 0;
int n;
@@ -1106,7 +1183,7 @@ static struct hid_device *usb_hid_configure(struct usb_device *dev, int ifnum)
return NULL;
}
-#ifdef DEBUG
+#ifdef DEBUG_DATA
printk(KERN_DEBUG __FILE__ ": report (size %u, read %d) = ", rsize, n);
for (n = 0; n < rsize; n++)
printk(" %02x", (unsigned) rdesc[n]);
@@ -1149,6 +1226,15 @@ static struct hid_device *usb_hid_configure(struct usb_device *dev, int ifnum)
return NULL;
}
+ hid->dr.requesttype = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+ hid->dr.request = USB_REQ_SET_REPORT;
+ hid->dr.value = 0x200;
+ hid->dr.index = interface->bInterfaceNumber;
+ hid->dr.length = 1;
+
+ FILL_CONTROL_URB(&hid->urbout, dev, usb_sndctrlpipe(dev, 0),
+ (void*) &hid->dr, hid->bufout, 1, hid_ctrl, hid);
+
hid->version = hdesc->bcdHID;
hid->country = hdesc->bCountryCode;
hid->dev = dev;
diff --git a/drivers/usb/hid.h b/drivers/usb/hid.h
index 8ccdb67bd..ab652442f 100644
--- a/drivers/usb/hid.h
+++ b/drivers/usb/hid.h
@@ -4,8 +4,8 @@
/*
* drivers/usb/hid.h Version 0.8
*
- * Copyright (c) 1999 Vojtech Pavlik
* Copyright (c) 1999 Andreas Gal
+ * Copyright (c) 2000 Vojtech Pavlik
*
* Sponsored by SuSE
*/
@@ -36,37 +36,12 @@
#include <linux/list.h>
/*
- * Enable/Disable debug information.
- */
-
-#ifdef CONFIG_USB_HID_DEBUG
-#define hid_debug(fmt,arg...) printk(KERN_DEBUG "hid: " fmt "\n" , ##arg)
-#else
-#define hid_debug(fmt,arg...) do { } while (0)
-#endif
-
-/*
* USB HID (Human Interface Device) interface class code
*/
#define USB_INTERFACE_CLASS_HID 3
/*
- * USB interface subclass codes.
- */
-
-#define USB_INTERFACE_SUBCLASS_NONE 0
-#define USB_INTERFACE_SUBCLASS_HID_BP 1
-
-/*
- * HID protocol codes (only for boot protocol)
- */
-
-#define HID_PROTOCOL_NONE 0
-#define HID_PROTOCOL_KBD 1
-#define HID_PROTOCOL_MOUSE 2
-
-/*
* We parse each description item into this structure. Short items data
* values are expanded to 32-bit signed int, long items contain a pointer
* into the data area.
@@ -122,7 +97,6 @@ struct hid_item {
/*
* HID report descriptor main item contents
- * Warning: VOLATILE is not available for TAG_INPUT
*/
#define HID_MAIN_ITEM_CONSTANT 0x001
@@ -196,18 +170,6 @@ struct hid_item {
#define HID_GD_HATSWITCH 0x00010039
/*
- * HID interface requests (this belongs here, the USB_REQ_xxx stuff should
- * disapear).
- */
-
-#define HID_REQ_GET_REPORT 0x01
-#define HID_REQ_GET_IDLE 0x02
-#define HID_REQ_GET_PROTOCOL 0x03
-#define HID_REQ_SET_REPORT 0x09
-#define HID_REQ_SET_IDLE 0x0A
-#define HID_REQ_SET_PROTOCOL 0x0B
-
-/*
* HID report types --- Ouch! HID spec says 1 2 3!
*/
@@ -216,13 +178,6 @@ struct hid_item {
#define HID_FEATURE_REPORT 2
/*
- * HID protocols
- */
-
-#define HID_PROTOCOL_BOOT 0
-#define HID_PROTOCOL_REPORT 1
-
-/*
* This is the global enviroment of the parser. This information is
* persistent for main-items. The global enviroment can be saved and
* restored with PUSH/POP statements.
@@ -324,7 +279,10 @@ struct hid_device { /* device report descriptor */
int ifnum; /* USB interface number */
char buffer[32]; /* Receive buffer */
+ char bufout[32]; /* Transmit buffer */
+ devrequest dr; /* Startup packet */
struct urb urb; /* USB URB structure */
+ struct urb urbout; /* Output URB */
struct input_dev input; /* input device structure */
};
@@ -341,5 +299,21 @@ struct hid_parser {
struct hid_device *device;
};
+struct hid_class_descriptor {
+ __u8 bDescriptorType;
+ __u16 wDescriptorLength;
+} __attribute__ ((packed));
+
+struct hid_descriptor {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u16 bcdHID;
+ __u8 bCountryCode;
+ __u8 bNumDescriptors;
+
+ struct hid_class_descriptor desc[1];
+} __attribute__ ((packed));
+
+
#endif
diff --git a/drivers/usb/hub.c b/drivers/usb/hub.c
index de7c65674..c066c3c43 100644
--- a/drivers/usb/hub.c
+++ b/drivers/usb/hub.c
@@ -48,13 +48,11 @@ static int usb_get_hub_descriptor(struct usb_device *dev, void *data, int size)
USB_DT_HUB << 8, 0, data, size, HZ);
}
-#if 0
-static int usb_clear_hub_feature(struct usb_device *dev, int feature)
+static int usb_clear_hub_feature(struct usb_device *dev, int feature)
{
return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- USB_REQ_CLEAR_FEATURE, USB_RT_HUB, feature, 0 , NULL, 0, HZ);
+ USB_REQ_CLEAR_FEATURE, USB_RT_HUB, feature, 0, NULL, 0, HZ);
}
-#endif
static int usb_clear_port_feature(struct usb_device *dev, int port, int feature)
{
@@ -359,7 +357,8 @@ static void usb_hub_port_connect_change(struct usb_device *hub, int port)
}
if (tries==MAX_TRIES) {
- err("can not enable port %i after %i retries, disabling port", port+1, MAX_TRIES);
+ err("Cannot enable port %i after %i retries, disabling port.", port+1, MAX_TRIES);
+ err("Maybe the USB cable is bad?");
return;
}
/* Allocate a new device struct for it */
@@ -392,6 +391,8 @@ static void usb_hub_events(void)
struct list_head *tmp;
struct usb_device *dev;
struct usb_hub *hub;
+ struct usb_hub_status hubsts;
+ unsigned short hubstatus, hubchange;
/*
* We restart the list everytime to avoid a deadlock with
@@ -444,14 +445,32 @@ static void usb_hub_events(void)
if (portchange & USB_PORT_STAT_C_SUSPEND)
dbg("port %d suspend change", i + 1);
- if (portchange & USB_PORT_STAT_C_OVERCURRENT)
+ if (portchange & USB_PORT_STAT_C_OVERCURRENT) {
dbg("port %d over-current change", i + 1);
+ usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_OVER_CURRENT);
+ }
if (portchange & USB_PORT_STAT_C_RESET) {
dbg("port %d reset change", i + 1);
usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_RESET);
}
} /* end for i */
+
+ /* deal with hub status changes */
+ if (usb_get_hub_status(dev, &hubsts) < 0) {
+ err("get_hub_status failed");
+ } else {
+ hubstatus = le16_to_cpup(&hubsts.wHubStatus);
+ hubchange = le16_to_cpup(&hubsts.wHubChange);
+ if (hubchange & HUB_CHANGE_LOCAL_POWER) {
+ dbg("hub power change");
+ usb_clear_hub_feature(dev, C_HUB_LOCAL_POWER);
+ }
+ if (hubchange & HUB_CHANGE_OVERCURRENT) {
+ dbg("hub overcurrent change");
+ usb_clear_hub_feature(dev, C_HUB_OVER_CURRENT);
+ }
+ }
} /* end while (1) */
he_unlock:
diff --git a/drivers/usb/hub.h b/drivers/usb/hub.h
index c95a07d74..0da7eb87c 100644
--- a/drivers/usb/hub.h
+++ b/drivers/usb/hub.h
@@ -4,6 +4,13 @@
#include <linux/list.h>
/*
+ * Hub request types
+ */
+
+#define USB_RT_HUB (USB_TYPE_CLASS | USB_RECIP_DEVICE)
+#define USB_RT_PORT (USB_TYPE_CLASS | USB_RECIP_OTHER)
+
+/*
* Hub Class feature numbers
*/
#define C_HUB_LOCAL_POWER 0
diff --git a/drivers/usb/inode.c b/drivers/usb/inode.c
new file mode 100644
index 000000000..00a2ac523
--- /dev/null
+++ b/drivers/usb/inode.c
@@ -0,0 +1,729 @@
+/*****************************************************************************/
+
+/*
+ * inode.c -- Inode/Dentry functions for the USB device file system.
+ *
+ * Copyright (C) 2000
+ * Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: inode.c,v 1.3 2000/01/11 13:58:25 tom Exp $
+ *
+ * History:
+ * 0.1 04.01.2000 Created
+ */
+
+/*****************************************************************************/
+
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/smp_lock.h>
+#include <linux/locks.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <asm/uaccess.h>
+
+#include "usb.h"
+#include "usbdevice_fs.h"
+
+/* --------------------------------------------------------------------- */
+
+static LIST_HEAD(superlist);
+
+extern struct inode_operations usbdevfs_bus_inode_operations;
+
+static struct inode_operations devices_inode_operations = {
+ &usbdevfs_devices_fops
+};
+
+static struct inode_operations drivers_inode_operations = {
+ &usbdevfs_drivers_fops
+};
+
+struct special {
+ const char *name;
+ struct inode_operations *iops;
+ struct list_head inodes;
+};
+
+static struct special special[] = {
+ { "devices", &devices_inode_operations, },
+ { "drivers", &drivers_inode_operations, }
+};
+
+#define NRSPECIAL (sizeof(special)/sizeof(special[0]))
+
+/* --------------------------------------------------------------------- */
+
+static int dnumber(struct dentry *dentry)
+{
+ const char *name;
+ unsigned int s;
+
+ if (dentry->d_name.len != 3)
+ return -1;
+ name = dentry->d_name.name;
+ if (name[0] < '0' || name[0] > '9' ||
+ name[1] < '0' || name[1] > '9' ||
+ name[2] < '0' || name[2] > '9')
+ return -1;
+ s = name[0] - '0';
+ s = s * 10 + name[1] - '0';
+ s = s * 10 + name[2] - '0';
+ return s;
+}
+
+/*
+ * utility functions; should be called with the kernel lock held
+ * to protect against busses/devices appearing/disappearing
+ */
+
+static void new_dev_inode(struct usb_device *dev, struct super_block *sb)
+{
+ struct inode *inode;
+ unsigned int devnum = dev->devnum;
+ unsigned int busnum = dev->bus->busnum;
+
+ if (devnum < 1 || devnum > 127 || busnum > 255)
+ return;
+ inode = iget(sb, IDEVICE | (busnum << 8) | devnum);
+ if (!inode) {
+ printk(KERN_ERR "usbdevfs: cannot create inode for bus %u device %u\n", busnum, devnum);
+ return;
+ }
+ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->i_uid = sb->u.usbdevfs_sb.devuid;
+ inode->i_gid = sb->u.usbdevfs_sb.devgid;
+ inode->i_mode = sb->u.usbdevfs_sb.devmode | S_IFREG;
+ inode->i_op = &usbdevfs_device_inode_operations;
+ inode->i_size = sizeof(struct usb_device_descriptor);
+ inode->u.usbdev_i.p.dev = dev;
+ list_add_tail(&inode->u.usbdev_i.slist, &sb->u.usbdevfs_sb.ilist);
+ list_add_tail(&inode->u.usbdev_i.dlist, &dev->inodes);
+}
+
+static void recurse_new_dev_inode(struct usb_device *dev, struct super_block *sb)
+{
+ unsigned int i;
+
+ if (!dev)
+ return;
+ new_dev_inode(dev, sb);
+ for (i = 0; i < dev->maxchild; i++) {
+ if (!dev->children[i])
+ continue;
+ recurse_new_dev_inode(dev->children[i], sb);
+ }
+}
+
+static void new_bus_inode(struct usb_bus *bus, struct super_block *sb)
+{
+ struct inode *inode;
+ unsigned int busnum = bus->busnum;
+
+ if (busnum > 255)
+ return;
+ inode = iget(sb, IBUS | (busnum << 8));
+ if (!inode) {
+ printk(KERN_ERR "usbdevfs: cannot create inode for bus %u\n", busnum);
+ return;
+ }
+ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->i_uid = sb->u.usbdevfs_sb.busuid;
+ inode->i_gid = sb->u.usbdevfs_sb.busgid;
+ inode->i_mode = sb->u.usbdevfs_sb.busmode | S_IFDIR;
+ inode->i_op = &usbdevfs_bus_inode_operations;
+ inode->u.usbdev_i.p.bus = bus;
+ list_add_tail(&inode->u.usbdev_i.slist, &sb->u.usbdevfs_sb.ilist);
+ list_add_tail(&inode->u.usbdev_i.dlist, &bus->inodes);
+}
+
+static void free_inode(struct inode *inode)
+{
+ inode->u.usbdev_i.p.bus = NULL;
+ inode->u.usbdev_i.p.dev = NULL;
+ inode->i_mode &= ~S_IRWXUGO;
+ inode->i_uid = inode->i_gid = 0;
+ inode->i_op = NULL;
+ inode->i_size = 0;
+ list_del(&inode->u.usbdev_i.slist);
+ INIT_LIST_HEAD(&inode->u.usbdev_i.slist);
+ list_del(&inode->u.usbdev_i.dlist);
+ INIT_LIST_HEAD(&inode->u.usbdev_i.dlist);
+ iput(inode);
+}
+
+static struct usb_bus *usbdevfs_findbus(int busnr)
+{
+ struct list_head *list;
+ struct usb_bus *bus;
+
+ for (list = usb_bus_list.next; list != &usb_bus_list; list = list->next) {
+ bus = list_entry(list, struct usb_bus, bus_list);
+ if (bus->busnum == busnr)
+ return bus;
+ }
+ return NULL;
+}
+
+#if 0
+static struct usb_device *finddev(struct usb_device *dev, int devnr)
+{
+ unsigned int i;
+ struct usb_device *d2;
+
+ if (!dev)
+ return NULL;
+ if (dev->devnum == devnr)
+ return dev;
+ for (i = 0; i < dev->maxchild; i++) {
+ if (!dev->children[i])
+ continue;
+ if ((d2 = finddev(dev->children[i], devnr)))
+ return d2;
+ }
+ return NULL;
+}
+
+static struct usb_device *usbdevfs_finddevice(struct usb_bus *bus, int devnr)
+{
+ return finddev(bus->root_hub, devnr);
+}
+#endif
+
+/* --------------------------------------------------------------------- */
+
+static int usbdevfs_revalidate(struct dentry *dentry, int flags)
+{
+ struct inode *inode = dentry->d_inode;
+
+ if (!inode)
+ return 0;
+ if (ITYPE(inode->i_ino) == IBUS && !inode->u.usbdev_i.p.bus)
+ return 0;
+ if (ITYPE(inode->i_ino) == IDEVICE && !inode->u.usbdev_i.p.dev)
+ return 0;
+ return 1;
+}
+
+static struct dentry_operations usbdevfs_dentry_operations = {
+ usbdevfs_revalidate, /* d_revalidate */
+ NULL, /* d_hash */
+ NULL, /* d_compare */
+};
+
+static struct dentry *usbdevfs_root_lookup(struct inode *dir, struct dentry *dentry)
+{
+ int busnr;
+ unsigned long ino = 0;
+ unsigned int i;
+ struct inode *inode;
+
+ /* sanity check */
+ if (dir->i_ino != IROOT)
+ return ERR_PTR(-EINVAL);
+ dentry->d_op = &usbdevfs_dentry_operations;
+ busnr = dnumber(dentry);
+ if (busnr >= 0 && busnr <= 255)
+ ino = IBUS | (busnr << 8);
+ if (!ino) {
+ for (i = 0; i < NRSPECIAL; i++) {
+ if (strlen(special[i].name) == dentry->d_name.len &&
+ !strncmp(special[i].name, dentry->d_name.name, dentry->d_name.len)) {
+ ino = ISPECIAL | (i + IROOT + 1);
+ break;
+ }
+ }
+ }
+ if (!ino)
+ return ERR_PTR(-ENOENT);
+ inode = iget(dir->i_sb, ino);
+ if (!inode)
+ return ERR_PTR(-EINVAL);
+ if (inode && ITYPE(ino) == IBUS && inode->u.usbdev_i.p.bus == NULL) {
+ iput(inode);
+ inode = NULL;
+ }
+ d_add(dentry, inode);
+ return NULL;
+}
+
+static struct dentry *usbdevfs_bus_lookup(struct inode *dir, struct dentry *dentry)
+{
+ struct inode *inode;
+ int devnr;
+
+ /* sanity check */
+ if (ITYPE(dir->i_ino) != IBUS)
+ return ERR_PTR(-EINVAL);
+ dentry->d_op = &usbdevfs_dentry_operations;
+ devnr = dnumber(dentry);
+ if (devnr < 1 || devnr > 127)
+ return ERR_PTR(-ENOENT);
+ inode = iget(dir->i_sb, IDEVICE | (dir->i_ino & (0xff << 8)) | devnr);
+ if (!inode)
+ return ERR_PTR(-EINVAL);
+ if (inode && inode->u.usbdev_i.p.dev == NULL) {
+ iput(inode);
+ inode = NULL;
+ }
+ d_add(dentry, inode);
+ return NULL;
+}
+
+static int usbdevfs_root_readdir(struct file *filp, void *dirent, filldir_t filldir)
+{
+ struct inode *inode = filp->f_dentry->d_inode;
+ unsigned long ino = inode->i_ino;
+ struct special *spec;
+ struct list_head *list;
+ struct usb_bus *bus;
+ char numbuf[8];
+ unsigned int i;
+
+ /* sanity check */
+ if (ino != IROOT)
+ return -EINVAL;
+ i = filp->f_pos;
+ switch (i) {
+ case 0:
+ if (filldir(dirent, ".", 1, i, IROOT) < 0)
+ return 0;
+ filp->f_pos++;
+ i++;
+ /* fall through */
+
+ case 1:
+ if (filldir(dirent, "..", 2, i, IROOT) < 0)
+ return 0;
+ filp->f_pos++;
+ i++;
+ /* fall through */
+
+ default:
+
+ while (i >= 2 && i < 2+NRSPECIAL) {
+ spec = &special[filp->f_pos-2];
+ if (filldir(dirent, spec->name, strlen(spec->name), i, ISPECIAL | (filp->f_pos-2+IROOT)) < 0)
+ return 0;
+ filp->f_pos++;
+ i++;
+ }
+ if (i < 2+NRSPECIAL)
+ return 0;
+ i -= 2+NRSPECIAL;
+ lock_kernel();
+ for (list = usb_bus_list.next; list != &usb_bus_list; list = list->next) {
+ if (i > 0) {
+ i--;
+ continue;
+ }
+ bus = list_entry(list, struct usb_bus, bus_list);
+ sprintf(numbuf, "%03d", bus->busnum);
+ if (filldir(dirent, numbuf, 3, filp->f_pos, IBUS | ((bus->busnum & 0xff) << 8)) < 0)
+ break;
+ filp->f_pos++;
+ }
+ unlock_kernel();
+ return 0;
+ }
+}
+
+static int bus_readdir(struct usb_device *dev, unsigned long ino, int pos, struct file *filp, void *dirent, filldir_t filldir)
+{
+ char numbuf[8];
+ unsigned int i;
+
+ if (!dev)
+ return pos;
+ sprintf(numbuf, "%03d", dev->devnum);
+ if (pos > 0)
+ pos--;
+ else {
+ if (filldir(dirent, numbuf, 3, filp->f_pos, ino | (dev->devnum & 0xff)) < 0)
+ return -1;
+ filp->f_pos++;
+ }
+ for (i = 0; i < dev->maxchild; i++) {
+ if (!dev->children[i])
+ continue;
+ pos = bus_readdir(dev->children[i], ino, pos, filp, dirent, filldir);
+ if (pos < 0)
+ return -1;
+ }
+ return pos;
+}
+
+static int usbdevfs_bus_readdir(struct file *filp, void *dirent, filldir_t filldir)
+{
+ struct inode *inode = filp->f_dentry->d_inode;
+ unsigned long ino = inode->i_ino;
+ struct usb_bus *bus;
+
+ /* sanity check */
+ if (ITYPE(ino) != IBUS)
+ return -EINVAL;
+ switch ((unsigned int)filp->f_pos) {
+ case 0:
+ if (filldir(dirent, ".", 1, filp->f_pos, ino) < 0)
+ return 0;
+ filp->f_pos++;
+ /* fall through */
+
+ case 1:
+ if (filldir(dirent, "..", 2, filp->f_pos, IROOT) < 0)
+ return 0;
+ filp->f_pos++;
+ /* fall through */
+
+ default:
+ lock_kernel();
+ bus = usbdevfs_findbus(IBUSNR(ino));
+ bus_readdir(bus->root_hub, IDEVICE | ((bus->busnum & 0xff) << 8), filp->f_pos-2, filp, dirent, filldir);
+ unlock_kernel();
+ return 0;
+ }
+}
+
+static struct file_operations usbdevfs_root_file_operations = {
+ readdir: usbdevfs_root_readdir
+};
+
+static struct inode_operations usbdevfs_root_inode_operations = {
+ default_file_ops: &usbdevfs_root_file_operations,
+ lookup: usbdevfs_root_lookup
+};
+
+static struct file_operations usbdevfs_bus_file_operations = {
+ readdir: usbdevfs_bus_readdir
+};
+
+static struct inode_operations usbdevfs_bus_inode_operations = {
+ default_file_ops: &usbdevfs_bus_file_operations,
+ lookup: usbdevfs_bus_lookup
+};
+
+static void usbdevfs_read_inode(struct inode *inode)
+{
+ struct special *spec;
+
+ inode->i_ctime = inode->i_mtime = inode->i_atime = CURRENT_TIME;
+ inode->i_mode = S_IFREG;
+ inode->i_gid = inode->i_uid = 0;
+ INIT_LIST_HEAD(&inode->u.usbdev_i.dlist);
+ INIT_LIST_HEAD(&inode->u.usbdev_i.slist);
+ inode->u.usbdev_i.p.dev = NULL;
+ inode->u.usbdev_i.p.bus = NULL;
+ switch (ITYPE(inode->i_ino)) {
+ case ISPECIAL:
+ if (inode->i_ino == IROOT) {
+ inode->i_op = &usbdevfs_root_inode_operations;
+ inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
+ return;
+ }
+ if (inode->i_ino <= IROOT || inode->i_ino > IROOT+NRSPECIAL)
+ return;
+ spec = &special[inode->i_ino-(IROOT+1)];
+ inode->i_op = spec->iops;
+ return;
+
+ case IDEVICE:
+ return;
+
+ case IBUS:
+ return;
+
+ default:
+ return;
+ }
+}
+
+static void usbdevfs_put_inode(struct inode *inode)
+{
+}
+
+static void usbdevfs_put_super(struct super_block *sb)
+{
+ list_del(&sb->u.usbdevfs_sb.slist);
+ INIT_LIST_HEAD(&sb->u.usbdevfs_sb.slist);
+ while (!list_empty(&sb->u.usbdevfs_sb.ilist))
+ free_inode(list_entry(sb->u.usbdevfs_sb.ilist.next, struct inode, u.usbdev_i.slist));
+ MOD_DEC_USE_COUNT;
+}
+
+static int usbdevfs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+{
+ struct statfs tmp;
+
+ tmp.f_type = USBDEVICE_SUPER_MAGIC;
+ tmp.f_bsize = PAGE_SIZE/sizeof(long); /* ??? */
+ tmp.f_blocks = 0;
+ tmp.f_bfree = 0;
+ tmp.f_bavail = 0;
+ tmp.f_files = 0;
+ tmp.f_ffree = 0;
+ tmp.f_namelen = NAME_MAX;
+ return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+}
+
+static struct super_operations usbdevfs_sops = {
+ usbdevfs_read_inode,
+ NULL,
+ usbdevfs_put_inode,
+ NULL,
+ NULL,
+ usbdevfs_put_super,
+ NULL,
+ usbdevfs_statfs,
+ NULL
+};
+
+struct super_block *usbdevfs_read_super(struct super_block *s, void *data, int silent)
+{
+ struct inode *root_inode, *inode;
+ struct list_head *blist;
+ struct usb_bus *bus;
+ unsigned int i;
+ uid_t devuid = 0, busuid = 0, listuid = 0;
+ gid_t devgid = 0, busgid = 0, listgid = 0;
+ umode_t devmode = S_IWUSR | S_IRUGO, busmode = S_IXUGO | S_IRUGO, listmode = S_IRUGO;
+ char *curopt = NULL, *value;
+
+ /* parse options */
+ if (data)
+ curopt = strtok(data, ",");
+ for (; curopt; curopt = strtok(NULL, ",")) {
+ if ((value = strchr(curopt, '=')) != NULL)
+ *value++ = 0;
+ if (!strcmp(curopt, "devuid")) {
+ if (!value || !value[0])
+ goto opterr;
+ devuid = simple_strtoul(value, &value, 0);
+ if (*value)
+ goto opterr;
+ }
+ if (!strcmp(curopt, "devgid")) {
+ if (!value || !value[0])
+ goto opterr;
+ devgid = simple_strtoul(value, &value, 0);
+ if (*value)
+ goto opterr;
+ }
+ if (!strcmp(curopt, "devmode")) {
+ if (!value || !value[0])
+ goto opterr;
+ devmode = simple_strtoul(value, &value, 0) & S_IRWXUGO;
+ if (*value)
+ goto opterr;
+ }
+ if (!strcmp(curopt, "busuid")) {
+ if (!value || !value[0])
+ goto opterr;
+ busuid = simple_strtoul(value, &value, 0);
+ if (*value)
+ goto opterr;
+ }
+ if (!strcmp(curopt, "busgid")) {
+ if (!value || !value[0])
+ goto opterr;
+ busgid = simple_strtoul(value, &value, 0);
+ if (*value)
+ goto opterr;
+ }
+ if (!strcmp(curopt, "busmode")) {
+ if (!value || !value[0])
+ goto opterr;
+ busmode = simple_strtoul(value, &value, 0) & S_IRWXUGO;
+ if (*value)
+ goto opterr;
+ }
+ if (!strcmp(curopt, "listuid")) {
+ if (!value || !value[0])
+ goto opterr;
+ listuid = simple_strtoul(value, &value, 0);
+ if (*value)
+ goto opterr;
+ }
+ if (!strcmp(curopt, "listgid")) {
+ if (!value || !value[0])
+ goto opterr;
+ listgid = simple_strtoul(value, &value, 0);
+ if (*value)
+ goto opterr;
+ }
+ if (!strcmp(curopt, "listmode")) {
+ if (!value || !value[0])
+ goto opterr;
+ listmode = simple_strtoul(value, &value, 0) & S_IRWXUGO;
+ if (*value)
+ goto opterr;
+ }
+ }
+ /* fill superblock */
+ MOD_INC_USE_COUNT;
+ lock_super(s);
+ s->s_blocksize = 1024;
+ s->s_blocksize_bits = 10;
+ s->s_magic = USBDEVICE_SUPER_MAGIC;
+ s->s_op = &usbdevfs_sops;
+ INIT_LIST_HEAD(&s->u.usbdevfs_sb.slist);
+ INIT_LIST_HEAD(&s->u.usbdevfs_sb.ilist);
+ s->u.usbdevfs_sb.devuid = devuid;
+ s->u.usbdevfs_sb.devgid = devgid;
+ s->u.usbdevfs_sb.devmode = devmode;
+ s->u.usbdevfs_sb.busuid = busuid;
+ s->u.usbdevfs_sb.busgid = busgid;
+ s->u.usbdevfs_sb.busmode = busmode;
+ root_inode = iget(s, IROOT);
+ if (!root_inode)
+ goto out_no_root;
+ s->s_root = d_alloc_root(root_inode);
+ if (!s->s_root)
+ goto out_no_root;
+ list_add_tail(&s->u.usbdevfs_sb.slist, &superlist);
+ unlock_super(s);
+ for (i = 0; i < NRSPECIAL; i++) {
+ if (!(inode = iget(s, IROOT+1+i)))
+ continue;
+ inode->i_uid = listuid;
+ inode->i_gid = listgid;
+ inode->i_mode = listmode | S_IFREG;
+ list_add_tail(&inode->u.usbdev_i.slist, &s->u.usbdevfs_sb.ilist);
+ list_add_tail(&inode->u.usbdev_i.dlist, &special[i].inodes);
+ }
+ lock_kernel();
+ for (blist = usb_bus_list.next; blist != &usb_bus_list; blist = blist->next) {
+ bus = list_entry(blist, struct usb_bus, bus_list);
+ new_bus_inode(bus, s);
+ recurse_new_dev_inode(bus->root_hub, s);
+ }
+ unlock_kernel();
+ return s;
+
+ out_no_root:
+ printk("usbdevfs_read_super: get root inode failed\n");
+ iput(root_inode);
+ s->s_dev = 0;
+ unlock_super(s);
+ MOD_DEC_USE_COUNT;
+ return NULL;
+
+ opterr:
+ printk(KERN_WARNING "usbdevfs: mount parameter error\n");
+ s->s_dev = 0;
+ return NULL;
+}
+
+static struct file_system_type usbdevice_fs_type = {
+ "usbdevfs",
+ 0,
+ usbdevfs_read_super,
+ NULL
+};
+
+/* --------------------------------------------------------------------- */
+
+void usbdevfs_add_bus(struct usb_bus *bus)
+{
+ struct list_head *slist;
+
+ lock_kernel();
+ for (slist = superlist.next; slist != &superlist; slist = slist->next)
+ new_bus_inode(bus, list_entry(slist, struct super_block, u.usbdevfs_sb.slist));
+ unlock_kernel();
+ usbdevfs_conn_disc_event();
+}
+
+void usbdevfs_remove_bus(struct usb_bus *bus)
+{
+ lock_kernel();
+ while (!list_empty(&bus->inodes))
+ free_inode(list_entry(bus->inodes.next, struct inode, u.usbdev_i.dlist));
+ unlock_kernel();
+ usbdevfs_conn_disc_event();
+}
+
+void usbdevfs_add_device(struct usb_device *dev)
+{
+ struct list_head *slist;
+
+ lock_kernel();
+ for (slist = superlist.next; slist != &superlist; slist = slist->next)
+ new_dev_inode(dev, list_entry(slist, struct super_block, u.usbdevfs_sb.slist));
+ unlock_kernel();
+ usbdevfs_conn_disc_event();
+}
+
+void usbdevfs_remove_device(struct usb_device *dev)
+{
+ struct dev_state *ds;
+ struct siginfo sinfo;
+
+ lock_kernel();
+ while (!list_empty(&dev->inodes))
+ free_inode(list_entry(dev->inodes.next, struct inode, u.usbdev_i.dlist));
+ while (!list_empty(&dev->filelist)) {
+ ds = list_entry(dev->filelist.next, struct dev_state, list);
+ list_del(&ds->list);
+ INIT_LIST_HEAD(&ds->list);
+ down_write(&ds->devsem);
+ ds->dev = NULL;
+ up_write(&ds->devsem);
+ if (ds->discsignr) {
+ sinfo.si_signo = SIGPIPE;
+ sinfo.si_errno = EPIPE;
+ sinfo.si_code = SI_ASYNCIO;
+ sinfo.si_addr = ds->disccontext;
+ send_sig_info(ds->discsignr, &sinfo, ds->disctask);
+ }
+ }
+ unlock_kernel();
+ usbdevfs_conn_disc_event();
+}
+
+/* --------------------------------------------------------------------- */
+
+static struct proc_dir_entry *usbdir = NULL;
+
+int __init usbdevfs_init(void)
+{
+ int ret;
+
+ for (ret = 0; ret < NRSPECIAL; ret++) {
+ INIT_LIST_HEAD(&special[ret].inodes);
+ }
+ if ((ret = usb_register(&usbdevfs_driver)))
+ return ret;
+ if ((ret = register_filesystem(&usbdevice_fs_type)))
+ usb_deregister(&usbdevfs_driver);
+ /* create mount point for usbdevfs */
+ usbdir = proc_mkdir("usb", proc_bus);
+ return ret;
+}
+
+void __exit usbdevfs_cleanup(void)
+{
+ usb_deregister(&usbdevfs_driver);
+ unregister_filesystem(&usbdevice_fs_type);
+ if (usbdir)
+ remove_proc_entry("usb", proc_bus);
+}
+
+#if 0
+module_init(usbdevfs_init);
+module_exit(usbdevfs_cleanup);
+#endif
diff --git a/drivers/usb/joydev.c b/drivers/usb/joydev.c
index 9c0ff47c8..9f1c94fc0 100644
--- a/drivers/usb/joydev.c
+++ b/drivers/usb/joydev.c
@@ -424,9 +424,13 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev)
joydev->minor = ffz(joydev_minors);
set_bit(joydev->minor, &joydev_minors);
joydev_base[joydev->minor] = joydev;
-
+
for (i = 0; i < joydev->nabs; i++) {
j = joydev->abspam[i];
+ if (dev->absmax[j] == dev->absmin[j]) {
+ joydev->corr[i].type = JS_CORR_NONE;
+ continue;
+ }
joydev->corr[i].type = JS_CORR_BROKEN;
joydev->corr[i].prec = dev->absfuzz[j];
joydev->corr[i].coef[0] = (dev->absmax[j] + dev->absmin[j]) / 2 - dev->absflat[j];
diff --git a/drivers/usb/keybdev.c b/drivers/usb/keybdev.c
index f09f90845..34da92941 100644
--- a/drivers/usb/keybdev.c
+++ b/drivers/usb/keybdev.c
@@ -34,6 +34,7 @@
#include <linux/malloc.h>
#include <linux/init.h>
#include <linux/module.h>
+#include <linux/kbd_kern.h>
#ifdef CONFIG_X86
@@ -43,11 +44,11 @@ static unsigned char keybdev_x86_e0s[] =
0x26, 0x25, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x00,
0x23, 0x24, 0x25, 0x26, 0x27 };
-#elif CONFIG_MAC_KEYBOARD
+#elif CONFIG_ADB_KEYBOARD
static unsigned char keybdev_mac_codes[256] =
{ 0, 53, 18, 19, 20, 21, 23, 22, 26, 28, 25, 29, 27, 24, 51, 48,
- 12, 13, 14, 15, 17, 16, 32, 34, 31, 35, 33, 30, 36, 54, 0, 1,
+ 12, 13, 14, 15, 17, 16, 32, 34, 31, 35, 33, 30, 36, 54,128, 1,
2, 3, 5, 4, 38, 40, 37, 41, 39, 50, 56, 42, 6, 7, 8, 9,
11, 45, 46, 43, 47, 44,123, 67, 55, 49, 57,122,120, 99,118, 96,
97, 98,100,101,109, 71,107, 89, 91, 92, 78, 86, 87, 88, 69, 83,
@@ -57,6 +58,21 @@ static unsigned char keybdev_mac_codes[256] =
#endif
+struct input_handler keybdev_handler;
+
+void keybdev_ledfunc(unsigned int led)
+{
+ struct input_handle *handle;
+
+ for (handle = keybdev_handler.handle; handle; handle = handle->hnext) {
+
+ input_event(handle->dev, EV_LED, LED_SCROLLL, !!(led & 0x01));
+ input_event(handle->dev, EV_LED, LED_NUML, !!(led & 0x02));
+ input_event(handle->dev, EV_LED, LED_CAPSL, !!(led & 0x04));
+
+ }
+}
+
void keybdev_event(struct input_handle *handle, unsigned int type, unsigned int code, int down)
{
if (type != EV_KEY || code > 255) return;
@@ -85,10 +101,10 @@ void keybdev_event(struct input_handle *handle, unsigned int type, unsigned int
}
} else handle_scancode(code, down);
-#elif CONFIG_MAC_KEYBOARD
+#elif CONFIG_ADB_KEYBOARD
- if (keycode < 128 && keybdev_mac_codes[code])
- handle_scancode(keybdev_mac_codes[code], down);
+ if (code < 128 && keybdev_mac_codes[code])
+ handle_scancode(keybdev_mac_codes[code] & 0x7f, down);
else
printk(KERN_WARNING "keybdev.c: can't emulate keycode %d\n", code);
@@ -96,6 +112,7 @@ void keybdev_event(struct input_handle *handle, unsigned int type, unsigned int
#error "Cannot generate rawmode keyboard for your architecture yet."
#endif
+ mark_bh(KEYBOARD_BH);
}
static int keybdev_connect(struct input_handler *handler, struct input_dev *dev)
@@ -137,6 +154,7 @@ struct input_handler keybdev_handler = {
#ifdef MODULE
void cleanup_module(void)
{
+ kbd_ledfunc = NULL;
input_unregister_handler(&keybdev_handler);
}
int init_module(void)
@@ -145,5 +163,6 @@ int __init keybdev_init(void)
#endif
{
input_register_handler(&keybdev_handler);
+ kbd_ledfunc = keybdev_ledfunc;
return 0;
}
diff --git a/drivers/usb/mousedev.c b/drivers/usb/mousedev.c
index b52609bf0..c10b76557 100644
--- a/drivers/usb/mousedev.c
+++ b/drivers/usb/mousedev.c
@@ -53,7 +53,7 @@ struct mousedev_list {
struct mousedev_list *next;
int dx, dy, dz;
unsigned char ps2[6];
- unsigned char buttons;
+ unsigned long buttons;
unsigned char ready, buffer, bufsiz;
unsigned char mode, genseq, impseq;
};
@@ -83,7 +83,7 @@ static void mousedev_event(struct input_handle *handle, unsigned int type, unsig
switch (code) {
case REL_X: list->dx += value; break;
case REL_Y: list->dy -= value; break;
- case REL_WHEEL: if (list->mode) list->dz += value; break;
+ case REL_WHEEL: if (list->mode) list->dz -= value; break;
}
break;
diff --git a/drivers/usb/ohci-hcd.c b/drivers/usb/ohci-hcd.c
index e95d66e96..30274cb85 100644
--- a/drivers/usb/ohci-hcd.c
+++ b/drivers/usb/ohci-hcd.c
@@ -47,6 +47,7 @@
#include <asm/system.h>
#undef DEBUG
+#define OHCI_USE_NPS
#include "usb.h"
#include "ohci-hcd.h"
@@ -154,8 +155,9 @@ void ep_print_int_eds (ohci_t * ohci, char * str) {
printk (KERN_DEBUG __FILE__ " %s branch int %2d(%2x):", str, i, i);
ed_p = &(ohci->hcca.int_table [i]);
while (*ed_p != 0 && j--) {
- printk (" ed: %4x;", (((ed_t *) bus_to_virt (*ed_p))->hwINFO));
- ed_p = &(((ed_t *) bus_to_virt (*ed_p))->hwNextED);
+ ed_t *ed = (ed_t *) bus_to_virt(le32_to_cpup(ed_p));
+ printk (" ed: %4x;", ed->hwINFO);
+ ed_p = &ed->hwNextED;
}
printk ("\n");
}
@@ -174,7 +176,7 @@ static int sohci_return_urb (urb_t * urb)
{
urb_priv_t * urb_priv = urb->hcpriv;
urb_t * urbt;
- unsigned int flags;
+ unsigned long flags;
int i;
/* just to be sure */
@@ -245,7 +247,7 @@ static int sohci_submit_urb (urb_t * urb)
urb_priv_t * urb_priv;
unsigned int pipe = urb->pipe;
int i, size = 0;
- unsigned int flags;
+ unsigned long flags;
if (!urb->dev || !urb->dev->bus) return -EINVAL;
@@ -346,7 +348,7 @@ static int sohci_submit_urb (urb_t * urb)
static int sohci_unlink_urb (urb_t * urb)
{
- unsigned int flags;
+ unsigned long flags;
ohci_t * ohci;
DECLARE_WAITQUEUE (wait, current);
@@ -412,7 +414,7 @@ static int sohci_alloc_dev (struct usb_device *usb_dev)
static int sohci_free_dev (struct usb_device * usb_dev)
{
- unsigned int flags;
+ unsigned long flags;
int i, cnt = 0;
ed_t * ed;
DECLARE_WAITQUEUE (wait, current);
@@ -566,9 +568,9 @@ static int ep_link (ohci_t * ohci, ed_t * edi)
for (i = 0; i < ep_rev (6, interval); i += inter) {
inter = 1;
for (ed_p = &(ohci->hcca.int_table[ep_rev (5, i) + int_branch]);
- (*ed_p != 0) && (((ed_t *) bus_to_virt (le32_to_cpu (*ed_p)))->int_interval >= interval);
- ed_p = &(((ed_t *) bus_to_virt (le32_to_cpu (*ed_p)))->hwNextED))
- inter = ep_rev (6, ((ed_t *) bus_to_virt (le32_to_cpu (*ed_p)))->int_interval);
+ (*ed_p != 0) && (((ed_t *) bus_to_virt (le32_to_cpup (ed_p)))->int_interval >= interval);
+ ed_p = &(((ed_t *) bus_to_virt (le32_to_cpup (ed_p)))->hwNextED))
+ inter = ep_rev (6, ((ed_t *) bus_to_virt (le32_to_cpup (ed_p)))->int_interval);
ed->hwNextED = *ed_p;
*ed_p = cpu_to_le32 (virt_to_bus (ed));
}
@@ -588,8 +590,8 @@ static int ep_link (ohci_t * ohci, ed_t * edi)
inter = 1;
for (ed_p = &(ohci->hcca.int_table[ep_rev (5, i)]);
*ed_p != 0;
- ed_p = &(((ed_t *) bus_to_virt (le32_to_cpu (*ed_p)))->hwNextED))
- inter = ep_rev (6, ((ed_t *) bus_to_virt (le32_to_cpu (*ed_p)))->int_interval);
+ ed_p = &(((ed_t *) bus_to_virt (le32_to_cpup (ed_p)))->hwNextED))
+ inter = ep_rev (6, ((ed_t *) bus_to_virt (le32_to_cpup (ed_p)))->int_interval);
*ed_p = cpu_to_le32 (virt_to_bus (ed));
}
ed->ed_prev = NULL;
@@ -622,27 +624,27 @@ static int ep_unlink (ohci_t * ohci, ed_t * ed)
switch (ed->type) {
case CTRL:
if (ed->ed_prev == NULL) {
- writel (le32_to_cpu (ed->hwNextED), &ohci->regs->ed_controlhead);
+ writel (le32_to_cpup (&ed->hwNextED), &ohci->regs->ed_controlhead);
} else {
ed->ed_prev->hwNextED = ed->hwNextED;
}
if(ohci->ed_controltail == ed) {
ohci->ed_controltail = ed->ed_prev;
} else {
- ((ed_t *) bus_to_virt (le32_to_cpu (ed->hwNextED)))->ed_prev = ed->ed_prev;
+ ((ed_t *) bus_to_virt (le32_to_cpup (&ed->hwNextED)))->ed_prev = ed->ed_prev;
}
break;
case BULK:
if (ed->ed_prev == NULL) {
- writel (le32_to_cpu (ed->hwNextED), &ohci->regs->ed_bulkhead);
+ writel (le32_to_cpup (&ed->hwNextED), &ohci->regs->ed_bulkhead);
} else {
ed->ed_prev->hwNextED = ed->hwNextED;
}
if (ohci->ed_bulktail == ed) {
ohci->ed_bulktail = ed->ed_prev;
} else {
- ((ed_t *) bus_to_virt (le32_to_cpu (ed->hwNextED)))->ed_prev = ed->ed_prev;
+ ((ed_t *) bus_to_virt (le32_to_cpup (&ed->hwNextED)))->ed_prev = ed->ed_prev;
}
break;
@@ -653,9 +655,9 @@ static int ep_unlink (ohci_t * ohci, ed_t * ed)
for (i = 0; i < ep_rev (6, interval); i += inter) {
for (ed_p = &(ohci->hcca.int_table[ep_rev (5, i) + int_branch]), inter = 1;
(*ed_p != 0) && (*ed_p != ed->hwNextED);
- ed_p = &(((ed_t *) bus_to_virt (le32_to_cpu (*ed_p)))->hwNextED),
- inter = ep_rev (6, ((ed_t *) bus_to_virt (le32_to_cpu (*ed_p)))->int_interval)) {
- if(((ed_t *) bus_to_virt (le32_to_cpu (*ed_p))) == ed) {
+ ed_p = &(((ed_t *) bus_to_virt (le32_to_cpup (ed_p)))->hwNextED),
+ inter = ep_rev (6, ((ed_t *) bus_to_virt (le32_to_cpup (ed_p)))->int_interval)) {
+ if(((ed_t *) bus_to_virt (le32_to_cpup (ed_p))) == ed) {
*ed_p = ed->hwNextED;
break;
}
@@ -670,7 +672,7 @@ static int ep_unlink (ohci_t * ohci, ed_t * ed)
if (ohci->ed_isotail == ed)
ohci->ed_isotail = ed->ed_prev;
if (ed->hwNextED != 0)
- ((ed_t *) bus_to_virt (le32_to_cpu (ed->hwNextED)))->ed_prev = ed->ed_prev;
+ ((ed_t *) bus_to_virt (le32_to_cpup (&ed->hwNextED)))->ed_prev = ed->ed_prev;
if (ed->ed_prev != NULL) {
ed->ed_prev->hwNextED = ed->hwNextED;
@@ -679,9 +681,9 @@ static int ep_unlink (ohci_t * ohci, ed_t * ed)
inter = 1;
for (ed_p = &(ohci->hcca.int_table[ep_rev (5, i)]);
*ed_p != 0;
- ed_p = &(((ed_t *) bus_to_virt (le32_to_cpu (*ed_p)))->hwNextED)) {
- inter = ep_rev (6, ((ed_t *) bus_to_virt (le32_to_cpu (*ed_p)))->int_interval);
- if(((ed_t *) bus_to_virt (le32_to_cpu (*ed_p))) == ed) {
+ ed_p = &(((ed_t *) bus_to_virt (le32_to_cpup (ed_p)))->hwNextED)) {
+ inter = ep_rev (6, ((ed_t *) bus_to_virt (le32_to_cpup (ed_p)))->int_interval);
+ if(((ed_t *) bus_to_virt (le32_to_cpup (ed_p))) == ed) {
*ed_p = ed->hwNextED;
break;
}
@@ -800,7 +802,7 @@ static void td_fill (unsigned int info, void * data, int len, urb_t * urb, int t
td_pt = urb_priv->td [index];
/* fill the old dummy TD */
- td = (td_t *) bus_to_virt (le32_to_cpu (urb_priv->ed->hwTailP) & 0xfffffff0);
+ td = (td_t *) bus_to_virt (le32_to_cpup (&urb_priv->ed->hwTailP) & 0xfffffff0);
td->ed = urb_priv->ed;
td->index = index;
td->urb = urb;
@@ -900,20 +902,20 @@ static td_t * dl_reverse_done_list (ohci_t * ohci)
td_t * td_rev = NULL;
td_t * td_list = NULL;
urb_priv_t * urb_priv = NULL;
- unsigned int flags;
+ unsigned long flags;
spin_lock_irqsave (&usb_ed_lock, flags);
- td_list_hc = le32_to_cpu (ohci->hcca.done_head) & 0xfffffff0;
+ td_list_hc = le32_to_cpup (&ohci->hcca.done_head) & 0xfffffff0;
ohci->hcca.done_head = 0;
while (td_list_hc) {
td_list = (td_t *) bus_to_virt (td_list_hc);
- if (TD_CC_GET (le32_to_cpu (td_list->hwINFO))) {
+ if (TD_CC_GET (le32_to_cpup (&td_list->hwINFO))) {
urb_priv = (urb_priv_t *) td_list->urb->hcpriv;
dbg(" USB-error/status: %x : %p",
- TD_CC_GET (le32_to_cpu (td_list->hwINFO)), td_list);
+ TD_CC_GET (le32_to_cpup (&td_list->hwINFO)), td_list);
if (td_list->ed->hwHeadP & cpu_to_le32 (0x1)) {
if (urb_priv && ((td_list->index + 1) < urb_priv->length)) {
td_list->ed->hwHeadP =
@@ -927,7 +929,7 @@ static td_t * dl_reverse_done_list (ohci_t * ohci)
td_list->next_dl_td = td_rev;
td_rev = td_list;
- td_list_hc = le32_to_cpu (td_list->hwNextTD) & 0xfffffff0;
+ td_list_hc = le32_to_cpup (&td_list->hwNextTD) & 0xfffffff0;
}
spin_unlock_irqrestore (&usb_ed_lock, flags);
return td_list;
@@ -941,7 +943,7 @@ static td_t * dl_reverse_done_list (ohci_t * ohci)
static void dl_del_list (ohci_t * ohci, unsigned int frame)
{
- unsigned int flags;
+ unsigned long flags;
ed_t * ed;
__u32 edINFO;
td_t * td = NULL, * td_next = NULL, * tdHeadP = NULL, * tdTailP;
@@ -951,16 +953,16 @@ static void dl_del_list (ohci_t * ohci, unsigned int frame)
spin_lock_irqsave (&usb_ed_lock, flags);
for (ed = ohci->ed_rm_list[frame]; ed != NULL; ed = ed->ed_rm_list) {
- tdTailP = bus_to_virt (le32_to_cpu (ed->hwTailP) & 0xfffffff0);
- tdHeadP = bus_to_virt (le32_to_cpu (ed->hwHeadP) & 0xfffffff0);
- edINFO = le32_to_cpu (ed->hwINFO);
+ tdTailP = bus_to_virt (le32_to_cpup (&ed->hwTailP) & 0xfffffff0);
+ tdHeadP = bus_to_virt (le32_to_cpup (&ed->hwHeadP) & 0xfffffff0);
+ edINFO = le32_to_cpup (&ed->hwINFO);
td_p = &ed->hwHeadP;
for (td = tdHeadP; td != tdTailP; td = td_next) {
urb_t * urb = td->urb;
urb_priv_t * urb_priv = td->urb->hcpriv;
- td_next = bus_to_virt (le32_to_cpu (td->hwNextTD) & 0xfffffff0);
+ td_next = bus_to_virt (le32_to_cpup (&td->hwNextTD) & 0xfffffff0);
if ((urb_priv->state == URB_DEL) || (ed->state & ED_DEL)) {
*td_p = td->hwNextTD | (*td_p & cpu_to_le32 (0x3));
if(++ (urb_priv->td_cnt) == urb_priv->length)
@@ -1013,16 +1015,16 @@ static void dl_done_list (ohci_t * ohci, td_t * td_list)
urb_priv_t * urb_priv;
__u32 tdINFO, tdBE, tdCBP, edHeadP, edTailP;
__u16 tdPSW;
- unsigned int flags;
+ unsigned long flags;
while (td_list) {
td_list_next = td_list->next_dl_td;
urb = td_list->urb;
urb_priv = urb->hcpriv;
- tdINFO = le32_to_cpu (td_list->hwINFO);
- tdBE = le32_to_cpu (td_list->hwBE);
- tdCBP = le32_to_cpu (td_list->hwCBP);
+ tdINFO = le32_to_cpup (&td_list->hwINFO);
+ tdBE = le32_to_cpup (&td_list->hwBE);
+ tdCBP = le32_to_cpup (&td_list->hwCBP);
ed = td_list->ed;
@@ -1071,8 +1073,8 @@ static void dl_done_list (ohci_t * ohci, td_t * td_list)
spin_lock_irqsave (&usb_ed_lock, flags);
if (ed->state != ED_NEW) {
- edHeadP = le32_to_cpu (ed->hwHeadP) & 0xfffffff0;
- edTailP = le32_to_cpu (ed->hwTailP);
+ edHeadP = le32_to_cpup (&ed->hwHeadP) & 0xfffffff0;
+ edTailP = le32_to_cpup (&ed->hwTailP);
if((edHeadP == edTailP) && (ed->state == ED_OPER))
ep_unlink (ohci, ed); /* unlink eds if they are not busy */
@@ -1185,9 +1187,9 @@ static int rh_send_irq (ohci_t * ohci, void * rh_data, int rh_len)
ret = *(__u8 *) data;
for ( i = 0; i < num_ports; i++) {
- *(__u8 *) (data + i / 8) |=
+ *(__u8 *) (data + (i + 1) / 8) |=
((readl (&ohci->regs->roothub.portstatus[i]) & 0x001f0000) > 0? 1: 0) << ((i + 1) % 8);
- ret += *(__u8 *) (data + i / 8);
+ ret += *(__u8 *) (data + (i + 1) / 8);
}
len = i/8 + 1;
@@ -1313,8 +1315,10 @@ static int rh_submit_urb (urb_t * urb)
case RH_CLEAR_FEATURE | RH_CLASS:
switch (wValue) {
+ case RH_C_HUB_LOCAL_POWER:
+ OK(0);
case (RH_C_HUB_OVER_CURRENT):
- WR_RH_STAT(RH_PS_OCIC); OK (0);
+ WR_RH_STAT(RH_HS_OCIC); OK (0);
}
break;
@@ -1489,6 +1493,13 @@ static int hc_start (ohci_t * ohci)
writel (ohci->hc_control = 0xBF, &ohci->regs->control); /* USB Operational */
writel (mask, &ohci->regs->intrenable);
writel (mask, &ohci->regs->intrstatus);
+
+#ifdef OHCI_USE_NPS
+ writel ((readl(&ohci->regs->roothub.a) | 0x200) & ~0x100,
+ &ohci->regs->roothub.a);
+ writel (0x10000, &ohci->regs->roothub.status);
+ mdelay ((readl(&ohci->regs->roothub.a) >> 23) & 0x1fe);
+#endif /* OHCI_USE_NPS */
/* connect the virtual root hub */
@@ -1516,7 +1527,7 @@ static void hc_interrupt (int irq, void * __ohci, struct pt_regs * r)
struct ohci_regs * regs = ohci->regs;
int ints;
- if ((ohci->hcca.done_head != 0) && !(le32_to_cpu (ohci->hcca.done_head) & 0x01)) {
+ if ((ohci->hcca.done_head != 0) && !(le32_to_cpup (&ohci->hcca.done_head) & 0x01)) {
ints = OHCI_INTR_WDH;
} else {
if ((ints = (readl (&regs->intrstatus) & readl (&regs->intrenable))) == 0)
@@ -1578,7 +1589,7 @@ static ohci_t * hc_alloc_ohci (void * mem_base)
bus = usb_alloc_bus (&sohci_device_operations);
if (!bus) {
- free_pages ((unsigned int) ohci, 1);
+ free_pages ((unsigned long) ohci, 1);
return NULL;
}
@@ -1614,7 +1625,7 @@ static void hc_release_ohci (ohci_t * ohci)
/* unmap the IO address space */
iounmap (ohci->regs);
- free_pages ((unsigned int) ohci, 1);
+ free_pages ((unsigned long) ohci, 1);
}
/*-------------------------------------------------------------------------*/
@@ -1625,7 +1636,7 @@ static void hc_release_ohci (ohci_t * ohci)
static int hc_found_ohci (int irq, void * mem_base)
{
ohci_t * ohci;
- dbg("USB HC found: irq= %d membase= %x", irq, (int) mem_base);
+ dbg("USB HC found: irq= %d membase= %lx", irq, (unsigned long) mem_base);
ohci = hc_alloc_ohci (mem_base);
if (!ohci) {
@@ -1655,15 +1666,15 @@ static int hc_found_ohci (int irq, void * mem_base)
static int hc_start_ohci (struct pci_dev * dev)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
- unsigned int mem_base = dev->resource[0].start;
+ unsigned long mem_base = dev->resource[0].start;
#else
- unsigned int mem_base = dev->base_address[0];
+ unsigned long mem_base = dev->base_address[0];
if (mem_base & PCI_BASE_ADDRESS_SPACE_IO) return -ENODEV;
mem_base &= PCI_BASE_ADDRESS_MEM_MASK;
#endif
pci_set_master (dev);
- mem_base = (unsigned int) ioremap_nocache (mem_base, 4096);
+ mem_base = (unsigned long) ioremap_nocache (mem_base, 4096);
if (!mem_base) {
err("Error mapping OHCI memory");
diff --git a/drivers/usb/ohci-hcd.h b/drivers/usb/ohci-hcd.h
index c9267f533..f3d71154f 100644
--- a/drivers/usb/ohci-hcd.h
+++ b/drivers/usb/ohci-hcd.h
@@ -314,6 +314,13 @@ struct virt_root_hub {
#define RH_PS_OCIC 0x00080000
#define RH_PS_PRSC 0x00100000
+/* Root hub status bits */
+#define RH_HS_LPS 0x00000001
+#define RH_HS_OCI 0x00000002
+#define RH_HS_DRWE 0x00008000
+#define RH_HS_LPSC 0x00010000
+#define RH_HS_OCIC 0x00020000
+#define RH_HS_CRWE 0x80000000
#define min(a,b) (((a)<(b))?(a):(b))
diff --git a/drivers/usb/ov511.c b/drivers/usb/ov511.c
index d0da393f3..c26f96132 100644
--- a/drivers/usb/ov511.c
+++ b/drivers/usb/ov511.c
@@ -11,8 +11,11 @@
* DEBUG - Debugging code.
* FIXME - Something that is broken or needs improvement.
*
- * Version History:
- * Version 1.00 - Initial version
+ * Version: 1.05
+ *
+ * Please see the file: linux/Documentation/usb/ov511.txt
+ * and the website at: http://people.delphi.com/mmcclelland/linux/
+ * for more info.
*/
/*
@@ -63,13 +66,15 @@
#define OV511_I2C_RETRIES 3
-/* Video Size 384 x 288 x 3 bytes for RGB */
-#define MAX_FRAME_SIZE (320 * 240 * 3)
+#define OV7610_AUTO_ADJUST 1
+
+/* Video Size 640 x 480 x 3 bytes for RGB */
+#define MAX_FRAME_SIZE (640 * 480 * 3)
// FIXME - Force CIF to make some apps happy for the moment. Should find a
// better way to do this.
-#define DEFAULT_WIDTH 320
-#define DEFAULT_HEIGHT 240
+#define DEFAULT_WIDTH 640
+#define DEFAULT_HEIGHT 480
char kernel_version[] = UTS_RELEASE;
@@ -200,7 +205,9 @@ int ov511_reg_write(struct usb_device *dev, unsigned char reg, unsigned char val
USB_TYPE_CLASS | USB_RECIP_DEVICE,
0, (__u16)reg, &value, 1, HZ);
- PDEBUG("reg write: 0x%02X:0x%02X\n", reg, value);
+#if 0
+ PDEBUG("reg write: 0x%02X:0x%02X", reg, value);
+#endif
return rc;
}
@@ -217,7 +224,9 @@ int ov511_reg_read(struct usb_device *dev, unsigned char reg)
USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_DEVICE,
0, (__u16)reg, buffer, 1, HZ);
- PDEBUG("reg read: 0x%02X:0x%02X\n", reg, buffer[0]);
+#if 0
+ PDEBUG("reg read: 0x%02X:0x%02X", reg, buffer[0]);
+#endif
if(rc < 0)
return rc;
@@ -229,7 +238,9 @@ int ov511_i2c_write(struct usb_device *dev, unsigned char reg, unsigned char val
{
int rc, retries;
- PDEBUG("i2c write: 0x%02X:0x%02X\n", reg, value);
+#if 0
+ PDEBUG("i2c write: 0x%02X:0x%02X", reg, value);
+#endif
/* Three byte write cycle */
for(retries = OV511_I2C_RETRIES;;) {
/* Select camera register */
@@ -309,7 +320,9 @@ int ov511_i2c_read(struct usb_device *dev, unsigned char reg)
}
value = ov511_reg_read(dev, OV511_REG_I2C_DATA_PORT);
- PDEBUG("i2c read: 0x%02X:0x%02X\n", reg, value);
+#if 0
+ PDEBUG("i2c read: 0x%02X:0x%02X", reg, value);
+#endif
/* This is needed to make ov511_i2c_write() work */
rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x05);
@@ -318,27 +331,94 @@ int ov511_i2c_read(struct usb_device *dev, unsigned char reg)
return (value);
}
+#if 0
+static void ov511_dump_i2c_range( struct usb_device *dev, int reg1, int regn)
+{
+ int i;
+ int rc;
+ for(i=reg1; i<=regn; i++) {
+ rc = ov511_i2c_read(dev, i);
+#if 0
+ PDEBUG("OV7610[0x%X] = 0x%X", i, rc);
+#endif
+ }
+}
+
+static void ov511_dump_i2c_regs( struct usb_device *dev)
+{
+ PDEBUG("I2C REGS");
+ ov511_dump_i2c_range(dev, 0x00, 0x38);
+}
+
+static void ov511_dump_reg_range( struct usb_device *dev, int reg1, int regn)
+{
+ int i;
+ int rc;
+ for(i=reg1; i<=regn; i++) {
+ rc = ov511_reg_read(dev, i);
+ PDEBUG("OV511[0x%X] = 0x%X", i, rc);
+ }
+}
+
+static void ov511_dump_regs( struct usb_device *dev)
+{
+ PDEBUG("CAMERA INTERFACE REGS");
+ ov511_dump_reg_range(dev, 0x10, 0x1f);
+ PDEBUG("DRAM INTERFACE REGS");
+ ov511_dump_reg_range(dev, 0x20, 0x23);
+ PDEBUG("ISO FIFO REGS");
+ ov511_dump_reg_range(dev, 0x30, 0x31);
+ PDEBUG("PIO REGS");
+ ov511_dump_reg_range(dev, 0x38, 0x39);
+ ov511_dump_reg_range(dev, 0x3e, 0x3e);
+ PDEBUG("I2C REGS");
+ ov511_dump_reg_range(dev, 0x40, 0x49);
+ PDEBUG("SYSTEM CONTROL REGS");
+ ov511_dump_reg_range(dev, 0x50, 0x53);
+ ov511_dump_reg_range(dev, 0x5e, 0x5f);
+ PDEBUG("OmniCE REGS");
+ ov511_dump_reg_range(dev, 0x70, 0x79);
+ ov511_dump_reg_range(dev, 0x80, 0x9f);
+ ov511_dump_reg_range(dev, 0xa0, 0xbf);
+
+}
+#endif
+
+int ov511_i2c_reset(struct usb_device *dev)
+{
+ int rc;
+
+ PDEBUG("Reset 7610");
+ rc = ov511_i2c_write(dev, 0x12, 0x80);
+ if (rc < 0)
+ err("i2c reset: command failed");
+
+ return rc;
+}
+
int ov511_reset(struct usb_device *dev, unsigned char reset_type)
{
int rc;
- PDEBUG("Reset: type=0x%X\n", reset_type);
+ PDEBUG("Reset: type=0x%X", reset_type);
rc = ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, reset_type);
if (rc < 0)
- printk(KERN_ERR "ov511: reset: command failed\n");
+ err("reset: command failed");
rc = ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0);
if (rc < 0)
- printk(KERN_ERR "ov511: reset: command failed\n");
+ err("reset: command failed");
return rc;
}
int ov511_set_packet_size(struct usb_ov511 *ov511, int size)
{
- int alt, multiplier, err;
+ int alt, multiplier, rc;
- PDEBUG("set packet size: %d\n", size);
+#if 0
+ PDEBUG("set packet size: %d", size);
+#endif
switch (size) {
case 992:
@@ -374,21 +454,19 @@ int ov511_set_packet_size(struct usb_ov511 *ov511, int size)
multiplier = 1; // FIXME - is this correct?
break;
default:
- printk(KERN_ERR "ov511_set_packet_size: invalid size (%d)\n",
- size);
+ err("Set packet size: invalid size (%d)", size);
return -EINVAL;
}
- err = ov511_reg_write(ov511->dev, OV511_REG_FIFO_PACKET_SIZE,
- multiplier);
- if (err < 0) {
- printk(KERN_ERR "ov511: Set packet size: Set FIFO size ret %d\n",
- err);
+ rc = ov511_reg_write(ov511->dev, OV511_REG_FIFO_PACKET_SIZE,
+ multiplier);
+ if (rc < 0) {
+ err("Set packet size: Set FIFO size ret %d", rc);
return -ENOMEM;
}
if (usb_set_interface(ov511->dev, ov511->iface, alt) < 0) {
- printk(KERN_ERR "ov511: Set packet size: set interface error\n");
+ err("Set packet size: set interface error");
return -EBUSY;
}
@@ -399,8 +477,258 @@ int ov511_set_packet_size(struct usb_ov511 *ov511, int size)
return 0;
}
-/* How much data is left in the scratch buf? */
-#define scratch_left(x) (ov511->scratchlen - (int)((char *)x - (char *)ov511->scratch))
+static inline int ov7610_set_picture(struct usb_ov511 *ov511,
+ struct video_picture *p)
+{
+ if(ov511_i2c_write(ov511->dev, OV7610_REG_SAT, p->colour >> 8) < 0)
+ return -EIO;
+
+ if(ov511_i2c_write(ov511->dev, OV7610_REG_CNT, p->contrast >> 8) < 0)
+ return -EIO;
+
+ if(ov511_i2c_write(ov511->dev, OV7610_REG_BRT, p->brightness >> 8) < 0)
+ return -EIO;
+
+ return 0;
+}
+
+static inline int ov7610_get_picture(struct usb_ov511 *ov511,
+ struct video_picture *p)
+{
+ int ret;
+
+ if((ret = ov511_i2c_read(ov511->dev, OV7610_REG_SAT)) < 0) return -EIO;
+ p->colour = ret << 8;
+
+ if((ret = ov511_i2c_read(ov511->dev, OV7610_REG_CNT)) < 0) return -EIO;
+ p->contrast = ret << 8;
+
+ if((ret = ov511_i2c_read(ov511->dev, OV7610_REG_BRT)) < 0) return -EIO;
+ p->brightness = ret << 8;
+
+ p->hue = 0x8000;
+ p->whiteness = 105 << 8;
+ p->depth = 24;
+ p->palette = VIDEO_PALETTE_RGB24;
+
+ return 0;
+}
+
+static int ov511_mode_init_regs(struct usb_ov511 *ov511,
+ int width, int height, int mode)
+{
+ int rc = 0;
+ struct usb_device *dev = ov511->dev;
+
+#if 0
+ PDEBUG("ov511_mode_init_regs(ov511, %d, %d, %d)", width, height, mode);
+#endif
+ ov511_set_packet_size(ov511, 0);
+
+ /* Set mode consistent registers */
+ ov511_i2c_write(dev, 0x0f, 0x03);
+ ov511_i2c_write(dev, 0x10, 0xff);
+ ov511_i2c_write(dev, 0x13, 0x01);
+ ov511_i2c_write(dev, 0x16, 0x06);
+ ov511_i2c_write(dev, 0x20, 0x1c);
+ ov511_i2c_write(dev, 0x24, 0x2e); /* 10 */
+ ov511_i2c_write(dev, 0x25, 0x7c); /* 8a */
+ ov511_i2c_write(dev, 0x26, 0x70);
+ ov511_i2c_write(dev, 0x28, 0x24); /* 24 */
+ ov511_i2c_write(dev, 0x2b, 0xac);
+ ov511_i2c_write(dev, 0x2c, 0xfe);
+ ov511_i2c_write(dev, 0x2d, 0x93);
+ ov511_i2c_write(dev, 0x34, 0x8b);
+
+ if (width == 640 && height == 480) {
+ ov511_reg_write(dev, 0x12, 0x4f);
+ ov511_reg_write(dev, 0x13, 0x3d);
+ ov511_reg_write(dev, 0x14, 0x00);
+ ov511_reg_write(dev, 0x15, 0x00);
+ ov511_reg_write(dev, 0x18, 0x03);
+
+ ov511_i2c_write(dev, 0x11, 0x01);
+ ov511_i2c_write(dev, 0x12, 0x24);
+ ov511_i2c_write(dev, 0x14, 0x04);
+ ov511_i2c_write(dev, 0x35, 0x9e);
+ } else if (width == 320 && height == 240) {
+ ov511_reg_write(dev, 0x12, 0x27);
+ ov511_reg_write(dev, 0x13, 0x1f);
+ ov511_reg_write(dev, 0x14, 0x00);
+ ov511_reg_write(dev, 0x15, 0x00);
+ ov511_reg_write(dev, 0x18, 0x03);
+
+ ov511_i2c_write(dev, 0x11, 0x00);
+ ov511_i2c_write(dev, 0x12, 0x04);
+ ov511_i2c_write(dev, 0x14, 0x24);
+ ov511_i2c_write(dev, 0x35, 0x1e);
+ } else {
+ err("Unknown mode (%d, %d): %d", width, height, mode);
+ rc = -EINVAL;
+ }
+ ov511_set_packet_size(ov511, 993);
+
+ return rc;
+}
+
+
+/*************************************************************
+
+Turn a YUV4:2:0 block into an RGB block
+
+*************************************************************/
+#define LIMIT(x) ((((x)>0xffffff)?0xff0000:(((x)<=0xffff)?0:(x)&0xff0000))>>16)
+static inline void ov511_move_420_block(int y00, int y01, int y10, int y11,
+ int u, int v, int w,
+ unsigned char * pOut)
+{
+ int r = 68911 * v;
+ int g = -16915 * u + -35101 * v;
+ int b = 87097 * u;
+ y00 *= 49152;
+ y01 *= 49152;
+ y10 *= 49152;
+ y11 *= 49152;
+ *(pOut+w*3) = LIMIT(r + y10);
+ *pOut++ = LIMIT(r + y00);
+ *(pOut+w*3) = LIMIT(g + y10);
+ *pOut++ = LIMIT(g + y00);
+ *(pOut+w*3) = LIMIT(b + y10);
+ *pOut++ = LIMIT(b + y00);
+ *(pOut+w*3) = LIMIT(r + y11);
+ *pOut++ = LIMIT(r + y01);
+ *(pOut+w*3) = LIMIT(g + y11);
+ *pOut++ = LIMIT(g + y01);
+ *(pOut+w*3) = LIMIT(b + y11);
+ *pOut++ = LIMIT(b + y01);
+}
+
+/***************************************************************
+
+For a 640x480 YUV4:2:0 images, data shows up in 1200 384 byte segments. The
+first 64 bytes of each segment are V, the next 64 are U. The V and
+U are arranged as follows:
+
+ 0 1 ... 7
+ 8 9 ... 15
+ ...
+ 56 57 ... 63
+
+The next 256 bytes are Y data and represent 4 squares of 8x8 pixels as
+follows:
+
+ 0 1 ... 7 64 65 ... 71 ... 192 193 ... 199
+ 8 9 ... 15 72 73 ... 79 200 201 ... 207
+ ... ... ...
+ 56 57 ... 63 120 121 127 248 249 ... 255
+
+If OV511_DUMPPIX is defined, _parse_data just dumps the
+incoming segments, verbatim, in order, into the frame.
+When used with vidcat -f ppm -s 640x480 this puts the data
+on the standard output and can be analyzed with the parseppm.c
+utility I wrote. That's a much faster way for figuring out how
+this data is scrambled.
+
+****************************************************************/
+#define HDIV 8
+#define WDIV (256/HDIV)
+
+static void ov511_parse_data(unsigned char * pIn0,
+ unsigned char * pOut0,
+ int iWidth,
+ int iSegment)
+
+{
+#ifndef OV511_DUMPPIX
+ int k, l, m;
+ unsigned char * pIn;
+ unsigned char * pOut, * pOut1;
+
+ int iHalf = (iSegment / (iWidth / 32)) & 1;
+ int iY = iSegment / (iWidth / WDIV);
+ int jY = iSegment - iY * (iWidth / WDIV);
+ int iOutY = (iY*HDIV*iWidth + jY*WDIV) * 3;
+ int iUV = iSegment / (iWidth / WDIV * 2);
+ int jUV = iSegment - iUV * (iWidth / WDIV * 2);
+ int iOutUV = (iUV*HDIV*2*iWidth + jUV*WDIV/2) * 3;
+
+ /* Just copy the Y's if in the first stripe */
+ if (!iHalf) {
+ pIn = pIn0 + 128;
+ pOut = pOut0 + iOutY;
+ for(k=0; k<4; k++) {
+ pOut1 = pOut;
+ for(l=0; l<8; l++) {
+ for(m=0; m<8; m++) {
+ *pOut1 = *pIn++;
+ pOut1 += 3;
+ }
+ pOut1 += (iWidth - 8) * 3;
+ }
+ pOut += 8 * 3;
+ }
+ }
+
+ /* Use the first half of VUs to calculate value */
+ pIn = pIn0;
+ pOut = pOut0 + iOutUV;
+ for(l=0; l<4; l++) {
+ for(m=0; m<8; m++) {
+ int y00 = *(pOut);
+ int y01 = *(pOut+3);
+ int y10 = *(pOut+iWidth*3);
+ int y11 = *(pOut+iWidth*3+3);
+ int u = *(pIn+64) - 128;
+ int v = *pIn++ - 128;
+ ov511_move_420_block(y00, y01, y10, y11, u, v, iWidth, pOut);
+ pOut += 6;
+ }
+ pOut += (iWidth*2 - 16) * 3;
+ }
+
+ /* Just copy the other UV rows */
+ for(l=0; l<4; l++) {
+ for(m=0; m<8; m++) {
+ *pOut++ = *(pIn + 64);
+ *pOut = *pIn++;
+ pOut += 5;
+ }
+ pOut += (iWidth*2 - 16) * 3;
+ }
+
+ /* Calculate values if it's the second half */
+ if (iHalf) {
+ pIn = pIn0 + 128;
+ pOut = pOut0 + iOutY;
+ for(k=0; k<4; k++) {
+ pOut1 = pOut;
+ for(l=0; l<4; l++) {
+ for(m=0; m<4; m++) {
+ int y10 = *(pIn+8);
+ int y00 = *pIn++;
+ int y11 = *(pIn+8);
+ int y01 = *pIn++;
+ int u = *pOut1 - 128;
+ int v = *(pOut1+1) - 128;
+ ov511_move_420_block(y00, y01, y10, y11, u, v, iWidth, pOut1);
+ pOut1 += 6;
+ }
+ pOut1 += (iWidth*2 - 8) * 3;
+ pIn += 8;
+ }
+ pOut += 8 * 3;
+ }
+ }
+
+#else
+ /* Just dump pix data straight out for debug */
+ int i;
+ pOut0 += iSegment * 384;
+ for(i=0; i<384; i++) {
+ *pOut0++ = *pIn0++;
+ }
+#endif
+}
static int ov511_move_data(struct usb_ov511 *ov511, urb_t *urb)
{
@@ -421,13 +749,10 @@ static int ov511_move_data(struct usb_ov511 *ov511, urb_t *urb)
if (!n) continue;
- aPackNum[i] = n ? cdata[512] : -1;
+ aPackNum[i] = n ? cdata[992] : -1;
- if (st){
- // Macro - must be in braces!
- PDEBUG("data error: [%d] len=%d, status=%d\n",
- i, n, st);
- }
+ if (st)
+ PDEBUG("data error: [%d] len=%d, status=%d", i, n, st);
frame = &ov511->frame[ov511->curframe];
@@ -436,13 +761,18 @@ static int ov511_move_data(struct usb_ov511 *ov511, urb_t *urb)
cdata[4] | cdata[5] | cdata[6] | cdata[7]) == 0 &&
(cdata[8] & 8) && (cdata[8] & 0x80)) {
- PDEBUG("Found Frame End!, packnum = %d\n", (int)(cdata[512]));
- PDEBUG("Current frame = %d\n", ov511->curframe);
+#if 0
+ PDEBUG("Found Frame End!, packnum = %d", (int)(cdata[992]));
+ PDEBUG("Current frame = %d", ov511->curframe);
+#endif
if (frame->scanstate == STATE_LINES) {
if (waitqueue_active(&frame->wq)) {
- PDEBUG("About to wake up waiting processes\n");
+#if 0
+ PDEBUG("About to wake up waiting processes");
+#endif
frame->grabstate = FRAME_DONE;
+ ov511->curframe = -1;
wake_up_interruptible(&frame->wq);
}
}
@@ -452,35 +782,52 @@ static int ov511_move_data(struct usb_ov511 *ov511, urb_t *urb)
else if ((cdata[0] | cdata[1] | cdata[2] | cdata[3] |
cdata[4] | cdata[5] | cdata[6] | cdata[7]) == 0 &&
(cdata[8] & 8)) {
- PDEBUG("ov511: Found Frame Start!, packnum = %d\n", (int)(cdata[512]));
+#if 0
+ PDEBUG("ov511: Found Frame Start!, packnum = %d", (int)(cdata[992]));
+ PDEBUG("ov511: Frame Header Byte = 0x%x", (int)(cdata[8]));
+#endif
frame->scanstate = STATE_LINES;
- frame->curpix = 0;
+ frame->segment = 0;
}
/* Are we in a frame? */
- else if (frame->scanstate == STATE_LINES) {
- unsigned char *f = frame->data + 3 * frame->curpix;
- int i;
- if (frame->curpix <= 320 * 240 - 256) {
- for (i=0; i<256; i++) {
- *f++ = *cdata;
- *f++ = *cdata;
- *f++ = *cdata++;
- *f++ = *cdata;
- *f++ = *cdata;
- *f++ = *cdata++;
- }
- frame->curpix += 512;
+ if (frame->scanstate == STATE_LINES) {
+ unsigned char * pData;
+ int iPix;
+
+ /* Deal with leftover from last segment, if any */
+ if (frame->segment) {
+ pData = ov511->scratch;
+ iPix = - ov511->scratchlen;
+ memmove(pData + ov511->scratchlen, cdata, iPix+384);
} else {
- PDEBUG("Too many pixels!\n");
+ pData = &cdata[iPix = 9];
}
+
+ /* Parse the segments */
+ while(iPix <= 992 - 384 &&
+ frame->segment < frame->width * frame->height / 256) {
+ ov511_parse_data(pData, frame->data,
+ frame->width,
+ frame->segment);
+ frame->segment++;
+ iPix += 384;
+ pData = &cdata[iPix];
}
+ /* Save extra data for next time */
+ if (frame->segment < frame->width * frame->height / 256) {
+ memmove(ov511->scratch, pData, 992 - iPix);
+ ov511->scratchlen = 992 - iPix;
+ }
+ }
}
+#if 0
PDEBUG("pn: %d %d %d %d %d %d %d %d %d %d\n",
aPackNum[0], aPackNum[1], aPackNum[2], aPackNum[3], aPackNum[4],
aPackNum[5],aPackNum[6], aPackNum[7], aPackNum[8], aPackNum[9]);
+#endif
return totlen;
}
@@ -491,18 +838,6 @@ static void ov511_isoc_irq(struct urb *urb)
struct ov511_sbuf *sbuf;
int i;
-#if 0
- static int last_status, last_error_count, last_actual_length;
- if (last_status != urb->status ||
- last_error_count != urb->error_count ||
- last_actual_length != urb->actual_length) {
- PDEBUG("ov511_isoc_irq: %p status %d, errcount = %d, length = %d\n", urb, urb->status, urb->error_count, urb->actual_length);
- last_status = urb->status;
- last_error_count = urb->error_count;
- last_actual_length = urb->actual_length;
- }
-#endif
-
if (!ov511->streaming) {
PDEBUG("hmmm... not streaming, but got interrupt\n");
return;
@@ -511,17 +846,10 @@ static void ov511_isoc_irq(struct urb *urb)
sbuf = &ov511->sbuf[ov511->cursbuf];
/* Copy the data received into our scratch buffer */
- len = ov511_move_data(ov511, urb);
-#if 0
- /* If we don't have a frame we're current working on, complain */
- if (ov511->scratchlen) {
- if (ov511->curframe < 0) {
- // Macro - must be in braces!!
- PDEBUG("received data, but no frame available\n");
- } else
- ov511_parse_data(ov511);
+ if (ov511->curframe >= 0) {
+ len = ov511_move_data(ov511, urb);
}
-#endif
+
for (i = 0; i < FRAMES_PER_DESC; i++) {
sbuf->urb->iso_frame_desc[i].status = 0;
sbuf->urb->iso_frame_desc[i].actual_length = 0;
@@ -544,30 +872,13 @@ static int ov511_init_isoc(struct usb_ov511 *ov511)
ov511->cursbuf = 0;
ov511->scratchlen = 0;
- ov511_set_packet_size(ov511, 512);
-
-#define OV511_COLOR_BAR_TEST
-#ifdef OV511_COLOR_BAR_TEST
- {
- int rc;
- rc = ov511_i2c_read(ov511->dev, 0x12);
- rc = ov511_i2c_write(ov511->dev, 0x12, 0x3f);
- rc = ov511_i2c_read(ov511->dev, 0x12);
- rc = ov511_i2c_read(ov511->dev, 0x13);
- rc = ov511_i2c_write(ov511->dev, 0x14, 0x4);
- rc = ov511_i2c_read(ov511->dev, 0x14);
- rc = ov511_i2c_write(ov511->dev, 0x28, 0x60);
- rc = ov511_i2c_read(ov511->dev, 0x28);
- ov511_reg_write(ov511->dev, OV511_REG_CAMERA_DATA_INPUT_SELECT,
- 0);
- }
-#endif
+ ov511_set_packet_size(ov511, 993);
/* We double buffer the Iso lists */
urb = usb_alloc_urb(FRAMES_PER_DESC);
if (!urb) {
- printk(KERN_ERR "ov511_init_isoc: usb_alloc_urb ret. NULL\n");
+ err("ov511_init_isoc: usb_alloc_urb ret. NULL");
return -ENOMEM;
}
ov511->sbuf[0].urb = urb;
@@ -586,7 +897,7 @@ static int ov511_init_isoc(struct usb_ov511 *ov511)
urb = usb_alloc_urb(FRAMES_PER_DESC);
if (!urb) {
- printk(KERN_ERR "ov511_init_isoc: usb_alloc_urb ret. NULL\n");
+ err("ov511_init_isoc: usb_alloc_urb ret. NULL");
return -ENOMEM;
}
ov511->sbuf[1].urb = urb;
@@ -608,12 +919,10 @@ static int ov511_init_isoc(struct usb_ov511 *ov511)
err = usb_submit_urb(ov511->sbuf[0].urb);
if (err)
- printk(KERN_ERR "ov511_init_isoc: usb_run_isoc(0) ret %d\n",
- err);
+ err("ov511_init_isoc: usb_run_isoc(0) ret %d", err);
err = usb_submit_urb(ov511->sbuf[1].urb);
if (err)
- printk(KERN_ERR "ov511_init_isoc: usb_run_isoc(1) ret %d\n",
- err);
+ err("ov511_init_isoc: usb_run_isoc(1) ret %d\n", err);
ov511->streaming = 1;
@@ -685,7 +994,7 @@ static int ov511_open(struct video_device *dev, int flags)
int err = -EBUSY;
struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;
- PDEBUG("ov511_open\n");
+ PDEBUG("ov511_open");
down(&ov511->lock);
if (ov511->user)
@@ -704,8 +1013,8 @@ static int ov511_open(struct video_device *dev, int flags)
ov511->frame[0].data = ov511->fbuf;
ov511->frame[1].data = ov511->fbuf + MAX_FRAME_SIZE;
- PDEBUG("frame [0] @ %p\n", ov511->frame[0].data);
- PDEBUG("frame [1] @ %p\n", ov511->frame[1].data);
+ PDEBUG("frame [0] @ %p", ov511->frame[0].data);
+ PDEBUG("frame [1] @ %p", ov511->frame[1].data);
ov511->sbuf[0].data = kmalloc(FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL);
if (!ov511->sbuf[0].data)
@@ -714,17 +1023,8 @@ static int ov511_open(struct video_device *dev, int flags)
if (!ov511->sbuf[1].data)
goto open_err_on1;
- PDEBUG("sbuf[0] @ %p\n", ov511->sbuf[0].data);
- PDEBUG("sbuf[1] @ %p\n", ov511->sbuf[1].data);
-
- /* Set default sizes in case IOCTL (VIDIOCMCAPTURE) is not used
- * (using read() instead). */
- ov511->frame[0].width = DEFAULT_WIDTH;
- ov511->frame[0].height = DEFAULT_HEIGHT;
- ov511->frame[0].bytes_read = 0;
- ov511->frame[1].width = DEFAULT_WIDTH;
- ov511->frame[1].height = DEFAULT_HEIGHT;
- ov511->frame[1].bytes_read = 0;
+ PDEBUG("sbuf[0] @ %p", ov511->sbuf[0].data);
+ PDEBUG("sbuf[1] @ %p", ov511->sbuf[1].data);
err = ov511_init_isoc(ov511);
if (err)
@@ -755,7 +1055,7 @@ static void ov511_close(struct video_device *dev)
{
struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;
- PDEBUG("ov511_close\n");
+ PDEBUG("ov511_close");
down(&ov511->lock);
ov511->user--;
@@ -783,12 +1083,12 @@ static long ov511_write(struct video_device *dev, const char *buf, unsigned long
}
// FIXME - Needs much work!!!
-static int ov511_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
+static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
{
- struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;
-
- PDEBUG("IOCtl: 0x%X\n", cmd);
-
+ struct usb_ov511 *ov511 = (struct usb_ov511 *)vdev;
+#if 0
+ PDEBUG("IOCtl: 0x%X", cmd);
+#endif
switch (cmd) {
case VIDIOCGCAP:
{
@@ -844,14 +1144,9 @@ static int ov511_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
{
struct video_picture p;
- p.colour = 0x8000; /* Damn British people :) */
- p.hue = 0x8000;
- p.brightness = 180 << 8; /* XXX */
- p.contrast = 192 << 8; /* XXX */
- p.whiteness = 105 << 8; /* XXX */
- p.depth = 24;
- p.palette = VIDEO_PALETTE_RGB24;
-
+ if (ov7610_get_picture(ov511, &p))
+ return -EIO;
+
if (copy_to_user(arg, &p, sizeof(p)))
return -EFAULT;
@@ -863,6 +1158,9 @@ static int ov511_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
if (copy_from_user(&p, arg, sizeof(p)))
return -EFAULT;
+
+ if (ov7610_set_picture(ov511, &p))
+ return -EIO;
return 0;
}
@@ -923,9 +1221,11 @@ static int ov511_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
if (copy_from_user((void *)&vm, (void *)arg, sizeof(vm)))
return -EFAULT;
- PDEBUG("MCAPTURE\n");
- PDEBUG("frame: %d, size: %dx%d, format: %d\n",
+#if 0
+ PDEBUG("MCAPTURE");
+ PDEBUG("frame: %d, size: %dx%d, format: %d",
vm.frame, vm.width, vm.height, vm.format);
+#endif
if (vm.format != VIDEO_PALETTE_RGB24)
return -EINVAL;
@@ -938,8 +1238,15 @@ static int ov511_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
/* Don't compress if the size changed */
if ((ov511->frame[vm.frame].width != vm.width) ||
- (ov511->frame[vm.frame].height != vm.height))
+ (ov511->frame[vm.frame].height != vm.height)) {
ov511->compress = 0;
+ ov511_mode_init_regs(ov511,
+ vm.width, vm.height, 0);
+#if 0
+ PDEBUG("ov511: Setting frame %d to (%d, %d) : %d",
+ vm.frame, vm.width, vm.height, 0);
+#endif
+ }
ov511->frame[vm.frame].width = vm.width;
ov511->frame[vm.frame].height = vm.height;
@@ -956,8 +1263,9 @@ static int ov511_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
if (copy_from_user((void *)&frame, arg, sizeof(int)))
return -EFAULT;
- PDEBUG("syncing to frame %d\n", frame);
-
+#if 0
+ PDEBUG("syncing to frame %d", frame);
+#endif
switch (ov511->frame[frame].grabstate) {
case FRAME_UNUSED:
return -EINVAL;
@@ -1029,7 +1337,7 @@ static long ov511_read(struct video_device *dev, char *buf, unsigned long count,
int frmx = -1;
volatile struct ov511_frame *frame;
- PDEBUG("ov511_read: %ld bytes, noblock=%d\n", count, noblock);
+ PDEBUG("ov511_read: %ld bytes, noblock=%d", count, noblock);
if (!dev || !buf)
return -EFAULT;
@@ -1060,20 +1368,20 @@ static long ov511_read(struct video_device *dev, char *buf, unsigned long count,
restart:
while (frame->grabstate == FRAME_GRABBING) {
- interruptible_sleep_on(&frame->wq);
+ interruptible_sleep_on(&ov511->frame[frmx].wq);
if (signal_pending(current))
return -EINTR;
}
if (frame->grabstate == FRAME_ERROR) {
frame->bytes_read = 0;
- printk(KERN_ERR "ov511_read: errored frame %d\n", ov511->curframe);
+ err("ov511_read: errored frame %d", ov511->curframe);
if (ov511_new_frame(ov511, frmx))
- printk(KERN_ERR "ov511_read: ov511_new_frame error\n");
+ err("ov511_read: ov511_new_frame error");
goto restart;
}
- PDEBUG("ov511_read: frmx=%d, bytes_read=%ld, scanlength=%ld\n", frmx,
+ PDEBUG("ov511_read: frmx=%d, bytes_read=%ld, scanlength=%ld", frmx,
frame->bytes_read, frame->scanlength);
/* copy bytes to user space; we allow for partials reads */
@@ -1084,7 +1392,7 @@ restart:
return -EFAULT;
frame->bytes_read += count;
- PDEBUG("ov511_read: {copy} count used=%ld, new bytes_read=%ld\n",
+ PDEBUG("ov511_read: {copy} count used=%ld, new bytes_read=%ld",
count, frame->bytes_read);
if (frame->bytes_read >= frame->scanlength) { /* All data has been read */
@@ -1093,7 +1401,7 @@ restart:
/* Mark it as available to be used again. */
ov511->frame[frmx].grabstate = FRAME_UNUSED;
if (ov511_new_frame(ov511, frmx ? 0 : 1))
- printk(KERN_ERR "ov511_read: ov511_new_frame returned error\n");
+ err("ov511_read: ov511_new_frame returned error");
}
return count;
@@ -1105,7 +1413,7 @@ static int ov511_mmap(struct video_device *dev, const char *adr, unsigned long s
unsigned long start = (unsigned long)adr;
unsigned long page, pos;
- PDEBUG("mmap: %ld (%lX) bytes\n", size, size);
+ PDEBUG("mmap: %ld (%lX) bytes", size, size);
if (size > (((2 * MAX_FRAME_SIZE) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))
return -EINVAL;
@@ -1145,14 +1453,52 @@ static struct video_device ov511_template = {
0
};
+static int ov7610_configure(struct usb_device *dev)
+{
+ if(ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_WRITE,
+ OV7610_I2C_WRITE_ID) < 0)
+ return -1;
+
+ if(ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_READ,
+ OV7610_I2C_READ_ID) < 0)
+ return -1;
+
+ /* Reset the camera chip */
+ if (ov511_i2c_reset(dev) < 0)
+ return -1;
+
+#if 0
+ if(usb_ov511_reg_write(dev, OV511_REG_I2C_CLOCK_PRESCALER,
+ OV511_I2C_CLOCK_PRESCALER))
+ return -1;
+#endif
+
+ if (ov511_reset(dev, OV511_RESET_NOREGS) < 0)
+ return -1;
+
+ /* Dummy read to sync I2C */
+ if(ov511_i2c_read(dev, 0x00) < 0)
+ return -1;
+
+
+ if((ov511_i2c_read(dev, OV7610_REG_ID_HIGH) != 0x7F) ||
+ (ov511_i2c_read(dev, OV7610_REG_ID_LOW) != 0xA2)) {
+ err("Failed to read OV7610 ID. You might not have an OV7610,");
+ err("or it may be not responding. Report this to");
+ err("mmcclelland@delphi.com");
+ return -1;
+ }
+
+ return 0;
+}
+
static int ov511_configure(struct usb_ov511 *ov511)
{
struct usb_device *dev = ov511->dev;
- int temprc; // DEBUG CODE
/* Set altsetting 0 */
if (usb_set_interface(dev, ov511->iface, 0) < 0) {
- printk(KERN_ERR "ov511: usb_set_interface error\n");
+ err("usb_set_interface error");
return -EBUSY;
}
@@ -1162,7 +1508,7 @@ static int ov511_configure(struct usb_ov511 *ov511)
init_waitqueue_head(&ov511->frame[1].wq);
if (video_register_device(&ov511->vdev, VFL_TYPE_GRABBER) == -1) {
- printk(KERN_ERR "ov511: video_register_device failed\n");
+ err("video_register_device failed");
return -EBUSY;
}
@@ -1172,7 +1518,7 @@ static int ov511_configure(struct usb_ov511 *ov511)
/* Initialize system */
if (ov511_reg_write(dev, OV511_REG_SYSTEM_INIT, 0x01) < 0) {
- printk(KERN_ERR "ov511: enable system: command failed\n");
+ err("enable system: command failed");
goto error;
}
@@ -1180,36 +1526,31 @@ static int ov511_configure(struct usb_ov511 *ov511)
if (ov511_reset(dev, OV511_RESET_ALL) < 0)
goto error;
+ if(ov7610_configure(dev) < 0) {
+ err("failed to configure OV7610");
+ goto error;
+ }
+
/* Disable compression */
if (ov511_reg_write(dev, OV511_OMNICE_ENABLE, 0x00) < 0) {
- printk(KERN_ERR "ov511: disable compression: command failed\n");
+ err("disable compression: command failed");
goto error;
}
-// FIXME - error checking needed
- ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_WRITE,
- OV7610_I2C_WRITE_ID);
- ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_READ,
- OV7610_I2C_READ_ID);
-
-// DEBUG CODE
-// usb_ov511_reg_write(dev, OV511_REG_I2C_CLOCK_PRESCALER,
-// OV511_I2C_CLOCK_PRESCALER);
-
- if (ov511_reset(dev, OV511_RESET_NOREGS) < 0)
- goto error;
-
- /* Dummy read to sync I2C */
- ov511_i2c_read(dev, 0x1C);
-
-// DEBUG - TEST CODE FOR CAMERA REG READ
- temprc = ov511_i2c_read(dev, 0x1C);
-
- temprc = ov511_i2c_read(dev, 0x1D);
-// END DEBUG CODE
-
ov511->compress = 0;
+ /* Set default sizes in case IOCTL (VIDIOCMCAPTURE) is not used
+ * (using read() instead). */
+ ov511->frame[0].width = DEFAULT_WIDTH;
+ ov511->frame[0].height = DEFAULT_HEIGHT;
+ ov511->frame[0].bytes_read = 0;
+ ov511->frame[1].width = DEFAULT_WIDTH;
+ ov511->frame[1].height = DEFAULT_HEIGHT;
+ ov511->frame[1].bytes_read = 0;
+
+ /* Initialize to DEFAULT_WIDTH, DEFAULT_HEIGHT, YUV4:2:0 */
+ ov511_mode_init_regs(ov511, DEFAULT_WIDTH, DEFAULT_HEIGHT, 0);
+
return 0;
error:
@@ -1228,7 +1569,7 @@ static void* ov511_probe(struct usb_device *dev, unsigned int ifnum)
struct usb_ov511 *ov511;
int rc;
- PDEBUG("probing for device...\n");
+ PDEBUG("probing for device...");
/* We don't handle multi-config cameras */
if (dev->descriptor.bNumConfigurations != 1)
@@ -1252,7 +1593,7 @@ static void* ov511_probe(struct usb_device *dev, unsigned int ifnum)
printk(KERN_INFO "ov511: USB OV511-based camera found\n");
if ((ov511 = kmalloc(sizeof(*ov511), GFP_KERNEL)) == NULL) {
- printk(KERN_ERR "ov511: couldn't kmalloc ov511 struct\n");
+ err("couldn't kmalloc ov511 struct");
return NULL;
}
@@ -1263,18 +1604,30 @@ static void* ov511_probe(struct usb_device *dev, unsigned int ifnum)
rc = ov511_reg_read(dev, OV511_REG_SYSTEM_CUSTOM_ID);
if (rc < 0) {
- printk("ov511: Unable to read camera bridge registers\n");
+ err("Unable to read camera bridge registers");
return NULL;
- } else if (rc == 3) { /* D-Link DSB-C300 */
+ }
+
+ switch(ov511->customid = rc) {
+ case 0: /* This also means that no custom ID was set */
+ printk("ov511: Camera is probably a MediaForte MV300\n");
+ break;
+ case 3:
printk("ov511: Camera is a D-Link DSB-C300\n");
- ov511->customid = 3;
- } else if (rc == 21) { /* Creative Labs WebCam 3 */
+ break;
+ case 21:
printk("ov511: Camera is a Creative Labs WebCam 3\n");
- ov511->customid = 21;
- } else {
- printk("ov511: Specific camera type (%d) not recognized\n", rc);
- printk("ov511: Please contact mmcclelland@delphi.com to request\n");
- printk("ov511: support for your camera.\n");
+ break;
+ case 100:
+ printk("ov511: Camera is a Lifeview RoboCam\n");
+ break;
+ case 102:
+ printk("ov511: Camera is a AverMedia InterCam Elite\n");
+ break;
+ default:
+ err("Specific camera type (%d) not recognized", rc);
+ err("Please contact mmcclelland@delphi.com to request");
+ err("support for your camera.");
return NULL;
}
@@ -1284,7 +1637,7 @@ static void* ov511_probe(struct usb_device *dev, unsigned int ifnum)
return ov511;
}
else {
- printk(KERN_ERR "ov511: Failed to configure camera\n");
+ err("Failed to configure camera");
return NULL;
}
@@ -1314,7 +1667,7 @@ static struct usb_driver ov511_driver = {
int usb_ov511_init(void)
{
- PDEBUG("usb_ov511_init()\n");
+ PDEBUG("usb_ov511_init()");
EXPORT_NO_SYMBOLS;
@@ -1336,7 +1689,7 @@ void cleanup_module(void)
{
usb_ov511_cleanup();
- PDEBUG("Module unloaded\n");
+ PDEBUG("Module unloaded");
}
#endif
diff --git a/drivers/usb/ov511.h b/drivers/usb/ov511.h
index 4dc7074bb..3f41e382d 100644
--- a/drivers/usb/ov511.h
+++ b/drivers/usb/ov511.h
@@ -6,9 +6,9 @@
#define OV511_DEBUG /* Turn on debug messages */
#ifdef OV511_DEBUG
-# define PDEBUG(fmt, args...) printk("ov511: " fmt, ## args)
+# define PDEBUG(fmt, args...) printk("ov511: " fmt "\n" , ## args)
#else
-# define PDEBUG(fmt, args...) /* Nothing */
+# define PDEBUG(fmt, args...) do {} while(0)
#endif
/* Camera interface register numbers */
@@ -103,13 +103,57 @@
#define OV511_ALTERNATE_SIZE_257 6
#define OV511_ALTERNATE_SIZE_0 7
+/* ov7610 registers */
+#define OV7610_REG_GAIN 0x00
+#define OV7610_REG_BLUE 0x01
+#define OV7610_REG_RED 0x02
+#define OV7610_REG_SAT 0x03
+#define OV7610_REG_CNT 0x05
+#define OV7610_REG_BRT 0x06
+#define OV7610_REG_BLUE_BIAS 0x0C
+#define OV7610_REG_RED_BIAS 0x0D
+#define OV7610_REG_GAMMA_COEFF 0x0E
+#define OV7610_REG_WB_RANGE 0x0F
+#define OV7610_REG_EXP 0x10
+#define OV7610_REG_CLOCK 0x11
+#define OV7610_REG_COM_A 0x12
+#define OV7610_REG_COM_B 0x13
+#define OV7610_REG_COM_C 0x14
+#define OV7610_REG_COM_D 0x15
+#define OV7610_REG_FIELD_DIVIDE 0x16
+#define OV7610_REG_HWIN_START 0x17
+#define OV7610_REG_HWIN_END 0x18
+#define OV7610_REG_VWIN_START 0x19
+#define OV7610_REG_VWIN_END 0x1A
+#define OV7610_REG_PIXEL_SHIFT 0x1B
+#define OV7610_REG_ID_HIGH 0x1C
+#define OV7610_REG_ID_LOW 0x1D
+#define OV7610_REG_COM_E 0x20
+#define OV7610_REG_YOFFSET 0x21
+#define OV7610_REG_UOFFSET 0x22
+#define OV7610_REG_ECW 0x24
+#define OV7610_REG_ECB 0x25
+#define OV7610_REG_COM_F 0x26
+#define OV7610_REG_COM_G 0x27
+#define OV7610_REG_COM_H 0x28
+#define OV7610_REG_COM_I 0x29
+#define OV7610_REG_FRAMERATE_H 0x2A
+#define OV7610_REG_FRAMERATE_L 0x2B
+#define OV7610_REG_ALC 0x2C
+#define OV7610_REG_COM_J 0x2D
+#define OV7610_REG_VOFFSET 0x2E
+#define OV7610_REG_YGAMMA 0x33
+#define OV7610_REG_BIAS_ADJUST 0x34
+#define OV7610_REG_COM_L 0x35
+#define OV7610_REG_COM_K 0x38
+
#define STREAM_BUF_SIZE (PAGE_SIZE * 4)
-#define SCRATCH_BUF_SIZE (STREAM_BUF_SIZE * 2)
+#define SCRATCH_BUF_SIZE 384
#define FRAMES_PER_DESC 10 /* FIXME - What should this be? */
-#define FRAME_SIZE_PER_DESC 512 /* FIXME - Shouldn't be hardcoded */
+#define FRAME_SIZE_PER_DESC 993 /* FIXME - Shouldn't be hardcoded */
// FIXME - should this be 0x81 (endpoint address) or 0x01 (endpoint number)?
#define OV511_ENDPOINT_ADDRESS 0x81 /* Address of isoc endpoint */
@@ -166,6 +210,7 @@ struct ov511_frame {
int curline; /* Line of frame we're working on */
int curpix;
+ int segment; /* Segment from the incoming data */
long scanlength; /* uncompressed, raw data length of frame */
long bytes_read; /* amount of scanlength that has been read from *data */
diff --git a/drivers/usb/printer.c b/drivers/usb/printer.c
index 6fb7df722..370ed6dd6 100644
--- a/drivers/usb/printer.c
+++ b/drivers/usb/printer.c
@@ -1,481 +1,450 @@
-/* Driver for USB Printers
- *
- * Copyright 1999 Michael Gee (michael@linuxspecific.com)
- * Copyright 1999 Pavel Machek (pavel@suse.cz)
+/*
+ * printer.c Version 0.3
+ *
+ * Copyright (c) 1999 Michael Gee <michael@linuxspecific.com>
+ * Copyright (c) 1999 Pavel Machek <pavel@suse.cz>
+ * Copyright (c) 2000 Vojtech Pavlik <vojtech@suse.cz>
+ *
+ * USB Printer Device Class driver for USB printers and printer cables
+ *
+ * Sponsored by SuSE
+ *
+ * ChangeLog:
+ * v0.1 - thorough cleaning, URBification, almost a rewrite
+ * v0.2 - some more cleanups
+ * v0.3 - cleaner again, waitqueue fixes
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * Distribute under GPL version 2 or later.
+ * 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
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/signal.h>
-#include <linux/errno.h>
-#include <linux/miscdevice.h>
-#include <linux/random.h>
#include <linux/poll.h>
#include <linux/init.h>
#include <linux/malloc.h>
#include <linux/lp.h>
-#include <linux/spinlock.h>
+
+#define DEBUG
#include "usb.h"
-/* Define IEEE_DEVICE_ID if you want to see the IEEE-1284 Device ID string.
- * This may include the printer's serial number.
- * An example from an HP 970C DeskJet printer is (this is one long string,
- * with the serial number changed):
-MFG:HEWLETT-PACKARD;MDL:DESKJET 970C;CMD:MLC,PCL,PML;CLASS:PRINTER;DESCRIPTION:Hewlett-Packard DeskJet 970C;SERN:US970CSEPROF;VSTATUS:$HB0$NC0,ff,DN,IDLE,CUT,K1,C0,DP,NR,KP000,CP027;VP:0800,FL,B0;VJ: ;
+#define USBLP_BUF_SIZE 8192
+
+/*
+ * USB Printer Requests
*/
-#define IEEE_DEVICE_ID
-#define NAK_TIMEOUT (HZ) /* stall wait for printer */
-#define MAX_RETRY_COUNT ((60*60*HZ)/NAK_TIMEOUT) /* should not take 1 minute a page! */
+#define USBLP_REQ_GET_ID 0x00
+#define USBLP_REQ_GET_STATUS 0x01
+#define USBLP_REQ_RESET 0x02
+
+#define USBLP_MINORS 16
+#define USBLP_MINOR_BASE 0
+
+#define USBLP_WRITE_TIMEOUT (60*HZ) /* 60 seconds */
+
+struct usblp {
+ struct usb_device *dev; /* USB device */
+ struct urb readurb, writeurb; /* The urbs */
+ wait_queue_head_t wait; /* Zzzzz ... */
+ int readcount; /* Counter for reads */
+ int ifnum; /* Interface number */
+ int minor; /* minor number of device */
+ unsigned char used; /* True if open */
+ unsigned char bidir; /* interface is bidirectional */
+};
-#define BIG_BUF_SIZE 8192
-#define SUBCLASS_PRINTERS 1
-#define PROTOCOL_UNIDIRECTIONAL 1
-#define PROTOCOL_BIDIRECTIONAL 2
+static struct usblp *usblp_table[USBLP_MINORS] = { NULL, /* ... */ };
/*
- * USB Printer Requests
+ * Functions for usblp control messages.
*/
-#define USB_PRINTER_REQ_GET_DEVICE_ID 0
-#define USB_PRINTER_REQ_GET_PORT_STATUS 1
-#define USB_PRINTER_REQ_SOFT_RESET 2
-
-#define MAX_PRINTERS 8
-
-struct pp_usb_data {
- struct usb_device *pusb_dev;
- __u8 isopen; /* True if open */
- __u8 noinput; /* True if no input stream */
- __u8 minor; /* minor number of device */
- __u8 status; /* last status from device */
- int maxin, maxout; /* max transfer size in and out */
- char *obuf; /* transfer buffer (out only) */
- wait_queue_head_t wait_q; /* for timeouts */
- unsigned int last_error; /* save for checking */
- int bulk_in_ep; /* Bulk IN endpoint */
- int bulk_out_ep; /* Bulk OUT endpoint */
- int bulk_in_index; /* endpoint[bulk_in_index] */
- int bulk_out_index; /* endpoint[bulk_out_index] */
-};
-static struct pp_usb_data *minor_data[MAX_PRINTERS];
+static int usblp_ctrl_msg(struct usblp *usblp, int request, int dir, int recip, void *buf, int len)
+{
+ int retval = usb_control_msg(usblp->dev,
+ dir ? usb_rcvctrlpipe(usblp->dev, 0) : usb_sndctrlpipe(usblp->dev, 0),
+ request, USB_TYPE_CLASS | dir | recip, 0, usblp->ifnum, buf, len, HZ * 5);
+ dbg("usblp_control_msg: rq: 0x%02x dir: %d recip: %d len: %#x result: %d", request, !!dir, recip, len, retval);
+ return retval < 0 ? retval : 0;
+}
-#define PPDATA(x) ((struct pp_usb_data *)(x))
+#define usblp_read_status(usblp, status)\
+ usblp_ctrl_msg(usblp, USBLP_REQ_GET_STATUS, USB_DIR_IN, USB_RECIP_INTERFACE, status, 1)
+#define usblp_get_id(usblp, id, maxlen)\
+ usblp_ctrl_msg(usblp, USBLP_REQ_GET_ID, USB_DIR_IN, USB_RECIP_INTERFACE, id, maxlen)
+#define usblp_reset(usblp)\
+ usblp_ctrl_msg(usblp, USBLP_REQ_RESET, USB_DIR_OUT, USB_RECIP_OTHER, NULL, 0)
-static unsigned char printer_read_status(struct pp_usb_data *p)
+/*
+ * URB callback.
+ */
+
+static void usblp_bulk(struct urb *urb)
{
- __u8 status;
- int err;
- struct usb_device *dev = p->pusb_dev;
-
- err = usb_control_msg(dev, usb_rcvctrlpipe(dev,0),
- USB_PRINTER_REQ_GET_PORT_STATUS,
- USB_TYPE_CLASS | USB_RT_INTERFACE | USB_DIR_IN,
- 0, 0, &status, sizeof(status), HZ);
- if (err < 0) {
- printk(KERN_ERR "usblp%d: read_status control_msg error = %d\n",
- p->minor, err);
- return 0;
- }
- return status;
+ struct usblp *usblp = urb->context;
+
+ if (!usblp || !usblp->dev || !usblp->used)
+ return;
+
+ if (urb->status)
+ warn("nonzero read bulk status received: %d", urb->status);
+
+ wake_up_interruptible(&usblp->wait);
}
-static int printer_check_status(struct pp_usb_data *p)
+/*
+ * Get and print printer errors.
+ */
+
+static int usblp_check_status(struct usblp *usblp)
{
- unsigned int last = p->last_error;
- unsigned char status = printer_read_status(p);
-
- if (status & LP_PERRORP)
- /* No error. */
- last = 0;
- else if ((status & LP_POUTPA)) {
- if (last != LP_POUTPA) {
- last = LP_POUTPA;
- printk(KERN_INFO "usblp%d out of paper (%x)\n", p->minor, status);
+ unsigned char status;
+
+ if (usblp_read_status(usblp, &status)) {
+ err("failed reading usblp status");
+ return -EIO;
+ }
+
+ if (status & LP_PERRORP) {
+
+ if (status & LP_POUTPA) {
+ printk(KERN_INFO "usblp%d: out of paper", usblp->minor);
+ return -ENOSPC;
}
- } else if (!(status & LP_PSELECD)) {
- if (last != LP_PSELECD) {
- last = LP_PSELECD;
- printk(KERN_INFO "usblp%d off-line (%x)\n", p->minor, status);
+ if (~status & LP_PSELECD) {
+ printk(KERN_INFO "usblp%d: off-line", usblp->minor);
+ return -EIO;
}
- } else {
- if (last != LP_PERRORP) {
- last = LP_PERRORP;
- printk(KERN_INFO "usblp%d on fire (%x)\n", p->minor, status);
+ if (~status & LP_PERRORP) {
+ printk(KERN_INFO "usblp%d: on fire", usblp->minor);
+ return -EIO;
}
}
- p->last_error = last;
- return status;
+ return 0;
}
-static void printer_reset(struct pp_usb_data *p)
-{
- struct usb_device *dev = p->pusb_dev;
- int err;
-
- err = usb_control_msg(dev, usb_sndctrlpipe(dev,0),
- USB_PRINTER_REQ_SOFT_RESET,
- USB_TYPE_CLASS | USB_RECIP_OTHER,
- 0, 0, NULL, 0, HZ);
- if (err < 0)
- printk(KERN_ERR "usblp%d: reset control_msg error = %d\n",
- p->minor, err);
-}
+/*
+ * File op functions.
+ */
-static int open_printer(struct inode *inode, struct file *file)
+static int usblp_open(struct inode *inode, struct file *file)
{
- struct pp_usb_data *p;
+ int minor = MINOR(inode->i_rdev) - USBLP_MINOR_BASE;
+ struct usblp *usblp;
+ int retval;
- if (MINOR(inode->i_rdev) >= MAX_PRINTERS ||
- !minor_data[MINOR(inode->i_rdev)]) {
+ if (minor < 0 || minor >= USBLP_MINORS)
return -ENODEV;
- }
- p = minor_data[MINOR(inode->i_rdev)];
- p->minor = MINOR(inode->i_rdev);
+ usblp = usblp_table[minor];
- if (p->isopen++) {
- printk(KERN_ERR "usblp%d: printer is already open\n",
- p->minor);
- return -EBUSY;
- }
- if (!(p->obuf = (char *)__get_free_page(GFP_KERNEL))) {
- p->isopen = 0;
- printk(KERN_ERR "usblp%d: cannot allocate memory\n",
- p->minor);
- return -ENOMEM;
- }
+ if (!usblp || !usblp->dev)
+ return -ENODEV;
- printer_check_status(p);
+ if (usblp->used)
+ return -EBUSY;
- file->private_data = p;
-// printer_reset(p);
- init_waitqueue_head(&p->wait_q);
+ if ((retval = usblp_check_status(usblp)))
+ return retval;
MOD_INC_USE_COUNT;
+ usblp->used = 1;
+ file->private_data = usblp;
+
+ usblp->writeurb.transfer_buffer_length = 0;
+ usblp->writeurb.status = 0;
+ usblp->readcount = 0;
+
+ usb_submit_urb(&usblp->readurb);
return 0;
}
-static int close_printer(struct inode *inode, struct file *file)
+static int usblp_release(struct inode *inode, struct file *file)
{
- struct pp_usb_data *p = file->private_data;
-
- free_page((unsigned long)p->obuf);
- p->isopen = 0;
- file->private_data = NULL;
- /* free the resources if the printer is no longer around */
- if (!p->pusb_dev) {
- minor_data[p->minor] = NULL;
- kfree(p);
- }
+ struct usblp *usblp = file->private_data;
+
MOD_DEC_USE_COUNT;
+ usblp->used = 0;
+
+ if (usblp->dev) {
+ usb_unlink_urb(&usblp->readurb);
+ usb_unlink_urb(&usblp->writeurb);
+ return 0;
+ }
+
+ usblp_table[usblp->minor] = NULL;
+ kfree(usblp);
+
return 0;
}
-static ssize_t write_printer(struct file *file,
- const char *buffer, size_t count, loff_t *ppos)
+static unsigned int usblp_poll(struct file *file, struct poll_table_struct *wait)
{
- struct pp_usb_data *p = file->private_data;
- unsigned long copy_size;
- unsigned long bytes_written = 0;
- unsigned long partial;
- int result = USB_ST_NOERROR;
- int maxretry;
-
- do {
- char *obuf = p->obuf;
- unsigned long thistime;
-
- thistime = copy_size = (count > p->maxout) ? p->maxout : count;
- if (copy_from_user(p->obuf, buffer, copy_size))
- return -EFAULT;
- maxretry = MAX_RETRY_COUNT;
-
- while (thistime) {
- if (!p->pusb_dev)
- return -ENODEV;
- if (signal_pending(current)) {
- return bytes_written ? bytes_written : -EINTR;
- }
- result = usb_bulk_msg(p->pusb_dev,
- usb_sndbulkpipe(p->pusb_dev, p->bulk_out_ep),
- obuf, thistime, &partial, HZ*20);
- if (partial) {
- obuf += partial;
- thistime -= partial;
- maxretry = MAX_RETRY_COUNT;
- }
- if (result == USB_ST_TIMEOUT) { /* NAK - so hold for a while */
- if (!maxretry--)
- return -ETIME;
- interruptible_sleep_on_timeout(&p->wait_q, NAK_TIMEOUT);
- continue;
- } else if (!result && !partial) {
- break;
+ struct usblp *usblp = file->private_data;
+ poll_wait(file, &usblp->wait, wait);
+ return (usblp->readurb.status == -EINPROGRESS ? 0 : POLLIN | POLLRDNORM)
+ | (usblp->writeurb.status == -EINPROGRESS ? 0 : POLLOUT | POLLWRNORM);
+}
+
+static ssize_t usblp_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ struct usblp *usblp = file->private_data;
+ int retval, timeout, writecount = 0;
+
+ while (writecount < count) {
+
+ if (usblp->writeurb.status == -EINPROGRESS) {
+
+ if (file->f_flags & O_NONBLOCK)
+ return -EAGAIN;
+
+ timeout = USBLP_WRITE_TIMEOUT;
+ while (timeout && usblp->writeurb.status == -EINPROGRESS) {
+
+ if (signal_pending(current))
+ return writecount ? writecount : -EINTR;
+
+ timeout = interruptible_sleep_on_timeout(&usblp->wait, timeout);
}
- };
- if (result) {
- /* whoops - let's reset and fail the request */
-// printk("Whoops - %x\n", result);
- printer_reset(p);
- interruptible_sleep_on_timeout(&p->wait_q, 5*HZ); /* let reset do its stuff */
+ }
+
+ if (usblp->writeurb.status == -EINPROGRESS) {
+ usb_unlink_urb(&usblp->writeurb);
+ printk(KERN_ERR "usblp%d: timed out\n", usblp->minor);
return -EIO;
}
- bytes_written += copy_size;
- count -= copy_size;
- buffer += copy_size;
- } while ( count > 0 );
- return bytes_written ? bytes_written : -EIO;
+ if (!usblp->dev)
+ return -ENODEV;
+
+ if (!usblp->writeurb.status)
+ writecount += usblp->writeurb.transfer_buffer_length;
+ else {
+ if (!(retval = usblp_check_status(usblp))) {
+ printk(KERN_ERR "usblp%d: error %d writing to printer\n",
+ usblp->minor, usblp->writeurb.status);
+ return -EIO;
+ }
+
+ return retval;
+ }
+
+ if (writecount == count)
+ continue;
+
+ usblp->writeurb.transfer_buffer_length = (count - writecount) < USBLP_BUF_SIZE ?
+ (count - writecount) : USBLP_BUF_SIZE;
+
+ if (copy_from_user(usblp->writeurb.transfer_buffer, buffer + writecount,
+ usblp->writeurb.transfer_buffer_length)) return -EFAULT;
+
+ usb_submit_urb(&usblp->writeurb);
+ }
+
+ return count;
}
-static ssize_t read_printer(struct file *file,
- char *buffer, size_t count, loff_t *ppos)
+static ssize_t usblp_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
{
- struct pp_usb_data *p = file->private_data;
- int read_count = 0;
- int this_read;
- char buf[64];
- unsigned long partial;
- int result;
-
- if (p->noinput)
+ struct usblp *usblp = file->private_data;
+ DECLARE_WAITQUEUE(wait, current);
+
+ if (!usblp->bidir)
return -EINVAL;
- while (count) {
- if (signal_pending(current)) {
- return read_count ? read_count : -EINTR;
- }
- if (!p->pusb_dev)
- return -ENODEV;
+ if (usblp->readurb.status == -EINPROGRESS) {
- this_read = (count > sizeof(buf)) ? sizeof(buf) : count;
- result = usb_bulk_msg(p->pusb_dev,
- usb_rcvbulkpipe(p->pusb_dev, p->bulk_in_ep),
- buf, this_read, &partial, HZ*20);
- if (result < 0)
- printk(KERN_ERR "usblp%d read_printer bulk_msg error = %d\n",
- p->minor, result);
-
- /* unlike writes, we don't retry a NAK, just stop now */
- if (!result & partial)
- count = this_read = partial;
- else if (result)
- return -EIO;
+ if (file->f_flags & O_NONBLOCK)
+ return -EAGAIN;
- if (this_read) {
- if (copy_to_user(buffer, buf, this_read))
- return -EFAULT;
- count -= this_read;
- read_count += this_read;
- buffer += this_read;
+ while (usblp->readurb.status == -EINPROGRESS) {
+ if (signal_pending(current))
+ return -EINTR;
+ interruptible_sleep_on(&usblp->wait);
}
}
- return read_count;
+ if (!usblp->dev)
+ return -ENODEV;
+
+ if (usblp->readurb.status) {
+ printk(KERN_ERR "usblp%d: error %d reading from printer\n",
+ usblp->minor, usblp->readurb.status);
+ usb_submit_urb(&usblp->readurb);
+ return -EIO;
+ }
+
+ count = count < usblp->readurb.actual_length - usblp->readcount ?
+ count : usblp->readurb.actual_length - usblp->readcount;
+
+ if (copy_to_user(buffer, usblp->readurb.transfer_buffer + usblp->readcount, count))
+ return -EFAULT;
+
+ if ((usblp->readcount += count) == usblp->readurb.actual_length)
+ usb_submit_urb(&usblp->readurb);
+
+ return count;
}
-static void *printer_probe(struct usb_device *dev, unsigned int ifnum)
+static void *usblp_probe(struct usb_device *dev, unsigned int ifnum)
{
struct usb_interface_descriptor *interface;
- struct pp_usb_data *pp;
- int i;
- __u8 status;
-
- /*
- * FIXME - this will not cope with combined printer/scanners
- */
- if ((dev->descriptor.bDeviceClass != USB_CLASS_PRINTER &&
- dev->descriptor.bDeviceClass != 0) ||
- dev->descriptor.bNumConfigurations != 1 ||
- dev->actconfig->bNumInterfaces != 1) {
- return NULL;
- }
+ struct usb_endpoint_descriptor *epread, *epwrite;
+ struct usblp *usblp;
+ int minor, i, alts = -1, bidir = 0;
+ char *buf;
- interface = &dev->actconfig->interface[ifnum].altsetting[0];
- /* Let's be paranoid (for the moment). */
- if (interface->bInterfaceClass != USB_CLASS_PRINTER ||
- interface->bInterfaceSubClass != SUBCLASS_PRINTERS ||
- (interface->bInterfaceProtocol != PROTOCOL_BIDIRECTIONAL &&
- interface->bInterfaceProtocol != PROTOCOL_UNIDIRECTIONAL) ||
- interface->bNumEndpoints > 2) {
- return NULL;
+ for (i = 0; i < dev->actconfig->interface[ifnum].num_altsetting; i++) {
+
+ interface = &dev->actconfig->interface[ifnum].altsetting[i];
+
+ if (interface->bInterfaceClass != 7 || interface->bInterfaceSubClass != 1 ||
+ (interface->bInterfaceProtocol != 1 && interface->bInterfaceProtocol != 2) ||
+ (interface->bInterfaceProtocol > interface->bNumEndpoints))
+ continue;
+
+ if (alts == -1)
+ alts = i;
+
+ if (!bidir && interface->bInterfaceProtocol == 2) {
+ bidir = 1;
+ alts = i;
+ }
}
- /* Does this (these) interface(s) support bulk transfers? */
- if ((interface->endpoint[0].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
- != USB_ENDPOINT_XFER_BULK) {
+ if (alts == -1)
return NULL;
+
+ interface = &dev->actconfig->interface[ifnum].altsetting[alts];
+ if (usb_set_interface(dev, ifnum, alts))
+ err("can't set desired altsetting %d on interface %d", alts, ifnum);
+
+ epwrite = interface->endpoint + 0;
+ epread = NULL;
+
+ if (bidir) {
+ epread = interface->endpoint + 1;
+ if ((epread->bEndpointAddress & 0x80) != 0x80) {
+ epwrite = interface->endpoint + 1;
+ epread = interface->endpoint + 0;
+
+ if ((epread->bEndpointAddress & 0x80) != 0x80)
+ return NULL;
+ }
}
- if ((interface->bNumEndpoints > 1) &&
- ((interface->endpoint[1].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
- != USB_ENDPOINT_XFER_BULK)) {
+
+ if ((epwrite->bEndpointAddress & 0x80) == 0x80)
return NULL;
- }
- /*
- * Does this interface have at least one OUT endpoint
- * that we can write to: endpoint index 0 or 1?
- */
- if ((interface->endpoint[0].bEndpointAddress & USB_ENDPOINT_DIR_MASK)
- != USB_DIR_OUT &&
- (interface->bNumEndpoints > 1 &&
- (interface->endpoint[1].bEndpointAddress & USB_ENDPOINT_DIR_MASK)
- != USB_DIR_OUT)) {
- return NULL;
- }
-
- for (i=0; i<MAX_PRINTERS; i++) {
- if (!minor_data[i])
- break;
+ for (minor = 0; minor < USBLP_MINORS && usblp_table[minor]; minor++);
+ if (usblp_table[minor]) {
+ err("no more free usblp devices");
+ return NULL;
}
- if (i >= MAX_PRINTERS) {
- printk(KERN_ERR "No minor table space available for new USB printer\n");
+
+ if (!(usblp = kmalloc(sizeof(struct usblp), GFP_KERNEL))) {
+ err("out of memory");
return NULL;
}
+ memset(usblp, 0, sizeof(struct usblp));
+
+ usblp->dev = dev;
+ usblp->ifnum = ifnum;
+ usblp->minor = minor;
+ usblp->bidir = bidir;
- printk(KERN_INFO "USB printer found at address %d\n", dev->devnum);
+ init_waitqueue_head(&usblp->wait);
- if (!(pp = kmalloc(sizeof(struct pp_usb_data), GFP_KERNEL))) {
- printk(KERN_DEBUG "USB printer: no memory!\n");
+ if (!(buf = kmalloc(USBLP_BUF_SIZE * (bidir ? 2 : 1), GFP_KERNEL))) {
+ err("out of memory");
+ kfree(usblp);
return NULL;
}
- memset(pp, 0, sizeof(struct pp_usb_data));
- minor_data[i] = PPDATA(pp);
-
- pp->minor = i;
- pp->pusb_dev = dev;
- pp->maxout = (BIG_BUF_SIZE > PAGE_SIZE) ? PAGE_SIZE : BIG_BUF_SIZE;
- if (interface->bInterfaceProtocol != PROTOCOL_BIDIRECTIONAL)
- pp->noinput = 1;
-
- pp->bulk_out_index =
- ((interface->endpoint[0].bEndpointAddress & USB_ENDPOINT_DIR_MASK)
- == USB_DIR_OUT) ? 0 : 1;
- pp->bulk_in_index = pp->noinput ? -1 :
- (pp->bulk_out_index == 0) ? 1 : 0;
- pp->bulk_in_ep = pp->noinput ? -1 :
- interface->endpoint[pp->bulk_in_index].bEndpointAddress &
- USB_ENDPOINT_NUMBER_MASK;
- pp->bulk_out_ep =
- interface->endpoint[pp->bulk_out_index].bEndpointAddress &
- USB_ENDPOINT_NUMBER_MASK;
- if (interface->bInterfaceProtocol == PROTOCOL_BIDIRECTIONAL) {
- pp->maxin =
- interface->endpoint[pp->bulk_in_index].wMaxPacketSize;
- }
+ FILL_BULK_URB(&usblp->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress),
+ buf, 0, usblp_bulk, usblp);
- printk(KERN_INFO "usblp%d Summary:\n", pp->minor);
- printk(KERN_INFO "index=%d, maxout=%d, noinput=%d, maxin=%d\n",
- i, pp->maxout, pp->noinput, pp->maxin);
- printk(KERN_INFO "bulk_in_ix=%d, bulk_in_ep=%d, bulk_out_ix=%d, bulk_out_ep=%d\n",
- pp->bulk_in_index,
- pp->bulk_in_ep,
- pp->bulk_out_index,
- pp->bulk_out_ep);
-
-#ifdef IEEE_DEVICE_ID
- {
- __u8 ieee_id[64]; /* first 2 bytes are (big-endian) length */
- /* This string space may be too short. */
- int length = (ieee_id[0] << 8) + ieee_id[1]; /* high-low */
- /* This calc. or be16_to_cpu() both get
- * some weird results for <length>. */
- int err;
-
- /* Let's get the device id if possible. */
- err = usb_control_msg(dev, usb_rcvctrlpipe(dev,0),
- USB_PRINTER_REQ_GET_DEVICE_ID,
- USB_TYPE_CLASS | USB_RT_INTERFACE | USB_DIR_IN,
- 0, 0, ieee_id,
- sizeof(ieee_id)-1, HZ);
- if (err >= 0) {
- if (ieee_id[1] < sizeof(ieee_id) - 1)
- ieee_id[ieee_id[1]+2] = '\0';
- else
- ieee_id[sizeof(ieee_id)-1] = '\0';
- printk(KERN_INFO "usblp%d Device ID length=%d [%x:%x]\n",
- pp->minor, length, ieee_id[0], ieee_id[1]);
- printk(KERN_INFO "usblp%d Device ID=%s\n",
- pp->minor, &ieee_id[2]);
- }
- else
- printk(KERN_INFO "usblp%d: error = %d reading IEEE-1284 Device ID\n",
- pp->minor, err);
+ if (bidir) {
+ FILL_BULK_URB(&usblp->readurb, dev, usb_rcvbulkpipe(dev, epread->bEndpointAddress),
+ buf + USBLP_BUF_SIZE, USBLP_BUF_SIZE, usblp_bulk, usblp);
}
-#endif
- status = printer_read_status(PPDATA(pp));
- printk(KERN_INFO "usblp%d probe status is %x: %s,%s,%s\n",
- pp->minor, status,
- (status & LP_PSELECD) ? "Selected" : "Not Selected",
- (status & LP_POUTPA) ? "No Paper" : "Paper",
- (status & LP_PERRORP) ? "No Error" : "Error");
+ printk(KERN_INFO "usblp%d: USB %sdirectional printer dev %d if %d alt %d\n",
+ minor, bidir ? "Bi" : "Uni", dev->devnum, ifnum, alts);
- return pp;
+ return usblp_table[minor] = usblp;
}
-static void printer_disconnect(struct usb_device *dev, void *ptr)
+static void usblp_disconnect(struct usb_device *dev, void *ptr)
{
- struct pp_usb_data *pp = ptr;
+ struct usblp *usblp = ptr;
- if (pp->isopen) {
- /* better let it finish - the release will do whats needed */
- pp->pusb_dev = NULL;
+ if (!usblp || !usblp->dev) {
+ err("disconnect on nonexisting interface");
return;
}
- minor_data[pp->minor] = NULL;
- kfree(pp);
+
+ usblp->dev = NULL;
+
+ usb_unlink_urb(&usblp->readurb);
+ usb_unlink_urb(&usblp->writeurb);
+
+ kfree(usblp->writeurb.transfer_buffer);
+
+ if (usblp->used) return;
+
+ usblp_table[usblp->minor] = NULL;
+ kfree(usblp);
}
-static struct file_operations usb_printer_fops = {
- NULL, /* seek */
- read_printer,
- write_printer,
- NULL, /* readdir */
- NULL, /* poll - out for the moment */
- NULL, /* ioctl */
- NULL, /* mmap */
- open_printer,
- NULL, /* flush ? */
- close_printer,
- NULL,
- NULL
+static struct file_operations usblp_fops = {
+ read: usblp_read,
+ write: usblp_write,
+ open: usblp_open,
+ release: usblp_release,
+ poll: usblp_poll
};
-static struct usb_driver printer_driver = {
- "printer",
- printer_probe,
- printer_disconnect,
- { NULL, NULL },
- &usb_printer_fops,
- 0
+static struct usb_driver usblp_driver = {
+ name: "usblp",
+ probe: usblp_probe,
+ disconnect: usblp_disconnect,
+ fops: &usblp_fops,
+ minor: USBLP_MINOR_BASE
};
-int usb_printer_init(void)
+#ifdef MODULE
+void cleanup_module(void)
{
- if (usb_register(&printer_driver))
- return -1;
-
- printk(KERN_INFO "USB Printer driver registered.\n");
- return 0;
+ usb_deregister(&usblp_driver);
}
-
-#ifdef MODULE
int init_module(void)
+#else
+int usb_printer_init(void)
+#endif
{
- return usb_printer_init();
-}
+ if (usb_register(&usblp_driver))
+ return -1;
-void cleanup_module(void)
-{
- usb_deregister(&printer_driver);
+ return 0;
}
-#endif
diff --git a/drivers/usb/proc_usb.c b/drivers/usb/proc_usb.c
deleted file mode 100644
index ca431d454..000000000
--- a/drivers/usb/proc_usb.c
+++ /dev/null
@@ -1,1189 +0,0 @@
-/*
- * drivers/usb/proc_usb.c
- * (C) Copyright 1999 Randy Dunlap.
- * (C) Copyright 1999 Thomas Sailer <sailer@ife.ee.ethz.ch>. (proc file per device)
- * (C) Copyright 1999 Deti Fliegl (new USB architecture)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- *************************************************************
- *
- * This is a /proc/bus/usb filesystem output module for USB.
- * It creates /proc/bus/usb/drivers and /proc/bus/usb/devices.
- *
- * /proc/bus/usb/devices contains USB topology, device, config, class,
- * interface, & endpoint data.
- *
- * I considered using /proc/bus/usb/devices/device# for each device
- * as it is attached or detached, but I didn't like this for some
- * reason -- maybe it's just too deep of a directory structure.
- * I also don't like looking in multiple places to gather and view
- * the data. Having only one file for ./devices also prevents race
- * conditions that could arise if a program was reading device info
- * for devices that are being removed (unplugged). (That is, the
- * program may find a directory for devnum_12 then try to open it,
- * but it was just unplugged, so the directory is now deleted.
- * But programs would just have to be prepared for situations like
- * this in any plug-and-play environment.)
- *
- * 1999-12-16: Thomas Sailer <sailer@ife.ee.ethz.ch>
- * Converted the whole proc stuff to real
- * read methods. Now not the whole device list needs to fit
- * into one page, only the device list for one bus.
- * Added a poll method to /proc/bus/usb/devices, to wake
- * up an eventual usbd
- *
- * $Id: proc_usb.c,v 1.14 1999/12/17 10:51:41 fliegl Exp $
- */
-
-#define __NO_VERSION__
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-#include <linux/string.h>
-#include <linux/list.h>
-#include <linux/bitops.h>
-#include <asm/uaccess.h>
-#include <linux/mm.h>
-#include <linux/wait.h>
-#include <linux/poll.h>
-
-#include "usb.h"
-
-
-#define MAX_TOPO_LEVEL 6
-
-/* Define ALLOW_SERIAL_NUMBER if you want to see the serial number of devices */
-#define ALLOW_SERIAL_NUMBER
-
-static char *format_topo =
-/* T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd */
- "T: Bus=%2.2d Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%3s MxCh=%2d\n";
-
-static char *format_string_manufacturer =
-/* S: Manufacturer=xxxx */
- "S: Manufacturer=%s\n";
-
-static char *format_string_product =
-/* S: Product=xxxx */
- "S: Product=%s\n";
-
-#ifdef ALLOW_SERIAL_NUMBER
-static char *format_string_serialnumber =
-/* S: SerialNumber=xxxx */
- "S: SerialNumber=%s\n";
-#endif
-
-static char *format_bandwidth =
-/* B: Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd */
- "B: Alloc=%3d/%3d us (%2d%%), #Int=%3d, #Iso=%3d\n";
-
-static char *format_device1 =
-/* D: Ver=xx.xx Cls=xx(sssss) Sub=xx Prot=xx MxPS=dd #Cfgs=dd */
- "D: Ver=%2x.%02x Cls=%02x(%-5s) Sub=%02x Prot=%02x MxPS=%2d #Cfgs=%3d\n";
-
-static char *format_device2 =
-/* P: Vendor=xxxx ProdID=xxxx Rev=xx.xx */
- "P: Vendor=%04x ProdID=%04x Rev=%2x.%02x\n";
-
-static char *format_config =
-/* C: #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA */
- "C:%c #Ifs=%2d Cfg#=%2d Atr=%02x MxPwr=%3dmA\n";
-
-static char *format_iface =
-/* I: If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=xxxx*/
- "I: If#=%2d Alt=%2d #EPs=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x Driver=%s\n";
-
-static char *format_endpt =
-/* E: Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=dddms */
- "E: Ad=%02x(%c) Atr=%02x(%-4s) MxPS=%4d Ivl=%3dms\n";
-
-
-/*
- * Need access to the driver and USB bus lists.
- * extern struct list_head usb_driver_list;
- * extern struct list_head usb_bus_list;
- * However, these will come from functions that return ptrs to each of them.
- */
-
-extern struct list_head *usb_driver_get_list (void);
-extern struct list_head *usb_bus_get_list (void);
-
-extern struct proc_dir_entry *proc_bus;
-
-static struct proc_dir_entry *usbdir = NULL, *driversdir = NULL;
-static struct proc_dir_entry *devicesdir = NULL;
-
-static DECLARE_WAIT_QUEUE_HEAD(deviceconndiscwq);
-static unsigned int conndiscevcnt = 0;
-
-/* this struct stores the poll state for /proc/bus/usb/devices pollers */
-struct usb_device_status {
- unsigned int lastev;
-};
-
-struct class_info {
- int class;
- char *class_name;
-};
-
-static const struct class_info clas_info[] =
-{ /* max. 5 chars. per name string */
- {USB_CLASS_PER_INTERFACE, ">ifc"},
- {USB_CLASS_AUDIO, "audio"},
- {USB_CLASS_COMM, "comm."},
- {USB_CLASS_HID, "HID"},
- {USB_CLASS_HUB, "hub"},
- {USB_CLASS_PRINTER, "print"},
- {USB_CLASS_MASS_STORAGE, "stor."},
- {USB_CLASS_DATA, "data"},
- {USB_CLASS_VENDOR_SPEC, "vend."},
- {-1, "unk."} /* leave as last */
-};
-
-/*****************************************************************/
-
-extern inline void conndiscevent(void)
-{
- wake_up(&deviceconndiscwq);
- conndiscevcnt++;
-}
-
-static const char *class_decode(const int class)
-{
- int ix;
-
- for (ix = 0; clas_info[ix].class != -1; ix++)
- if (clas_info[ix].class == class)
- break;
- return (clas_info[ix].class_name);
-}
-
-static char *usb_dump_endpoint_descriptor(char *start, char *end, const struct usb_endpoint_descriptor *desc)
-{
- char *EndpointType [4] = {"Ctrl", "Isoc", "Bulk", "Int."};
-
- if (start > end)
- return start;
- start += sprintf(start, format_endpt, desc->bEndpointAddress,
- (desc->bEndpointAddress & USB_DIR_IN) ? 'I' : 'O',
- desc->bmAttributes, EndpointType[desc->bmAttributes & 3],
- desc->wMaxPacketSize, desc->bInterval);
- return start;
-}
-
-static char *usb_dump_endpoint(char *start, char *end, const struct usb_endpoint_descriptor *endpoint)
-{
- return usb_dump_endpoint_descriptor(start, end, endpoint);
-}
-
-static char *usb_dump_interface_descriptor(char *start, char *end, const struct usb_interface *iface, int setno)
-{
- struct usb_interface_descriptor *desc = &iface->altsetting[setno];
-
- if (start > end)
- return start;
- start += sprintf(start, format_iface,
- desc->bInterfaceNumber,
- desc->bAlternateSetting,
- desc->bNumEndpoints,
- desc->bInterfaceClass,
- class_decode(desc->bInterfaceClass),
- desc->bInterfaceSubClass,
- desc->bInterfaceProtocol,
- iface->driver ? iface->driver->name : "(none)");
- return start;
-}
-
-static char *usb_dump_interface(char *start, char *end, const struct usb_interface *iface, int setno)
-{
- struct usb_interface_descriptor *desc = &iface->altsetting[setno];
- int i;
-
- start = usb_dump_interface_descriptor(start, end, iface, setno);
- for (i = 0; i < desc->bNumEndpoints; i++) {
- if (start > end)
- return start;
- start = usb_dump_endpoint(start, end, desc->endpoint + i);
- }
- return start;
-}
-
-/* TBD:
- * 0. TBDs
- * 1. marking active config and ifaces (code lists all, but should mark
- * which ones are active, if any)
- * 2. add <halted> status to each endpoint line
- */
-
-static char *usb_dump_config_descriptor(char *start, char *end, const struct usb_config_descriptor *desc, const int active)
-{
- if (start > end)
- return start;
- start += sprintf(start, format_config,
- active ? '*' : ' ', /* mark active/actual/current cfg. */
- desc->bNumInterfaces,
- desc->bConfigurationValue,
- desc->bmAttributes,
- desc->MaxPower * 2);
- return start;
-}
-
-static char *usb_dump_config(char *start, char *end, const struct usb_config_descriptor *config, const int active)
-{
- int i, j;
- struct usb_interface *interface;
-
- if (start > end)
- return start;
- if (!config) /* getting these some in 2.3.7; none in 2.3.6 */
- return start + sprintf(start, "(null Cfg. desc.)\n");
- start = usb_dump_config_descriptor(start, end, config, active);
- for (i = 0; i < config->bNumInterfaces; i++) {
- interface = config->interface + i;
- if (!interface)
- break;
- for (j = 0; j < interface->num_altsetting; j++) {
- if (start > end)
- return start;
- start = usb_dump_interface(start, end, interface, j);
- }
- }
- return start;
-}
-
-/*
- * Dump the different USB descriptors.
- */
-static char *usb_dump_device_descriptor(char *start, char *end, const struct usb_device_descriptor *desc)
-{
- if (start > end)
- return start;
- start += sprintf (start, format_device1,
- desc->bcdUSB >> 8, desc->bcdUSB & 0xff,
- desc->bDeviceClass,
- class_decode (desc->bDeviceClass),
- desc->bDeviceSubClass,
- desc->bDeviceProtocol,
- desc->bMaxPacketSize0,
- desc->bNumConfigurations);
- if (start > end)
- return start;
- start += sprintf(start, format_device2,
- desc->idVendor, desc->idProduct,
- desc->bcdDevice >> 8, desc->bcdDevice & 0xff);
- return start;
-}
-
-/*
- * Dump the different strings that this device holds.
- */
-static char *usb_dump_device_strings (char *start, char *end, const struct usb_device *dev)
-{
- if (start > end)
- return start;
-
- if (dev->descriptor.iManufacturer) {
- char * string = usb_string ((struct usb_device *)dev,
- dev->descriptor.iManufacturer);
- if (string) {
- start += sprintf (start, format_string_manufacturer,
- string
- );
- if (start > end)
- return start;
-
- }
- }
-
- if (dev->descriptor.iProduct) {
- char * string = usb_string ((struct usb_device *)dev,
- dev->descriptor.iProduct);
- if (string) {
- start += sprintf (start, format_string_product,
- string
- );
- if (start > end)
- return start;
-
- }
- }
-
-#ifdef ALLOW_SERIAL_NUMBER
- if (dev->descriptor.iSerialNumber) {
- char * string = usb_string ((struct usb_device *)dev,
- dev->descriptor.iSerialNumber);
- if (string) {
- start += sprintf (start, format_string_serialnumber,
- string
- );
- }
- }
-#endif
-
- return start;
-}
-
-static char *usb_dump_desc(char *start, char *end, const struct usb_device *dev)
-{
- int i;
-
- if (start > end)
- return start;
-
- start = usb_dump_device_descriptor(start, end, &dev->descriptor);
-
- if (start > end)
- return start;
-
- start = usb_dump_device_strings (start, end, dev);
-
- for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
- if (start > end)
- return start;
- start = usb_dump_config(start, end, dev->config + i,
- (dev->config + i) == dev->actconfig); /* active ? */
- }
- return start;
-}
-
-
-#ifdef PROC_EXTRA /* TBD: may want to add this code later */
-
-static char *usb_dump_hub_descriptor(char *start, char *end, const struct usb_hub_descriptor * desc)
-{
- int leng = USB_DT_HUB_NONVAR_SIZE;
- unsigned char *ptr = (unsigned char *)desc;
-
- if (start > end)
- return start;
- start += sprintf(start, "Interface:");
- while (leng) {
- start += sprintf(start, " %02x", *ptr);
- ptr++; leng--;
- }
- start += sprintf(start, "\n");
- return start;
-}
-
-#endif /* PROC_EXTRA */
-
-/*****************************************************************/
-
-static char *usb_device_dump(char *start, char *end, const struct usb_device *usbdev,
- const struct usb_bus *bus, int level, int index, int count)
-{
- int chix;
- int cnt = 0;
- int parent_devnum = 0;
-
- if (level > MAX_TOPO_LEVEL)
- return start;
- if (usbdev->parent && usbdev->parent->devnum != -1)
- parent_devnum = usbdev->parent->devnum;
- /*
- * So the root hub's parent is 0 and any device that is
- * plugged into the root hub has a parent of 0.
- */
- start += sprintf(start, format_topo, bus->busnum-1, level, parent_devnum, index, count,
- usbdev->devnum, usbdev->slow ? "1.5" : "12 ", usbdev->maxchild);
- /*
- * level = topology-tier level;
- * parent_devnum = parent device number;
- * index = parent's connector number;
- * count = device count at this level
- */
- /* If this is the root hub, display the bandwidth information */
- if (level == 0)
- start += sprintf(start, format_bandwidth, bus->bandwidth_allocated,
- FRAME_TIME_MAX_USECS_ALLOC,
- (100 * bus->bandwidth_allocated + FRAME_TIME_MAX_USECS_ALLOC / 2) / FRAME_TIME_MAX_USECS_ALLOC,
- bus->bandwidth_int_reqs, bus->bandwidth_isoc_reqs);
-
- /* show the descriptor information for this device */
- start = usb_dump_desc(start, end, usbdev);
- if (start > end)
- return start + sprintf(start, "(truncated)\n");
-
- /* Now look at all of this device's children. */
- for (chix = 0; chix < usbdev->maxchild; chix++) {
- if (start > end)
- return start;
- if (usbdev->children[chix])
- start = usb_device_dump(start, end, usbdev->children[chix], bus, level + 1, chix, ++cnt);
- }
- return start;
-}
-
-static ssize_t usb_device_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
-{
- struct list_head *usb_bus_list, *buslist;
- struct usb_bus *bus;
- char *page, *end;
- ssize_t ret = 0;
- unsigned int pos, len;
-
- if (*ppos < 0)
- return -EINVAL;
- if (nbytes <= 0)
- return 0;
- if (!access_ok(VERIFY_WRITE, buf, nbytes))
- return -EFAULT;
- if (!(page = (char*) __get_free_page(GFP_KERNEL)))
- return -ENOMEM;
- pos = *ppos;
- usb_bus_list = usb_bus_get_list();
- /* enumerate busses */
- for (buslist = usb_bus_list->next; buslist != usb_bus_list; buslist = buslist->next) {
- bus = list_entry(buslist, struct usb_bus, bus_list);
- end = usb_device_dump(page, page + (PAGE_SIZE - 100), bus->root_hub, bus, 0, 0, 0);
- len = end - page;
- if (len > pos) {
- len -= pos;
- if (len > nbytes)
- len = nbytes;
- if (copy_to_user(buf, page + pos, len)) {
- if (!ret)
- ret = -EFAULT;
- break;
- }
- nbytes -= len;
- buf += len;
- ret += len;
- pos = 0;
- *ppos += len;
- } else
- pos -= len;
- }
- free_page((unsigned long)page);
- return ret;
-}
-
-static unsigned int usb_device_poll(struct file *file, struct poll_table_struct *wait)
-{
- struct usb_device_status *st = (struct usb_device_status *)file->private_data;
- unsigned int mask = 0;
-
- if (!st) {
- st = kmalloc(sizeof(struct usb_device_status), GFP_KERNEL);
- if (!st)
- return POLLIN;
- /*
- * need to prevent the module from being unloaded, since
- * proc_unregister does not call the release method and
- * we would have a memory leak
- */
- st->lastev = conndiscevcnt;
- file->private_data = st;
- MOD_INC_USE_COUNT;
- mask = POLLIN;
- }
- if (file->f_mode & FMODE_READ)
- poll_wait(file, &deviceconndiscwq, wait);
- if (st->lastev != conndiscevcnt)
- mask |= POLLIN;
- st->lastev = conndiscevcnt;
- return mask;
-}
-
-static int usb_device_open(struct inode *inode, struct file *file)
-{
- file->private_data = NULL;
- MOD_INC_USE_COUNT;
- return 0;
-}
-
-static int usb_device_release(struct inode *inode, struct file *file)
-{
- if (file->private_data) {
- kfree(file->private_data);
- file->private_data = NULL;
- }
- MOD_DEC_USE_COUNT;
- return 0;
-}
-
-/*
- * Dump usb_driver_list.
- *
- * We now walk the list of registered USB drivers.
- */
-static ssize_t usb_driver_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
-{
- struct list_head *usb_driver_list = usb_driver_get_list();
- struct list_head *tmp = usb_driver_list->next;
- char *page, *start, *end;
- ssize_t ret = 0;
- unsigned int pos, len;
-
- if (*ppos < 0)
- return -EINVAL;
- if (nbytes <= 0)
- return 0;
- if (!access_ok(VERIFY_WRITE, buf, nbytes))
- return -EFAULT;
- if (!(page = (char*) __get_free_page(GFP_KERNEL)))
- return -ENOMEM;
- start = page;
- end = page + (PAGE_SIZE - 100);
- pos = *ppos;
- for (; tmp != usb_driver_list; tmp = tmp->next) {
- struct usb_driver *driver = list_entry(tmp, struct usb_driver, driver_list);
- start += sprintf (start, "%s\n", driver->name);
- if (start > end) {
- start += sprintf(start, "(truncated)\n");
- break;
- }
- }
- if (start == page)
- start += sprintf(start, "(none)\n");
- len = start - page;
- if (len > pos) {
- len -= pos;
- if (len > nbytes)
- len = nbytes;
- ret = len;
- if (copy_to_user(buf, page + pos, len))
- ret = -EFAULT;
- else
- *ppos += len;
- }
- free_page((unsigned long)page);
- return ret;
-}
-
-static long long usbdev_lseek(struct file * file, long long offset, int orig);
-
-static struct file_operations proc_usb_devlist_file_operations = {
- usbdev_lseek, /* lseek */
- usb_device_read, /* read */
- NULL, /* write */
- NULL, /* readdir */
- usb_device_poll, /* poll */
- NULL, /* ioctl */
- NULL, /* mmap */
- usb_device_open, /* open */
- NULL, /* flush */
- usb_device_release, /* release */
- NULL /* fsync */
-};
-
-static struct inode_operations proc_usb_devlist_inode_operations = {
- &proc_usb_devlist_file_operations, /* file-ops */
-};
-
-static struct file_operations proc_usb_drvlist_file_operations = {
- usbdev_lseek, /* lseek */
- usb_driver_read, /* read */
- NULL, /* write */
- NULL, /* readdir */
- NULL, /* poll */
- NULL, /* ioctl */
- NULL, /* mmap */
- NULL, /* no special open code */
- NULL, /* flush */
- NULL, /* no special release code */
- NULL /* can't fsync */
-};
-
-static struct inode_operations proc_usb_drvlist_inode_operations = {
- &proc_usb_drvlist_file_operations, /* file-ops */
-};
-
-
-/*
- * proc entry for every device
- */
-
-static long long usbdev_lseek(struct file * file, long long offset, int orig)
-{
- switch (orig) {
- case 0:
- file->f_pos = offset;
- return file->f_pos;
-
- case 1:
- file->f_pos += offset;
- return file->f_pos;
-
- case 2:
- return -EINVAL;
-
- default:
- return -EINVAL;
- }
-}
-
-static ssize_t usbdev_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos)
-{
- struct inode *inode = file->f_dentry->d_inode;
- struct proc_dir_entry *dp = (struct proc_dir_entry *)inode->u.generic_ip;
- struct usb_device *dev = (struct usb_device *)dp->data;
- ssize_t ret = 0;
- unsigned len;
-
- if (*ppos < 0)
- return -EINVAL;
- if (*ppos < sizeof(struct usb_device_descriptor)) {
- len = sizeof(struct usb_device_descriptor);
- if (len > nbytes)
- len = nbytes;
- copy_to_user_ret(buf, ((char *)&dev->descriptor) + *ppos, len, -EFAULT);
- *ppos += len;
- buf += len;
- nbytes -= len;
- ret += len;
- }
- return ret;
-}
-
-/* note: this is a compatibility kludge that will vanish soon. */
-#include "ezusb.h"
-
-static int usbdev_ioctl_ezusbcompat(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
- static unsigned obsolete_warn = 0;
- struct proc_dir_entry *dp = (struct proc_dir_entry *)inode->u.generic_ip;
- struct usb_device *dev = (struct usb_device *)dp->data;
- struct ezusb_ctrltransfer ctrl;
- struct ezusb_bulktransfer bulk;
- struct ezusb_old_ctrltransfer octrl;
- struct ezusb_old_bulktransfer obulk;
- struct ezusb_setinterface setintf;
- unsigned int len1, ep, pipe, cfg;
- unsigned long len2;
- unsigned char *tbuf;
- int i;
-
- switch (cmd) {
- case EZUSB_CONTROL:
- if (obsolete_warn < 20) {
- warn("process %d (%s) used obsolete EZUSB_CONTROL ioctl",
- current->pid, current->comm);
- obsolete_warn++;
- }
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
- copy_from_user_ret(&ctrl, (void *)arg, sizeof(ctrl), -EFAULT);
- if (ctrl.length > PAGE_SIZE)
- return -EINVAL;
- if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
- return -ENOMEM;
- if (ctrl.requesttype & 0x80) {
- if (ctrl.length && !access_ok(VERIFY_WRITE, ctrl.data, ctrl.length)) {
- free_page((unsigned long)tbuf);
- return -EINVAL;
- }
- i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.request, ctrl.requesttype,
- ctrl.value, ctrl.index, tbuf, ctrl.length,
- (ctrl.timeout * HZ + 500) / 1000);
- if ((i > 0) && ctrl.length) {
- copy_to_user_ret(ctrl.data, tbuf, ctrl.length, -EFAULT);
- }
- } else {
- if (ctrl.length) {
- copy_from_user_ret(tbuf, ctrl.data, ctrl.length, -EFAULT);
- }
- i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.request, ctrl.requesttype,
- ctrl.value, ctrl.index, tbuf, ctrl.length,
- (ctrl.timeout * HZ + 500) / 1000);
- }
- free_page((unsigned long)tbuf);
- if (i < 0) {
- warn("EZUSB_CONTROL failed rqt %u rq %u len %u ret %d",
- ctrl.requesttype, ctrl.request, ctrl.length, i);
- return i;
- }
- return i;
-
- case EZUSB_BULK:
- if (obsolete_warn < 20) {
- warn("process %d (%s) used obsolete EZUSB_BULK ioctl",
- current->pid, current->comm);
- obsolete_warn++;
- }
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
- copy_from_user_ret(&bulk, (void *)arg, sizeof(bulk), -EFAULT);
- if (bulk.ep & 0x80)
- pipe = usb_rcvbulkpipe(dev, bulk.ep & 0x7f);
- else
- pipe = usb_sndbulkpipe(dev, bulk.ep & 0x7f);
- if (!usb_maxpacket(dev, pipe, !(bulk.ep & 0x80)))
- return -EINVAL;
- len1 = bulk.len;
- if (len1 > PAGE_SIZE)
- len1 = PAGE_SIZE;
- if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
- return -ENOMEM;
- if (bulk.ep & 0x80) {
- if (len1 && !access_ok(VERIFY_WRITE, bulk.data, len1)) {
- free_page((unsigned long)tbuf);
- return -EINVAL;
- }
- i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, (ctrl.timeout * HZ + 500) / 1000);
- if ((i > 0) && len2) {
- copy_to_user_ret(bulk.data, tbuf, len2, -EFAULT);
- }
- } else {
- if (len1) {
- copy_from_user_ret(tbuf, bulk.data, len1, -EFAULT);
- }
- i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, (ctrl.timeout * HZ + 500) / 1000);
- }
- free_page((unsigned long)tbuf);
- if (i < 0) {
- warn("EZUSB_BULK failed ep 0x%x len %u ret %d",
- bulk.ep, bulk.len, i);
- return i;
- }
- return len2;
-
- case EZUSB_OLD_CONTROL:
- if (obsolete_warn < 20) {
- warn("process %d (%s) used obsolete EZUSB_OLD_CONTROL ioctl",
- current->pid, current->comm);
- obsolete_warn++;
- }
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
- copy_from_user_ret(&octrl, (void *)arg, sizeof(octrl), -EFAULT);
- if (octrl.dlen > PAGE_SIZE)
- return -EINVAL;
- if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
- return -ENOMEM;
- if (octrl.requesttype & 0x80) {
- if (octrl.dlen && !access_ok(VERIFY_WRITE, octrl.data, octrl.dlen)) {
- free_page((unsigned long)tbuf);
- return -EINVAL;
- }
- i = usb_internal_control_msg(dev, usb_rcvctrlpipe(dev, 0), (devrequest *)&octrl, tbuf, octrl.dlen, HZ);
- if ((i > 0) && octrl.dlen) {
- copy_to_user_ret(octrl.data, tbuf, octrl.dlen, -EFAULT);
- }
- } else {
- if (octrl.dlen) {
- copy_from_user_ret(tbuf, octrl.data, octrl.dlen, -EFAULT);
- }
- i = usb_internal_control_msg(dev, usb_sndctrlpipe(dev, 0), (devrequest *)&octrl, tbuf, octrl.dlen, HZ);
- }
- free_page((unsigned long)tbuf);
- if (i < 0) {
- warn("EZUSB_OLD_CONTROL failed rqt %u rq %u len %u ret %d",
- octrl.requesttype, octrl.request, octrl.length, i);
- return i;
- }
- return i;
-
- case EZUSB_OLD_BULK:
- if (obsolete_warn < 20) {
- warn("process %d (%s) used obsolete EZUSB_OLD_BULK ioctl",
- current->pid, current->comm);
- obsolete_warn++;
- }
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
- copy_from_user_ret(&obulk, (void *)arg, sizeof(obulk), -EFAULT);
- if (obulk.ep & 0x80)
- pipe = usb_rcvbulkpipe(dev, obulk.ep & 0x7f);
- else
- pipe = usb_sndbulkpipe(dev, obulk.ep & 0x7f);
- if (!usb_maxpacket(dev, pipe, !(obulk.ep & 0x80)))
- return -EINVAL;
- len1 = obulk.len;
- if (len1 > PAGE_SIZE)
- len1 = PAGE_SIZE;
- if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
- return -ENOMEM;
- if (obulk.ep & 0x80) {
- if (len1 && !access_ok(VERIFY_WRITE, obulk.data, len1)) {
- free_page((unsigned long)tbuf);
- return -EINVAL;
- }
- i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, HZ*5);
- if ((i > 0) && len2) {
- copy_to_user_ret(obulk.data, tbuf, len2, -EFAULT);
- }
- } else {
- if (len1) {
- copy_from_user_ret(tbuf, obulk.data, len1, -EFAULT);
- }
- i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, HZ*5);
- }
- free_page((unsigned long)tbuf);
- if (i < 0) {
- warn("EZUSB_OLD_BULK failed ep 0x%x len %u ret %d",
- obulk.ep, obulk.len, i);
- return i;
- }
- return len2;
-
- case EZUSB_RESETEP:
- if (obsolete_warn < 20) {
- warn("process %d (%s) used obsolete EZUSB_RESETEP ioctl",
- current->pid, current->comm);
- obsolete_warn++;
- }
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
- get_user_ret(ep, (unsigned int *)arg, -EFAULT);
- if ((ep & ~0x80) >= 16)
- return -EINVAL;
- usb_settoggle(dev, ep & 0xf, !(ep & 0x80), 0);
- return 0;
-
- case EZUSB_SETINTERFACE:
- if (obsolete_warn < 20) {
- warn("process %d (%s) used obsolete EZUSB_SETINTERFACE ioctl",
- current->pid, current->comm);
- obsolete_warn++;
- }
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
- copy_from_user_ret(&setintf, (void *)arg, sizeof(setintf), -EFAULT);
- if (usb_set_interface(dev, setintf.interface, setintf.altsetting))
- return -EINVAL;
- return 0;
-
- case EZUSB_SETCONFIGURATION:
- if (obsolete_warn < 20) {
- warn("process %d (%s) used obsolete EZUSB_SETCONFIGURATION ioctl",
- current->pid, current->comm);
- obsolete_warn++;
- }
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
- get_user_ret(cfg, (unsigned int *)arg, -EFAULT);
- if (usb_set_configuration(dev, cfg) < 0)
- return -EINVAL;
- return 0;
-
- }
- return -ENOIOCTLCMD;
-}
-
-
-
-static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
- struct proc_dir_entry *dp = (struct proc_dir_entry *)inode->u.generic_ip;
- struct usb_device *dev = (struct usb_device *)dp->data;
- struct usb_proc_ctrltransfer ctrl;
- struct usb_proc_bulktransfer bulk;
- struct usb_proc_old_ctrltransfer octrl;
- struct usb_proc_old_bulktransfer obulk;
- struct usb_proc_setinterface setintf;
- unsigned int len1, ep, pipe, cfg;
- unsigned long len2;
- unsigned char *tbuf;
- int i;
-
- switch (cmd) {
- case USB_PROC_CONTROL:
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
- copy_from_user_ret(&ctrl, (void *)arg, sizeof(ctrl), -EFAULT);
- if (ctrl.length > PAGE_SIZE)
- return -EINVAL;
- if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
- return -ENOMEM;
- if (ctrl.requesttype & 0x80) {
- if (ctrl.length && !access_ok(VERIFY_WRITE, ctrl.data, ctrl.length)) {
- free_page((unsigned long)tbuf);
- return -EINVAL;
- }
- i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.request,
- ctrl.requesttype, ctrl.value, ctrl.index, tbuf,
- ctrl.length, (ctrl.timeout * HZ + 500) / 1000);
- if ((i > 0) && ctrl.length) {
- copy_to_user_ret(ctrl.data, tbuf, ctrl.length, -EFAULT);
- }
- } else {
- if (ctrl.length) {
- copy_from_user_ret(tbuf, ctrl.data, ctrl.length, -EFAULT);
- }
- i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.request,
- ctrl.requesttype, ctrl.value, ctrl.index, tbuf,
- ctrl.length, (ctrl.timeout * HZ + 500) / 1000);
- }
- free_page((unsigned long)tbuf);
- if (i<0) {
- warn("USB_PROC_CONTROL failed rqt %u rq %u len %u ret %d",
- ctrl.requesttype, ctrl.request, ctrl.length, i);
- return i;
- }
- return 0;
-
- case USB_PROC_BULK:
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
- copy_from_user_ret(&bulk, (void *)arg, sizeof(bulk), -EFAULT);
- if (bulk.ep & 0x80)
- pipe = usb_rcvbulkpipe(dev, bulk.ep & 0x7f);
- else
- pipe = usb_sndbulkpipe(dev, bulk.ep & 0x7f);
- if (!usb_maxpacket(dev, pipe, !(bulk.ep & 0x80)))
- return -EINVAL;
- len1 = bulk.len;
- if (len1 > PAGE_SIZE)
- len1 = PAGE_SIZE;
- if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
- return -ENOMEM;
- if (bulk.ep & 0x80) {
- if (len1 && !access_ok(VERIFY_WRITE, bulk.data, len1)) {
- free_page((unsigned long)tbuf);
- return -EINVAL;
- }
- i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, (bulk.timeout * HZ + 500) / 1000);
- if (!i && len2) {
- copy_to_user_ret(bulk.data, tbuf, len2, -EFAULT);
- }
- } else {
- if (len1) {
- copy_from_user_ret(tbuf, bulk.data, len1, -EFAULT);
- }
- i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, (bulk.timeout * HZ + 500) / 1000);
- }
- free_page((unsigned long)tbuf);
- if (i) {
- warn("USB_PROC_BULK failed ep 0x%x len %u ret %d",
- bulk.ep, bulk.len, i);
- return -ENXIO;
- }
- return len2;
-
- case USB_PROC_OLD_CONTROL:
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
- copy_from_user_ret(&octrl, (void *)arg, sizeof(octrl), -EFAULT);
- if (octrl.length > PAGE_SIZE)
- return -EINVAL;
- if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
- return -ENOMEM;
- if (octrl.requesttype & 0x80) {
- if (octrl.length && !access_ok(VERIFY_WRITE, octrl.data, octrl.length)) {
- free_page((unsigned long)tbuf);
- return -EINVAL;
- }
- i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), octrl.request,
- octrl.requesttype, octrl.value, octrl.index, tbuf,
- octrl.length, HZ);
- if ((i > 0) && octrl.length) {
- copy_to_user_ret(octrl.data, tbuf, octrl.length, -EFAULT);
- }
- } else {
- if (octrl.length) {
- copy_from_user_ret(tbuf, octrl.data, octrl.length, -EFAULT);
- }
- i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), octrl.request,
- octrl.requesttype, octrl.value, octrl.index, tbuf,
- octrl.length, HZ);
- }
- free_page((unsigned long)tbuf);
- if (i < 0) {
- warn("USB_PROC_OLD_CONTROL failed rqt %u rq %u len %u ret %d",
- octrl.requesttype, octrl.request, octrl.length, i);
- return i;
- }
- return 0;
-
- case USB_PROC_OLD_BULK:
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
- copy_from_user_ret(&obulk, (void *)arg, sizeof(obulk), -EFAULT);
- if (obulk.ep & 0x80)
- pipe = usb_rcvbulkpipe(dev, obulk.ep & 0x7f);
- else
- pipe = usb_sndbulkpipe(dev, obulk.ep & 0x7f);
- if (!usb_maxpacket(dev, pipe, !(obulk.ep & 0x80)))
- return -EINVAL;
- len1 = obulk.len;
- if (len1 > PAGE_SIZE)
- len1 = PAGE_SIZE;
- if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
- return -ENOMEM;
- if (obulk.ep & 0x80) {
- if (len1 && !access_ok(VERIFY_WRITE, obulk.data, len1)) {
- free_page((unsigned long)tbuf);
- return -EINVAL;
- }
- i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, HZ*5);
- if ((i > 0) && len2) {
- copy_to_user_ret(obulk.data, tbuf, len2, -EFAULT);
- }
- } else {
- if (len1) {
- copy_from_user_ret(tbuf, obulk.data, len1, -EFAULT);
- }
- i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, HZ*5);
- }
- free_page((unsigned long)tbuf);
- if (i < 0) {
- warn("USB_PROC_OLD_BULK failed ep 0x%x len %u ret %d",
- obulk.ep, obulk.len, i);
- return i;
- }
- return len2;
-
- case USB_PROC_RESETEP:
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
- get_user_ret(ep, (unsigned int *)arg, -EFAULT);
- if ((ep & ~0x80) >= 16)
- return -EINVAL;
- usb_settoggle(dev, ep & 0xf, !(ep & 0x80), 0);
- return 0;
-
- case USB_PROC_SETINTERFACE:
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
- copy_from_user_ret(&setintf, (void *)arg, sizeof(setintf), -EFAULT);
- if (usb_set_interface(dev, setintf.interface, setintf.altsetting))
- return -EINVAL;
- return 0;
-
- case USB_PROC_SETCONFIGURATION:
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
- get_user_ret(cfg, (unsigned int *)arg, -EFAULT);
- if (usb_set_configuration(dev, cfg) < 0)
- return -EINVAL;
- return 0;
-
- case EZUSB_CONTROL:
- case EZUSB_BULK:
- case EZUSB_OLD_CONTROL:
- case EZUSB_OLD_BULK:
- case EZUSB_RESETEP:
- case EZUSB_SETINTERFACE:
- case EZUSB_SETCONFIGURATION:
- return usbdev_ioctl_ezusbcompat(inode, file, cmd, arg);
- }
- return -ENOIOCTLCMD;
-}
-
-static struct file_operations proc_usb_device_file_operations = {
- usbdev_lseek, /* lseek */
- usbdev_read, /* read */
- NULL, /* write */
- NULL, /* readdir */
- NULL, /* poll */
- usbdev_ioctl, /* ioctl */
- NULL, /* mmap */
- NULL, /* no special open code */
- NULL, /* flush */
- NULL, /* no special release code */
- NULL /* can't fsync */
-};
-
-static struct inode_operations proc_usb_device_inode_operations = {
- &proc_usb_device_file_operations, /* file-ops */
-};
-
-void proc_usb_add_bus(struct usb_bus *bus)
-{
- char buf[16];
-
- bus->proc_entry = NULL;
- if (!usbdir)
- return;
- sprintf(buf, "%03d", bus->busnum);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,31)
- if (!(bus->proc_entry = create_proc_entry(buf, S_IFDIR, usbdir)))
-#else
- if (!(bus->proc_entry = proc_mkdir(buf, usbdir)))
-#endif
- return;
- bus->proc_entry->data = bus;
- conndiscevent();
-}
-
-/* devices need already be removed! */
-void proc_usb_remove_bus(struct usb_bus *bus)
-{
- if (!bus->proc_entry)
- return;
- remove_proc_entry(bus->proc_entry->name, usbdir);
- conndiscevent();
-}
-
-void proc_usb_add_device(struct usb_device *dev)
-{
- char buf[16];
-
- dev->proc_entry = NULL;
- if (!dev->bus->proc_entry)
- return;
- sprintf(buf, "%03d", dev->devnum);
- if (!(dev->proc_entry = create_proc_entry(buf, 0, dev->bus->proc_entry)))
- return;
- dev->proc_entry->ops = &proc_usb_device_inode_operations;
- dev->proc_entry->data = dev;
- conndiscevent();
-}
-
-void proc_usb_remove_device(struct usb_device *dev)
-{
- if (dev->proc_entry)
- remove_proc_entry(dev->proc_entry->name, dev->bus->proc_entry);
- conndiscevent();
-}
-
-
-void proc_usb_cleanup (void)
-{
- if (driversdir)
- remove_proc_entry("drivers", usbdir);
- if (devicesdir)
- remove_proc_entry("devices", usbdir);
- if (usbdir)
- remove_proc_entry("usb", proc_bus);
-}
-
-int proc_usb_init (void)
-{
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,31)
- usbdir = create_proc_entry("usb", S_IFDIR, proc_bus);
-#else
- usbdir = proc_mkdir("usb", proc_bus);
-#endif
- if (!usbdir) {
- err("cannot create /proc/bus/usb entry");
- return -1;
- }
-
- driversdir = create_proc_entry("drivers", 0, usbdir);
- if (!driversdir) {
- err("cannot create /proc/bus/usb/drivers entry");
- proc_usb_cleanup();
- return -1;
- }
- driversdir->ops = &proc_usb_drvlist_inode_operations;
-
- devicesdir = create_proc_entry("devices", 0, usbdir);
- if (!devicesdir) {
- err("cannot create /proc/bus/usb/devices entry");
- proc_usb_cleanup ();
- return -1;
- }
- devicesdir->ops = &proc_usb_devlist_inode_operations;
-
- return 0;
-}
-
-/* end proc_usb.c */
diff --git a/drivers/usb/scanner.c b/drivers/usb/scanner.c
index 806e15ab3..97399bc2d 100644
--- a/drivers/usb/scanner.c
+++ b/drivers/usb/scanner.c
@@ -125,7 +125,7 @@ static struct hpscan_usb_data hpscan;
MODULE_AUTHOR("David E. Nelson, dnelson@jump.net, http://www.jump.net/~dnelson");
MODULE_DESCRIPTION("USB Scanner Driver");
-static __u16 vendor=0, product=0;
+static __u16 vendor=0x05f9, product=0xffff;
MODULE_PARM(vendor, "i");
MODULE_PARM_DESC(vendor, "User specified USB idVendor");
@@ -410,9 +410,12 @@ probe_scanner(struct usb_device *dev, unsigned int ifnum)
hps->oep = endpoint[1].bEndpointAddress;
}
- ident = usb_string(dev, dev->descriptor.iProduct); /* usb_string allocates memory using kmalloc() so kfree() needs to be called afterwards when the pointer is no longer needed. */
- info("USB Scanner (%s) found at address %d", ident, dev->devnum);
- kfree(ident);
+ ident = kmalloc(256, GFP_KERNEL);
+ if (ident) {
+ usb_string(dev, dev->descriptor.iProduct, ident, 256);
+ info("USB Scanner (%s) found at address %d", ident, dev->devnum);
+ kfree(ident);
+ }
dbg("probe_scanner: using bulk endpoints - In: %x Out: %x", hps->iep, hps->oep);
diff --git a/drivers/usb/usb-core.c b/drivers/usb/usb-core.c
index 2302d42a7..f0b30bf93 100644
--- a/drivers/usb/usb-core.c
+++ b/drivers/usb/usb-core.c
@@ -24,8 +24,6 @@ int usb_hub_init(void);
void usb_hub_cleanup(void);
int usb_major_init(void);
void usb_major_cleanup(void);
-int proc_usb_init(void);
-void proc_usb_cleanup(void);
/*
* USB device drivers
@@ -38,13 +36,14 @@ int usb_ov511_init(void);
int usb_dc2xx_init(void);
int usb_scanner_init(void);
int usb_printer_init(void);
-int usb_scsi_init(void);
+int usb_stor_init(void);
int usb_serial_init(void);
int dabusb_init(void);
int hid_init(void);
int input_init(void);
int usb_mouse_init(void);
int usb_kbd_init(void);
+int graphire_init(void);
/*
* HCI drivers
@@ -62,10 +61,8 @@ int ohci_hcd_init(void);
void cleanup_module(void)
{
usb_major_cleanup();
-#ifdef CONFIG_USB_PROC
- proc_usb_cleanup ();
-#endif
- usb_hub_cleanup();
+ usbdevfs_cleanup();
+ usb_hub_cleanup();
}
@@ -79,9 +76,7 @@ int usb_init(void)
#endif
{
usb_major_init();
-#ifdef CONFIG_USB_PROC
- proc_usb_init();
-#endif
+ usbdevfs_init();
usb_hub_init();
#ifndef CONFIG_USB_MODULE
@@ -110,12 +105,12 @@ int usb_init(void)
usb_dc2xx_init();
#endif
#ifdef CONFIG_USB_SCSI
- usb_scsi_init();
+ usb_stor_init();
#endif
#ifdef CONFIG_USB_DABUSB
dabusb_init();
#endif
-#if defined(CONFIG_USB_HID) || defined(CONFIG_USB_MOUSE) || defined(CONFIG_USB_KBD)
+#if defined(CONFIG_USB_HID) || defined(CONFIG_USB_MOUSE) || defined(CONFIG_USB_KBD) || defined(CONFIG_USB_GRAPHIRE)
input_init();
#endif
#ifdef CONFIG_USB_HID
@@ -127,6 +122,9 @@ int usb_init(void)
#ifdef CONFIG_USB_KBD
usb_kbd_init();
#endif
+#ifdef CONFIG_USB_GRAPHIRE
+ graphire_init();
+#endif
#ifdef CONFIG_USB_UHCI
uhci_init();
#endif
diff --git a/drivers/usb/usb-debug.c b/drivers/usb/usb-debug.c
index b321fdff3..2cca35151 100644
--- a/drivers/usb/usb-debug.c
+++ b/drivers/usb/usb-debug.c
@@ -6,6 +6,7 @@
*/
#include <linux/version.h>
#include <linux/kernel.h>
+#include <linux/slab.h>
#define DEBUG
@@ -131,24 +132,6 @@ void usb_show_interface_descriptor(struct usb_interface_descriptor *desc)
printk(" iInterface = %02x\n", desc->iInterface);
}
-void usb_show_hid_descriptor(struct usb_hid_descriptor * desc)
-{
- int i;
-
- printk(" HID:\n");
- printk(" HID version %x.%02x\n", desc->bcdHID >> 8, desc->bcdHID & 0xff);
- printk(" bLength = %4d\n", desc->bLength);
- printk(" bDescriptorType = %02x\n", desc->bDescriptorType);
- printk(" bCountryCode = %02x\n", desc->bCountryCode);
- printk(" bNumDescriptors = %02x\n", desc->bNumDescriptors);
-
- for (i=0; i<desc->bNumDescriptors; i++) {
- printk(" %d:\n", i);
- printk(" bDescriptorType = %02x\n", desc->desc[i].bDescriptorType);
- printk(" wDescriptorLength = %04x\n", desc->desc[i].wDescriptorLength);
- }
-}
-
void usb_show_endpoint_descriptor(struct usb_endpoint_descriptor *desc)
{
char *LengthCommentString = (desc->bLength ==
@@ -175,9 +158,12 @@ void usb_show_endpoint_descriptor(struct usb_endpoint_descriptor *desc)
void usb_show_string(struct usb_device *dev, char *id, int index)
{
- char *p = usb_string(dev, index);
+ char *buf;
- if (p != 0)
- printk(KERN_INFO "%s: %s\n", id, p);
+ if (!(buf = kmalloc(256, GFP_KERNEL)))
+ return;
+ if (usb_string(dev, index, buf, 256) > 0)
+ printk(KERN_INFO "%s: %s\n", id, buf);
+ kfree(buf);
}
diff --git a/drivers/usb/usb-serial.c b/drivers/usb/usb-serial.c
index 0cb3bdcba..8826bc522 100644
--- a/drivers/usb/usb-serial.c
+++ b/drivers/usb/usb-serial.c
@@ -1,7 +1,7 @@
/*
* USB Serial Converter driver
*
- * (C) Copyright (C) 1999
+ * (C) Copyright (C) 1999, 2000
* Greg Kroah-Hartman (greg@kroah.com)
*
* This program is free software; you can redistribute it and/or modify
@@ -12,8 +12,42 @@
* This driver was originally based on the ACM driver by Armin Fuerst (which was
* based on a driver by Brad Keryan)
*
- * See README.serial for more information on using this driver.
+ * See Documentation/usb/usb-serial.txt for more information on using this driver
*
+ * (01/19/2000) gkh
+ * Removed lots of cruft that was around from the old (pre urb) driver
+ * interface.
+ * Made the serial_table dynamic. This should save lots of memory when
+ * the number of minor nodes goes up to 256.
+ * Added initial support for devices that have more than one port.
+ * Added more debugging comments for the Visor, and added a needed
+ * set_configuration call.
+ *
+ * (01/17/2000) gkh
+ * Fixed the WhiteHEAT firmware (my processing tool had a bug)
+ * and added new debug loader firmware for it.
+ * Removed the put_char function as it isn't really needed.
+ * Added visor startup commands as found by the Win98 dump.
+ *
+ * (01/13/2000) gkh
+ * Fixed the vendor id for the generic driver to the one I meant it to be.
+ *
+ * (01/12/2000) gkh
+ * Forget the version numbering...that's pretty useless...
+ * Made the driver able to be compiled so that the user can select which
+ * converter they want to use. This allows people who only want the Visor
+ * support to not pay the memory size price of the WhiteHEAT.
+ * Fixed bug where the generic driver (idVendor=0000 and idProduct=0000)
+ * grabbed the root hub. Not good.
+ *
+ * version 0.4.0 (01/10/2000) gkh
+ * Added whiteheat.h containing the firmware for the ConnectTech WhiteHEAT
+ * device. Added startup function to allow firmware to be downloaded to
+ * a device if it needs to be.
+ * Added firmware download logic to the WhiteHEAT device.
+ * Started to add #defines to split up the different drivers for potential
+ * configuration option.
+ *
* version 0.3.1 (12/30/99) gkh
* Fixed problems with urb for bulk out.
* Added initial support for multiple sets of endpoints. This enables
@@ -63,6 +97,7 @@
*
*/
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/signal.h>
@@ -77,21 +112,31 @@
#include <linux/module.h>
#include <linux/spinlock.h>
-#undef DEBUG
+#define DEBUG
#include "usb.h"
+#ifdef CONFIG_USB_SERIAL_WHITEHEAT
+#include "whiteheat.h" /* firmware for the ConnectTech WhiteHEAT device */
+#endif
+
/* Module information */
MODULE_AUTHOR("Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux-usb/");
MODULE_DESCRIPTION("USB Serial Driver");
-static __u16 vendor = 0;
-static __u16 product = 0;
+#ifdef CONFIG_USB_SERIAL_GENERIC
+static __u16 vendor = 0x05f9;
+static __u16 product = 0xffff;
MODULE_PARM(vendor, "i");
MODULE_PARM_DESC(vendor, "User specified USB idVendor");
MODULE_PARM(product, "i");
MODULE_PARM_DESC(product, "User specified USB idProduct");
+#endif
+
+
+static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum);
+static void usb_serial_disconnect(struct usb_device *dev, void *ptr);
/* USB Serial devices vendor ids and device ids that this driver supports */
@@ -106,12 +151,36 @@ MODULE_PARM_DESC(product, "User specified USB idProduct");
#define HANDSPRING_VISOR_ID 0x0100
-#define SERIAL_MAJOR 188 /* Nice legal number now */
-#define NUM_PORTS 16 /* Actually we are allowed 255, but this is good for now */
+#define SERIAL_TTY_MAJOR 188 /* Nice legal number now */
+#define SERIAL_TTY_MINORS 16 /* Actually we are allowed 255, but this is good for now */
-static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum);
-static void usb_serial_disconnect(struct usb_device *dev, void *ptr);
+#define MAX_NUM_PORTS 8 /* The maximum number of ports one device can grab at once */
+
+struct usb_serial {
+ struct usb_device * dev;
+ struct usb_serial_device_type * type;
+ void * irq_handle;
+ unsigned int irqpipe;
+ struct tty_struct * tty; /* the coresponding tty for this device */
+ unsigned char minor;
+ unsigned char num_ports; /* the number of ports this device has */
+ char active[MAX_NUM_PORTS]; /* someone has this device open */
+
+ char num_interrupt_in; /* number of interrupt in endpoints we have */
+ __u8 interrupt_in_interval[MAX_NUM_PORTS];
+ unsigned char * interrupt_in_buffer[MAX_NUM_PORTS];
+ struct urb control_urb[MAX_NUM_PORTS];
+
+ char num_bulk_in; /* number of bulk in endpoints we have */
+ unsigned char * bulk_in_buffer[MAX_NUM_PORTS];
+ struct urb read_urb[MAX_NUM_PORTS];
+
+ char num_bulk_out; /* number of bulk out endpoints we have */
+ unsigned char * bulk_out_buffer[MAX_NUM_PORTS];
+ int bulk_out_size[MAX_NUM_PORTS];
+ struct urb write_urb[MAX_NUM_PORTS];
+};
#define MUST_HAVE_NOT 0x01
@@ -127,7 +196,6 @@ static void usb_serial_disconnect(struct usb_device *dev, void *ptr);
static int serial_open (struct tty_struct *tty, struct file * filp);
static void serial_close (struct tty_struct *tty, struct file * filp);
static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count);
-static void serial_put_char (struct tty_struct *tty, unsigned char ch);
static int serial_write_room (struct tty_struct *tty);
static int serial_chars_in_buffer (struct tty_struct *tty);
static void serial_throttle (struct tty_struct * tty);
@@ -145,15 +213,15 @@ struct usb_serial_device_type {
char num_interrupt_in;
char num_bulk_in;
char num_bulk_out;
+ char num_ports; /* number of serial ports this device has */
/* function call to make before accepting driver */
- void (*startup) (void);
+ int (*startup) (struct usb_serial *serial); /* return 0 to continue initialization, anything else to abort */
/* serial function calls */
int (*open)(struct tty_struct * tty, struct file * filp);
void (*close)(struct tty_struct * tty, struct file * filp);
int (*write)(struct tty_struct * tty, int from_user,const unsigned char *buf, int count);
- void (*put_char)(struct tty_struct *tty, unsigned char ch);
int (*write_room)(struct tty_struct *tty);
int (*chars_in_buffer)(struct tty_struct *tty);
void (*throttle)(struct tty_struct * tty);
@@ -162,13 +230,14 @@ struct usb_serial_device_type {
/* function prototypes for a "generic" type serial converter (no flow control, not all endpoints needed) */
+/* need to always compile these in, as some of the other devices use these functions as their own. */
static int generic_serial_open (struct tty_struct *tty, struct file *filp);
static void generic_serial_close (struct tty_struct *tty, struct file *filp);
static int generic_serial_write (struct tty_struct *tty, int from_user, const unsigned char *buf, int count);
-static void generic_serial_put_char (struct tty_struct *tty, unsigned char ch);
static int generic_write_room (struct tty_struct *tty);
static int generic_chars_in_buffer (struct tty_struct *tty);
+#ifdef CONFIG_USB_SERIAL_GENERIC
/* All of the device info needed for the Generic Serial Converter */
static struct usb_serial_device_type generic_device = {
name: "Generic",
@@ -180,19 +249,22 @@ static struct usb_serial_device_type generic_device = {
num_interrupt_in: NUM_DONT_CARE,
num_bulk_in: NUM_DONT_CARE,
num_bulk_out: NUM_DONT_CARE,
+ num_ports: 1,
open: generic_serial_open,
close: generic_serial_close,
write: generic_serial_write,
- put_char: generic_serial_put_char,
write_room: generic_write_room,
chars_in_buffer: generic_chars_in_buffer,
};
+#endif
-
+#if defined(CONFIG_USB_SERIAL_BELKIN) || defined(CONFIG_USB_SERIAL_PERACOM)
/* function prototypes for the eTek type converters (this includes Belkin and Peracom) */
static int etek_serial_open (struct tty_struct *tty, struct file *filp);
static void etek_serial_close (struct tty_struct *tty, struct file *filp);
+#endif
+#ifdef CONFIG_USB_SERIAL_BELKIN
/* All of the device info needed for the Belkin Serial Converter */
static __u16 belkin_vendor_id = BELKIN_VENDOR_ID;
static __u16 belkin_product_id = BELKIN_SERIAL_CONVERTER;
@@ -206,14 +278,17 @@ static struct usb_serial_device_type belkin_device = {
num_interrupt_in: 1,
num_bulk_in: 1,
num_bulk_out: 1,
+ num_ports: 1,
open: etek_serial_open,
close: etek_serial_close,
write: generic_serial_write,
- put_char: generic_serial_put_char,
write_room: generic_write_room,
chars_in_buffer: generic_chars_in_buffer,
};
+#endif
+
+#ifdef CONFIG_USB_SERIAL_PERACOM
/* All of the device info needed for the Peracom Serial Converter */
static __u16 peracom_vendor_id = PERACOM_VENDOR_ID;
static __u16 peracom_product_id = PERACOM_SERIAL_CONVERTER;
@@ -224,23 +299,26 @@ static struct usb_serial_device_type peracom_device = {
needs_interrupt_in: MUST_HAVE, /* this device must have an interrupt in endpoint */
needs_bulk_in: MUST_HAVE, /* this device must have a bulk in endpoint */
needs_bulk_out: MUST_HAVE, /* this device must have a bulk out endpoint */
+ num_ports: 1,
num_interrupt_in: 1,
num_bulk_in: 1,
num_bulk_out: 1,
open: etek_serial_open,
close: etek_serial_close,
write: generic_serial_write,
- put_char: generic_serial_put_char,
write_room: generic_write_room,
chars_in_buffer: generic_chars_in_buffer,
};
+#endif
+#ifdef CONFIG_USB_SERIAL_WHITEHEAT
/* function prototypes for the Connect Tech WhiteHEAT serial converter */
static int whiteheat_serial_open (struct tty_struct *tty, struct file *filp);
static void whiteheat_serial_close (struct tty_struct *tty, struct file *filp);
static void whiteheat_throttle (struct tty_struct *tty);
static void whiteheat_unthrottle (struct tty_struct *tty);
+static int whiteheat_startup (struct usb_serial *serial);
/* All of the device info needed for the Connect Tech WhiteHEAT */
static __u16 connecttech_vendor_id = CONNECT_TECH_VENDOR_ID;
@@ -256,6 +334,7 @@ static struct usb_serial_device_type whiteheat_fake_device = {
num_interrupt_in: NUM_DONT_CARE,
num_bulk_in: NUM_DONT_CARE,
num_bulk_out: NUM_DONT_CARE,
+ startup: whiteheat_startup
};
static struct usb_serial_device_type whiteheat_device = {
name: "Connect Tech - WhiteHEAT",
@@ -267,22 +346,25 @@ static struct usb_serial_device_type whiteheat_device = {
num_interrupt_in: NUM_DONT_CARE,
num_bulk_in: NUM_DONT_CARE,
num_bulk_out: NUM_DONT_CARE,
+ num_ports: 4,
open: whiteheat_serial_open,
close: whiteheat_serial_close,
write: generic_serial_write,
- put_char: generic_serial_put_char,
write_room: generic_write_room,
chars_in_buffer: generic_chars_in_buffer,
throttle: whiteheat_throttle,
unthrottle: whiteheat_unthrottle
};
+#endif
+#ifdef CONFIG_USB_SERIAL_VISOR
/* function prototypes for a handspring visor */
static int visor_serial_open (struct tty_struct *tty, struct file *filp);
static void visor_serial_close (struct tty_struct *tty, struct file *filp);
static void visor_throttle (struct tty_struct *tty);
static void visor_unthrottle (struct tty_struct *tty);
+static int visor_startup (struct usb_serial *serial);
/* All of the device info needed for the Handspring Visor */
static __u16 handspring_vendor_id = HANDSPRING_VENDOR_ID;
@@ -297,72 +379,42 @@ static struct usb_serial_device_type handspring_device = {
num_interrupt_in: 0,
num_bulk_in: 2,
num_bulk_out: 2,
+ num_ports: 2,
open: visor_serial_open,
close: visor_serial_close,
write: generic_serial_write,
- put_char: generic_serial_put_char,
write_room: generic_write_room,
chars_in_buffer: generic_chars_in_buffer,
throttle: visor_throttle,
- unthrottle: visor_unthrottle
+ unthrottle: visor_unthrottle,
+ startup: visor_startup
};
-
+#endif
/* To add support for another serial converter, create a usb_serial_device_type
structure for that device, and add it to this list, making sure that the last
entry is NULL. */
static struct usb_serial_device_type *usb_serial_devices[] = {
+#ifdef CONFIG_USB_SERIAL_GENERIC
&generic_device,
+#endif
+#ifdef CONFIG_USB_SERIAL_WHITEHEAT
&whiteheat_fake_device,
&whiteheat_device,
+#endif
+#ifdef CONFIG_USB_SERIAL_BELKIN
&belkin_device,
+#endif
+#ifdef CONFIG_USB_SERIAL_PERACOM
&peracom_device,
+#endif
+#ifdef CONFIG_USB_SERIAL_VISOR
&handspring_device,
+#endif
NULL
};
-#define MAX_ENDPOINTS 8
-
-struct usb_serial_state {
- struct usb_device * dev;
- struct usb_serial_device_type * type;
- void * irq_handle;
- unsigned int irqpipe;
- struct tty_struct * tty; /* the coresponding tty for this device */
- unsigned char number;
- char present;
- char active;
-
- char num_interrupt_in; /* number of interrupt in endpoints we have */
- char interrupt_in_inuse; /* if the interrupt in endpoint is in use */
- __u8 interrupt_in_endpoint[MAX_ENDPOINTS];
- __u8 interrupt_in_interval[MAX_ENDPOINTS];
- __u16 interrupt_in_size[MAX_ENDPOINTS]; /* the size of the interrupt in endpoint */
- unsigned int interrupt_in_pipe[MAX_ENDPOINTS];
- unsigned char * interrupt_in_buffer[MAX_ENDPOINTS];
- void * interrupt_in_transfer[MAX_ENDPOINTS];
- struct urb control_urb;
-
- char num_bulk_in; /* number of bulk in endpoints we have */
- __u8 bulk_in_endpoint[MAX_ENDPOINTS];
- __u8 bulk_in_interval[MAX_ENDPOINTS];
- __u16 bulk_in_size[MAX_ENDPOINTS]; /* the size of the bulk in endpoint */
- unsigned int bulk_in_pipe[MAX_ENDPOINTS];
- unsigned char * bulk_in_buffer[MAX_ENDPOINTS];
- void * bulk_in_transfer[MAX_ENDPOINTS];
- struct urb read_urb;
-
- char num_bulk_out; /* number of bulk out endpoints we have */
- __u8 bulk_out_endpoint[MAX_ENDPOINTS];
- __u8 bulk_out_interval[MAX_ENDPOINTS];
- __u16 bulk_out_size[MAX_ENDPOINTS]; /* the size of the bulk out endpoint */
- unsigned int bulk_out_pipe[MAX_ENDPOINTS];
- unsigned char * bulk_out_buffer[MAX_ENDPOINTS];
- void * bulk_out_transfer[MAX_ENDPOINTS];
- struct urb write_urb;
-};
-
static struct usb_driver usb_serial_driver = {
"serial",
usb_serial_probe,
@@ -371,16 +423,61 @@ static struct usb_driver usb_serial_driver = {
};
static int serial_refcount;
-static struct tty_struct * serial_tty[NUM_PORTS];
-static struct termios * serial_termios[NUM_PORTS];
-static struct termios * serial_termios_locked[NUM_PORTS];
-static struct usb_serial_state serial_state_table[NUM_PORTS];
+static struct tty_struct * serial_tty[SERIAL_TTY_MINORS];
+static struct termios * serial_termios[SERIAL_TTY_MINORS];
+static struct termios * serial_termios_locked[SERIAL_TTY_MINORS];
+static struct usb_serial *serial_table[SERIAL_TTY_MINORS] = {NULL, };
+
+
+
+#define SERIAL_PTR_EMPTY ((void *)(-1))
+
+static struct usb_serial *get_serial_by_minor (int minor)
+{
+ int i;
+ dbg("get_serial_by_minor %d", minor);
+
+ for (i = 0; i < SERIAL_TTY_MINORS; ++i)
+ if (serial_table[i])
+ if (serial_table[i] != SERIAL_PTR_EMPTY)
+ if (serial_table[i]->minor == minor)
+ return (serial_table[i]);
+
+ return (NULL);
+}
+
+
+static struct usb_serial *get_free_serial (int num_ports, int *minor)
+{
+ struct usb_serial *serial = NULL;
+ int i;
+
+ dbg("get_free_serial %d", num_ports);
+
+ *minor = 0;
+ for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
+ if (serial_table[i])
+ continue;
+ if (!(serial = kmalloc(sizeof(struct usb_serial), GFP_KERNEL))) {
+ err("Out of memory");
+ return NULL;
+ }
+ memset(serial, 0, sizeof(struct usb_serial));
+ serial_table[i] = serial;
+ *minor = i;
+ dbg("minor base = %d", *minor);
+ for (i = *minor+1; (i < num_ports) && (i < SERIAL_TTY_MINORS); ++i)
+ serial_table[i] = SERIAL_PTR_EMPTY;
+ return (serial);
+ }
+ return (NULL);
+}
static void serial_read_bulk (struct urb *urb)
{
- struct usb_serial_state *serial = (struct usb_serial_state *)urb->context;
+ struct usb_serial *serial = (struct usb_serial *)urb->context;
struct tty_struct *tty = serial->tty;
unsigned char *data = urb->transfer_buffer;
int i;
@@ -412,7 +509,7 @@ static void serial_read_bulk (struct urb *urb)
static void serial_write_bulk (struct urb *urb)
{
- struct usb_serial_state *serial = (struct usb_serial_state *) urb->context;
+ struct usb_serial *serial = (struct usb_serial *) urb->context;
struct tty_struct *tty = serial->tty;
dbg("serial_write_irq");
@@ -437,12 +534,12 @@ static void serial_write_bulk (struct urb *urb)
*****************************************************************************/
static int serial_open (struct tty_struct *tty, struct file * filp)
{
- struct usb_serial_state *serial;
+ struct usb_serial *serial;
dbg("serial_open");
- /* assign a serial object to the tty pointer */
- serial = &serial_state_table [MINOR(tty->device)-tty->driver.minor_start];
+ /* get the serial object associated with this tty pointer */
+ serial = get_serial_by_minor (MINOR(tty->device));
/* do some sanity checking that we really have a device present */
if (!serial) {
@@ -469,8 +566,10 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
static void serial_close(struct tty_struct *tty, struct file * filp)
{
- struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data;
- dbg("serial_close");
+ struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
+ int port = MINOR(tty->device) - serial->minor;
+
+ dbg("serial_close port %d", port);
/* do some sanity checking that we really have a device present */
if (!serial) {
@@ -481,11 +580,7 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
dbg("serial->type == NULL!");
return;
}
- if (!serial->present) {
- dbg("no device registered");
- return;
- }
- if (!serial->active) {
+ if (!serial->active[port]) {
dbg ("device already open");
return;
}
@@ -499,9 +594,10 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
{
- struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data;
+ struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
+ int port = MINOR(tty->device) - serial->minor;
- dbg("serial_write");
+ dbg("serial_write port %d, %d byte(s)", port, count);
/* do some sanity checking that we really have a device present */
if (!serial) {
@@ -512,11 +608,7 @@ static int serial_write (struct tty_struct * tty, int from_user, const unsigned
dbg("serial->type == NULL!");
return (-ENODEV);
}
- if (!serial->present) {
- dbg("device not registered");
- return (-EINVAL);
- }
- if (!serial->active) {
+ if (!serial->active[port]) {
dbg ("device not opened");
return (-EINVAL);
}
@@ -531,44 +623,12 @@ static int serial_write (struct tty_struct * tty, int from_user, const unsigned
}
-static void serial_put_char (struct tty_struct *tty, unsigned char ch)
-{
- struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data;
-
- dbg("serial_put_char");
-
- /* do some sanity checking that we really have a device present */
- if (!serial) {
- dbg("serial == NULL!");
- return;
- }
- if (!serial->type) {
- dbg("serial->type == NULL!");
- return;
- }
- if (!serial->present) {
- dbg("no device registered");
- return;
- }
- if (!serial->active) {
- dbg ("device not open");
- return;
- }
-
- /* pass on to the driver specific version of this function */
- if (serial->type->put_char) {
- serial->type->put_char(tty, ch);
- }
-
- return;
-}
-
-
static int serial_write_room (struct tty_struct *tty)
{
- struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data;
+ struct usb_serial *serial = (struct usb_serial *)tty->driver_data;
+ int port = MINOR(tty->device) - serial->minor;
- dbg("serial_write_room");
+ dbg("serial_write_room port %d", port);
/* do some sanity checking that we really have a device present */
if (!serial) {
@@ -579,11 +639,7 @@ static int serial_write_room (struct tty_struct *tty)
dbg("serial->type == NULL!");
return (-ENODEV);
}
- if (!serial->present) {
- dbg("no device registered");
- return (-EINVAL);
- }
- if (!serial->active) {
+ if (!serial->active[port]) {
dbg ("device not open");
return (-EINVAL);
}
@@ -599,9 +655,10 @@ static int serial_write_room (struct tty_struct *tty)
static int serial_chars_in_buffer (struct tty_struct *tty)
{
- struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data;
+ struct usb_serial *serial = (struct usb_serial *)tty->driver_data;
+ int port = MINOR(tty->device) - serial->minor;
- dbg("serial_chars_in_buffer");
+ dbg("serial_chars_in_buffer port %d", port);
/* do some sanity checking that we really have a device present */
if (!serial) {
@@ -612,11 +669,7 @@ static int serial_chars_in_buffer (struct tty_struct *tty)
dbg("serial->type == NULL!");
return (-ENODEV);
}
- if (!serial->present) {
- dbg("no device registered");
- return (-EINVAL);
- }
- if (!serial->active) {
+ if (!serial->active[port]) {
dbg ("device not open");
return (-EINVAL);
}
@@ -632,9 +685,10 @@ static int serial_chars_in_buffer (struct tty_struct *tty)
static void serial_throttle (struct tty_struct * tty)
{
- struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data;
+ struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
+ int port = MINOR(tty->device) - serial->minor;
- dbg("serial_throttle");
+ dbg("serial_throttle port %d", port);
/* do some sanity checking that we really have a device present */
if (!serial) {
@@ -645,11 +699,7 @@ static void serial_throttle (struct tty_struct * tty)
dbg("serial->type == NULL!");
return;
}
- if (!serial->present) {
- dbg("no device registered");
- return;
- }
- if (!serial->active) {
+ if (!serial->active[port]) {
dbg ("device not open");
return;
}
@@ -665,9 +715,10 @@ static void serial_throttle (struct tty_struct * tty)
static void serial_unthrottle (struct tty_struct * tty)
{
- struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data;
+ struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
+ int port = MINOR(tty->device) - serial->minor;
- dbg("serial_unthrottle");
+ dbg("serial_unthrottle port %d", port);
/* do some sanity checking that we really have a device present */
if (!serial) {
@@ -678,16 +729,11 @@ static void serial_unthrottle (struct tty_struct * tty)
dbg("serial->type == NULL!");
return;
}
- if (!serial->present) {
- dbg("no device registered");
- return;
- }
- if (!serial->active) {
+ if (!serial->active[port]) {
dbg ("device not open");
return;
}
-
/* pass on to the driver specific version of this function */
if (serial->type->unthrottle) {
serial->type->unthrottle(tty);
@@ -697,28 +743,25 @@ static void serial_unthrottle (struct tty_struct * tty)
}
+#if defined(CONFIG_USB_SERIAL_BELKIN) || defined(CONFIG_USB_SERIAL_PERACOM)
/*****************************************************************************
* eTek specific driver functions
*****************************************************************************/
static int etek_serial_open (struct tty_struct *tty, struct file *filp)
{
- struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data;
+ struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
+ int port = MINOR(tty->device) - serial->minor;
- dbg("etek_serial_open");
+ dbg("etek_serial_open port %d", port);
- if (!serial->present) {
- dbg("no device registered");
- return -EINVAL;
- }
-
- if (serial->active) {
+ if (serial->active[port]) {
dbg ("device already open");
return -EINVAL;
}
- serial->active = 1;
+ serial->active[port] = 1;
/*Start reading from the device*/
- if (usb_submit_urb(&serial->read_urb))
+ if (usb_submit_urb(&serial->read_urb[port]))
dbg("usb_submit_urb(read bulk) failed");
/* Need to do device specific setup here (control lines, baud rate, etc.) */
@@ -730,41 +773,42 @@ static int etek_serial_open (struct tty_struct *tty, struct file *filp)
static void etek_serial_close(struct tty_struct *tty, struct file * filp)
{
- struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data;
- dbg("etek_serial_close");
+ struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
+ int port = MINOR(tty->device) - serial->minor;
+
+ dbg("etek_serial_close port %d", port);
/* Need to change the control lines here */
/* FIXME */
/* shutdown our bulk reads and writes */
- usb_unlink_urb (&serial->write_urb);
- usb_unlink_urb (&serial->read_urb);
- serial->active = 0;
+ usb_unlink_urb (&serial->write_urb[port]);
+ usb_unlink_urb (&serial->read_urb[port]);
+ serial->active[port] = 0;
}
+#endif /* defined(CONFIG_USB_SERIAL_BELKIN) || defined(CONFIG_USB_SERIAL_PERACOM) */
+
+#ifdef CONFIG_USB_SERIAL_WHITEHEAT
/*****************************************************************************
* Connect Tech's White Heat specific driver functions
*****************************************************************************/
static int whiteheat_serial_open (struct tty_struct *tty, struct file *filp)
{
- struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data;
+ struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
+ int port = MINOR(tty->device) - serial->minor;
- dbg("whiteheat_serial_open");
+ dbg("whiteheat_serial_open port %d", port);
- if (!serial->present) {
- dbg("no device registered");
- return -EINVAL;
- }
-
- if (serial->active) {
+ if (serial->active[port]) {
dbg ("device already open");
return -EINVAL;
}
- serial->active = 1;
+ serial->active[port] = 1;
/*Start reading from the device*/
- if (usb_submit_urb(&serial->read_urb))
+ if (usb_submit_urb(&serial->read_urb[port]))
dbg("usb_submit_urb(read bulk) failed");
/* Need to do device specific setup here (control lines, baud rate, etc.) */
@@ -776,23 +820,28 @@ static int whiteheat_serial_open (struct tty_struct *tty, struct file *filp)
static void whiteheat_serial_close(struct tty_struct *tty, struct file * filp)
{
- struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data;
- dbg("whiteheat_serial_close");
+ struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
+ int port = MINOR(tty->device) - serial->minor;
+
+ dbg("whiteheat_serial_close port %d", port);
/* Need to change the control lines here */
/* FIXME */
/* shutdown our bulk reads and writes */
- usb_unlink_urb (&serial->write_urb);
- usb_unlink_urb (&serial->read_urb);
- serial->active = 0;
+ usb_unlink_urb (&serial->write_urb[port]);
+ usb_unlink_urb (&serial->read_urb[port]);
+ serial->active[port] = 0;
}
static void whiteheat_throttle (struct tty_struct * tty)
{
- dbg("whiteheat_throttle");
-
+ struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
+ int port = MINOR(tty->device) - serial->minor;
+
+ dbg("whiteheat_throttle port %d", port);
+
/* Change the control signals */
/* FIXME!!! */
@@ -802,8 +851,11 @@ static void whiteheat_throttle (struct tty_struct * tty)
static void whiteheat_unthrottle (struct tty_struct * tty)
{
- dbg("whiteheat_unthrottle");
-
+ struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
+ int port = MINOR(tty->device) - serial->minor;
+
+ dbg("whiteheat_unthrottle port %d", port);
+
/* Change the control signals */
/* FIXME!!! */
@@ -811,28 +863,131 @@ static void whiteheat_unthrottle (struct tty_struct * tty)
}
+static int whiteheat_writememory (struct usb_serial *serial, int address, unsigned char *data, int length, __u8 bRequest)
+{
+ int result;
+ unsigned char *transfer_buffer = kmalloc (length, GFP_KERNEL);
+
+// dbg("whiteheat_writememory %x, %d", address, length);
+
+ if (!transfer_buffer) {
+ err("whiteheat_writememory: kmalloc(%d) failed.\n", length);
+ return -ENOMEM;
+ }
+ memcpy (transfer_buffer, data, length);
+ result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), bRequest, 0x40, address, 0, transfer_buffer, length, 300);
+ kfree (transfer_buffer);
+ return result;
+}
+
+/* EZ-USB Control and Status Register. Bit 0 controls 8051 reset */
+#define CPUCS_REG 0x7F92
+
+static int whiteheat_set_reset (struct usb_serial *serial, unsigned char reset_bit)
+{
+ int response;
+ dbg("whiteheat_set_reset: %d", reset_bit);
+ response = whiteheat_writememory (serial, CPUCS_REG, &reset_bit, 1, 0xa0);
+ if (response < 0) {
+ err("whiteheat_set_reset %d failed", reset_bit);
+ }
+ return (response);
+}
+
+
+/* steps to download the firmware to the WhiteHEAT device:
+ - hold the reset (by writing to the reset bit of the CPUCS register)
+ - download the VEND_AX.HEX file to the chip using VENDOR_REQUEST-ANCHOR_LOAD
+ - release the reset (by writing to the CPUCS register)
+ - download the WH.HEX file for all addresses greater than 0x1b3f using
+ VENDOR_REQUEST-ANCHOR_EXTERNAL_RAM_LOAD
+ - hold the reset
+ - download the WH.HEX file for all addresses less than 0x1b40 using
+ VENDOR_REQUEST_ANCHOR_LOAD
+ - release the reset
+ - device renumerated itself and comes up as new device id with all
+ firmware download completed.
+*/
+static int whiteheat_startup (struct usb_serial *serial)
+{
+ int response;
+ const struct whiteheat_hex_record *record;
+
+ dbg("whiteheat_startup");
+
+ response = whiteheat_set_reset (serial, 1);
+
+ record = &whiteheat_loader[0];
+ while (record->address != 0xffff) {
+ response = whiteheat_writememory (serial, record->address,
+ (unsigned char *)record->data, record->data_size, 0xa0);
+ if (response < 0) {
+ err("whiteheat_writememory failed for loader (%d %04X %p %d)",
+ response, record->address, record->data, record->data_size);
+ break;
+ }
+ ++record;
+ }
+
+ response = whiteheat_set_reset (serial, 0);
+
+ record = &whiteheat_firmware[0];
+ while (record->address < 0x1b40) {
+ ++record;
+ }
+ while (record->address != 0xffff) {
+ response = whiteheat_writememory (serial, record->address,
+ (unsigned char *)record->data, record->data_size, 0xa0);
+ if (response < 0) {
+ err("whiteheat_writememory failed for first firmware step (%d %04X %p %d)",
+ response, record->address, record->data, record->data_size);
+ break;
+ }
+ ++record;
+ }
+
+ response = whiteheat_set_reset (serial, 1);
+
+ record = &whiteheat_firmware[0];
+ while (record->address < 0x1b40) {
+ response = whiteheat_writememory (serial, record->address,
+ (unsigned char *)record->data, record->data_size, 0xa0);
+ if (response < 0) {
+ err("whiteheat_writememory failed for second firmware step (%d %04X %p %d)\n",
+ response, record->address, record->data, record->data_size);
+ break;
+ }
+ ++record;
+ }
+
+ response = whiteheat_set_reset (serial, 0);
+
+ /* we want this device to fail to have a driver assigned to it. */
+ return (1);
+}
+#endif /* CONFIG_USB_SERIAL_WHITEHEAT */
+
+
+#ifdef CONFIG_USB_SERIAL_VISOR
/******************************************************************************
* Handspring Visor specific driver functions
******************************************************************************/
static int visor_serial_open (struct tty_struct *tty, struct file *filp)
{
- struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data;
- dbg("visor_serial_open");
+ struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
+ int port = MINOR(tty->device) - serial->minor;
- if (!serial->present) {
- dbg("no device registered");
- return -EINVAL;
- }
+ dbg("visor_serial_open port %d", port);
- if (serial->active) {
+ if (serial->active[port]) {
dbg ("device already open");
return -EINVAL;
}
- serial->active = 1;
+ serial->active[port] = 1;
/*Start reading from the device*/
- if (usb_submit_urb(&serial->read_urb))
+ if (usb_submit_urb(&serial->read_urb[port]))
dbg("usb_submit_urb(read bulk) failed");
return (0);
@@ -840,66 +995,146 @@ static int visor_serial_open (struct tty_struct *tty, struct file *filp)
static void visor_serial_close(struct tty_struct *tty, struct file * filp)
{
- struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data;
+ struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
+ int port = MINOR(tty->device) - serial->minor;
- dbg("USB: visor_serial_close");
+ dbg("visor_serial_close port %d", port);
/* shutdown our bulk reads and writes */
- usb_unlink_urb (&serial->write_urb);
- usb_unlink_urb (&serial->read_urb);
- serial->active = 0;
+ usb_unlink_urb (&serial->write_urb[port]);
+ usb_unlink_urb (&serial->read_urb[port]);
+ serial->active[port] = 0;
}
static void visor_throttle (struct tty_struct * tty)
{
-/* struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; */
+ struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
+ int port = MINOR(tty->device) - serial->minor;
- dbg("visor_throttle");
+ dbg("visor_throttle port %d", port);
- /* Change the control signals */
- /* FIXME!!! */
+ usb_unlink_urb (&serial->read_urb[port]);
return;
}
+
static void visor_unthrottle (struct tty_struct * tty)
{
-/* struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; */
+ struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
+ int port = MINOR(tty->device) - serial->minor;
- dbg("visor_unthrottle");
+ dbg("visor_unthrottle port %d", port);
- /* Change the control signals */
- /* FIXME!!! */
+ if (usb_unlink_urb (&serial->read_urb[port]))
+ dbg("usb_submit_urb(read bulk) failed");
return;
}
+/*
+ Here's the raw dump of the vendor specific command data that the Visor sends on Win98
+______________________________________________________________________
+SETUP(0xB4) ADDR(0x02) ENDP(0x0) CRC5(0x15)
+______________________________________________________________________
+DATA0(0xC3) DATA(C2 03 00 00 00 00 12 00 ) CRC16(0xB0BB)
+______________________________________________________________________
+ACK(0x4B)
+______________________________________________________________________
+IN(0x96) ADDR(0x02) ENDP(0x0) CRC5(0x15)
+______________________________________________________________________
+DATA1(0xD2) DATA(02 00 00 01 02 02 ) CRC16(0xF4E6)
+______________________________________________________________________
+ACK(0x4B)
+______________________________________________________________________
+OUT(0x87) ADDR(0x02) ENDP(0x0) CRC5(0x15)
+______________________________________________________________________
+DATA1(0xD2) DATA() CRC16(0x0000)
+______________________________________________________________________
+ACK(0x4B)
+______________________________________________________________________
+SETUP(0xB4) ADDR(0x02) ENDP(0x0) CRC5(0x15)
+______________________________________________________________________
+DATA0(0xC3) DATA(C2 01 00 00 05 00 02 00 ) CRC16(0xC488)
+______________________________________________________________________
+ACK(0x4B)
+______________________________________________________________________
+IN(0x96) ADDR(0x02) ENDP(0x0) CRC5(0x15)
+______________________________________________________________________
+DATA1(0xD2) DATA(01 00 ) CRC16(0xFFFB)
+______________________________________________________________________
+ACK(0x4B)
+______________________________________________________________________
+OUT(0x87) ADDR(0x02) ENDP(0x0) CRC5(0x15)
+______________________________________________________________________
+DATA1(0xD2) DATA() CRC16(0x0000)
+______________________________________________________________________
+ACK(0x4B)
+______________________________________________________________________
+*/
+
+static int visor_startup (struct usb_serial *serial)
+{
+ /* send out two unknown commands that I found by looking at a Win98 trace */
+ int response;
+ unsigned char *transfer_buffer = kmalloc (256, GFP_KERNEL);
+
+ if (!transfer_buffer) {
+ err("visor_startup: kmalloc(%d) failed.\n", 256);
+ return -ENOMEM;
+ }
+
+ dbg("visor_startup");
+
+ dbg("visor_setup: Set config to 1");
+ usb_set_configuration (serial->dev, 1);
+
+ response = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), 0x03, 0xc2, 0x0000, 0x0000, transfer_buffer, 0x12, 300);
+ if (response < 0) {
+ err("visor_startup: error getting first vendor specific message");
+ } else {
+ dbg("visor_startup: First vendor specific message successful");
+ }
+
+ response = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), 0x01, 0xc2, 0x0000, 0x0005, transfer_buffer, 0x02, 300);
+ if (response < 0) {
+ err("visor_startup: error getting second vendor specific message");
+ } else {
+ dbg("visor_startup: Second vendor specific message successful");
+ }
+
+ kfree (transfer_buffer);
+
+ /* continue on with initialization */
+ return (0);
+}
+
+
+#endif /* CONFIG_USB_SERIAL_VISOR*/
+
+
/*****************************************************************************
* generic devices specific driver functions
*****************************************************************************/
static int generic_serial_open (struct tty_struct *tty, struct file *filp)
{
- struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data;
+ struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
+ int port = MINOR(tty->device) - serial->minor;
- dbg("generic_serial_open");
+ dbg("generic_serial_open port %d", port);
- if (!serial->present) {
- dbg("no device registered");
- return -EINVAL;
- }
-
- if (serial->active) {
+ if (serial->active[port]) {
dbg ("device already open");
return -EINVAL;
}
- serial->active = 1;
+ serial->active[port] = 1;
/* if we have a bulk interrupt, start reading from it */
if (serial->num_bulk_in) {
/*Start reading from the device*/
- if (usb_submit_urb(&serial->read_urb))
+ if (usb_submit_urb(&serial->read_urb[port]))
dbg("usb_submit_urb(read bulk) failed");
}
@@ -909,26 +1144,29 @@ static int generic_serial_open (struct tty_struct *tty, struct file *filp)
static void generic_serial_close(struct tty_struct *tty, struct file * filp)
{
- struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data;
- dbg("generic_serial_close");
+ struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
+ int port = MINOR(tty->device) - serial->minor;
+
+ dbg("generic_serial_close port %d", port);
/* shutdown any bulk reads that might be going on */
if (serial->num_bulk_out) {
- usb_unlink_urb (&serial->write_urb);
+ usb_unlink_urb (&serial->write_urb[port]);
}
if (serial->num_bulk_in) {
- usb_unlink_urb (&serial->read_urb);
+ usb_unlink_urb (&serial->read_urb[port]);
}
- serial->active = 0;
+ serial->active[port] = 0;
}
static int generic_serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
{
- struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data;
-
- dbg("generic_serial_write");
+ struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
+ int port = MINOR(tty->device) - serial->minor;
+
+ dbg("generic_serial_write port %d", port);
if (count == 0) {
dbg("write request of 0 bytes");
@@ -937,24 +1175,24 @@ static int generic_serial_write (struct tty_struct * tty, int from_user, const u
/* only do something if we have a bulk out endpoint */
if (serial->num_bulk_out) {
- if (serial->write_urb.status == -EINPROGRESS) {
+ if (serial->write_urb[port].status == -EINPROGRESS) {
dbg ("already writing");
return (0);
}
- count = (count > serial->bulk_out_size[0]) ? serial->bulk_out_size[0] : count;
+ count = (count > serial->bulk_out_size[port]) ? serial->bulk_out_size[port] : count;
if (from_user) {
- copy_from_user(serial->write_urb.transfer_buffer, buf, count);
+ copy_from_user(serial->write_urb[port].transfer_buffer, buf, count);
}
else {
- memcpy (serial->write_urb.transfer_buffer, buf, count);
+ memcpy (serial->write_urb[port].transfer_buffer, buf, count);
}
/* send the data out the bulk port */
- serial->write_urb.transfer_buffer_length = count;
+ serial->write_urb[port].transfer_buffer_length = count;
- if (usb_submit_urb(&serial->write_urb))
+ if (usb_submit_urb(&serial->write_urb[port]))
dbg("usb_submit_urb(write bulk) failed");
return (count);
@@ -965,39 +1203,19 @@ static int generic_serial_write (struct tty_struct * tty, int from_user, const u
}
-static void generic_serial_put_char (struct tty_struct *tty, unsigned char ch)
-{
- struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data;
-
- dbg("generic_serial_put_char");
-
- /* if we have a bulk out endpoint, then shove a character out it */
- if (serial->num_bulk_out) {
- /* send the single character out the bulk port */
- memcpy (serial->write_urb.transfer_buffer, &ch, 1);
- serial->write_urb.transfer_buffer_length = 1;
-
- if (usb_submit_urb(&serial->write_urb))
- dbg("usb_submit_urb(write bulk) failed");
-
- }
-
- return;
-}
-
-
static int generic_write_room (struct tty_struct *tty)
{
- struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data;
+ struct usb_serial *serial = (struct usb_serial *)tty->driver_data;
+ int port = MINOR(tty->device) - serial->minor;
int room;
- dbg("generic_write_room");
+ dbg("generic_write_room port %d", port);
if (serial->num_bulk_out) {
- if (serial->write_urb.status == -EINPROGRESS)
+ if (serial->write_urb[port].status == -EINPROGRESS)
room = 0;
else
- room = serial->bulk_out_size[0];
+ room = serial->bulk_out_size[port];
dbg("generic_write_room returns %d", room);
return (room);
}
@@ -1008,13 +1226,14 @@ static int generic_write_room (struct tty_struct *tty)
static int generic_chars_in_buffer (struct tty_struct *tty)
{
- struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data;
+ struct usb_serial *serial = (struct usb_serial *)tty->driver_data;
+ int port = MINOR(tty->device) - serial->minor;
- dbg("generic_chars_in_buffer");
+ dbg("generic_chars_in_buffer port %d", port);
if (serial->num_bulk_out) {
- if (serial->write_urb.status == -EINPROGRESS) {
- return (serial->bulk_out_size[0]);
+ if (serial->write_urb[port].status == -EINPROGRESS) {
+ return (serial->bulk_out_size[port]);
}
}
@@ -1022,29 +1241,18 @@ static int generic_chars_in_buffer (struct tty_struct *tty)
}
-static int Get_Free_Serial (void)
-{
- int i;
-
- for (i=0; i < NUM_PORTS; ++i) {
- if (!serial_state_table[i].present)
- return (i);
- }
- return (-1);
-}
-
-
static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum)
{
- struct usb_serial_state *serial = NULL;
+ struct usb_serial *serial = NULL;
struct usb_interface_descriptor *interface;
struct usb_endpoint_descriptor *endpoint;
- struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_ENDPOINTS];
- struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_ENDPOINTS];
- struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_ENDPOINTS];
+ struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS];
+ struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS];
+ struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
struct usb_serial_device_type *type;
int device_num;
- int serial_num;
+ int minor;
+ int buffer_size;
int i;
char interrupt_pipe;
char bulk_in_pipe;
@@ -1109,83 +1317,69 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum)
/* found all that we need */
info("%s converter detected", type->name);
- if (0>(serial_num = Get_Free_Serial())) {
- dbg("Too many devices connected");
+ serial = get_free_serial (type->num_ports, &minor);
+ if (serial == NULL) {
+ err("No more free serial devices");
return NULL;
}
- serial = &serial_state_table[serial_num];
-
- memset(serial, 0, sizeof(struct usb_serial_state));
serial->dev = dev;
serial->type = type;
- serial->number = serial_num;
+ serial->minor = minor;
+ serial->num_ports = type->num_ports;
serial->num_bulk_in = num_bulk_in;
serial->num_bulk_out = num_bulk_out;
serial->num_interrupt_in = num_interrupt_in;
+ /* if this device type has a startup function, call it */
+ if (type->startup) {
+ if (type->startup (serial))
+ return NULL;
+ }
+
/* set up the endpoint information */
for (i = 0; i < num_bulk_in; ++i) {
- serial->bulk_in_endpoint[i] = bulk_in_endpoint[i]->bEndpointAddress;
- serial->bulk_in_size[i] = bulk_in_endpoint[i]->wMaxPacketSize;
- serial->bulk_in_interval[i] = bulk_in_endpoint[i]->bInterval;
- serial->bulk_in_pipe[i] = usb_rcvbulkpipe (dev, serial->bulk_in_endpoint[i]);
- serial->bulk_in_buffer[i] = kmalloc (serial->bulk_in_size[i], GFP_KERNEL);
+ buffer_size = bulk_in_endpoint[i]->wMaxPacketSize;
+ serial->bulk_in_buffer[i] = kmalloc (buffer_size, GFP_KERNEL);
if (!serial->bulk_in_buffer[i]) {
err("Couldn't allocate bulk_in_buffer");
goto probe_error;
}
+ FILL_BULK_URB(&serial->read_urb[i], dev, usb_rcvbulkpipe (dev, bulk_in_endpoint[i]->bEndpointAddress),
+ serial->bulk_in_buffer[i], buffer_size, serial_read_bulk, serial);
}
- if (num_bulk_in)
- FILL_BULK_URB(&serial->read_urb, dev, usb_rcvbulkpipe (dev, serial->bulk_in_endpoint[0]),
- serial->bulk_in_buffer[0], serial->bulk_in_size[0], serial_read_bulk, serial);
for (i = 0; i < num_bulk_out; ++i) {
- serial->bulk_out_endpoint[i] = bulk_out_endpoint[i]->bEndpointAddress;
serial->bulk_out_size[i] = bulk_out_endpoint[i]->wMaxPacketSize;
- serial->bulk_out_interval[i] = bulk_out_endpoint[i]->bInterval;
- serial->bulk_out_pipe[i] = usb_rcvbulkpipe (dev, serial->bulk_out_endpoint[i]);
serial->bulk_out_buffer[i] = kmalloc (serial->bulk_out_size[i], GFP_KERNEL);
if (!serial->bulk_out_buffer[i]) {
err("Couldn't allocate bulk_out_buffer");
goto probe_error;
}
+ FILL_BULK_URB(&serial->write_urb[i], dev, usb_sndbulkpipe (dev, bulk_out_endpoint[i]->bEndpointAddress),
+ serial->bulk_out_buffer[i], serial->bulk_out_size[i], serial_write_bulk, serial);
}
- if (num_bulk_out)
- FILL_BULK_URB(&serial->write_urb, dev, usb_sndbulkpipe (dev, serial->bulk_in_endpoint[0]),
- serial->bulk_in_buffer[0], serial->bulk_in_size[0], serial_write_bulk, serial);
+#if 0 /* use this code when WhiteHEAT is up and running */
for (i = 0; i < num_interrupt_in; ++i) {
- serial->interrupt_in_inuse = 0;
- serial->interrupt_in_endpoint[i] = interrupt_in_endpoint[i]->bEndpointAddress;
- serial->interrupt_in_size[i] = interrupt_in_endpoint[i]->wMaxPacketSize;
- serial->interrupt_in_interval[i] = interrupt_in_endpoint[i]->bInterval;
- /* serial->interrupt_in_pipe = usb_rcvbulkpipe (dev, serial->bulk_in_endpoint); */
- serial->interrupt_in_buffer[i] = kmalloc (serial->bulk_in_size[i], GFP_KERNEL);
+ buffer_size = interrupt_in_endpoint[i]->wMaxPacketSize;
+ serial->interrupt_in_buffer[i] = kmalloc (buffer_size, GFP_KERNEL);
if (!serial->interrupt_in_buffer[i]) {
err("Couldn't allocate interrupt_in_buffer");
goto probe_error;
}
+ FILL_INT_URB(&serial->control_urb[i], dev, usb_rcvintpipe (dev, interrupt_in_endpoint[i]->bEndpointAddress),
+ serial->interrupt_in_buffer[i], buffer_size, serial_control_irq,
+ serial, interrupt_in_endpoint[i]->bInterval);
}
+#endif
- #if 0
- /* set up an interrupt for out bulk in pipe */
- /* ask for a bulk read */
- serial->bulk_in_inuse = 1;
- serial->bulk_in_transfer = usb_request_bulk (serial->dev, serial->bulk_in_pipe, serial_read_irq, serial->bulk_in_buffer, serial->bulk_in_size, serial);
-
- /* set up our interrupt to be the time for the bulk in read */
- ret = usb_request_irq (dev, serial->bulk_in_pipe, usb_serial_irq, serial->bulk_in_interval, serial, &serial->irq_handle);
- if (ret) {
- info("failed usb_request_irq (0x%x)", ret);
- goto probe_error;
+ for (i = 0; i < serial->num_ports; ++i) {
+ info("%s converter now attached to ttyUSB%d", type->name, serial->minor + i);
}
- #endif
- serial->present = 1;
MOD_INC_USE_COUNT;
- info("%s converter now attached to ttyUSB%d", type->name, serial_num);
return serial;
} else {
info("descriptors matched, but endpoints did not");
@@ -1214,19 +1408,16 @@ probe_error:
static void usb_serial_disconnect(struct usb_device *dev, void *ptr)
{
- struct usb_serial_state *serial = (struct usb_serial_state *) ptr;
+ struct usb_serial *serial = (struct usb_serial *) ptr;
int i;
if (serial) {
- if (!serial->present) {
- /* something strange is going on */
- dbg("disconnect but not present?");
- return;
- }
-
/* need to stop any transfers...*/
- usb_unlink_urb (&serial->write_urb);
- usb_unlink_urb (&serial->read_urb);
+ for (i = 0; i < serial->num_ports; ++i) {
+ usb_unlink_urb (&serial->write_urb[i]);
+ usb_unlink_urb (&serial->read_urb[i]);
+ serial->active[i] = 0;
+ }
/* free up any memory that we allocated */
for (i = 0; i < serial->num_bulk_in; ++i)
@@ -1239,17 +1430,18 @@ static void usb_serial_disconnect(struct usb_device *dev, void *ptr)
if (serial->interrupt_in_buffer[i])
kfree (serial->interrupt_in_buffer[i]);
- serial->present = 0;
- serial->active = 0;
+ for (i = 0; i < serial->num_ports; ++i) {
+ info("%s converter now disconnected from ttyUSB%d", serial->type->name, serial->minor + i);
+ }
- info("%s converter now disconnected from ttyUSB%d", serial->type->name, serial->number);
+ serial_table[serial->minor] = NULL;
+ kfree (serial);
} else {
info("device disconnected");
}
MOD_DEC_USE_COUNT;
-
}
@@ -1257,9 +1449,9 @@ static struct tty_driver serial_tty_driver = {
magic: TTY_DRIVER_MAGIC,
driver_name: "usb",
name: "ttyUSB",
- major: SERIAL_MAJOR,
+ major: SERIAL_TTY_MAJOR,
minor_start: 0,
- num: NUM_PORTS,
+ num: SERIAL_TTY_MINORS,
type: TTY_DRIVER_TYPE_SERIAL,
subtype: SERIAL_TYPE_NORMAL,
flags: TTY_DRIVER_REAL_RAW,
@@ -1273,7 +1465,7 @@ static struct tty_driver serial_tty_driver = {
open: serial_open,
close: serial_close,
write: serial_write,
- put_char: serial_put_char,
+ put_char: NULL,
flush_chars: NULL,
write_room: serial_write_room,
ioctl: NULL,
@@ -1298,8 +1490,8 @@ int usb_serial_init(void)
int i;
/* Initalize our global data */
- for (i = 0; i < NUM_PORTS; ++i) {
- memset(&serial_state_table[i], 0x00, sizeof(struct usb_serial_state));
+ for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
+ serial_table[i] = NULL;
}
/* register the tty driver */
diff --git a/drivers/usb/usb.c b/drivers/usb/usb.c
index 2c75fb86b..6b02641a9 100644
--- a/drivers/usb/usb.c
+++ b/drivers/usb/usb.c
@@ -39,8 +39,8 @@ static void usb_check_support(struct usb_device *);
/*
* We have a per-interface "registered driver" list.
*/
-static LIST_HEAD(usb_driver_list);
-static LIST_HEAD(usb_bus_list);
+LIST_HEAD(usb_driver_list);
+LIST_HEAD(usb_bus_list);
static struct usb_busmap busmap;
@@ -240,6 +240,7 @@ struct usb_bus *usb_alloc_bus(struct usb_operations *op)
bus->bandwidth_isoc_reqs = 0;
INIT_LIST_HEAD(&bus->bus_list);
+ INIT_LIST_HEAD(&bus->inodes);
return bus;
}
@@ -263,11 +264,11 @@ void usb_register_bus(struct usb_bus *bus)
} else
warn("too many buses");
- proc_usb_add_bus(bus);
-
/* Add it to the list of buses */
list_add(&bus->bus_list, &usb_bus_list);
+ usbdevfs_add_bus(bus);
+
info("new USB bus registered, assigned bus number %d", bus->busnum);
}
@@ -282,7 +283,7 @@ void usb_deregister_bus(struct usb_bus *bus)
*/
list_del(&bus->bus_list);
- proc_usb_remove_bus(bus);
+ usbdevfs_remove_bus(bus);
clear_bit(bus->busnum, busmap.busmap);
}
@@ -443,6 +444,8 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus)
dev->bus = bus;
dev->parent = parent;
atomic_set(&dev->refcnt, 1);
+ INIT_LIST_HEAD(&dev->inodes);
+ INIT_LIST_HEAD(&dev->filelist);
dev->bus->op->allocate(dev);
@@ -559,9 +562,10 @@ static int usb_start_wait_urb(urb_t *urb, int timeout, unsigned long* rval)
return status;
}
- if (urb->status == -EINPROGRESS)
- status=schedule_timeout(timeout); // ZZzzzz....
- else
+ if (urb->status == -EINPROGRESS) {
+ while (timeout && urb->status == -EINPROGRESS)
+ status = timeout = schedule_timeout(timeout);
+ } else
status = 1;
remove_wait_queue(&wqh, &wait);
@@ -646,8 +650,6 @@ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
void *usb_request_bulk(struct usb_device *dev, unsigned int pipe, usb_device_irq handler, void *data, int len, void *dev_id)
{
urb_t *urb;
- DECLARE_WAITQUEUE(wait, current);
- DECLARE_WAIT_QUEUE_HEAD(wqh);
api_wrapper_data *awd;
if (!(urb=usb_alloc_urb(0)))
@@ -1154,11 +1156,6 @@ void usb_destroy_configuration(struct usb_device *dev)
kfree(cf->interface);
}
kfree(dev->config);
-
- if (dev->string) {
- kfree(dev->string);
- dev->string = 0;
- }
}
void usb_init_root_hub(struct usb_device *dev)
@@ -1229,7 +1226,7 @@ void usb_disconnect(struct usb_device **pdev)
}
/* remove /proc/bus/usb entry */
- proc_usb_remove_device(dev);
+ usbdevfs_remove_device(dev);
/* Free up the device itself, including its device number */
if (dev->devnum > 0)
@@ -1290,7 +1287,7 @@ int usb_get_class_descriptor(struct usb_device *dev, unsigned char type,
unsigned char id, unsigned char index, void *buf, int size)
{
return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
- USB_REQ_GET_DESCRIPTOR, USB_RT_INTERFACE | USB_DIR_IN,
+ USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN,
(type << 8) + id, index, buf, size, HZ * GET_TIMEOUT);
}
@@ -1326,7 +1323,7 @@ int usb_get_protocol(struct usb_device *dev)
int ret;
if ((ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
- USB_REQ_GET_PROTOCOL, USB_DIR_IN | USB_RT_HIDD,
+ USB_REQ_GET_PROTOCOL, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
0, 1, &type, 1, HZ * GET_TIMEOUT)) < 0)
return ret;
@@ -1336,13 +1333,15 @@ int usb_get_protocol(struct usb_device *dev)
int usb_set_protocol(struct usb_device *dev, int protocol)
{
return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- USB_REQ_SET_PROTOCOL, USB_RT_HIDD, protocol, 1, NULL, 0, HZ * SET_TIMEOUT);
+ USB_REQ_SET_PROTOCOL, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ protocol, 1, NULL, 0, HZ * SET_TIMEOUT);
}
int usb_set_idle(struct usb_device *dev, int duration, int report_id)
{
- return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_IDLE,
- USB_RT_HIDD, (duration << 8) | report_id, 1, NULL, 0, HZ * SET_TIMEOUT);
+ return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ USB_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ (duration << 8) | report_id, 1, NULL, 0, HZ * SET_TIMEOUT);
}
static void usb_set_maxpacket(struct usb_device *dev)
@@ -1385,14 +1384,14 @@ int usb_clear_halt(struct usb_device *dev, int endp)
*/
result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- USB_REQ_CLEAR_FEATURE, USB_RT_ENDPOINT, 0, endp, NULL, 0, HZ * SET_TIMEOUT);
+ USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, endp, NULL, 0, HZ * SET_TIMEOUT);
/* don't clear if failed */
if (result < 0)
return result;
result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
- USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_ENDPOINT, 0, endp,
+ USB_REQ_GET_STATUS, USB_DIR_IN | USB_RECIP_ENDPOINT, 0, endp,
&status, sizeof(status), HZ * SET_TIMEOUT);
if (result < 0)
return result;
@@ -1426,7 +1425,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
}
if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- USB_REQ_SET_INTERFACE, USB_RT_INTERFACE, alternate,
+ USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE, alternate,
interface, NULL, 0, HZ * 5)) < 0)
return ret;
@@ -1466,14 +1465,14 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
int usb_get_report(struct usb_device *dev, unsigned char type, unsigned char id, unsigned char index, void *buf, int size)
{
return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
- USB_REQ_GET_REPORT, USB_DIR_IN | USB_RT_HIDD,
+ USB_REQ_GET_REPORT, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
(type << 8) + id, index, buf, size, HZ * GET_TIMEOUT);
}
int usb_set_report(struct usb_device *dev, unsigned char type, unsigned char id, unsigned char index, void *buf, int size)
{
return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- USB_REQ_SET_REPORT, USB_RT_HIDD,
+ USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
(type << 8) + id, index, buf, size, HZ);
}
@@ -1491,6 +1490,11 @@ int usb_get_configuration(struct usb_device *dev)
return -1;
}
+ if (dev->descriptor.bNumConfigurations < 1) {
+ warn("not enough configurations");
+ return -1;
+ }
+
dev->config = (struct usb_config_descriptor *)
kmalloc(dev->descriptor.bNumConfigurations *
sizeof(struct usb_config_descriptor), GFP_KERNEL);
@@ -1547,54 +1551,45 @@ int usb_get_configuration(struct usb_device *dev)
return result;
}
-char *usb_string(struct usb_device *dev, int index)
+int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
{
- int i, len, ret;
- char *ptr;
- union {
- unsigned char buffer[256];
- struct usb_string_descriptor desc;
- } u;
-
- if (index <= 0)
- return 0;
- if (dev->string)
- kfree (dev->string);
-
- if (dev->string_langid == 0) {
- /* read string descriptor 0 */
- ret = usb_get_string(dev, 0, 0, u.buffer, 4);
- if (ret >= 0 && u.desc.bLength >= 4)
- dev->string_langid = le16_to_cpup(&u.desc.wData[0]);
- else
- err("error getting string");
- dev->string_langid |= 0x10000; /* so it's non-zero */
- }
+ unsigned char *tbuf;
+ int err;
+ unsigned int u, idx;
- if (usb_get_string(dev, dev->string_langid, index, u.buffer, 4) < 0 ||
- ((ret = usb_get_string(dev, dev->string_langid, index, u.buffer,
- u.desc.bLength)) < 0)) {
- err("error retrieving string");
- return NULL;
- }
-
- if (ret > 0) ret /= 2; /* going from 16-bit chars to 8-bit */
- len = u.desc.bLength / 2; /* includes terminating null */
- /* after removing bLength & bDescType */
- if (ret < len) len = ret; /* use min of (ret, len) */
-
- ptr = kmalloc(len, GFP_KERNEL);
- if (!ptr) {
- err("couldn't allocate memory for string");
- return NULL;
+ if (size <= 0 || !buf)
+ return -EINVAL;
+ buf[0] = 0;
+ tbuf = kmalloc(256, GFP_KERNEL);
+ if (!tbuf)
+ return -ENOMEM;
+ /*
+ * is this two step process necessary? can't we just
+ * ask for a maximum length string and then take the length
+ * that was returned?
+ */
+ err = usb_get_string(dev, dev->string_langid, index, tbuf, 4);
+ if (err < 0)
+ goto errout;
+ err = usb_get_string(dev, dev->string_langid, index, tbuf, tbuf[0]);
+ if (err < 0)
+ goto errout;
+ size--;
+ for (idx = 0, u = 2; u < tbuf[0]; u += 2) {
+ if (idx >= size)
+ break;
+ if (tbuf[u+1]) {
+ buf[idx++] = '?'; /* non ASCII character */
+ continue;
+ }
+ buf[idx++] = tbuf[u];
}
+ buf[idx] = 0;
+ err = idx;
- for (i = 0; i < len - 1; ++i)
- ptr[i] = le16_to_cpup(&u.desc.wData[i]);
- ptr[i] = 0;
-
- dev->string = ptr;
- return ptr;
+ errout:
+ kfree(tbuf);
+ return err;
}
/*
@@ -1606,10 +1601,10 @@ char *usb_string(struct usb_device *dev, int index)
*/
int usb_new_device(struct usb_device *dev)
{
+ unsigned char *buf;
int addr, err;
- info("USB new device connect, assigned device number %d",
- dev->devnum);
+ info("USB new device connect, assigned device number %d", dev->devnum);
dev->maxpacketsize = 0; /* Default to 8 byte max packet size */
dev->epmaxpacketin [0] = 8;
@@ -1657,8 +1652,7 @@ int usb_new_device(struct usb_device *dev)
return 1;
}
- err=usb_get_configuration(dev);
-
+ err = usb_get_configuration(dev);
if (err < 0) {
err("unable to get configuration (error=%d)", err);
clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
@@ -1674,13 +1668,28 @@ int usb_new_device(struct usb_device *dev)
err("failed to set default configuration");
return -1;
}
+ /* get langid for strings */
+ buf = kmalloc(256, GFP_KERNEL);
+ if (!buf) {
+ err("out of memory\n");
+ } else {
+ err = usb_get_string(dev, 0, 0, buf, 4);
+ if (err < 0) {
+ err("error getting string descriptor 0 (error=%d)\n", err);
+ } else if (buf[0] < 4) {
+ err("string descriptpr 0 too short\n");
+ } else
+ dev->string_langid = buf[2] | (buf[3]<< 8);
+ kfree(buf);
+ info("USB device number %d default language ID 0x%x", dev->devnum, dev->string_langid);
+ }
usb_show_string(dev, "Manufacturer", dev->descriptor.iManufacturer);
usb_show_string(dev, "Product", dev->descriptor.iProduct);
usb_show_string(dev, "SerialNumber", dev->descriptor.iSerialNumber);
/* now that the basic setup is over, add a /proc/bus/usb entry */
- proc_usb_add_device(dev);
+ usbdevfs_add_device(dev);
/* find drivers willing to handle this device */
usb_find_drivers(dev);
@@ -1771,6 +1780,7 @@ EXPORT_SYMBOL(usb_set_address);
EXPORT_SYMBOL(usb_get_descriptor);
EXPORT_SYMBOL(usb_get_class_descriptor);
EXPORT_SYMBOL(__usb_get_extra_descriptor);
+EXPORT_SYMBOL(usb_get_device_descriptor);
EXPORT_SYMBOL(usb_get_string);
EXPORT_SYMBOL(usb_string);
EXPORT_SYMBOL(usb_get_protocol);
diff --git a/drivers/usb/usb.h b/drivers/usb/usb.h
index 15bf6a664..c6f52047b 100644
--- a/drivers/usb/usb.h
+++ b/drivers/usb/usb.h
@@ -21,6 +21,28 @@
#define USB_CLASS_VENDOR_SPEC 0xff
/*
+ * USB types
+ */
+#define USB_TYPE_STANDARD (0x00 << 5)
+#define USB_TYPE_CLASS (0x01 << 5)
+#define USB_TYPE_VENDOR (0x02 << 5)
+#define USB_TYPE_RESERVED (0x03 << 5)
+
+/*
+ * USB recipients
+ */
+#define USB_RECIP_DEVICE 0x00
+#define USB_RECIP_INTERFACE 0x01
+#define USB_RECIP_ENDPOINT 0x02
+#define USB_RECIP_OTHER 0x03
+
+/*
+ * USB directions
+ */
+#define USB_DIR_OUT 0
+#define USB_DIR_IN 0x80
+
+/*
* Descriptor types
*/
#define USB_DT_DEVICE 0x01
@@ -29,10 +51,10 @@
#define USB_DT_INTERFACE 0x04
#define USB_DT_ENDPOINT 0x05
-#define USB_DT_HUB 0x29
-#define USB_DT_HID 0x21
-#define USB_DT_REPORT 0x22
-#define USB_DT_PHYSICAL 0x23
+#define USB_DT_HID (USB_TYPE_CLASS | 0x01)
+#define USB_DT_REPORT (USB_TYPE_CLASS | 0x02)
+#define USB_DT_PHYSICAL (USB_TYPE_CLASS | 0x03)
+#define USB_DT_HUB (USB_TYPE_CLASS | 0x09)
/*
* Descriptor sizes per descriptor type
@@ -46,11 +68,8 @@
#define USB_DT_HID_SIZE 9
/*
- * USB Request Type and Endpoint Directions
+ * Endpoints
*/
-#define USB_DIR_OUT 0
-#define USB_DIR_IN 0x80
-
#define USB_ENDPOINT_NUMBER_MASK 0x0f /* in bEndpointAddress */
#define USB_ENDPOINT_DIR_MASK 0x80
@@ -72,9 +91,7 @@
*/
#define USB_REQ_GET_STATUS 0x00
#define USB_REQ_CLEAR_FEATURE 0x01
-/* 0x02 is reserved */
#define USB_REQ_SET_FEATURE 0x03
-/* 0x04 is reserved */
#define USB_REQ_SET_ADDRESS 0x05
#define USB_REQ_GET_DESCRIPTOR 0x06
#define USB_REQ_SET_DESCRIPTOR 0x07
@@ -85,7 +102,7 @@
#define USB_REQ_SYNCH_FRAME 0x0C
/*
- * HIDD requests
+ * HID requests
*/
#define USB_REQ_GET_REPORT 0x01
#define USB_REQ_GET_IDLE 0x02
@@ -94,79 +111,6 @@
#define USB_REQ_SET_IDLE 0x0A
#define USB_REQ_SET_PROTOCOL 0x0B
-#define USB_TYPE_STANDARD (0x00 << 5)
-#define USB_TYPE_CLASS (0x01 << 5)
-#define USB_TYPE_VENDOR (0x02 << 5)
-#define USB_TYPE_RESERVED (0x03 << 5)
-
-#define USB_RECIP_DEVICE 0x00
-#define USB_RECIP_INTERFACE 0x01
-#define USB_RECIP_ENDPOINT 0x02
-#define USB_RECIP_OTHER 0x03
-
-#define USB_HID_RPT_INPUT 0x01
-#define USB_HID_RPT_OUTPUT 0x02
-#define USB_HID_RPT_FEATURE 0x03
-
-/*
- * Request target types.
- */
-#define USB_RT_DEVICE 0x00
-#define USB_RT_INTERFACE 0x01
-#define USB_RT_ENDPOINT 0x02
-
-#define USB_RT_HUB (USB_TYPE_CLASS | USB_RECIP_DEVICE)
-#define USB_RT_PORT (USB_TYPE_CLASS | USB_RECIP_OTHER)
-
-#define USB_RT_HIDD (USB_TYPE_CLASS | USB_RECIP_INTERFACE)
-
-/* /proc/bus/usb/xxx/yyy ioctl codes */
-
-struct usb_proc_ctrltransfer {
- __u8 requesttype;
- __u8 request;
- __u16 value;
- __u16 index;
- __u16 length;
- __u32 timeout; /* in milliseconds */
- void *data;
-};
-
-struct usb_proc_bulktransfer {
- unsigned int ep;
- unsigned int len;
- unsigned int timeout; /* in milliseconds */
- void *data;
-};
-
-struct usb_proc_old_ctrltransfer {
- __u8 requesttype;
- __u8 request;
- __u16 value;
- __u16 index;
- __u16 length;
- /* pointer to data */
- void *data;
-};
-
-struct usb_proc_old_bulktransfer {
- unsigned int ep;
- unsigned int len;
- void *data;
-};
-
-struct usb_proc_setinterface {
- unsigned int interface;
- unsigned int altsetting;
-};
-
-#define USB_PROC_CONTROL _IOWR('U', 0, struct usb_proc_ctrltransfer)
-#define USB_PROC_BULK _IOWR('U', 2, struct usb_proc_bulktransfer)
-#define USB_PROC_OLD_CONTROL _IOWR('U', 0, struct usb_proc_old_ctrltransfer)
-#define USB_PROC_OLD_BULK _IOWR('U', 2, struct usb_proc_old_bulktransfer)
-#define USB_PROC_RESETEP _IOR('U', 3, unsigned int)
-#define USB_PROC_SETINTERFACE _IOR('U', 4, struct usb_proc_setinterface)
-#define USB_PROC_SETCONFIGURATION _IOR('U', 5, unsigned int)
#ifdef __KERNEL__
@@ -227,9 +171,10 @@ typedef struct {
__u16 length;
} devrequest __attribute__ ((packed));
-/* USB-status codes:
+/*
+ * USB-status codes:
* USB_ST* maps to -E* and should go away in the future
-*/
+ */
#define USB_ST_NOERROR 0
#define USB_ST_CRC (-EILSEQ)
@@ -318,22 +263,6 @@ struct usb_endpoint_descriptor {
int extralen;
} __attribute__ ((packed));
-/* HID descriptor */
-struct usb_hid_class_descriptor {
- __u8 bDescriptorType;
- __u16 wDescriptorLength;
-} __attribute__ ((packed));
-
-struct usb_hid_descriptor {
- __u8 bLength;
- __u8 bDescriptorType;
- __u16 bcdHID;
- __u8 bCountryCode;
- __u8 bNumDescriptors;
-
- struct usb_hid_class_descriptor desc[1];
-} __attribute__ ((packed));
-
/* Interface descriptor */
struct usb_interface_descriptor {
__u8 bLength;
@@ -548,8 +477,8 @@ struct usb_bus {
int bandwidth_int_reqs; /* number of Interrupt requesters */
int bandwidth_isoc_reqs; /* number of Isoc. requesters */
- /* procfs entry */
- struct proc_dir_entry *proc_entry;
+ /* usbdevfs inode list */
+ struct list_head inodes;
};
#define USB_MAXCHILDREN (8) /* This is arbitrary */
@@ -574,13 +503,13 @@ struct usb_device {
struct usb_device_descriptor descriptor;/* Descriptor */
struct usb_config_descriptor *config; /* All of the configs */
- char *string; /* pointer to the last string read from the device */
int string_langid; /* language ID for strings */
void *hcpriv; /* Host Controller private data */
- /* procfs entry */
- struct proc_dir_entry *proc_entry;
+ /* usbdevfs inode list */
+ struct list_head inodes;
+ struct list_head filelist;
/*
* Child devices - these can be either new devices
@@ -746,7 +675,7 @@ int usb_get_report(struct usb_device *dev, unsigned char type,
unsigned char id, unsigned char index, void *buf, int size);
int usb_set_report(struct usb_device *dev, unsigned char type,
unsigned char id, unsigned char index, void *buf, int size);
-char *usb_string(struct usb_device *dev, int index);
+int usb_string(struct usb_device *dev, int index, char *buf, size_t size);
int usb_clear_halt(struct usb_device *dev, int endp);
#define usb_get_extra_descriptor(ifpoint,type,ptr)\
@@ -778,36 +707,56 @@ int usb_clear_halt(struct usb_device *dev, int endp);
void usb_show_device_descriptor(struct usb_device_descriptor *);
void usb_show_config_descriptor(struct usb_config_descriptor *);
void usb_show_interface_descriptor(struct usb_interface_descriptor *);
-void usb_show_hid_descriptor(struct usb_hid_descriptor * desc);
void usb_show_endpoint_descriptor(struct usb_endpoint_descriptor *);
void usb_show_device(struct usb_device *);
void usb_show_string(struct usb_device *dev, char *id, int index);
#ifdef DEBUG
-#define dbg(format, arg...) printk(KERN_DEBUG __FILE__ ": " format "\n", ## arg)
+#define dbg(format, arg...) printk(KERN_DEBUG __FILE__ ": " format "\n" , ## arg)
#else
-#define dbg(format, arg...)
+#define dbg(format, arg...) do {} while (0)
#endif
-#define err(format, arg...) printk(KERN_ERR __FILE__ ": " format "\n", ## arg)
-#define info(format, arg...) printk(KERN_INFO __FILE__ ": " format "\n", ## arg)
-#define warn(format, arg...) printk(KERN_WARNING __FILE__ ": " format "\n", ## arg)
+#define err(format, arg...) printk(KERN_ERR __FILE__ ": " format "\n" , ## arg)
+#define info(format, arg...) printk(KERN_INFO __FILE__ ": " format "\n" , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING __FILE__ ": " format "\n" , ## arg)
/*
- * procfs stuff
+ * bus and driver list
*/
-#ifdef CONFIG_USB_PROC
-void proc_usb_add_bus(struct usb_bus *bus);
-void proc_usb_remove_bus(struct usb_bus *bus);
-void proc_usb_add_device(struct usb_device *dev);
-void proc_usb_remove_device(struct usb_device *dev);
-#else
-extern inline void proc_usb_add_bus(struct usb_bus *bus) {}
-extern inline void proc_usb_remove_bus(struct usb_bus *bus) {}
-extern inline void proc_usb_add_device(struct usb_device *dev) {}
-extern inline void proc_usb_remove_device(struct usb_device *dev) {}
-#endif
+extern struct list_head usb_driver_list;
+extern struct list_head usb_bus_list;
+
+/*
+ * USB device fs stuff
+ */
+
+#ifdef CONFIG_USB_DEVICEFS
+
+/*
+ * these are expected to be called from the USB core/hub thread
+ * with the kernel lock held
+ */
+extern void usbdevfs_add_bus(struct usb_bus *bus);
+extern void usbdevfs_remove_bus(struct usb_bus *bus);
+extern void usbdevfs_add_device(struct usb_device *dev);
+extern void usbdevfs_remove_device(struct usb_device *dev);
+
+extern int usbdevfs_init(void);
+extern void usbdevfs_cleanup(void);
+
+#else /* CONFIG_USB_DEVICEFS */
+
+extern inline void usbdevfs_add_bus(struct usb_bus *bus) {}
+extern inline void usbdevfs_remove_bus(struct usb_bus *bus) {}
+extern inline void usbdevfs_add_device(struct usb_device *dev) {}
+extern inline void usbdevfs_remove_device(struct usb_device *dev) {}
+
+extern inline int usbdevfs_init(void) { return 0; }
+extern inline void usbdevfs_cleanup(void) { }
+
+#endif /* CONFIG_USB_DEVICEFS */
#endif /* __KERNEL__ */
diff --git a/drivers/usb/usb_scsi.c b/drivers/usb/usb_scsi.c
index e1713ed12..885cdac77 100644
--- a/drivers/usb/usb_scsi.c
+++ b/drivers/usb/usb_scsi.c
@@ -288,7 +288,7 @@ static int pop_CB_reset(struct us_data *us)
cmd[0] = SEND_DIAGNOSTIC;
cmd[1] = 4;
result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
- US_CBI_ADSC, USB_TYPE_CLASS | USB_RT_INTERFACE,
+ US_CBI_ADSC, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
0, us->ifnum, cmd, sizeof(cmd), HZ*5);
/* long wait for reset */
@@ -346,7 +346,7 @@ static int pop_CB_command(Scsi_Cmnd *srb)
} /* switch */
result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
- US_CBI_ADSC, USB_TYPE_CLASS | USB_RT_INTERFACE,
+ US_CBI_ADSC, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
0, us->ifnum,
cmd, us->fixedlength, HZ*5);
US_DEBUGP("First usb_control_msg returns %d\n", result);
@@ -367,7 +367,7 @@ static int pop_CB_command(Scsi_Cmnd *srb)
result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
US_CBI_ADSC,
- USB_TYPE_CLASS | USB_RT_INTERFACE,
+ USB_TYPE_CLASS | USB_RECIP_INTERFACE,
0, us->ifnum,
cmd, us->fixedlength, HZ*5);
US_DEBUGP("Next usb_control_msg returns %d\n", result);
@@ -378,7 +378,7 @@ static int pop_CB_command(Scsi_Cmnd *srb)
}
} else { /* !US_FL_FIXED_COMMAND */
result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
- US_CBI_ADSC, USB_TYPE_CLASS | USB_RT_INTERFACE,
+ US_CBI_ADSC, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
0, us->ifnum,
srb->cmnd, srb->cmd_len, HZ*5);
}
@@ -411,7 +411,7 @@ static int pop_CB_status(Scsi_Cmnd *srb)
while (retry--) {
result = usb_control_msg(us->pusb_dev, usb_rcvctrlpipe(us->pusb_dev,0),
USB_REQ_GET_STATUS, USB_DIR_IN |
- USB_TYPE_STANDARD | USB_RT_DEVICE,
+ USB_TYPE_STANDARD | USB_RECIP_DEVICE,
0, us->ifnum, status, sizeof(status), HZ*5);
if (result != USB_ST_TIMEOUT)
break;
@@ -517,7 +517,7 @@ static int pop_Bulk_reset(struct us_data *us)
int result;
result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
- US_BULK_RESET, USB_TYPE_CLASS | USB_RT_INTERFACE,
+ US_BULK_RESET, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
US_BULK_RESET_HARD, us->ifnum,
NULL, 0, HZ*5);
if (result)
@@ -770,24 +770,24 @@ int usb_stor_proc_info (char *buffer, char **start, off_t offset,
SPRINTF ("Host scsi%d: usb-scsi\n", hostno);
/* print product and vendor strings */
- if (!us->pusb_dev) {
+ tmp_ptr = kmalloc(256, GFP_KERNEL);
+ if (!us->pusb_dev || !tmp_ptr) {
SPRINTF("Vendor: Unknown Vendor\n");
SPRINTF("Product: Unknown Product\n");
} else {
SPRINTF("Vendor: ");
- tmp_ptr = usb_string(us->pusb_dev, us->pusb_dev->descriptor.iManufacturer);
- if (!tmp_ptr)
- SPRINTF("Unknown Vendor\n");
- else
+ if (usb_string(us->pusb_dev, us->pusb_dev->descriptor.iManufacturer, tmp_ptr, 256) > 0)
SPRINTF("%s\n", tmp_ptr);
+ else
+ SPRINTF("Unknown Vendor\n");
SPRINTF("Product: ");
- tmp_ptr = usb_string(us->pusb_dev, us->pusb_dev->descriptor.iProduct);
- if (!tmp_ptr)
- SPRINTF("Unknown Vendor\n");
- else
+ if (usb_string(us->pusb_dev, us->pusb_dev->descriptor.iProduct, tmp_ptr, 256) > 0)
SPRINTF("%s\n", tmp_ptr);
+ else
+ SPRINTF("Unknown Vendor\n");
}
+ kfree(tmp_ptr);
SPRINTF("Protocol: ");
switch (us->protocol) {
@@ -1196,9 +1196,9 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum)
{
struct usb_interface_descriptor *interface;
int i;
- char *mf; /* manufacturer */
- char *prod; /* product */
- char *serial; /* serial number */
+ char mf[32]; /* manufacturer */
+ char prod[32]; /* product */
+ char serial[32]; /* serial number */
struct us_data *ss = NULL;
unsigned int flags = 0;
GUID(guid); /* Global Unique Identifier */
@@ -1211,9 +1211,9 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum)
/* clear the GUID and fetch the strings */
GUID_CLEAR(guid);
- mf = usb_string(dev, dev->descriptor.iManufacturer);
- prod = usb_string(dev, dev->descriptor.iProduct);
- serial = usb_string(dev, dev->descriptor.iSerialNumber);
+ usb_string(dev, dev->descriptor.iManufacturer, mf, sizeof(mf));
+ usb_string(dev, dev->descriptor.iProduct, prod, sizeof(prod));
+ usb_string(dev, dev->descriptor.iSerialNumber, serial, sizeof(serial));
/* let's examine the device now */
@@ -1234,12 +1234,11 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum)
US_DEBUGP("USB Mass Storage device detected\n");
/* Create a GUID for this device */
- if (dev->descriptor.iSerialNumber &&
- usb_string(dev, dev->descriptor.iSerialNumber) ) {
+ if (dev->descriptor.iSerialNumber && serial[0]) {
/* If we have a serial number, and it's a non-NULL string */
make_guid(guid, dev->descriptor.idVendor,
dev->descriptor.idProduct,
- usb_string(dev, dev->descriptor.iSerialNumber));
+ serial);
} else {
/* We don't have a serial number, so we use 0 */
make_guid(guid, dev->descriptor.idVendor,
diff --git a/drivers/usb/usbdevice_fs.h b/drivers/usb/usbdevice_fs.h
new file mode 100644
index 000000000..a4bd5d154
--- /dev/null
+++ b/drivers/usb/usbdevice_fs.h
@@ -0,0 +1,168 @@
+/*****************************************************************************/
+
+/*
+ * usbdevice_fs.h -- USB device file system.
+ *
+ * Copyright (C) 2000
+ * Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * History:
+ * 0.1 04.01.2000 Created
+ *
+ * $Id: usbdevice_fs.h,v 1.1 2000/01/06 18:40:41 tom Exp $
+ */
+
+/*****************************************************************************/
+
+#ifndef _LINUX_USBDEVICE_FS_H
+#define _LINUX_USBDEVICE_FS_H
+
+/* --------------------------------------------------------------------- */
+
+#define USBDEVICE_SUPER_MAGIC 0x9fa2
+
+/* usbdevfs ioctl codes */
+
+struct usbdevfs_ctrltransfer {
+ __u8 requesttype;
+ __u8 request;
+ __u16 value;
+ __u16 index;
+ __u16 length;
+ __u32 timeout; /* in milliseconds */
+ void *data;
+};
+
+struct usbdevfs_bulktransfer {
+ unsigned int ep;
+ unsigned int len;
+ unsigned int timeout; /* in milliseconds */
+ void *data;
+};
+
+struct usbdevfs_setinterface {
+ unsigned int interface;
+ unsigned int altsetting;
+};
+
+struct usbdevfs_disconnectsignal {
+ unsigned int signr;
+ void *context;
+};
+
+#define USBDEVFS_URB_DISABLE_SPD 1
+#define USBDEVFS_URB_ISO_ASAP 2
+
+#define USBDEVFS_URB_TYPE_ISO 0
+#define USBDEVFS_URB_TYPE_INTERRUPT 1
+#define USBDEVFS_URB_TYPE_CONTROL 2
+#define USBDEVFS_URB_TYPE_BULK 3
+
+struct usbdevfs_iso_packet_desc {
+ unsigned int length;
+ unsigned int actual_length;
+ unsigned int status;
+};
+
+struct usbdevfs_urb {
+ unsigned char type;
+ unsigned char endpoint;
+ int status;
+ unsigned int flags;
+ void *buffer;
+ int buffer_length;
+ int actual_length;
+ int start_frame;
+ int number_of_packets;
+ int error_count;
+ unsigned int signr; /* signal to be sent on error, -1 if none should be sent */
+ void *usercontext;
+ struct usbdevfs_iso_packet_desc iso_frame_desc[0];
+};
+
+#define USBDEVFS_CONTROL _IOWR('U', 0, struct usbdevfs_ctrltransfer)
+#define USBDEVFS_BULK _IOWR('U', 2, struct usbdevfs_bulktransfer)
+#define USBDEVFS_RESETEP _IOR('U', 3, unsigned int)
+#define USBDEVFS_SETINTERFACE _IOR('U', 4, struct usbdevfs_setinterface)
+#define USBDEVFS_SETCONFIGURATION _IOR('U', 5, unsigned int)
+#define USBDEVFS_SUBMITURB _IOR('U', 10, struct usbdevfs_urb)
+#define USBDEVFS_DISCARDURB _IO('U', 11)
+#define USBDEVFS_REAPURB _IOW('U', 12, void *)
+#define USBDEVFS_REAPURBNDELAY _IOW('U', 13, void *)
+#define USBDEVFS_DISCSIGNAL _IOR('U', 14, struct usbdevfs_disconnectsignal)
+#define USBDEVFS_CLAIMINTERFACE _IOR('U', 15, unsigned int)
+#define USBDEVFS_RELEASEINTERFACE _IOR('U', 16, unsigned int)
+
+/* --------------------------------------------------------------------- */
+
+#ifdef __KERNEL__
+
+#include <linux/config.h>
+#include <linux/list.h>
+#include <asm/semaphore.h>
+
+/*
+ * inode number macros
+ */
+#define ITYPE(x) ((x)&(0xf<<28))
+#define ISPECIAL (0<<28)
+#define IBUS (1<<28)
+#define IDEVICE (2<<28)
+#define IBUSNR(x) (((x)>>8)&0xff)
+#define IDEVNR(x) ((x)&0xff)
+
+#define IROOT 1
+
+/*
+ * sigh. rwsemaphores do not (yet) work from modules
+ */
+
+#define rw_semaphore semaphore
+#define init_rwsem init_MUTEX
+#define down_read down
+#define down_write down
+#define up_read up
+#define up_write up
+
+
+struct dev_state {
+ struct list_head list; /* state list */
+ struct rw_semaphore devsem; /* protects modifications to dev (dev == NULL indicating disconnect) */
+ struct usb_device *dev;
+ struct file *file;
+ spinlock_t lock; /* protects the async urb lists */
+ struct list_head async_pending;
+ struct list_head async_completed;
+ wait_queue_head_t wait; /* wake up if a request completed */
+ unsigned int discsignr;
+ struct task_struct *disctask;
+ void *disccontext;
+ unsigned long ifclaimed;
+};
+
+/* internal methods & data */
+extern struct usb_driver usbdevfs_driver;
+extern struct file_operations usbdevfs_drivers_fops;
+extern struct file_operations usbdevfs_devices_fops;
+extern struct inode_operations usbdevfs_device_inode_operations;
+extern void usbdevfs_conn_disc_event(void);
+
+
+#endif /* __KERNEL__ */
+
+/* --------------------------------------------------------------------- */
+#endif /* _LINUX_USBDEVICE_FS_H */
diff --git a/drivers/usb/usbkbd.c b/drivers/usb/usbkbd.c
index c85ac5fec..26de45a38 100644
--- a/drivers/usb/usbkbd.c
+++ b/drivers/usb/usbkbd.c
@@ -99,19 +99,28 @@ int usb_kbd_event(struct input_dev *dev, unsigned int type, unsigned int code, i
if (type != EV_LED) return -1;
+ if (kbd->led.status == -EINPROGRESS) {
+ warn("had to kill led urb");
+ usb_unlink_urb(&kbd->led);
+ }
+
kbd->leds = (!!test_bit(LED_KANA, dev->led) << 3) | (!!test_bit(LED_COMPOSE, dev->led) << 3) |
(!!test_bit(LED_SCROLLL, dev->led) << 2) | (!!test_bit(LED_CAPSL, dev->led) << 1) |
(!!test_bit(LED_NUML, dev->led));
-
- usb_submit_urb(&kbd->led);
- return -1;
+
+ if (usb_submit_urb(&kbd->led)) {
+ err("usb_submit_urb(leds) failed");
+ return -1;
+ }
+
+ return 0;
}
static void usb_kbd_led(struct urb *urb)
{
if (urb->status)
- printk(KERN_DEBUG "nonzero control status received: %d\n", urb->status);
+ warn("led urb status %d received", urb->status);
}
static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum)
@@ -148,12 +157,6 @@ static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum)
kbd->dev.private = kbd;
kbd->dev.event = usb_kbd_event;
- kbd->dr.requesttype = USB_RT_HIDD;
- kbd->dr.request = USB_REQ_SET_REPORT;
- kbd->dr.value = 0x200;
- kbd->dr.index = 1;
- kbd->dr.length = 1;
-
{
int pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
int maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
@@ -162,7 +165,13 @@ static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum)
usb_kbd_irq, kbd, endpoint->bInterval);
}
- FILL_CONTROL_URB(&kbd->led, dev, usb_sndctrlpipe(dev, endpoint->bEndpointAddress),
+ kbd->dr.requesttype = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+ kbd->dr.request = USB_REQ_SET_REPORT;
+ kbd->dr.value = 0x200;
+ kbd->dr.index = interface->bInterfaceNumber;
+ kbd->dr.length = 1;
+
+ FILL_CONTROL_URB(&kbd->led, dev, usb_sndctrlpipe(dev, 0),
(void*) &kbd->dr, &kbd->leds, 1, usb_kbd_led, kbd);
if (usb_submit_urb(&kbd->irq)) {
diff --git a/drivers/usb/whiteheat.h b/drivers/usb/whiteheat.h
new file mode 100644
index 000000000..d7053e337
--- /dev/null
+++ b/drivers/usb/whiteheat.h
@@ -0,0 +1,1542 @@
+/*****************************************************************************
+ *
+ * whiteheat.h -- ConnectTech WhiteHEAT Firmware.
+ *
+ * Copyright (C) 2000 ConnectTech Inc (http://www.connecttech.com/)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * (01/16/2000) gkh
+ * Fixed my intel hex processing tool, so now the firmware actually
+ * matches the original file (this was causing a few problems...)
+ *
+ * (01/15/2000) gkh
+ * Added debug loader firmware if DEBUG is #defined:
+ * Port 1 LED flashes when the vend_ax program is running
+ * Port 2 LED flashes when any SETUP command arrives
+ * Port 3 LED flashes when any valid VENDOR request occurs
+ * Port 4 LED flashes when the EXTERNAL RAM DOWNLOAD request occurs
+ *
+ * version 1.0 (01/09/2000) gkh
+ * Original firmware from ConnectTech massaged a little to be program
+ * readable.
+ *
+ *****************************************************************************/
+
+#define whiteheat_DATE "20000106"
+
+struct whiteheat_hex_record {
+ __u16 address;
+ __u8 data_size;
+ __u8 data[16];
+};
+
+static const struct whiteheat_hex_record whiteheat_firmware[] = {
+{ 0x0000, 3, {0x02, 0x91, 0xc9} },
+{ 0x0003, 3, {0x02, 0x13, 0x12} },
+{ 0x000b, 3, {0x02, 0x0a, 0x8d} },
+{ 0x0033, 3, {0x02, 0x07, 0x84} },
+{ 0x0043, 3, {0x02, 0x09, 0x00} },
+{ 0x0053, 3, {0x02, 0x0f, 0x6e} },
+{ 0x005b, 3, {0x02, 0x11, 0xb9} },
+{ 0x0300, 16, {0x90, 0x7f, 0xe9, 0xe0, 0x70, 0x03, 0x02, 0x04, 0x03, 0x14, 0x70, 0x03, 0x02, 0x04, 0x77, 0x24} },
+{ 0x0310, 16, {0xfe, 0x70, 0x03, 0x02, 0x04, 0xca, 0x24, 0xfb, 0x70, 0x03, 0x02, 0x03, 0xf4, 0x14, 0x70, 0x03} },
+{ 0x0320, 16, {0x02, 0x03, 0xe2, 0x14, 0x70, 0x03, 0x02, 0x03, 0xca, 0x14, 0x70, 0x03, 0x02, 0x03, 0xd9, 0x24} },
+{ 0x0330, 16, {0x05, 0x60, 0x03, 0x02, 0x05, 0x19, 0x90, 0x7f, 0xeb, 0xe0, 0x24, 0xfe, 0x60, 0x16, 0x14, 0x60} },
+{ 0x0340, 16, {0x36, 0x24, 0x02, 0x70, 0x7b, 0x74, 0x12, 0x90, 0x7f, 0xd4, 0xf0, 0x74, 0x00, 0x90, 0x7f, 0xd5} },
+{ 0x0350, 16, {0xf0, 0x02, 0x05, 0x20, 0x90, 0x7f, 0xea, 0xe0, 0xff, 0x12, 0x09, 0x58, 0xea, 0x49, 0x60, 0x0d} },
+{ 0x0360, 16, {0xea, 0x90, 0x7f, 0xd4, 0xf0, 0xe9, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x05, 0x20, 0x90, 0x7f, 0xb4} },
+{ 0x0370, 16, {0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0x20, 0x90, 0x7f, 0xea, 0xe0, 0xff, 0x12, 0x08, 0xa9, 0xea} },
+{ 0x0380, 16, {0x49, 0x60, 0x33, 0x12, 0x9a, 0x48, 0xf5, 0x5e, 0x90, 0x7f, 0xee, 0xe0, 0xff, 0xe5, 0x5e, 0xd3} },
+{ 0x0390, 16, {0x9f, 0x40, 0x03, 0xe0, 0xf5, 0x5e, 0xe5, 0x5e, 0xd3, 0x94, 0x40, 0x40, 0x03, 0x75, 0x5e, 0x40} },
+{ 0x03a0, 16, {0xae, 0x02, 0xaf, 0x01, 0x7c, 0x7f, 0x7d, 0x00, 0xab, 0x5e, 0x12, 0x1b, 0x0c, 0x90, 0x7f, 0xb5} },
+{ 0x03b0, 16, {0xe5, 0x5e, 0xf0, 0x02, 0x05, 0x20, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0x20} },
+{ 0x03c0, 16, {0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0x20, 0x90, 0x7f, 0x00, 0xe5, 0x21, 0xf0} },
+{ 0x03d0, 16, {0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x02, 0x05, 0x20, 0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x21, 0x02} },
+{ 0x03e0, 16, {0x05, 0x20, 0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x31, 0xd2, 0x02, 0x43, 0x88, 0x10, 0xd2, 0xeb, 0xd2} },
+{ 0x03f0, 16, {0xa8, 0x02, 0x05, 0x20, 0x90, 0x7f, 0x00, 0xe5, 0x31, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0} },
+{ 0x0400, 16, {0x02, 0x05, 0x20, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0x7f, 0x60, 0x24, 0x14, 0x60, 0x31, 0x24, 0x02} },
+{ 0x0410, 16, {0x70, 0x5b, 0xa2, 0x00, 0xe4, 0x33, 0xff, 0x25, 0xe0, 0xff, 0xa2, 0x05, 0xe4, 0x33, 0x4f, 0x90} },
+{ 0x0420, 16, {0x7f, 0x00, 0xf0, 0xe4, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0x20, 0xe4} },
+{ 0x0430, 16, {0x90, 0x7f, 0x00, 0xf0, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0x20, 0x90} },
+{ 0x0440, 16, {0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25} },
+{ 0x0450, 16, {0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe0, 0x54, 0x01, 0x90, 0x7f, 0x00} },
+{ 0x0460, 16, {0xf0, 0xe4, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0x20, 0x90, 0x7f, 0xb4} },
+{ 0x0470, 16, {0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0x20, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0xfe, 0x60, 0x1d, 0x24} },
+{ 0x0480, 16, {0x02, 0x60, 0x03, 0x02, 0x05, 0x20, 0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x05, 0xc2, 0x00, 0x02} },
+{ 0x0490, 16, {0x05, 0x20, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0x20, 0x90, 0x7f, 0xea, 0xe0} },
+{ 0x04a0, 16, {0x70, 0x1f, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54} },
+{ 0x04b0, 16, {0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe4, 0xf0, 0x80} },
+{ 0x04c0, 16, {0x5f, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x56, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0xfe} },
+{ 0x04d0, 16, {0x60, 0x18, 0x24, 0x02, 0x70, 0x4a, 0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x04, 0xd2, 0x00, 0x80} },
+{ 0x04e0, 16, {0x3f, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x36, 0x90, 0x7f, 0xea, 0xe0, 0x70, 0x20} },
+{ 0x04f0, 16, {0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f} },
+{ 0x0500, 16, {0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0x74, 0x01, 0xf0, 0x80, 0x10} },
+{ 0x0510, 16, {0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x07, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0} },
+{ 0x0520, 7, {0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0} },
+{ 0x0527, 1, {0x22} },
+{ 0x0528, 16, {0x75, 0x5a, 0xff, 0x75, 0x59, 0xff, 0x75, 0x58, 0x0f, 0x75, 0x57, 0x00, 0xd2, 0x03, 0xc2, 0x06} },
+{ 0x0538, 16, {0xc2, 0x02, 0xc2, 0x00, 0xc2, 0x05, 0xc2, 0x01, 0x90, 0x02, 0x9e, 0x74, 0x19, 0xf0, 0xe4, 0x90} },
+{ 0x0548, 16, {0x01, 0x5b, 0xf0, 0xc2, 0x04, 0x90, 0x01, 0x5e, 0xf0, 0xa3, 0xf0, 0xc2, 0xaf, 0xc2, 0xa8, 0x12} },
+{ 0x0558, 16, {0x0a, 0xfa, 0xe4, 0x90, 0x02, 0x4d, 0xf0, 0x90, 0x01, 0x00, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3} },
+{ 0x0568, 16, {0xf0, 0xa3, 0xf0, 0xa3, 0x74, 0x10, 0xf0, 0xa3, 0x74, 0x01, 0xf0, 0xa3, 0x74, 0x08, 0xf0, 0x7e} },
+{ 0x0578, 16, {0x01, 0x7f, 0x00, 0x12, 0x19, 0xc1, 0x75, 0x5c, 0x12, 0x75, 0x5d, 0x0a, 0x90, 0x01, 0x0b, 0xe0} },
+{ 0x0588, 16, {0xff, 0x05, 0x5d, 0xe5, 0x5d, 0xac, 0x5c, 0x70, 0x02, 0x05, 0x5c, 0x14, 0xf5, 0x82, 0x8c, 0x83} },
+{ 0x0598, 16, {0xef, 0xf0, 0x90, 0x01, 0x0c, 0xe0, 0x44, 0x80, 0xff, 0x05, 0x5d, 0xe5, 0x5d, 0xac, 0x5c, 0x70} },
+{ 0x05a8, 16, {0x02, 0x05, 0x5c, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x90, 0x01, 0x0d, 0xe0, 0xff, 0x05} },
+{ 0x05b8, 16, {0x5d, 0xe5, 0x5d, 0xac, 0x5c, 0x70, 0x02, 0x05, 0x5c, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0} },
+{ 0x05c8, 16, {0x90, 0x01, 0x0e, 0xe0, 0xff, 0x05, 0x5d, 0xe5, 0x5d, 0xac, 0x5c, 0x70, 0x02, 0x05, 0x5c, 0x14} },
+{ 0x05d8, 16, {0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x90, 0x12, 0x0a, 0xe4, 0x93, 0xff, 0x74, 0x01, 0x93, 0x90} },
+{ 0x05e8, 16, {0x01, 0x1c, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0x01, 0x1c, 0xe0, 0xff, 0xa3, 0xe0, 0xfe, 0xef} },
+{ 0x05f8, 16, {0x6e, 0xff, 0x90, 0x01, 0x1c, 0xf0, 0xa3, 0xe0, 0x6f, 0xff, 0xf0, 0x90, 0x01, 0x1c, 0xe0, 0x6f} },
+{ 0x0608, 16, {0xf0, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xe4, 0xfc, 0xfd, 0x75, 0x62, 0x10, 0x75, 0x63, 0x02, 0x75} },
+{ 0x0618, 16, {0x64, 0x12, 0x75, 0x65, 0xac, 0x12, 0x8e, 0x35, 0x75, 0x5c, 0x12, 0x75, 0x5d, 0xb2, 0x90, 0x01} },
+{ 0x0628, 16, {0x0d, 0xe0, 0xff, 0x05, 0x5d, 0xe5, 0x5d, 0xac, 0x5c, 0x70, 0x02, 0x05, 0x5c, 0x14, 0xf5, 0x82} },
+{ 0x0638, 16, {0x8c, 0x83, 0xef, 0xf0, 0x90, 0x01, 0x0e, 0xe0, 0xff, 0x05, 0x5d, 0xe5, 0x5d, 0xac, 0x5c, 0x70} },
+{ 0x0648, 16, {0x02, 0x05, 0x5c, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x90, 0x7f, 0x92, 0xe0, 0xff, 0xc4} },
+{ 0x0658, 16, {0x54, 0x0f, 0x24, 0x41, 0xff, 0x05, 0x5d, 0xe5, 0x5d, 0xac, 0x5c, 0x70, 0x02, 0x05, 0x5c, 0x14} },
+{ 0x0668, 16, {0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x05, 0x5d, 0xe5, 0x5d, 0xae, 0x5c, 0x70, 0x02, 0x05, 0x5c} },
+{ 0x0678, 16, {0x14, 0xf5, 0x82, 0x8e, 0x83, 0xe4, 0xf0, 0x75, 0x82, 0x10, 0x75, 0x83, 0x01, 0xe0, 0xfc, 0xa3} },
+{ 0x0688, 16, {0xe0, 0xfd, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x90, 0x01, 0x18, 0x12, 0x9b, 0xfb, 0x7e, 0x01} },
+{ 0x0698, 16, {0x7f, 0x18, 0x12, 0x84, 0x61, 0x90, 0x01, 0x18, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe} },
+{ 0x06a8, 16, {0xa3, 0xe0, 0xff, 0x75, 0x62, 0x0a, 0x75, 0x63, 0x06, 0x75, 0x64, 0x12, 0x75, 0x65, 0xb8, 0x12} },
+{ 0x06b8, 16, {0x8e, 0x35, 0xd2, 0xe8, 0x43, 0xd8, 0x20, 0x90, 0x7f, 0xab, 0x74, 0xff, 0xf0, 0x53, 0x91, 0xef} },
+{ 0x06c8, 16, {0x90, 0x7f, 0xaf, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xae, 0xe0, 0x44, 0x1f, 0xf0, 0xd2, 0xaf} },
+{ 0x06d8, 16, {0x20, 0x01, 0x2e, 0x20, 0x01, 0x2b, 0xa2, 0x03, 0x92, 0x07, 0x12, 0x09, 0xa7, 0x75, 0x56, 0x50} },
+{ 0x06e8, 16, {0x75, 0x55, 0x6d, 0x75, 0x54, 0x33, 0x75, 0x53, 0x00, 0x20, 0x01, 0xe4, 0x7f, 0xff, 0x7e, 0xff} },
+{ 0x06f8, 16, {0x7d, 0xff, 0x7c, 0xff, 0x78, 0x53, 0x12, 0x9b, 0xe4, 0xec, 0x4d, 0x4e, 0x4f, 0x60, 0xd1, 0x80} },
+{ 0x0708, 16, {0xe8, 0x30, 0x01, 0x05, 0x12, 0x03, 0x00, 0xc2, 0x01, 0x30, 0x06, 0x0d, 0x12, 0x08, 0xfb, 0x50} },
+{ 0x0718, 16, {0x06, 0x12, 0x0a, 0x00, 0x12, 0x09, 0xf4, 0xc2, 0x06, 0x12, 0x90, 0x58, 0x12, 0x98, 0x7d, 0xe4} },
+{ 0x0728, 16, {0xff, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xfe, 0x90, 0x01, 0x5b} },
+{ 0x0738, 16, {0xe0, 0x5e, 0x60, 0x14, 0x74, 0x27, 0x2f, 0xf8, 0xe6, 0xd3, 0x94, 0x0a, 0x40, 0x04, 0x7e, 0x01} },
+{ 0x0748, 16, {0x80, 0x02, 0x7e, 0x00, 0x8e, 0x5b, 0x80, 0x03, 0x75, 0x5b, 0x01, 0x74, 0x68, 0x2f, 0xf5, 0x82} },
+{ 0x0758, 16, {0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe5, 0x5b, 0xf0, 0x0f, 0xbf, 0x04, 0xc5, 0xe5, 0x2b, 0xd3, 0x94} },
+{ 0x0768, 16, {0x0a, 0x40, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0x90, 0x20, 0x6c, 0xef, 0xf0, 0x90, 0x02} },
+{ 0x0778, 11, {0x4d, 0xe0, 0x64, 0x0f, 0x70, 0x8b, 0x12, 0x93, 0x50, 0x80, 0x86} },
+{ 0x0783, 1, {0x22} },
+{ 0x0784, 4, {0x53, 0xd8, 0xef, 0x32} },
+{ 0x0788, 16, {0xe4, 0x90, 0x7f, 0x9c, 0xf0, 0x7f, 0x0a, 0xfe, 0x12, 0x08, 0x92, 0x90, 0x7f, 0x96, 0x74, 0x89} },
+{ 0x0798, 16, {0xf0, 0x90, 0x7f, 0x9c, 0x74, 0xcf, 0xf0, 0x7f, 0xf4, 0x7e, 0x01, 0x12, 0x08, 0x92, 0x90, 0x7f} },
+{ 0x07a8, 16, {0x96, 0xe0, 0x54, 0xfe, 0xf0, 0x7f, 0x0a, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x7f, 0x02, 0x7d, 0xff} },
+{ 0x07b8, 16, {0x12, 0x11, 0x4b, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x02} },
+{ 0x07c8, 16, {0xf0, 0xe0, 0x54, 0x7f, 0xf0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x90, 0x7f, 0x96, 0xe0} },
+{ 0x07d8, 16, {0x44, 0x40, 0xf0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x90, 0x7f, 0x96, 0xe0, 0x54, 0xbf} },
+{ 0x07e8, 16, {0xf0, 0x7f, 0x32, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x40, 0xf0, 0x7f} },
+{ 0x07f8, 7, {0x32, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x22} },
+{ 0x07ff, 16, {0x90, 0x7f, 0x96, 0xe0, 0x54, 0xfd, 0xf0, 0xe0, 0x44, 0x80, 0xf0, 0x7f, 0x0a, 0x7e, 0x00, 0x12} },
+{ 0x080f, 16, {0x08, 0x92, 0x7f, 0x02, 0xe4, 0xfd, 0x12, 0x11, 0x4b, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x08, 0x92} },
+{ 0x081f, 16, {0x90, 0x7f, 0x96, 0xe0, 0x54, 0xbf, 0xf0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x90, 0x7f} },
+{ 0x082f, 16, {0x96, 0xe0, 0x44, 0x04, 0xf0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x90, 0x7f, 0x96, 0xe0} },
+{ 0x083f, 16, {0x54, 0xf7, 0xf0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x01} },
+{ 0x084f, 12, {0xf0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x12, 0x0a, 0x00, 0x22} },
+{ 0x085b, 16, {0x90, 0x11, 0xef, 0xe4, 0x93, 0x70, 0x2f, 0x90, 0x7f, 0x93, 0x74, 0x30, 0xf0, 0x90, 0x7f, 0x94} },
+{ 0x086b, 16, {0x74, 0x3c, 0xf0, 0x90, 0x7f, 0x95, 0x74, 0xc6, 0xf0, 0xe4, 0x90, 0x7f, 0x97, 0xf0, 0x90, 0x7f} },
+{ 0x087b, 16, {0x9d, 0x74, 0x02, 0xf0, 0x90, 0x7f, 0xe2, 0x74, 0x12, 0xf0, 0x12, 0x07, 0x88, 0x75, 0x82, 0xef} },
+{ 0x088b, 7, {0x75, 0x83, 0x11, 0x74, 0xff, 0xf0, 0x22} },
+{ 0x0892, 16, {0x8e, 0x6d, 0x8f, 0x6e, 0xe5, 0x6e, 0x15, 0x6e, 0xae, 0x6d, 0x70, 0x02, 0x15, 0x6d, 0x4e, 0x60} },
+{ 0x08a2, 7, {0x05, 0x12, 0x08, 0xea, 0x80, 0xee, 0x22} },
+{ 0x08a9, 2, {0x8f, 0x5f} },
+{ 0x08ab, 16, {0xe4, 0xf5, 0x60, 0x75, 0x61, 0xff, 0x75, 0x62, 0x12, 0x75, 0x63, 0x6a, 0xab, 0x61, 0xaa, 0x62} },
+{ 0x08bb, 16, {0xa9, 0x63, 0x90, 0x00, 0x01, 0x12, 0x9a, 0x61, 0xb4, 0x03, 0x1d, 0xaf, 0x60, 0x05, 0x60, 0xef} },
+{ 0x08cb, 16, {0xb5, 0x5f, 0x01, 0x22, 0x12, 0x9a, 0x48, 0x7e, 0x00, 0x29, 0xff, 0xee, 0x3a, 0xa9, 0x07, 0x75} },
+{ 0x08db, 14, {0x61, 0xff, 0xf5, 0x62, 0x89, 0x63, 0x80, 0xd4, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} },
+{ 0x08e9, 1, {0x22} },
+{ 0x08ea, 16, {0x74, 0x00, 0xf5, 0x86, 0x90, 0xfd, 0xa5, 0x7c, 0x05, 0xa3, 0xe5, 0x82, 0x45, 0x83, 0x70, 0xf9} },
+{ 0x08fa, 1, {0x22} },
+{ 0x08fb, 5, {0x12, 0x07, 0xff, 0xd3, 0x22} },
+{ 0x0900, 16, {0x02, 0x0b, 0x17, 0x00, 0x02, 0x0b, 0x4a, 0x00, 0x02, 0x0b, 0x2f, 0x00, 0x02, 0x0b, 0x89, 0x00} },
+{ 0x0910, 16, {0x02, 0x0b, 0x73, 0x00, 0x02, 0x09, 0xf9, 0x00, 0x02, 0x09, 0xfa, 0x00, 0x02, 0x09, 0xfb, 0x00} },
+{ 0x0920, 16, {0x02, 0x0b, 0xa4, 0x00, 0x02, 0x0c, 0x78, 0x00, 0x02, 0x0b, 0xd9, 0x00, 0x02, 0x0c, 0xc5, 0x00} },
+{ 0x0930, 16, {0x02, 0x0c, 0x0e, 0x00, 0x02, 0x0d, 0x12, 0x00, 0x02, 0x0c, 0x43, 0x00, 0x02, 0x0d, 0x5f, 0x00} },
+{ 0x0940, 16, {0x02, 0x09, 0xfc, 0x00, 0x02, 0x09, 0xfe, 0x00, 0x02, 0x09, 0xfd, 0x00, 0x02, 0x09, 0xff, 0x00} },
+{ 0x0950, 8, {0x02, 0x0d, 0xac, 0x00, 0x02, 0x0d, 0xc2, 0x00} },
+{ 0x0958, 16, {0xe4, 0xfe, 0x75, 0x61, 0xff, 0x75, 0x62, 0x12, 0x75, 0x63, 0x12, 0xab, 0x61, 0xaa, 0x62, 0xa9} },
+{ 0x0968, 16, {0x63, 0x90, 0x00, 0x01, 0x12, 0x9a, 0x61, 0x64, 0x02, 0x70, 0x2d, 0xad, 0x06, 0x0e, 0xed, 0xb5} },
+{ 0x0978, 16, {0x07, 0x01, 0x22, 0x90, 0x00, 0x02, 0x12, 0x9a, 0xba, 0x85, 0xf0, 0x5f, 0xf5, 0x60, 0x62, 0x5f} },
+{ 0x0988, 16, {0xe5, 0x5f, 0x62, 0x60, 0xe5, 0x60, 0x62, 0x5f, 0x29, 0xfd, 0xe5, 0x5f, 0x3a, 0xa9, 0x05, 0x75} },
+{ 0x0998, 14, {0x61, 0xff, 0xf5, 0x62, 0x89, 0x63, 0x80, 0xc3, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} },
+{ 0x09a6, 1, {0x22} },
+{ 0x09a7, 16, {0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xfb, 0xf0, 0xe0, 0x44, 0x08, 0xf0, 0x30, 0x07, 0x04, 0xe0, 0x44} },
+{ 0x09b7, 16, {0x02, 0xf0, 0x7f, 0xd0, 0x7e, 0x07, 0x12, 0x08, 0x92, 0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xf7, 0xf0} },
+{ 0x09c7, 5, {0xe0, 0x44, 0x04, 0xf0, 0x22} },
+{ 0x09cc, 16, {0x53, 0x8e, 0xf7, 0xe5, 0x89, 0x54, 0xf1, 0x44, 0x01, 0xf5, 0x89, 0x75, 0x8c, 0xb1, 0xd2, 0xa9} },
+{ 0x09dc, 16, {0x75, 0x98, 0x40, 0x75, 0xcb, 0xff, 0x75, 0xca, 0xf3, 0x75, 0xc8, 0x34, 0xe4, 0xff, 0x7f, 0x05} },
+{ 0x09ec, 7, {0x78, 0x27, 0xe4, 0xf6, 0x08, 0xdf, 0xfc} },
+{ 0x09f3, 1, {0x22} },
+{ 0x09f4, 5, {0x12, 0x07, 0x88, 0xd3, 0x22} },
+{ 0x09f9, 1, {0x32} },
+{ 0x09fa, 1, {0x32} },
+{ 0x09fb, 1, {0x32} },
+{ 0x09fc, 1, {0x32} },
+{ 0x09fd, 1, {0x32} },
+{ 0x09fe, 1, {0x32} },
+{ 0x09ff, 1, {0x32} },
+{ 0x0a00, 9, {0x90, 0x7f, 0xd6, 0xe0, 0x44, 0x80, 0xf0, 0x80, 0x74} },
+{ 0x0a7d, 16, {0x43, 0x87, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22} },
+{ 0x0a8d, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x00, 0xc0, 0x00, 0xc0, 0x06, 0xc0} },
+{ 0x0a9d, 1, {0x07} },
+{ 0x0a9e, 16, {0x30, 0x04, 0x16, 0x75, 0x8c, 0xf8, 0x75, 0x8a, 0x30, 0x7f, 0x2f, 0xae, 0x07, 0x1f, 0xee, 0x60} },
+{ 0x0aae, 16, {0x3c, 0x90, 0x20, 0x00, 0x74, 0x55, 0xf0, 0x80, 0xf2, 0x75, 0x8c, 0xb1, 0x7f, 0x27, 0xef, 0xd3} },
+{ 0x0abe, 16, {0x94, 0x2b, 0x50, 0x09, 0xa8, 0x07, 0xe6, 0x60, 0x01, 0x16, 0x0f, 0x80, 0xf1, 0x90, 0x02, 0x9e} },
+{ 0x0ace, 16, {0xe0, 0x60, 0x02, 0x14, 0xf0, 0x90, 0x01, 0x5e, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x0e, 0x90} },
+{ 0x0ade, 13, {0x01, 0x5f, 0xe0, 0x24, 0xff, 0xf0, 0x90, 0x01, 0x5e, 0xe0, 0x34, 0xff, 0xf0} },
+{ 0x0aeb, 15, {0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x00, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0afa, 16, {0xd2, 0x00, 0x75, 0x8e, 0x10, 0xe4, 0x90, 0x7f, 0x92, 0xf0, 0x12, 0x0f, 0x72, 0x12, 0x08, 0x5b} },
+{ 0x0b0a, 13, {0x12, 0x0e, 0x0f, 0x12, 0x8f, 0x06, 0x12, 0x11, 0x9c, 0x12, 0x09, 0xcc, 0x22} },
+{ 0x0b17, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xd2, 0x01, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x01} },
+{ 0x0b27, 8, {0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0b2f, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x90, 0x7f, 0xc4, 0xe4, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f} },
+{ 0x0b3f, 11, {0xab, 0x74, 0x04, 0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0b4a, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x02, 0xf0, 0x90} },
+{ 0x0b5a, 16, {0x7f, 0xd8, 0xe0, 0x70, 0x0d, 0x90, 0x7f, 0xd9, 0xe0, 0x70, 0x07, 0xe5, 0x2b, 0x70, 0x03, 0x75} },
+{ 0x0b6a, 9, {0x2b, 0x14, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0b73, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x10, 0xf0, 0xd0} },
+{ 0x0b83, 6, {0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0b89, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x30, 0x02, 0x02, 0xd2, 0x06, 0x53, 0x91, 0xef, 0x90, 0x7f} },
+{ 0x0b99, 11, {0xab, 0x74, 0x08, 0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0ba4, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xa9, 0x74, 0x02, 0xf0, 0xe5} },
+{ 0x0bb4, 16, {0x30, 0x30, 0xe0, 0x13, 0xe5, 0x3b, 0x30, 0xe0, 0x07, 0x90, 0x20, 0x04, 0xe0, 0x44, 0x01, 0xf0} },
+{ 0x0bc4, 16, {0x90, 0x20, 0x01, 0xe0, 0x44, 0x01, 0xf0, 0xe5, 0x2b, 0x70, 0x03, 0x75, 0x2b, 0x14, 0xd0, 0x82} },
+{ 0x0bd4, 5, {0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0bd9, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xa9, 0x74, 0x04, 0xf0, 0xe5} },
+{ 0x0be9, 16, {0x30, 0x30, 0xe1, 0x13, 0xe5, 0x3b, 0x30, 0xe1, 0x07, 0x90, 0x20, 0x0c, 0xe0, 0x44, 0x01, 0xf0} },
+{ 0x0bf9, 16, {0x90, 0x20, 0x09, 0xe0, 0x44, 0x01, 0xf0, 0xe5, 0x2b, 0x70, 0x03, 0x75, 0x2b, 0x14, 0xd0, 0x82} },
+{ 0x0c09, 5, {0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0c0e, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xa9, 0x74, 0x08, 0xf0, 0xe5} },
+{ 0x0c1e, 16, {0x30, 0x30, 0xe2, 0x13, 0xe5, 0x3b, 0x30, 0xe2, 0x07, 0x90, 0x20, 0x14, 0xe0, 0x44, 0x01, 0xf0} },
+{ 0x0c2e, 16, {0x90, 0x20, 0x11, 0xe0, 0x44, 0x01, 0xf0, 0xe5, 0x2b, 0x70, 0x03, 0x75, 0x2b, 0x14, 0xd0, 0x82} },
+{ 0x0c3e, 5, {0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0c43, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xa9, 0x74, 0x10, 0xf0, 0xe5} },
+{ 0x0c53, 16, {0x30, 0x30, 0xe3, 0x13, 0xe5, 0x3b, 0x30, 0xe3, 0x07, 0x90, 0x20, 0x1c, 0xe0, 0x44, 0x01, 0xf0} },
+{ 0x0c63, 16, {0x90, 0x20, 0x19, 0xe0, 0x44, 0x01, 0xf0, 0xe5, 0x2b, 0x70, 0x03, 0x75, 0x2b, 0x14, 0xd0, 0x82} },
+{ 0x0c73, 5, {0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0c78, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x53} },
+{ 0x0c88, 16, {0x91, 0xef, 0x90, 0x7f, 0xaa, 0x74, 0x02, 0xf0, 0xe5, 0x30, 0x20, 0xe0, 0x06, 0x90, 0x7f, 0xc7} },
+{ 0x0c98, 16, {0xf0, 0x80, 0x16, 0xe5, 0x3b, 0x30, 0xe0, 0x0a, 0x90, 0x7f, 0xc7, 0xe0, 0x90, 0x02, 0x96, 0xf0} },
+{ 0x0ca8, 16, {0x80, 0x07, 0x90, 0x20, 0x01, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x2b, 0x70, 0x03, 0x75, 0x2b, 0x14} },
+{ 0x0cb8, 13, {0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0cc5, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x53} },
+{ 0x0cd5, 16, {0x91, 0xef, 0x90, 0x7f, 0xaa, 0x74, 0x04, 0xf0, 0xe5, 0x30, 0x20, 0xe1, 0x06, 0x90, 0x7f, 0xc9} },
+{ 0x0ce5, 16, {0xf0, 0x80, 0x16, 0xe5, 0x3b, 0x30, 0xe1, 0x0a, 0x90, 0x7f, 0xc9, 0xe0, 0x90, 0x02, 0x97, 0xf0} },
+{ 0x0cf5, 16, {0x80, 0x07, 0x90, 0x20, 0x09, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x2b, 0x70, 0x03, 0x75, 0x2b, 0x14} },
+{ 0x0d05, 13, {0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0d12, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x53} },
+{ 0x0d22, 16, {0x91, 0xef, 0x90, 0x7f, 0xaa, 0x74, 0x08, 0xf0, 0xe5, 0x30, 0x20, 0xe2, 0x06, 0x90, 0x7f, 0xcb} },
+{ 0x0d32, 16, {0xf0, 0x80, 0x16, 0xe5, 0x3b, 0x30, 0xe2, 0x0a, 0x90, 0x7f, 0xcb, 0xe0, 0x90, 0x02, 0x98, 0xf0} },
+{ 0x0d42, 16, {0x80, 0x07, 0x90, 0x20, 0x11, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x2b, 0x70, 0x03, 0x75, 0x2b, 0x14} },
+{ 0x0d52, 13, {0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0d5f, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x53} },
+{ 0x0d6f, 16, {0x91, 0xef, 0x90, 0x7f, 0xaa, 0x74, 0x10, 0xf0, 0xe5, 0x30, 0x20, 0xe3, 0x06, 0x90, 0x7f, 0xcd} },
+{ 0x0d7f, 16, {0xf0, 0x80, 0x16, 0xe5, 0x3b, 0x30, 0xe3, 0x0a, 0x90, 0x7f, 0xcd, 0xe0, 0x90, 0x02, 0x99, 0xf0} },
+{ 0x0d8f, 16, {0x80, 0x07, 0x90, 0x20, 0x19, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x2b, 0x70, 0x03, 0x75, 0x2b, 0x14} },
+{ 0x0d9f, 13, {0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0dac, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xa9, 0x74, 0x80, 0xf0, 0xd0} },
+{ 0x0dbc, 6, {0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0dc2, 16, {0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x00, 0xc0, 0x00, 0xc0} },
+{ 0x0dd2, 16, {0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0x53, 0x91, 0xef} },
+{ 0x0de2, 16, {0x90, 0x7f, 0xaa, 0x74, 0x80, 0xf0, 0x7e, 0x7b, 0x7f, 0x40, 0x12, 0x8c, 0xfb, 0x90, 0x7f, 0xd3} },
+{ 0x0df2, 16, {0xe4, 0xf0, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01} },
+{ 0x0e02, 13, {0xd0, 0x00, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32} },
+{ 0x0e0f, 16, {0x90, 0x01, 0x20, 0x12, 0x9c, 0x07, 0x00, 0x00, 0x25, 0x80, 0x90, 0x01, 0x24, 0x74, 0x08, 0xf0} },
+{ 0x0e1f, 16, {0xa3, 0x74, 0x01, 0xf0, 0xa3, 0x74, 0x6e, 0xf0, 0xa3, 0xf0, 0xe4, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3} },
+{ 0x0e2f, 16, {0xf0, 0xa3, 0xf0, 0x90, 0x01, 0x1e, 0xf0, 0x90, 0x01, 0x1e, 0xe0, 0xff, 0xc3, 0x94, 0x04, 0x50} },
+{ 0x0e3f, 16, {0x13, 0xef, 0x04, 0xa3, 0xf0, 0x7e, 0x01, 0x7f, 0x1f, 0x12, 0x84, 0xf4, 0x90, 0x01, 0x1e, 0xe0} },
+{ 0x0e4f, 16, {0x04, 0xf0, 0x80, 0xe3, 0xe4, 0xf5, 0x26, 0x90, 0x01, 0x1e, 0xf0, 0x90, 0x01, 0x1e, 0xe0, 0xff} },
+{ 0x0e5f, 16, {0xc3, 0x94, 0x04, 0x50, 0x1a, 0x74, 0x96, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe4} },
+{ 0x0e6f, 16, {0xf0, 0x74, 0x22, 0x2f, 0xf8, 0xe4, 0xf6, 0x90, 0x01, 0x1e, 0xe0, 0x04, 0xf0, 0x80, 0xdc, 0xe4} },
+{ 0x0e7f, 16, {0xf5, 0x30, 0xe5, 0xc0, 0x60, 0x2f, 0x90, 0x01, 0x1e, 0x74, 0x01, 0xf0, 0x90, 0x01, 0x1e, 0xe0} },
+{ 0x0e8f, 16, {0xff, 0xd3, 0x94, 0x04, 0x50, 0x1f, 0xef, 0x14, 0xff, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02} },
+{ 0x0e9f, 16, {0xc3, 0x33, 0xd8, 0xfc, 0x42, 0x30, 0x7e, 0x01, 0x7f, 0x1e, 0x12, 0x82, 0xea, 0x90, 0x01, 0x1e} },
+{ 0x0eaf, 16, {0xe0, 0x04, 0xf0, 0x80, 0xd7, 0xe4, 0xf5, 0x3a, 0x90, 0x01, 0x1e, 0xf0, 0x90, 0x01, 0x1e, 0xe0} },
+{ 0x0ebf, 16, {0xff, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0, 0x54} },
+{ 0x0ecf, 16, {0xf0, 0xfe, 0x74, 0x63, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x01, 0xf5, 0x83, 0xee, 0xf0, 0x74, 0x36} },
+{ 0x0edf, 16, {0x2f, 0xf8, 0xa6, 0x06, 0x74, 0x32, 0x2f, 0xf8, 0xe4, 0xf6, 0x74, 0x2c, 0x2f, 0xf8, 0xe4, 0xf6} },
+{ 0x0eef, 16, {0x74, 0x9a, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe4, 0xf0, 0x90, 0x01, 0x1e, 0xe0} },
+{ 0x0eff, 16, {0x04, 0xf0, 0xe0, 0xb4, 0x04, 0xb6, 0x90, 0x20, 0x60, 0xe0, 0x54, 0x0f, 0xf5, 0x5e, 0x60, 0x5e} },
+{ 0x0f0f, 16, {0xe4, 0x90, 0x01, 0x1e, 0xf0, 0x90, 0x01, 0x1e, 0xe0, 0xff, 0xc3, 0x94, 0x04, 0x50, 0xe7, 0x74} },
+{ 0x0f1f, 16, {0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x55, 0x5e, 0x60, 0x38, 0x90, 0x01} },
+{ 0x0f2f, 1, {0x1e} },
+{ 0x0f30, 16, {0xe0, 0xff, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x02, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0} },
+{ 0x0f40, 16, {0xfe, 0xef, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0} },
+{ 0x0f50, 16, {0xef, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0, 0xfe} },
+{ 0x0f60, 14, {0x7d, 0x06, 0x12, 0x82, 0x60, 0x90, 0x01, 0x1e, 0xe0, 0x04, 0xf0, 0x80, 0xa7, 0x22} },
+{ 0x0f6e, 4, {0x53, 0x91, 0xbf, 0x32} },
+{ 0x0f72, 16, {0x7b, 0xff, 0x7a, 0x12, 0x79, 0x1b, 0x90, 0x00, 0x04, 0x12, 0x9a, 0x61, 0xfd, 0x8b, 0x60, 0x75} },
+{ 0x0f82, 16, {0x61, 0x12, 0x75, 0x62, 0x24, 0xe4, 0x90, 0x7f, 0xe1, 0xf0, 0x90, 0x7f, 0xe0, 0xf0, 0xf5, 0x5e} },
+{ 0x0f92, 16, {0xf5, 0x5f, 0x90, 0x02, 0x4c, 0xf0, 0x90, 0x7f, 0xdf, 0xf0, 0x90, 0x7f, 0xde, 0xf0, 0x90, 0x7f} },
+{ 0x0fa2, 16, {0xa9, 0x74, 0xff, 0xf0, 0x90, 0x7f, 0xaa, 0xf0, 0xe4, 0xfc, 0xec, 0x25, 0xe0, 0x24, 0xb4, 0xf5} },
+{ 0x0fb2, 16, {0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe4, 0xf0, 0x0c, 0xbc, 0x10, 0xee, 0xe4, 0x90, 0x7f, 0xdd} },
+{ 0x0fc2, 16, {0xf0, 0xaf, 0x05, 0x1d, 0xef, 0x70, 0x03, 0x02, 0x11, 0x38, 0xab, 0x60, 0xaa, 0x61, 0xa9, 0x62} },
+{ 0x0fd2, 16, {0x90, 0x00, 0x01, 0x12, 0x9a, 0x61, 0x64, 0x05, 0x60, 0x03, 0x02, 0x11, 0x27, 0x90, 0x00, 0x03} },
+{ 0x0fe2, 16, {0x12, 0x9a, 0x61, 0x64, 0x01, 0x60, 0x03, 0x02, 0x10, 0xae, 0x90, 0x00, 0x02, 0x12, 0x9a, 0x61} },
+{ 0x0ff2, 16, {0xff, 0x54, 0x7f, 0xfc, 0xd3, 0x94, 0x07, 0x50, 0x03, 0x02, 0x10, 0x88, 0xec, 0xc3, 0x94, 0x10} },
+{ 0x1002, 16, {0x40, 0x03, 0x02, 0x10, 0x88, 0xef, 0x30, 0xe7, 0x42, 0xe5, 0x5f, 0xae, 0x5e, 0x78, 0x02, 0xce} },
+{ 0x1012, 16, {0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xff, 0x74, 0xf0, 0x2c, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5} },
+{ 0x1022, 16, {0x83, 0xef, 0xf0, 0x90, 0x7f, 0xe0, 0xe0, 0xff, 0xec, 0x24, 0xf8, 0xfe, 0x74, 0x01, 0xa8, 0x06} },
+{ 0x1032, 16, {0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x4f, 0x90, 0x7f, 0xe0, 0xf0, 0x90, 0x02, 0x4c, 0xe0} },
+{ 0x1042, 16, {0x04, 0xf0, 0x90, 0x7f, 0xdd, 0xe0, 0x44, 0x80, 0xf0, 0x80, 0x3e, 0xe5, 0x5f, 0xae, 0x5e, 0x78} },
+{ 0x1052, 16, {0x02, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xff, 0x74, 0xe8, 0x2c, 0xf5, 0x82, 0xe4, 0x34} },
+{ 0x1062, 16, {0x7f, 0xf5, 0x83, 0xef, 0xf0, 0x90, 0x7f, 0xe1, 0xe0, 0xff, 0xec, 0x24, 0xf8, 0xfe, 0x74, 0x01} },
+{ 0x1072, 16, {0xa8, 0x06, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x4f, 0x90, 0x7f, 0xe1, 0xf0, 0x90, 0x02} },
+{ 0x1082, 16, {0x4c, 0xe0, 0x04, 0xf0, 0x80, 0x03, 0x7f, 0xff, 0x22, 0x90, 0x00, 0x04, 0x12, 0x9a, 0x61, 0x25} },
+{ 0x1092, 16, {0x5f, 0xf5, 0x5f, 0xe4, 0x35, 0x5e, 0xf5, 0x5e, 0x90, 0x00, 0x05, 0x12, 0x9a, 0x61, 0xfe, 0xe4} },
+{ 0x10a2, 16, {0x25, 0x5f, 0xf5, 0x5f, 0xee, 0x35, 0x5e, 0xf5, 0x5e, 0x02, 0x11, 0x2a, 0xab, 0x60, 0xaa, 0x61} },
+{ 0x10b2, 16, {0xa9, 0x62, 0x90, 0x00, 0x03, 0x12, 0x9a, 0x61, 0xff, 0x64, 0x02, 0x60, 0x05, 0xef, 0x64, 0x03} },
+{ 0x10c2, 16, {0x70, 0x60, 0x90, 0x00, 0x02, 0x12, 0x9a, 0x61, 0xff, 0x54, 0x7f, 0xfc, 0xd3, 0x94, 0x07, 0x50} },
+{ 0x10d2, 16, {0x4e, 0xef, 0x30, 0xe7, 0x1e, 0x90, 0x7f, 0xde, 0xe0, 0xff, 0x74, 0x01, 0xa8, 0x04, 0x08, 0x80} },
+{ 0x10e2, 16, {0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xfe, 0x4f, 0x90, 0x7f, 0xde, 0xf0, 0x90, 0x7f, 0xac, 0xe0, 0x4e} },
+{ 0x10f2, 16, {0xf0, 0x80, 0x35, 0x90, 0x7f, 0xdf, 0xe0, 0xff, 0x74, 0x01, 0xa8, 0x04, 0x08, 0x80, 0x02, 0xc3} },
+{ 0x1102, 16, {0x33, 0xd8, 0xfc, 0xfe, 0x4f, 0x90, 0x7f, 0xdf, 0xf0, 0x90, 0x7f, 0xad, 0xe0, 0x4e, 0xf0, 0xec} },
+{ 0x1112, 16, {0x25, 0xe0, 0x24, 0xc5, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xec, 0xf0, 0x80, 0x09, 0x7f} },
+{ 0x1122, 16, {0xff, 0x22, 0x7f, 0xff, 0x22, 0x7f, 0xff, 0x22, 0x74, 0x07, 0x25, 0x62, 0xf5, 0x62, 0xe4, 0x35} },
+{ 0x1132, 16, {0x61, 0xf5, 0x61, 0x02, 0x0f, 0xc3, 0x20, 0x03, 0x0d, 0x90, 0x02, 0x4c, 0xe0, 0x60, 0x07, 0x90} },
+{ 0x1142, 8, {0x7f, 0xae, 0xe0, 0x44, 0x02, 0xf0, 0x7f, 0x00} },
+{ 0x114a, 1, {0x22} },
+{ 0x114b, 2, {0xae, 0x07} },
+{ 0x114d, 16, {0x7c, 0x02, 0xec, 0x14, 0x60, 0x15, 0x14, 0x70, 0x1e, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0} },
+{ 0x115d, 16, {0xee, 0x25, 0xe0, 0x44, 0x40, 0x90, 0x7f, 0xa6, 0xf0, 0x80, 0x0c, 0x90, 0x7f, 0xa6, 0xed, 0xf0} },
+{ 0x116d, 16, {0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x90, 0x7f, 0xa5, 0xe0, 0xfb, 0x30, 0xe0, 0xf8, 0xbc} },
+{ 0x117d, 16, {0x02, 0x0a, 0x20, 0xe1, 0x07, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x07, 0x22, 0xeb, 0x30, 0xe2, 0x0a} },
+{ 0x118d, 14, {0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x06, 0x22, 0xdc, 0xb6, 0x7f, 0x08} },
+{ 0x119b, 1, {0x22} },
+{ 0x119c, 16, {0x7f, 0x05, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x7f, 0x02, 0x7d, 0xff, 0x12, 0x11, 0x4b, 0x7f, 0x05} },
+{ 0x11ac, 13, {0x7e, 0x00, 0x12, 0x08, 0x92, 0x7f, 0x03, 0x7d, 0xff, 0x12, 0x11, 0x4b, 0x22} },
+{ 0x11b9, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc2, 0xa9, 0x90, 0x02, 0x9e, 0x74, 0x19, 0xf0, 0xd2, 0xa9} },
+{ 0x11c9, 15, {0x53, 0x91, 0x7f, 0x90, 0x01, 0x62, 0xe4, 0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x11d8, 16, {0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x14, 0xff, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33} },
+{ 0x11e8, 7, {0xd8, 0xfc, 0x42, 0x3a, 0x7f, 0x00, 0x22} },
+{ 0x11ef, 3, {0x00, 0x02, 0x28} },
+{ 0x1200, 16, {0x12, 0x01, 0x00, 0x01, 0xff, 0xff, 0xff, 0x40, 0x10, 0x07, 0x01, 0x80, 0x42, 0x00, 0x01, 0x02} },
+{ 0x1210, 16, {0x03, 0x01, 0x09, 0x02, 0x58, 0x00, 0x01, 0x01, 0x04, 0x80, 0x3c, 0x09, 0x04, 0x00, 0x00, 0x0a} },
+{ 0x1220, 16, {0xff, 0xff, 0xff, 0x05, 0x07, 0x05, 0x81, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x01, 0x02, 0x40} },
+{ 0x1230, 16, {0x00, 0x00, 0x07, 0x05, 0x82, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x02, 0x02, 0x40, 0x00, 0x00} },
+{ 0x1240, 16, {0x07, 0x05, 0x83, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x03, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05} },
+{ 0x1250, 16, {0x84, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x04, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x87, 0x02} },
+{ 0x1260, 16, {0x40, 0x00, 0x00, 0x07, 0x05, 0x07, 0x02, 0x40, 0x00, 0x00, 0x04, 0x03, 0x09, 0x04, 0x24, 0x03} },
+{ 0x1270, 16, {0x43, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x20, 0x00} },
+{ 0x1280, 16, {0x54, 0x00, 0x65, 0x00, 0x63, 0x00, 0x68, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x63, 0x00} },
+{ 0x1290, 16, {0x2e, 0x00, 0x18, 0x03, 0x57, 0x00, 0x68, 0x00, 0x69, 0x00, 0x74, 0x00, 0x65, 0x00, 0x48, 0x00} },
+{ 0x12a0, 16, {0x45, 0x00, 0x41, 0x00, 0x54, 0x00, 0x2d, 0x00, 0x34, 0x00, 0x1a, 0x03, 0x58, 0x00, 0x58, 0x00} },
+{ 0x12b0, 16, {0x2d, 0x00, 0x58, 0x00, 0x58, 0x00, 0x2d, 0x00, 0x58, 0x00, 0x58, 0x00, 0x58, 0x00, 0x58, 0x00} },
+{ 0x12c0, 16, {0x58, 0x00, 0x58, 0x00, 0x2a, 0x03, 0x43, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x66, 0x00, 0x69, 0x00} },
+{ 0x12d0, 16, {0x67, 0x00, 0x75, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00} },
+{ 0x12e0, 16, {0x20, 0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x22, 0x03} },
+{ 0x12f0, 16, {0x49, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x66, 0x00, 0x61, 0x00, 0x63, 0x00} },
+{ 0x1300, 16, {0x65, 0x00, 0x20, 0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00} },
+{ 0x1310, 2, {0x00, 0x00} },
+{ 0x1312, 16, {0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0xc0, 0xd0} },
+{ 0x1322, 16, {0x75, 0x86, 0x00, 0x75, 0xd0, 0x18, 0x90, 0x20, 0x60, 0xe0, 0x54, 0x0f, 0xf5, 0xf0, 0x70, 0x11} },
+{ 0x1332, 16, {0xd0, 0xd0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0} },
+{ 0x1342, 16, {0x32, 0x75, 0x86, 0x00, 0x10, 0xf0, 0x0b, 0x10, 0xf1, 0x12, 0x10, 0xf2, 0x19, 0x10, 0xf3, 0x20} },
+{ 0x1352, 16, {0x80, 0xd4, 0xe5, 0x27, 0x70, 0x03, 0x75, 0x27, 0x14, 0x02, 0x13, 0x7c, 0xe5, 0x28, 0x70, 0x03} },
+{ 0x1362, 16, {0x75, 0x28, 0x14, 0x02, 0x15, 0x0d, 0xe5, 0x29, 0x70, 0x03, 0x75, 0x29, 0x14, 0x02, 0x16, 0x9e} },
+{ 0x1372, 16, {0xe5, 0x2a, 0x70, 0x03, 0x75, 0x2a, 0x14, 0x02, 0x18, 0x2f, 0x90, 0x20, 0x02, 0xe0, 0x54, 0x3f} },
+{ 0x1382, 16, {0x20, 0xe2, 0x3a, 0x20, 0xe1, 0x0b, 0x20, 0xe4, 0x0b, 0x20, 0xe5, 0x14, 0x60, 0x09, 0x02, 0x13} },
+{ 0x1392, 16, {0x43, 0x02, 0x14, 0x65, 0x02, 0x13, 0x43, 0x43, 0x82, 0x04, 0xe0, 0xf5, 0x36, 0x02, 0x13, 0x43} },
+{ 0x13a2, 16, {0x43, 0x82, 0x04, 0xe0, 0x43, 0x2c, 0x01, 0x02, 0x13, 0x43, 0x53, 0x82, 0xf8, 0x43, 0x82, 0x05} },
+{ 0x13b2, 16, {0xe0, 0x42, 0x32, 0x53, 0x82, 0xfb, 0xe0, 0x54, 0xfb, 0xf0, 0x02, 0x13, 0x43, 0x30, 0xe1, 0x02} },
+{ 0x13c2, 16, {0x80, 0xe8, 0xf5, 0x85, 0xe5, 0x3b, 0x30, 0xe0, 0x0a, 0x53, 0x82, 0xf8, 0x43, 0x82, 0x04, 0xe0} },
+{ 0x13d2, 16, {0x54, 0xfe, 0xf0, 0xe5, 0x85, 0x20, 0xe3, 0x56, 0x90, 0x20, 0x50, 0x74, 0x00, 0xf0, 0x90, 0x20} },
+{ 0x13e2, 16, {0x58, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xe2, 0xe0, 0x44, 0x40, 0xf0, 0x90, 0x7f, 0xe3, 0x05, 0x86} },
+{ 0x13f2, 16, {0x90, 0x7e, 0x80, 0x05, 0x86, 0xe5, 0x85, 0xf0, 0xa3, 0xe5, 0x84, 0xf0, 0x05, 0x86, 0x90, 0x7f} },
+{ 0x1402, 16, {0xe5, 0xe5, 0x3c, 0xfd, 0x03, 0x03, 0x03, 0xfe, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0} },
+{ 0x1412, 16, {0xde, 0xf6, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00, 0xf0, 0x90} },
+{ 0x1422, 16, {0x7f, 0xb7, 0xed, 0xf0, 0x90, 0x20, 0x01, 0xe0, 0x54, 0xfe, 0xf0, 0x02, 0x13, 0x43, 0x7f, 0x40} },
+{ 0x1432, 16, {0x90, 0x7e, 0x80, 0x05, 0x86, 0x90, 0x20, 0x00, 0xe5, 0x84, 0xfe, 0x24, 0x05, 0xfd, 0x8d, 0x84} },
+{ 0x1442, 16, {0xe0, 0x8e, 0x84, 0x30, 0xe0, 0x09, 0xe0, 0x05, 0x86, 0xf0, 0xa3, 0x05, 0x86, 0xdf, 0xef, 0x05} },
+{ 0x1452, 16, {0x86, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0x7f, 0xb7, 0xf0, 0x05, 0x86, 0xa3, 0xe0, 0x54, 0xfe, 0xf0} },
+{ 0x1462, 16, {0x02, 0x13, 0x43, 0x53, 0x2c, 0xfa, 0xe5, 0x22, 0x60, 0x08, 0x75, 0x22, 0x00, 0xd2, 0xe7, 0xfe} },
+{ 0x1472, 16, {0x80, 0x0a, 0x90, 0x7f, 0xc7, 0xe0, 0xfe, 0x70, 0x03, 0x02, 0x14, 0xff, 0x90, 0x20, 0x50, 0x74} },
+{ 0x1482, 16, {0x00, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xe2, 0xe0, 0x44, 0x40, 0xf0, 0x90} },
+{ 0x1492, 16, {0x7f, 0xe3, 0x05, 0x86, 0x90, 0x7e, 0x40, 0x05, 0x86, 0xe5, 0x85, 0xf0, 0xa3, 0xe5, 0x84, 0xf0} },
+{ 0x14a2, 16, {0x05, 0x86, 0x90, 0x7f, 0xe5, 0xee, 0x30, 0xe7, 0x08, 0x05, 0x86, 0xe0, 0x24, 0x38, 0xf0, 0x05} },
+{ 0x14b2, 16, {0x86, 0xee, 0x54, 0x7f, 0xfe, 0x54, 0x07, 0xfb, 0xee, 0x54, 0x78, 0x60, 0x30, 0x03, 0x03, 0x03} },
+{ 0x14c2, 16, {0x30, 0xe3, 0x04, 0x74, 0x07, 0x7b, 0x08, 0xfd, 0xfc, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0} },
+{ 0x14d2, 16, {0xe0, 0xdd, 0xf6, 0xeb, 0xfe, 0x60, 0x19, 0xec, 0x64, 0x07, 0x70, 0x11, 0x8b, 0x22, 0x90, 0x7f} },
+{ 0x14e2, 16, {0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00, 0xf0, 0x80, 0x1b, 0xe0, 0xde, 0xfd} },
+{ 0x14f2, 16, {0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00, 0xf0, 0x90, 0x20, 0x01} },
+{ 0x1502, 16, {0xe0, 0x54, 0xfd, 0xf0, 0x90, 0x7f, 0xc7, 0xf0, 0x02, 0x13, 0x43, 0x90, 0x20, 0x0a, 0xe0, 0x54} },
+{ 0x1512, 16, {0x3f, 0x20, 0xe2, 0x3a, 0x20, 0xe1, 0x0b, 0x20, 0xe4, 0x0b, 0x20, 0xe5, 0x14, 0x60, 0x09, 0x02} },
+{ 0x1522, 16, {0x13, 0x43, 0x02, 0x15, 0xf6, 0x02, 0x13, 0x43, 0x43, 0x82, 0x04, 0xe0, 0xf5, 0x37, 0x02, 0x13} },
+{ 0x1532, 16, {0x43, 0x43, 0x82, 0x04, 0xe0, 0x43, 0x2d, 0x01, 0x02, 0x13, 0x43, 0x53, 0x82, 0xf8, 0x43, 0x82} },
+{ 0x1542, 16, {0x05, 0xe0, 0x42, 0x33, 0x53, 0x82, 0xfb, 0xe0, 0x54, 0xfb, 0xf0, 0x02, 0x13, 0x43, 0x30, 0xe1} },
+{ 0x1552, 16, {0x02, 0x80, 0xe8, 0xf5, 0x85, 0xe5, 0x3b, 0x30, 0xe1, 0x0a, 0x53, 0x82, 0xf8, 0x43, 0x82, 0x04} },
+{ 0x1562, 16, {0xe0, 0x54, 0xfe, 0xf0, 0xe5, 0x85, 0x20, 0xe3, 0x56, 0x90, 0x20, 0x50, 0x74, 0x01, 0xf0, 0x90} },
+{ 0x1572, 16, {0x20, 0x58, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xe2, 0xe0, 0x44, 0x40, 0xf0, 0x90, 0x7f, 0xe3, 0x05} },
+{ 0x1582, 16, {0x86, 0x90, 0x7e, 0x00, 0x05, 0x86, 0xe5, 0x85, 0xf0, 0xa3, 0xe5, 0x84, 0xf0, 0x05, 0x86, 0x90} },
+{ 0x1592, 16, {0x7f, 0xe5, 0xe5, 0x3d, 0xfd, 0x03, 0x03, 0x03, 0xfe, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0} },
+{ 0x15a2, 16, {0xf0, 0xde, 0xf6, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00, 0xf0} },
+{ 0x15b2, 16, {0x90, 0x7f, 0xb9, 0xed, 0xf0, 0x90, 0x20, 0x09, 0xe0, 0x54, 0xfe, 0xf0, 0x02, 0x13, 0x43, 0x7f} },
+{ 0x15c2, 16, {0x40, 0x90, 0x7e, 0x00, 0x05, 0x86, 0x90, 0x20, 0x08, 0xe5, 0x84, 0xfe, 0x24, 0x05, 0xfd, 0x8d} },
+{ 0x15d2, 16, {0x84, 0xe0, 0x8e, 0x84, 0x30, 0xe0, 0x09, 0xe0, 0x05, 0x86, 0xf0, 0xa3, 0x05, 0x86, 0xdf, 0xef} },
+{ 0x15e2, 16, {0x05, 0x86, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0x7f, 0xb9, 0xf0, 0x05, 0x86, 0xa3, 0xe0, 0x54, 0xfe} },
+{ 0x15f2, 16, {0xf0, 0x02, 0x13, 0x43, 0x53, 0x2d, 0xfa, 0xe5, 0x23, 0x60, 0x08, 0x75, 0x23, 0x00, 0xd2, 0xe7} },
+{ 0x1602, 16, {0xfe, 0x80, 0x0a, 0x90, 0x7f, 0xc9, 0xe0, 0xfe, 0x70, 0x03, 0x02, 0x16, 0x90, 0x90, 0x20, 0x50} },
+{ 0x1612, 16, {0x74, 0x01, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xe2, 0xe0, 0x44, 0x40, 0xf0} },
+{ 0x1622, 16, {0x90, 0x7f, 0xe3, 0x05, 0x86, 0x90, 0x7d, 0xc0, 0x05, 0x86, 0xe5, 0x85, 0xf0, 0xa3, 0xe5, 0x84} },
+{ 0x1632, 16, {0xf0, 0x05, 0x86, 0x90, 0x7f, 0xe5, 0xee, 0x30, 0xe7, 0x08, 0x05, 0x86, 0xe0, 0x24, 0x38, 0xf0} },
+{ 0x1642, 16, {0x05, 0x86, 0xee, 0x54, 0x7f, 0xfe, 0x54, 0x07, 0xfb, 0xee, 0x54, 0x78, 0x60, 0x30, 0x03, 0x03} },
+{ 0x1652, 16, {0x03, 0x30, 0xe3, 0x04, 0x74, 0x07, 0x7b, 0x08, 0xfd, 0xfc, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0} },
+{ 0x1662, 16, {0xe0, 0xe0, 0xdd, 0xf6, 0xeb, 0xfe, 0x60, 0x19, 0xec, 0x64, 0x07, 0x70, 0x11, 0x8b, 0x23, 0x90} },
+{ 0x1672, 16, {0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00, 0xf0, 0x80, 0x1b, 0xe0, 0xde} },
+{ 0x1682, 14, {0xfd, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00, 0xf0} },
+{ 0x1690, 16, {0x90, 0x20, 0x09, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0x7f, 0xc9, 0xf0, 0x02, 0x13, 0x43, 0x90, 0x20} },
+{ 0x16a0, 16, {0x12, 0xe0, 0x54, 0x3f, 0x20, 0xe2, 0x3a, 0x20, 0xe1, 0x0b, 0x20, 0xe4, 0x0b, 0x20, 0xe5, 0x14} },
+{ 0x16b0, 16, {0x60, 0x09, 0x02, 0x13, 0x43, 0x02, 0x17, 0x87, 0x02, 0x13, 0x43, 0x43, 0x82, 0x04, 0xe0, 0xf5} },
+{ 0x16c0, 16, {0x38, 0x02, 0x13, 0x43, 0x43, 0x82, 0x04, 0xe0, 0x43, 0x2e, 0x01, 0x02, 0x13, 0x43, 0x53, 0x82} },
+{ 0x16d0, 16, {0xf8, 0x43, 0x82, 0x05, 0xe0, 0x42, 0x34, 0x53, 0x82, 0xfb, 0xe0, 0x54, 0xfb, 0xf0, 0x02, 0x13} },
+{ 0x16e0, 16, {0x43, 0x30, 0xe1, 0x02, 0x80, 0xe8, 0xf5, 0x85, 0xe5, 0x3b, 0x30, 0xe2, 0x0a, 0x53, 0x82, 0xf8} },
+{ 0x16f0, 16, {0x43, 0x82, 0x04, 0xe0, 0x54, 0xfe, 0xf0, 0xe5, 0x85, 0x20, 0xe3, 0x56, 0x90, 0x20, 0x50, 0x74} },
+{ 0x1700, 16, {0x02, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xe2, 0xe0, 0x44, 0x40, 0xf0, 0x90} },
+{ 0x1710, 16, {0x7f, 0xe3, 0x05, 0x86, 0x90, 0x7d, 0x80, 0x05, 0x86, 0xe5, 0x85, 0xf0, 0xa3, 0xe5, 0x84, 0xf0} },
+{ 0x1720, 16, {0x05, 0x86, 0x90, 0x7f, 0xe5, 0xe5, 0x3e, 0xfd, 0x03, 0x03, 0x03, 0xfe, 0xf0, 0xf0, 0xf0, 0xf0} },
+{ 0x1730, 16, {0xf0, 0xf0, 0xf0, 0xf0, 0xde, 0xf6, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58} },
+{ 0x1740, 16, {0x74, 0x00, 0xf0, 0x90, 0x7f, 0xbb, 0xed, 0xf0, 0x90, 0x20, 0x11, 0xe0, 0x54, 0xfe, 0xf0, 0x02} },
+{ 0x1750, 16, {0x13, 0x43, 0x7f, 0x40, 0x90, 0x7d, 0x80, 0x05, 0x86, 0x90, 0x20, 0x10, 0xe5, 0x84, 0xfe, 0x24} },
+{ 0x1760, 16, {0x05, 0xfd, 0x8d, 0x84, 0xe0, 0x8e, 0x84, 0x30, 0xe0, 0x09, 0xe0, 0x05, 0x86, 0xf0, 0xa3, 0x05} },
+{ 0x1770, 16, {0x86, 0xdf, 0xef, 0x05, 0x86, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0x7f, 0xbb, 0xf0, 0x05, 0x86, 0xa3} },
+{ 0x1780, 16, {0xe0, 0x54, 0xfe, 0xf0, 0x02, 0x13, 0x43, 0x53, 0x2e, 0xfa, 0xe5, 0x24, 0x60, 0x08, 0x75, 0x24} },
+{ 0x1790, 16, {0x00, 0xd2, 0xe7, 0xfe, 0x80, 0x0a, 0x90, 0x7f, 0xcb, 0xe0, 0xfe, 0x70, 0x03, 0x02, 0x18, 0x21} },
+{ 0x17a0, 16, {0x90, 0x20, 0x50, 0x74, 0x02, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xe2, 0xe0} },
+{ 0x17b0, 16, {0x44, 0x40, 0xf0, 0x90, 0x7f, 0xe3, 0x05, 0x86, 0x90, 0x7d, 0x40, 0x05, 0x86, 0xe5, 0x85, 0xf0} },
+{ 0x17c0, 16, {0xa3, 0xe5, 0x84, 0xf0, 0x05, 0x86, 0x90, 0x7f, 0xe5, 0xee, 0x30, 0xe7, 0x08, 0x05, 0x86, 0xe0} },
+{ 0x17d0, 16, {0x24, 0x38, 0xf0, 0x05, 0x86, 0xee, 0x54, 0x7f, 0xfe, 0x54, 0x07, 0xfb, 0xee, 0x54, 0x78, 0x60} },
+{ 0x17e0, 16, {0x30, 0x03, 0x03, 0x03, 0x30, 0xe3, 0x04, 0x74, 0x07, 0x7b, 0x08, 0xfd, 0xfc, 0xe0, 0xe0, 0xe0} },
+{ 0x17f0, 16, {0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xdd, 0xf6, 0xeb, 0xfe, 0x60, 0x19, 0xec, 0x64, 0x07, 0x70, 0x11} },
+{ 0x1800, 16, {0x8b, 0x24, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00, 0xf0, 0x80} },
+{ 0x1810, 16, {0x1b, 0xe0, 0xde, 0xfd, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00} },
+{ 0x1820, 16, {0xf0, 0x90, 0x20, 0x11, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0x7f, 0xcb, 0xf0, 0x02, 0x13, 0x43, 0x90} },
+{ 0x1830, 16, {0x20, 0x1a, 0xe0, 0x54, 0x3f, 0x20, 0xe2, 0x3a, 0x20, 0xe1, 0x0b, 0x20, 0xe4, 0x0b, 0x20, 0xe5} },
+{ 0x1840, 16, {0x14, 0x60, 0x09, 0x02, 0x13, 0x43, 0x02, 0x19, 0x18, 0x02, 0x13, 0x43, 0x43, 0x82, 0x04, 0xe0} },
+{ 0x1850, 16, {0xf5, 0x39, 0x02, 0x13, 0x43, 0x43, 0x82, 0x04, 0xe0, 0x43, 0x2f, 0x01, 0x02, 0x13, 0x43, 0x53} },
+{ 0x1860, 16, {0x82, 0xf8, 0x43, 0x82, 0x05, 0xe0, 0x42, 0x35, 0x53, 0x82, 0xfb, 0xe0, 0x54, 0xfb, 0xf0, 0x02} },
+{ 0x1870, 16, {0x13, 0x43, 0x30, 0xe1, 0x02, 0x80, 0xe8, 0xf5, 0x85, 0xe5, 0x3b, 0x30, 0xe3, 0x0a, 0x53, 0x82} },
+{ 0x1880, 16, {0xf8, 0x43, 0x82, 0x04, 0xe0, 0x54, 0xfe, 0xf0, 0xe5, 0x85, 0x20, 0xe3, 0x56, 0x90, 0x20, 0x50} },
+{ 0x1890, 16, {0x74, 0x03, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xe2, 0xe0, 0x44, 0x40, 0xf0} },
+{ 0x18a0, 16, {0x90, 0x7f, 0xe3, 0x05, 0x86, 0x90, 0x7d, 0x00, 0x05, 0x86, 0xe5, 0x85, 0xf0, 0xa3, 0xe5, 0x84} },
+{ 0x18b0, 16, {0xf0, 0x05, 0x86, 0x90, 0x7f, 0xe5, 0xe5, 0x3f, 0xfd, 0x03, 0x03, 0x03, 0xfe, 0xf0, 0xf0, 0xf0} },
+{ 0x18c0, 16, {0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xde, 0xf6, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20} },
+{ 0x18d0, 16, {0x58, 0x74, 0x00, 0xf0, 0x90, 0x7f, 0xbd, 0xed, 0xf0, 0x90, 0x20, 0x19, 0xe0, 0x54, 0xfe, 0xf0} },
+{ 0x18e0, 16, {0x02, 0x13, 0x43, 0x7f, 0x40, 0x90, 0x7d, 0x00, 0x05, 0x86, 0x90, 0x20, 0x18, 0xe5, 0x84, 0xfe} },
+{ 0x18f0, 16, {0x24, 0x05, 0xfd, 0x8d, 0x84, 0xe0, 0x8e, 0x84, 0x30, 0xe0, 0x09, 0xe0, 0x05, 0x86, 0xf0, 0xa3} },
+{ 0x1900, 16, {0x05, 0x86, 0xdf, 0xef, 0x05, 0x86, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0x7f, 0xbd, 0xf0, 0x05, 0x86} },
+{ 0x1910, 16, {0xa3, 0xe0, 0x54, 0xfe, 0xf0, 0x02, 0x13, 0x43, 0x53, 0x2f, 0xfa, 0xe5, 0x25, 0x60, 0x08, 0x75} },
+{ 0x1920, 16, {0x25, 0x00, 0xd2, 0xe7, 0xfe, 0x80, 0x0a, 0x90, 0x7f, 0xcd, 0xe0, 0xfe, 0x70, 0x03, 0x02, 0x19} },
+{ 0x1930, 16, {0xb2, 0x90, 0x20, 0x50, 0x74, 0x03, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xe2} },
+{ 0x1940, 16, {0xe0, 0x44, 0x40, 0xf0, 0x90, 0x7f, 0xe3, 0x05, 0x86, 0x90, 0x7c, 0xc0, 0x05, 0x86, 0xe5, 0x85} },
+{ 0x1950, 16, {0xf0, 0xa3, 0xe5, 0x84, 0xf0, 0x05, 0x86, 0x90, 0x7f, 0xe5, 0xee, 0x30, 0xe7, 0x08, 0x05, 0x86} },
+{ 0x1960, 16, {0xe0, 0x24, 0x38, 0xf0, 0x05, 0x86, 0xee, 0x54, 0x7f, 0xfe, 0x54, 0x07, 0xfb, 0xee, 0x54, 0x78} },
+{ 0x1970, 16, {0x60, 0x30, 0x03, 0x03, 0x03, 0x30, 0xe3, 0x04, 0x74, 0x07, 0x7b, 0x08, 0xfd, 0xfc, 0xe0, 0xe0} },
+{ 0x1980, 16, {0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xdd, 0xf6, 0xeb, 0xfe, 0x60, 0x19, 0xec, 0x64, 0x07, 0x70} },
+{ 0x1990, 16, {0x11, 0x8b, 0x25, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00, 0xf0} },
+{ 0x19a0, 16, {0x80, 0x1b, 0xe0, 0xde, 0xfd, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74} },
+{ 0x19b0, 16, {0x00, 0xf0, 0x90, 0x20, 0x19, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0x7f, 0xcd, 0xf0, 0x02, 0x13, 0x43} },
+{ 0x19c0, 1, {0x32} },
+{ 0x19c1, 4, {0xad, 0x07, 0xac, 0x06} },
+{ 0x19c5, 16, {0x79, 0x06, 0xed, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x3c, 0xf5, 0x83, 0xe0, 0xfa, 0xa3, 0xe0, 0xfb} },
+{ 0x19d5, 16, {0x4a, 0x70, 0x03, 0x02, 0x1b, 0x09, 0xe9, 0xb4, 0x07, 0x00, 0x40, 0x03, 0x02, 0x1a, 0xdb, 0x90} },
+{ 0x19e5, 16, {0x19, 0xeb, 0xf8, 0x28, 0x28, 0x73, 0x02, 0x1a, 0xb9, 0x02, 0x1a, 0x71, 0x02, 0x1a, 0x5a, 0x02} },
+{ 0x19f5, 16, {0x1a, 0x40, 0x02, 0x1a, 0x2f, 0x02, 0x1a, 0x1a, 0x02, 0x1a, 0x00, 0x90, 0x7f, 0xa5, 0xe0, 0x44} },
+{ 0x1a05, 16, {0x80, 0xf0, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xe0, 0xff, 0x25, 0xe0, 0x44, 0xa0, 0x90, 0x7f, 0xa6} },
+{ 0x1a15, 16, {0xf0, 0x19, 0x02, 0x1a, 0xdb, 0x19, 0x8d, 0x82, 0x8c, 0x83, 0xe0, 0xc3, 0x94, 0x20, 0x40, 0x0a} },
+{ 0x1a25, 16, {0xa3, 0xa3, 0xe0, 0x90, 0x7f, 0xa6, 0xf0, 0x02, 0x1a, 0xdb, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3} },
+{ 0x1a35, 16, {0xe0, 0xa3, 0xe0, 0x90, 0x7f, 0xa6, 0xf0, 0x19, 0x02, 0x1a, 0xdb, 0x90, 0x7f, 0xa5, 0xe0, 0x44} },
+{ 0x1a45, 16, {0x80, 0xf0, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xe0, 0xff, 0x25, 0xe0, 0x44, 0xa1, 0x90, 0x7f, 0xa6} },
+{ 0x1a55, 16, {0xf0, 0x19, 0x02, 0x1a, 0xdb, 0xeb, 0x64, 0x01, 0x4a, 0x70, 0x08, 0x90, 0x7f, 0xa5, 0xe0, 0x44} },
+{ 0x1a65, 16, {0x20, 0xf0, 0x19, 0x90, 0x7f, 0xa6, 0xe0, 0xf5, 0x69, 0x19, 0x80, 0x6a, 0xed, 0x24, 0x04, 0xf5} },
+{ 0x1a75, 16, {0x82, 0xe4, 0x3c, 0xf5, 0x83, 0xe0, 0xfe, 0xa3, 0xe0, 0x64, 0x02, 0x4e, 0x70, 0x08, 0x90, 0x7f} },
+{ 0x1a85, 16, {0xa5, 0xe0, 0x44, 0x20, 0xf0, 0x19, 0x90, 0x7f, 0xa6, 0xe0, 0xff, 0xed, 0x24, 0x06, 0xf5, 0x82} },
+{ 0x1a95, 16, {0xe4, 0x3c, 0xf5, 0x83, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9a, 0xa4, 0x85, 0xf0, 0x82, 0xf5, 0x83} },
+{ 0x1aa5, 16, {0xef, 0xf0, 0xed, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x3c, 0xf5, 0x83, 0x74, 0xff, 0xf5, 0xf0, 0x12} },
+{ 0x1ab5, 16, {0x9a, 0x8e, 0x80, 0x22, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x90, 0x7f, 0xa6, 0xe0, 0xff} },
+{ 0x1ac5, 16, {0xed, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x3c, 0xf5, 0x83, 0xe0, 0xfa, 0xa3, 0xe0, 0xf5, 0x82, 0x8a} },
+{ 0x1ad5, 16, {0x83, 0xef, 0xf0, 0x7f, 0x08, 0x22, 0x90, 0x7f, 0xa5, 0xe0, 0xf5, 0x69, 0x30, 0xe0, 0xf7, 0x30} },
+{ 0x1ae5, 16, {0xe2, 0x07, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x06, 0x22, 0xe9, 0xd3, 0x94, 0x02, 0x50, 0x03, 0x02} },
+{ 0x1af5, 16, {0x19, 0xc7, 0xe5, 0x69, 0x30, 0xe1, 0x03, 0x02, 0x19, 0xc7, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40} },
+{ 0x1b05, 6, {0xf0, 0x7f, 0x07, 0x22, 0x7f, 0x08} },
+{ 0x1b0b, 1, {0x22} },
+{ 0x1b0c, 16, {0x8e, 0x5f, 0x8f, 0x60, 0x8c, 0x61, 0x8d, 0x62, 0xaf, 0x03, 0x1b, 0xef, 0x60, 0x24, 0x05, 0x60} },
+{ 0x1b1c, 16, {0xe5, 0x60, 0xae, 0x5f, 0x70, 0x02, 0x05, 0x5f, 0x14, 0xf5, 0x82, 0x8e, 0x83, 0xe0, 0xff, 0x05} },
+{ 0x1b2c, 16, {0x62, 0xe5, 0x62, 0xac, 0x61, 0x70, 0x02, 0x05, 0x61, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0} },
+{ 0x1b3c, 3, {0x80, 0xd6, 0x22} },
+{ 0x8000, 4, {0x8e, 0x69, 0x8f, 0x6a} },
+{ 0x8004, 16, {0x75, 0x6b, 0x03, 0xe5, 0x6a, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x69, 0xf5, 0x83, 0xe0, 0xfe} },
+{ 0x8014, 16, {0xa3, 0xe0, 0x4e, 0x70, 0x03, 0x02, 0x81, 0x0e, 0xe5, 0x6b, 0x60, 0x4e, 0x14, 0x60, 0x38, 0x14} },
+{ 0x8024, 16, {0x60, 0x20, 0x14, 0x60, 0x03, 0x02, 0x80, 0xb2, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0, 0x85} },
+{ 0x8034, 16, {0x6a, 0x82, 0x85, 0x69, 0x83, 0xa3, 0xe0, 0xff, 0x25, 0xe0, 0x44, 0xa0, 0x90, 0x7f, 0xa6, 0xf0} },
+{ 0x8044, 16, {0x80, 0x6c, 0x85, 0x6a, 0x82, 0x85, 0x69, 0x83, 0xe0, 0xc3, 0x94, 0x20, 0x40, 0x09, 0xa3, 0xa3} },
+{ 0x8054, 16, {0xe0, 0x90, 0x7f, 0xa6, 0xf0, 0x80, 0x57, 0x15, 0x6b, 0x85, 0x6a, 0x82, 0x85, 0x69, 0x83, 0xa3} },
+{ 0x8064, 16, {0xa3, 0xe0, 0xa3, 0xe0, 0x90, 0x7f, 0xa6, 0xf0, 0x80, 0x44, 0xe5, 0x6a, 0x24, 0x06, 0xf5, 0x82} },
+{ 0x8074, 16, {0xe4, 0x35, 0x69, 0xf5, 0x83, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9a, 0xa4, 0x85, 0xf0, 0x82, 0xf5} },
+{ 0x8084, 16, {0x83, 0xe0, 0x90, 0x7f, 0xa6, 0xf0, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0xe5, 0x6a, 0x24} },
+{ 0x8094, 16, {0x04, 0xf5, 0x82, 0xe4, 0x35, 0x69, 0xf5, 0x83, 0x74, 0xff, 0xf5, 0xf0, 0x12, 0x9a, 0x8e, 0x85} },
+{ 0x80a4, 16, {0x6a, 0x82, 0x85, 0x69, 0x83, 0xa3, 0xa3, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9a, 0x8e, 0x90, 0x7f} },
+{ 0x80b4, 16, {0xa5, 0xe0, 0xf5, 0x6c, 0x30, 0xe0, 0xf7, 0x30, 0xe2, 0x07, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x06} },
+{ 0x80c4, 16, {0x22, 0xe5, 0x6c, 0x20, 0xe1, 0x0a, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x07, 0x22} },
+{ 0x80d4, 16, {0xe5, 0x6b, 0x70, 0x31, 0x7f, 0x01, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x90, 0x7f, 0xa5, 0xe0, 0x44} },
+{ 0x80e4, 16, {0x80, 0xf0, 0x85, 0x6a, 0x82, 0x85, 0x69, 0x83, 0xa3, 0xe0, 0xff, 0x25, 0xe0, 0x44, 0xa0, 0x90} },
+{ 0x80f4, 16, {0x7f, 0xa6, 0xf0, 0x90, 0x7f, 0xa5, 0xe0, 0xf5, 0x6c, 0x30, 0xe0, 0xf7, 0x30, 0xe1, 0xd5, 0x75} },
+{ 0x8104, 12, {0x6b, 0x03, 0x02, 0x80, 0x07, 0x15, 0x6b, 0x02, 0x80, 0x07, 0x7f, 0x08} },
+{ 0x8110, 1, {0x22} },
+{ 0x8111, 2, {0xac, 0x07} },
+{ 0x8113, 16, {0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0, 0xec, 0x25, 0xe0, 0x44, 0x41, 0x90, 0x7f, 0xa6, 0xf0} },
+{ 0x8123, 16, {0x7b, 0x3c, 0xaf, 0x03, 0x1b, 0xef, 0x70, 0x16, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x90} },
+{ 0x8133, 16, {0x7f, 0xa6, 0xe0, 0xfd, 0x7d, 0x32, 0xaf, 0x05, 0x1d, 0xef, 0x60, 0xd4, 0x80, 0xf8, 0x90, 0x7f} },
+{ 0x8143, 16, {0xa5, 0xe0, 0xfd, 0x30, 0xe0, 0xdc, 0x20, 0xe1, 0x09, 0xe0, 0x44, 0x40, 0xf0, 0x7e, 0xff, 0x7f} },
+{ 0x8153, 16, {0xf9, 0x22, 0xed, 0x30, 0xe2, 0x0c, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x7e, 0xff, 0x7f} },
+{ 0x8163, 16, {0xfa, 0x22, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0x7f, 0xa6, 0xe0, 0xfd, 0x7b, 0x1e} },
+{ 0x8173, 16, {0xaf, 0x03, 0x1b, 0xef, 0x70, 0x16, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x90, 0x7f, 0xa6} },
+{ 0x8183, 16, {0xe0, 0xfd, 0x7d, 0x32, 0xaf, 0x05, 0x1d, 0xef, 0x60, 0x86, 0x80, 0xf8, 0x90, 0x7f, 0xa5, 0xe0} },
+{ 0x8193, 16, {0xfd, 0x20, 0xe0, 0xdc, 0x7b, 0x3c, 0xaf, 0x03, 0x1b, 0xef, 0x70, 0x19, 0x90, 0x7f, 0xa5, 0xe0} },
+{ 0x81a3, 16, {0x44, 0x40, 0xf0, 0x90, 0x7f, 0xa6, 0xe0, 0xfd, 0x7d, 0x32, 0xaf, 0x05, 0x1d, 0xef, 0x70, 0x03} },
+{ 0x81b3, 16, {0x02, 0x81, 0x13, 0x80, 0xf5, 0x90, 0x7f, 0xa5, 0xe0, 0xfd, 0x30, 0xe0, 0xd9, 0x30, 0xe2, 0x09} },
+{ 0x81c3, 16, {0xe0, 0x44, 0x40, 0xf0, 0x7e, 0xff, 0x7f, 0xfa, 0x22, 0xc2, 0xaf, 0x90, 0x7f, 0xa5, 0xe0, 0x44} },
+{ 0x81d3, 12, {0x40, 0xf0, 0x90, 0x7f, 0xa6, 0xe0, 0xfd, 0xd2, 0xaf, 0xff, 0x7e, 0x00} },
+{ 0x81df, 1, {0x22} },
+{ 0x81e0, 16, {0xef, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xab, 0x82, 0xfa, 0xf5} },
+{ 0x81f0, 16, {0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xf9, 0x74, 0xbf, 0xf0, 0x8b, 0x82, 0x8a, 0x83, 0xa3, 0xa3, 0xe0} },
+{ 0x8200, 16, {0x44, 0x10, 0xf0, 0x8b, 0x82, 0x8a, 0x83, 0xa3, 0xa3, 0xa3, 0xe4, 0xf0, 0x8b, 0x82, 0x8a, 0x83} },
+{ 0x8210, 16, {0xa3, 0xf0, 0xed, 0x60, 0x29, 0x74, 0x01, 0x7e, 0x00, 0xa8, 0x07, 0x08, 0x80, 0x05, 0xc3, 0x33} },
+{ 0x8220, 16, {0xce, 0x33, 0xce, 0xd8, 0xf9, 0xff, 0xe4, 0xef, 0x55, 0x3b, 0x60, 0x0a, 0x8b, 0x82, 0x8a, 0x83} },
+{ 0x8230, 16, {0xa3, 0x74, 0x01, 0xf0, 0x80, 0x08, 0x8b, 0x82, 0x8a, 0x83, 0xa3, 0x74, 0xad, 0xf0, 0x8b, 0x82} },
+{ 0x8240, 16, {0x8a, 0x83, 0xa3, 0xa3, 0xa3, 0x74, 0xbf, 0xf0, 0x8b, 0x82, 0x8a, 0x83, 0xa3, 0xa3, 0xe0, 0x54} },
+{ 0x8250, 15, {0xef, 0xf0, 0xae, 0x02, 0xaf, 0x03, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xa3, 0xe9, 0xf0} },
+{ 0x825f, 1, {0x22} },
+{ 0x8260, 4, {0x8f, 0x68, 0x8d, 0x69} },
+{ 0x8264, 16, {0xe4, 0xf5, 0x6a, 0x74, 0x3c, 0x2f, 0xf8, 0x76, 0x08, 0xe5, 0x68, 0x75, 0xf0, 0x0d, 0xa4, 0x24} },
+{ 0x8274, 16, {0xa0, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe} },
+{ 0x8284, 16, {0xa3, 0xe0, 0xff, 0x7b, 0x80, 0x7a, 0x25, 0x79, 0x00, 0x78, 0x00, 0xc3, 0x12, 0x9b, 0xc0, 0x50} },
+{ 0x8294, 16, {0x3c, 0xe5, 0x68, 0x75, 0xf0, 0x0d, 0xa4, 0x24, 0xa0, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83} },
+{ 0x82a4, 16, {0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x7b, 0x00, 0x7a, 0x96, 0x78} },
+{ 0x82b4, 16, {0x00, 0xc3, 0x12, 0x9b, 0xc0, 0x40, 0x0c, 0x75, 0x6a, 0x40, 0x74, 0x3c, 0x25, 0x68, 0xf8, 0x76} },
+{ 0x82c4, 16, {0x10, 0x80, 0x0a, 0x75, 0x6a, 0x80, 0x74, 0x3c, 0x25, 0x68, 0xf8, 0x76, 0x38, 0xe5, 0x6a, 0x45} },
+{ 0x82d4, 16, {0x69, 0x44, 0x01, 0xff, 0xe5, 0x68, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x02, 0xf5, 0x82, 0xe4, 0x34} },
+{ 0x82e4, 5, {0x20, 0xf5, 0x83, 0xef, 0xf0} },
+{ 0x82e9, 1, {0x22} },
+{ 0x82ea, 16, {0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x14, 0xf5, 0x5f, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82} },
+{ 0x82fa, 16, {0xe4, 0x34, 0x20, 0xaf, 0x82, 0xf5, 0x61, 0x8f, 0x62, 0xf5, 0x83, 0xe5, 0x82, 0x24, 0x04, 0xf5} },
+{ 0x830a, 16, {0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0xe0, 0x44, 0x03, 0xf0, 0xaf, 0x5f, 0x7d, 0x06, 0x12, 0x82} },
+{ 0x831a, 16, {0x60, 0xaf, 0x5f, 0x7d, 0x01, 0x12, 0x81, 0xe0, 0x85, 0x62, 0x82, 0x85, 0x61, 0x83, 0xa3, 0xa3} },
+{ 0x832a, 16, {0xe0, 0x20, 0xe0, 0x28, 0xe0, 0xf5, 0x60, 0xe5, 0x62, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x61} },
+{ 0x833a, 16, {0xf5, 0x83, 0xe0, 0xf5, 0x60, 0xe5, 0x62, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x35, 0x61, 0xf5, 0x83} },
+{ 0x834a, 16, {0xe0, 0xf5, 0x60, 0xaf, 0x5f, 0x7d, 0x06, 0x12, 0x82, 0x60, 0x80, 0xcc, 0x74, 0x96, 0x25, 0x5f} },
+{ 0x835a, 16, {0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x5f, 0x25, 0xe0, 0xff, 0xc3, 0x74} },
+{ 0x836a, 16, {0x0c, 0x9f, 0x75, 0xf0, 0x40, 0xa4, 0x24, 0x40, 0xf5, 0x82, 0xe5, 0xf0, 0x34, 0x7b, 0xaf, 0x82} },
+{ 0x837a, 16, {0xfe, 0xe5, 0x5f, 0x25, 0xe0, 0x24, 0x8d, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xee, 0xf0} },
+{ 0x838a, 16, {0xa3, 0xef, 0xf0, 0xaf, 0x5f, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc} },
+{ 0x839a, 4, {0x42, 0x30, 0x7f, 0x00} },
+{ 0x839e, 1, {0x22} },
+{ 0x839f, 16, {0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x14, 0xf5, 0x47, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82} },
+{ 0x83af, 16, {0xe4, 0x34, 0x20, 0xaf, 0x82, 0xf5, 0x49, 0x8f, 0x4a, 0x74, 0x96, 0x25, 0x47, 0xf5, 0x82, 0xe4} },
+{ 0x83bf, 16, {0x34, 0x02, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x4a, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x49, 0xf5} },
+{ 0x83cf, 16, {0x83, 0xe0, 0x54, 0xfc, 0xf0, 0xaf, 0x47, 0xe4, 0xfd, 0x12, 0x81, 0xe0, 0xaf, 0x47, 0x7d, 0x06} },
+{ 0x83df, 16, {0x12, 0x82, 0x60, 0xe5, 0x4a, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x49, 0xf5, 0x83, 0xe0, 0x30} },
+{ 0x83ef, 16, {0xe0, 0x0b, 0x85, 0x4a, 0x82, 0x85, 0x49, 0x83, 0xe0, 0xf5, 0x48, 0x80, 0xe6, 0xaf, 0x47, 0x74} },
+{ 0x83ff, 16, {0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xf4, 0x52, 0x30, 0xe5, 0x47, 0x25} },
+{ 0x840f, 13, {0xe0, 0x24, 0xc7, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe4, 0xf0, 0xff} },
+{ 0x841c, 1, {0x22} },
+{ 0x841d, 4, {0x8e, 0x47, 0x8f, 0x48} },
+{ 0x8421, 16, {0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x14, 0xf5, 0x49, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x01, 0xf5, 0x82} },
+{ 0x8431, 16, {0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0, 0x54, 0x03, 0x70, 0x23, 0x85, 0x48, 0x82, 0x8e, 0x83, 0xa3} },
+{ 0x8441, 16, {0xe0, 0x30, 0xe0, 0x07, 0xaf, 0x49, 0x7d, 0x02, 0x12, 0x82, 0x60, 0x85, 0x48, 0x82, 0x85, 0x47} },
+{ 0x8451, 15, {0x83, 0xa3, 0xe0, 0x30, 0xe1, 0x07, 0xaf, 0x49, 0x7d, 0x04, 0x12, 0x82, 0x60, 0x7f, 0x00} },
+{ 0x8460, 1, {0x22} },
+{ 0x8461, 16, {0x8f, 0x82, 0x8e, 0x83, 0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfd, 0xa3, 0xa3, 0xa3, 0xe0, 0xfc, 0xed} },
+{ 0x8471, 16, {0x6c, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xa3, 0xc0, 0x83, 0xc0} },
+{ 0x8481, 16, {0x82, 0xe0, 0xfd, 0x8f, 0x82, 0x8e, 0x83, 0xe0, 0xfc, 0xed, 0x6c, 0xd0, 0x82, 0xd0, 0x83, 0xf0} },
+{ 0x8491, 16, {0x8f, 0x82, 0x8e, 0x83, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0xe0, 0xfd, 0xec, 0x6d, 0xd0} },
+{ 0x84a1, 16, {0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfd, 0x8f} },
+{ 0x84b1, 16, {0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xe0, 0xfc, 0xed, 0x6c, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82} },
+{ 0x84c1, 16, {0x8e, 0x83, 0xa3, 0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfd, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xe0} },
+{ 0x84d1, 16, {0xfc, 0xed, 0x6c, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xc0, 0x83, 0xc0} },
+{ 0x84e1, 16, {0x82, 0xe0, 0xfd, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xe0, 0xff, 0xed, 0x6f, 0xd0, 0x82, 0xd0} },
+{ 0x84f1, 3, {0x83, 0xf0, 0x22} },
+{ 0x84f4, 4, {0x8e, 0x5f, 0x8f, 0x60} },
+{ 0x84f8, 16, {0x8f, 0x82, 0x8e, 0x83, 0xe0, 0xff, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0xf8, 0xf5, 0x82, 0xe4, 0x34} },
+{ 0x8508, 16, {0x1f, 0xad, 0x82, 0xf5, 0x66, 0x8d, 0x67, 0xaa, 0x5f, 0xa9, 0x60, 0x7b, 0x01, 0xc0, 0x03, 0xc0} },
+{ 0x8518, 16, {0x01, 0xef, 0x75, 0xf0, 0x0d, 0xa4, 0x24, 0x92, 0xf9, 0x74, 0x02, 0x35, 0xf0, 0xa8, 0x01, 0xfc} },
+{ 0x8528, 16, {0xad, 0x03, 0xd0, 0x01, 0xd0, 0x03, 0x7e, 0x00, 0x7f, 0x0d, 0x12, 0x9a, 0x1f, 0x85, 0x60, 0x82} },
+{ 0x8538, 16, {0x85, 0x5f, 0x83, 0xa3, 0xe0, 0xf8, 0xa3, 0xe0, 0xf9, 0xa3, 0xe0, 0xfa, 0xa3, 0xe0, 0xfb, 0x7f} },
+{ 0x8548, 16, {0x00, 0x7e, 0x08, 0x7d, 0x07, 0x7c, 0x00, 0x12, 0x9b, 0x2e, 0x8f, 0x64, 0x8e, 0x63, 0x8d, 0x62} },
+{ 0x8558, 16, {0x8c, 0x61, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00, 0x78, 0x00, 0xc3, 0x12, 0x9b, 0xc0, 0x70, 0x09} },
+{ 0x8568, 16, {0x75, 0x64, 0x01, 0xf5, 0x63, 0xf5, 0x62, 0xf5, 0x61, 0x7f, 0xff, 0x7e, 0xff, 0x7d, 0x00, 0x7c} },
+{ 0x8578, 16, {0x00, 0xab, 0x64, 0xaa, 0x63, 0xa9, 0x62, 0xa8, 0x61, 0xd3, 0x12, 0x9b, 0xc0, 0x40, 0x0c, 0x75} },
+{ 0x8588, 16, {0x64, 0xff, 0x75, 0x63, 0xff, 0x75, 0x62, 0x00, 0x75, 0x61, 0x00, 0x85, 0x67, 0x82, 0x85, 0x66} },
+{ 0x8598, 16, {0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0x44, 0x80, 0xf0, 0x85, 0x67, 0x82, 0x85, 0x66, 0x83, 0xe5, 0x64} },
+{ 0x85a8, 16, {0xf0, 0xaf, 0x64, 0xae, 0x63, 0xad, 0x62, 0xac, 0x61, 0x78, 0x08, 0x12, 0x9b, 0xd1, 0x85, 0x67} },
+{ 0x85b8, 16, {0x82, 0x85, 0x66, 0x83, 0xa3, 0xef, 0xf0, 0x85, 0x67, 0x82, 0x85, 0x66, 0x83, 0xa3, 0xa3, 0xa3} },
+{ 0x85c8, 16, {0xe0, 0x54, 0x7f, 0xf0, 0xe4, 0xf5, 0x65, 0xe5, 0x60, 0x24, 0x08, 0xf5, 0x82, 0xe4, 0x35, 0x5f} },
+{ 0x85d8, 16, {0xf5, 0x83, 0xe0, 0xff, 0xb4, 0x62, 0x05, 0x43, 0x65, 0x0a, 0x80, 0x10, 0xef, 0xb4, 0x72, 0x05} },
+{ 0x85e8, 16, {0x43, 0x65, 0x08, 0x80, 0x07, 0xef, 0xb4, 0x74, 0x03, 0x43, 0x65, 0x02, 0xe5, 0x60, 0x24, 0x0b} },
+{ 0x85f8, 16, {0xf5, 0x82, 0xe4, 0x35, 0x5f, 0xf5, 0x83, 0xe0, 0xff, 0x30, 0xe3, 0x03, 0x43, 0x65, 0x80, 0xef} },
+{ 0x8608, 16, {0x30, 0xe7, 0x12, 0x43, 0x65, 0x40, 0xe5, 0x67, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x66, 0xf5} },
+{ 0x8618, 16, {0x83, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x60, 0x24, 0x0b, 0xf5, 0x82, 0xe4, 0x35, 0x5f, 0xf5, 0x83} },
+{ 0x8628, 16, {0xe0, 0xff, 0x20, 0xe1, 0x03, 0x30, 0xe4, 0x27, 0x85, 0x60, 0x82, 0x85, 0x5f, 0x83, 0xe0, 0x14} },
+{ 0x8638, 16, {0xff, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x42, 0x3b, 0xe5, 0x67} },
+{ 0x8648, 16, {0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x66, 0xf5, 0x83, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x17, 0x85} },
+{ 0x8658, 16, {0x60, 0x82, 0x85, 0x5f, 0x83, 0xe0, 0x14, 0xff, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3} },
+{ 0x8668, 16, {0x33, 0xd8, 0xfc, 0xf4, 0x52, 0x3b, 0x85, 0x67, 0x82, 0x85, 0x66, 0x83, 0xa3, 0xa3, 0xa3, 0x74} },
+{ 0x8678, 16, {0xbf, 0xf0, 0x85, 0x67, 0x82, 0x85, 0x66, 0x83, 0xa3, 0xa3, 0xe4, 0xf0, 0xe5, 0x65, 0xf0, 0xe5} },
+{ 0x8688, 16, {0x60, 0x24, 0x0a, 0xf5, 0x82, 0xe4, 0x35, 0x5f, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x67, 0x24, 0x04} },
+{ 0x8698, 16, {0xf5, 0x82, 0xe4, 0x35, 0x66, 0xf5, 0x83, 0xef, 0xf0, 0xe5, 0x60, 0x24, 0x0a, 0xf5, 0x82, 0xe4} },
+{ 0x86a8, 16, {0x35, 0x5f, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x67, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x66, 0xf5} },
+{ 0x86b8, 16, {0x83, 0xef, 0xf0, 0xe5, 0x60, 0x24, 0x09, 0xf5, 0x82, 0xe4, 0x35, 0x5f, 0xf5, 0x83, 0xe0, 0xff} },
+{ 0x86c8, 16, {0xe5, 0x67, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x35, 0x66, 0xf5, 0x83, 0xef, 0xf0, 0xe5, 0x60, 0x24} },
+{ 0x86d8, 16, {0x09, 0xf5, 0x82, 0xe4, 0x35, 0x5f, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x67, 0x24, 0x07, 0xf5, 0x82} },
+{ 0x86e8, 16, {0xe4, 0x35, 0x66, 0xf5, 0x83, 0xef, 0xf0, 0x85, 0x67, 0x82, 0x85, 0x66, 0x83, 0xa3, 0xa3, 0xa3} },
+{ 0x86f8, 16, {0xe4, 0xf0, 0x85, 0x67, 0x82, 0x85, 0x66, 0x83, 0xa3, 0xa3, 0xf0, 0x85, 0x60, 0x82, 0x85, 0x5f} },
+{ 0x8708, 16, {0x83, 0xe0, 0x14, 0xff, 0x7d, 0x06, 0x12, 0x82, 0x60, 0x75, 0x65, 0x08, 0xe5, 0x60, 0x24, 0x0c} },
+{ 0x8718, 16, {0xf5, 0x82, 0xe4, 0x35, 0x5f, 0xf5, 0x83, 0xe0, 0x60, 0x03, 0x43, 0x65, 0x10, 0xe5, 0x67, 0x24} },
+{ 0x8728, 16, {0x04, 0xf5, 0x82, 0xe4, 0x35, 0x66, 0xf5, 0x83, 0xe0, 0x54, 0x03, 0x45, 0x65, 0xf0, 0xe5, 0x60} },
+{ 0x8738, 16, {0x24, 0x06, 0xf5, 0x82, 0xe4, 0x35, 0x5f, 0xf5, 0x83, 0xe0, 0x14, 0xff, 0x25, 0xe0, 0x25, 0xe0} },
+{ 0x8748, 16, {0xff, 0xe5, 0x60, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x5f, 0xf5, 0x83, 0xe0, 0x24, 0xfb, 0x4f} },
+{ 0x8758, 16, {0xf5, 0x65, 0xe5, 0x60, 0x24, 0x07, 0xf5, 0x82, 0xe4, 0x35, 0x5f, 0xf5, 0x83, 0xe0, 0x24, 0xd0} },
+{ 0x8768, 16, {0x60, 0x15, 0x14, 0x60, 0x17, 0x24, 0xc2, 0x60, 0x09, 0x24, 0x0a, 0x70, 0x12, 0x43, 0x65, 0x18} },
+{ 0x8778, 16, {0x80, 0x0d, 0x43, 0x65, 0x08, 0x80, 0x08, 0x43, 0x65, 0x38, 0x80, 0x03, 0x43, 0x65, 0x28, 0x85} },
+{ 0x8788, 13, {0x67, 0x82, 0x85, 0x66, 0x83, 0xa3, 0xa3, 0xa3, 0xe5, 0x65, 0xf0, 0x7f, 0x00} },
+{ 0x8795, 1, {0x22} },
+{ 0x8796, 4, {0x8e, 0x47, 0x8f, 0x48} },
+{ 0x879a, 16, {0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x14, 0xf5, 0x4a, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82} },
+{ 0x87aa, 16, {0xe4, 0x34, 0x20, 0xaf, 0x82, 0xf5, 0x4d, 0x8f, 0x4e, 0x7e, 0x7b, 0x7f, 0x80, 0xef, 0x24, 0x01} },
+{ 0x87ba, 16, {0xf5, 0x4c, 0xe4, 0x3e, 0xf5, 0x4b, 0x8f, 0x82, 0x8e, 0x83, 0x74, 0x08, 0xf0, 0xe5, 0x4a, 0x04} },
+{ 0x87ca, 16, {0x85, 0x4c, 0x82, 0x85, 0x4b, 0x83, 0xf0, 0xa3, 0xe4, 0xf0, 0xe5, 0x4e, 0x24, 0x06, 0xf5, 0x82} },
+{ 0x87da, 16, {0xe4, 0x35, 0x4d, 0xf5, 0x83, 0xe0, 0x85, 0x4c, 0x82, 0x85, 0x4b, 0x83, 0xa3, 0xa3, 0xf0, 0xe5} },
+{ 0x87ea, 16, {0x4e, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x4d, 0xf5, 0x83, 0xe0, 0x54, 0x1e, 0x85, 0x4c, 0x82} },
+{ 0x87fa, 16, {0x85, 0x4b, 0x83, 0xa3, 0xa3, 0xa3, 0xf0, 0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xe0, 0x24, 0x2b} },
+{ 0x880a, 16, {0xf8, 0xe6, 0xff, 0xe5, 0x4c, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x4b, 0xf5, 0x83, 0xef, 0xf0} },
+{ 0x881a, 16, {0xaf, 0x4a, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xf5, 0x49, 0x7f} },
+{ 0x882a, 16, {0x02, 0x12, 0x81, 0x11, 0xc3, 0xee, 0x64, 0x80, 0x94, 0x80, 0x40, 0xf3, 0xe5, 0x49, 0x5f, 0xff} },
+{ 0x883a, 16, {0xe5, 0x4c, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x4b, 0xf5, 0x83, 0xef, 0xf0, 0x90, 0x7f, 0xc3} },
+{ 0x884a, 5, {0x74, 0x07, 0xf0, 0x7f, 0x00} },
+{ 0x884f, 1, {0x22} },
+{ 0x8850, 16, {0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0xf8, 0xf5, 0x82, 0xe4, 0x34, 0x1f} },
+{ 0x8860, 16, {0xaf, 0x82, 0xf5, 0x47, 0x8f, 0x48, 0x7e, 0x7b, 0x7f, 0x80, 0xef, 0x24, 0x01, 0xfd, 0xe4, 0x3e} },
+{ 0x8870, 16, {0xfc, 0x8f, 0x82, 0x8e, 0x83, 0x74, 0x0a, 0xf0, 0xe5, 0x48, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35} },
+{ 0x8880, 16, {0x47, 0xf5, 0x83, 0xe0, 0x8d, 0x82, 0x8c, 0x83, 0xf0, 0x90, 0x7f, 0xc3, 0x74, 0x02, 0xf0, 0x7f} },
+{ 0x8890, 1, {0x00} },
+{ 0x8891, 1, {0x22} },
+{ 0x8892, 16, {0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0xf8, 0xf5, 0x82, 0xe4, 0x34, 0x1f} },
+{ 0x88a2, 16, {0xad, 0x82, 0xfc, 0x8f, 0x82, 0xa3, 0xe0, 0x60, 0x0f, 0xed, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x3c} },
+{ 0x88b2, 16, {0xf5, 0x83, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x11, 0xae, 0x04, 0xaf, 0x05, 0xef, 0x24, 0x04, 0xf5} },
+{ 0x88c2, 11, {0x82, 0xe4, 0x3e, 0xf5, 0x83, 0xe0, 0x54, 0xfd, 0xf0, 0x7f, 0x00} },
+{ 0x88cd, 1, {0x22} },
+{ 0x88ce, 16, {0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0xf8, 0xf5, 0x82, 0xe4, 0x34, 0x1f} },
+{ 0x88de, 16, {0xad, 0x82, 0xfc, 0x8f, 0x82, 0xa3, 0xe0, 0x60, 0x0f, 0xed, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x3c} },
+{ 0x88ee, 16, {0xf5, 0x83, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x11, 0xae, 0x04, 0xaf, 0x05, 0xef, 0x24, 0x04, 0xf5} },
+{ 0x88fe, 11, {0x82, 0xe4, 0x3e, 0xf5, 0x83, 0xe0, 0x54, 0xfe, 0xf0, 0x7f, 0x00} },
+{ 0x8909, 1, {0x22} },
+{ 0x890a, 16, {0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0xf8, 0xf5, 0x82, 0xe4, 0x34, 0x1f} },
+{ 0x891a, 16, {0xad, 0x82, 0xfc, 0x8f, 0x82, 0xa3, 0xe0, 0x60, 0x0d, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xa3} },
+{ 0x892a, 16, {0xe0, 0x44, 0x40, 0xf0, 0x80, 0x0f, 0xae, 0x04, 0xaf, 0x05, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3} },
+{ 0x893a, 7, {0xa3, 0xe0, 0x54, 0xbf, 0xf0, 0x7f, 0x00} },
+{ 0x8941, 1, {0x22} },
+{ 0x8942, 4, {0x8e, 0x47, 0x8f, 0x48} },
+{ 0x8946, 16, {0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xe0, 0xf5, 0x4b, 0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x24, 0xfe, 0x60} },
+{ 0x8956, 16, {0x16, 0x14, 0x60, 0x1f, 0x14, 0x60, 0x28, 0x24, 0x03, 0x70, 0x2e, 0x7e, 0x7e, 0x7f, 0x80, 0x75} },
+{ 0x8966, 16, {0x49, 0x7e, 0x75, 0x4a, 0x80, 0x80, 0x22, 0x7e, 0x7e, 0x7f, 0x00, 0x75, 0x49, 0x7e, 0x75, 0x4a} },
+{ 0x8976, 16, {0x00, 0x80, 0x16, 0x7e, 0x7d, 0x7f, 0x80, 0x75, 0x49, 0x7d, 0x75, 0x4a, 0x80, 0x80, 0x0a, 0x7e} },
+{ 0x8986, 16, {0x7d, 0x7f, 0x00, 0x75, 0x49, 0x7d, 0x75, 0x4a, 0x00, 0xe5, 0x4b, 0x70, 0x20, 0x85, 0x4a, 0x82} },
+{ 0x8996, 16, {0x85, 0x49, 0x83, 0x74, 0xff, 0xf0, 0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xe0, 0x25, 0xe0, 0x24} },
+{ 0x89a6, 16, {0xb5, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0x74, 0x01, 0xf0, 0x80, 0x3a, 0xe5, 0x48, 0x24} },
+{ 0x89b6, 16, {0x02, 0xff, 0xe4, 0x35, 0x47, 0xfe, 0xe5, 0x4b, 0x60, 0x10, 0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x85} },
+{ 0x89c6, 16, {0x4a, 0x82, 0x85, 0x49, 0x83, 0xf0, 0x15, 0x4b, 0x80, 0xec, 0x85, 0x48, 0x82, 0x85, 0x47, 0x83} },
+{ 0x89d6, 16, {0xa3, 0xe0, 0xff, 0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xe0, 0x25, 0xe0, 0x24, 0xb5, 0xf5, 0x82} },
+{ 0x89e6, 9, {0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xef, 0xf0, 0x7f, 0x00} },
+{ 0x89ef, 1, {0x22} },
+{ 0x89f0, 16, {0xef, 0x24, 0x01, 0xf5, 0x48, 0xe4, 0x3e, 0xf5, 0x47, 0x7c, 0x7b, 0x7d, 0x80, 0x7e, 0x7b, 0x7f} },
+{ 0x8a00, 16, {0x80, 0x8f, 0x82, 0x8e, 0x83, 0x74, 0x07, 0xf0, 0xef, 0x24, 0x01, 0xff, 0xe4, 0x3e, 0x90, 0x01} },
+{ 0x8a10, 16, {0x31, 0xf0, 0xa3, 0xef, 0xf0, 0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xfe} },
+{ 0x8a20, 16, {0xa3, 0xe0, 0x8e, 0x49, 0xf5, 0x4a, 0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xe0, 0x24, 0x9e, 0x60} },
+{ 0x8a30, 16, {0x61, 0x24, 0xf9, 0x60, 0x0e, 0x24, 0xf1, 0x70, 0x03, 0x02, 0x8a, 0xdd, 0x24, 0x14, 0x60, 0x03} },
+{ 0x8a40, 16, {0x02, 0x8b, 0x30, 0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xc3} },
+{ 0x8a50, 16, {0xe4, 0x9f, 0xf5, 0x4c, 0x74, 0x01, 0x9e, 0xf5, 0x4b, 0xd3, 0xe5, 0x4c, 0x94, 0x40, 0xe5, 0x4b} },
+{ 0x8a60, 16, {0x94, 0x00, 0x40, 0x06, 0x75, 0x4b, 0x00, 0x75, 0x4c, 0x40, 0xd3, 0xe5, 0x4a, 0x95, 0x4c, 0xe5} },
+{ 0x8a70, 16, {0x49, 0x95, 0x4b, 0x50, 0x03, 0x02, 0x8b, 0x30, 0xae, 0x4b, 0xaf, 0x4c, 0x85, 0x48, 0x82, 0x85} },
+{ 0x8a80, 16, {0x47, 0x83, 0xa3, 0xa3, 0xa3, 0xee, 0xf0, 0xfe, 0xa3, 0xef, 0xf0, 0x8e, 0x49, 0xf5, 0x4a, 0x02} },
+{ 0x8a90, 16, {0x8b, 0x30, 0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xc3, 0x74} },
+{ 0x8aa0, 16, {0x30, 0x9f, 0xf5, 0x4c, 0xe4, 0x9e, 0xf5, 0x4b, 0xd3, 0xe5, 0x4c, 0x94, 0x40, 0xe5, 0x4b, 0x94} },
+{ 0x8ab0, 16, {0x00, 0x40, 0x06, 0x75, 0x4b, 0x00, 0x75, 0x4c, 0x40, 0xd3, 0xe5, 0x4a, 0x95, 0x4c, 0xe5, 0x49} },
+{ 0x8ac0, 16, {0x95, 0x4b, 0x40, 0x6c, 0xae, 0x4b, 0xaf, 0x4c, 0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xa3, 0xa3} },
+{ 0x8ad0, 16, {0xa3, 0xee, 0xf0, 0xfe, 0xa3, 0xef, 0xf0, 0x8e, 0x49, 0xf5, 0x4a, 0x80, 0x53, 0x85, 0x48, 0x82} },
+{ 0x8ae0, 16, {0x85, 0x47, 0x83, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xc3, 0xe4, 0x9f, 0xf5, 0x4c, 0xe4, 0x9e} },
+{ 0x8af0, 16, {0xf5, 0x4b, 0x45, 0x4c, 0x70, 0x07, 0xf5, 0x4b, 0x75, 0x4c, 0x40, 0x80, 0x11, 0xd3, 0xe5, 0x4c} },
+{ 0x8b00, 16, {0x94, 0x40, 0xe5, 0x4b, 0x94, 0x00, 0x40, 0x06, 0x75, 0x4b, 0x00, 0x75, 0x4c, 0x40, 0xd3, 0xe5} },
+{ 0x8b10, 16, {0x4a, 0x95, 0x4c, 0xe5, 0x49, 0x95, 0x4b, 0x40, 0x17, 0xae, 0x4b, 0xaf, 0x4c, 0x85, 0x48, 0x82} },
+{ 0x8b20, 16, {0x85, 0x47, 0x83, 0xa3, 0xa3, 0xa3, 0xee, 0xf0, 0xfe, 0xa3, 0xef, 0xf0, 0x8e, 0x49, 0xf5, 0x4a} },
+{ 0x8b30, 16, {0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xe0, 0x24, 0x9e, 0x70, 0x03, 0x02, 0x8b, 0xf0, 0x24, 0xf9} },
+{ 0x8b40, 16, {0x60, 0x58, 0x24, 0xf1, 0x70, 0x03, 0x02, 0x8c, 0x40, 0x24, 0x14, 0x60, 0x03, 0x02, 0x8c, 0x84} },
+{ 0x8b50, 16, {0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xd3, 0x94, 0xff, 0xee} },
+{ 0x8b60, 16, {0x94, 0x00, 0x40, 0x03, 0x02, 0x8c, 0x84, 0x90, 0x01, 0x2c, 0xef, 0xf0, 0xe5, 0x4a, 0x15, 0x4a} },
+{ 0x8b70, 16, {0xae, 0x49, 0x70, 0x02, 0x15, 0x49, 0x4e, 0x70, 0x03, 0x02, 0x8c, 0x84, 0x90, 0x01, 0x2c, 0xe0} },
+{ 0x8b80, 16, {0xff, 0x04, 0xf0, 0xa8, 0x07, 0xe6, 0xff, 0x90, 0x01, 0x31, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9a} },
+{ 0x8b90, 16, {0xa4, 0x85, 0xf0, 0x82, 0xf5, 0x83, 0xef, 0xf0, 0x80, 0xd2, 0x85, 0x48, 0x82, 0x85, 0x47, 0x83} },
+{ 0x8ba0, 16, {0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xc3, 0x94, 0x80, 0xee, 0x94, 0x00, 0x50, 0x03, 0x02, 0x8c} },
+{ 0x8bb0, 16, {0x84, 0xd3, 0xef, 0x94, 0xff, 0xee, 0x94, 0x00, 0x40, 0x03, 0x02, 0x8c, 0x84, 0x90, 0x01, 0x2d} },
+{ 0x8bc0, 16, {0xef, 0xf0, 0xe5, 0x4a, 0x15, 0x4a, 0xae, 0x49, 0x70, 0x02, 0x15, 0x49, 0x4e, 0x70, 0x03, 0x02} },
+{ 0x8bd0, 16, {0x8c, 0x84, 0x90, 0x01, 0x2d, 0xe0, 0xff, 0x04, 0xf0, 0xa8, 0x07, 0xe6, 0xff, 0x90, 0x01, 0x31} },
+{ 0x8be0, 16, {0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9a, 0xa4, 0x85, 0xf0, 0x82, 0xf5, 0x83, 0xef, 0xf0, 0x80, 0xd2} },
+{ 0x8bf0, 16, {0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xc3, 0x94, 0x20, 0xee} },
+{ 0x8c00, 16, {0x94, 0x00, 0x50, 0x03, 0x02, 0x8c, 0x84, 0xd3, 0xef, 0x94, 0x2f, 0xee, 0x94, 0x00, 0x50, 0x74} },
+{ 0x8c10, 16, {0x90, 0x01, 0x2e, 0xef, 0xf0, 0xe5, 0x4a, 0x15, 0x4a, 0xae, 0x49, 0x70, 0x02, 0x15, 0x49, 0x4e} },
+{ 0x8c20, 16, {0x60, 0x62, 0x90, 0x01, 0x2e, 0xe0, 0xff, 0x04, 0xf0, 0xa8, 0x07, 0xe6, 0xff, 0x90, 0x01, 0x31} },
+{ 0x8c30, 16, {0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9a, 0xa4, 0x85, 0xf0, 0x82, 0xf5, 0x83, 0xef, 0xf0, 0x80, 0xd5} },
+{ 0x8c40, 16, {0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xa3, 0xe0, 0xff, 0xa3, 0xe0, 0x90, 0x01, 0x2f, 0xcf, 0xf0} },
+{ 0x8c50, 16, {0xa3, 0xef, 0xf0, 0xe5, 0x4a, 0x15, 0x4a, 0xae, 0x49, 0x70, 0x02, 0x15, 0x49, 0x4e, 0x60, 0x24} },
+{ 0x8c60, 16, {0x90, 0x01, 0x2f, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9a, 0xa4, 0x85, 0xf0, 0x82, 0xf5, 0x83, 0xe0} },
+{ 0x8c70, 16, {0xff, 0x90, 0x01, 0x31, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9a, 0xa4, 0x85, 0xf0, 0x82, 0xf5, 0x83} },
+{ 0x8c80, 16, {0xef, 0xf0, 0x80, 0xcf, 0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xa3, 0xe0} },
+{ 0x8c90, 6, {0x90, 0x7f, 0xc3, 0xf0, 0x7f, 0x00} },
+{ 0x8c96, 1, {0x22} },
+{ 0x8c97, 16, {0x7e, 0x7b, 0x7f, 0x80, 0xef, 0x24, 0x01, 0xfd, 0xe4, 0x3e, 0xfc, 0x8f, 0x82, 0x8e, 0x83, 0x74} },
+{ 0x8ca7, 16, {0x0b, 0xf0, 0x90, 0x20, 0x70, 0xe0, 0x54, 0xf0, 0xff, 0xc4, 0x54, 0x0f, 0x8d, 0x82, 0x8c, 0x83} },
+{ 0x8cb7, 16, {0xf0, 0x90, 0x11, 0xf0, 0xe4, 0x93, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xf0, 0x90, 0x11, 0xf1, 0xe4} },
+{ 0x8cc7, 16, {0x93, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xf0, 0xe4, 0x90, 0x01, 0x33, 0xf0, 0xa3, 0xf0, 0xa3} },
+{ 0x8cd7, 16, {0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0x74, 0x10, 0xf0, 0xed, 0x24, 0x03, 0xfe, 0xe4, 0x3c, 0xa3} },
+{ 0x8ce7, 16, {0xf0, 0xa3, 0xce, 0xf0, 0x7e, 0x01, 0x7f, 0x33, 0x12, 0x19, 0xc1, 0x90, 0x7f, 0xc3, 0x74, 0x14} },
+{ 0x8cf7, 3, {0xf0, 0x7f, 0x00} },
+{ 0x8cfa, 1, {0x22} },
+{ 0x8cfb, 4, {0x8e, 0x40, 0x8f, 0x41} },
+{ 0x8cff, 16, {0x85, 0x40, 0x43, 0x85, 0x41, 0x44, 0x85, 0x44, 0x82, 0x85, 0x43, 0x83, 0xe0, 0x14, 0xb4, 0x0f} },
+{ 0x8d0f, 16, {0x00, 0x40, 0x03, 0x02, 0x8e, 0x32, 0x90, 0x8d, 0x1c, 0xf8, 0x28, 0x28, 0x73, 0x02, 0x8d, 0x49} },
+{ 0x8d1f, 16, {0x02, 0x8d, 0x5a, 0x02, 0x8d, 0x6b, 0x02, 0x8d, 0x8e, 0x02, 0x8d, 0x9f, 0x02, 0x8d, 0xb0, 0x02} },
+{ 0x8d2f, 16, {0x8d, 0xc0, 0x02, 0x8d, 0xcb, 0x02, 0x8d, 0xdb, 0x02, 0x8d, 0xeb, 0x02, 0x8d, 0xfb, 0x02, 0x8e} },
+{ 0x8d3f, 16, {0x02, 0x02, 0x8e, 0x32, 0x02, 0x8e, 0x12, 0x02, 0x8e, 0x22, 0xe5, 0x44, 0x24, 0x01, 0xff, 0xe4} },
+{ 0x8d4f, 16, {0x35, 0x43, 0xfe, 0x12, 0x82, 0xea, 0x8f, 0x42, 0x02, 0x8e, 0x32, 0xe5, 0x44, 0x24, 0x01, 0xff} },
+{ 0x8d5f, 16, {0xe4, 0x35, 0x43, 0xfe, 0x12, 0x83, 0x9f, 0x8f, 0x42, 0x02, 0x8e, 0x32, 0xe5, 0x44, 0x24, 0x01} },
+{ 0x8d6f, 16, {0xf5, 0x46, 0xe4, 0x35, 0x43, 0xf5, 0x45, 0xe5, 0x46, 0x24, 0x01, 0xff, 0xe4, 0x35, 0x45, 0xfe} },
+{ 0x8d7f, 16, {0x12, 0x84, 0x61, 0xaf, 0x46, 0xae, 0x45, 0x12, 0x84, 0xf4, 0x8f, 0x42, 0x02, 0x8e, 0x32, 0xe5} },
+{ 0x8d8f, 16, {0x44, 0x24, 0x01, 0xff, 0xe4, 0x35, 0x43, 0xfe, 0x12, 0x88, 0x92, 0x8f, 0x42, 0x02, 0x8e, 0x32} },
+{ 0x8d9f, 16, {0xe5, 0x44, 0x24, 0x01, 0xff, 0xe4, 0x35, 0x43, 0xfe, 0x12, 0x88, 0xce, 0x8f, 0x42, 0x02, 0x8e} },
+{ 0x8daf, 16, {0x32, 0xe5, 0x44, 0x24, 0x01, 0xff, 0xe4, 0x35, 0x43, 0xfe, 0x12, 0x89, 0x0a, 0x8f, 0x42, 0x80} },
+{ 0x8dbf, 16, {0x72, 0xaf, 0x41, 0xae, 0x40, 0x12, 0x89, 0xf0, 0x8f, 0x42, 0x80, 0x67, 0xe5, 0x44, 0x24, 0x01} },
+{ 0x8dcf, 16, {0xff, 0xe4, 0x35, 0x43, 0xfe, 0x12, 0x87, 0x96, 0x8f, 0x42, 0x80, 0x57, 0xe5, 0x44, 0x24, 0x01} },
+{ 0x8ddf, 16, {0xff, 0xe4, 0x35, 0x43, 0xfe, 0x12, 0x84, 0x1d, 0x8f, 0x42, 0x80, 0x47, 0xe5, 0x44, 0x24, 0x01} },
+{ 0x8def, 16, {0xff, 0xe4, 0x35, 0x43, 0xfe, 0x12, 0x88, 0x50, 0x8f, 0x42, 0x80, 0x37, 0x12, 0x8c, 0x97, 0x8f} },
+{ 0x8dff, 16, {0x42, 0x80, 0x30, 0xe5, 0x44, 0x24, 0x01, 0xff, 0xe4, 0x35, 0x43, 0xfe, 0x12, 0x11, 0xd8, 0x8f} },
+{ 0x8e0f, 16, {0x42, 0x80, 0x20, 0xe5, 0x44, 0x24, 0x01, 0xff, 0xe4, 0x35, 0x43, 0xfe, 0x12, 0x89, 0x42, 0x8f} },
+{ 0x8e1f, 16, {0x42, 0x80, 0x10, 0xaf, 0x41, 0xae, 0x40, 0x7c, 0x02, 0x7d, 0x4d, 0x7b, 0x40, 0x12, 0x1b, 0x0c} },
+{ 0x8e2f, 5, {0xe4, 0xf5, 0x42, 0xaf, 0x42} },
+{ 0x8e34, 1, {0x22} },
+{ 0x8e35, 8, {0x8f, 0x61, 0x8e, 0x60, 0x8d, 0x5f, 0x8c, 0x5e} },
+{ 0x8e3d, 16, {0x75, 0x68, 0x01, 0x75, 0x69, 0x3b, 0xe4, 0xf5, 0x67, 0xaf, 0x63, 0x15, 0x63, 0xef, 0x70, 0x03} },
+{ 0x8e4d, 16, {0x02, 0x8e, 0xd3, 0xaf, 0x62, 0xe4, 0xfc, 0xfd, 0xfe, 0xf8, 0xf9, 0xfa, 0xab, 0x07, 0xaf, 0x61} },
+{ 0x8e5d, 16, {0xae, 0x60, 0xad, 0x5f, 0xac, 0x5e, 0x12, 0x9b, 0x2e, 0xaf, 0x03, 0x8f, 0x66, 0xaf, 0x61, 0xae} },
+{ 0x8e6d, 16, {0x60, 0xad, 0x5f, 0xac, 0x5e, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0xaf, 0x62, 0xe4} },
+{ 0x8e7d, 16, {0xfc, 0xfd, 0xfe, 0xf8, 0xf9, 0xfa, 0xab, 0x07, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04} },
+{ 0x8e8d, 16, {0x12, 0x9b, 0x2e, 0x8f, 0x61, 0x8e, 0x60, 0x8d, 0x5f, 0x8c, 0x5e, 0xe5, 0x66, 0x24, 0x30, 0xf5} },
+{ 0x8e9d, 16, {0x66, 0xd3, 0x94, 0x39, 0x40, 0x06, 0x74, 0x07, 0x25, 0x66, 0xf5, 0x66, 0x05, 0x69, 0xe5, 0x69} },
+{ 0x8ead, 16, {0xae, 0x68, 0x70, 0x02, 0x05, 0x68, 0x14, 0xf5, 0x82, 0x8e, 0x83, 0xe4, 0xf0, 0x05, 0x69, 0xe5} },
+{ 0x8ebd, 16, {0x69, 0xae, 0x68, 0x70, 0x02, 0x05, 0x68, 0x14, 0xf5, 0x82, 0x8e, 0x83, 0xe5, 0x66, 0xf0, 0x05} },
+{ 0x8ecd, 16, {0x67, 0x05, 0x67, 0x02, 0x8e, 0x46, 0xe5, 0x69, 0x15, 0x69, 0x70, 0x02, 0x15, 0x68, 0xaf, 0x67} },
+{ 0x8edd, 16, {0x15, 0x67, 0xef, 0x60, 0x23, 0xe5, 0x69, 0x15, 0x69, 0xae, 0x68, 0x70, 0x02, 0x15, 0x68, 0xf5} },
+{ 0x8eed, 16, {0x82, 0x8e, 0x83, 0xe0, 0xff, 0x05, 0x65, 0xe5, 0x65, 0xac, 0x64, 0x70, 0x02, 0x05, 0x64, 0x14} },
+{ 0x8efd, 8, {0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x80, 0xd6} },
+{ 0x8f05, 1, {0x22} },
+{ 0x8f06, 16, {0xe4, 0x90, 0x01, 0x67, 0xf0, 0x7e, 0x01, 0x7f, 0x68, 0x90, 0x01, 0x5c, 0xee, 0xf0, 0xa3, 0xef} },
+{ 0x8f16, 10, {0xf0, 0x90, 0x01, 0x60, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x22} },
+{ 0x8f20, 16, {0xaa, 0x07, 0xa9, 0x05, 0x90, 0x01, 0x67, 0xe0, 0xc3, 0x94, 0x40, 0x50, 0x61, 0xac, 0x02, 0x74} },
+{ 0x8f30, 16, {0x01, 0x7e, 0x00, 0xa8, 0x04, 0x08, 0x80, 0x05, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9, 0xff} },
+{ 0x8f40, 16, {0xe4, 0xef, 0x55, 0x30, 0x60, 0x45, 0xea, 0x04, 0xff, 0x90, 0x01, 0x60, 0xe0, 0xfc, 0xa3, 0xe0} },
+{ 0x8f50, 16, {0xfd, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0xa3, 0xe9, 0xf0, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3} },
+{ 0x8f60, 16, {0xeb, 0xf0, 0x90, 0x01, 0x60, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x9a, 0x8e, 0xfc, 0xd3, 0xe5, 0xf0} },
+{ 0x8f70, 16, {0x94, 0x25, 0xec, 0x94, 0x02, 0x40, 0x0a, 0x90, 0x01, 0x60, 0x74, 0x01, 0xf0, 0xa3, 0x74, 0x68} },
+{ 0x8f80, 16, {0xf0, 0xc2, 0xaf, 0x90, 0x01, 0x67, 0xe0, 0x04, 0xf0, 0xd2, 0xaf, 0x7f, 0x01, 0x22, 0x7f, 0x00} },
+{ 0x8f90, 1, {0x22} },
+{ 0x8f91, 16, {0x90, 0x01, 0x67, 0xe0, 0xd3, 0x94, 0x00, 0x40, 0x55, 0x90, 0x01, 0x5c, 0xe0, 0xfc, 0xa3, 0xe0} },
+{ 0x8fa1, 16, {0xaa, 0x04, 0xf9, 0x7b, 0x01, 0xc0, 0x03, 0xc0, 0x02, 0xc0, 0x01, 0xaa, 0x06, 0xa9, 0x07, 0xa8} },
+{ 0x8fb1, 16, {0x01, 0xac, 0x02, 0xad, 0x03, 0xd0, 0x01, 0xd0, 0x02, 0xd0, 0x03, 0x7e, 0x00, 0x7f, 0x03, 0x12} },
+{ 0x8fc1, 16, {0x9a, 0x1f, 0x90, 0x01, 0x5c, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x9a, 0x8e, 0xfc, 0xd3, 0xe5, 0xf0} },
+{ 0x8fd1, 16, {0x94, 0x25, 0xec, 0x94, 0x02, 0x40, 0x0a, 0x90, 0x01, 0x5c, 0x74, 0x01, 0xf0, 0xa3, 0x74, 0x68} },
+{ 0x8fe1, 16, {0xf0, 0xc2, 0xaf, 0x90, 0x01, 0x67, 0xe0, 0x14, 0xf0, 0xd2, 0xaf, 0x7f, 0x01, 0x22, 0x7f, 0x00} },
+{ 0x8ff1, 1, {0x22} },
+{ 0x8ff2, 16, {0x90, 0x7f, 0xc2, 0xe0, 0x20, 0xe1, 0x5e, 0x7e, 0x7b, 0x7f, 0x80, 0x75, 0x63, 0x7b, 0x75, 0x64} },
+{ 0x9002, 16, {0x80, 0xe5, 0x64, 0x24, 0x01, 0xff, 0xe4, 0x35, 0x63, 0xa9, 0x07, 0x7b, 0x01, 0x8b, 0x65, 0xf5} },
+{ 0x9012, 16, {0x66, 0x89, 0x67, 0xfe, 0x12, 0x8f, 0x91, 0xef, 0x60, 0x3b, 0xab, 0x65, 0xaa, 0x66, 0xa9, 0x67} },
+{ 0x9022, 16, {0x12, 0x9a, 0x48, 0x14, 0xff, 0x90, 0x00, 0x01, 0x12, 0x9a, 0x61, 0xb4, 0x02, 0x16, 0xc2, 0xaf} },
+{ 0x9032, 16, {0xef, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x01, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0, 0x44} },
+{ 0x9042, 16, {0x04, 0xf0, 0xd2, 0xaf, 0x85, 0x64, 0x82, 0x85, 0x63, 0x83, 0x74, 0x0d, 0xf0, 0x90, 0x7f, 0xc3} },
+{ 0x9052, 5, {0x74, 0x04, 0xf0, 0xd2, 0xaf} },
+{ 0x9057, 1, {0x22} },
+{ 0x9058, 16, {0x12, 0x8f, 0xf2, 0xe4, 0xf5, 0x5e, 0x74, 0x36, 0x25, 0x5e, 0xf8, 0xe6, 0x54, 0xf0, 0xf5, 0x5f} },
+{ 0x9068, 16, {0x74, 0x63, 0x25, 0x5e, 0xf5, 0x82, 0xe4, 0x34, 0x01, 0xf5, 0x83, 0xe0, 0x65, 0x5f, 0xff, 0xc4} },
+{ 0x9078, 16, {0x54, 0x0f, 0xf5, 0x60, 0x60, 0x22, 0x74, 0x63, 0x25, 0x5e, 0xf5, 0x82, 0xe4, 0x34, 0x01, 0xf5} },
+{ 0x9088, 16, {0x83, 0xe5, 0x5f, 0xf0, 0xaf, 0x5e, 0x7d, 0x01, 0xe5, 0x5f, 0x45, 0x60, 0xfb, 0x12, 0x8f, 0x20} },
+{ 0x9098, 16, {0xef, 0x70, 0x05, 0x12, 0x8f, 0xf2, 0x80, 0xec, 0x05, 0x5e, 0xe5, 0x5e, 0xc3, 0x94, 0x04, 0x40} },
+{ 0x90a8, 16, {0xb5, 0x12, 0x8f, 0xf2, 0xe5, 0x3a, 0x60, 0x48, 0xe4, 0xf5, 0x5e, 0xaf, 0x5e, 0x74, 0x01, 0xa8} },
+{ 0x90b8, 16, {0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xf5, 0x5f, 0x55, 0x3a, 0x60, 0x29, 0xe5, 0x5e} },
+{ 0x90c8, 16, {0x75, 0xf0, 0x08, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0, 0x30, 0xe6} },
+{ 0x90d8, 16, {0x16, 0xaf, 0x5e, 0x7d, 0x04, 0x7b, 0x80, 0x12, 0x8f, 0x20, 0xef, 0x70, 0x05, 0x12, 0x8f, 0xf2} },
+{ 0x90e8, 16, {0x80, 0xef, 0xe5, 0x5f, 0xf4, 0x52, 0x3a, 0x05, 0x5e, 0xe5, 0x5e, 0xc3, 0x94, 0x04, 0x40, 0xbb} },
+{ 0x90f8, 16, {0x90, 0x02, 0x9e, 0xe0, 0x60, 0x03, 0x02, 0x91, 0xc5, 0x74, 0x19, 0xf0, 0x7f, 0x02, 0x12, 0x81} },
+{ 0x9108, 16, {0x11, 0x8e, 0x61, 0x8f, 0x62, 0xc3, 0xe5, 0x61, 0x64, 0x80, 0x94, 0x80, 0x40, 0xee, 0x90, 0x01} },
+{ 0x9118, 16, {0x5b, 0xe0, 0x65, 0x62, 0xf0, 0x60, 0x37, 0xe4, 0xf5, 0x5e, 0xaf, 0x5e, 0x74, 0x01, 0xa8, 0x07} },
+{ 0x9128, 16, {0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xf5, 0x5f, 0x90, 0x01, 0x5b, 0xe0, 0x55, 0x5f, 0x60} },
+{ 0x9138, 16, {0x14, 0xaf, 0x5e, 0x7d, 0x08, 0xe5, 0x5f, 0x55, 0x62, 0xfb, 0x12, 0x8f, 0x20, 0xef, 0x70, 0x05} },
+{ 0x9148, 16, {0x12, 0x8f, 0xf2, 0x80, 0xec, 0x05, 0x5e, 0xe5, 0x5e, 0xc3, 0x94, 0x04, 0x40, 0xcc, 0x90, 0x01} },
+{ 0x9158, 16, {0x5b, 0xe5, 0x62, 0xf0, 0xe4, 0xf5, 0x5e, 0xc2, 0xaf, 0x74, 0x32, 0x25, 0x5e, 0xf8, 0xe6, 0xf5} },
+{ 0x9168, 16, {0x5f, 0xe4, 0xf6, 0xd2, 0xaf, 0x53, 0x5f, 0x1e, 0xe5, 0x5f, 0x60, 0x11, 0xaf, 0x5e, 0x7d, 0x02} },
+{ 0x9178, 16, {0xab, 0x5f, 0x12, 0x8f, 0x20, 0xef, 0x70, 0x05, 0x12, 0x8f, 0xf2, 0x80, 0xef, 0x74, 0x2c, 0x25} },
+{ 0x9188, 16, {0x5e, 0xf8, 0xe6, 0xf5, 0x5f, 0x74, 0x9a, 0x25, 0x5e, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83} },
+{ 0x9198, 16, {0xe0, 0x65, 0x5f, 0x60, 0x11, 0xaf, 0x5e, 0x7d, 0x04, 0xab, 0x5f, 0x12, 0x8f, 0x20, 0xef, 0x70} },
+{ 0x91a8, 16, {0x05, 0x12, 0x8f, 0xf2, 0x80, 0xef, 0x74, 0x9a, 0x25, 0x5e, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5} },
+{ 0x91b8, 16, {0x83, 0xe5, 0x5f, 0xf0, 0x05, 0x5e, 0xe5, 0x5e, 0xc3, 0x94, 0x04, 0x40, 0x9a, 0x12, 0x8f, 0xf2} },
+{ 0x91c8, 1, {0x22} },
+{ 0x91c9, 12, {0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x6e, 0x02, 0x92, 0x10} },
+{ 0x91d5, 16, {0x02, 0x05, 0x28, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, 0xf2} },
+{ 0x91e5, 16, {0x08, 0xdf, 0xf4, 0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, 0x33} },
+{ 0x91f5, 16, {0xc4, 0x54, 0x0f, 0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf} },
+{ 0x9205, 16, {0xe4, 0x80, 0x0b, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x92, 0x55, 0xe4, 0x7e} },
+{ 0x9215, 16, {0x01, 0x93, 0x60, 0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, 0x93} },
+{ 0x9225, 16, {0xa3, 0x60, 0x01, 0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, 0xa3} },
+{ 0x9235, 16, {0xfa, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca} },
+{ 0x9245, 16, {0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0xbe} },
+{ 0x9255, 16, {0x60, 0x24, 0x02, 0x28, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x81, 0x82, 0x84, 0x88} },
+{ 0x9265, 16, {0x90, 0xa0, 0xc0, 0xc1, 0xc2, 0xc4, 0xc8, 0xd0, 0xe0, 0xe1, 0xe2, 0xe4, 0xe8, 0xf0, 0xf1, 0xf2} },
+{ 0x9275, 8, {0xf4, 0xf8, 0xf9, 0xfa, 0xfc, 0xfd, 0xfe, 0xff} },
+{ 0x927d, 1, {0x00} },
+{ 0x927e, 11, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x18} },
+{ 0x9289, 16, {0x90, 0x20, 0x60, 0xe0, 0x54, 0x0f, 0xfe, 0x30, 0xe0, 0x05, 0x90, 0x20, 0x02, 0xe0, 0xff, 0xee} },
+{ 0x9299, 16, {0x30, 0xe1, 0x05, 0x90, 0x20, 0x0a, 0xe0, 0xff, 0xee, 0x30, 0xe2, 0x05, 0x90, 0x20, 0x12, 0xe0} },
+{ 0x92a9, 16, {0xff, 0xee, 0x30, 0xe3, 0x05, 0x90, 0x20, 0x1a, 0xe0, 0xff, 0x90, 0x01, 0x62, 0xe0, 0xb5, 0x1e} },
+{ 0x92b9, 10, {0x04, 0xe4, 0xf0, 0x80, 0x05, 0x90, 0x01, 0x62, 0xee, 0xf0} },
+{ 0x92c3, 9, {0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x92cc, 2, {0xa9, 0x03} },
+{ 0x92ce, 16, {0xef, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xab, 0x82, 0xfa, 0xe5} },
+{ 0x92de, 16, {0x6c, 0x45, 0x6d, 0xf5, 0x6e, 0xe9, 0x60, 0x14, 0x8a, 0x83, 0xe5, 0x82, 0x24, 0x04, 0xf5, 0x82} },
+{ 0x92ee, 16, {0xe4, 0x35, 0x83, 0xf5, 0x83, 0xe0, 0x4d, 0xf0, 0xe4, 0xfe, 0x80, 0x13, 0xeb, 0x24, 0x04, 0xf5} },
+{ 0x92fe, 16, {0x82, 0xe4, 0x3a, 0xf5, 0x83, 0xe0, 0xff, 0xed, 0xf4, 0xfc, 0xef, 0x5c, 0xf0, 0xae, 0x6e, 0xeb} },
+{ 0x930e, 16, {0x24, 0x06, 0xf5, 0x82, 0xe4, 0x3a, 0xf5, 0x83, 0xe0, 0x55, 0x6e, 0xfc, 0xb5, 0x06, 0x03, 0xaf} },
+{ 0x931e, 16, {0x05, 0x22, 0xe5, 0x6c, 0x5c, 0xfe, 0xe5, 0x6d, 0x5c, 0xfd, 0xe9, 0x60, 0x16, 0xee, 0x70, 0x04} },
+{ 0x932e, 16, {0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0xae, 0x07, 0xed, 0x70, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f} },
+{ 0x933e, 16, {0x00, 0xad, 0x07, 0xee, 0x60, 0x03, 0xaf, 0x6c, 0x22, 0xed, 0x60, 0x03, 0xaf, 0x6d, 0x22, 0x7f} },
+{ 0x934e, 1, {0x00} },
+{ 0x934f, 1, {0x22} },
+{ 0x9350, 16, {0x7e, 0x7b, 0x7f, 0x80, 0xef, 0x24, 0x01, 0xf5, 0x66, 0xe4, 0x3e, 0xf5, 0x65, 0x75, 0x63, 0x02} },
+{ 0x9360, 16, {0x75, 0x64, 0x4e, 0x8f, 0x82, 0x8e, 0x83, 0x74, 0x0f, 0xf0, 0x85, 0x64, 0x82, 0x85, 0x63, 0x83} },
+{ 0x9370, 16, {0xe0, 0x85, 0x66, 0x82, 0x85, 0x65, 0x83, 0xf0, 0x85, 0x64, 0x82, 0x85, 0x63, 0x83, 0xa3, 0xe0} },
+{ 0x9380, 16, {0x85, 0x66, 0x82, 0x85, 0x65, 0x83, 0xa3, 0xf0, 0x85, 0x66, 0x82, 0x85, 0x65, 0x83, 0xa3, 0xa3} },
+{ 0x9390, 16, {0x74, 0xff, 0xf0, 0xe5, 0x66, 0x24, 0x03, 0xf5, 0x68, 0xe4, 0x35, 0x65, 0xf5, 0x67, 0x85, 0x64} },
+{ 0x93a0, 16, {0x82, 0x85, 0x63, 0x83, 0xe0, 0x14, 0xb4, 0x0b, 0x00, 0x40, 0x03, 0x02, 0x98, 0x43, 0x90, 0x93} },
+{ 0x93b0, 16, {0xb5, 0xf8, 0x28, 0x28, 0x73, 0x02, 0x93, 0xd6, 0x02, 0x94, 0x7c, 0x02, 0x95, 0xba, 0x02, 0x95} },
+{ 0x93c0, 16, {0xda, 0x02, 0x95, 0xda, 0x02, 0x96, 0x7f, 0x02, 0x96, 0xbd, 0x02, 0x96, 0xe4, 0x02, 0x97, 0xa6} },
+{ 0x93d0, 16, {0x02, 0x97, 0xda, 0x02, 0x98, 0x0b, 0xe4, 0xf5, 0x5e, 0xe5, 0x5e, 0x75, 0xf0, 0x08, 0xa4, 0x24} },
+{ 0x93e0, 16, {0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xaf, 0x82, 0xf5, 0x61, 0x8f, 0x62, 0xe4, 0xff, 0xe4, 0xfe} },
+{ 0x93f0, 16, {0xef, 0x60, 0x10, 0x74, 0x28, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe0, 0xf4, 0xf5} },
+{ 0x9400, 16, {0x5f, 0x80, 0x0d, 0x74, 0x28, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe0, 0xf5, 0x5f} },
+{ 0x9410, 16, {0xe5, 0x62, 0x24, 0x07, 0xf5, 0x82, 0xe4, 0x35, 0x61, 0xf5, 0x83, 0xe5, 0x5f, 0xf0, 0xe0, 0xf5} },
+{ 0x9420, 16, {0x60, 0x65, 0x5f, 0x60, 0x3d, 0x85, 0x66, 0x82, 0x85, 0x65, 0x83, 0xa3, 0xa3, 0xe4, 0xf0, 0xe5} },
+{ 0x9430, 16, {0x5e, 0x04, 0xfd, 0x05, 0x68, 0xe5, 0x68, 0xaa, 0x67, 0x70, 0x02, 0x05, 0x67, 0x14, 0xf5, 0x82} },
+{ 0x9440, 16, {0x8a, 0x83, 0xed, 0xf0, 0x05, 0x68, 0xe5, 0x68, 0xac, 0x67, 0x70, 0x02, 0x05, 0x67, 0x14, 0xf5} },
+{ 0x9450, 16, {0x82, 0x8c, 0x83, 0xe5, 0x5f, 0xf0, 0x85, 0x68, 0x82, 0x85, 0x67, 0x83, 0xe5, 0x60, 0xf0, 0x02} },
+{ 0x9460, 16, {0x98, 0x4e, 0x0e, 0xee, 0x64, 0x24, 0x70, 0x88, 0x0f, 0xef, 0x64, 0x02, 0x70, 0x80, 0x05, 0x5e} },
+{ 0x9470, 16, {0xe5, 0x5e, 0x64, 0x04, 0x60, 0x03, 0x02, 0x93, 0xd9, 0x02, 0x98, 0x4e, 0x7e, 0x20, 0x7f, 0x00} },
+{ 0x9480, 16, {0x75, 0x61, 0x20, 0x75, 0x62, 0x00, 0xe4, 0xf5, 0x5e, 0xaf, 0x62, 0xae, 0x61, 0xe4, 0xfd, 0x12} },
+{ 0x9490, 16, {0x81, 0xe0, 0x74, 0x08, 0x25, 0x62, 0xf5, 0x62, 0xe4, 0x35, 0x61, 0xf5, 0x61, 0x05, 0x5e, 0xe5} },
+{ 0x94a0, 16, {0x5e, 0xd3, 0x94, 0x03, 0x40, 0xe3, 0x90, 0x00, 0x04, 0x74, 0x92, 0xf0, 0xa3, 0x74, 0x7e, 0xf0} },
+{ 0x94b0, 16, {0xe4, 0xf5, 0x60, 0x7e, 0x20, 0x7f, 0x00, 0x75, 0x61, 0x20, 0x75, 0x62, 0x00, 0xf5, 0x5e, 0xaf} },
+{ 0x94c0, 16, {0x5e, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xf5, 0x5f, 0x90, 0x01} },
+{ 0x94d0, 16, {0x62, 0xf0, 0x90, 0x01, 0x5e, 0xe4, 0xf0, 0xa3, 0x74, 0x0a, 0xf0, 0x85, 0x62, 0x82, 0x85, 0x61} },
+{ 0x94e0, 16, {0x83, 0xa3, 0x74, 0x02, 0xf0, 0x90, 0x01, 0x62, 0xe0, 0x65, 0x5f, 0x70, 0x39, 0x90, 0x01, 0x5e} },
+{ 0x94f0, 16, {0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x70, 0xee, 0x85, 0x66, 0x82, 0x85, 0x65, 0x83, 0xa3, 0xa3, 0xf0} },
+{ 0x9500, 16, {0xe5, 0x5e, 0x04, 0xff, 0x05, 0x68, 0xe5, 0x68, 0xac, 0x67, 0x70, 0x02, 0x05, 0x67, 0x14, 0xf5} },
+{ 0x9510, 16, {0x82, 0x8c, 0x83, 0xef, 0xf0, 0x85, 0x68, 0x82, 0x85, 0x67, 0x83, 0x74, 0xff, 0xf0, 0xe4, 0x90} },
+{ 0x9520, 16, {0x01, 0x62, 0xf0, 0x75, 0x60, 0xff, 0x90, 0x01, 0x62, 0xe0, 0xff, 0x60, 0x3c, 0x85, 0x66, 0x82} },
+{ 0x9530, 16, {0x85, 0x65, 0x83, 0xa3, 0xa3, 0xe4, 0xf0, 0xe5, 0x5e, 0x04, 0xfe, 0x05, 0x68, 0xe5, 0x68, 0xac} },
+{ 0x9540, 16, {0x67, 0x70, 0x02, 0x05, 0x67, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xee, 0xf0, 0x05, 0x68, 0xe5, 0x68} },
+{ 0x9550, 16, {0xac, 0x67, 0x70, 0x02, 0x05, 0x67, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x85, 0x68, 0x82} },
+{ 0x9560, 16, {0x85, 0x67, 0x83, 0xe5, 0x5f, 0xf0, 0x75, 0x60, 0xff, 0xe5, 0x60, 0x70, 0x16, 0x74, 0x08, 0x25} },
+{ 0x9570, 16, {0x62, 0xf5, 0x62, 0xe4, 0x35, 0x61, 0xf5, 0x61, 0x05, 0x5e, 0xe5, 0x5e, 0x64, 0x04, 0x60, 0x03} },
+{ 0x9580, 16, {0x02, 0x94, 0xbf, 0x7e, 0x20, 0x7f, 0x00, 0x75, 0x61, 0x20, 0x75, 0x62, 0x00, 0xe4, 0xf5, 0x5e} },
+{ 0x9590, 16, {0xaf, 0x62, 0xae, 0x61, 0x7d, 0x01, 0x12, 0x81, 0xe0, 0x74, 0x08, 0x25, 0x62, 0xf5, 0x62, 0xe4} },
+{ 0x95a0, 16, {0x35, 0x61, 0xf5, 0x61, 0x05, 0x5e, 0xe5, 0x5e, 0xd3, 0x94, 0x03, 0x40, 0xe3, 0x90, 0x00, 0x04} },
+{ 0x95b0, 16, {0x74, 0x13, 0xf0, 0xa3, 0x74, 0x12, 0xf0, 0x02, 0x98, 0x4e, 0x85, 0x64, 0x82, 0x85, 0x63, 0x83} },
+{ 0x95c0, 16, {0xa3, 0xe0, 0x14, 0xff, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x90} },
+{ 0x95d0, 16, {0x02, 0x95, 0xf0, 0x90, 0x01, 0x62, 0xf0, 0x02, 0x98, 0x4e, 0x90, 0x01, 0x5e, 0x74, 0x03, 0xf0} },
+{ 0x95e0, 16, {0xa3, 0x74, 0xe8, 0xf0, 0xe4, 0xf5, 0x60, 0x90, 0x02, 0x95, 0xe0, 0xff, 0x90, 0x01, 0x62, 0xe0} },
+{ 0x95f0, 16, {0xb5, 0x07, 0x1e, 0x90, 0x01, 0x5e, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x70, 0xea, 0x85, 0x66, 0x82} },
+{ 0x9600, 16, {0x85, 0x65, 0x83, 0xa3, 0xa3, 0xf0, 0x85, 0x68, 0x82, 0x85, 0x67, 0x83, 0x74, 0xff, 0xf0, 0xf5} },
+{ 0x9610, 16, {0x60, 0xe5, 0x60, 0x60, 0x03, 0x02, 0x98, 0x4e, 0x90, 0x01, 0x5e, 0xf0, 0xa3, 0x74, 0x96, 0xf0} },
+{ 0x9620, 16, {0x90, 0x01, 0x5e, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x70, 0xf6, 0x7f, 0x02, 0x12, 0x81, 0x11, 0xc3} },
+{ 0x9630, 16, {0xee, 0x64, 0x80, 0x94, 0x80, 0x40, 0xf3, 0xef, 0x54, 0x0f, 0xf5, 0x60, 0x90, 0x02, 0x95, 0xe0} },
+{ 0x9640, 16, {0x55, 0x60, 0x70, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0x8f, 0x5f, 0x85, 0x64, 0x82, 0x85} },
+{ 0x9650, 16, {0x63, 0x83, 0xe0, 0xb4, 0x05, 0x0c, 0xe5, 0x5f, 0x70, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00} },
+{ 0x9660, 16, {0x8f, 0x5f, 0xe5, 0x5f, 0x70, 0x03, 0x02, 0x98, 0x4e, 0x85, 0x66, 0x82, 0x85, 0x65, 0x83, 0xa3} },
+{ 0x9670, 16, {0xa3, 0xe4, 0xf0, 0x85, 0x68, 0x82, 0x85, 0x67, 0x83, 0xe5, 0x60, 0xf0, 0x02, 0x98, 0x4e, 0x7e} },
+{ 0x9680, 16, {0x20, 0x7f, 0x00, 0x75, 0x61, 0x20, 0x75, 0x62, 0x00, 0xaf, 0x62, 0xae, 0x61, 0xe4, 0xfd, 0x12} },
+{ 0x9690, 16, {0x81, 0xe0, 0x85, 0x62, 0x82, 0x85, 0x61, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0x44, 0x80, 0xf0, 0x85} },
+{ 0x96a0, 16, {0x62, 0x82, 0x85, 0x61, 0x83, 0x74, 0x01, 0xf0, 0xa3, 0xe4, 0xf0, 0x85, 0x62, 0x82, 0x85, 0x61} },
+{ 0x96b0, 16, {0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0x54, 0x7f, 0xf0, 0xd2, 0x04, 0x02, 0x98, 0x4e, 0xc2, 0x04, 0x7e} },
+{ 0x96c0, 16, {0x20, 0x7f, 0x00, 0x75, 0x61, 0x20, 0x75, 0x62, 0x00, 0xe5, 0x62, 0x24, 0x05, 0xf5, 0x82, 0xe4} },
+{ 0x96d0, 16, {0x35, 0x61, 0xf5, 0x83, 0xe0, 0x30, 0xe6, 0xf1, 0xaf, 0x62, 0xae, 0x61, 0x7d, 0x01, 0x12, 0x81} },
+{ 0x96e0, 16, {0xe0, 0x02, 0x98, 0x4e, 0xe4, 0xf5, 0x60, 0xf5, 0x5e, 0xe5, 0x5e, 0x75, 0xf0, 0x08, 0xa4, 0x24} },
+{ 0x96f0, 16, {0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xaf, 0x82, 0xf5, 0x61, 0x8f, 0x62, 0xfe, 0xe4, 0xfd, 0x12} },
+{ 0x9700, 16, {0x81, 0xe0, 0xe5, 0x62, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x61, 0xf5, 0x83, 0xe0, 0x54, 0xfc} },
+{ 0x9710, 16, {0xf0, 0xaf, 0x5e, 0x7d, 0x01, 0x7b, 0x01, 0x75, 0x6c, 0x80, 0x75, 0x6d, 0x40, 0x12, 0x92, 0xcc} },
+{ 0x9720, 16, {0x8f, 0x60, 0xe5, 0x60, 0x70, 0x11, 0xaf, 0x5e, 0x7d, 0x02, 0x7b, 0x01, 0x75, 0x6c, 0x10, 0x75} },
+{ 0x9730, 16, {0x6d, 0x20, 0x12, 0x92, 0xcc, 0x8f, 0x60, 0xe5, 0x60, 0x70, 0x10, 0xaf, 0x5e, 0x7d, 0x01, 0xfb} },
+{ 0x9740, 16, {0x75, 0x6c, 0x80, 0x75, 0x6d, 0x40, 0x12, 0x92, 0xcc, 0x8f, 0x60, 0xe5, 0x60, 0x70, 0x10, 0xaf} },
+{ 0x9750, 16, {0x5e, 0x7d, 0x02, 0xfb, 0x75, 0x6c, 0x10, 0x75, 0x6d, 0x20, 0x12, 0x92, 0xcc, 0x8f, 0x60, 0xaf} },
+{ 0x9760, 16, {0x62, 0xae, 0x61, 0x7d, 0x01, 0x12, 0x81, 0xe0, 0xe5, 0x60, 0x60, 0x2b, 0x85, 0x66, 0x82, 0x85} },
+{ 0x9770, 16, {0x65, 0x83, 0xa3, 0xa3, 0xe4, 0xf0, 0xe5, 0x5e, 0x04, 0xff, 0x05, 0x68, 0xe5, 0x68, 0xac, 0x67} },
+{ 0x9780, 16, {0x70, 0x02, 0x05, 0x67, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x85, 0x68, 0x82, 0x85, 0x67} },
+{ 0x9790, 16, {0x83, 0xe5, 0x60, 0xf0, 0x02, 0x98, 0x4e, 0x05, 0x5e, 0xe5, 0x5e, 0xd3, 0x94, 0x03, 0x50, 0x03} },
+{ 0x97a0, 16, {0x02, 0x96, 0xe9, 0x02, 0x98, 0x4e, 0xe4, 0x90, 0x02, 0xd3, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3} },
+{ 0x97b0, 16, {0xf0, 0xa3, 0xf0, 0xa3, 0x74, 0x10, 0xf0, 0xa3, 0x74, 0x98, 0xf0, 0xa3, 0x74, 0x6d, 0xf0, 0x7e} },
+{ 0x97c0, 16, {0x02, 0x7f, 0xd3, 0x12, 0x80, 0x00, 0xef, 0x64, 0x08, 0x70, 0x03, 0x02, 0x98, 0x4e, 0x85, 0x66} },
+{ 0x97d0, 16, {0x82, 0x85, 0x65, 0x83, 0xa3, 0xa3, 0xe4, 0xf0, 0x80, 0x74, 0xe4, 0x90, 0x02, 0xd3, 0xf0, 0xa3} },
+{ 0x97e0, 16, {0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0x74, 0x10, 0xf0, 0xa3, 0xe5, 0x67, 0xf0, 0xa3} },
+{ 0x97f0, 16, {0xe5, 0x68, 0xf0, 0x7e, 0x02, 0x7f, 0xd3, 0x12, 0x19, 0xc1, 0xef, 0x64, 0x08, 0x60, 0x4f, 0x85} },
+{ 0x9800, 16, {0x66, 0x82, 0x85, 0x65, 0x83, 0xa3, 0xa3, 0xe4, 0xf0, 0x80, 0x43, 0xe4, 0x90, 0x02, 0xd3, 0xf0} },
+{ 0x9810, 16, {0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0x74, 0x10, 0xf0, 0xe5, 0x64, 0x24, 0x02} },
+{ 0x9820, 16, {0x90, 0x02, 0xda, 0xf0, 0xe4, 0x35, 0x63, 0x90, 0x02, 0xd9, 0xf0, 0x7e, 0x02, 0x7f, 0xd3, 0x12} },
+{ 0x9830, 16, {0x80, 0x00, 0xef, 0x64, 0x08, 0x60, 0x17, 0x85, 0x66, 0x82, 0x85, 0x65, 0x83, 0xa3, 0xa3, 0xe4} },
+{ 0x9840, 16, {0xf0, 0x80, 0x0b, 0x85, 0x66, 0x82, 0x85, 0x65, 0x83, 0xa3, 0xa3, 0x74, 0x01, 0xf0, 0x90, 0x01} },
+{ 0x9850, 16, {0x5e, 0xe4, 0xf0, 0xa3, 0x74, 0x0a, 0xf0, 0x90, 0x01, 0x5e, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x70} },
+{ 0x9860, 12, {0xf6, 0x90, 0x7f, 0xc3, 0x74, 0x24, 0xf0, 0xe4, 0x90, 0x02, 0x4d, 0xf0} },
+{ 0x986c, 1, {0x22} },
+{ 0x986d, 16, {0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0} },
+{ 0x987d, 16, {0xe4, 0xfd, 0x74, 0x01, 0x7e, 0x00, 0xa8, 0x05, 0x08, 0x80, 0x05, 0xc3, 0x33, 0xce, 0x33, 0xce} },
+{ 0x988d, 16, {0xd8, 0xf9, 0xff, 0xe5, 0x3b, 0xfb, 0xe4, 0xef, 0x5b, 0x70, 0x03, 0x02, 0x99, 0x45, 0xed, 0x75} },
+{ 0x989d, 16, {0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xaf, 0x82, 0xfe, 0xf5, 0x83, 0xe5} },
+{ 0x98ad, 16, {0x82, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0xe0, 0x54, 0x60, 0x64, 0x60, 0x60} },
+{ 0x98bd, 16, {0x03, 0x02, 0x99, 0x45, 0xef, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x3e, 0xf5, 0x83, 0xe0, 0xfc, 0x74} },
+{ 0x98cd, 16, {0x36, 0x2d, 0xf8, 0xec, 0xf6, 0x30, 0xe5, 0x70, 0x74, 0x96, 0x2d, 0xf5, 0x82, 0xe4, 0x34, 0x02} },
+{ 0x98dd, 16, {0xf5, 0x83, 0xe0, 0x60, 0x63, 0xed, 0x25, 0xe0, 0x24, 0x8d, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5} },
+{ 0x98ed, 16, {0x83, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9a, 0xa4, 0x85, 0xf0, 0x82, 0xf5, 0x83, 0xe0, 0x8f, 0x82} },
+{ 0x98fd, 16, {0x8e, 0x83, 0xf0, 0x74, 0x96, 0x2d, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe0, 0x14, 0xf0} },
+{ 0x990d, 16, {0x70, 0x36, 0xed, 0x25, 0xe0, 0x24, 0xc7, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe4, 0xf0} },
+{ 0x991d, 16, {0xed, 0x25, 0xe0, 0xff, 0xc3, 0x74, 0x0c, 0x9f, 0x75, 0xf0, 0x40, 0xa4, 0x24, 0x40, 0xf5, 0x82} },
+{ 0x992d, 16, {0xe5, 0xf0, 0x34, 0x7b, 0xaf, 0x82, 0xfe, 0xed, 0x25, 0xe0, 0x24, 0x8d, 0xf5, 0x82, 0xe4, 0x34} },
+{ 0x993d, 16, {0x02, 0xf5, 0x83, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x0d, 0xed, 0x64, 0x04, 0x60, 0x03, 0x02, 0x98} },
+{ 0x994d, 1, {0x7f} },
+{ 0x994e, 1, {0x22} },
+{ 0x994f, 16, {0xe7, 0x09, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x46, 0xe7, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x3e} },
+{ 0x995f, 16, {0x88, 0x82, 0x8c, 0x83, 0xe7, 0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x32, 0xe3, 0x09, 0xf6, 0x08} },
+{ 0x996f, 16, {0xdf, 0xfa, 0x80, 0x78, 0xe3, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x70, 0x88, 0x82, 0x8c, 0x83} },
+{ 0x997f, 16, {0xe3, 0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x64, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf6, 0x08} },
+{ 0x998f, 16, {0xdf, 0xfa, 0x80, 0x58, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x4c} },
+{ 0x999f, 16, {0x80, 0xd2, 0x80, 0xfa, 0x80, 0xc6, 0x80, 0xd4, 0x80, 0x69, 0x80, 0xf2, 0x80, 0x33, 0x80, 0x10} },
+{ 0x99af, 16, {0x80, 0xa6, 0x80, 0xea, 0x80, 0x9a, 0x80, 0xa8, 0x80, 0xda, 0x80, 0xe2, 0x80, 0xca, 0x80, 0x33} },
+{ 0x99bf, 16, {0x89, 0x82, 0x8a, 0x83, 0xec, 0xfa, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83} },
+{ 0x99cf, 16, {0xcc, 0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf, 0xe9, 0xde, 0xe7, 0x80} },
+{ 0x99df, 16, {0x0d, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf6, 0x08, 0xdf, 0xf9, 0xec, 0xfa, 0xa9, 0xf0} },
+{ 0x99ef, 16, {0xed, 0xfb, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xec, 0xfa, 0xe0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc} },
+{ 0x99ff, 16, {0xc5, 0x83, 0xcc, 0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf, 0xea, 0xde} },
+{ 0x9a0f, 16, {0xe8, 0x80, 0xdb, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf2, 0x08, 0xdf, 0xf9, 0x80, 0xcc} },
+{ 0x9a1f, 16, {0x88, 0xf0, 0xed, 0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, 0xc2, 0xf5, 0x82, 0xeb, 0x24, 0x02, 0xb4} },
+{ 0x9a2f, 16, {0x04, 0x00, 0x50, 0xb8, 0x23, 0x23, 0x45, 0x82, 0xf5, 0x82, 0xef, 0x4e, 0x60, 0xae, 0xef, 0x60} },
+{ 0x9a3f, 9, {0x01, 0x0e, 0xe5, 0x82, 0x23, 0x90, 0x99, 0x9f, 0x73} },
+{ 0x9a48, 16, {0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb, 0xfe, 0x02} },
+{ 0x9a58, 9, {0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22} },
+{ 0x9a61, 16, {0xbb, 0x01, 0x0c, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50} },
+{ 0x9a71, 16, {0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22} },
+{ 0x9a81, 13, {0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe4, 0x93, 0x22} },
+{ 0x9a8e, 16, {0xc5, 0xf0, 0xf8, 0xa3, 0xe0, 0x28, 0xf0, 0xc5, 0xf0, 0xf8, 0xe5, 0x82, 0x15, 0x82, 0x70, 0x02} },
+{ 0x9a9e, 6, {0x15, 0x83, 0xe0, 0x38, 0xf0, 0x22} },
+{ 0x9aa4, 16, {0xa3, 0xf8, 0xe0, 0xc5, 0xf0, 0x25, 0xf0, 0xf0, 0xe5, 0x82, 0x15, 0x82, 0x70, 0x02, 0x15, 0x83} },
+{ 0x9ab4, 6, {0xe0, 0xc8, 0x38, 0xf0, 0xe8, 0x22} },
+{ 0x9aba, 16, {0xbb, 0x01, 0x10, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0xf5, 0xf0} },
+{ 0x9aca, 16, {0xa3, 0xe0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, 0xf8, 0x86, 0xf0, 0x08, 0xe6, 0x22, 0xbb, 0xfe} },
+{ 0x9ada, 16, {0x0a, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0xf5, 0xf0, 0x08, 0xe2, 0x22, 0xe5, 0x83, 0x2a, 0xf5, 0x83} },
+{ 0x9aea, 8, {0xe9, 0x93, 0xf5, 0xf0, 0xa3, 0xe9, 0x93, 0x22} },
+{ 0x9af2, 16, {0x75, 0xf0, 0x08, 0x75, 0x82, 0x00, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xcd, 0x33, 0xcd, 0xcc} },
+{ 0x9b02, 16, {0x33, 0xcc, 0xc5, 0x82, 0x33, 0xc5, 0x82, 0x9b, 0xed, 0x9a, 0xec, 0x99, 0xe5, 0x82, 0x98, 0x40} },
+{ 0x9b12, 16, {0x0c, 0xf5, 0x82, 0xee, 0x9b, 0xfe, 0xed, 0x9a, 0xfd, 0xec, 0x99, 0xfc, 0x0f, 0xd5, 0xf0, 0xd6} },
+{ 0x9b22, 16, {0xe4, 0xce, 0xfb, 0xe4, 0xcd, 0xfa, 0xe4, 0xcc, 0xf9, 0xa8, 0x82, 0x22, 0xb8, 0x00, 0xc1, 0xb9} },
+{ 0x9b32, 16, {0x00, 0x59, 0xba, 0x00, 0x2d, 0xec, 0x8b, 0xf0, 0x84, 0xcf, 0xce, 0xcd, 0xfc, 0xe5, 0xf0, 0xcb} },
+{ 0x9b42, 16, {0xf9, 0x78, 0x18, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xec, 0x33, 0xfc, 0xeb} },
+{ 0x9b52, 16, {0x33, 0xfb, 0x10, 0xd7, 0x03, 0x99, 0x40, 0x04, 0xeb, 0x99, 0xfb, 0x0f, 0xd8, 0xe5, 0xe4, 0xf9} },
+{ 0x9b62, 16, {0xfa, 0x22, 0x78, 0x18, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xec, 0x33, 0xfc} },
+{ 0x9b72, 16, {0xc9, 0x33, 0xc9, 0x10, 0xd7, 0x05, 0x9b, 0xe9, 0x9a, 0x40, 0x07, 0xec, 0x9b, 0xfc, 0xe9, 0x9a} },
+{ 0x9b82, 16, {0xf9, 0x0f, 0xd8, 0xe0, 0xe4, 0xc9, 0xfa, 0xe4, 0xcc, 0xfb, 0x22, 0x75, 0xf0, 0x10, 0xef, 0x2f} },
+{ 0x9b92, 16, {0xff, 0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xcc, 0x33, 0xcc, 0xc8, 0x33, 0xc8, 0x10, 0xd7, 0x07} },
+{ 0x9ba2, 16, {0x9b, 0xec, 0x9a, 0xe8, 0x99, 0x40, 0x0a, 0xed, 0x9b, 0xfd, 0xec, 0x9a, 0xfc, 0xe8, 0x99, 0xf8} },
+{ 0x9bb2, 14, {0x0f, 0xd5, 0xf0, 0xda, 0xe4, 0xcd, 0xfb, 0xe4, 0xcc, 0xfa, 0xe4, 0xc8, 0xf9, 0x22} },
+{ 0x9bc0, 16, {0xeb, 0x9f, 0xf5, 0xf0, 0xea, 0x9e, 0x42, 0xf0, 0xe9, 0x9d, 0x42, 0xf0, 0xe8, 0x9c, 0x45, 0xf0} },
+{ 0x9bd0, 1, {0x22} },
+{ 0x9bd1, 16, {0xe8, 0x60, 0x0f, 0xec, 0xc3, 0x13, 0xfc, 0xed, 0x13, 0xfd, 0xee, 0x13, 0xfe, 0xef, 0x13, 0xff} },
+{ 0x9be1, 3, {0xd8, 0xf1, 0x22} },
+{ 0x9be4, 16, {0x08, 0x08, 0x08, 0xe6, 0xcf, 0x2f, 0xf6, 0x18, 0xe6, 0xce, 0x3e, 0xf6, 0x18, 0xe6, 0xcd, 0x3d} },
+{ 0x9bf4, 7, {0xf6, 0x18, 0xe6, 0xcc, 0x3c, 0xf6, 0x22} },
+{ 0x9bfb, 12, {0xec, 0xf0, 0xa3, 0xed, 0xf0, 0xa3, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x22} },
+{ 0x9c07, 16, {0xa8, 0x82, 0x85, 0x83, 0xf0, 0xd0, 0x83, 0xd0, 0x82, 0x12, 0x9c, 0x1e, 0x12, 0x9c, 0x1e, 0x12} },
+{ 0x9c17, 16, {0x9c, 0x1e, 0x12, 0x9c, 0x1e, 0xe4, 0x73, 0xe4, 0x93, 0xa3, 0xc5, 0x83, 0xc5, 0xf0, 0xc5, 0x83} },
+{ 0x9c27, 16, {0xc8, 0xc5, 0x82, 0xc8, 0xf0, 0xa3, 0xc5, 0x83, 0xc5, 0xf0, 0xc5, 0x83, 0xc8, 0xc5, 0x82, 0xc8} },
+{ 0x9c37, 1, {0x22} },
+{ 0xffff, 0, {0x00} }
+};
+
+#ifdef DEBUG
+static const struct whiteheat_hex_record whiteheat_loader[] = {
+{ 0x0000, 3, {0x02, 0x09, 0x8d} },
+{ 0x0033, 3, {0x02, 0x0e, 0x70} },
+{ 0x0043, 3, {0x02, 0x0b, 0x00} },
+{ 0x004b, 3, {0x02, 0x05, 0xb3} },
+{ 0x0100, 16, {0x90, 0x7f, 0xa5, 0xe0, 0x54, 0x10, 0xff, 0xc4, 0x54, 0x0f, 0x44, 0x50, 0xf5, 0x0f, 0x13, 0xe4} },
+{ 0x0110, 16, {0x33, 0xf5, 0x11, 0x90, 0x7f, 0xe9, 0xe0, 0x24, 0x5e, 0xb4, 0x07, 0x00, 0x40, 0x03, 0x02, 0x03} },
+{ 0x0120, 16, {0x7c, 0x90, 0x01, 0x28, 0xf8, 0x28, 0x28, 0x73, 0x02, 0x01, 0xbc, 0x02, 0x01, 0xbc, 0x02, 0x01} },
+{ 0x0130, 16, {0x91, 0x02, 0x01, 0x3d, 0x02, 0x01, 0x53, 0x02, 0x01, 0x6f, 0x02, 0x01, 0x9a, 0x90, 0x7f, 0x00} },
+{ 0x0140, 16, {0xe5, 0x11, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0} },
+{ 0x0150, 16, {0x02, 0x03, 0x7c, 0x90, 0x7f, 0x92, 0xe0, 0xff, 0xc4, 0x54, 0x0f, 0x90, 0x7f, 0x00, 0xf0, 0x90} },
+{ 0x0160, 16, {0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x02, 0x03, 0x7c, 0x12} },
+{ 0x0170, 16, {0x0a, 0x89, 0x50, 0x07, 0xe4, 0x90, 0x7f, 0x00, 0xf0, 0x80, 0x06, 0x90, 0x7f, 0x00, 0x74, 0x0f} },
+{ 0x0180, 16, {0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x02, 0x03} },
+{ 0x0190, 16, {0x7c, 0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x0f, 0x02, 0x03, 0x7c, 0x90, 0x7f, 0x00, 0x74, 0x07, 0xf0} },
+{ 0x01a0, 16, {0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x7f, 0xe8, 0x7e} },
+{ 0x01b0, 16, {0x03, 0x12, 0x0d, 0xd5, 0xd2, 0x06, 0x12, 0x0d, 0x0d, 0x02, 0x03, 0x7c, 0x90, 0x7f, 0xea, 0xe0} },
+{ 0x01c0, 16, {0x75, 0x29, 0x00, 0xf5, 0x2a, 0xa3, 0xe0, 0xfe, 0xe4, 0xee, 0x42, 0x29, 0x90, 0x7f, 0xee, 0xe0} },
+{ 0x01d0, 16, {0x75, 0x2b, 0x00, 0xf5, 0x2c, 0xa3, 0xe0, 0xfe, 0xe4, 0xee, 0x42, 0x2b, 0x90, 0x7f, 0xe8, 0xe0} },
+{ 0x01e0, 16, {0x64, 0xc0, 0x60, 0x03, 0x02, 0x02, 0xc9, 0xe5, 0x2c, 0x45, 0x2b, 0x70, 0x03, 0x02, 0x03, 0x7c} },
+{ 0x01f0, 16, {0xc3, 0xe5, 0x2c, 0x94, 0x40, 0xe5, 0x2b, 0x94, 0x00, 0x50, 0x08, 0x85, 0x2b, 0x2d, 0x85, 0x2c} },
+{ 0x0200, 16, {0x2e, 0x80, 0x06, 0x75, 0x2d, 0x00, 0x75, 0x2e, 0x40, 0x90, 0x7f, 0xe9, 0xe0, 0x64, 0xa3, 0x70} },
+{ 0x0210, 16, {0x34, 0xf5, 0x31, 0xf5, 0x32, 0xc3, 0xe5, 0x32, 0x95, 0x2e, 0xe5, 0x31, 0x95, 0x2d, 0x50, 0x5c} },
+{ 0x0220, 16, {0xe5, 0x2a, 0x25, 0x32, 0xf5, 0x82, 0xe5, 0x31, 0x35, 0x29, 0xf5, 0x83, 0xe0, 0xff, 0x74, 0x00} },
+{ 0x0230, 16, {0x25, 0x32, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xef, 0xf0, 0x05, 0x32, 0xe5, 0x32, 0x70} },
+{ 0x0240, 16, {0x02, 0x05, 0x31, 0x80, 0xd0, 0xe4, 0xf5, 0x31, 0xf5, 0x32, 0xc3, 0xe5, 0x32, 0x95, 0x2e, 0xe5} },
+{ 0x0250, 16, {0x31, 0x95, 0x2d, 0x50, 0x18, 0x74, 0x00, 0x25, 0x32, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83} },
+{ 0x0260, 16, {0x74, 0xcd, 0xf0, 0x05, 0x32, 0xe5, 0x32, 0x70, 0x02, 0x05, 0x31, 0x80, 0xdd, 0xaf, 0x2a, 0xae} },
+{ 0x0270, 16, {0x29, 0xad, 0x2e, 0x7a, 0x7f, 0x79, 0x00, 0x7b, 0x00, 0x12, 0x0b, 0xf4, 0x90, 0x7f, 0xb5, 0xe5} },
+{ 0x0280, 16, {0x2e, 0xf0, 0xe5, 0x2e, 0x25, 0x2a, 0xf5, 0x2a, 0xe5, 0x2d, 0x35, 0x29, 0xf5, 0x29, 0xc3, 0xe5} },
+{ 0x0290, 16, {0x2c, 0x95, 0x2e, 0xf5, 0x2c, 0xe5, 0x2b, 0x95, 0x2d, 0xf5, 0x2b, 0x90, 0x7f, 0x92, 0xe0, 0xff} },
+{ 0x02a0, 16, {0xc4, 0x54, 0x0f, 0x75, 0x2f, 0x00, 0xf5, 0x30, 0xd3, 0x94, 0x00, 0xe5, 0x2f, 0x94, 0x00, 0x50} },
+{ 0x02b0, 16, {0x0c, 0x90, 0x7f, 0xb4, 0xe0, 0x20, 0xe1, 0x03, 0x02, 0x01, 0xe7, 0x80, 0xf4, 0x90, 0x7f, 0xb4} },
+{ 0x02c0, 16, {0xe0, 0x20, 0xe2, 0x03, 0x02, 0x01, 0xe7, 0x80, 0xf4, 0x90, 0x7f, 0xe8, 0xe0, 0x64, 0x40, 0x60} },
+{ 0x02d0, 16, {0x03, 0x02, 0x03, 0x7c, 0xe5, 0x2c, 0x45, 0x2b, 0x70, 0x03, 0x02, 0x03, 0x7c, 0xe4, 0x90, 0x7f} },
+{ 0x02e0, 16, {0xc5, 0xf0, 0x90, 0x7f, 0x92, 0xe0, 0xff, 0xc4, 0x54, 0x0f, 0x75, 0x2f, 0x00, 0xf5, 0x30, 0xd3} },
+{ 0x02f0, 16, {0x94, 0x00, 0xe5, 0x2f, 0x94, 0x00, 0x50, 0x09, 0x90, 0x7f, 0xc4, 0xe0, 0x30, 0xe1, 0x09, 0x80} },
+{ 0x0300, 16, {0xf7, 0x90, 0x7f, 0xb4, 0xe0, 0x20, 0xe3, 0xf9, 0x90, 0x7f, 0xc5, 0xe0, 0x75, 0x2d, 0x00, 0xf5} },
+{ 0x0310, 16, {0x2e, 0x90, 0x7f, 0xe9, 0xe0, 0x64, 0xa3, 0x70, 0x38, 0x90, 0x20, 0x6b, 0xf0, 0xf5, 0x31, 0xf5} },
+{ 0x0320, 16, {0x32, 0xc3, 0xe5, 0x32, 0x95, 0x2e, 0xe5, 0x31, 0x95, 0x2d, 0x50, 0x34, 0x74, 0xc0, 0x25, 0x32} },
+{ 0x0330, 16, {0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x2a, 0x25, 0x32, 0xf5, 0x82, 0xe5} },
+{ 0x0340, 16, {0x31, 0x35, 0x29, 0xf5, 0x83, 0xef, 0xf0, 0x05, 0x32, 0xe5, 0x32, 0x70, 0x02, 0x05, 0x31, 0x80} },
+{ 0x0350, 16, {0xd0, 0xaf, 0x2a, 0xae, 0x29, 0xad, 0x2e, 0x7a, 0x7e, 0x79, 0xc0, 0x7b, 0xc0, 0x12, 0x0c, 0x80} },
+{ 0x0360, 16, {0xe5, 0x2e, 0x25, 0x2a, 0xf5, 0x2a, 0xe5, 0x2d, 0x35, 0x29, 0xf5, 0x29, 0xc3, 0xe5, 0x2c, 0x95} },
+{ 0x0370, 13, {0x2e, 0xf5, 0x2c, 0xe5, 0x2b, 0x95, 0x2d, 0xf5, 0x2b, 0x02, 0x02, 0xd4, 0xc3} },
+{ 0x037d, 1, {0x22} },
+{ 0x037e, 16, {0x90, 0x7f, 0xe9, 0xe0, 0x70, 0x03, 0x02, 0x04, 0x56, 0x14, 0x70, 0x03, 0x02, 0x04, 0xd2, 0x24} },
+{ 0x038e, 16, {0xfe, 0x70, 0x03, 0x02, 0x05, 0x46, 0x24, 0xfb, 0x70, 0x03, 0x02, 0x04, 0x50, 0x14, 0x70, 0x03} },
+{ 0x039e, 16, {0x02, 0x04, 0x4a, 0x14, 0x70, 0x03, 0x02, 0x04, 0x3e, 0x14, 0x70, 0x03, 0x02, 0x04, 0x44, 0x24} },
+{ 0x03ae, 16, {0x05, 0x60, 0x03, 0x02, 0x05, 0x9a, 0x12, 0x0e, 0x7b, 0x40, 0x03, 0x02, 0x05, 0xab, 0x90, 0x7f} },
+{ 0x03be, 16, {0xeb, 0xe0, 0x24, 0xfe, 0x60, 0x16, 0x14, 0x60, 0x40, 0x24, 0x02, 0x70, 0x69, 0x74, 0x11, 0x90} },
+{ 0x03ce, 16, {0x7f, 0xd4, 0xf0, 0x74, 0x00, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xea, 0xe0} },
+{ 0x03de, 16, {0xff, 0x12, 0x0b, 0x58, 0x8b, 0x26, 0x8a, 0x27, 0x89, 0x28, 0xea, 0x49, 0x60, 0x11, 0xae, 0x02} },
+{ 0x03ee, 16, {0xee, 0x90, 0x7f, 0xd4, 0xf0, 0xaf, 0x01, 0xef, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x05, 0xab, 0x90} },
+{ 0x03fe, 16, {0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xea, 0xe0, 0xff, 0x12, 0x0c} },
+{ 0x040e, 16, {0x3f, 0x8b, 0x26, 0x8a, 0x27, 0x89, 0x28, 0xea, 0x49, 0x60, 0x11, 0xae, 0x02, 0xee, 0x90, 0x7f} },
+{ 0x041e, 16, {0xd4, 0xf0, 0xaf, 0x01, 0xef, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xb4, 0xe0} },
+{ 0x042e, 16, {0x44, 0x01, 0xf0, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0xab} },
+{ 0x043e, 16, {0x12, 0x0e, 0x52, 0x02, 0x05, 0xab, 0x12, 0x0e, 0x60, 0x02, 0x05, 0xab, 0x12, 0x0a, 0xf7, 0x02} },
+{ 0x044e, 16, {0x05, 0xab, 0x12, 0x08, 0xf1, 0x02, 0x05, 0xab, 0x12, 0x0e, 0x7d, 0x40, 0x03, 0x02, 0x05, 0xab} },
+{ 0x045e, 16, {0x90, 0x7f, 0xe8, 0xe0, 0x24, 0x7f, 0x60, 0x24, 0x14, 0x60, 0x31, 0x24, 0x02, 0x70, 0x5b, 0xa2} },
+{ 0x046e, 16, {0x00, 0xe4, 0x33, 0xff, 0x25, 0xe0, 0xff, 0xa2, 0x02, 0xe4, 0x33, 0x4f, 0x90, 0x7f, 0x00, 0xf0} },
+{ 0x047e, 16, {0xe4, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0xab, 0xe4, 0x90, 0x7f, 0x00} },
+{ 0x048e, 16, {0xf0, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xec, 0xe0} },
+{ 0x049e, 16, {0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4} },
+{ 0x04ae, 16, {0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe0, 0x54, 0xfd, 0x90, 0x7f, 0x00, 0xf0, 0xe4, 0xa3} },
+{ 0x04be, 16, {0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01} },
+{ 0x04ce, 16, {0xf0, 0x02, 0x05, 0xab, 0x12, 0x0e, 0x7f, 0x40, 0x03, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xe8, 0xe0} },
+{ 0x04de, 16, {0x24, 0xfe, 0x60, 0x1d, 0x24, 0x02, 0x60, 0x03, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xea, 0xe0, 0xb4} },
+{ 0x04ee, 16, {0x01, 0x05, 0xc2, 0x00, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05} },
+{ 0x04fe, 16, {0xab, 0x90, 0x7f, 0xea, 0xe0, 0x70, 0x38, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4} },
+{ 0x050e, 16, {0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f} },
+{ 0x051e, 16, {0xf5, 0x83, 0xe4, 0xf0, 0x90, 0x7f, 0xec, 0xe0, 0x54, 0x80, 0xff, 0x13, 0x13, 0x13, 0x54, 0x1f} },
+{ 0x052e, 16, {0xff, 0xe0, 0x54, 0x07, 0x2f, 0x90, 0x7f, 0xd7, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x6e, 0x90} },
+{ 0x053e, 16, {0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x65, 0x12, 0x0e, 0x81, 0x50, 0x60, 0x90, 0x7f, 0xe8} },
+{ 0x054e, 16, {0xe0, 0x24, 0xfe, 0x60, 0x18, 0x24, 0x02, 0x70, 0x54, 0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x04} },
+{ 0x055e, 16, {0xd2, 0x00, 0x80, 0x49, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x40, 0x90, 0x7f, 0xea} },
+{ 0x056e, 16, {0xe0, 0x70, 0x20, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0} },
+{ 0x057e, 16, {0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0x74, 0x01} },
+{ 0x058e, 16, {0xf0, 0x80, 0x1a, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x11, 0xe4, 0x90, 0x20, 0x6a} },
+{ 0x059e, 16, {0xf0, 0x12, 0x01, 0x00, 0x50, 0x07, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xb4} },
+{ 0x05ae, 4, {0xe0, 0x44, 0x02, 0xf0} },
+{ 0x05b2, 1, {0x22} },
+{ 0x05b3, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xc0} },
+{ 0x05c3, 16, {0xd0, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x06, 0xc0, 0x07, 0x90, 0x7f, 0xa5} },
+{ 0x05d3, 16, {0xe0, 0x30, 0xe2, 0x06, 0x75, 0x0d, 0x06, 0x02, 0x06, 0x7f, 0x90, 0x7f, 0xa5, 0xe0, 0x20, 0xe1} },
+{ 0x05e3, 16, {0x0c, 0xe5, 0x0d, 0x64, 0x02, 0x60, 0x06, 0x75, 0x0d, 0x07, 0x02, 0x06, 0x7f, 0xaf, 0x0d, 0xef} },
+{ 0x05f3, 16, {0x24, 0xfe, 0x60, 0x48, 0x14, 0x60, 0x2c, 0x24, 0xfe, 0x60, 0x77, 0x24, 0x04, 0x60, 0x03, 0x02} },
+{ 0x0603, 16, {0x06, 0x7f, 0xab, 0x09, 0xaa, 0x0a, 0xa9, 0x0b, 0xaf, 0x0c, 0x05, 0x0c, 0x8f, 0x82, 0x75, 0x83} },
+{ 0x0613, 16, {0x00, 0x12, 0x07, 0x85, 0x90, 0x7f, 0xa6, 0xf0, 0xe5, 0x0c, 0x65, 0x08, 0x70, 0x5e, 0x75, 0x0d} },
+{ 0x0623, 16, {0x05, 0x80, 0x59, 0x90, 0x7f, 0xa6, 0xe0, 0xab, 0x09, 0xaa, 0x0a, 0xa9, 0x0b, 0xae, 0x0c, 0x8e} },
+{ 0x0633, 16, {0x82, 0x75, 0x83, 0x00, 0x12, 0x07, 0xb2, 0x75, 0x0d, 0x02, 0x80, 0x40, 0xe5, 0x08, 0x24, 0xfe} },
+{ 0x0643, 16, {0xb5, 0x0c, 0x07, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x20, 0xf0, 0xe5, 0x08, 0x14, 0xb5, 0x0c, 0x0a} },
+{ 0x0653, 16, {0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0xe4, 0xf5, 0x0d, 0x90, 0x7f, 0xa6, 0xe0, 0xab, 0x09} },
+{ 0x0663, 16, {0xaa, 0x0a, 0xa9, 0x0b, 0xae, 0x0c, 0x8e, 0x82, 0x75, 0x83, 0x00, 0x12, 0x07, 0xb2, 0x05, 0x0c} },
+{ 0x0673, 16, {0x80, 0x0a, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0xe4, 0xf5, 0x0d, 0x53, 0x91, 0xdf, 0xd0} },
+{ 0x0683, 16, {0x07, 0xd0, 0x06, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0xd0, 0xd0, 0x86, 0xd0} },
+{ 0x0693, 10, {0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x069d, 16, {0xc2, 0x04, 0xd2, 0x05, 0xe4, 0xf5, 0x25, 0xc2, 0x03, 0xc2, 0x00, 0xc2, 0x02, 0xc2, 0x01, 0x12} },
+{ 0x06ad, 16, {0x0e, 0x74, 0xd2, 0xe8, 0x43, 0xd8, 0x20, 0x90, 0x7f, 0xab, 0x74, 0xff, 0xf0, 0x90, 0x7f, 0xa9} },
+{ 0x06bd, 16, {0xf0, 0x90, 0x7f, 0xaa, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f, 0x95, 0xe0, 0x44, 0xc0, 0xf0, 0x90} },
+{ 0x06cd, 16, {0x7f, 0x93, 0x74, 0x30, 0xf0, 0x12, 0x0a, 0x19, 0x75, 0x24, 0x48, 0x75, 0x23, 0x92, 0x75, 0x22} },
+{ 0x06dd, 16, {0x00, 0x75, 0x21, 0x00, 0xe4, 0xff, 0xfe, 0x7e, 0x05, 0x90, 0x20, 0x68, 0x74, 0x01, 0xf0, 0xa3} },
+{ 0x06ed, 16, {0xde, 0xfc, 0x7e, 0x00, 0x7f, 0x05, 0x90, 0x7f, 0xaf, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xae} },
+{ 0x06fd, 16, {0xe0, 0x44, 0x0d, 0xf0, 0xd2, 0xaf, 0x12, 0x0e, 0x68, 0x30, 0x01, 0x0a, 0xe4, 0x90, 0x20, 0x69} },
+{ 0x070d, 16, {0xf0, 0x12, 0x03, 0x7e, 0xc2, 0x01, 0x30, 0x04, 0x1a, 0x12, 0x0e, 0x77, 0x50, 0x13, 0x12, 0x09} },
+{ 0x071d, 16, {0x00, 0x30, 0x00, 0x07, 0x90, 0x7f, 0xd6, 0xe0, 0x30, 0xe7, 0xf3, 0x12, 0x0d, 0x8b, 0x12, 0x0e} },
+{ 0x072d, 16, {0x79, 0xc2, 0x03, 0x7f, 0xff, 0x7e, 0xff, 0x7d, 0xff, 0x7c, 0xff, 0x78, 0x21, 0x12, 0x08, 0x1d} },
+{ 0x073d, 16, {0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00, 0x78, 0x00, 0xc3, 0x12, 0x08, 0x0c, 0x70, 0x1b, 0x75, 0x24} },
+{ 0x074d, 16, {0x48, 0x75, 0x23, 0x92, 0xf5, 0x22, 0xf5, 0x21, 0x63, 0x25, 0xff, 0x90, 0x20, 0x68, 0xe5, 0x25} },
+{ 0x075d, 14, {0xf0, 0xa3, 0x74, 0x01, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0x12, 0x08, 0xff, 0x80, 0x9b} },
+{ 0x076b, 1, {0x22} },
+{ 0x076c, 16, {0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb, 0xfe, 0x02} },
+{ 0x077c, 9, {0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22} },
+{ 0x0785, 16, {0xbb, 0x01, 0x0c, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50} },
+{ 0x0795, 16, {0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22} },
+{ 0x07a5, 13, {0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe4, 0x93, 0x22} },
+{ 0x07b2, 16, {0xf8, 0xbb, 0x01, 0x0d, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe8, 0xf0} },
+{ 0x07c2, 16, {0x22, 0x50, 0x06, 0xe9, 0x25, 0x82, 0xc8, 0xf6, 0x22, 0xbb, 0xfe, 0x05, 0xe9, 0x25, 0x82, 0xc8} },
+{ 0x07d2, 2, {0xf2, 0x22} },
+{ 0x07d4, 16, {0xbb, 0x01, 0x10, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0xf5, 0xf0} },
+{ 0x07e4, 16, {0xa3, 0xe0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, 0xf8, 0x86, 0xf0, 0x08, 0xe6, 0x22, 0xbb, 0xfe} },
+{ 0x07f4, 16, {0x0a, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0xf5, 0xf0, 0x08, 0xe2, 0x22, 0xe5, 0x83, 0x2a, 0xf5, 0x83} },
+{ 0x0804, 8, {0xe9, 0x93, 0xf5, 0xf0, 0xa3, 0xe9, 0x93, 0x22} },
+{ 0x080c, 16, {0xeb, 0x9f, 0xf5, 0xf0, 0xea, 0x9e, 0x42, 0xf0, 0xe9, 0x9d, 0x42, 0xf0, 0xe8, 0x9c, 0x45, 0xf0} },
+{ 0x081c, 1, {0x22} },
+{ 0x081d, 16, {0x08, 0x08, 0x08, 0xe6, 0x2f, 0xff, 0xf6, 0x18, 0xe6, 0x3e, 0xfe, 0xf6, 0x18, 0xe6, 0x3d, 0xfd} },
+{ 0x082d, 7, {0xf6, 0x18, 0xe6, 0x3c, 0xfc, 0xf6, 0x22} },
+{ 0x0834, 4, {0x8c, 0x34, 0x8d, 0x35} },
+{ 0x0838, 16, {0x90, 0x7f, 0x95, 0xe0, 0x44, 0xc0, 0xf0, 0xe4, 0xf5, 0x36, 0xf5, 0x37, 0xc3, 0xe5, 0x37, 0x95} },
+{ 0x0848, 16, {0x35, 0xe5, 0x36, 0x95, 0x34, 0x50, 0x69, 0xef, 0x25, 0x37, 0xf5, 0x82, 0xe5, 0x36, 0x3e, 0xf5} },
+{ 0x0858, 16, {0x83, 0x74, 0xff, 0xf0, 0xf4, 0x60, 0x02, 0xc3, 0x22, 0xef, 0x25, 0x37, 0xf5, 0x82, 0xe5, 0x36} },
+{ 0x0868, 16, {0x3e, 0xf5, 0x83, 0xe4, 0xf0, 0x60, 0x02, 0xc3, 0x22, 0xef, 0x25, 0x37, 0xf5, 0x82, 0xe5, 0x36} },
+{ 0x0878, 16, {0x3e, 0xf5, 0x83, 0x74, 0xaa, 0xf0, 0x64, 0xaa, 0x60, 0x02, 0xc3, 0x22, 0xef, 0x25, 0x37, 0xf5} },
+{ 0x0888, 16, {0x82, 0xe5, 0x36, 0x3e, 0xf5, 0x83, 0x74, 0x55, 0xf0, 0x64, 0x55, 0x60, 0x02, 0xc3, 0x22, 0xad} },
+{ 0x0898, 16, {0x37, 0xe5, 0x37, 0x2f, 0xf5, 0x82, 0xe5, 0x36, 0x3e, 0xf5, 0x83, 0xed, 0xf0, 0xfc, 0xac, 0x05} },
+{ 0x08a8, 16, {0xed, 0x6c, 0x60, 0x02, 0xc3, 0x22, 0x05, 0x37, 0xe5, 0x37, 0x70, 0x02, 0x05, 0x36, 0x80, 0x8c} },
+{ 0x08b8, 16, {0xe4, 0xf5, 0x36, 0xf5, 0x37, 0xc3, 0xe5, 0x37, 0x95, 0x35, 0xe5, 0x36, 0x95, 0x34, 0x50, 0x27} },
+{ 0x08c8, 16, {0xef, 0x25, 0x37, 0xf5, 0x82, 0xe5, 0x36, 0x3e, 0xf5, 0x83, 0xe0, 0x65, 0x37, 0x60, 0x02, 0xc3} },
+{ 0x08d8, 16, {0x22, 0xef, 0x25, 0x37, 0xf5, 0x82, 0xe5, 0x36, 0x3e, 0xf5, 0x83, 0xe4, 0xf0, 0x05, 0x37, 0xe5} },
+{ 0x08e8, 8, {0x37, 0x70, 0x02, 0x05, 0x36, 0x80, 0xce, 0xd3} },
+{ 0x08f0, 1, {0x22} },
+{ 0x08f1, 14, {0x90, 0x7f, 0x00, 0xe5, 0x10, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0xd3, 0x22} },
+{ 0x08ff, 1, {0x22} },
+{ 0x0900, 9, {0x90, 0x7f, 0xd6, 0xe0, 0x44, 0x80, 0xf0, 0x80, 0x74} },
+{ 0x097d, 16, {0x43, 0x87, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22} },
+{ 0x098d, 12, {0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x3a, 0x02, 0x09, 0xd4} },
+{ 0x0999, 16, {0x02, 0x06, 0x9d, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, 0xf2} },
+{ 0x09a9, 16, {0x08, 0xdf, 0xf4, 0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, 0x33} },
+{ 0x09b9, 16, {0xc4, 0x54, 0x0f, 0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf} },
+{ 0x09c9, 16, {0xe4, 0x80, 0x0b, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x0e, 0x2d, 0xe4, 0x7e} },
+{ 0x09d9, 16, {0x01, 0x93, 0x60, 0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, 0x93} },
+{ 0x09e9, 16, {0xa3, 0x60, 0x01, 0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, 0xa3} },
+{ 0x09f9, 16, {0xfa, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca} },
+{ 0x0a09, 16, {0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0xbe} },
+{ 0x0a19, 16, {0xe4, 0x90, 0x7f, 0x9c, 0xf0, 0x7f, 0x0a, 0xfe, 0x12, 0x0d, 0xd5, 0x90, 0x7f, 0x96, 0x74, 0x89} },
+{ 0x0a29, 16, {0xf0, 0x90, 0x7f, 0x9c, 0x74, 0xcf, 0xf0, 0x7f, 0xf4, 0x7e, 0x01, 0x12, 0x0d, 0xd5, 0x90, 0x7f} },
+{ 0x0a39, 16, {0x96, 0xe0, 0x54, 0xfe, 0xf0, 0x7f, 0x0a, 0x7e, 0x00, 0x12, 0x0d, 0xd5, 0x7f, 0x05, 0x7e, 0x00} },
+{ 0x0a49, 16, {0x12, 0x0d, 0xd5, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x02, 0xf0, 0xe0, 0x54, 0x7f, 0xf0, 0x7f, 0x05} },
+{ 0x0a59, 16, {0x7e, 0x00, 0x12, 0x0d, 0xd5, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x05, 0x7e, 0x00} },
+{ 0x0a69, 16, {0x12, 0x0d, 0xd5, 0x90, 0x7f, 0x96, 0xe0, 0x54, 0xbf, 0xf0, 0x7f, 0x32, 0x7e, 0x00, 0x12, 0x0d} },
+{ 0x0a79, 16, {0xd5, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x32, 0x7e, 0x00, 0x12, 0x0d, 0xd5, 0x22} },
+{ 0x0a89, 16, {0x75, 0x33, 0x01, 0xe5, 0x33, 0x60, 0x1b, 0x7f, 0x01, 0x12, 0x0e, 0x18, 0x7f, 0x00, 0x7e, 0x0e} },
+{ 0x0a99, 16, {0x7d, 0x00, 0x7c, 0x01, 0x12, 0x08, 0x34, 0xe4, 0x33, 0xf5, 0x33, 0x70, 0x05, 0x7f, 0x0f, 0x12} },
+{ 0x0aa9, 16, {0x0e, 0x18, 0xe5, 0x33, 0x60, 0x1b, 0x7f, 0x02, 0x12, 0x0e, 0x18, 0x7f, 0x00, 0x7e, 0x80, 0x7d} },
+{ 0x0ab9, 16, {0x00, 0x7c, 0x80, 0x12, 0x08, 0x34, 0xe4, 0x33, 0xf5, 0x33, 0x70, 0x05, 0x7f, 0x0f, 0x12, 0x0e} },
+{ 0x0ac9, 16, {0x18, 0xe5, 0x33, 0x60, 0x1b, 0x7f, 0x03, 0x12, 0x0e, 0x18, 0x7f, 0x00, 0x7e, 0x20, 0x7d, 0x40} },
+{ 0x0ad9, 16, {0x7c, 0x5b, 0x12, 0x08, 0x34, 0xe4, 0x33, 0xf5, 0x33, 0x70, 0x05, 0x7f, 0x0f, 0x12, 0x0e, 0x18} },
+{ 0x0ae9, 13, {0xe5, 0x33, 0x60, 0x05, 0xe4, 0xff, 0x12, 0x0e, 0x18, 0xe5, 0x33, 0x24, 0xff} },
+{ 0x0af6, 1, {0x22} },
+{ 0x0af7, 8, {0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x10, 0xd3, 0x22} },
+{ 0x0aff, 1, {0x32} },
+{ 0x0b00, 16, {0x02, 0x0d, 0xa5, 0x00, 0x02, 0x0d, 0xec, 0x00, 0x02, 0x0d, 0x70, 0x00, 0x02, 0x0d, 0xbd, 0x00} },
+{ 0x0b10, 16, {0x02, 0x0e, 0x02, 0x00, 0x02, 0x0a, 0xff, 0x00, 0x02, 0x0e, 0x83, 0x00, 0x02, 0x0e, 0x84, 0x00} },
+{ 0x0b20, 16, {0x02, 0x0e, 0x85, 0x00, 0x02, 0x0e, 0x86, 0x00, 0x02, 0x0e, 0x87, 0x00, 0x02, 0x0e, 0x88, 0x00} },
+{ 0x0b30, 16, {0x02, 0x0e, 0x89, 0x00, 0x02, 0x0e, 0x8a, 0x00, 0x02, 0x0e, 0x8b, 0x00, 0x02, 0x0e, 0x8c, 0x00} },
+{ 0x0b40, 16, {0x02, 0x0e, 0x8d, 0x00, 0x02, 0x0e, 0x8e, 0x00, 0x02, 0x0e, 0x8f, 0x00, 0x02, 0x0e, 0x90, 0x00} },
+{ 0x0b50, 8, {0x02, 0x0e, 0x91, 0x00, 0x02, 0x0e, 0x92, 0x00} },
+{ 0x0b58, 16, {0xe4, 0xfe, 0x75, 0x2b, 0xff, 0x75, 0x2c, 0x11, 0x75, 0x2d, 0x12, 0xab, 0x2b, 0xaa, 0x2c, 0xa9} },
+{ 0x0b68, 16, {0x2d, 0x90, 0x00, 0x01, 0x12, 0x07, 0x85, 0x64, 0x02, 0x70, 0x2d, 0xad, 0x06, 0x0e, 0xed, 0xb5} },
+{ 0x0b78, 16, {0x07, 0x01, 0x22, 0x90, 0x00, 0x02, 0x12, 0x07, 0xd4, 0x85, 0xf0, 0x29, 0xf5, 0x2a, 0x62, 0x29} },
+{ 0x0b88, 16, {0xe5, 0x29, 0x62, 0x2a, 0xe5, 0x2a, 0x62, 0x29, 0x29, 0xfd, 0xe5, 0x29, 0x3a, 0xa9, 0x05, 0x75} },
+{ 0x0b98, 14, {0x2b, 0xff, 0xf5, 0x2c, 0x89, 0x2d, 0x80, 0xc3, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} },
+{ 0x0ba6, 1, {0x22} },
+{ 0x0ba7, 6, {0xab, 0x07, 0xaa, 0x06, 0xac, 0x05} },
+{ 0x0bad, 16, {0xe4, 0xfd, 0xe5, 0x11, 0x60, 0x11, 0xea, 0xff, 0xae, 0x05, 0x0d, 0xee, 0x24, 0x10, 0xf5, 0x82} },
+{ 0x0bbd, 16, {0xe4, 0x34, 0x0f, 0xf5, 0x83, 0xef, 0xf0, 0xeb, 0xae, 0x05, 0x0d, 0x74, 0x10, 0x2e, 0xf5, 0x82} },
+{ 0x0bcd, 16, {0xe4, 0x34, 0x0f, 0xf5, 0x83, 0xeb, 0xf0, 0xaf, 0x05, 0x0d, 0x74, 0x10, 0x2f, 0xf5, 0x82, 0xe4} },
+{ 0x0bdd, 16, {0x34, 0x0f, 0xf5, 0x83, 0xec, 0xf0, 0xaf, 0x0f, 0x7a, 0x0f, 0x7b, 0x10, 0x12, 0x0d, 0x51, 0x7f} },
+{ 0x0bed, 6, {0x0a, 0x7e, 0x00, 0x12, 0x0d, 0xd5} },
+{ 0x0bf3, 1, {0x22} },
+{ 0x0bf4, 10, {0x8e, 0x33, 0x8f, 0x34, 0x8d, 0x35, 0x8a, 0x36, 0x8b, 0x37} },
+{ 0x0bfe, 16, {0xe4, 0xfd, 0xf5, 0x38, 0xe5, 0x11, 0x60, 0x12, 0xe5, 0x33, 0xff, 0xae, 0x05, 0x0d, 0xee, 0x24} },
+{ 0x0c0e, 16, {0x13, 0xf5, 0x82, 0xe4, 0x34, 0x0f, 0xf5, 0x83, 0xef, 0xf0, 0xe5, 0x34, 0xae, 0x05, 0x0d, 0x74} },
+{ 0x0c1e, 16, {0x13, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x0f, 0xf5, 0x83, 0xe5, 0x34, 0xf0, 0xaf, 0x0f, 0x7a, 0x0f} },
+{ 0x0c2e, 16, {0x7b, 0x13, 0x12, 0x0d, 0x51, 0xaf, 0x0f, 0xad, 0x35, 0xab, 0x37, 0xaa, 0x36, 0x12, 0x0d, 0x32} },
+{ 0x0c3e, 1, {0x22} },
+{ 0x0c3f, 2, {0x8f, 0x29} },
+{ 0x0c41, 16, {0xe4, 0xf5, 0x2a, 0x75, 0x2b, 0xff, 0x75, 0x2c, 0x11, 0x75, 0x2d, 0x32, 0xab, 0x2b, 0xaa, 0x2c} },
+{ 0x0c51, 16, {0xa9, 0x2d, 0x90, 0x00, 0x01, 0x12, 0x07, 0x85, 0xb4, 0x03, 0x1d, 0xaf, 0x2a, 0x05, 0x2a, 0xef} },
+{ 0x0c61, 16, {0xb5, 0x29, 0x01, 0x22, 0x12, 0x07, 0x6c, 0x7e, 0x00, 0x29, 0xff, 0xee, 0x3a, 0xa9, 0x07, 0x75} },
+{ 0x0c71, 14, {0x2b, 0xff, 0xf5, 0x2c, 0x89, 0x2d, 0x80, 0xd4, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} },
+{ 0x0c7f, 1, {0x22} },
+{ 0x0c80, 10, {0x8e, 0x33, 0x8f, 0x34, 0x8d, 0x35, 0x8a, 0x36, 0x8b, 0x37} },
+{ 0x0c8a, 16, {0xe4, 0xf5, 0x38, 0xe5, 0x38, 0xc3, 0x95, 0x35, 0x50, 0x20, 0x05, 0x34, 0xe5, 0x34, 0xae, 0x33} },
+{ 0x0c9a, 16, {0x70, 0x02, 0x05, 0x33, 0x14, 0xff, 0xe5, 0x37, 0x25, 0x38, 0xf5, 0x82, 0xe4, 0x35, 0x36, 0xf5} },
+{ 0x0caa, 10, {0x83, 0xe0, 0xfd, 0x12, 0x0b, 0xa7, 0x05, 0x38, 0x80, 0xd9} },
+{ 0x0cb4, 1, {0x22} },
+{ 0x0cb5, 16, {0xa9, 0x07, 0xe5, 0x0d, 0x70, 0x25, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0, 0xe9, 0x25, 0xe0} },
+{ 0x0cc5, 16, {0x44, 0x01, 0x90, 0x7f, 0xa6, 0xf0, 0x8d, 0x08, 0xaf, 0x03, 0xa9, 0x07, 0x75, 0x09, 0x01, 0x8a} },
+{ 0x0cd5, 13, {0x0a, 0x89, 0x0b, 0xe4, 0xf5, 0x0c, 0x75, 0x0d, 0x03, 0xd3, 0x22, 0xc3, 0x22} },
+{ 0x0ce2, 16, {0xa9, 0x07, 0xe5, 0x0d, 0x70, 0x23, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0, 0xe9, 0x25, 0xe0} },
+{ 0x0cf2, 16, {0x90, 0x7f, 0xa6, 0xf0, 0x8d, 0x08, 0xaf, 0x03, 0xa9, 0x07, 0x75, 0x09, 0x01, 0x8a, 0x0a, 0x89} },
+{ 0x0d02, 11, {0x0b, 0xe4, 0xf5, 0x0c, 0x75, 0x0d, 0x01, 0xd3, 0x22, 0xc3, 0x22} },
+{ 0x0d0d, 16, {0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xfb, 0xf0, 0xe0, 0x44, 0x08, 0xf0, 0x30, 0x06, 0x04, 0xe0, 0x44} },
+{ 0x0d1d, 16, {0x02, 0xf0, 0x7f, 0xd0, 0x7e, 0x07, 0x12, 0x0d, 0xd5, 0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xf7, 0xf0} },
+{ 0x0d2d, 5, {0xe0, 0x44, 0x04, 0xf0, 0x22} },
+{ 0x0d32, 16, {0x12, 0x0c, 0xb5, 0xe5, 0x0d, 0x24, 0xfa, 0x60, 0x10, 0x14, 0x60, 0x07, 0x24, 0x07, 0x70, 0xf3} },
+{ 0x0d42, 15, {0x7f, 0x08, 0x22, 0xe4, 0xf5, 0x0d, 0x7f, 0x07, 0x22, 0xe4, 0xf5, 0x0d, 0x7f, 0x06, 0x22} },
+{ 0x0d51, 16, {0x12, 0x0c, 0xe2, 0xe5, 0x0d, 0x24, 0xfa, 0x60, 0x10, 0x14, 0x60, 0x07, 0x24, 0x07, 0x70, 0xf3} },
+{ 0x0d61, 15, {0x7f, 0x08, 0x22, 0xe4, 0xf5, 0x0d, 0x7f, 0x07, 0x22, 0xe4, 0xf5, 0x0d, 0x7f, 0x06, 0x22} },
+{ 0x0d70, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x90, 0x7f, 0xc4, 0xe4, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f} },
+{ 0x0d80, 11, {0xab, 0x74, 0x04, 0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0d8b, 16, {0x90, 0x7f, 0xd6, 0xe0, 0x30, 0xe7, 0x12, 0xe0, 0x44, 0x01, 0xf0, 0x7f, 0x14, 0x7e, 0x00, 0x12} },
+{ 0x0d9b, 10, {0x0d, 0xd5, 0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xfe, 0xf0, 0x22} },
+{ 0x0da5, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xd2, 0x01, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x01} },
+{ 0x0db5, 8, {0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0dbd, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xd2, 0x03, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x08} },
+{ 0x0dcd, 8, {0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0dd5, 16, {0x8e, 0x39, 0x8f, 0x3a, 0xe5, 0x3a, 0x15, 0x3a, 0xae, 0x39, 0x70, 0x02, 0x15, 0x39, 0x4e, 0x60} },
+{ 0x0de5, 7, {0x05, 0x12, 0x0e, 0x41, 0x80, 0xee, 0x22} },
+{ 0x0dec, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x02, 0xf0, 0xd0} },
+{ 0x0dfc, 6, {0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0e02, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x10, 0xf0, 0xd0} },
+{ 0x0e12, 6, {0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0e18, 16, {0xae, 0x07, 0x7f, 0x21, 0x7d, 0x01, 0x74, 0x00, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x0f, 0xab, 0x82} },
+{ 0x0e28, 5, {0xfa, 0x12, 0x0d, 0x51, 0x22} },
+{ 0x0e2d, 16, {0x50, 0x0f, 0x00, 0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x98, 0x88, 0x83, 0xc6} },
+{ 0x0e3d, 3, {0xa1, 0x86, 0x8e} },
+{ 0x0e40, 1, {0x00} },
+{ 0x0e41, 16, {0x74, 0x00, 0xf5, 0x86, 0x90, 0xfd, 0xa5, 0x7c, 0x05, 0xa3, 0xe5, 0x82, 0x45, 0x83, 0x70, 0xf9} },
+{ 0x0e51, 1, {0x22} },
+{ 0x0e52, 14, {0x90, 0x7f, 0x00, 0xe5, 0x0e, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0xd3, 0x22} },
+{ 0x0e60, 8, {0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x0e, 0xd3, 0x22} },
+{ 0x0e68, 8, {0xe4, 0xf5, 0x0d, 0xd2, 0xe9, 0xd2, 0xaf, 0x22} },
+{ 0x0e70, 4, {0x53, 0xd8, 0xef, 0x32} },
+{ 0x0e74, 3, {0xd2, 0x00, 0x22} },
+{ 0x0e77, 2, {0xd3, 0x22} },
+{ 0x0e79, 2, {0xd3, 0x22} },
+{ 0x0e7b, 2, {0xd3, 0x22} },
+{ 0x0e7d, 2, {0xd3, 0x22} },
+{ 0x0e7f, 2, {0xd3, 0x22} },
+{ 0x0e81, 2, {0xd3, 0x22} },
+{ 0x0e83, 1, {0x32} },
+{ 0x0e84, 1, {0x32} },
+{ 0x0e85, 1, {0x32} },
+{ 0x0e86, 1, {0x32} },
+{ 0x0e87, 1, {0x32} },
+{ 0x0e88, 1, {0x32} },
+{ 0x0e89, 1, {0x32} },
+{ 0x0e8a, 1, {0x32} },
+{ 0x0e8b, 1, {0x32} },
+{ 0x0e8c, 1, {0x32} },
+{ 0x0e8d, 1, {0x32} },
+{ 0x0e8e, 1, {0x32} },
+{ 0x0e8f, 1, {0x32} },
+{ 0x0e90, 1, {0x32} },
+{ 0x0e91, 1, {0x32} },
+{ 0x0e92, 1, {0x32} },
+{ 0x1100, 16, {0x12, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x47, 0x05, 0x10, 0x27, 0x01, 0x00, 0x01, 0x02} },
+{ 0x1110, 16, {0x00, 0x01, 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x03, 0xa0, 0x00, 0x09, 0x04, 0x00, 0x00, 0x02} },
+{ 0x1120, 16, {0xff, 0x00, 0x00, 0x04, 0x07, 0x05, 0x82, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x02, 0x02, 0x40} },
+{ 0x1130, 16, {0x00, 0x00, 0x04, 0x03, 0x09, 0x04, 0x26, 0x03, 0x41, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x68, 0x00} },
+{ 0x1140, 16, {0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x43, 0x00, 0x68, 0x00, 0x69, 0x00, 0x70, 0x00, 0x73, 0x00} },
+{ 0x1150, 16, {0x2c, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x2e, 0x00, 0x28, 0x03, 0x46, 0x00} },
+{ 0x1160, 16, {0x69, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x77, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00} },
+{ 0x1170, 16, {0x46, 0x00, 0x72, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x57, 0x00, 0x6f, 0x00, 0x72, 0x00} },
+{ 0x1180, 16, {0x6b, 0x00, 0x73, 0x00, 0x2a, 0x03, 0x43, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x66, 0x00, 0x69, 0x00} },
+{ 0x1190, 16, {0x67, 0x00, 0x75, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00} },
+{ 0x11a0, 16, {0x20, 0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x22, 0x03} },
+{ 0x11b0, 16, {0x49, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x66, 0x00, 0x61, 0x00, 0x63, 0x00} },
+{ 0x11c0, 16, {0x65, 0x00, 0x20, 0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00} },
+{ 0x11d0, 2, {0x00, 0x00} },
+{ 0xffff, 0, {0x00} }
+};
+
+#else
+
+static const struct whiteheat_hex_record whiteheat_loader[] = {
+{ 0x0000, 3, {0x02, 0x09, 0x8d} },
+{ 0x0033, 3, {0x02, 0x08, 0xfb} },
+{ 0x0043, 3, {0x02, 0x0b, 0x00} },
+{ 0x004b, 3, {0x02, 0x05, 0xaa} },
+{ 0x0100, 16, {0x90, 0x7f, 0xa5, 0xe0, 0x54, 0x10, 0xff, 0xc4, 0x54, 0x0f, 0x44, 0x50, 0xf5, 0x0f, 0x13, 0xe4} },
+{ 0x0110, 16, {0x33, 0xf5, 0x11, 0x90, 0x7f, 0xe9, 0xe0, 0x24, 0x5e, 0xb4, 0x07, 0x00, 0x40, 0x03, 0x02, 0x03} },
+{ 0x0120, 16, {0x78, 0x90, 0x01, 0x28, 0xf8, 0x28, 0x28, 0x73, 0x02, 0x01, 0xbc, 0x02, 0x01, 0xbc, 0x02, 0x01} },
+{ 0x0130, 16, {0x91, 0x02, 0x01, 0x3d, 0x02, 0x01, 0x53, 0x02, 0x01, 0x6f, 0x02, 0x01, 0x9a, 0x90, 0x7f, 0x00} },
+{ 0x0140, 16, {0xe5, 0x11, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0} },
+{ 0x0150, 16, {0x02, 0x03, 0x78, 0x90, 0x7f, 0x92, 0xe0, 0xff, 0xc4, 0x54, 0x0f, 0x90, 0x7f, 0x00, 0xf0, 0x90} },
+{ 0x0160, 16, {0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x02, 0x03, 0x78, 0x12} },
+{ 0x0170, 16, {0x0a, 0x89, 0x50, 0x07, 0xe4, 0x90, 0x7f, 0x00, 0xf0, 0x80, 0x06, 0x90, 0x7f, 0x00, 0x74, 0x0f} },
+{ 0x0180, 16, {0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x02, 0x03} },
+{ 0x0190, 16, {0x78, 0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x0f, 0x02, 0x03, 0x78, 0x90, 0x7f, 0x00, 0x74, 0x07, 0xf0} },
+{ 0x01a0, 16, {0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x7f, 0xe8, 0x7e} },
+{ 0x01b0, 16, {0x03, 0x12, 0x0d, 0x94, 0xd2, 0x06, 0x12, 0x0c, 0xcc, 0x02, 0x03, 0x78, 0x90, 0x7f, 0xea, 0xe0} },
+{ 0x01c0, 16, {0x75, 0x28, 0x00, 0xf5, 0x29, 0xa3, 0xe0, 0xfe, 0xe4, 0xee, 0x42, 0x28, 0x90, 0x7f, 0xee, 0xe0} },
+{ 0x01d0, 16, {0x75, 0x2a, 0x00, 0xf5, 0x2b, 0xa3, 0xe0, 0xfe, 0xe4, 0xee, 0x42, 0x2a, 0x90, 0x7f, 0xe8, 0xe0} },
+{ 0x01e0, 16, {0x64, 0xc0, 0x60, 0x03, 0x02, 0x02, 0xc9, 0xe5, 0x2b, 0x45, 0x2a, 0x70, 0x03, 0x02, 0x03, 0x78} },
+{ 0x01f0, 16, {0xc3, 0xe5, 0x2b, 0x94, 0x40, 0xe5, 0x2a, 0x94, 0x00, 0x50, 0x08, 0x85, 0x2a, 0x2c, 0x85, 0x2b} },
+{ 0x0200, 16, {0x2d, 0x80, 0x06, 0x75, 0x2c, 0x00, 0x75, 0x2d, 0x40, 0x90, 0x7f, 0xe9, 0xe0, 0x64, 0xa3, 0x70} },
+{ 0x0210, 16, {0x34, 0xf5, 0x30, 0xf5, 0x31, 0xc3, 0xe5, 0x31, 0x95, 0x2d, 0xe5, 0x30, 0x95, 0x2c, 0x50, 0x5c} },
+{ 0x0220, 16, {0xe5, 0x29, 0x25, 0x31, 0xf5, 0x82, 0xe5, 0x30, 0x35, 0x28, 0xf5, 0x83, 0xe0, 0xff, 0x74, 0x00} },
+{ 0x0230, 16, {0x25, 0x31, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xef, 0xf0, 0x05, 0x31, 0xe5, 0x31, 0x70} },
+{ 0x0240, 16, {0x02, 0x05, 0x30, 0x80, 0xd0, 0xe4, 0xf5, 0x30, 0xf5, 0x31, 0xc3, 0xe5, 0x31, 0x95, 0x2d, 0xe5} },
+{ 0x0250, 16, {0x30, 0x95, 0x2c, 0x50, 0x18, 0x74, 0x00, 0x25, 0x31, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83} },
+{ 0x0260, 16, {0x74, 0xcd, 0xf0, 0x05, 0x31, 0xe5, 0x31, 0x70, 0x02, 0x05, 0x30, 0x80, 0xdd, 0xaf, 0x29, 0xae} },
+{ 0x0270, 16, {0x28, 0xad, 0x2d, 0x7a, 0x7f, 0x79, 0x00, 0x7b, 0x00, 0x12, 0x0b, 0xf4, 0x90, 0x7f, 0xb5, 0xe5} },
+{ 0x0280, 16, {0x2d, 0xf0, 0xe5, 0x2d, 0x25, 0x29, 0xf5, 0x29, 0xe5, 0x2c, 0x35, 0x28, 0xf5, 0x28, 0xc3, 0xe5} },
+{ 0x0290, 16, {0x2b, 0x95, 0x2d, 0xf5, 0x2b, 0xe5, 0x2a, 0x95, 0x2c, 0xf5, 0x2a, 0x90, 0x7f, 0x92, 0xe0, 0xff} },
+{ 0x02a0, 16, {0xc4, 0x54, 0x0f, 0x75, 0x2e, 0x00, 0xf5, 0x2f, 0xd3, 0x94, 0x00, 0xe5, 0x2e, 0x94, 0x00, 0x50} },
+{ 0x02b0, 16, {0x0c, 0x90, 0x7f, 0xb4, 0xe0, 0x20, 0xe1, 0x03, 0x02, 0x01, 0xe7, 0x80, 0xf4, 0x90, 0x7f, 0xb4} },
+{ 0x02c0, 16, {0xe0, 0x20, 0xe2, 0x03, 0x02, 0x01, 0xe7, 0x80, 0xf4, 0x90, 0x7f, 0xe8, 0xe0, 0x64, 0x40, 0x60} },
+{ 0x02d0, 16, {0x03, 0x02, 0x03, 0x78, 0xe5, 0x2b, 0x45, 0x2a, 0x70, 0x03, 0x02, 0x03, 0x78, 0xe4, 0x90, 0x7f} },
+{ 0x02e0, 16, {0xc5, 0xf0, 0x90, 0x7f, 0x92, 0xe0, 0xff, 0xc4, 0x54, 0x0f, 0x75, 0x2e, 0x00, 0xf5, 0x2f, 0xd3} },
+{ 0x02f0, 16, {0x94, 0x00, 0xe5, 0x2e, 0x94, 0x00, 0x50, 0x09, 0x90, 0x7f, 0xc4, 0xe0, 0x30, 0xe1, 0x09, 0x80} },
+{ 0x0300, 16, {0xf7, 0x90, 0x7f, 0xb4, 0xe0, 0x20, 0xe3, 0xf9, 0x90, 0x7f, 0xc5, 0xe0, 0x75, 0x2c, 0x00, 0xf5} },
+{ 0x0310, 16, {0x2d, 0x90, 0x7f, 0xe9, 0xe0, 0x64, 0xa3, 0x70, 0x34, 0xf5, 0x30, 0xf5, 0x31, 0xc3, 0xe5, 0x31} },
+{ 0x0320, 16, {0x95, 0x2d, 0xe5, 0x30, 0x95, 0x2c, 0x50, 0x34, 0x74, 0xc0, 0x25, 0x31, 0xf5, 0x82, 0xe4, 0x34} },
+{ 0x0330, 1, {0x7e} },
+{ 0x0331, 16, {0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x29, 0x25, 0x31, 0xf5, 0x82, 0xe5, 0x30, 0x35, 0x28, 0xf5, 0x83} },
+{ 0x0341, 16, {0xef, 0xf0, 0x05, 0x31, 0xe5, 0x31, 0x70, 0x02, 0x05, 0x30, 0x80, 0xd0, 0xaf, 0x29, 0xae, 0x28} },
+{ 0x0351, 16, {0xad, 0x2d, 0x7a, 0x7e, 0x79, 0xc0, 0x7b, 0xc0, 0x12, 0x0c, 0x3f, 0xe5, 0x2d, 0x25, 0x29, 0xf5} },
+{ 0x0361, 16, {0x29, 0xe5, 0x2c, 0x35, 0x28, 0xf5, 0x28, 0xc3, 0xe5, 0x2b, 0x95, 0x2d, 0xf5, 0x2b, 0xe5, 0x2a} },
+{ 0x0371, 9, {0x95, 0x2c, 0xf5, 0x2a, 0x02, 0x02, 0xd4, 0xc3, 0x22} },
+{ 0x037a, 16, {0x90, 0x7f, 0xe9, 0xe0, 0x70, 0x03, 0x02, 0x04, 0x52, 0x14, 0x70, 0x03, 0x02, 0x04, 0xce, 0x24} },
+{ 0x038a, 16, {0xfe, 0x70, 0x03, 0x02, 0x05, 0x42, 0x24, 0xfb, 0x70, 0x03, 0x02, 0x04, 0x4c, 0x14, 0x70, 0x03} },
+{ 0x039a, 16, {0x02, 0x04, 0x46, 0x14, 0x70, 0x03, 0x02, 0x04, 0x3a, 0x14, 0x70, 0x03, 0x02, 0x04, 0x40, 0x24} },
+{ 0x03aa, 16, {0x05, 0x60, 0x03, 0x02, 0x05, 0x96, 0x12, 0x0e, 0x44, 0x40, 0x03, 0x02, 0x05, 0xa2, 0x90, 0x7f} },
+{ 0x03ba, 16, {0xeb, 0xe0, 0x24, 0xfe, 0x60, 0x16, 0x14, 0x60, 0x40, 0x24, 0x02, 0x70, 0x69, 0x74, 0x11, 0x90} },
+{ 0x03ca, 16, {0x7f, 0xd4, 0xf0, 0x74, 0x00, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xea, 0xe0} },
+{ 0x03da, 16, {0xff, 0x12, 0x0b, 0x58, 0x8b, 0x25, 0x8a, 0x26, 0x89, 0x27, 0xea, 0x49, 0x60, 0x11, 0xae, 0x02} },
+{ 0x03ea, 16, {0xee, 0x90, 0x7f, 0xd4, 0xf0, 0xaf, 0x01, 0xef, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x05, 0xa2, 0x90} },
+{ 0x03fa, 16, {0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xea, 0xe0, 0xff, 0x12, 0x08} },
+{ 0x040a, 16, {0xba, 0x8b, 0x25, 0x8a, 0x26, 0x89, 0x27, 0xea, 0x49, 0x60, 0x11, 0xae, 0x02, 0xee, 0x90, 0x7f} },
+{ 0x041a, 16, {0xd4, 0xf0, 0xaf, 0x01, 0xef, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xb4, 0xe0} },
+{ 0x042a, 16, {0x44, 0x01, 0xf0, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0xa2} },
+{ 0x043a, 16, {0x12, 0x0e, 0x1f, 0x02, 0x05, 0xa2, 0x12, 0x0e, 0x2d, 0x02, 0x05, 0xa2, 0x12, 0x0a, 0xf7, 0x02} },
+{ 0x044a, 16, {0x05, 0xa2, 0x12, 0x0e, 0x11, 0x02, 0x05, 0xa2, 0x12, 0x0e, 0x46, 0x40, 0x03, 0x02, 0x05, 0xa2} },
+{ 0x045a, 16, {0x90, 0x7f, 0xe8, 0xe0, 0x24, 0x7f, 0x60, 0x24, 0x14, 0x60, 0x31, 0x24, 0x02, 0x70, 0x5b, 0xa2} },
+{ 0x046a, 16, {0x00, 0xe4, 0x33, 0xff, 0x25, 0xe0, 0xff, 0xa2, 0x02, 0xe4, 0x33, 0x4f, 0x90, 0x7f, 0x00, 0xf0} },
+{ 0x047a, 16, {0xe4, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0xa2, 0xe4, 0x90, 0x7f, 0x00} },
+{ 0x048a, 16, {0xf0, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xec, 0xe0} },
+{ 0x049a, 16, {0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4} },
+{ 0x04aa, 16, {0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe0, 0x54, 0xfd, 0x90, 0x7f, 0x00, 0xf0, 0xe4, 0xa3} },
+{ 0x04ba, 16, {0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01} },
+{ 0x04ca, 16, {0xf0, 0x02, 0x05, 0xa2, 0x12, 0x0e, 0x48, 0x40, 0x03, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xe8, 0xe0} },
+{ 0x04da, 16, {0x24, 0xfe, 0x60, 0x1d, 0x24, 0x02, 0x60, 0x03, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xea, 0xe0, 0xb4} },
+{ 0x04ea, 16, {0x01, 0x05, 0xc2, 0x00, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05} },
+{ 0x04fa, 16, {0xa2, 0x90, 0x7f, 0xea, 0xe0, 0x70, 0x38, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4} },
+{ 0x050a, 16, {0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f} },
+{ 0x051a, 16, {0xf5, 0x83, 0xe4, 0xf0, 0x90, 0x7f, 0xec, 0xe0, 0x54, 0x80, 0xff, 0x13, 0x13, 0x13, 0x54, 0x1f} },
+{ 0x052a, 16, {0xff, 0xe0, 0x54, 0x07, 0x2f, 0x90, 0x7f, 0xd7, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x69, 0x90} },
+{ 0x053a, 16, {0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x60, 0x12, 0x0e, 0x4a, 0x50, 0x5b, 0x90, 0x7f, 0xe8} },
+{ 0x054a, 16, {0xe0, 0x24, 0xfe, 0x60, 0x18, 0x24, 0x02, 0x70, 0x4f, 0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x04} },
+{ 0x055a, 16, {0xd2, 0x00, 0x80, 0x44, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x3b, 0x90, 0x7f, 0xea} },
+{ 0x056a, 16, {0xe0, 0x70, 0x20, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0} },
+{ 0x057a, 16, {0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0x74, 0x01} },
+{ 0x058a, 16, {0xf0, 0x80, 0x15, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x0c, 0x12, 0x01, 0x00, 0x50} },
+{ 0x059a, 16, {0x07, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x22} },
+{ 0x05aa, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xc0} },
+{ 0x05ba, 16, {0xd0, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x06, 0xc0, 0x07, 0x90, 0x7f, 0xa5} },
+{ 0x05ca, 16, {0xe0, 0x30, 0xe2, 0x06, 0x75, 0x0d, 0x06, 0x02, 0x06, 0x76, 0x90, 0x7f, 0xa5, 0xe0, 0x20, 0xe1} },
+{ 0x05da, 16, {0x0c, 0xe5, 0x0d, 0x64, 0x02, 0x60, 0x06, 0x75, 0x0d, 0x07, 0x02, 0x06, 0x76, 0xaf, 0x0d, 0xef} },
+{ 0x05ea, 16, {0x24, 0xfe, 0x60, 0x48, 0x14, 0x60, 0x2c, 0x24, 0xfe, 0x60, 0x77, 0x24, 0x04, 0x60, 0x03, 0x02} },
+{ 0x05fa, 16, {0x06, 0x76, 0xab, 0x09, 0xaa, 0x0a, 0xa9, 0x0b, 0xaf, 0x0c, 0x05, 0x0c, 0x8f, 0x82, 0x75, 0x83} },
+{ 0x060a, 16, {0x00, 0x12, 0x08, 0x22, 0x90, 0x7f, 0xa6, 0xf0, 0xe5, 0x0c, 0x65, 0x08, 0x70, 0x5e, 0x75, 0x0d} },
+{ 0x061a, 16, {0x05, 0x80, 0x59, 0x90, 0x7f, 0xa6, 0xe0, 0xab, 0x09, 0xaa, 0x0a, 0xa9, 0x0b, 0xae, 0x0c, 0x8e} },
+{ 0x062a, 16, {0x82, 0x75, 0x83, 0x00, 0x12, 0x08, 0x4f, 0x75, 0x0d, 0x02, 0x80, 0x40, 0xe5, 0x08, 0x24, 0xfe} },
+{ 0x063a, 16, {0xb5, 0x0c, 0x07, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x20, 0xf0, 0xe5, 0x08, 0x14, 0xb5, 0x0c, 0x0a} },
+{ 0x064a, 16, {0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0xe4, 0xf5, 0x0d, 0x90, 0x7f, 0xa6, 0xe0, 0xab, 0x09} },
+{ 0x065a, 16, {0xaa, 0x0a, 0xa9, 0x0b, 0xae, 0x0c, 0x8e, 0x82, 0x75, 0x83, 0x00, 0x12, 0x08, 0x4f, 0x05, 0x0c} },
+{ 0x066a, 16, {0x80, 0x0a, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0xe4, 0xf5, 0x0d, 0x53, 0x91, 0xdf, 0xd0} },
+{ 0x067a, 16, {0x07, 0xd0, 0x06, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0xd0, 0xd0, 0x86, 0xd0} },
+{ 0x068a, 10, {0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0694, 16, {0x8c, 0x33, 0x8d, 0x34, 0x90, 0x7f, 0x95, 0xe0, 0x44, 0xc0, 0xf0, 0xe4, 0xf5, 0x35, 0xf5, 0x36} },
+{ 0x06a4, 16, {0xc3, 0xe5, 0x36, 0x95, 0x34, 0xe5, 0x35, 0x95, 0x33, 0x50, 0x69, 0xef, 0x25, 0x36, 0xf5, 0x82} },
+{ 0x06b4, 16, {0xe5, 0x35, 0x3e, 0xf5, 0x83, 0x74, 0xff, 0xf0, 0xf4, 0x60, 0x02, 0xc3, 0x22, 0xef, 0x25, 0x36} },
+{ 0x06c4, 16, {0xf5, 0x82, 0xe5, 0x35, 0x3e, 0xf5, 0x83, 0xe4, 0xf0, 0x60, 0x02, 0xc3, 0x22, 0xef, 0x25, 0x36} },
+{ 0x06d4, 16, {0xf5, 0x82, 0xe5, 0x35, 0x3e, 0xf5, 0x83, 0x74, 0xaa, 0xf0, 0x64, 0xaa, 0x60, 0x02, 0xc3, 0x22} },
+{ 0x06e4, 16, {0xef, 0x25, 0x36, 0xf5, 0x82, 0xe5, 0x35, 0x3e, 0xf5, 0x83, 0x74, 0x55, 0xf0, 0x64, 0x55, 0x60} },
+{ 0x06f4, 16, {0x02, 0xc3, 0x22, 0xad, 0x36, 0xe5, 0x36, 0x2f, 0xf5, 0x82, 0xe5, 0x35, 0x3e, 0xf5, 0x83, 0xed} },
+{ 0x0704, 16, {0xf0, 0xfc, 0xac, 0x05, 0xed, 0x6c, 0x60, 0x02, 0xc3, 0x22, 0x05, 0x36, 0xe5, 0x36, 0x70, 0x02} },
+{ 0x0714, 16, {0x05, 0x35, 0x80, 0x8c, 0xe4, 0xf5, 0x35, 0xf5, 0x36, 0xc3, 0xe5, 0x36, 0x95, 0x34, 0xe5, 0x35} },
+{ 0x0724, 16, {0x95, 0x33, 0x50, 0x27, 0xef, 0x25, 0x36, 0xf5, 0x82, 0xe5, 0x35, 0x3e, 0xf5, 0x83, 0xe0, 0x65} },
+{ 0x0734, 16, {0x36, 0x60, 0x02, 0xc3, 0x22, 0xef, 0x25, 0x36, 0xf5, 0x82, 0xe5, 0x35, 0x3e, 0xf5, 0x83, 0xe4} },
+{ 0x0744, 13, {0xf0, 0x05, 0x36, 0xe5, 0x36, 0x70, 0x02, 0x05, 0x35, 0x80, 0xce, 0xd3, 0x22} },
+{ 0x0751, 16, {0xc2, 0x04, 0xd2, 0x05, 0xc2, 0x03, 0xc2, 0x00, 0xc2, 0x02, 0xc2, 0x01, 0x12, 0x0e, 0x3d, 0xd2} },
+{ 0x0761, 16, {0xe8, 0x43, 0xd8, 0x20, 0x90, 0x7f, 0xab, 0x74, 0xff, 0xf0, 0x90, 0x7f, 0xa9, 0xf0, 0x90, 0x7f} },
+{ 0x0771, 16, {0xaa, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f, 0x95, 0xe0, 0x44, 0xc0, 0xf0, 0x90, 0x7f, 0x93, 0x74} },
+{ 0x0781, 16, {0x30, 0xf0, 0x12, 0x0a, 0x19, 0x90, 0x7f, 0xaf, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xae, 0xe0} },
+{ 0x0791, 16, {0x44, 0x0d, 0xf0, 0xd2, 0xaf, 0x12, 0x0e, 0x35, 0x20, 0x01, 0x42, 0x75, 0x24, 0x00, 0x75, 0x23} },
+{ 0x07a1, 16, {0x00, 0x75, 0x22, 0x00, 0x75, 0x21, 0x00, 0x7f, 0x48, 0x7e, 0x92, 0x7d, 0x00, 0x7c, 0x00, 0xab} },
+{ 0x07b1, 16, {0x24, 0xaa, 0x23, 0xa9, 0x22, 0xa8, 0x21, 0xc3, 0x12, 0x08, 0xa9, 0x50, 0xdb, 0x20, 0x01, 0xd8} },
+{ 0x07c1, 16, {0x7a, 0x00, 0x79, 0x00, 0x78, 0x00, 0xe5, 0x24, 0x24, 0x01, 0xf5, 0x24, 0xea, 0x35, 0x23, 0xf5} },
+{ 0x07d1, 16, {0x23, 0xe9, 0x35, 0x22, 0xf5, 0x22, 0xe8, 0x35, 0x21, 0xf5, 0x21, 0x80, 0xca, 0x30, 0x01, 0x05} },
+{ 0x07e1, 16, {0x12, 0x03, 0x7a, 0xc2, 0x01, 0x30, 0x04, 0x1a, 0x12, 0x0e, 0x40, 0x50, 0x13, 0x12, 0x09, 0x00} },
+{ 0x07f1, 16, {0x30, 0x00, 0x07, 0x90, 0x7f, 0xd6, 0xe0, 0x30, 0xe7, 0xf3, 0x12, 0x0d, 0x4a, 0x12, 0x0e, 0x42} },
+{ 0x0801, 8, {0xc2, 0x03, 0x12, 0x08, 0xff, 0x80, 0xd6, 0x22} },
+{ 0x0809, 16, {0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb, 0xfe, 0x02} },
+{ 0x0819, 9, {0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22} },
+{ 0x0822, 16, {0xbb, 0x01, 0x0c, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50} },
+{ 0x0832, 16, {0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22} },
+{ 0x0842, 13, {0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe4, 0x93, 0x22} },
+{ 0x084f, 16, {0xf8, 0xbb, 0x01, 0x0d, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe8, 0xf0} },
+{ 0x085f, 16, {0x22, 0x50, 0x06, 0xe9, 0x25, 0x82, 0xc8, 0xf6, 0x22, 0xbb, 0xfe, 0x05, 0xe9, 0x25, 0x82, 0xc8} },
+{ 0x086f, 2, {0xf2, 0x22} },
+{ 0x0871, 16, {0xbb, 0x01, 0x10, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0xf5, 0xf0} },
+{ 0x0881, 16, {0xa3, 0xe0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, 0xf8, 0x86, 0xf0, 0x08, 0xe6, 0x22, 0xbb, 0xfe} },
+{ 0x0891, 16, {0x0a, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0xf5, 0xf0, 0x08, 0xe2, 0x22, 0xe5, 0x83, 0x2a, 0xf5, 0x83} },
+{ 0x08a1, 8, {0xe9, 0x93, 0xf5, 0xf0, 0xa3, 0xe9, 0x93, 0x22} },
+{ 0x08a9, 16, {0xeb, 0x9f, 0xf5, 0xf0, 0xea, 0x9e, 0x42, 0xf0, 0xe9, 0x9d, 0x42, 0xf0, 0xe8, 0x9c, 0x45, 0xf0} },
+{ 0x08b9, 1, {0x22} },
+{ 0x08ba, 2, {0x8f, 0x28} },
+{ 0x08bc, 16, {0xe4, 0xf5, 0x29, 0x75, 0x2a, 0xff, 0x75, 0x2b, 0x11, 0x75, 0x2c, 0x32, 0xab, 0x2a, 0xaa, 0x2b} },
+{ 0x08cc, 16, {0xa9, 0x2c, 0x90, 0x00, 0x01, 0x12, 0x08, 0x22, 0xb4, 0x03, 0x1d, 0xaf, 0x29, 0x05, 0x29, 0xef} },
+{ 0x08dc, 16, {0xb5, 0x28, 0x01, 0x22, 0x12, 0x08, 0x09, 0x7e, 0x00, 0x29, 0xff, 0xee, 0x3a, 0xa9, 0x07, 0x75} },
+{ 0x08ec, 14, {0x2a, 0xff, 0xf5, 0x2b, 0x89, 0x2c, 0x80, 0xd4, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} },
+{ 0x08fa, 1, {0x22} },
+{ 0x08fb, 4, {0x53, 0xd8, 0xef, 0x32} },
+{ 0x08ff, 1, {0x22} },
+{ 0x0900, 9, {0x90, 0x7f, 0xd6, 0xe0, 0x44, 0x80, 0xf0, 0x80, 0x74} },
+{ 0x097d, 16, {0x43, 0x87, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22} },
+{ 0x098d, 12, {0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x39, 0x02, 0x09, 0xd4} },
+{ 0x0999, 16, {0x02, 0x07, 0x51, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, 0xf2} },
+{ 0x09a9, 16, {0x08, 0xdf, 0xf4, 0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, 0x33} },
+{ 0x09b9, 16, {0xc4, 0x54, 0x0f, 0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf} },
+{ 0x09c9, 16, {0xe4, 0x80, 0x0b, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x0d, 0xec, 0xe4, 0x7e} },
+{ 0x09d9, 16, {0x01, 0x93, 0x60, 0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, 0x93} },
+{ 0x09e9, 16, {0xa3, 0x60, 0x01, 0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, 0xa3} },
+{ 0x09f9, 16, {0xfa, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca} },
+{ 0x0a09, 16, {0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0xbe} },
+{ 0x0a19, 16, {0xe4, 0x90, 0x7f, 0x9c, 0xf0, 0x7f, 0x0a, 0xfe, 0x12, 0x0d, 0x94, 0x90, 0x7f, 0x96, 0x74, 0x89} },
+{ 0x0a29, 16, {0xf0, 0x90, 0x7f, 0x9c, 0x74, 0xcf, 0xf0, 0x7f, 0xf4, 0x7e, 0x01, 0x12, 0x0d, 0x94, 0x90, 0x7f} },
+{ 0x0a39, 16, {0x96, 0xe0, 0x54, 0xfe, 0xf0, 0x7f, 0x0a, 0x7e, 0x00, 0x12, 0x0d, 0x94, 0x7f, 0x05, 0x7e, 0x00} },
+{ 0x0a49, 16, {0x12, 0x0d, 0x94, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x02, 0xf0, 0xe0, 0x54, 0x7f, 0xf0, 0x7f, 0x05} },
+{ 0x0a59, 16, {0x7e, 0x00, 0x12, 0x0d, 0x94, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x05, 0x7e, 0x00} },
+{ 0x0a69, 16, {0x12, 0x0d, 0x94, 0x90, 0x7f, 0x96, 0xe0, 0x54, 0xbf, 0xf0, 0x7f, 0x32, 0x7e, 0x00, 0x12, 0x0d} },
+{ 0x0a79, 16, {0x94, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x32, 0x7e, 0x00, 0x12, 0x0d, 0x94, 0x22} },
+{ 0x0a89, 16, {0x75, 0x32, 0x01, 0xe5, 0x32, 0x60, 0x1b, 0x7f, 0x01, 0x12, 0x0d, 0xd7, 0x7f, 0x00, 0x7e, 0x0e} },
+{ 0x0a99, 16, {0x7d, 0x00, 0x7c, 0x01, 0x12, 0x06, 0x94, 0xe4, 0x33, 0xf5, 0x32, 0x70, 0x05, 0x7f, 0x0f, 0x12} },
+{ 0x0aa9, 16, {0x0d, 0xd7, 0xe5, 0x32, 0x60, 0x1b, 0x7f, 0x02, 0x12, 0x0d, 0xd7, 0x7f, 0x00, 0x7e, 0x80, 0x7d} },
+{ 0x0ab9, 16, {0x00, 0x7c, 0x80, 0x12, 0x06, 0x94, 0xe4, 0x33, 0xf5, 0x32, 0x70, 0x05, 0x7f, 0x0f, 0x12, 0x0d} },
+{ 0x0ac9, 16, {0xd7, 0xe5, 0x32, 0x60, 0x1b, 0x7f, 0x03, 0x12, 0x0d, 0xd7, 0x7f, 0x00, 0x7e, 0x20, 0x7d, 0x40} },
+{ 0x0ad9, 16, {0x7c, 0x5b, 0x12, 0x06, 0x94, 0xe4, 0x33, 0xf5, 0x32, 0x70, 0x05, 0x7f, 0x0f, 0x12, 0x0d, 0xd7} },
+{ 0x0ae9, 14, {0xe5, 0x32, 0x60, 0x05, 0xe4, 0xff, 0x12, 0x0d, 0xd7, 0xe5, 0x32, 0x24, 0xff, 0x22} },
+{ 0x0af7, 8, {0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x10, 0xd3, 0x22} },
+{ 0x0aff, 1, {0x32} },
+{ 0x0b00, 16, {0x02, 0x0d, 0x64, 0x00, 0x02, 0x0d, 0xab, 0x00, 0x02, 0x0d, 0x2f, 0x00, 0x02, 0x0d, 0x7c, 0x00} },
+{ 0x0b10, 16, {0x02, 0x0d, 0xc1, 0x00, 0x02, 0x0a, 0xff, 0x00, 0x02, 0x0e, 0x4c, 0x00, 0x02, 0x0e, 0x4d, 0x00} },
+{ 0x0b20, 16, {0x02, 0x0e, 0x4e, 0x00, 0x02, 0x0e, 0x4f, 0x00, 0x02, 0x0e, 0x50, 0x00, 0x02, 0x0e, 0x51, 0x00} },
+{ 0x0b30, 16, {0x02, 0x0e, 0x52, 0x00, 0x02, 0x0e, 0x53, 0x00, 0x02, 0x0e, 0x54, 0x00, 0x02, 0x0e, 0x55, 0x00} },
+{ 0x0b40, 16, {0x02, 0x0e, 0x56, 0x00, 0x02, 0x0e, 0x57, 0x00, 0x02, 0x0e, 0x58, 0x00, 0x02, 0x0e, 0x59, 0x00} },
+{ 0x0b50, 8, {0x02, 0x0e, 0x5a, 0x00, 0x02, 0x0e, 0x5b, 0x00} },
+{ 0x0b58, 16, {0xe4, 0xfe, 0x75, 0x2a, 0xff, 0x75, 0x2b, 0x11, 0x75, 0x2c, 0x12, 0xab, 0x2a, 0xaa, 0x2b, 0xa9} },
+{ 0x0b68, 16, {0x2c, 0x90, 0x00, 0x01, 0x12, 0x08, 0x22, 0x64, 0x02, 0x70, 0x2d, 0xad, 0x06, 0x0e, 0xed, 0xb5} },
+{ 0x0b78, 16, {0x07, 0x01, 0x22, 0x90, 0x00, 0x02, 0x12, 0x08, 0x71, 0x85, 0xf0, 0x28, 0xf5, 0x29, 0x62, 0x28} },
+{ 0x0b88, 16, {0xe5, 0x28, 0x62, 0x29, 0xe5, 0x29, 0x62, 0x28, 0x29, 0xfd, 0xe5, 0x28, 0x3a, 0xa9, 0x05, 0x75} },
+{ 0x0b98, 14, {0x2a, 0xff, 0xf5, 0x2b, 0x89, 0x2c, 0x80, 0xc3, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} },
+{ 0x0ba6, 1, {0x22} },
+{ 0x0ba7, 16, {0xab, 0x07, 0xaa, 0x06, 0xac, 0x05, 0xe4, 0xfd, 0xe5, 0x11, 0x60, 0x11, 0xea, 0xff, 0xae, 0x05} },
+{ 0x0bb7, 16, {0x0d, 0xee, 0x24, 0x10, 0xf5, 0x82, 0xe4, 0x34, 0x0f, 0xf5, 0x83, 0xef, 0xf0, 0xeb, 0xae, 0x05} },
+{ 0x0bc7, 16, {0x0d, 0x74, 0x10, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x0f, 0xf5, 0x83, 0xeb, 0xf0, 0xaf, 0x05, 0x0d} },
+{ 0x0bd7, 16, {0x74, 0x10, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x0f, 0xf5, 0x83, 0xec, 0xf0, 0xaf, 0x0f, 0x7a, 0x0f} },
+{ 0x0be7, 13, {0x7b, 0x10, 0x12, 0x0d, 0x10, 0x7f, 0x0a, 0x7e, 0x00, 0x12, 0x0d, 0x94, 0x22} },
+{ 0x0bf4, 16, {0x8e, 0x32, 0x8f, 0x33, 0x8d, 0x34, 0x8a, 0x35, 0x8b, 0x36, 0xe4, 0xfd, 0xf5, 0x37, 0xe5, 0x11} },
+{ 0x0c04, 16, {0x60, 0x12, 0xe5, 0x32, 0xff, 0xae, 0x05, 0x0d, 0xee, 0x24, 0x13, 0xf5, 0x82, 0xe4, 0x34, 0x0f} },
+{ 0x0c14, 16, {0xf5, 0x83, 0xef, 0xf0, 0xe5, 0x33, 0xae, 0x05, 0x0d, 0x74, 0x13, 0x2e, 0xf5, 0x82, 0xe4, 0x34} },
+{ 0x0c24, 16, {0x0f, 0xf5, 0x83, 0xe5, 0x33, 0xf0, 0xaf, 0x0f, 0x7a, 0x0f, 0x7b, 0x13, 0x12, 0x0d, 0x10, 0xaf} },
+{ 0x0c34, 11, {0x0f, 0xad, 0x34, 0xab, 0x36, 0xaa, 0x35, 0x12, 0x0c, 0xf1, 0x22} },
+{ 0x0c3f, 16, {0x8e, 0x32, 0x8f, 0x33, 0x8d, 0x34, 0x8a, 0x35, 0x8b, 0x36, 0xe4, 0xf5, 0x37, 0xe5, 0x37, 0xc3} },
+{ 0x0c4f, 16, {0x95, 0x34, 0x50, 0x20, 0x05, 0x33, 0xe5, 0x33, 0xae, 0x32, 0x70, 0x02, 0x05, 0x32, 0x14, 0xff} },
+{ 0x0c5f, 16, {0xe5, 0x36, 0x25, 0x37, 0xf5, 0x82, 0xe4, 0x35, 0x35, 0xf5, 0x83, 0xe0, 0xfd, 0x12, 0x0b, 0xa7} },
+{ 0x0c6f, 5, {0x05, 0x37, 0x80, 0xd9, 0x22} },
+{ 0x0c74, 16, {0xa9, 0x07, 0xe5, 0x0d, 0x70, 0x25, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0, 0xe9, 0x25, 0xe0} },
+{ 0x0c84, 16, {0x44, 0x01, 0x90, 0x7f, 0xa6, 0xf0, 0x8d, 0x08, 0xaf, 0x03, 0xa9, 0x07, 0x75, 0x09, 0x01, 0x8a} },
+{ 0x0c94, 13, {0x0a, 0x89, 0x0b, 0xe4, 0xf5, 0x0c, 0x75, 0x0d, 0x03, 0xd3, 0x22, 0xc3, 0x22} },
+{ 0x0ca1, 16, {0xa9, 0x07, 0xe5, 0x0d, 0x70, 0x23, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0, 0xe9, 0x25, 0xe0} },
+{ 0x0cb1, 16, {0x90, 0x7f, 0xa6, 0xf0, 0x8d, 0x08, 0xaf, 0x03, 0xa9, 0x07, 0x75, 0x09, 0x01, 0x8a, 0x0a, 0x89} },
+{ 0x0cc1, 11, {0x0b, 0xe4, 0xf5, 0x0c, 0x75, 0x0d, 0x01, 0xd3, 0x22, 0xc3, 0x22} },
+{ 0x0ccc, 16, {0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xfb, 0xf0, 0xe0, 0x44, 0x08, 0xf0, 0x30, 0x06, 0x04, 0xe0, 0x44} },
+{ 0x0cdc, 16, {0x02, 0xf0, 0x7f, 0xd0, 0x7e, 0x07, 0x12, 0x0d, 0x94, 0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xf7, 0xf0} },
+{ 0x0cec, 5, {0xe0, 0x44, 0x04, 0xf0, 0x22} },
+{ 0x0cf1, 16, {0x12, 0x0c, 0x74, 0xe5, 0x0d, 0x24, 0xfa, 0x60, 0x10, 0x14, 0x60, 0x07, 0x24, 0x07, 0x70, 0xf3} },
+{ 0x0d01, 15, {0x7f, 0x08, 0x22, 0xe4, 0xf5, 0x0d, 0x7f, 0x07, 0x22, 0xe4, 0xf5, 0x0d, 0x7f, 0x06, 0x22} },
+{ 0x0d10, 16, {0x12, 0x0c, 0xa1, 0xe5, 0x0d, 0x24, 0xfa, 0x60, 0x10, 0x14, 0x60, 0x07, 0x24, 0x07, 0x70, 0xf3} },
+{ 0x0d20, 15, {0x7f, 0x08, 0x22, 0xe4, 0xf5, 0x0d, 0x7f, 0x07, 0x22, 0xe4, 0xf5, 0x0d, 0x7f, 0x06, 0x22} },
+{ 0x0d2f, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x90, 0x7f, 0xc4, 0xe4, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f} },
+{ 0x0d3f, 11, {0xab, 0x74, 0x04, 0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0d4a, 16, {0x90, 0x7f, 0xd6, 0xe0, 0x30, 0xe7, 0x12, 0xe0, 0x44, 0x01, 0xf0, 0x7f, 0x14, 0x7e, 0x00, 0x12} },
+{ 0x0d5a, 10, {0x0d, 0x94, 0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xfe, 0xf0, 0x22} },
+{ 0x0d64, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xd2, 0x01, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x01} },
+{ 0x0d74, 8, {0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0d7c, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xd2, 0x03, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x08} },
+{ 0x0d8c, 8, {0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0d94, 16, {0x8e, 0x38, 0x8f, 0x39, 0xe5, 0x39, 0x15, 0x39, 0xae, 0x38, 0x70, 0x02, 0x15, 0x38, 0x4e, 0x60} },
+{ 0x0da4, 7, {0x05, 0x12, 0x0e, 0x00, 0x80, 0xee, 0x22} },
+{ 0x0dab, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x02, 0xf0, 0xd0} },
+{ 0x0dbb, 6, {0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0dc1, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x10, 0xf0, 0xd0} },
+{ 0x0dd1, 6, {0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0dd7, 16, {0xae, 0x07, 0x7f, 0x21, 0x7d, 0x01, 0x74, 0x00, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x0f, 0xab, 0x82} },
+{ 0x0de7, 5, {0xfa, 0x12, 0x0d, 0x10, 0x22} },
+{ 0x0dec, 16, {0x50, 0x0f, 0x00, 0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x98, 0x88, 0x83, 0xc6} },
+{ 0x0dfc, 3, {0xa1, 0x86, 0x8e} },
+{ 0x0dff, 1, {0x00} },
+{ 0x0e00, 16, {0x74, 0x00, 0xf5, 0x86, 0x90, 0xfd, 0xa5, 0x7c, 0x05, 0xa3, 0xe5, 0x82, 0x45, 0x83, 0x70, 0xf9} },
+{ 0x0e10, 1, {0x22} },
+{ 0x0e11, 14, {0x90, 0x7f, 0x00, 0xe5, 0x10, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0xd3, 0x22} },
+{ 0x0e1f, 14, {0x90, 0x7f, 0x00, 0xe5, 0x0e, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0xd3, 0x22} },
+{ 0x0e2d, 8, {0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x0e, 0xd3, 0x22} },
+{ 0x0e35, 8, {0xe4, 0xf5, 0x0d, 0xd2, 0xe9, 0xd2, 0xaf, 0x22} },
+{ 0x0e3d, 3, {0xd2, 0x00, 0x22} },
+{ 0x0e40, 2, {0xd3, 0x22} },
+{ 0x0e42, 2, {0xd3, 0x22} },
+{ 0x0e44, 2, {0xd3, 0x22} },
+{ 0x0e46, 2, {0xd3, 0x22} },
+{ 0x0e48, 2, {0xd3, 0x22} },
+{ 0x0e4a, 2, {0xd3, 0x22} },
+{ 0x0e4c, 1, {0x32} },
+{ 0x0e4d, 1, {0x32} },
+{ 0x0e4e, 1, {0x32} },
+{ 0x0e4f, 1, {0x32} },
+{ 0x0e50, 1, {0x32} },
+{ 0x0e51, 1, {0x32} },
+{ 0x0e52, 1, {0x32} },
+{ 0x0e53, 1, {0x32} },
+{ 0x0e54, 1, {0x32} },
+{ 0x0e55, 1, {0x32} },
+{ 0x0e56, 1, {0x32} },
+{ 0x0e57, 1, {0x32} },
+{ 0x0e58, 1, {0x32} },
+{ 0x0e59, 1, {0x32} },
+{ 0x0e5a, 1, {0x32} },
+{ 0x0e5b, 1, {0x32} },
+{ 0x1100, 16, {0x12, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x47, 0x05, 0x10, 0x27, 0x01, 0x00, 0x01, 0x02} },
+{ 0x1110, 16, {0x00, 0x01, 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x03, 0xa0, 0x00, 0x09, 0x04, 0x00, 0x00, 0x02} },
+{ 0x1120, 16, {0xff, 0x00, 0x00, 0x04, 0x07, 0x05, 0x82, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x02, 0x02, 0x40} },
+{ 0x1130, 16, {0x00, 0x00, 0x04, 0x03, 0x09, 0x04, 0x26, 0x03, 0x41, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x68, 0x00} },
+{ 0x1140, 16, {0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x43, 0x00, 0x68, 0x00, 0x69, 0x00, 0x70, 0x00, 0x73, 0x00} },
+{ 0x1150, 16, {0x2c, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x2e, 0x00, 0x28, 0x03, 0x46, 0x00} },
+{ 0x1160, 16, {0x69, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x77, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00} },
+{ 0x1170, 16, {0x46, 0x00, 0x72, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x57, 0x00, 0x6f, 0x00, 0x72, 0x00} },
+{ 0x1180, 16, {0x6b, 0x00, 0x73, 0x00, 0x2a, 0x03, 0x43, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x66, 0x00, 0x69, 0x00} },
+{ 0x1190, 16, {0x67, 0x00, 0x75, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00} },
+{ 0x11a0, 16, {0x20, 0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x22, 0x03} },
+{ 0x11b0, 16, {0x49, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x66, 0x00, 0x61, 0x00, 0x63, 0x00} },
+{ 0x11c0, 16, {0x65, 0x00, 0x20, 0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00} },
+{ 0x11d0, 2, {0x00, 0x00} },
+{ 0xffff, 0, {0x00} }
+};
+#endif
diff --git a/drivers/usb/wmforce.c b/drivers/usb/wmforce.c
new file mode 100644
index 000000000..b8fef7891
--- /dev/null
+++ b/drivers/usb/wmforce.c
@@ -0,0 +1,165 @@
+/*
+ * wmforce.c Version 0.1
+ *
+ * Copyright (c) 1999 Vojtech Pavlik
+ *
+ * USB Logitech WingMan Force tablet support
+ *
+ * Sponsored by SuSE
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include <linux/kernel.h>
+#include <linux/malloc.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include "usb.h"
+
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
+
+#define USB_VENDOR_ID_LOGITECH 0x046d
+#define USB_DEVICE_ID_LOGITECH_WMFORCE 0xc281
+
+struct wmforce {
+ signed char data[8];
+ struct input_dev dev;
+ struct urb irq;
+};
+
+static struct {
+ __s32 x;
+ __s32 y;
+} wmforce_hat_to_axis[16] = {{ 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
+
+static void wmforce_irq(struct urb *urb)
+{
+ struct wmforce *wmforce = urb->context;
+ unsigned char *data = wmforce->data;
+ struct input_dev *dev = &wmforce->dev;
+
+ if (urb->status) return;
+
+ if (data[0] != 1) {
+ if (data[0] != 2)
+ warn("received unknown report #%d", data[0]);
+ return;
+ }
+
+ input_report_abs(dev, ABS_X, (__s16) (((__s16)data[2] << 8) | data[1]));
+ input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[4] << 8) | data[3]));
+ input_report_abs(dev, ABS_THROTTLE, data[5]);
+ input_report_abs(dev, ABS_HAT0X, wmforce_hat_to_axis[data[7] >> 4].x);
+ input_report_abs(dev, ABS_HAT0Y, wmforce_hat_to_axis[data[7] >> 4].y);
+
+ input_report_key(dev, BTN_TRIGGER, !!(data[6] & 0x01));
+ input_report_key(dev, BTN_TOP, !!(data[6] & 0x02));
+ input_report_key(dev, BTN_THUMB, !!(data[6] & 0x04));
+ input_report_key(dev, BTN_TOP2, !!(data[6] & 0x08));
+ input_report_key(dev, BTN_BASE, !!(data[6] & 0x10));
+ input_report_key(dev, BTN_BASE2, !!(data[6] & 0x20));
+ input_report_key(dev, BTN_BASE3, !!(data[6] & 0x40));
+ input_report_key(dev, BTN_BASE4, !!(data[6] & 0x80));
+ input_report_key(dev, BTN_BASE5, !!(data[7] & 0x01));
+}
+
+static void *wmforce_probe(struct usb_device *dev, unsigned int ifnum)
+{
+ struct usb_endpoint_descriptor *endpoint;
+ struct wmforce *wmforce;
+ int i;
+
+ if (dev->descriptor.idVendor != USB_VENDOR_ID_LOGITECH ||
+ dev->descriptor.idProduct != USB_DEVICE_ID_LOGITECH_WMFORCE)
+ return NULL;
+
+ endpoint = dev->config[0].interface[ifnum].altsetting[0].endpoint + 0;
+
+ if (!(wmforce = kmalloc(sizeof(struct wmforce), GFP_KERNEL))) return NULL;
+ memset(wmforce, 0, sizeof(struct wmforce));
+
+ wmforce->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ wmforce->dev.keybit[LONG(BTN_JOYSTICK)] = BIT(BTN_TRIGGER) | BIT(BTN_TOP) | BIT(BTN_THUMB) | BIT(BTN_TOP2) |
+ BIT(BTN_BASE) | BIT(BTN_BASE2) | BIT(BTN_BASE3) | BIT(BTN_BASE4) | BIT(BTN_BASE5);
+ wmforce->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_THROTTLE) | BIT(ABS_HAT0X) | BIT(ABS_HAT0Y);
+
+ for (i = ABS_X; i <= ABS_Y; i++) {
+ wmforce->dev.absmax[i] = 1920;
+ wmforce->dev.absmin[i] = -1920;
+ wmforce->dev.absfuzz[i] = 0;
+ wmforce->dev.absflat[i] = 128;
+ }
+
+ wmforce->dev.absmax[ABS_THROTTLE] = 0;
+ wmforce->dev.absmin[ABS_THROTTLE] = 255;
+ wmforce->dev.absfuzz[ABS_THROTTLE] = 0;
+ wmforce->dev.absflat[ABS_THROTTLE] = 0;
+
+ for (i = ABS_HAT0X; i <= ABS_HAT0Y; i++) {
+ wmforce->dev.absmax[i] = 1;
+ wmforce->dev.absmin[i] = -1;
+ wmforce->dev.absfuzz[i] = 0;
+ wmforce->dev.absflat[i] = 0;
+ }
+
+ FILL_INT_URB(&wmforce->irq, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress),
+ wmforce->data, 8, wmforce_irq, wmforce, endpoint->bInterval);
+
+ if (usb_submit_urb(&wmforce->irq)) {
+ kfree(wmforce);
+ return NULL;
+ }
+
+ input_register_device(&wmforce->dev);
+
+ printk(KERN_INFO "input%d: Logitech WingMan Force USB\n", wmforce->dev.number);
+
+ return wmforce;
+}
+
+static void wmforce_disconnect(struct usb_device *dev, void *ptr)
+{
+ struct wmforce *wmforce = ptr;
+ usb_unlink_urb(&wmforce->irq);
+ input_unregister_device(&wmforce->dev);
+ kfree(wmforce);
+}
+
+static struct usb_driver wmforce_driver = {
+ name: "wmforce",
+ probe: wmforce_probe,
+ disconnect: wmforce_disconnect,
+};
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+ usb_deregister(&wmforce_driver);
+}
+
+int init_module(void)
+#else
+int wmforce_init(void)
+#endif
+{
+ usb_register(&wmforce_driver);
+ return 0;
+}