diff options
Diffstat (limited to 'drivers/usb')
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 (®s->intrstatus) & readl (®s->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; +} |