From b9558d5f86c471a125abf1fb3a3882fb053b1f8c Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 18 Feb 2000 00:24:27 +0000 Subject: Merge with Linux 2.3.41. --- drivers/usb/Config.in | 23 +- drivers/usb/Makefile | 25 +- drivers/usb/audio.c | 4 +- drivers/usb/bitstream.h | 1508 ------------------ drivers/usb/dabfirmware.h | 1408 +++++++++++++++++ drivers/usb/dabusb.c | 3 +- drivers/usb/dc2xx.c | 4 +- drivers/usb/devices.c | 4 +- drivers/usb/firmware.h | 3213 --------------------------------------- drivers/usb/graphire.c | 71 +- drivers/usb/hid.c | 80 +- drivers/usb/hid.h | 2 +- drivers/usb/hub.c | 66 +- drivers/usb/ibmcam.c | 2346 ++++++++++++++++++++++++++++ drivers/usb/ibmcam.h | 222 +++ drivers/usb/keybdev.c | 6 +- drivers/usb/mousedev.c | 55 +- drivers/usb/ohci-hcd.c | 1823 ---------------------- drivers/usb/ohci-hcd.h | 407 ----- drivers/usb/ov511.c | 34 +- drivers/usb/scanner.c | 397 +++-- drivers/usb/scanner.h | 55 + drivers/usb/uhci-debug.c | 245 --- drivers/usb/uhci-debug.h | 202 ++- drivers/usb/uhci.c | 2336 ---------------------------- drivers/usb/uhci.h | 251 --- drivers/usb/usb-core.c | 8 +- drivers/usb/usb-debug.c | 31 +- drivers/usb/usb-ohci.c | 1822 ++++++++++++++++++++++ drivers/usb/usb-ohci.h | 407 +++++ drivers/usb/usb-serial.c | 315 +++- drivers/usb/usb-uhci.c | 2359 ++++++++++++++++++++++++++++ drivers/usb/usb-uhci.h | 252 +++ drivers/usb/usb.c | 158 +- drivers/usb/usb.h | 38 +- drivers/usb/usb_scsi.c | 1539 ------------------- drivers/usb/usb_scsi.h | 146 -- drivers/usb/usb_scsi_debug.c | 102 -- drivers/usb/usb_storage.c | 1837 ++++++++++++++++++++++ drivers/usb/usb_storage.h | 130 ++ drivers/usb/usb_storage_debug.c | 104 ++ drivers/usb/usbdevice_fs.h | 1 - drivers/usb/usbkbd.c | 3 +- drivers/usb/usbmouse.c | 3 +- drivers/usb/uss720.c | 21 +- drivers/usb/wmforce.c | 4 +- 46 files changed, 12070 insertions(+), 12000 deletions(-) delete mode 100644 drivers/usb/bitstream.h create mode 100644 drivers/usb/dabfirmware.h delete mode 100644 drivers/usb/firmware.h create mode 100644 drivers/usb/ibmcam.c create mode 100644 drivers/usb/ibmcam.h delete mode 100644 drivers/usb/ohci-hcd.c delete mode 100644 drivers/usb/ohci-hcd.h create mode 100644 drivers/usb/scanner.h delete mode 100644 drivers/usb/uhci-debug.c delete mode 100644 drivers/usb/uhci.c delete mode 100644 drivers/usb/uhci.h create mode 100644 drivers/usb/usb-ohci.c create mode 100644 drivers/usb/usb-ohci.h create mode 100644 drivers/usb/usb-uhci.c create mode 100644 drivers/usb/usb-uhci.h delete mode 100644 drivers/usb/usb_scsi.c delete mode 100644 drivers/usb/usb_scsi.h delete mode 100644 drivers/usb/usb_scsi_debug.c create mode 100644 drivers/usb/usb_storage.c create mode 100644 drivers/usb/usb_storage.h create mode 100644 drivers/usb/usb_storage_debug.c (limited to 'drivers/usb') diff --git a/drivers/usb/Config.in b/drivers/usb/Config.in index b0a372455..aa8c6adb2 100644 --- a/drivers/usb/Config.in +++ b/drivers/usb/Config.in @@ -9,7 +9,7 @@ if [ ! "$CONFIG_USB" = "n" ]; then comment 'USB Controllers' 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 + dep_tristate ' OHCI (Compaq, iMacs, OPTi, SiS, ALi, ...) support' CONFIG_USB_OHCI $CONFIG_USB comment 'Miscellaneous USB options' bool ' Preliminary USB device filesystem' CONFIG_USB_DEVICEFS @@ -22,17 +22,19 @@ comment 'USB Devices' 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 + bool ' USB ConnectTech WhiteHEAT Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_WHITEHEAT + bool ' USB FTDI Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_FTDI + bool ' USB Belkin Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_BELKIN + bool ' USB Peracom Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_PERACOM fi dep_tristate ' USB CPiA Camera support' CONFIG_USB_CPIA $CONFIG_USB + dep_tristate ' USB IBM (Xirlink) C-it Camera support' CONFIG_USB_IBMCAM $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 - dep_tristate ' USB SCSI (mass storage) support' CONFIG_USB_SCSI $CONFIG_USB - if [ "$CONFIG_USB_SCSI" != "n" ]; then - bool ' USB SCSI verbose debug' CONFIG_USB_SCSI_DEBUG + dep_tristate ' USB Mass Storage support' CONFIG_USB_STORAGE $CONFIG_USB + if [ "$CONFIG_USB_STORAGE" != "n" ]; then + bool ' USB Mass Storage verbose debug' CONFIG_USB_STORAGE_DEBUG fi dep_tristate ' USS720 parport driver' CONFIG_USB_USS720 $CONFIG_USB $CONFIG_PARPORT dep_tristate ' DABUSB driver' CONFIG_USB_DABUSB $CONFIG_USB @@ -48,7 +50,12 @@ comment 'USB HID' dep_tristate ' Keyboard support' CONFIG_INPUT_KEYBDEV $CONFIG_USB dep_tristate ' Mouse support' CONFIG_INPUT_MOUSEDEV $CONFIG_USB if [ "$CONFIG_INPUT_MOUSEDEV" != "n" ]; then - bool ' Mix all mice into one device' CONFIG_INPUT_MOUSEDEV_MIX + bool ' Mix all mice into one device' CONFIG_INPUT_MOUSEDEV_MIX + bool ' Support for digitizers' CONFIG_INPUT_MOUSEDEV_DIGITIZER + if [ "$CONFIG_INPUT_MOUSEDEV_DIGITIZER" != "n" ]; then + int ' Horizontal screen resolution' CONFIG_INPUT_MOUSEDEV_SCREEN_X 1024 + int ' Vertical screen resolution' CONFIG_INPUT_MOUSEDEV_SCREEN_Y 768 + fi fi dep_tristate ' Joystick support' CONFIG_INPUT_JOYDEV $CONFIG_USB dep_tristate ' Event interface support' CONFIG_INPUT_EVDEV $CONFIG_USB diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index 9eb62b6a1..ee2cee37a 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -21,19 +21,17 @@ export-objs := usb.o input.o # Multipart objects. -list-multi := usbcore.o usb-uhci.o usb-ohci-hcd.o +list-multi := usbcore.o usbcore-objs := usb.o usb-debug.o usb-core.o hub.o -usb-uhci-objs := uhci.o uhci-debug.o -usb-ohci-hcd-objs := ohci-hcd.o -usb-scsi-objs := usb_scsi.o +usb-storage-objs := usb_storage.o # Optional parts of multipart objects. 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 +ifeq ($(CONFIG_USB_STORAGE_DEBUG),y) + usb-storage-objs += usb_storage_debug.o endif # Object file lists. @@ -47,7 +45,7 @@ obj- := obj-$(CONFIG_USB) += usbcore.o obj-$(CONFIG_USB_UHCI) += usb-uhci.o -obj-$(CONFIG_USB_OHCI_HCD) += usb-ohci-hcd.o +obj-$(CONFIG_USB_OHCI) += usb-ohci.o obj-$(CONFIG_USB_MOUSE) += usbmouse.o input.o obj-$(CONFIG_USB_HID) += hid.o input.o @@ -65,8 +63,9 @@ obj-$(CONFIG_USB_PRINTER) += printer.o obj-$(CONFIG_USB_SERIAL) += usb-serial.o obj-$(CONFIG_USB_AUDIO) += audio.o obj-$(CONFIG_USB_CPIA) += cpia.o +obj-$(CONFIG_USB_IBMCAM) += ibmcam.o obj-$(CONFIG_USB_DC2XX) += dc2xx.o -obj-$(CONFIG_USB_SCSI) += usb-scsi.o +obj-$(CONFIG_USB_STORAGE) += usb-storage.o obj-$(CONFIG_USB_USS720) += uss720.o obj-$(CONFIG_USB_DABUSB) += dabusb.o obj-$(CONFIG_USB_OV511) += ov511.o @@ -106,11 +105,5 @@ include $(TOPDIR)/Rules.make usbcore.o: $(usbcore-objs) $(LD) -r -o $@ $(usbcore-objs) -usb-uhci.o: $(usb-uhci-objs) - $(LD) -r -o $@ $(usb-uhci-objs) - -usb-ohci-hcd.o: $(usb-ohci-hcd-objs) - $(LD) -r -o $@ $(usb-ohci-hcd-objs) - -usb-scsi.o: $(usb-scsi-objs) - $(LD) -r -o $@ $(usb-scsi-objs) +usb-storage.o: $(usb-storage-objs) + $(LD) -r -o $@ $(usb-storage-objs) diff --git a/drivers/usb/audio.c b/drivers/usb/audio.c index 8be39a9b3..35181ee90 100644 --- a/drivers/usb/audio.c +++ b/drivers/usb/audio.c @@ -3129,10 +3129,12 @@ static void usb_audio_processingunit(struct consmixstate *state, unsigned char * static void usb_audio_featureunit(struct consmixstate *state, unsigned char *ftr) { - struct usb_device *dev = state->s->usbdev; struct mixerchannel *ch; unsigned short chftr, mchftr; +#if 0 + struct usb_device *dev = state->s->usbdev; unsigned char data[1]; +#endif usb_audio_recurseunit(state, ftr[4]); if (state->nrchannels == 0) { diff --git a/drivers/usb/bitstream.h b/drivers/usb/bitstream.h deleted file mode 100644 index 5d272b130..000000000 --- a/drivers/usb/bitstream.h +++ /dev/null @@ -1,1508 +0,0 @@ -static unsigned char bitstream[] = { -0x00,0x09,0x0F,0xF0,0x0F,0xF0,0x0F,0xF0, -0x0F,0xF0,0x00,0x00,0x01,0x61,0x00,0x0D, -0x64,0x61,0x62,0x75,0x73,0x62,0x74,0x72, -0x2E,0x6E,0x63,0x64,0x00,0x62,0x00,0x0B, -0x73,0x31,0x30,0x78,0x6C,0x76,0x71,0x31, -0x30,0x30,0x00,0x63,0x00,0x0B,0x31,0x39, -0x39,0x39,0x2F,0x30,0x39,0x2F,0x32,0x34, -0x00,0x64,0x00,0x09,0x31,0x30,0x3A,0x34, -0x32,0x3A,0x34,0x36,0x00,0x65,0x00,0x00, -0x2E,0xC0,0xFF,0x20,0x17,0x5F,0x9F,0x5B, -0xFE,0xFB,0xBB,0xB7,0xBB,0xBB,0xFB,0xBF, -0xAF,0xEF,0xFB,0xDF,0xB7,0xFB,0xFB,0x7F, -0xBF,0xB7,0xEF,0xF2,0xFF,0xFB,0xFE,0xFF, -0xFF,0xEF,0xFF,0xFE,0xFF,0xBF,0xFF,0xFF, -0xFF,0xFF,0xAF,0xFF,0xFA,0xFF,0xFF,0xFF, -0xC9,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFB,0xFF,0xA3,0xFF,0xFB, -0xFE,0xFF,0xBF,0xEF,0xE3,0xFE,0xFF,0xBF, -0xE3,0xFE,0xFF,0xBF,0x6F,0xFB,0xF6,0xFF, -0xBF,0xFF,0x47,0xFF,0xFF,0x9F,0xEE,0xF9, -0xFE,0xCF,0x9F,0xEF,0xFB,0xCF,0x9B,0xEE, -0xF8,0xFE,0xEF,0x8F,0xEE,0xFB,0xFE,0x0B, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xBF,0xFF,0xFF,0xFB,0xFF,0xFF, -0xBF,0xFF,0xFF,0xFC,0x17,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0x7F, -0xFF,0xFF,0xFB,0xFF,0xFF,0x7F,0xFF,0xFF, -0xFC,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x5F,0xFF, -0xFF,0xFD,0xFF,0xFF,0xDB,0xFF,0xFD,0xFF, -0x77,0xFF,0xFD,0xFF,0xFF,0xDF,0xFE,0xFD, -0xFF,0xFF,0xF2,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFD,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE1, -0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xE3,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF, -0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0x67,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0x7F,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF, -0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0x2F,0xFF, -0xF3,0xFD,0xFF,0x7F,0xDE,0xF7,0xFD,0xFF, -0x7F,0xF7,0x7D,0xFF,0x7F,0xDF,0xF7,0xBD, -0xFF,0x7F,0xFF,0x1F,0xFF,0xEF,0xFB,0xFE, -0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xEF,0xFB, -0xFE,0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xFF, -0x3F,0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x7F, -0x9F,0xE7,0xFA,0x7F,0x9F,0xE7,0xF9,0xFE, -0x7F,0x9F,0xE7,0xFF,0xFC,0x7F,0xBF,0xBF, -0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB,0xB7, -0xBF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB, -0xFF,0xE0,0xFD,0xF9,0xFE,0x7F,0x9F,0xE7, -0xF9,0xFE,0x7F,0x9D,0xF9,0xFE,0x7D,0x9D, -0xE7,0xF9,0xFE,0x7F,0x9F,0xED,0xED,0xFF, -0xFD,0xFF,0x7F,0xDF,0xF7,0xFD,0xFF,0x7F, -0xDF,0xFD,0xFF,0x7F,0xDF,0xF7,0xFD,0xFF, -0x7F,0xDF,0xFF,0x9B,0xFF,0xEF,0xFB,0xFE, -0xFB,0xBF,0xEF,0xBB,0xFE,0xFF,0xAF,0xBB, -0xBE,0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xFF, -0xB7,0xBF,0xDB,0xF6,0xBD,0xBF,0x6B,0xDB, -0xF6,0xF9,0xBF,0x5B,0xD6,0xF9,0xBF,0x6F, -0xDB,0xF6,0xFD,0xBF,0xFF,0x0E,0xFF,0xFF, -0xFF,0xFF,0x5F,0xFF,0xF7,0xFF,0xFF,0x7F, -0xF7,0xBD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xDF,0x9F,0xFF,0xFF,0xFF,0xFE,0xFF, -0xFF,0xEF,0xFE,0xFE,0xFF,0xFF,0x77,0xFF, -0xFB,0xFB,0xFF,0xFF,0xFF,0xFF,0xF8,0x3F, -0xFF,0xFD,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xF4,0x7F,0xFF,0xFE,0xFD, -0xBE,0xFF,0xDF,0xFE,0xFF,0xFF,0xEF,0x7F, -0xFF,0xCF,0xFF,0xCF,0xFF,0xFF,0xFF,0xDF, -0xE6,0xFF,0xFF,0x7F,0xDF,0xF7,0xDD,0x7F, -0x7F,0xDF,0xF7,0xFF,0x7F,0xDF,0xD7,0xFD, -0xFF,0x7F,0xDF,0xF7,0xFF,0xCD,0xFF,0xF2, -0xFF,0xFF,0x4F,0x7F,0xF4,0xFF,0xFF,0xFF, -0xE7,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xBB,0xFF,0xEF,0xFF,0xFE,0xFF, -0xFF,0xFF,0xEF,0xFF,0xFF,0xEF,0xFF,0xFB, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x65, -0xEF,0xFF,0xFF,0x7F,0xFF,0xFD,0xEF,0xFF, -0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFE,0xCF,0xDF,0xFE,0xFF, -0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xF3,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFE,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xBF,0xFF, -0xFF,0xFF,0xE3,0x7F,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xEF,0xEB,0xFF,0xFE,0xBF,0xFF, -0xEB,0xFF,0xFC,0x7F,0xFF,0xFF,0xFF,0xEE, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDD,0xFF, -0xD6,0xFF,0xFD,0xBF,0xFF,0xFB,0xFF,0xFE, -0xFD,0xFF,0xFF,0xFD,0xEF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xDE,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xBF,0xFF,0xFD,0xFF,0x7F,0xBF, -0xFF,0x5F,0xDF,0xFF,0xFF,0xBF,0x77,0xFF, -0xFF,0xFF,0x7F,0xD7,0xFF,0xFF,0xFF,0xFF, -0xFF,0xC3,0xFF,0xFF,0xFF,0xFF,0xDF,0xEF, -0xFF,0xFF,0xFE,0xFB,0xFF,0xFF,0xDF,0xBF, -0xFF,0xFF,0xFF,0xFF,0xED,0xFF,0xB7,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xAF,0x7F,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xDF,0xBF,0xDF,0xF3,0xFD,0xFB,0xFF,0x5B, -0xFD,0xFF,0xBF,0xEF,0xF7,0xFF,0xFF,0x7D, -0xFF,0xFF,0xFF,0xFF,0xF8,0x3B,0xFF,0xBF, -0x6F,0xFF,0xFE,0xFF,0xBF,0xFF,0xEB,0x7D, -0xFF,0xEF,0xFB,0xFE,0xFF,0xFF,0xFF,0xFF, -0xFF,0xF2,0x7F,0xFC,0xFF,0x3F,0xDF,0xED, -0xFE,0xFF,0xFF,0xFF,0xFF,0xEF,0x5F,0xF7, -0xB5,0xFF,0xEF,0xFF,0xFF,0xFF,0xE0,0x3F, -0x9F,0x9E,0xFF,0xFF,0xEF,0xFF,0xDF,0xFF, -0xBF,0x5F,0xBF,0xCF,0xF3,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0x69,0xAF,0x33,0xFD,0xFF, -0xFB,0xFF,0xFF,0xFF,0xFF,0xFC,0xFF,0x7F, -0xD9,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xF5, -0xA3,0xDF,0x6E,0xDE,0xFF,0xFF,0xBD,0xFF, -0xFF,0xFE,0xFF,0xFF,0xFF,0xFE,0xE7,0xFD, -0xFF,0xFF,0xFF,0xF9,0xEF,0xC6,0xFE,0xB7, -0xAD,0xE5,0xF9,0xFF,0xFF,0xFF,0xCF,0xFF, -0xFF,0xFF,0xCD,0xFB,0x7F,0xFF,0xFF,0xFF, -0xF9,0xF6,0x0F,0xDF,0xEC,0xCF,0x7F,0xFF, -0xFB,0x7F,0xFF,0xFF,0xFF,0xFD,0xFF,0xFE, -0xF9,0xFD,0x7F,0xFF,0x7F,0xFF,0xF9,0x5B, -0xFF,0x73,0xDC,0xFD,0x7B,0xDF,0xFF,0xFF, -0xFF,0x7B,0xFF,0xFF,0xF7,0x53,0xD6,0xFF, -0xFF,0xFF,0xFF,0xD8,0x9F,0xFE,0xFF,0xEF, -0x7F,0xEE,0xFF,0xFF,0xFF,0xFB,0xED,0xED, -0xFD,0xFF,0xFE,0xFF,0xFF,0xFB,0x7F,0xFF, -0xE2,0x7F,0xFF,0x6F,0xD8,0x57,0xF7,0xFF, -0xFF,0xFF,0xDF,0xFF,0xE8,0xFF,0xFF,0xFD, -0xFF,0xFF,0xFC,0x7F,0xFF,0xE4,0xFF,0xFB, -0xEF,0xFB,0xFE,0xDF,0xB7,0xED,0xFF,0xFE, -0xDF,0x7F,0xFF,0xFE,0x7F,0xB7,0xFF,0xFF, -0xFF,0xFF,0x89,0xFF,0xFF,0xCF,0xF3,0xFE, -0x7F,0xFF,0xEF,0xFF,0xFE,0x7E,0x7F,0xFB, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF1, -0xFF,0xEB,0x7A,0xD5,0xBF,0x6F,0xDB,0xBE, -0xFD,0xB7,0xD8,0xF6,0xE5,0xBF,0x6F,0xFB, -0xFE,0xF5,0xBD,0x7E,0x06,0xFF,0xDF,0xF7, -0xFB,0xF6,0xFF,0x3F,0xFF,0xDB,0xFF,0xFF, -0x6F,0xFB,0xF7,0xFF,0xFF,0xFF,0xFB,0xFE, -0xF7,0xAF,0xFF,0xB7,0xED,0xEF,0xF7,0xFE, -0xFF,0xFF,0xDF,0xFF,0xFE,0xFF,0xEF,0xFF, -0xFF,0xFF,0xFF,0xBF,0xF7,0xFC,0x1F,0xEE, -0xFB,0xFE,0xBD,0xFF,0x7F,0x5F,0xD7,0xFD, -0xFB,0x43,0xFF,0xFF,0xFD,0xFF,0x5F,0xFF, -0xF7,0xFF,0xF9,0x3F,0xFF,0xCF,0xF3,0xFD, -0xF7,0x7E,0xEF,0xA7,0xF9,0xFE,0x8F,0xA7, -0xE9,0xF3,0x7E,0x9F,0xFB,0xF8,0xFF,0xFF, -0x3F,0xFD,0x7F,0x5F,0xDF,0xFD,0xFF,0xFF, -0x5F,0xFF,0xFD,0x5F,0xFF,0xFF,0x7F,0xFD, -0x7F,0xFD,0x9F,0xFF,0xE0,0xFF,0xFA,0xF8, -0xBE,0x6F,0x9F,0xE6,0xF8,0xBE,0x3F,0x9A, -0xF9,0xBE,0x6F,0x9F,0xE2,0xF9,0xFE,0x6F, -0x9F,0xF9,0xFF,0xF5,0xFD,0x7F,0xCF,0xDF, -0xFD,0xFD,0x7F,0xFF,0xF5,0xFF,0xFF,0xFF, -0xF7,0xF5,0xFD,0x0F,0xDB,0xFF,0xD3,0xFF, -0xEB,0xFA,0xFF,0xFF,0xBF,0xFF,0xFA,0xFF, -0xFF,0xCB,0xFB,0xFE,0xFF,0xFF,0xEB,0xFA, -0xFE,0xFF,0xFF,0xB7,0xFF,0xFF,0xFF,0xFF, -0xBF,0xFF,0xDF,0xF5,0xFF,0xFF,0xD7,0xFF, -0xFF,0xFF,0xDF,0xD7,0xF5,0xFF,0x7F,0xFE, -0x4F,0xFF,0xFD,0xFF,0x7F,0x7F,0xFF,0xAD, -0xEB,0xFB,0xFF,0xAD,0xFF,0xFF,0xFF,0xFF, -0xAF,0xEB,0xFB,0xFF,0xFC,0x0D,0xFF,0xFF, -0xDF,0xD2,0xFD,0xFF,0xFF,0xFD,0xF6,0xFF, -0xFF,0x7F,0xFF,0xFF,0x1F,0xFF,0xFF,0xFF, -0xFF,0xFB,0x3F,0x7D,0xEB,0x32,0xFE,0xBF, -0x2F,0xEB,0xFA,0xAE,0xBD,0xE0,0xFA,0x7E, -0xBF,0xAD,0xEB,0xFA,0xFE,0xBF,0xF5,0x7F, -0xFF,0xDE,0xFE,0xE3,0xFB,0xFF,0xFF,0xFF, -0xDF,0xEF,0x4F,0xDF,0xFF,0x7F,0xDF,0xFF, -0xF7,0xFF,0xFF,0xF8,0x7F,0xFF,0xFF,0xEF, -0xFB,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xDF, -0xED,0xFB,0xDF,0xFF,0xBF,0xFF,0xFF,0xFF, -0x81,0xFF,0xFF,0xFF,0xFF,0x3F,0xFF,0xFF, -0xFF,0xFF,0xFE,0xDD,0xFE,0xEF,0xFD,0xFF, -0xFF,0xFB,0xFE,0xF7,0xFF,0x93,0xFD,0xFB, -0x7E,0xFF,0xFE,0x87,0xE9,0xFF,0x7F,0xB3, -0x9F,0xFE,0xFE,0xFF,0xAF,0xFD,0xFE,0x7E, -0x3F,0xFE,0x67,0xFF,0xFF,0xF7,0xFF,0xFF, -0xFC,0xF7,0xDF,0xFD,0xFF,0x7F,0xFF,0xFF, -0x7F,0x6D,0xFF,0xFF,0xFE,0xFF,0xFF,0x2F, -0xFF,0xBF,0xFF,0xFF,0xEE,0xFF,0xBE,0xFF, -0xFF,0xFE,0xFF,0xEF,0xFF,0xFF,0xFE,0xFF, -0xEF,0xFF,0xFF,0xFA,0x5F,0xFF,0xFF,0xFB, -0xFF,0xFF,0xEF,0xFF,0xFB,0xFE,0xFD,0xFF, -0xFE,0xFF,0xFB,0xFF,0xFF,0xFF,0x7F,0xFF, -0xFE,0xBF,0xDF,0xFF,0xFB,0xFF,0xFF,0xF7, -0xFC,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F, -0xFF,0xFF,0xFF,0xFF,0xFF,0xF2,0x7F,0xFF, -0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF, -0xF3,0xFF,0xFF,0xFF,0xEF,0xFB,0xFF,0xFF, -0xFF,0xDF,0xE2,0xFF,0xFF,0xFB,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFB,0xE7,0xFF,0xFD, -0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xED, -0xEF,0xFD,0xFF,0xFF,0xDF,0xD7,0xF5,0xFD, -0x7F,0x5D,0xFD,0xFF,0x7F,0xDF,0x97,0xF4, -0xFD,0x7B,0x5F,0xFF,0xC9,0xFF,0xFB,0xFE, -0xFF,0xBF,0xFF,0x5F,0xFF,0xFF,0xF7,0xFF, -0xEF,0xFD,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xF7,0xFF,0xD7,0xFD,0x7D,0x7F,0xFF, -0xFF,0xFF,0xFF,0xEF,0xDF,0xF7,0xFD,0xFF, -0xBB,0xFF,0xFF,0x7F,0xFF,0xFE,0xE3,0xFF, -0xF9,0xFE,0x7F,0xBF,0xEF,0xFB,0xFE,0xFF, -0xBF,0xF9,0xFE,0xFF,0x9F,0xEF,0xF9,0xFE, -0xFF,0xBF,0xF3,0xDA,0xFF,0x37,0xCD,0xF3, -0x7C,0xDF,0x37,0xCD,0xF3,0x7F,0x37,0xCD, -0xF3,0x7C,0xDF,0x37,0xCC,0xF3,0x7F,0x5A, -0xBD,0xF6,0xFD,0xBF,0x6F,0xDB,0xF6,0xFD, -0xBF,0x6F,0xDE,0xFD,0xBF,0x6F,0xDB,0xF6, -0xFD,0xBF,0x6F,0xFE,0xF1,0x6F,0xEB,0x7A, -0xDE,0xB7,0xAD,0xEB,0x7A,0xDE,0xB7,0xAF, -0x7A,0xDE,0xB7,0xAD,0xEB,0x7A,0xDE,0xB7, -0xFF,0x7E,0xFF,0xFE,0xCD,0xB3,0x6C,0xDB, -0x36,0xCD,0xB3,0x6C,0xDE,0xCD,0xB3,0x6C, -0xDB,0x36,0xCD,0xB3,0x6C,0xDF,0xC9,0xBF, -0xF7,0xBD,0xEF,0x7A,0x9E,0xA7,0xA9,0xEA, -0x7A,0xB7,0xBD,0xEA,0x7B,0xDE,0xA7,0xBD, -0xCA,0x72,0x8D,0x91,0xFF,0xEF,0xFB,0xFE, -0xFF,0xBF,0xEF,0xFB,0xFE,0xF7,0xEF,0xFB, -0xFE,0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xFE, -0x87,0xFF,0xF6,0xFD,0xBF,0x6F,0xDB,0xF6, -0xFD,0xBF,0x6F,0xF6,0xFD,0xBF,0x6F,0xDB, -0xF6,0xFD,0xBF,0x6F,0xFE,0x4F,0xFF,0xBF, -0xEF,0xBB,0xEE,0xFB,0xBE,0xEF,0xBB,0xEF, -0xBE,0xEF,0xBB,0xEE,0xFB,0xBE,0xEF,0xBB, -0xEF,0xFC,0x5F,0xFF,0xFF,0xFF,0x3F,0xCF, -0xF3,0xFC,0xFF,0x3F,0xCF,0xFC,0xFF,0x3F, -0xCF,0xF3,0xFC,0xFF,0x3F,0xCF,0xFD,0x9F, -0xFE,0xBF,0xAF,0xEB,0xFA,0xFE,0xBF,0xAF, -0xEB,0xFE,0xBF,0xAF,0xEB,0xFA,0xFE,0xBF, -0xAF,0xEB,0xFF,0xE1,0x6F,0xFD,0xFF,0x7F, -0xDF,0xF7,0xFD,0xFF,0x7F,0xDF,0xFD,0xFF, -0x7F,0xDF,0xF7,0xFD,0xFF,0x7F,0xDF,0xFF, -0x7A,0xBF,0xFB,0xFE,0xDF,0xB7,0xED,0xFB, -0x7E,0xDF,0xB7,0xFB,0x7E,0xDF,0xB7,0xED, -0xFB,0x7E,0xDF,0xB7,0xFF,0xC9,0xFF,0xFF, -0xBF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB, -0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEE, -0xFB,0xFE,0xBB,0xFF,0xFE,0xFF,0xBF,0xEF, -0xFB,0xFE,0xFF,0xBF,0xEF,0xFE,0xFF,0xBF, -0xEF,0xFB,0xFE,0xFF,0x3F,0xCF,0xFF,0xE7, -0xFE,0xFF,0xF5,0xFD,0x77,0x5D,0xD7,0x35, -0xDD,0x77,0xD7,0xF5,0xCD,0x7B,0x5D,0xD7, -0xF5,0xDD,0x77,0xFE,0x27,0xFF,0xFF,0x8B, -0xE2,0xF8,0xBE,0x2F,0x8B,0xE2,0xF9,0xAF, -0x8B,0xE2,0xF8,0xBE,0x2F,0x8B,0xE2,0xF9, -0xFE,0x1F,0xFF,0x5F,0xD7,0xF5,0xFD,0x7F, -0x5F,0xD7,0xF5,0xFF,0x5F,0xD7,0xF5,0xFD, -0x7F,0x5F,0xD7,0xF5,0xFF,0xFA,0x3F,0xFE, -0xBF,0xAF,0xEB,0xFA,0xFE,0xBF,0xAF,0xEB, -0xEC,0xBF,0xAF,0xEB,0xFA,0xFE,0xBF,0xAF, -0xEB,0xFF,0xFE,0x7F,0xFD,0x7F,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6, -0xFF,0xFA,0xDF,0xF7,0xFD,0xFF,0x7F,0xDF, -0xF7,0xFC,0xFF,0xDF,0xF7,0xFD,0xFF,0x7F, -0xDF,0xF7,0xFD,0xFF,0xF5,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0x02,0xFF,0xFE,0xBF,0xAB,0xEB,0xFA, -0xBE,0xBF,0x23,0xEB,0xDE,0x1F,0xAF,0xEA, -0xFA,0xFE,0xAF,0xAF,0xEB,0xFD,0x97,0xFF, -0xF3,0xFC,0x7B,0x1F,0xCF,0xF1,0xFC,0x7F, -0x1F,0xF1,0xFC,0x77,0x1F,0xCD,0xF1,0xFC, -0xFF,0x1F,0xFE,0x87,0xFF,0xAF,0xEF,0xFA, -0xFE,0xFF,0xAF,0xEF,0xFA,0xFD,0xBF,0x2B, -0xFB,0x7E,0xBF,0xBF,0xEB,0xFB,0xFB,0xFB, -0xDF,0xFF,0xFB,0xF7,0xFF,0xFF,0x7F,0xF7, -0xF7,0xFF,0xFD,0xDF,0xFE,0xFC,0xDF,0xFF, -0xDF,0xFF,0xFD,0xFF,0xDA,0xBF,0xFF,0xBB, -0xEF,0xFB,0xF9,0xFF,0xBE,0xEF,0xFB,0xFB, -0xBF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB, -0xFF,0xF7,0x7F,0xFD,0xD7,0xFF,0xFF,0x7F, -0xFF,0xFF,0xFF,0xFE,0xF7,0xFF,0xFE,0xFF, -0xF7,0xFF,0xFF,0x7F,0xFF,0xFF,0xEC,0xFF, -0xFF,0xFE,0xDF,0xBF,0xFF,0xFB,0xFE,0xFF, -0xBB,0x68,0xAE,0x1F,0xAE,0xFB,0xFB,0xFF, -0xFF,0xBF,0xFF,0xD5,0xFF,0x7F,0xFF,0xFF, -0xF7,0xFE,0xFE,0xFF,0xBF,0xEF,0x9F,0xFD, -0x7F,0xFF,0xCB,0xFF,0xFF,0xDF,0xFF,0xFF, -0xBB,0xF7,0xBF,0xFF,0xFF,0xFF,0xFF,0xDF, -0xFF,0xBF,0xFB,0xFF,0xFF,0xFF,0xDE,0x3F, -0xFF,0xFF,0xFF,0xFF,0xFF,0xA7,0xFF,0xFF, -0xFF,0xFF,0xEF,0xFF,0x7F,0xFB,0xFD,0xFB, -0x7F,0xFF,0xFF,0xFF,0xFF,0xCF,0xF3,0x7C, -0xFF,0x7F,0x8D,0x7F,0xFF,0xFF,0xFF,0xFF, -0xFB,0xFF,0xF7,0xFB,0xFE,0xFD,0xFF,0xFF, -0xFF,0xFF,0xF7,0xFD,0xFF,0x7F,0xFD,0x1F, -0xFD,0xFF,0xFF,0xFF,0xFF,0xBF,0xDF,0xFF, -0xFF,0xFE,0x5C,0xFF,0x6D,0xFF,0x7F,0xAB, -0xE7,0xF1,0xFF,0xFD,0x9F,0xFF,0xFF,0xAD, -0xEB,0x7A,0x3F,0x1F,0xFF,0xFF,0xFE,0xBF, -0xAF,0xF3,0xDE,0xF5,0xFF,0x8F,0xFB,0xDF, -0xE6,0x7F,0xFF,0xDF,0xF3,0xFD,0xFF,0x7E, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xF7,0xF3, -0x7F,0xDF,0xF7,0xEF,0xFF,0xF6,0x3F,0x9F, -0xDF,0xFF,0xFF,0xEE,0xFF,0xFF,0xEF,0xFB, -0xFF,0xFF,0xF9,0xFB,0xFE,0x4F,0xBF,0xEF, -0xBB,0xFF,0x69,0xAF,0xAF,0xFC,0xFF,0x3F, -0xDD,0xFF,0xFC,0xBF,0x8F,0xFF,0xFD,0xF3, -0xBF,0xED,0x9E,0xFC,0xBF,0x6F,0xF5,0xD3, -0xDF,0xFF,0xDB,0xD6,0xF5,0xEF,0xFD,0xFE, -0xFF,0xB9,0xFF,0x1F,0xD2,0xA9,0xAF,0xFF, -0xDB,0xF7,0xBF,0xEF,0x46,0xFF,0xFF,0xAD, -0xEB,0x7A,0xDF,0xEF,0xF7,0xFF,0x7F,0xF7, -0x9F,0xED,0xFF,0x7F,0xFF,0xAD,0xEB,0x7F, -0xF5,0x6F,0xFF,0xFD,0xFB,0xD6,0xF4,0xF7, -0xFB,0xF9,0x7E,0x7F,0xFF,0x5F,0xC2,0xFE, -0xBF,0xFD,0xFB,0x33,0xDF,0xF9,0x5B,0xFF, -0xFF,0xDD,0x67,0x7D,0xCF,0xEF,0xDB,0xEC, -0xFF,0x77,0xDD,0xF7,0xFD,0xFF,0xFF,0xDE, -0xA7,0xBF,0xD4,0x9F,0xFF,0xFF,0xBF,0xEF, -0xFE,0xFF,0xDF,0xEF,0xBB,0xFF,0xFF,0xEF, -0xEB,0xFA,0xFF,0xEF,0xBD,0xFB,0xFF,0xE2, -0x7F,0xFF,0xDF,0xDF,0xF7,0xFD,0xBF,0xBB, -0x73,0xF7,0xFD,0x7F,0xDF,0xDE,0xF7,0xBF, -0xEA,0xDB,0xF6,0xFF,0xD6,0xFF,0xFF,0x66, -0xFF,0xBE,0xFF,0xBF,0x6B,0xD9,0xF6,0xDF, -0xFF,0xFB,0x7E,0x7F,0xB7,0x7E,0xFF,0xFE, -0xFF,0xCD,0xFF,0xFE,0x7F,0xFF,0xFC,0xFD, -0x3F,0xFB,0xFB,0xF7,0xFF,0xFF,0xFB,0xF6, -0x7D,0xFE,0x7F,0xFF,0xFC,0xFF,0xB9,0xFF, -0xF9,0xFA,0xFE,0xBF,0xAF,0x5B,0xD6,0xED, -0xAD,0x7B,0xF6,0xF9,0xBF,0xEF,0xF8,0xFA, -0xFE,0xBF,0xFE,0xE6,0xFF,0xFF,0xF7,0xFD, -0xFF,0x7F,0xBF,0xEF,0xF3,0xFF,0xFF,0x6F, -0xF7,0xFE,0xFF,0xFF,0xF7,0xFD,0xFE,0xF7, -0xEF,0xFF,0xFB,0xEF,0xFB,0x7E,0xDE,0xFE, -0xFF,0xBF,0xFF,0xFE,0xFF,0xFF,0xFB,0xFF, -0xFF,0xEF,0xFB,0x6F,0xFC,0x1F,0xFE,0xE7, -0xFF,0xFF,0xFF,0xEF,0xFF,0xD3,0xB4,0xBB, -0xFF,0xFF,0xFD,0xBF,0x6F,0xE3,0xFE,0xFF, -0xBF,0xFC,0xBF,0xF7,0xCF,0xF7,0xFD,0xFF, -0x2F,0xDF,0xAB,0xEA,0xFF,0xDF,0xE7,0xEA, -0x9A,0xAF,0xEF,0xFB,0xFE,0xFF,0xF5,0x3F, -0xFD,0x7E,0xFF,0xD7,0xF5,0xFB,0xFF,0xFD, -0xF7,0xFF,0x7F,0xFE,0xF7,0xFD,0xFF,0xD7, -0xFF,0xD7,0x7F,0xEE,0x7F,0xFA,0x79,0xFE, -0x2F,0x8B,0xE6,0xF9,0xFE,0x3F,0x9E,0xF9, -0xBE,0x2F,0x0B,0xE7,0xF9,0xFE,0x2F,0x9F, -0xFD,0xFF,0xFE,0x7D,0x7F,0x5F,0xD7,0xFF, -0xFF,0x7F,0xFF,0xFD,0xFF,0x7F,0x5F,0x97, -0xFF,0xFD,0x7F,0x5F,0xFF,0xE3,0xFF,0xFF, -0xFA,0xFE,0xBF,0xAF,0xFB,0xFB,0xFF,0xFF, -0xCF,0xEB,0xFE,0xBF,0xAF,0xFF,0xFA,0xFE, -0xBF,0xFF,0x87,0xFF,0xFF,0xF5,0xFF,0xFF, -0xFF,0xFF,0xFD,0xFF,0x7F,0xFF,0xFF,0xFF, -0xFB,0xFF,0xFF,0xF5,0xFF,0xFF,0xFE,0x0F, -0xFF,0xFD,0xEB,0xFF,0xFF,0xF7,0xFF,0xEF, -0x7B,0xDF,0xFE,0xFF,0xFF,0xDF,0xF7,0xFD, -0xEB,0x7F,0xDF,0xFF,0x5F,0xFF,0xFF,0xFF, -0xFF,0xFD,0xBF,0xFF,0x7E,0xFA,0xBF,0xC7, -0xDB,0xF7,0xBD,0x3F,0xFB,0xFF,0xF6,0xFF, -0xFA,0xAF,0xFF,0xEB,0xFA,0xFE,0x3F,0x2F, -0xEA,0xFA,0x3E,0xAD,0xC9,0xBA,0xF6,0xAD, -0xAF,0xEB,0xFA,0xF6,0xBF,0xFE,0x7F,0xFF, -0xFF,0xFD,0xFF,0xF1,0x7F,0x3F,0xCF,0xF1, -0xEF,0xFF,0x7F,0xFF,0xBC,0xDF,0xDF,0xF7, -0xDD,0xFF,0xE0,0x7F,0xFF,0xFF,0xFE,0xFF, -0xFA,0xEC,0xBB,0x7F,0x5F,0xFF,0xFB,0xEC, -0xFF,0xEF,0xB7,0xFF,0xF7,0xFF,0xFF,0xB5, -0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xEE,0xDF, -0x5F,0xDF,0xDE,0xFF,0xAE,0xE7,0x77,0xFF, -0xFF,0xDF,0xF7,0xFF,0xE3,0xFF,0xFA,0xBB, -0xFE,0xFF,0xAF,0xFD,0xFB,0xFE,0xBF,0xAB, -0xF9,0xFE,0xFF,0xBF,0x7F,0xBF,0xFE,0xBD, -0xFE,0xD7,0xFF,0x9F,0xFD,0xFF,0xBE,0xEF, -0xFF,0xEE,0xFD,0xBB,0x5B,0xEF,0xFF,0x7F, -0xEF,0xFF,0xEF,0xFF,0x7F,0xFF,0x4F,0xFF, -0xEF,0xFB,0xBC,0xFC,0xFF,0xFF,0xFF,0xFE, -0xFE,0xFD,0xFA,0xFE,0xFB,0xFF,0xFD,0xF3, -0xFB,0xFF,0xF8,0x5F,0xFF,0xFF,0xD7,0xF5, -0xFD,0xDF,0xEF,0xFF,0xF3,0xDC,0x5F,0xCE, -0xF5,0xBD,0xFF,0xFF,0xD7,0xFF,0xFF,0xF9, -0x3F,0xFF,0xDF,0xF7,0xFF,0xFE,0xFF,0xFD, -0xFF,0xFB,0xFF,0xF7,0xB9,0x7D,0xFE,0xDF, -0xFF,0xFF,0xFF,0xFF,0xF9,0x7F,0xFF,0xFE, -0xFF,0xFF,0x7F,0xFF,0xFE,0xFF,0xFF,0xF7, -0xF6,0xFF,0xBF,0xF1,0xF8,0xFF,0xFF,0xFF, -0xFF,0xE0,0xFF,0xFF,0xFF,0xFF,0xF9,0xFF, -0xFF,0xFF,0xFF,0xFF,0xEF,0xEF,0xFF,0xFF, -0x9B,0xFB,0x7F,0xFF,0xFF,0xFF,0xC1,0xFF, -0xDF,0xFF,0x3F,0x5F,0xD7,0xBF,0xEF,0xBB, -0xDE,0xEE,0xFF,0x7F,0xDF,0xFF,0xFE,0xF5, -0x7F,0xDF,0xFF,0x99,0xFF,0xFF,0xFA,0xFF, -0xBF,0xFD,0xEB,0x7A,0xFF,0xB7,0xFE,0xFE, -0xFF,0xFF,0xEF,0xFF,0xFF,0xFD,0xBF,0xFF, -0x97,0xFF,0xFD,0xF7,0xFF,0x7F,0xF7,0xFF, -0xFF,0xFD,0x5F,0xFE,0xF3,0xF9,0xDF,0xDF, -0xFF,0xFF,0xFC,0xFF,0xFF,0x83,0xFF,0xFF, -0xFE,0xFF,0x9E,0xEC,0xFB,0xEE,0xFF,0x9F, -0xBF,0xEF,0xFF,0xFE,0xED,0x7B,0xFF,0xFF, -0xFF,0xF1,0x5A,0xFF,0xFF,0xFD,0xFF,0x7C, -0x69,0x3B,0xDF,0xFF,0x7F,0x1F,0xDF,0xFF, -0xFD,0xBA,0xFF,0xFF,0xFB,0xFF,0x5B,0xBD, -0xFF,0xFF,0xFF,0xFF,0xD7,0xB6,0xED,0xE9, -0xFF,0xD6,0xBD,0x6F,0x5F,0xFB,0xFF,0xEF, -0xFF,0x5F,0xFE,0xF6,0x6F,0xFF,0xFF,0xFF, -0xFF,0xF7,0xEB,0x7A,0xDF,0xFF,0x9F,0x7F, -0x7F,0xFF,0xB7,0xFF,0xFF,0xFE,0xDF,0xFF, -0x6C,0xFF,0xFB,0xFF,0xBB,0x6F,0xEB,0xFE, -0xCC,0xF7,0xA5,0xFA,0x5C,0xF5,0x75,0xBB, -0xB7,0xDF,0xFE,0x6F,0x5F,0xC5,0xBF,0xFD, -0x7B,0xFE,0xFF,0x95,0xE7,0x29,0xCF,0x4F, -0xF5,0x91,0xEE,0x6B,0xDF,0xEF,0xFD,0x54, -0xF5,0xBD,0xB1,0xFF,0xEF,0xEE,0xFB,0xBE, -0xBF,0xAF,0xFE,0xDE,0xBD,0x6F,0xDA,0xF2, -0xFF,0xAF,0xBE,0xFF,0xFF,0xFD,0x7E,0xA7, -0xFF,0xF7,0xFF,0xBF,0xEF,0x7B,0xF6,0xFD, -0xBD,0x4A,0xF2,0x85,0x85,0xBF,0x5B,0xFE, -0xB5,0xFD,0xFA,0xFF,0x4F,0xFF,0xFE,0xDF, -0xFF,0xED,0xFF,0xBF,0xFF,0xBF,0x7F,0xFE, -0xFF,0xB7,0x6D,0xFF,0xF7,0xBF,0xBF,0xEF, -0xFD,0x1F,0xFF,0xFE,0x7D,0xFF,0x67,0xFF, -0xFF,0xFF,0x3F,0x7F,0xFE,0xBF,0xFF,0xE7, -0xDF,0xE7,0xFF,0xEF,0x6B,0xFC,0x1F,0xFF, -0xBF,0xEF,0xFB,0xFE,0xDE,0xBF,0xAF,0xFA, -0xFF,0xB6,0xEF,0xF9,0xFE,0xFF,0x8F,0xEF, -0xDB,0xEF,0xAB,0x6F,0xFB,0xFE,0xFF,0xFF, -0xEF,0xFD,0xFF,0x7F,0xFF,0xFF,0xDE,0xFF, -0xFF,0xEF,0xFF,0xFF,0xFF,0x3F,0xFF,0x6C, -0xFF,0xBF,0xFB,0xFF,0xFE,0xFF,0xFB,0xFE, -0xDF,0xFF,0xFF,0xEF,0xFF,0xFF,0xBF,0xFF, -0xFF,0xFE,0xFB,0xFF,0xD5,0x7F,0xFF,0xFF, -0xEF,0xFB,0xFF,0xFF,0xBF,0xEF,0x43,0xB5, -0xFD,0x6F,0xCF,0xD6,0xBE,0x3F,0x7F,0xDB, -0xFE,0xC3,0xFF,0xFD,0xFF,0xAF,0xEB,0xFB, -0xFC,0xFF,0x3E,0xEF,0xE8,0xFA,0xBD,0xCD, -0xAA,0xFE,0xFE,0x7D,0xCF,0xFF,0xB7,0xFF, -0xF7,0xFF,0xFF,0xFF,0xFD,0xFF,0x75,0xCD, -0x52,0xD7,0xFD,0xFB,0xF7,0xDD,0xFB,0xEF, -0xEB,0xFF,0xFF,0x4F,0xFF,0xBF,0x9F,0xE7, -0xF9,0xFC,0x7F,0x8B,0xC3,0xF9,0xAF,0x8F, -0xE7,0xE9,0xBE,0x7F,0x9F,0xE6,0xF9,0xFC, -0x5F,0xFF,0xFF,0xF7,0xFD,0xFF,0x7A,0x5F, -0xD7,0xED,0xFF,0xFF,0xD7,0xFF,0xDD,0x7F, -0xE7,0xFF,0xFC,0xFF,0xFC,0x3F,0xFF,0xFF, -0xFF,0xFB,0xFF,0xFE,0xBF,0xAF,0xFF,0xFD, -0xFF,0xEF,0xFF,0xEB,0xFF,0xFF,0xFF,0xFF, -0xFF,0xF7,0x7F,0xFF,0x7F,0xDF,0xFF,0xFD, -0xFD,0x7F,0xFE,0xF7,0xFD,0x7F,0xDF,0xFF, -0xFD,0xFF,0xFF,0xDF,0xFB,0xFF,0xEE,0xFF, -0xFB,0xFF,0xF7,0xFD,0xFF,0x7A,0xDF,0xF5, -0xFD,0xFA,0xDF,0xF7,0xFC,0xFF,0x7F,0xDF, -0xBF,0xED,0xFF,0xC9,0xFF,0xDF,0xFF,0xBF, -0x2F,0xFB,0xFF,0xBC,0xAD,0xFF,0xF7,0xFF, -0xFF,0xEF,0xD3,0xFF,0x7D,0xBF,0x6F,0xFF, -0xFA,0xFF,0xFE,0xBF,0xAE,0xEA,0xFA,0xBE, -0xAD,0xA5,0xEB,0xCE,0xBF,0xA7,0xEB,0x5A, -0xDE,0xBD,0xAF,0x6B,0xFD,0x57,0xFF,0xFF, -0xF4,0x7F,0x1F,0x7F,0xFD,0xFF,0x7F,0x36, -0xF0,0xDF,0x79,0xFF,0xFF,0xFF,0xF7,0xFD, -0xBF,0xFF,0x87,0xFF,0xFB,0xF3,0xFC,0xFF, -0xFF,0xFF,0xFF,0x7E,0xFF,0xBF,0xDF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFD,0xBF,0xF8,0x9F, -0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFD, -0xF7,0xFC,0xBD,0xFF,0xFE,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFB,0xF9,0xBF,0xFF,0xFF,0xEB, -0xE2,0xFE,0xFF,0xBF,0xEF,0xA9,0xBA,0x2F, -0xEB,0xF9,0xFE,0x77,0xDF,0xF7,0xFF,0xFF, -0xF9,0x7F,0xFF,0xFF,0x7F,0xEF,0xD7,0xFF, -0xFD,0xFF,0xFB,0xF5,0xFF,0xBF,0x6F,0xDF, -0xFF,0xFF,0xFD,0xFF,0xFF,0xF0,0xFF,0xFF, -0xFF,0x3F,0xCF,0xFF,0xBA,0xEE,0x9B,0xBF, -0xEE,0xD7,0xFE,0xCD,0xEF,0xFF,0xDF,0xBF, -0xFF,0xFF,0xC5,0xFF,0xFF,0xFD,0x7F,0x4F, -0xFD,0xF6,0xD9,0xFF,0x4F,0xD6,0xFD,0xBF, -0x6E,0xFF,0xFF,0xF4,0x7F,0xFF,0x7F,0x8B, -0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xF9,0xFE, -0x37,0xFF,0xD9,0xFB,0xF5,0xAF,0xFD,0xFF, -0xFF,0xFB,0xFF,0xFF,0x07,0xFF,0xFF,0xFF, -0xFB,0xF7,0xFF,0xFD,0xFF,0x7C,0xFA,0x7E, -0x4F,0xFC,0xDF,0x1D,0xC7,0xFF,0xFF,0xFF, -0xFF,0xAE,0xFF,0xFF,0xFF,0xFF,0xFD,0xFB, -0xFF,0xFF,0xFE,0xFE,0xFC,0xFF,0x7F,0x7F, -0xBF,0xEF,0xFE,0xFF,0xFF,0xFF,0x5F,0xFD, -0xFF,0xFF,0xFF,0xFD,0x6F,0x5A,0xD7,0x7B, -0xBE,0x5F,0xFE,0x39,0xFF,0xF7,0xFF,0xF7, -0xFD,0xFE,0xAA,0x1F,0xFF,0xFF,0xFF,0xFF, -0xFE,0xFE,0xAB,0xAF,0xFD,0xFE,0xBF,0xFF, -0xF7,0xFF,0x7F,0xFE,0x8F,0xE3,0xFB,0xEE, -0x7F,0xFF,0xFF,0xFF,0xFF,0xEB,0xFB,0xFF, -0xFD,0xBF,0xEF,0xDF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFB,0xE4,0x3F,0xFF,0xDF, -0xFF,0xFF,0xFF,0xFF,0xF3,0xEF,0xBB,0xFB, -0xBF,0xEF,0xBB,0xFF,0xD7,0xBF,0xFF,0xFF, -0xFF,0x29,0xAF,0xF7,0xFF,0xFF,0xFB,0xFF, -0xFB,0xE6,0xFF,0x0F,0xFB,0x3F,0xDF,0x0F, -0xFF,0xAF,0xFF,0xFF,0xFF,0xF5,0xC3,0xDF, -0x5F,0xFF,0xFF,0xFF,0xFE,0x6B,0xCA,0xBE, -0xBC,0xFF,0x9F,0xF2,0xBF,0xFF,0xFE,0xFA, -0xFF,0xFF,0xEF,0x16,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFC,0xDF,0x97,0xFD,0x79,0xFF,0x37, -0xE7,0x7F,0xFF,0xFF,0xB5,0xFF,0xFF,0xF6, -0x2F,0xFF,0xFD,0xFB,0xFE,0xFF,0xFF,0xFD, -0x5F,0x57,0x5F,0xFF,0xDB,0x52,0xDF,0xFF, -0xFD,0xBF,0xFF,0xFF,0xFC,0xDB,0xFF,0x7B, -0xB5,0xFD,0x7F,0xFF,0x71,0x9C,0x6E,0xFF, -0xF6,0x35,0xA5,0x9B,0xFF,0xFF,0xFD,0xFF, -0xFF,0xDB,0x9E,0x7F,0xFE,0xEF,0xFB,0xFF, -0xFF,0xBD,0xEF,0xFF,0xDE,0xB7,0xF9,0x4B, -0xFF,0xF5,0xEF,0xFF,0xFF,0xFF,0xE8,0x7E, -0xFF,0xEA,0xDF,0xF7,0xFF,0xFD,0x69,0x5B, -0xFC,0x9F,0xEF,0x78,0xD6,0xFF,0xEB,0xEF, -0xFF,0xFF,0xFF,0xE8,0xFF,0xFF,0xED,0xFF, -0xFF,0xFF,0xFF,0xE3,0xF9,0xF6,0xBF,0xFF, -0xFF,0xFE,0xDF,0xFF,0x7F,0xFF,0xFF,0xFF, -0xD1,0xFF,0xFF,0xE7,0xFF,0xFF,0xFF,0xFF, -0xE7,0xF9,0xFF,0xBF,0x7F,0xD9,0xFF,0xFD, -0xFE,0x7F,0xFF,0xFE,0xFF,0xF9,0xFF,0xFB, -0xD6,0xDF,0xBF,0xEF,0x5B,0xD6,0xFF,0xBF, -0xFB,0xF6,0xFF,0xBF,0xEF,0xF8,0xF6,0xDD, -0xBE,0xFE,0x16,0xFF,0xBF,0xEF,0xFF,0xFE, -0xFF,0xBF,0xEF,0xFF,0xFF,0xFF,0x6F,0xFB, -0xFF,0xFF,0xFF,0x6F,0xF3,0xFF,0xF7,0xEF, -0xFB,0xFF,0xBF,0xFF,0xEF,0xFE,0xFF,0xBF, -0xFF,0xFF,0xFF,0xBE,0xBF,0xFF,0xEF,0xFF, -0x7F,0xEF,0xFF,0xFD,0x17,0xFB,0x7B,0xFF, -0xFF,0xFD,0x7F,0xDB,0xF6,0xF4,0x7F,0xFA, -0xFE,0xF5,0xBF,0xEB,0xE3,0xF7,0xFF,0xFF, -0xE9,0xBF,0xFF,0xAF,0xF7,0xFD,0xF3,0x7E, -0x8F,0xA3,0xEA,0xFF,0xCB,0xF3,0xEE,0xFF, -0xBF,0xEF,0xF7,0xF9,0xFF,0xFE,0x7F,0xFF, -0xFF,0xFF,0xFF,0xF5,0xFB,0xF6,0xFF,0xF5, -0x2F,0xFE,0xFB,0xD7,0xBF,0xFF,0xBE,0xDF, -0x9F,0xFF,0xF0,0xFF,0xFF,0xF9,0xFE,0x7F, -0x8F,0xA3,0xF8,0xFE,0x6F,0x9F,0xF9,0xF6, -0x2F,0x9F,0xE7,0xF9,0xFE,0x2F,0x9F,0xE1, -0xFF,0xFF,0xFF,0x7F,0xDF,0xF7,0xF5,0xFD, -0x7F,0x7F,0xF5,0xFF,0x9F,0x5F,0xFB,0xFE, -0xFF,0x7F,0xFF,0xFF,0xCB,0xFF,0xFF,0xFB, -0xFE,0xFF,0xBF,0xAF,0xFB,0xFE,0xFF,0xDF, -0xFE,0xFE,0xBF,0xF7,0xFF,0xFF,0xFF,0xFF, -0xFF,0xC7,0xFF,0xFF,0xFD,0xFF,0x7F,0xDD, -0xF7,0xFD,0xFF,0xFF,0xD7,0xFF,0xFD,0x7F, -0xFF,0xFB,0xFD,0xFF,0xFF,0xFE,0xEF,0x7F, -0xFD,0xEF,0xFB,0xFE,0xFB,0xFD,0xFF,0x7F, -0xDF,0xFD,0xFF,0x7A,0xDF,0xF7,0xFD,0xFF, -0xFF,0xFF,0xFF,0x1F,0xFF,0xFF,0xD3,0xF7, -0xFF,0xFF,0x6F,0xDB,0xFF,0xFF,0xEF,0xCB, -0xF4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, -0x29,0xFF,0xE8,0xDA,0x76,0x9F,0xAF,0x6A, -0xDA,0xFE,0x35,0xEB,0xDA,0xD6,0xBF,0xAB, -0xEB,0x7A,0xDE,0xBF,0xD7,0x7F,0xFF,0xFE, -0xFF,0xBF,0xEF,0xFD,0xDF,0x77,0xBF,0xFD, -0x37,0xEF,0xFF,0xEF,0xFF,0x3F,0xFF,0xFF, -0xFF,0xFE,0x7F,0xFF,0xFF,0xFF,0xF7,0x7E, -0xDF,0xFF,0xFF,0xFF,0xFA,0xB7,0x7F,0xFF, -0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0x89,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0x9F,0xFB,0xFF,0xFF,0xFF,0xE7,0xFF, -0xFF,0xFF,0xFF,0xAA,0xFF,0xAB,0xFB,0xFA, -0xEF,0xBF,0xFF,0xDF,0xFA,0x7B,0xB9,0xFE, -0xFE,0xFF,0xFD,0xFF,0xF7,0xFE,0x3F,0xFF, -0xB7,0xFF,0xF7,0xEE,0xFF,0x7F,0xEF,0xFF, -0xFF,0x7F,0xFF,0x1F,0xFB,0xFF,0xBF,0xFB, -0xFE,0xFF,0xBD,0xFF,0xFF,0x2F,0xFF,0xBF, -0xFF,0x7F,0xDF,0xFA,0xFF,0xFF,0xFC,0xEE, -0xF5,0xF3,0xBE,0xFB,0x0F,0xEF,0xF3,0xBE, -0xEF,0xFC,0x5F,0xFF,0x5A,0xFF,0xF7,0xDF, -0xFF,0xFF,0xFE,0xD5,0xFC,0x5F,0xFB,0xF2, -0xFF,0xFF,0x2F,0xBB,0xF3,0xFF,0xFF,0xBF, -0xFF,0xEF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF, -0xBF,0xFF,0xFF,0xFD,0x7B,0xFF,0xDF,0xB9, -0xFF,0xFB,0xFF,0xD8,0x7F,0xFF,0xFF,0xFF, -0xFB,0xFF,0xFC,0x7F,0x1F,0xBF,0xE0,0xDF, -0xF7,0xEF,0xFF,0xFD,0x7F,0xFE,0xDF,0xFF, -0xE0,0xFF,0xFF,0xFD,0xEF,0xFB,0xFF,0xFE, -0xF7,0xDF,0xFF,0xEB,0x5F,0xFF,0xF7,0xFF, -0xFF,0xFF,0xFF,0xBF,0xFF,0xFD,0xFF,0xFD, -0xFF,0xFF,0xFF,0xF7,0xFD,0xFF,0x3B,0xDC, -0xFD,0x6D,0x7B,0x5F,0x57,0xF5,0xFD,0x7F, -0x5F,0xFF,0xB1,0xFF,0xEB,0xFF,0xFF,0xFF, -0xFB,0xFB,0xFE,0xFF,0xBF,0xFB,0xBE,0xFF, -0xBF,0xEF,0xFB,0xFE,0xFF,0xAF,0xFE,0xF7, -0xDF,0xDF,0xFF,0xFF,0xFF,0x7F,0xCF,0xF3, -0xF8,0xFF,0xD7,0xFB,0xFF,0x5F,0xBF,0xF7, -0xFB,0xFF,0x7F,0xFE,0x23,0xFF,0xFF,0xFE, -0x7F,0xF3,0xFF,0xFB,0xFE,0xFF,0xFF,0xF3, -0xFF,0xFF,0xF5,0xF9,0xFF,0x3F,0xFF,0xFF, -0xF0,0x9A,0xFF,0xBE,0x7F,0xFF,0xFC,0xF9, -0xFF,0xFD,0xAF,0xEB,0xFE,0xBF,0xFF,0xCF, -0xF3,0xFE,0x7F,0xFF,0xFF,0x5B,0xBD,0xFF, -0xBC,0xEB,0xFF,0xD7,0xD4,0xAF,0xAF,0xFD, -0xFF,0xCF,0xF7,0xFD,0xFF,0x7F,0xDF,0xF7, -0xFD,0xFE,0xFF,0x6F,0xFF,0xFB,0xFF,0xFF, -0xFF,0xFD,0x7F,0x5E,0xFD,0xBF,0xDB,0xF6, -0xFD,0xBF,0x6F,0xFB,0xEE,0xFD,0xFF,0x7A, -0xFF,0xFA,0xFB,0xFF,0x3F,0xFB,0xB7,0x5F, -0xD6,0xF7,0x1F,0x71,0xDC,0x77,0x1D,0xC7, -0x31,0xDC,0x77,0xDF,0xF9,0xBF,0xF5,0x5B, -0xF4,0xD7,0x9D,0xAE,0xFF,0xBF,0xFD,0xBF, -0xDB,0xF6,0xFD,0xBF,0x6F,0xDB,0xF6,0xFE, -0x3D,0x81,0xFF,0xEB,0xFE,0xFE,0xFE,0xFF, -0xEB,0x7A,0xDF,0x7D,0x77,0x7D,0xF5,0x79, -0xDF,0x57,0xDD,0xF5,0x7D,0x7E,0xE6,0xFF, -0xD6,0x3F,0xBF,0x7F,0xFF,0xD4,0xF5,0x3F, -0xBF,0xFB,0xBE,0xEF,0xB3,0xEE,0xFB,0x9E, -0xEF,0xBB,0xFE,0x8B,0xFF,0xFE,0xDF,0xB7, -0xED,0xFF,0xF7,0xFD,0xFE,0xFF,0xEF,0xBB, -0xEE,0xFF,0xBE,0xEF,0xBB,0xEE,0xEB,0xFC, -0x1F,0xFF,0xFF,0xFD,0xFF,0xE7,0xFF,0xF7, -0xFD,0xFF,0xEF,0xFE,0xFF,0xBF,0xEF,0xFB, -0xFE,0xFF,0xBF,0xEB,0xFA,0x1F,0xFF,0xB7, -0xEF,0x5B,0xFE,0xFF,0xAF,0xEB,0xDD,0xE7, -0xDE,0x77,0x9D,0xE7,0x79,0xDE,0x77,0x9D, -0xBF,0xE6,0x6F,0xFF,0xFE,0xFF,0xBF,0xEF, -0xFB,0xFE,0xFD,0xBF,0x6F,0xF6,0xFD,0xBF, -0x6F,0xDB,0xF6,0xFD,0xBF,0xFF,0x7E,0xFF, -0xFF,0xFB,0xFE,0xFE,0xFF,0xEF,0xFB,0xFD, -0xEF,0x7E,0xF7,0xBD,0xEF,0x7B,0xDE,0xF7, -0xBD,0xEF,0xFF,0xD5,0xFF,0xBF,0xFF,0xEF, -0xFE,0xFF,0xFC,0x3F,0x0F,0xE7,0xFE,0x7F, -0x9F,0xE7,0xF9,0xFE,0x7F,0x9F,0xE7,0xFE, -0xF3,0xFF,0xFE,0xDF,0xAD,0xDF,0x67,0xEE, -0xFB,0xBF,0xEF,0xFE,0xFF,0xBF,0xEF,0xFB, -0xFE,0xFF,0xBF,0xEF,0xFF,0x23,0xFF,0xFF, -0xFF,0xFF,0x7F,0xFF,0xF3,0xBC,0xDB,0xFE, -0xFB,0xFF,0xFB,0xBE,0xF7,0xFB,0xFF,0x7F, -0xDF,0xFF,0xCF,0xFB,0xFF,0x9F,0xE3,0xF9, -0xBE,0x3F,0x8F,0xE7,0x79,0xFF,0x9D,0xE7, -0xF9,0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x5F, -0xFF,0xCF,0xF7,0xFF,0xFF,0xFF,0xDF,0xF7, -0xFE,0x7F,0xE7,0xF9,0xFE,0x7F,0xFF,0xFF, -0xFB,0xFE,0xFF,0xFF,0xBF,0xFF,0xBF,0xBF, -0xFF,0xFE,0xFF,0xBF,0xEF,0xFF,0xFD,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFD,0xFF, -0xFF,0x3F,0xFF,0xBF,0xFF,0xF7,0xFF,0xFF, -0x7F,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xE8,0xEF,0xFF, -0x5F,0xF7,0xBF,0xF9,0xFE,0xDF,0xB7,0xFD, -0xFF,0xDF,0xF7,0xFD,0xFF,0x7F,0xDF,0xF7, -0xFD,0xFF,0xDD,0xFF,0xF2,0xFF,0xBF,0xFF, -0xFF,0xBF,0xFF,0xFF,0x2F,0xF2,0xFF,0xBF, -0x2F,0x7B,0xD2,0xF7,0xBF,0x2F,0xFF,0xBB, -0xFF,0xEE,0x8F,0xAF,0xEB,0xFA,0xFE,0x3F, -0xA7,0x69,0xCE,0x8F,0xA4,0xEA,0xFA,0xEE, -0xB7,0xAE,0xEB,0xFD,0xC7,0xFF,0xF7,0xF7, -0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x3E,0xF3, -0x74,0xFF,0x3F,0x4F,0xFF,0xE7,0xFF,0x3F, -0xFE,0xA7,0xFF,0xFF,0xDF,0xF7,0xB7,0xFF, -0xF7,0xFF,0xBA,0xEF,0x37,0xEB,0xFB,0xFE, -0xBF,0xFB,0xFE,0xF3,0xFF,0xF9,0xDF,0xFF, -0xBF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF, -0xFD,0xDF,0xFF,0xFD,0xFF,0xFF,0xFB,0xFE, -0xFD,0xFF,0xFB,0xBF,0xFE,0x3F,0xED,0xFF, -0xDF,0xBE,0x3D,0xA7,0xFB,0xFA,0x3F,0xE6, -0xE1,0xFE,0xFE,0x3F,0xEF,0xE3,0xDF,0xF5, -0x7F,0xFE,0xFF,0x7E,0xFF,0xFF,0xFF,0xFF, -0xEF,0x6F,0xF6,0xFF,0x7D,0xEF,0xD7,0xDE, -0xFF,0x7D,0xEF,0xFF,0xF2,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0x7B,0xDE,0xFB,0xE6,0xEE, -0xEF,0x37,0x6E,0xF3,0x7E,0xEB,0x37,0xEF, -0xFF,0xC1,0xFF,0xFE,0xFF,0xF7,0xEF,0xFF, -0xFF,0xFF,0xBF,0x3F,0xD2,0xDF,0xBF,0x2F, -0x7B,0xE2,0xFF,0xFE,0x3B,0xBD,0xDB,0xFF, -0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFE, -0xFF,0xFB,0xFF,0xFF,0xBF,0xFF,0xFB,0xDF, -0xFF,0xBF,0xFF,0xB7,0xFF,0xFF,0xBF,0xEF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0xFF, -0x7F,0xFF,0x1F,0xEF,0xF1,0xFD,0xFF,0xF6, -0xAF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF, -0xFF,0xFF,0xFE,0x9F,0xFF,0xFF,0xFF,0x77, -0xEF,0xF7,0xFB,0xFF,0xFE,0x5F,0xFF,0xFF, -0xBF,0xCF,0xFB,0xF7,0xDD,0xF7,0xF5,0xFF, -0x5F,0xD5,0xF5,0xFD,0x7F,0x5F,0xD7,0xF5, -0xFF,0xFB,0x0F,0xFF,0xFF,0xA9,0xEA,0x7A, -0xFF,0xAF,0x8F,0xFE,0xDF,0xAF,0xEF,0xFB, -0xFE,0xFF,0xBF,0xEF,0xFB,0xDF,0xE5,0x5F, -0xFF,0xFF,0xFF,0xFF,0xFF,0xBD,0x57,0xFF, -0xFF,0x6F,0x77,0xBF,0xF7,0xFB,0xFF,0x7F, -0xBF,0xF7,0xFF,0xFC,0xBF,0xFF,0x9F,0xFF, -0xFF,0xEF,0xFF,0xFE,0xFF,0xFF,0xFF,0x1F, -0xCF,0xFF,0xFC,0xFF,0xFF,0xFF,0xFF,0xFB, -0x65,0xAF,0xF3,0x7C,0xFF,0x3F,0xDF,0xFF, -0xFD,0xE9,0xFE,0x7F,0xE7,0xFF,0xFE,0x7F, -0xFF,0xFF,0xFF,0xFF,0xFD,0xE3,0xDF,0xFB, -0xDB,0xF6,0xFD,0xEF,0x5B,0xFB,0xFF,0xDF, -0xFC,0xFF,0x3F,0xDF,0xF3,0xFD,0xFF,0x7F, -0xDF,0xEF,0x66,0xFF,0xDF,0xAD,0xEB,0x7A, -0xDE,0xF7,0xF7,0xE7,0xD9,0xFD,0x9F,0x67, -0xD9,0xF6,0x7D,0x9F,0xE7,0xDF,0xF5,0x47, -0xFD,0x65,0x5B,0xD6,0xF4,0xFE,0xFF,0xEF, -0xFF,0x6D,0xF6,0xDD,0xB7,0x6D,0xDB,0x76, -0xDC,0xB7,0x7D,0xFA,0x9B,0xF6,0x6D,0x9D, -0x67,0x59,0xDF,0xF7,0xDD,0xFF,0xEB,0xFE, -0xBF,0xAF,0xEB,0xFA,0xFE,0xBF,0xAF,0xE3, -0xD1,0x9F,0xFF,0xBD,0xBF,0xEF,0xFE,0xF7, -0xBF,0xBF,0xF7,0xD7,0x7F,0xDD,0xF7,0x9D, -0xDF,0x7F,0xDF,0xF7,0xFF,0xE0,0x7F,0xFD, -0xC1,0xDF,0xF7,0xFD,0xC7,0x7F,0x7F,0xFB, -0xFF,0xBB,0xEC,0xFB,0x3E,0xFF,0xBF,0xEC, -0xFB,0xFF,0xD8,0x7F,0xBF,0x6C,0xFF,0xBE, -0xFF,0xBF,0xED,0xFF,0xEF,0xFE,0xFB,0xBF, -0xEF,0xFB,0xFE,0xFF,0xBF,0xEE,0xFF,0xC5, -0xFF,0xAF,0x6F,0xFF,0xFC,0xFD,0x3F,0xE7, -0xFF,0xFE,0xFF,0xEF,0xFB,0xFE,0xFF,0xBF, -0xEF,0xFB,0xFE,0xBF,0x89,0xFE,0xFA,0xBA, -0xFE,0xBF,0xAF,0xFB,0xF6,0xF5,0xD9,0x7D, -0x97,0x65,0xD9,0x74,0x5D,0x97,0x65,0xD3, -0xFE,0xD6,0xFF,0xBF,0xF7,0xFD,0xFF,0x7F, -0xBF,0xCF,0xFB,0xFE,0xFF,0xEF,0xFB,0xFE, -0xFF,0xBF,0xEF,0xFB,0xFF,0xF6,0x8F,0xFB, -0xFF,0xEF,0xFB,0x7E,0xDB,0xFE,0xFF,0xBE, -0xEF,0xEE,0xFB,0xBE,0xEF,0xBB,0xEE,0xFB, -0xBE,0xFF,0xFF,0xDF,0xFF,0x43,0xFF,0xFF, -0xFB,0xEF,0x5F,0xB7,0xFE,0x7F,0xE7,0xF9, -0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x7F,0xF9, -0xBF,0xFE,0xAF,0x77,0xFD,0xFF,0x2F,0xAF, -0xA7,0xFE,0xFF,0xEF,0xFB,0xFE,0xFF,0xBF, -0xEF,0xFB,0xFE,0xFF,0xF1,0x7F,0xEF,0xDF, -0xFF,0x97,0xF5,0xEF,0xFF,0xDF,0xFF,0xFF, -0xBF,0xFF,0xBF,0xFF,0xFF,0xFE,0xFF,0xFF, -0xFF,0xE0,0xFF,0xFF,0xF9,0xFE,0x2F,0x8B, -0xE3,0xF8,0xBE,0x77,0x9F,0xF9,0xDA,0x77, -0x9D,0xE7,0x79,0xDE,0x77,0x9F,0xDD,0xFF, -0xFD,0xFD,0x7F,0x5F,0xD7,0xFD,0xFF,0x7F, -0xE7,0xFE,0x7F,0x97,0xE7,0xFB,0xFE,0xFF, -0xBF,0xEF,0xFF,0xAB,0xFF,0xEF,0xFA,0xFE, -0xBF,0xAF,0xFF,0xFA,0xFF,0xFF,0xDF,0xFF, -0xFB,0xFF,0xF7,0xFD,0xFF,0x7F,0xDF,0xFF, -0x67,0xFF,0xF7,0xF5,0xFF,0xFF,0xFF,0xDF, -0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xBD, -0xEB,0xFF,0xFF,0xF7,0xAD,0xEB,0xFF,0xDF, -0xFD,0xFF,0x3F,0xDF,0xF7,0xFD,0xFF,0x7F, -0xDF,0xFF,0x5F,0xFF,0xF7,0xFF,0xFF,0xFD, -0xBF,0xFF,0xCB,0xF4,0xFF,0x7F,0xD3,0xF7, -0xFD,0x3F,0x7F,0xD3,0xF7,0xFF,0xFC,0x3F, -0xFF,0xEA,0xFA,0xBE,0xAF,0xAB,0xEB,0xBA, -0xF4,0x95,0x6B,0x52,0xD4,0xAD,0x2F,0x4A, -0xD2,0xF6,0xBF,0xD2,0x7F,0xF7,0x3F,0xFF, -0xFF,0xF3,0x7F,0xFF,0xFF,0xF7,0xFF,0xBA, -0xDF,0xFB,0xFD,0xFF,0xBF,0xFF,0xFB,0xFF, -0xF8,0x7F,0xEA,0xFF,0xFE,0xFE,0xDF,0xFF, -0xF7,0xFF,0x7F,0xBB,0xFF,0xFF,0xBF,0xDF, -0xFB,0xFF,0xFF,0xBF,0xFF,0xB1,0x7F,0xFF, -0xFB,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF, -0xCF,0xFE,0xFF,0xFF,0xEF,0xFF,0xF7,0xFF, -0xFF,0xFF,0xF1,0xFF,0x69,0xBE,0xFA,0xBF, -0xAF,0xE2,0xFF,0xFE,0xFD,0xAF,0xF3,0xFE, -0xFF,0xBF,0xEF,0xFB,0xFC,0xFF,0xFF,0x07, -0xFD,0x95,0xDB,0xDF,0x7F,0xDF,0xAF,0xFF, -0xF7,0xAF,0x36,0xFE,0xBF,0x65,0xEB,0xF6, -0xFE,0x9F,0x6F,0xFE,0x07,0xFF,0xCF,0xFF, -0xF8,0xFE,0xFF,0xCF,0xFF,0xF6,0xFA,0xE7, -0xFB,0xFE,0xFF,0xBB,0xED,0xF9,0xFF,0xFF, -0xFF,0x5F,0xFF,0xFF,0xFF,0x75,0xFF,0xEF, -0x7E,0xFD,0xE0,0xE8,0x5E,0xD3,0xE5,0xF9, -0x3E,0x5F,0xD7,0xF7,0xFF,0xFA,0x2F,0xFB, -0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0x7F, -0x7F,0xD7,0xF5,0x7D,0x5F,0x57,0xD5,0xF5, -0xEF,0xFF,0xF3,0x7F,0xFC,0x7F,0xFF,0xC7, -0xF1,0xFF,0xFF,0x1F,0xCF,0xB0,0xFF,0x3F, -0xCF,0xF3,0xFC,0xFF,0x3F,0xCE,0xFF,0xE4, -0xFF,0xDF,0x7F,0xFE,0xF7,0xBB,0xFF,0xFF, -0xDF,0xEF,0xEE,0xFF,0xBF,0xEF,0xFB,0xFE, -0xBF,0xBF,0xEF,0xFF,0xD1,0xFF,0xFF,0xFF, -0xFD,0xFB,0xFF,0xFD,0xFF,0xFB,0x9F,0xE9, -0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x7F,0xBF, -0xFF,0xB3,0xFF,0xFF,0xF7,0xFF,0xFF,0xAF, -0xF7,0xFF,0xB6,0x3F,0xEB,0xFA,0xFE,0xBF, -0xAF,0xEB,0xFA,0xFE,0xBF,0xFE,0xA7,0xFF, -0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF, -0xFE,0x9F,0xF7,0xF9,0xFF,0x7F,0x9F,0xE7, -0xFF,0xFF,0xFE,0xAF,0x6F,0xFF,0xFF,0xFF, -0x9F,0xFF,0xDF,0xFF,0x7D,0x5F,0xDD,0xFF, -0xFB,0xBF,0xE7,0xBB,0xFF,0xFB,0xDF,0x6D, -0x5F,0x7E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xEB,0xF7,0xFF,0xE7,0xEF,0xF7,0xFF,0xFF, -0x7F,0xFF,0xF7,0xFF,0xFC,0x8F,0xFF,0xEF, -0xFD,0xFE,0xFF,0xBE,0xF4,0xF2,0x7D,0xD7, -0xCF,0xFF,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xCF,0x6B,0xFF,0xBF,0x3F,0xFB,0xF2, -0xFC,0x7F,0xEB,0xFF,0x9F,0xFA,0xFF,0xFF, -0x3F,0xFF,0xF3,0xFF,0xFF,0xFD,0x70,0xF7, -0xFF,0xFF,0xBF,0xFF,0xFB,0xD7,0xFE,0xF5, -0x77,0xFF,0x15,0xDD,0x77,0xFD,0xFF,0x7F, -0xDF,0xF7,0xFB,0xCD,0xBF,0xFF,0xFD,0xFF, -0xFF,0xDF,0x37,0xCD,0xF9,0xEC,0xFE,0xEF, -0xBB,0xF4,0xFB,0x3F,0x4F,0xB3,0xFF,0xFD, -0xCB,0xFF,0xE9,0x7E,0x54,0x9F,0xE5,0x4B, -0xB7,0xFF,0xDD,0x7D,0xC7,0x71,0xDD,0x77, -0x5D,0xD7,0x75,0xCD,0x7F,0xD6,0xFF,0xD3, -0xF6,0xF9,0x3F,0x6D,0x95,0xAF,0x7F,0xFE, -0xFF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB, -0xFE,0xF6,0xC7,0xFF,0xAD,0x7B,0xCA,0xFF, -0xBF,0xBF,0xEF,0xFD,0xE3,0xDF,0xB7,0xED, -0xFB,0x7E,0xDF,0x37,0xED,0xE3,0xFB,0xDF, -0xFF,0x52,0x5C,0x15,0xFD,0xCF,0x7F,0xDF, -0xFE,0xEF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEC, -0x7B,0xFE,0xFF,0xFE,0x3E,0x7F,0xDA,0xF7, -0xFD,0xFF,0x7F,0xFF,0xFF,0xFB,0xEF,0xBB, -0x6F,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB,0xFF, -0xF7,0x7D,0xFF,0xD8,0xFF,0xFD,0xBF,0x7F, -0xFB,0xFF,0xFF,0x9F,0xFB,0xFE,0x7F,0x9F, -0xE7,0xF9,0xFE,0x7F,0x9F,0xEA,0x7F,0xF6, -0xBF,0xBD,0x6A,0x5A,0xF6,0xE5,0xBF,0x77, -0x5F,0x6D,0xDD,0x77,0x5D,0xD7,0x75,0xDD, -0x77,0xFF,0xA5,0xBF,0xCF,0xFB,0xFF,0xFF, -0xBF,0xCF,0xFB,0xFD,0xFF,0xBF,0xF3,0xFE, -0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xFD,0xAB, -0xFF,0xBF,0xBF,0xFF,0xFB,0xFF,0x7F,0xEF, -0xFF,0xBE,0xFB,0xEE,0xFB,0xBE,0xEF,0xBB, -0xEE,0xFB,0xBF,0xFF,0xB5,0xFF,0xD0,0xBC, -0xFD,0x2F,0x4B,0xF7,0xFF,0xFF,0x9F,0xF9, -0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x7F,0x9F, -0xFA,0x8F,0xFD,0xAB,0xFA,0xDA,0xBF,0xAF, -0xB3,0xFD,0xFF,0xBF,0xFB,0xFE,0xFF,0xBF, -0xEF,0xFB,0xFE,0xF7,0xBF,0xFF,0x9F,0xFF, -0x77,0xF7,0xBD,0xFD,0x77,0xDF,0xFF,0x7E, -0xDF,0xED,0xBB,0xFE,0xFF,0xBE,0xEF,0xFB, -0xFE,0xFF,0xFA,0x3F,0xFF,0xBE,0x6F,0x8F, -0xE6,0xF9,0xFE,0x7F,0x9F,0xC7,0xFE,0x7F, -0x9F,0xE7,0xF9,0xFE,0x7F,0x9F,0xE7,0xFB, -0x7F,0xFF,0x7F,0xCF,0xFF,0xFD,0xFF,0xFF, -0xDF,0xFB,0xAF,0xBF,0xEF,0xFF,0xFE,0xFF, -0x9F,0xEF,0xFB,0xFF,0xFC,0xFF,0xFB,0xFE, -0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xF7, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xF5,0xFF,0xFF,0xFF,0x3F,0xDF,0xF7, -0xFF,0xFF,0x7F,0xEF,0xFE,0xFF,0xBF,0xFF, -0xFB,0xFF,0xFF,0xBF,0xEF,0xFF,0xB3,0x7F, -0xFF,0x7B,0x5E,0xF7,0xFD,0xFF,0x7B,0x7F, -0xF7,0xFF,0x7F,0xDF,0xF7,0xFD,0xFF,0x7F, -0xDF,0xF7,0xFF,0x17,0xFF,0xFF,0xFF,0x7F, -0xFF,0xFF,0xDD,0xF6,0xFC,0xBF,0xCB,0xF2, -0xBC,0xBF,0x2F,0xCB,0xF2,0xFC,0xBF,0xFE, -0x8F,0xFF,0xFA,0x7E,0xBF,0xA7,0xEB,0xDA, -0xFC,0xBF,0xAF,0x7A,0xFE,0xBF,0xAF,0xEA, -0xFA,0xFE,0xBF,0xAF,0xF4,0xDF,0xFE,0xFF, -0xF3,0x3C,0x7F,0x3E,0xFF,0xCF,0xF8,0xBF, -0x8F,0xE3,0xF8,0xFE,0x3F,0x8F,0xE7,0xE8, -0xFF,0xFC,0x9F,0xFF,0xFF,0xCF,0xEB,0xB3, -0xE7,0xFB,0x7B,0xF3,0xFE,0xFF,0xCF,0xDB, -0xFB,0xFB,0xBF,0x6F,0x6F,0xDF,0xEC,0x7F, -0xFF,0xFF,0xF7,0xFD,0xFD,0xFF,0xFF,0xFF, -0xFF,0xB2,0xBF,0xFF,0xDE,0xFD,0xBD,0xEF, -0xFB,0xF6,0xDF,0xEA,0xE7,0xDB,0xFE,0xBB, -0xFF,0xEB,0xFB,0xBF,0x9F,0x8F,0xE8,0xFE, -0x3F,0x8F,0xA3,0xF8,0xFE,0x3F,0x8F,0xFF, -0xF8,0x7E,0xFD,0xFD,0x7F,0xFF,0xFB,0xCD, -0xFF,0xFD,0xFF,0x5F,0xEF,0xFD,0xFF,0xFF, -0xDF,0xF7,0xFD,0xFF,0xBE,0x90,0xFF,0xFF, -0xEE,0xFF,0x3F,0xBF,0xF3,0xBB,0xFE,0xB7, -0xAB,0xFA,0xFE,0xAF,0xAD,0xEA,0xFA,0xDE, -0xAB,0xFF,0x63,0xFF,0xFE,0xF2,0xFF,0xB3, -0xFF,0xDF,0xEE,0x7D,0xFF,0x03,0xF1,0xF4, -0x3F,0x1F,0xC3,0xF1,0xEC,0x7F,0xFE,0x6F, -0xFF,0xFB,0xFB,0xFF,0x9F,0xFF,0xBF,0xFF, -0x7B,0x5F,0xFD,0xFF,0xDF,0xF7,0xFD,0xFD, -0x7F,0x7F,0xDF,0xFE,0xCF,0xFB,0xFF,0xFF, -0xAF,0xFB,0xFF,0x1F,0xEF,0xA5,0xFD,0xBF, -0xDF,0xFB,0x7D,0xFF,0xBF,0xDF,0xFB,0xFF, -0xFD,0x3B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD, -0xAF,0xF3,0xFF,0xFB,0x7F,0xBF,0xD7,0xFB, -0xBF,0x7F,0xBB,0xF7,0xFF,0xF8,0x7F,0xFF, -0xFA,0x5F,0xD7,0xFF,0xDF,0x7F,0xEF,0xFF, -0xFF,0x7F,0xDB,0xF7,0xFD,0xFF,0x7F,0xDF, -0xB7,0xFB,0xEC,0xFF,0xFF,0xF7,0xBF,0xEF, -0xFD,0xFC,0xFB,0xFF,0xEF,0xF0,0xFE,0x3F, -0x8F,0xE3,0xF8,0xFE,0x3F,0x8F,0xEF,0x8D, -0xFF,0xFF,0xEF,0x7F,0xBF,0xFF,0xFB,0xFF, -0xDB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xEF,0xD8,0xFF,0x2E,0x7F, -0xBE,0xEF,0xFE,0x6E,0xFF,0xBF,0xF9,0xFF, -0xFF,0xF3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFC,0x66,0xBE,0x47,0xF3,0x7F,0xDF,0xFE, -0x87,0x9F,0xFF,0xFF,0xFF,0xFF,0xE7,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xD6,0x6F,0x7C, -0xFB,0x4F,0xD2,0xFF,0xFD,0x2B,0xFE,0xFF, -0xFF,0xFD,0x5F,0xD7,0xD5,0xF5,0x7D,0xFF, -0xFF,0xFF,0xBF,0x9B,0xFF,0xFF,0xDF,0xB7, -0xFF,0xFF,0xDF,0xFF,0x3F,0xCF,0xFE,0x7F, -0xBF,0xEF,0xFB,0xFC,0xFF,0x3F,0xFF,0xD9, -0xBF,0xFE,0x97,0xEC,0x8F,0xB7,0xFE,0x9B, -0x7D,0xFD,0xB7,0xDD,0x77,0x1D,0xC7,0x71, -0xDD,0x77,0x5D,0xD7,0xF3,0x6F,0xFD,0x3F, -0x73,0xDD,0xAF,0xFD,0x7A,0xFF,0xFF,0xAF, -0xFE,0xFD,0xBF,0xEF,0xFB,0xFE,0xFF,0xBF, -0xEF,0x66,0x7F,0xFF,0xFF,0xBF,0xBF,0xFF, -0xFB,0xFF,0xF7,0xDF,0xFD,0xFB,0x7D,0xDF, -0xB7,0xCD,0xF3,0x7C,0x5F,0x3F,0x91,0x3F, -0xFF,0x3D,0xEF,0x7B,0xFF,0xFC,0xFF,0xCA, -0xEF,0xFE,0xFF,0xBD,0xEF,0xFB,0x1E,0xE7, -0xBB,0xEC,0x7F,0xB3,0xFF,0xFD,0x9F,0xFF, -0xFF,0xFE,0xFF,0xFF,0x7F,0xBF,0xFB,0xFE, -0xFF,0xBF,0xEF,0xFB,0xEE,0xFB,0xBF,0xDF, -0x67,0xFF,0xFF,0xBF,0xEF,0xDB,0xFF,0xBC, -0xFE,0x7F,0xFB,0xFF,0x9F,0xEF,0xF9,0xFE, -0x7F,0x9F,0xE7,0xF9,0xFE,0x87,0xFF,0xEE, -0xFB,0xBE,0xE5,0xBF,0xEF,0xF9,0xD7,0x65, -0xF7,0xDD,0xE7,0x7D,0xDF,0x77,0x5D,0xD7, -0x7F,0xF8,0x9B,0xFE,0xFF,0xBF,0xEF,0xFB, -0xFF,0xFF,0xBF,0xEF,0xFB,0xFF,0x7F,0xCF, -0xF3,0xFC,0xFF,0xBF,0xEF,0xFF,0xDB,0x3F, -0xEF,0xFB,0xFE,0xFF,0xDF,0xFF,0xFE,0xFB, -0xBB,0xEF,0xBF,0xEF,0xBB,0xEE,0xFB,0xBE, -0xEF,0xBB,0xFF,0xFC,0x7F,0xFD,0x3B,0x5B, -0xD6,0xE5,0xFD,0x4F,0xC3,0xFB,0xFF,0xBF, -0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB,0xFF, -0xB4,0xFF,0xFA,0xBC,0x8F,0xB2,0xE9,0xD2, -0x2E,0xCF,0xFB,0xFF,0xBF,0xEF,0xFB,0xFE, -0xFF,0xBF,0xEF,0xFB,0xFF,0xEC,0xFF,0xFD, -0xFD,0x7F,0xDF,0xF7,0xE4,0xDF,0x5F,0xFF, -0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xC3,0xFF,0xEF,0xE6,0xF8,0xFE, -0x3F,0x8B,0x83,0xF9,0xFE,0x7F,0xE7,0xF9, -0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x7F,0x17, -0xFD,0xFF,0xFF,0xFF,0x7F,0x5F,0xF7,0x2C, -0xFF,0xFF,0xFF,0xFE,0x7F,0xFF,0xE7,0xF9, -0xFE,0x7F,0x9F,0xFE,0x2F,0xFF,0xFF,0xEF, -0xFF,0xFE,0xBF,0xEF,0xAD,0xFF,0xFF,0x7F, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFE,0xDF,0xFF,0xDF,0xFF,0xFD,0xFD,0x7F, -0xDF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFA,0x3F,0xFE, -0xF7,0xFD,0xEF,0x7A,0xFF,0xB1,0xBD,0xFF, -0x7F,0xF7,0xFD,0xFF,0x7F,0xDF,0xF7,0xFD, -0xFF,0x7F,0xF3,0x27,0xFF,0xDF,0xFF,0xDD, -0xFF,0xFC,0x9B,0xFF,0xCB,0xFC,0xBF,0x2F, -0xCB,0xF2,0xFC,0xBF,0x2F,0xC9,0xFF,0xDE, -0xFF,0xDF,0xAF,0xEB,0xDA,0xFE,0xBB,0xAF, -0xEB,0xF8,0xF7,0xAF,0xE8,0xFA,0xFE,0xBF, -0xAF,0xEB,0xF2,0xFF,0xFD,0xFF,0xFF,0xEF, -0xBD,0xD7,0xBF,0xFF,0xFF,0xDE,0x8F,0xB8, -0xDE,0x37,0x8D,0xA3,0x78,0xDA,0x3F,0x8F, -0xFF,0xA1,0xFF,0xFF,0xFB,0xFB,0xFF,0xFF, -0xFF,0xFF,0xA7,0xBD,0xFB,0x76,0xFD,0xBF, -0xEF,0xDB,0xFE,0xBB,0xBF,0xFE,0x27,0x7F, -0xFF,0xFE,0xFE,0xFD,0xF5,0xFF,0xEF,0xF5, -0xDF,0x1F,0xE7,0xFD,0xFF,0x7F,0xDF,0xF7, -0xFD,0xFF,0xFF,0xCD,0xFD,0xAE,0xFF,0xFA, -0x3E,0x3F,0xAB,0xFD,0xF8,0x7E,0x8F,0xE3, -0xF8,0xFE,0x3E,0x8F,0xE3,0xF8,0xFF,0xFE, -0x1F,0xEF,0xDF,0xBF,0xFE,0xDE,0xDF,0xD9, -0xFF,0xDF,0xBC,0xFF,0xFF,0x7F,0xFF,0xEF, -0xFD,0x7F,0xDF,0xF7,0xF9,0x3F,0xFE,0xFF, -0xFF,0x6F,0xFE,0xDE,0xBF,0xF7,0xED,0xEA, -0xFD,0x8F,0x83,0xF8,0xEA,0x3F,0x8F,0xEF, -0xFF,0xF4,0x7F,0xFF,0xEF,0xEF,0x7B,0xF3, -0xF1,0x5F,0xFF,0xFF,0xF1,0x3B,0x7F,0xDF, -0xF7,0xFD,0xFF,0xFF,0xFF,0xFF,0xE0,0xFF, -0xFF,0xFF,0xF7,0xFF,0x6F,0xFF,0x7F,0xFF, -0xFF,0xF7,0xDE,0xF7,0xBF,0xEF,0xFB,0xF7, -0xFD,0xFF,0xFF,0xF5,0xFA,0xFF,0xFF,0xFB, -0xE7,0xFF,0xF3,0xF8,0x7F,0xF3,0xDF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F,0xEF, -0xBB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD, -0xFF,0x7F,0xFF,0x9F,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xCF,0xFF,0x37,0xFF,0xFF, -0x7F,0xDF,0x77,0x5D,0xE7,0xFC,0xFF,0xBF, -0xF7,0xF5,0xFB,0xFF,0xFF,0xD7,0xF5,0xFB, -0xFF,0xFF,0x45,0xFD,0x7F,0xEA,0xFD,0xBE, -0xBF,0xDF,0xF7,0xFF,0xFF,0xDB,0xFB,0xFE, -0xFF,0xBF,0xEF,0xFF,0xFF,0xFF,0xFB,0x5F, -0x7F,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFE,0xFF,0xEF,0xFD,0xFF,0x7F,0xDF, -0xFF,0xEF,0xFB,0xF8,0x0F,0xF3,0xFF,0xF9, -0x2E,0xFB,0xFE,0xFC,0xF3,0xEF,0xFF,0xFF, -0xBF,0xFF,0xFB,0xE7,0xFF,0xFE,0x7E,0xFF, -0xC0,0x6B,0xCF,0xFF,0x34,0xDF,0xF1,0xFD, -0xFF,0xEF,0xFF,0xFF,0xFF,0xDF,0xF7,0xFD, -0xCF,0x7F,0x9C,0xFD,0xFD,0x6C,0xF7,0xFF, -0xF6,0xFD,0xEB,0x2B,0x9F,0xFF,0xFC,0xFE, -0x7E,0xFF,0xFF,0xFF,0xFF,0xD7,0xF3,0xF7, -0xFF,0xFB,0xE1,0xBF,0xFF,0xEB,0x7A,0xDE, -0xD7,0xFB,0xFF,0xF9,0xFE,0xFF,0xFF,0xF3, -0xDE,0x7F,0xFD,0xE7,0x7F,0xFF,0xFD,0xBB, -0xFF,0xFF,0x7E,0xCC,0xF6,0xAF,0x5F,0x7F, -0xFE,0xF4,0x7D,0xF7,0xFD,0xBB,0x6E,0xDB, -0xB7,0xFF,0xF7,0xDF,0x66,0xFF,0xFF,0xF7, -0x3D,0xCF,0xDE,0xBD,0xFF,0xFF,0xDE,0xDB, -0x8D,0xF7,0x7E,0xDF,0xB7,0xEF,0x7F,0xFF, -0xF6,0x87,0xFF,0xFF,0xEF,0xFE,0xDE,0xBF, -0xFF,0xFF,0xFF,0xBB,0xEF,0xFD,0xFF,0x7B, -0xDE,0xF7,0x3F,0xFF,0xBF,0xFB,0xDB,0xFF, -0xF2,0xB6,0xFD,0xBD,0x7F,0xE7,0xFF,0xFF, -0xFF,0x6F,0xF7,0xFF,0xFF,0xFF,0xFE,0x77, -0xFF,0xBF,0xF8,0xAF,0xFF,0xDF,0xBF,0xFF, -0xBF,0x7F,0xFB,0xFF,0xFF,0xFF,0xDB,0xFE, -0xFF,0xBF,0xFF,0xFA,0xFF,0xFD,0xFF,0xF6, -0x7F,0xFF,0x9F,0xFF,0xFF,0x3F,0xEF,0xF8, -0xEE,0x7E,0x9F,0xBA,0xFE,0xBF,0x8F,0xEF, -0xFE,0xFE,0xF9,0xFF,0xFA,0x7F,0xFE,0x7E, -0xBF,0xAF,0xFB,0x96,0xFD,0x9F,0xEF,0x5E, -0x65,0xBE,0xEF,0x5B,0xB6,0xFF,0xBE,0xE3, -0xFF,0xB5,0xBF,0xFF,0xFD,0xFF,0x7F,0xFF, -0xEF,0xDF,0xFE,0xFF,0xBF,0xFB,0xFE,0xFF, -0xBF,0xCF,0xFF,0xFF,0xFF,0xFD,0x9B,0xFF, -0xFE,0xFB,0xFE,0xDF,0xFF,0x7F,0xFF,0xF7, -0xFE,0xFF,0xDF,0xFB,0xFB,0xFE,0xFF,0xFF, -0xFF,0xFF,0xFF,0xB7,0xFE,0xFA,0xFF,0xAB, -0xEF,0xFF,0xFD,0xB5,0x7B,0x7F,0xFB,0xF7, -0xFD,0xFF,0xFF,0xDD,0xFF,0xEF,0x8F,0xFF, -0x2F,0xFF,0xFB,0x7C,0xFF,0x3F,0xDF,0x73, -0xEB,0xFE,0x3F,0xFF,0xEF,0xFB,0xFE,0xFF, -0xEF,0xFD,0xFF,0xBF,0xFD,0x0F,0xFF,0xFF, -0xFF,0xF5,0xF9,0xFF,0x7F,0xD7,0xFD,0xFF, -0xDF,0xFF,0xF7,0xFB,0xFF,0x7F,0xBF,0xFF, -0xFF,0xF0,0x9F,0xFF,0xFE,0x7F,0x8B,0xE3, -0xF9,0xDE,0x27,0x9B,0xE6,0xBE,0x7F,0x9B, -0xC3,0xF8,0xDE,0x7F,0x9D,0xE7,0xFE,0x7F, -0xFF,0xFF,0x5F,0xD7,0xFF,0xFF,0xFF,0x4F, -0xFB,0xFF,0xFF,0x7F,0xFF,0xAF,0xFF,0x9F, -0x7F,0xFB,0xFF,0xE8,0xFF,0xFF,0xFE,0xBF, -0xAF,0xFF,0xFF,0xFE,0xBF,0xEF,0xF7,0xFF, -0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF, -0xFC,0xFF,0xFF,0xFD,0x7F,0xFF,0xFF,0xFF, -0xFD,0x3F,0xCF,0xFF,0xFF,0xFF,0xFF,0xF7, -0xFF,0xFD,0x7F,0xFF,0xFF,0x93,0xFF,0xFF, -0x7A,0xDF,0xF7,0xFF,0xFF,0x7B,0x7F,0xB7, -0xEF,0xFF,0xFF,0xFD,0xBF,0xFD,0xFB,0xFF, -0xF7,0xFF,0xD7,0xFF,0xFF,0xFF,0xFC,0x9F, -0x6F,0xCB,0xFF,0xF4,0xBB,0xDF,0xD6,0xFD, -0xBF,0x2F,0xD3,0xF7,0xFF,0xDF,0xFF,0xCF, -0xFF,0xFA,0xBE,0xBD,0xAF,0x6A,0xDA,0xBE, -0xBB,0xAB,0x3A,0xBE,0x2D,0xAE,0xEB,0xDA, -0xF6,0x3F,0xAD,0xF5,0xDD,0xFF,0xCF,0xF1, -0xFF,0xF9,0x7F,0xFF,0x73,0xFE,0xFF,0xCF, -0xC3,0xF4,0xF7,0x2F,0xF3,0xFF,0xFC,0xFF, -0x7C,0x1F,0xFF,0x3F,0x4F,0xFF,0x7E,0xFF, -0xEF,0xBD,0xF6,0xFE,0xFF,0x2B,0xEF,0xDC, -0xFB,0xFD,0xFF,0xFB,0xFF,0xEA,0x7B,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFB,0xF7,0xDF,0xFF, -0xE3,0x7D,0xFF,0xB7,0xFF,0xBF,0xFF,0xFF, -0xDF,0xFF,0xF8,0xFF,0xBF,0xFF,0xBF,0xEB, -0xE7,0xFA,0xFE,0x3D,0xBF,0xE9,0xFC,0xBF, -0xFF,0xFA,0xFB,0xFE,0xFF,0xFF,0xFF,0xD9, -0xFF,0xFF,0xFF,0xF6,0x7F,0xFF,0xF6,0x7D, -0xFF,0xDF,0xCF,0xFD,0xBF,0xFB,0xEF,0x7E, -0xFF,0x7F,0xFF,0xFF,0xD3,0xFF,0xFD,0xFB, -0xFF,0xFB,0xFF,0xFF,0xFF,0xEF,0xFF,0xBF, -0xFE,0xFF,0xF7,0xEF,0xFF,0xFF,0xFF,0xFB, -0xFF,0x87,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF, -0x7B,0xFE,0xFF,0xFE,0x3B,0xF7,0xF7,0xFF, -0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0xFF, -0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xF7, -0xFF,0xFF,0xAD,0xFF,0xFE,0xF7,0xFF,0xFF, -0x5F,0xFF,0xFF,0xDF,0xFF,0xFD,0xFF,0xF5, -0xFF,0xDF,0xFF,0xBD,0xFF,0xE9,0xFF,0xC7, -0xF3,0xFF,0xFF,0xF7,0xFF,0xF3,0xFF,0xF8, -0x3B,0xFF,0xFF,0x7B,0xDF,0xBF,0xFB,0xEF, -0xFB,0xFF,0xFB,0xF7,0xF7,0xBB,0xFF,0xFF, -0xFF,0xFF,0xFB,0xFF,0xFE,0x7F,0xF3,0x7F, -0x5E,0xB7,0xBF,0xFD,0x7F,0xFF,0xF9,0x7F, -0xFB,0xFF,0xEB,0xFD,0x7F,0x7F,0xFF,0xEF, -0xFB,0xE0,0x3F,0xFE,0xBF,0xBF,0xDF,0xFF, -0x7E,0xFF,0xF7,0xFF,0xFF,0xFE,0xBF,0xFF, -0xDB,0x78,0xFF,0xFF,0xFF,0xEE,0xA1,0xBF, -0xF5,0xDE,0xFB,0xF7,0xFF,0xFB,0xFF,0xFF, -0xFF,0xFF,0xFB,0xFF,0xFF,0xD7,0xFF,0xFF, -0xFF,0xFF,0xEF,0xF0,0xFF,0xFF,0xFF,0xF3, -0xF7,0xFF,0xEF,0xFF,0xE7,0xCF,0xFF,0xFB, -0xFF,0xEF,0xFF,0xFF,0x9F,0x9F,0xEF,0xFC, -0x16,0xBF,0xFE,0xF3,0xE4,0xFF,0xFF,0xC6, -0xFF,0xE7,0xFF,0xFF,0xFD,0xFF,0xBF,0xFF, -0xFF,0x3F,0xFF,0xBF,0xD6,0xAF,0x7F,0xFE, -0x6B,0x7E,0x7F,0xFF,0xAF,0xFF,0xFF,0xBF, -0xFF,0x5F,0xFF,0xFE,0xFF,0xFF,0xFE,0xFF, -0xFF,0xBD,0xDB,0xFF,0xFE,0x5F,0xF2,0xFF, -0xFF,0x5F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xEF,0x7F,0xFF,0xFF,0xFF,0xFF,0xDE,0xBF, -0xFF,0xFF,0xEF,0xFB,0x77,0xFE,0xBD,0x7F, -0x5F,0xFF,0xFF,0xFF,0xDF,0x6F,0xED,0xFF, -0xFD,0xFF,0x7F,0xFD,0x6F,0xFF,0xFF,0x77, -0xDA,0xCF,0xFD,0x5F,0xFF,0xBF,0xFF,0xFF, -0xDF,0x7F,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF, -0x66,0x7F,0xFF,0xFE,0xBF,0xE7,0xBF,0xFA, -0xFF,0xFE,0xFF,0xFF,0xFF,0xDF,0xFF,0x59, -0xEF,0xFF,0xEF,0xFB,0x7F,0x89,0xFF,0xFF, -0xE9,0xFF,0x6F,0xFF,0xF5,0xFF,0xFF,0xFF, -0xFF,0xFF,0x7F,0xF2,0xF7,0xFF,0xFF,0xEF, -0xF8,0x7F,0xFB,0xFF,0xFD,0xFF,0xFF,0xD9, -0xFF,0xEF,0xBB,0xFF,0xFF,0xFF,0xBF,0xEF, -0xDE,0xFF,0xFF,0x9F,0x7F,0xDF,0xFF,0xF7, -0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xAF, -0xFF,0xFF,0xF7,0x3F,0xEB,0x9F,0xFE,0x7F, -0x9E,0x7F,0x9F,0xFE,0x87,0xFF,0xED,0xDB, -0x56,0xFF,0xBF,0xAF,0x0B,0xD2,0xFF,0xEF, -0xDB,0x6E,0x7D,0xBD,0x6F,0xF8,0xFE,0x3F, -0xFA,0x5B,0xFF,0xFD,0xBF,0xEF,0xFF,0xBF, -0x6F,0xDB,0xE6,0xFF,0xFF,0x3F,0xFF,0xDF, -0xFE,0xFF,0xFF,0xFF,0xFF,0xDA,0x3F,0xFF, -0xFB,0xFE,0xFE,0xFF,0xFF,0xDF,0xF7,0xBD, -0xFF,0xFD,0xFF,0xFE,0xFF,0xFB,0xFF,0xFF, -0xFF,0xFF,0xF1,0x5F,0xFD,0x9F,0xDF,0xFD, -0xFF,0xFD,0x7F,0xFF,0xFF,0xFF,0xFF,0x76, -0xFA,0xFF,0xFF,0x7F,0xE3,0xF8,0xFF,0xAE, -0xFF,0xFB,0x7E,0x9D,0x73,0xFF,0xFA,0x7F, -0xDF,0xFF,0xFF,0x7F,0xFF,0xFB,0xCD,0xFF, -0x7F,0xEF,0xFB,0xFF,0xFD,0xFF,0xF7,0x7F, -0x7F,0xEF,0xFF,0xED,0xFF,0xFF,0xFF,0xB5, -0xFF,0xBF,0xFF,0xBF,0xFD,0xEF,0xDB,0xF7, -0xFF,0x93,0xFF,0xEF,0xE2,0xF9,0xBE,0x7F, -0x8B,0xE7,0xF9,0xFE,0x6B,0xE7,0xF9,0xFE, -0x7F,0x9F,0xE7,0xF9,0xFE,0x7F,0x47,0xFF, -0xFF,0xFD,0xFF,0x9F,0xFF,0xD7,0xFF,0xFF, -0xFF,0xFF,0xF5,0xFF,0x9F,0xFF,0xF7,0xFE, -0xFF,0xBF,0xFE,0x6F,0xFF,0xFF,0xFB,0xFF, -0xFF,0xFF,0xAF,0xFF,0xFF,0xFF,0x7F,0xFB, -0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD, -0xDF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF,0xDF, -0xFF,0xFF,0xFF,0x5F,0xFF,0xFF,0xFF,0xFF, -0x5F,0xFB,0xFE,0xFF,0xF8,0x37,0xFF,0xFF, -0xEF,0xFF,0x7F,0xFE,0xBF,0xFF,0xFF,0xFE, -0xBF,0xFF,0xFF,0x7F,0xFF,0xBF,0xFD,0xFF, -0x7F,0xFA,0x7F,0xFF,0xFF,0x6F,0xFF,0xFF, -0x7D,0xFF,0xCF,0xFF,0xFF,0xFF,0x4F,0xFF, -0xF2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFA,0xBF, -0xFF,0xAE,0xEB,0xFA,0xFE,0xBB,0xAD,0xEB, -0xFA,0xF7,0xAF,0x6B,0xFA,0xF6,0xBF,0x25, -0xE9,0xF2,0x7F,0x45,0xFF,0xFF,0xFD,0xF7, -0xF7,0xBF,0xFF,0xDF,0xFF,0xFF,0xBF,0xFB, -0xFF,0xDF,0xF3,0xFF,0xF7,0x3F,0xCF,0xFF, -0xA1,0xFF,0xFF,0xBF,0xE7,0xFF,0xFF,0x7F, -0xFF,0x3D,0xFF,0xFF,0xFF,0xF7,0xFF,0x2F, -0xFF,0xFB,0xF5,0x7F,0xFE,0x57,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7, -0x3F,0xFF,0xFE,0xFF,0xFF,0xFF,0xFD,0xFE, -0xF7,0xEE,0xAF,0xFE,0xEE,0xE7,0xFA,0xFF, -0xFE,0x9D,0xF9,0x5E,0xFE,0xFF,0xEB,0xFF, -0xFF,0xDF,0xA7,0xFF,0xFF,0xFF,0xFC,0xDB, -0xFF,0xFF,0xFF,0x7E,0xFB,0xFF,0xFF,0xEF, -0xFB,0xFD,0xFF,0xDB,0xFF,0xFF,0xFF,0xEF, -0xFF,0xFF,0xFF,0xFD,0xBF,0xFE,0xBF,0xFF, -0x6F,0x7F,0xFF,0xF7,0xFF,0xFF,0xF9,0xFF, -0xF7,0xFF,0xBF,0xDE,0xF7,0xFF,0xFF,0xFF, -0xFA,0x7F,0xFD,0xBF,0x5F,0xFF,0xFF,0xBF, -0xFF,0xED,0xFF,0xF7,0xBF,0xFF,0xFF,0xEF, -0xFF,0xDF,0xFF,0xFF,0xFF,0xE6,0xFF,0xFB, -0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEB,0xFF, -0xFD,0xFF,0xF5,0xFF,0xF6,0x7F,0xDF,0xBD, -0xCF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF, -0xFF,0xF9,0xFF,0xFF,0xFF,0xFF,0xFF,0xE3, -0xFF,0xEE,0xBF,0xFF,0x7D,0xEF,0xFE,0xFF, -0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFE, -0xFF,0xFF,0xFF,0xFF,0xE7,0xFF,0xB5,0xAE, -0xFF,0xFF,0xB6,0xFE,0xBF,0xFF,0xFF,0xBF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0x27,0xFF,0xEF,0xFE,0x7F,0xDF,0xFF, -0x7E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFD,0xFF,0xF7,0xF9,0x9F,0xFF, -0x5F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F, -0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0x0F,0xFF,0xE7,0xBF,0xFE, -0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFC,0xBF, -0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xC4, -0x6B,0xFF,0x29,0x1F,0xFB,0xAF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xEF,0x1B,0xFE,0xFF,0xFC, -0x6F,0xFF,0xFF,0xFD,0x6A,0xF7,0xD7,0xF5, -0xBF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFE,0xBF,0xFF,0xFF,0xFA,0xFF,0xFF,0xF7, -0xFB,0xDD,0xBF,0xFF,0xE7,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x7F,0xFF, -0xFF,0xF5,0xFF,0xFF,0xF7,0xFD,0xB3,0xEF, -0xFD,0x7E,0x5D,0xFF,0xFD,0xFF,0xFF,0xFF, -0xFD,0x7F,0xD2,0xF5,0xFB,0x7E,0xCB,0xB7, -0xFF,0xFF,0xFF,0xC6,0xFF,0xFD,0xEE,0x63, -0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0xFD,0x65, -0x5B,0xDF,0xFF,0xD5,0xFF,0xFF,0xFF,0xF6, -0xE7,0xBF,0xF7,0xA9,0xFF,0xFF,0xED,0xFF, -0xFF,0xFF,0xFF,0xFF,0xEB,0xFF,0xFF,0xFF, -0xAF,0xFF,0xFF,0xFF,0xF8,0x1B,0xFF,0xE3, -0xD0,0xBF,0xFF,0xE1,0xFF,0xFF,0xFF,0xFF, -0xFF,0xD7,0xFF,0xFF,0xFF,0x5F,0xFF,0xFF, -0xFF,0xFF,0xAF,0xFF,0xDB,0x76,0xBF,0xFF, -0x7F,0xFF,0xBF,0xEF,0xFE,0xFF,0xBF,0xEF, -0xFB,0xFE,0xFF,0xFF,0xFF,0xBF,0xF2,0x7F, -0xFF,0x9F,0xFE,0xBD,0xFE,0x7F,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xF7,0x3F,0xEC,0x7F,0xF6,0x95,0xBB, -0xEF,0xF8,0xFE,0xFC,0xBF,0x2F,0xDA,0xFC, -0xBF,0x2F,0xCB,0xF2,0xFC,0xBF,0xEF,0xFF, -0xA9,0xBF,0xCF,0xFB,0xFF,0xFF,0xFF,0xFE, -0xDD,0xB7,0x6D,0xF6,0xD9,0xB6,0x6D,0x9B, -0x76,0xD9,0xBF,0xFB,0xFD,0xA3,0xFF,0xBF, -0xEF,0xFF,0xEF,0xFF,0xFF,0xFF,0x7F,0xDF, -0xFD,0xEF,0x7B,0xDE,0xF7,0xFD,0xEF,0x7F, -0xFF,0xFF,0x05,0xFF,0xFA,0xFE,0x7F,0xEF, -0xE3,0xFF,0xFF,0xFD,0x7F,0xFF,0xFF,0xFF, -0xFF,0x5F,0xFF,0xFF,0xFD,0x7F,0xFB,0xAF, -0xFF,0x63,0xC8,0xFF,0xBF,0xEF,0xFF,0xFF, -0xFA,0x7F,0xFF,0xFF,0xFF,0xFE,0x9F,0xF7, -0xFF,0xFA,0xBF,0xFE,0x9F,0xFB,0x7F,0xFF, -0xFF,0xEF,0xD7,0xFF,0xFF,0xF5,0xFF,0xFF, -0xFF,0xFF,0xFD,0x7F,0xFF,0xFF,0xBF,0xFF, -0xF9,0xBF,0xFF,0xBE,0x27,0x9F,0xE7,0xF9, -0xFE,0x7F,0x8B,0xE7,0xFE,0x7F,0x9F,0xE2, -0xF9,0xFE,0x7F,0x9F,0xE7,0xF1,0x7F,0xFF, -0xFF,0xFF,0xFB,0xFE,0xFF,0xFF,0xFF,0xD7, -0xFF,0xFF,0xFF,0xFF,0xF5,0xFF,0xFF,0xFF, -0xD7,0xFF,0xFA,0xFF,0xFE,0xFF,0xFF,0xFF, -0xFD,0xFF,0xFF,0xFF,0xAF,0xF7,0xFF,0xFF, -0xFF,0xEB,0xFF,0xFF,0xFF,0xAF,0xFF,0xC4, -0xFF,0xF7,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF, -0xFF,0x5F,0xFF,0xFF,0xFF,0xFF,0xD7,0xFF, -0xFF,0xFF,0xFF,0xFF,0xEB,0xFF,0xFB,0x7A, -0xDF,0xF7,0xFD,0xFF,0xFF,0xFE,0xBF,0xFF, -0xFF,0x7F,0xFF,0xAF,0xFF,0xFF,0xFF,0xF7, -0xEF,0xE3,0xFF,0xDD,0xD2,0xFF,0xDF,0xFF, -0xFF,0xF2,0xFC,0xBF,0xCB,0xF6,0xFD,0xBF, -0x2F,0xCB,0xFF,0x7F,0xDF,0xDE,0xAF,0xFF, -0xDA,0xEE,0xBF,0xAF,0xE9,0xFA,0xF4,0xBD, -0xAF,0x5A,0xAE,0xBB,0xAB,0x6B,0xDA,0xDE, -0xBF,0xAD,0xD7,0x5E,0xFF,0xFF,0xBF,0xFC, -0xFF,0xDF,0xFD,0xFF,0xFF,0xFF,0xFF,0xDF, -0xF7,0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFA, -0x1F,0xFF,0xFE,0xFB,0xEF,0xBF,0xFD,0xFF, -0xFD,0xBD,0x77,0xFF,0xFF,0xFF,0xFF,0x9D, -0xEF,0xFF,0xFF,0xFF,0xEF,0x7D,0xFF,0xFB, -0xFE,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEE, -0xBF,0xE4,0xFB,0xFF,0xFE,0x3F,0xFE,0xFF, -0xFF,0xFF,0xFF,0xAF,0xEA,0xFE,0xBF,0xAF, -0xEB,0xFA,0xFE,0xFF,0xFF,0xFF,0x55,0xF6, -0xFF,0xFE,0xF7,0xFF,0x7F,0xFF,0xEB,0xF7, -0x5F,0xC5,0xFD,0x7F,0x5F,0xD7,0xF5,0xFF, -0x6F,0xFB,0xFF,0x8A,0xFF,0xFF,0xFF,0xFF, -0xEB,0xFF,0xFF,0xFF,0xFF,0xFB,0xBF,0xBF, -0xEF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF, -0x77,0xDF,0xFB,0xFF,0xFD,0x7F,0xEF,0xFF, -0xFF,0xFF,0xBF,0x7F,0xFF,0xDF,0xBF,0xFF, -0xFB,0xFF,0xFF,0xFF,0xFE,0xEF,0xDF,0xFF, -0xFE,0xFF,0x9F,0xEF,0x7D,0xFF,0xF7,0xFF, -0x7F,0xFF,0xFF,0xDF,0xF7,0xFD,0xFF,0xEF, -0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFB, -0xFD,0xFF,0xBF,0xDF,0xD1,0xFF,0xF8,0x3B, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0x7E,0xDB,0xFD,0xFF,0x77,0xDB,0xB7,0x7D, -0xBF,0xFB,0xFF,0xF8,0x7F,0xED,0x7B,0x5E, -0xFF,0xFE,0xFF,0xFF,0x4F,0xD7,0xFD,0x7F, -0xDF,0xD7,0xF5,0xFF,0x7F,0xFF,0xFF,0xFF, -0xF2,0x3F,0xFE,0xFF,0xBF,0xFF,0xFF,0xFF, -0xFF,0xBF,0xEF,0xFE,0xFF,0x3B,0xEE,0xFF, -0xFC,0xEF,0xFF,0xFF,0xFF,0x85,0xFF,0xFD, -0xFE,0xFF,0xF5,0xFF,0xFF,0xFE,0xFF,0xDF, -0xFB,0xFF,0x5F,0xBF,0xFF,0xFD,0xFF,0xFF, -0xFF,0xFF,0xA8,0xFF,0xFF,0x9F,0x9E,0xFF, -0xFF,0xFF,0x7F,0xF3,0xFF,0xFF,0xCF,0xFF, -0xF7,0xFD,0xFF,0x7F,0xFF,0xFF,0xFC,0x16, -0xBF,0xCF,0xA3,0xE5,0xEF,0x7F,0xFF,0xF3, -0xE4,0xFF,0xCF,0x93,0xFC,0xFF,0x3F,0xCF, -0xFF,0xFF,0xFF,0xD6,0x0F,0x7D,0xBF,0x6E, -0xFB,0xF4,0xFC,0xAF,0x6D,0xDB,0x77,0xB7, -0x6D,0xDB,0xF6,0xFD,0xBF,0xFF,0xFF,0xFF, -0xBF,0x9B,0xFA,0xDE,0xB7,0xB7,0xED,0xF9, -0x7E,0xB7,0xAC,0xEB,0xD6,0xB3,0xAD,0xEB, -0x7A,0xDF,0xFF,0xFF,0xFF,0xD8,0xBF,0xFF, -0xB7,0xED,0x9F,0x6F,0xDD,0xF7,0x68,0xDB, -0x37,0xB3,0x6C,0xDB,0x36,0xCD,0xB3,0x7F, -0xFF,0x7F,0xF5,0x6F,0xFD,0xEF,0x79,0x3D, -0xF7,0x93,0xE4,0x7A,0x9E,0xAD,0xEA,0x7A, -0x9E,0xF7,0xBD,0xEF,0xFF,0xFF,0xFF,0x76, -0x7F,0xFB,0xC6,0xFF,0xBB,0xEF,0xDA,0xFE, -0xFD,0xBF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB, -0xFF,0xFF,0xFB,0xFF,0xA5,0xFF,0xFD,0xAB, -0x6F,0x78,0xDE,0x17,0x8F,0x79,0xDF,0xFD, -0xFF,0x7F,0xDF,0xF7,0xFD,0xFF,0xFF,0xFB, -0xFF,0xFB,0xFF,0xEF,0xFB,0xEF,0xFB,0xFE, -0xFF,0xBB,0xDA,0xF3,0xEF,0x3B,0xCE,0xF3, -0xBC,0xEF,0x3F,0xCF,0xDF,0xFF,0xB7,0xFF, -0xFF,0xFF,0xCF,0x73,0xFF,0xBF,0xEF,0xFF, -0xF3,0xFF,0x3F,0xCF,0xF3,0xFC,0xFF,0x3D, -0xCF,0x9F,0xFE,0x07,0xFF,0xAF,0xEB,0xFE, -0xFD,0xBF,0xEF,0xEB,0xFA,0xFF,0xAF,0xEB, -0xFA,0xFE,0xBF,0xAF,0xFB,0xFE,0x3F,0xFB, -0x9B,0xFF,0x7F,0xDF,0xFF,0xF3,0xFE,0xFF, -0xDE,0xF7,0xBF,0x7B,0xDE,0xF7,0xBD,0xEF, -0x7B,0xFE,0xFF,0xFF,0xDF,0x3F,0xFE,0xFF, -0xB7,0xFF,0xEF,0xF7,0xFF,0xBF,0xED,0xFE, -0xDF,0xB7,0xED,0xFB,0x7E,0xDF,0xFF,0xFF, -0xFF,0xFD,0x5F,0xEF,0xEB,0xFA,0xFE,0xF5, -0xBF,0x6F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFE,0xF8,0xFF,0xA8,0xFF, -0xFF,0xBF,0xEF,0xFB,0x6A,0xFB,0xB7,0xEF, -0xFB,0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xBF, -0xEF,0xFB,0xFF,0xE0,0xFF,0xFF,0xFD,0x7F, -0x5C,0xD7,0x7D,0xDF,0xF3,0x5C,0xF5,0xCD, -0x73,0x5E,0xD7,0xB5,0xFD,0x7F,0xEF,0xFF, -0xDB,0xFF,0xFF,0xE2,0xF8,0xBE,0x2F,0x8F, -0xE7,0xF8,0xBE,0x6B,0xE2,0xF8,0xBE,0x2F, -0x8B,0xE2,0xF9,0xFE,0x7F,0xE7,0xFF,0xD7, -0xF5,0xFD,0x7F,0xFF,0xF7,0xF5,0xFD,0x7F, -0xD7,0xF5,0xFD,0x7F,0x5F,0xD7,0xF5,0xFF, -0xFF,0xFF,0x8F,0xFF,0xAF,0xEB,0xFA,0xFF, -0xFF,0xBF,0xEB,0xFA,0xFF,0x2F,0xEB,0xFA, -0xFE,0xBF,0xAF,0xEB,0xFF,0xFF,0xFE,0x5F, -0xFF,0x5F,0xFF,0xFF,0xFD,0xFF,0xFF,0xD7, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xBF,0xFE,0xB7,0xFD, -0xFF,0x7E,0xDF,0xF7,0xAD,0xFF,0x7F,0xF7, -0xFD,0xFF,0x7F,0xDF,0xF7,0xFD,0xFF,0x7F, -0xF6,0x7F,0xFF,0xFF,0xFF,0xDB,0xF6,0xFC, -0xAF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xEC,0xBF,0xFF, -0xAF,0xEB,0xFA,0xF6,0xAB,0x8F,0xEB,0xFA, -0xF7,0xA5,0xEB,0xFA,0xBE,0xBF,0xAF,0xEB, -0xFA,0xFF,0x6D,0xFF,0xFF,0x7F,0xDF,0x33, -0xDD,0xFF,0x7F,0xFE,0xF7,0xFC,0x7F,0xFB, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA9, -0xFF,0xFD,0xFF,0xFF,0xFE,0xFF,0xFF,0xDF, -0xFF,0xFF,0xEF,0xEF,0xFD,0xFF,0x7F,0xFF, -0xFF,0xFF,0xFF,0xFE,0xA7,0xFF,0xFF,0xFF, -0x77,0xDF,0xF7,0xFD,0x9F,0x7F,0xFE,0x77, -0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xAF,0xBF,0xAF,0xFF,0xF9,0xBE,0xBF, -0x8F,0xFB,0xFE,0xFE,0xEF,0xFB,0xFE,0xFF, -0xBF,0xEF,0xFB,0xFF,0xFF,0xFD,0xDF,0x6F, -0xEF,0xFF,0x7F,0xFF,0xBF,0xBF,0xDF,0xFF, -0xFC,0xFF,0xDF,0xF7,0xFD,0xEF,0x7F,0xDF, -0xFF,0xFF,0xFF,0x3F,0xF6,0xFF,0xCF,0xFF, -0xDB,0xFB,0xF7,0xFF,0xEB,0x7A,0xFF,0xFF, -0xFF,0xBF,0xEF,0xFB,0xFF,0xFF,0xFF,0xFE, -0x6D,0xFD,0xFF,0x5F,0xFB,0xFF,0xFF,0xF7, -0xFF,0x5F,0xF5,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xF8,0xFF,0xFB,0xFF, -0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xE7,0xF6, -0xBF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xFF, -0xFF,0xC9,0xFF,0xFF,0xFF,0xBD,0xFF,0xBF, -0xAF,0xEF,0xEF,0x3F,0xD1,0xFC,0x7F,0xFB, -0xC7,0xFF,0xFF,0xFF,0xFF,0xFF,0xE3,0xFF, -0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0x77,0xFF, -0xDF,0xB7,0xFD,0xF7,0xFD,0xF7,0xFF,0xFF, -0xFF,0xFF,0xFF,0x57,0xFF,0xF7,0xA5,0xFD, -0x3F,0xDF,0xBF,0xBF,0xFE,0x7F,0xFF,0xFF, -0xFF,0xDF,0xFA,0xFD,0xFF,0xFF,0xFF,0xFE, -0x87,0xFF,0xE9,0xFF,0xFE,0xEF,0xBF,0xEF, -0xFE,0xFE,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFA,0x9F,0xFF,0x3F, -0xFF,0xFD,0xFD,0x57,0xDF,0xFD,0xF3,0xFF, -0xDF,0xFD,0xFF,0x5F,0xDF,0xF5,0xFD,0xFF, -0xFF,0xF9,0x8F,0xFF,0xFF,0xFF,0xEE,0x7F, -0xFF,0xFF,0xBF,0x5E,0xFE,0xEC,0xFB,0x3F, -0x7F,0x9F,0xEF,0xF9,0xFF,0xFF,0xCD,0x6B, -0xFF,0xFF,0xFF,0xC5,0xF3,0xFC,0xFA,0x38, -0xFF,0xAF,0x3F,0xEE,0x7F,0x9F,0xFF,0xD9, -0xFF,0xFF,0xFD,0x7A,0xF7,0xFF,0xF3,0xFF, -0xAF,0x6F,0xDB,0xF2,0xB9,0xE9,0xFB,0xFF, -0xFF,0xFF,0xFE,0xFF,0xFF,0xEF,0xFF,0xFB, -0xC5,0xBF,0xFF,0xEF,0xFF,0x5E,0xB7,0xAD, -0xCD,0x79,0x7C,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFD,0x93,0xFF,0xEF, -0xEA,0xFE,0xBF,0xEF,0x5B,0xD2,0xCD,0xF5, -0x6D,0x77,0xDF,0xF7,0xFD,0xFF,0x7F,0xDF, -0xFF,0xFF,0x66,0xFF,0xD5,0x65,0x7D,0x5F, -0x75,0x9D,0x65,0x7F,0xD6,0xFB,0x4F,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0xC7, -0xFF,0xBF,0xEF,0xFA,0xFE,0xFF,0xBF,0xEB, -0xFF,0xDF,0xFF,0x7E,0xFF,0xFF,0xEF,0xFD, -0x7E,0xD7,0xFF,0x78,0xDF,0xFF,0x5F,0xDF, -0xF5,0xBF,0x7F,0xDF,0xC5,0xFF,0x3F,0xF6, -0x7E,0xFF,0x0F,0xEF,0xF2,0x3E,0xBF,0xFF, -0xFB,0x3F,0xFF,0xFB,0x7F,0xFF,0xB3,0xFE, -0xFB,0xF6,0xFD,0xFF,0xDA,0xF7,0xFD,0xFF, -0x7F,0xDF,0xF7,0xBF,0xFF,0xFA,0x7F,0xFF, -0xFF,0xFF,0xFF,0x9F,0xFF,0xF3,0xDC,0xF9, -0xBF,0xCE,0xE7,0xF9,0xFE,0x7F,0x9F,0xE7, -0xFF,0xFF,0xE2,0x7F,0xFE,0xFF,0xBF,0xEF, -0xEB,0xFA,0xFF,0x9F,0x67,0x1E,0xFF,0x8F, -0xE7,0xF8,0xFE,0x7F,0x8F,0xEF,0xFF,0xBD, -0xBF,0xFF,0xFB,0xFF,0xFF,0xDF,0xF7,0xFF, -0xFC,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFD,0xB3,0xFF,0xFF,0xEF, -0xFF,0xFF,0xBF,0xED,0xFF,0xFB,0xEE,0xFE, -0xFF,0xFF,0xEF,0xFF,0xFE,0xFF,0xFF,0xFF, -0xFF,0xB5,0xFF,0xB7,0xFD,0xFD,0x6E,0xFF, -0xFF,0xFE,0xFD,0x2F,0xD8,0xFE,0xBF,0x8F, -0xEB,0xF9,0xFE,0x3F,0xFF,0xFA,0xCF,0xFF, -0xE7,0xD9,0xFA,0xBF,0xDF,0x77,0xFC,0xFB, -0x3F,0xAB,0xFE,0xFF,0xBF,0xEF,0xFB,0xFE, -0xFF,0xFF,0xEE,0x1F,0xFF,0xDF,0xF7,0xFF, -0xFF,0xFF,0x5F,0x97,0x35,0xBF,0x5E,0xFE, -0xBF,0xEF,0xFF,0xF7,0xFD,0xFF,0xFF,0xFA, -0xBF,0xFF,0xBE,0x6F,0x9F,0xE7,0xF8,0xBE, -0x2F,0x8B,0x66,0x94,0x7D,0x9D,0xE7,0xF9, -0xFE,0x7F,0x9F,0xE7,0xF1,0x7F,0xFF,0xFF, -0xFF,0xF7,0xF5,0xFD,0x7F,0x5F,0xFB,0xFD, -0x9E,0xFF,0xFB,0xFE,0xFF,0xFF,0xEF,0xFF, -0xFF,0xA0,0xFF,0xFF,0xFF,0xBF,0xEF,0xEB, -0xFA,0xFE,0xBF,0xB7,0xF7,0xF7,0xFF,0xFF, -0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xDD,0xFF, -0xFD,0xFF,0xFF,0xFF,0xD7,0xFF,0xFF,0xFF, -0x7F,0xF5,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF, -0xBF,0xFF,0xFF,0xAB,0xFE,0xFB,0xFE,0xFF, -0xF7,0xAF,0xFF,0xFF,0xDE,0xF7,0xEB,0x5F, -0xDF,0xF7,0xFD,0xFF,0x7F,0xDF,0xFF,0xFF, -0xB3,0xFF,0xC9,0xFE,0xFF,0xFF,0xFF,0xFF, -0xD6,0xFF,0xFF,0xCB,0xFF,0xFF,0xDF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFC,0x8F,0xFF,0xBA, -0xBE,0xBF,0xAF,0xEB,0x78,0xFE,0xB7,0xAD, -0x3A,0xFE,0xB7,0xAF,0xEB,0x7A,0xFE,0xBF, -0xAF,0xFF,0x9F,0xFF,0xFF,0xDF,0xFC,0xFF, -0xFF,0xFE,0xC3,0xFE,0xFF,0xFF,0x33,0xFC, -0xFF,0xBF,0xDF,0xF3,0xFF,0xFF,0xBB,0x9F, -0xFF,0xFF,0xFF,0xEB,0xDF,0xFF,0xFF,0xAF, -0xF7,0x6F,0xF9,0xBF,0xEF,0xFD,0xFF,0xFF, -0xFF,0xFF,0xFF,0xE3,0x7F,0xFF,0xFF,0xFF, -0xFB,0xFF,0xFF,0xBF,0xFD,0xFB,0xF7,0xFF, -0xDF,0xF7,0xFF,0xFE,0xEF,0x5F,0xBD,0xFF, -0xFA,0xFF,0xF8,0xFF,0xBF,0xAF,0xFB,0xFE, -0xFE,0x3F,0xEF,0xE8,0xFF,0xDF,0xF3,0xFD, -0xFF,0xFF,0xFF,0xFF,0xFF,0xED,0xFF,0xFB, -0xFD,0xFF,0xAF,0xFF,0xFF,0xFE,0xFE,0xBF, -0xDB,0xFF,0xFF,0xFF,0xBF,0xFF,0xDF,0xFF, -0xFD,0xFF,0xCB,0xFF,0xFF,0xFF,0xFF,0xFF, -0xBF,0x6F,0xFF,0x7F,0xB7,0xB3,0xFF,0xFF, -0xDF,0xFF,0xFB,0xEF,0xFF,0xFF,0xFF,0x07, -0xFF,0xFB,0xFF,0xFF,0xFF,0xED,0xFF,0xF5, -0x7C,0xFF,0x7F,0xFE,0xFF,0xFF,0xEF,0xCF, -0xFF,0xFB,0xFF,0xFF,0x2F,0xFF,0xFF,0xFF, -0xFF,0xF3,0xFF,0xFB,0xFF,0xFE,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF, -0xFD,0x1B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFE,0x7C,0xFF,0xFF,0xFF,0xFF, -0xEF,0xFF,0xFF,0xFF,0xFF,0xFB,0xBF,0x7F, -0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xDB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD, -0xFF,0xFF,0xF0,0x7F,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xDF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xBF,0xFE, -0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xEF,0xFE,0xFF,0xBF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xEF,0xFA,0xB5,0xFF,0xFF,0xFF, -0xF7,0xF7,0xFF,0xFF,0xFF,0xFF,0xDF,0xFB, -0xFC,0xFF,0xFF,0xFE,0xFF,0x7F,0xDF,0xBF, -0xFF,0xCB,0xBF,0xF9,0xFE,0x7F,0x9F,0xE7, -0xF9,0xFE,0x7F,0x97,0xE1,0xFE,0x79,0x9F, -0xE7,0xFD,0xFE,0x7F,0xDF,0xFE,0x37,0xFF, -0xFB,0xDE,0xDE,0xBD,0xEF,0xF3,0xFE,0xFB, -0xAF,0xEB,0xFE,0xFF,0xFF,0xCF,0xFF,0xFE, -0xFF,0xBF,0xFF,0x8F,0xFF,0xEF,0xFB,0xFE, -0xFF,0xBF,0xE7,0xF9,0x5E,0x7F,0xEF,0xFB, -0xDA,0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xFD, -0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF, -0xFF,0xFF,0x7F,0xFF,0xFF,0xF7,0xFB,0x7F, -0xFF,0xFF,0xFF,0xFF,0xFC,0x3F,0xFF,0xBF, -0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0x7B,0x7F, -0xBF,0xEF,0xFB,0xFE,0xFF,0xB5,0xEF,0xFB, -0xBF,0xFA,0x7F,0xFC,0xFF,0x3F,0xCF,0xF3, -0xFC,0xFF,0x3F,0xCF,0xBC,0xFF,0x3F,0xEF, -0xF3,0xFC,0xFE,0x3F,0xCF,0xFF,0xEE,0xEF, -0xFB,0xFE,0xFF,0xBF,0xEF,0xFB,0x6A,0xD7, -0xB7,0xFB,0xF8,0xFF,0xB7,0xEF,0xBA,0xFE, -0xFF,0xBF,0x7F,0xE9,0xFF,0xF9,0x7E,0x5F, -0x97,0xE5,0xF9,0xFE,0x7F,0xBF,0xF9,0x7E, -0x5F,0x9F,0xE5,0xFB,0xFE,0x5F,0xB7,0xFF, -0xA3,0xFF,0xF7,0xFD,0xFF,0x7F,0xDF,0xF7, -0xFD,0xFF,0x5E,0xF7,0x7D,0xFF,0x77,0xDF, -0xF7,0xFD,0xFF,0x7F,0xFF,0xD7,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFD,0xDF,0xFB,0x7F, -0xFF,0xFF,0xEF,0xFF,0xFE,0xFB,0xFF,0xFF, -0xBF,0xFE,0x8F,0xFF,0xDF,0xF7,0xFD,0xFD, -0x7F,0xDF,0xF7,0xFD,0x3E,0xDF,0xF5,0xBD, -0xFF,0x7F,0xDF,0xF7,0xFD,0xF7,0xFF,0x9F, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFD,0xFF,0xBE,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFD,0x3F,0xFF,0xDF,0xF7, -0xFD,0xFF,0x7F,0xDF,0xF7,0xFD,0xFF,0xCF, -0x77,0xFC,0xFF,0x5F,0xDF,0xF7,0xFD,0xFF, -0xF4,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFD,0xFF,0xFF,0xFF,0xEE,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xED,0xFB,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xE9,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFB,0xFF,0xFF,0xFF,0xD3,0xFF,0xFF, -0xBF,0x3F,0xFB,0xFF,0xFF,0xFF,0xFB,0xF3, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xF7, -0xFF,0xFF,0xFF,0xFF,0x17,0xFF,0xFF,0xFF, -0xDF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF, -0xDF,0xDF,0xFF,0xFD,0xFF,0xFF,0xDF,0xF7, -0xFF,0x4F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFD, -0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0x9F,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, -0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF, -0xFF,0xFF,0x7A,0x3F,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF2, -0x7F,0xFF,0xFB,0xFE,0xFF,0xBF,0xEF,0xF8, -0xFE,0xFF,0xBF,0xFB,0xFE,0xFF,0x8F,0xEC, -0xFB,0xFE,0xFF,0xBF,0xF8,0xF7,0xFE,0xFF, -0xBF,0xEF,0xFB,0xFE,0xFD,0xBF,0xCF,0xEC, -0xFF,0x3F,0xEF,0xDB,0xF8,0xFF,0xBF,0xCF, -0xFF,0xF9,0xFF,0xFF,0xBF,0xFF,0xFB,0xFF, -0xFF,0xFF,0xEF,0xFB,0xDF,0xFF,0xFF,0xFF, -0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xBB,0xFF, -0xEF,0xFB,0xFE,0xEF,0xBF,0xEE,0xEB,0xFB, -0xFE,0xFF,0xEF,0xFE,0xEE,0xBF,0xFE,0xEB, -0xFF,0xEF,0xFF,0x17,0xFF,0x7E,0xEB,0xBB, -0xFE,0xBF,0xBE,0xFB,0xEF,0x5B,0xF7,0xBD, -0xFB,0xCF,0xBF,0xBF,0xBB,0xFB,0x7E,0xCC, -0xEF,0xFF -}; diff --git a/drivers/usb/dabfirmware.h b/drivers/usb/dabfirmware.h new file mode 100644 index 000000000..d14d80356 --- /dev/null +++ b/drivers/usb/dabfirmware.h @@ -0,0 +1,1408 @@ +/* + * dabdata.h - dab usb firmware and bitstream data + */ + +static INTEL_HEX_RECORD firmware[] = { + +{ 2, 0x0000, 0, {0x21,0x57} }, +{ 3, 0x0003, 0, {0x02,0x01,0x66} }, +{ 3, 0x000b, 0, {0x02,0x01,0x66} }, +{ 3, 0x0013, 0, {0x02,0x01,0x66} }, +{ 3, 0x001b, 0, {0x02,0x01,0x66} }, +{ 3, 0x0023, 0, {0x02,0x01,0x66} }, +{ 3, 0x002b, 0, {0x02,0x01,0x66} }, +{ 3, 0x0033, 0, {0x02,0x03,0x0f} }, +{ 3, 0x003b, 0, {0x02,0x01,0x66} }, +{ 3, 0x0043, 0, {0x02,0x01,0x00} }, +{ 3, 0x004b, 0, {0x02,0x01,0x66} }, +{ 3, 0x0053, 0, {0x02,0x01,0x66} }, +{ 3, 0x005b, 0, {0x02,0x04,0xbd} }, +{ 3, 0x0063, 0, {0x02,0x01,0x67} }, +{ 3, 0x0100, 0, {0x02,0x0c,0x5a} }, +{ 3, 0x0104, 0, {0x02,0x01,0xed} }, +{ 3, 0x0108, 0, {0x02,0x02,0x51} }, +{ 3, 0x010c, 0, {0x02,0x02,0x7c} }, +{ 3, 0x0110, 0, {0x02,0x02,0xe4} }, +{ 1, 0x0114, 0, {0x32} }, +{ 1, 0x0118, 0, {0x32} }, +{ 3, 0x011c, 0, {0x02,0x05,0xfd} }, +{ 3, 0x0120, 0, {0x02,0x00,0x00} }, +{ 3, 0x0124, 0, {0x02,0x00,0x00} }, +{ 3, 0x0128, 0, {0x02,0x04,0x3c} }, +{ 3, 0x012c, 0, {0x02,0x04,0x6a} }, +{ 3, 0x0130, 0, {0x02,0x00,0x00} }, +{ 3, 0x0134, 0, {0x02,0x00,0x00} }, +{ 3, 0x0138, 0, {0x02,0x00,0x00} }, +{ 3, 0x013c, 0, {0x02,0x00,0x00} }, +{ 3, 0x0140, 0, {0x02,0x00,0x00} }, +{ 3, 0x0144, 0, {0x02,0x00,0x00} }, +{ 3, 0x0148, 0, {0x02,0x00,0x00} }, +{ 3, 0x014c, 0, {0x02,0x00,0x00} }, +{ 3, 0x0150, 0, {0x02,0x00,0x00} }, +{ 3, 0x0154, 0, {0x02,0x00,0x00} }, +{ 10, 0x0157, 0, {0x75,0x81,0x7f,0xe5,0x82,0x60,0x03,0x02,0x01,0x61} }, +{ 5, 0x0161, 0, {0x12,0x07,0x6f,0x21,0x64} }, +{ 1, 0x0166, 0, {0x32} }, +{ 14, 0x0167, 0, {0xc0,0xd0,0xc0,0x86,0xc0,0x82,0xc0,0x83,0xc0,0xe0,0x90,0x7f,0x97,0xe0} }, +{ 14, 0x0175, 0, {0x44,0x80,0xf0,0x90,0x7f,0x69,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0} }, +{ 14, 0x0183, 0, {0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0} }, +{ 14, 0x0191, 0, {0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x90,0x7f,0x97,0xe0} }, +{ 3, 0x019f, 0, {0x55,0x7f,0xf0} }, +{ 14, 0x01a2, 0, {0x90,0x7f,0x9a,0xe0,0x30,0xe4,0x23,0x90,0x7f,0x68,0xf0,0xf0,0xf0,0xf0} }, +{ 14, 0x01b0, 0, {0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0} }, +{ 14, 0x01be, 0, {0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0} }, +{ 14, 0x01cc, 0, {0xe5,0xd8,0xc2,0xe3,0xf5,0xd8,0xd0,0xe0,0xd0,0x83,0xd0,0x82,0xd0,0x86} }, +{ 3, 0x01da, 0, {0xd0,0xd0,0x32} }, +{ 8, 0x01dd, 0, {0x75,0x86,0x00,0x90,0xff,0xc3,0x7c,0x05} }, +{ 7, 0x01e5, 0, {0xa3,0xe5,0x82,0x45,0x83,0x70,0xf9} }, +{ 1, 0x01ec, 0, {0x22} }, +{ 14, 0x01ed, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0x02,0xc0,0x03,0xc0,0xd0} }, +{ 14, 0x01fb, 0, {0x75,0xd0,0x00,0xc0,0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91} }, +{ 13, 0x0209, 0, {0x90,0x88,0x00,0xe0,0xf5,0x41,0x90,0x7f,0xab,0x74,0x02,0xf0,0x90} }, +{ 9, 0x0216, 0, {0x7f,0xab,0x74,0x02,0xf0,0xe5,0x32,0x60,0x21} }, +{ 4, 0x021f, 0, {0x7a,0x00,0x7b,0x00} }, +{ 11, 0x0223, 0, {0xc3,0xea,0x94,0x18,0xeb,0x64,0x80,0x94,0x80,0x50,0x12} }, +{ 14, 0x022e, 0, {0x90,0x7f,0x69,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x0a,0xba,0x00} }, +{ 2, 0x023c, 0, {0x01,0x0b} }, +{ 2, 0x023e, 0, {0x80,0xe3} }, +{ 2, 0x0240, 0, {0xd0,0x86} }, +{ 14, 0x0242, 0, {0xd0,0xd0,0xd0,0x03,0xd0,0x02,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0} }, +{ 1, 0x0250, 0, {0x32} }, +{ 14, 0x0251, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} }, +{ 14, 0x025f, 0, {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90,0x7f,0xab,0x74} }, +{ 4, 0x026d, 0, {0x04,0xf0,0xd0,0x86} }, +{ 11, 0x0271, 0, {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} }, +{ 14, 0x027c, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0x02,0xc0,0x03,0xc0,0x04} }, +{ 14, 0x028a, 0, {0xc0,0x05,0xc0,0x06,0xc0,0x07,0xc0,0x00,0xc0,0x01,0xc0,0xd0,0x75,0xd0} }, +{ 13, 0x0298, 0, {0x00,0xc0,0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90} }, +{ 12, 0x02a5, 0, {0x7f,0xab,0x74,0x08,0xf0,0x75,0x6e,0x00,0x75,0x6f,0x02,0x12} }, +{ 6, 0x02b1, 0, {0x11,0x44,0x75,0x70,0x39,0x75} }, +{ 6, 0x02b7, 0, {0x71,0x0c,0x75,0x72,0x02,0x12} }, +{ 12, 0x02bd, 0, {0x11,0x75,0x90,0x7f,0xd6,0xe4,0xf0,0x75,0xd8,0x20,0xd0,0x86} }, +{ 14, 0x02c9, 0, {0xd0,0xd0,0xd0,0x01,0xd0,0x00,0xd0,0x07,0xd0,0x06,0xd0,0x05,0xd0,0x04} }, +{ 13, 0x02d7, 0, {0xd0,0x03,0xd0,0x02,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} }, +{ 14, 0x02e4, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} }, +{ 14, 0x02f2, 0, {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90,0x7f,0xab,0x74} }, +{ 4, 0x0300, 0, {0x10,0xf0,0xd0,0x86} }, +{ 11, 0x0304, 0, {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} }, +{ 14, 0x030f, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0x02,0xc0,0x03,0xc0,0x04} }, +{ 14, 0x031d, 0, {0xc0,0x05,0xc0,0x06,0xc0,0x07,0xc0,0x00,0xc0,0x01,0xc0,0xd0,0x75,0xd0} }, +{ 12, 0x032b, 0, {0x00,0xc0,0x86,0x75,0x86,0x00,0x75,0x6e,0x00,0x75,0x6f,0x02} }, +{ 7, 0x0337, 0, {0x12,0x11,0x44,0x75,0x70,0x40,0x75} }, +{ 6, 0x033e, 0, {0x71,0x0c,0x75,0x72,0x02,0x12} }, +{ 14, 0x0344, 0, {0x11,0x75,0x90,0x7f,0xd6,0x74,0x02,0xf0,0x90,0x7f,0xd6,0x74,0x06,0xf0} }, +{ 5, 0x0352, 0, {0x75,0xd8,0x10,0xd0,0x86} }, +{ 14, 0x0357, 0, {0xd0,0xd0,0xd0,0x01,0xd0,0x00,0xd0,0x07,0xd0,0x06,0xd0,0x05,0xd0,0x04} }, +{ 13, 0x0365, 0, {0xd0,0x03,0xd0,0x02,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} }, +{ 13, 0x0372, 0, {0x90,0x7f,0xa5,0x74,0x80,0xf0,0x90,0x7f,0xa6,0x74,0x9a,0xf0,0x12} }, +{ 12, 0x037f, 0, {0x10,0x1b,0x90,0x7f,0xa6,0xe5,0x42,0xf0,0x12,0x10,0x1b,0x90} }, +{ 13, 0x038b, 0, {0x7f,0xa6,0xe5,0x43,0xf0,0x12,0x10,0x1b,0x90,0x7f,0xa5,0x74,0x40} }, +{ 1, 0x0398, 0, {0xf0} }, +{ 1, 0x0399, 0, {0x22} }, +{ 13, 0x039a, 0, {0x90,0x7f,0xa5,0x74,0x80,0xf0,0x90,0x7f,0xa6,0x74,0x9a,0xf0,0x12} }, +{ 12, 0x03a7, 0, {0x10,0x1b,0x90,0x7f,0xa6,0xe5,0x44,0xf0,0x12,0x10,0x1b,0x90} }, +{ 12, 0x03b3, 0, {0x7f,0xa6,0xe5,0x45,0xf0,0x12,0x10,0x1b,0x90,0x7f,0xa6,0xe5} }, +{ 11, 0x03bf, 0, {0x46,0xf0,0x12,0x10,0x1b,0x90,0x7f,0xa5,0x74,0x40,0xf0} }, +{ 1, 0x03ca, 0, {0x22} }, +{ 10, 0x03cb, 0, {0x75,0x44,0x02,0x75,0x45,0x00,0x75,0x46,0x00,0x12} }, +{ 9, 0x03d5, 0, {0x03,0x9a,0x75,0x42,0x03,0x75,0x43,0x00,0x12} }, +{ 2, 0x03de, 0, {0x03,0x72} }, +{ 1, 0x03e0, 0, {0x22} }, +{ 12, 0x03e1, 0, {0x90,0x88,0x00,0xe5,0x36,0xf0,0x90,0x88,0x00,0x74,0x10,0x25} }, +{ 9, 0x03ed, 0, {0x36,0xf0,0x12,0x01,0xdd,0x75,0x42,0x01,0x75} }, +{ 9, 0x03f6, 0, {0x43,0x18,0x12,0x03,0x72,0x75,0x44,0x02,0x75} }, +{ 9, 0x03ff, 0,{0x45,0x00,0x75,0x46,0x00,0x12,0x03,0x9a,0x75} }, +{ 8, 0x0408, 0,{0x42,0x03,0x75,0x43,0x44,0x12,0x03,0x72} }, +{ 1, 0x0410, 0,{0x22} }, +{ 14, 0x0411, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} }, +{ 14, 0x041f, 0, {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90,0x7f,0xaa,0x74} }, +{ 4, 0x042d, 0, {0x02,0xf0,0xd0,0x86} }, +{ 11, 0x0431, 0, {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} }, +{ 14, 0x043c, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} }, +{ 14, 0x044a, 0, {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90,0x7f,0xa9,0x74} }, +{ 7, 0x0458, 0, {0x04,0xf0,0x75,0x30,0x01,0xd0,0x86} }, +{ 11, 0x045f, 0, {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} }, +{ 14, 0x046a, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} }, +{ 14, 0x0478, 0, {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90,0x7f,0xaa,0x74} }, +{ 7, 0x0486, 0, {0x04,0xf0,0x75,0x31,0x01,0xd0,0x86} }, +{ 11, 0x048d, 0, {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} }, +{ 14, 0x0498, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} }, +{ 12, 0x04a6, 0, {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe5,0xf5,0x91,0xd0,0x86} }, +{ 11, 0x04b2, 0, {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} }, +{ 14, 0x04bd, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} }, +{ 12, 0x04cb, 0, {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe7,0xf5,0x91,0xd0,0x86} }, +{ 11, 0x04d7, 0, {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} }, +{ 12, 0x04e2, 0, {0x90,0x7f,0xea,0xe0,0xfa,0x8a,0x20,0x90,0x7f,0x96,0xe4,0xf0} }, +{ 1, 0x04ee, 0, {0x22} }, +{ 7, 0x04ef, 0, {0x90,0x7f,0xea,0xe0,0xfa,0x8a,0x21} }, +{ 1, 0x04f6, 0, {0x22} }, +{ 14, 0x04f7, 0, {0x90,0x17,0x13,0xe0,0xfa,0x90,0x17,0x15,0xe0,0xfb,0x74,0x80,0x2a,0xfa} }, +{ 14, 0x0505, 0, {0x74,0x80,0x2b,0xfb,0xea,0x03,0x03,0x54,0x3f,0xfc,0xea,0xc4,0x23,0x54} }, +{ 14, 0x0513, 0, {0x1f,0xfa,0x2c,0xfa,0xeb,0x03,0x03,0x54,0x3f,0xfc,0xeb,0xc4,0x23,0x54} }, +{ 11, 0x0521, 0, {0x1f,0xfb,0x2c,0xfb,0x90,0x17,0x0a,0xe0,0xfc,0x60,0x02} }, +{ 2, 0x052c, 0, {0x7a,0x00} }, +{ 7, 0x052e, 0, {0x90,0x17,0x0c,0xe0,0xfc,0x60,0x02} }, +{ 2, 0x0535, 0, {0x7b,0x00} }, +{ 11, 0x0537, 0, {0xea,0x2b,0xfc,0xc3,0x13,0xf5,0x3a,0x75,0x44,0x02,0x8b} }, +{ 7, 0x0542, 0, {0x45,0x8a,0x46,0x12,0x03,0x9a,0x75} }, +{ 9, 0x0549, 0, {0x6e,0x08,0x75,0x6f,0x00,0x12,0x11,0x44,0x75} }, +{ 4, 0x0552, 0, {0x70,0x47,0x75,0x71} }, +{ 8, 0x0556, 0, {0x0c,0x75,0x72,0x02,0x12,0x11,0x75,0x85} }, +{ 5, 0x055e, 0, {0x3a,0x73,0x12,0x11,0xa0} }, +{ 1, 0x0563, 0, {0x22} }, +{ 14, 0x0564, 0, {0x90,0x7f,0x96,0xe0,0xfa,0x90,0x7f,0x96,0x74,0x80,0x65,0x02,0xf0,0x90} }, +{ 14, 0x0572, 0, {0x7f,0xeb,0xe0,0xfa,0x90,0x7f,0xea,0xe0,0xfb,0x90,0x7f,0xef,0xe0,0xfc} }, +{ 14, 0x0580, 0, {0x33,0x95,0xe0,0xfd,0x8c,0x05,0x7c,0x00,0x90,0x7f,0xee,0xe0,0xfe,0x33} }, +{ 14, 0x058e, 0, {0x95,0xe0,0xff,0xec,0x2e,0xfc,0xed,0x3f,0xfd,0x90,0x7f,0xe9,0xe0,0xfe} }, +{ 5, 0x059c, 0, {0xbe,0x01,0x02,0x80,0x03} }, +{ 3, 0x05a1, 0, {0x02,0x05,0xf9} }, +{ 6, 0x05a4, 0, {0xbc,0x01,0x21,0xbd,0x00,0x1e} }, +{ 14, 0x05aa, 0, {0xea,0xc4,0x03,0x54,0xf8,0xfc,0xeb,0x25,0xe0,0xfd,0x2c,0x24,0x00,0xfc} }, +{ 14, 0x05b8, 0, {0xe4,0x34,0x17,0xfd,0x90,0x7e,0xc0,0xe0,0xfe,0x8c,0x82,0x8d,0x83,0xf0} }, +{ 2, 0x05c6, 0, {0x80,0x31} }, +{ 14, 0x05c8, 0, {0xea,0xc4,0x03,0x54,0xf8,0xfa,0xeb,0x25,0xe0,0xfb,0x2a,0xfa,0x24,0x00} }, +{ 14, 0x05d6, 0, {0xfb,0xe4,0x34,0x17,0xfc,0x90,0x7e,0xc0,0xe0,0xfd,0x8b,0x82,0x8c,0x83} }, +{ 14, 0x05e4, 0, {0xf0,0x74,0x01,0x2a,0x24,0x00,0xfa,0xe4,0x34,0x17,0xfb,0x90,0x7e,0xc1} }, +{ 7, 0x05f2, 0, {0xe0,0xfc,0x8a,0x82,0x8b,0x83,0xf0} }, +{ 3, 0x05f9, 0, {0x75,0x38,0x01} }, +{ 1, 0x05fc, 0, {0x22} }, +{ 14, 0x05fd, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0x02,0xc0,0x03,0xc0,0x04} }, +{ 14, 0x060b, 0, {0xc0,0x05,0xc0,0x06,0xc0,0x07,0xc0,0x00,0xc0,0x01,0xc0,0xd0,0x75,0xd0} }, +{ 13, 0x0619, 0, {0x00,0xc0,0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90} }, +{ 13, 0x0626, 0, {0x7f,0xaa,0x74,0x01,0xf0,0x12,0x05,0x64,0x75,0x37,0x00,0xd0,0x86} }, +{ 14, 0x0633, 0, {0xd0,0xd0,0xd0,0x01,0xd0,0x00,0xd0,0x07,0xd0,0x06,0xd0,0x05,0xd0,0x04} }, +{ 13, 0x0641, 0, {0xd0,0x03,0xd0,0x02,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} }, +{ 14, 0x064e, 0, {0x90,0x7f,0xeb,0xe0,0xfa,0x90,0x7f,0xea,0xe0,0xfb,0x90,0x7f,0xee,0xe0} }, +{ 14, 0x065c, 0, {0xfc,0x33,0x95,0xe0,0xfd,0x90,0x7f,0x96,0xe0,0xfe,0x90,0x7f,0x96,0x74} }, +{ 14, 0x066a, 0, {0x80,0x65,0x06,0xf0,0x90,0x7f,0x00,0x74,0x01,0xf0,0xea,0xc4,0x03,0x54} }, +{ 14, 0x0678, 0, {0xf8,0xfe,0xeb,0x25,0xe0,0xfb,0x2e,0xfe,0x24,0x00,0xfb,0xe4,0x34,0x17} }, +{ 14, 0x0686, 0, {0xff,0x8b,0x82,0x8f,0x83,0xe0,0xfb,0x74,0x01,0x2e,0x24,0x00,0xfe,0xe4} }, +{ 14, 0x0694, 0, {0x34,0x17,0xff,0x8e,0x82,0x8f,0x83,0xe0,0xfe,0x90,0x7f,0xe9,0xe0,0xff} }, +{ 3, 0x06a2, 0, {0xbf,0x81,0x0a} }, +{ 10, 0x06a5, 0, {0x90,0x7f,0x00,0xeb,0xf0,0x90,0x7f,0x01,0xee,0xf0} }, +{ 8, 0x06af, 0, {0x90,0x7f,0xe9,0xe0,0xfb,0xbb,0x82,0x1a} }, +{ 3, 0x06b7, 0, {0xba,0x01,0x0c} }, +{ 12, 0x06ba, 0, {0x90,0x7f,0x00,0xe4,0xf0,0x90,0x7f,0x01,0xe4,0xf0,0x80,0x0b} }, +{ 11, 0x06c6, 0, {0x90,0x7f,0x00,0xe4,0xf0,0x90,0x7f,0x01,0x74,0xb5,0xf0} }, +{ 8, 0x06d1, 0, {0x90,0x7f,0xe9,0xe0,0xfb,0xbb,0x83,0x1b} }, +{ 3, 0x06d9, 0, {0xba,0x01,0x0d} }, +{ 13, 0x06dc, 0, {0x90,0x7f,0x00,0x74,0x01,0xf0,0x90,0x7f,0x01,0xe4,0xf0,0x80,0x0b} }, +{ 11, 0x06e9, 0, {0x90,0x7f,0x00,0xe4,0xf0,0x90,0x7f,0x01,0x74,0x12,0xf0} }, +{ 8, 0x06f4, 0, {0x90,0x7f,0xe9,0xe0,0xfb,0xbb,0x84,0x1c} }, +{ 3, 0x06fc, 0, {0xba,0x01,0x0d} }, +{ 13, 0x06ff, 0, {0x90,0x7f,0x00,0x74,0x01,0xf0,0x90,0x7f,0x01,0xe4,0xf0,0x80,0x0c} }, +{ 12, 0x070c, 0, {0x90,0x7f,0x00,0x74,0x80,0xf0,0x90,0x7f,0x01,0x74,0x01,0xf0} }, +{ 5, 0x0718, 0, {0x90,0x7f,0xb5,0xec,0xf0} }, +{ 1, 0x071d, 0, {0x22} }, +{ 12, 0x071e, 0, {0x75,0x36,0x0d,0x90,0x88,0x00,0x74,0x1d,0xf0,0x75,0x6b,0x80} }, +{ 10, 0x072a, 0, {0x75,0x6c,0x3c,0x12,0x10,0xe2,0x75,0x6b,0x80,0x75} }, +{ 9, 0x0734, 0, {0x6c,0x0f,0x12,0x10,0xe2,0x75,0x6b,0x80,0x75} }, +{ 9, 0x073d, 0, {0x6c,0x06,0x12,0x10,0xe2,0x75,0x6b,0x80,0x75} }, +{ 7, 0x0746, 0, {0x6c,0x01,0x12,0x10,0xe2,0x7a,0x00} }, +{ 3, 0x074d, 0, {0xba,0xff,0x00} }, +{ 2, 0x0750, 0, {0x50,0x0a} }, +{ 10, 0x0752, 0, {0xc0,0x02,0x12,0x01,0xdd,0xd0,0x02,0x0a,0x80,0xf1} }, +{ 10, 0x075c, 0, {0x75,0x6b,0x80,0x75,0x6c,0x3c,0x12,0x10,0xe2,0x75} }, +{ 8, 0x0766, 0, {0x6b,0x80,0x75,0x6c,0x0f,0x12,0x10,0xe2} }, +{ 1, 0x076e, 0, {0x22} }, +{ 14, 0x076f, 0, {0x90,0x7f,0xa1,0xe4,0xf0,0x90,0x7f,0xaf,0x74,0x01,0xf0,0x90,0x7f,0x92} }, +{ 14, 0x077d, 0, {0x74,0x02,0xf0,0x75,0x8e,0x31,0x75,0x89,0x21,0x75,0x88,0x00,0x75,0xc8} }, +{ 14, 0x078b, 0, {0x00,0x75,0x8d,0x40,0x75,0x98,0x40,0x75,0xc0,0x40,0x75,0x87,0x00,0x75} }, +{ 9, 0x0799, 0, {0x20,0x00,0x75,0x21,0x00,0x75,0x22,0x00,0x75} }, +{ 5, 0x07a2, 0, {0x23,0x00,0x75,0x47,0x00} }, +{ 7, 0x07a7, 0, {0xc3,0xe5,0x47,0x94,0x20,0x50,0x11} }, +{ 13, 0x07ae, 0, {0xe5,0x47,0x24,0x00,0xf5,0x82,0xe4,0x34,0x17,0xf5,0x83,0xe4,0xf0} }, +{ 4, 0x07bb, 0, {0x05,0x47,0x80,0xe8} }, +{ 9, 0x07bf, 0, {0xe4,0xf5,0x40,0xf5,0x3f,0xe4,0xf5,0x3c,0xf5} }, +{ 7, 0x07c8, 0, {0x3b,0xe4,0xf5,0x3e,0xf5,0x3d,0x75} }, +{ 11, 0x07cf, 0, {0x32,0x00,0x75,0x37,0x00,0x75,0x39,0x00,0x90,0x7f,0x93} }, +{ 14, 0x07da, 0, {0x74,0x3c,0xf0,0x90,0x7f,0x9c,0x74,0xff,0xf0,0x90,0x7f,0x96,0x74,0x80} }, +{ 14, 0x07e8, 0, {0xf0,0x90,0x7f,0x94,0x74,0x70,0xf0,0x90,0x7f,0x9d,0x74,0x8f,0xf0,0x90} }, +{ 14, 0x07f6, 0, {0x7f,0x97,0xe4,0xf0,0x90,0x7f,0x95,0x74,0xc2,0xf0,0x90,0x7f,0x98,0x74} }, +{ 14, 0x0804, 0, {0x28,0xf0,0x90,0x7f,0x9e,0x74,0x28,0xf0,0x90,0x7f,0xf0,0xe4,0xf0,0x90} }, +{ 14, 0x0812, 0, {0x7f,0xf1,0xe4,0xf0,0x90,0x7f,0xf2,0xe4,0xf0,0x90,0x7f,0xf3,0xe4,0xf0} }, +{ 14, 0x0820, 0, {0x90,0x7f,0xf4,0xe4,0xf0,0x90,0x7f,0xf5,0xe4,0xf0,0x90,0x7f,0xf6,0xe4} }, +{ 14, 0x082e, 0, {0xf0,0x90,0x7f,0xf7,0xe4,0xf0,0x90,0x7f,0xf8,0xe4,0xf0,0x90,0x7f,0xf9} }, +{ 14, 0x083c, 0, {0x74,0x38,0xf0,0x90,0x7f,0xfa,0x74,0xa0,0xf0,0x90,0x7f,0xfb,0x74,0xa0} }, +{ 14, 0x084a, 0, {0xf0,0x90,0x7f,0xfc,0x74,0xa0,0xf0,0x90,0x7f,0xfd,0x74,0xa0,0xf0,0x90} }, +{ 14, 0x0858, 0, {0x7f,0xfe,0x74,0xa0,0xf0,0x90,0x7f,0xff,0x74,0xa0,0xf0,0x90,0x7f,0xe0} }, +{ 14, 0x0866, 0, {0x74,0x03,0xf0,0x90,0x7f,0xe1,0x74,0x01,0xf0,0x90,0x7f,0xdd,0x74,0x80} }, +{ 11, 0x0874, 0, {0xf0,0x12,0x12,0x43,0x12,0x07,0x1e,0x7a,0x00,0x7b,0x00} }, +{ 9, 0x087f, 0, {0xc3,0xea,0x94,0x1e,0xeb,0x94,0x00,0x50,0x17} }, +{ 12, 0x0888, 0, {0x90,0x88,0x00,0xe0,0xf5,0x47,0x90,0x88,0x0b,0xe0,0xf5,0x47} }, +{ 9, 0x0894, 0, {0x90,0x7f,0x68,0xf0,0x0a,0xba,0x00,0x01,0x0b} }, +{ 2, 0x089d, 0, {0x80,0xe0} }, +{ 12, 0x089f, 0, {0x12,0x03,0xe1,0x90,0x7f,0xd6,0xe4,0xf0,0x7a,0x00,0x7b,0x00} }, +{ 13, 0x08ab, 0, {0x8a,0x04,0x8b,0x05,0xc3,0xea,0x94,0xe0,0xeb,0x94,0x2e,0x50,0x1a} }, +{ 14, 0x08b8, 0, {0xc0,0x02,0xc0,0x03,0xc0,0x04,0xc0,0x05,0x12,0x01,0xdd,0xd0,0x05,0xd0} }, +{ 10, 0x08c6, 0, {0x04,0xd0,0x03,0xd0,0x02,0x0a,0xba,0x00,0x01,0x0b} }, +{ 2, 0x08d0, 0, {0x80,0xd9} }, +{ 13, 0x08d2, 0, {0x90,0x7f,0xd6,0x74,0x02,0xf0,0x90,0x7f,0xd6,0x74,0x06,0xf0,0x90} }, +{ 14, 0x08df, 0, {0x7f,0xde,0x74,0x05,0xf0,0x90,0x7f,0xdf,0x74,0x05,0xf0,0x90,0x7f,0xac} }, +{ 14, 0x08ed, 0, {0xe4,0xf0,0x90,0x7f,0xad,0x74,0x05,0xf0,0x75,0xa8,0x80,0x75,0xf8,0x10} }, +{ 13, 0x08fb, 0, {0x90,0x7f,0xae,0x74,0x0b,0xf0,0x90,0x7f,0xe2,0x74,0x88,0xf0,0x90} }, +{ 12, 0x0908, 0, {0x7f,0xab,0x74,0x08,0xf0,0x75,0xe8,0x11,0x75,0x32,0x01,0x75} }, +{ 12, 0x0914, 0, {0x31,0x00,0x75,0x30,0x00,0xc0,0x04,0xc0,0x05,0x12,0x04,0xf7} }, +{ 10, 0x0920, 0, {0xd0,0x05,0xd0,0x04,0x75,0x34,0x00,0x75,0x35,0x01} }, +{ 13, 0x092a, 0, {0x90,0x7f,0xae,0x74,0x03,0xf0,0x8c,0x02,0xba,0x00,0x02,0x80,0x03} }, +{ 3, 0x0937, 0, {0x02,0x0a,0x3f} }, +{ 12, 0x093a, 0, {0x85,0x33,0x34,0x90,0x7f,0x9d,0x74,0x8f,0xf0,0x90,0x7f,0x97} }, +{ 14, 0x0946, 0, {0x74,0x08,0xf0,0x90,0x7f,0x9d,0x74,0x88,0xf0,0x90,0x7f,0x9a,0xe0,0xfa} }, +{ 12, 0x0954, 0, {0x74,0x05,0x5a,0xf5,0x33,0x90,0x7f,0x9d,0x74,0x8f,0xf0,0x90} }, +{ 13, 0x0960, 0, {0x7f,0x97,0x74,0x02,0xf0,0x90,0x7f,0x9d,0x74,0x82,0xf0,0xe5,0x33} }, +{ 13, 0x096d, 0, {0x25,0xe0,0xfa,0x90,0x7f,0x9a,0xe0,0x54,0x05,0xfb,0x4a,0xf5,0x33} }, +{ 2, 0x097a, 0, {0x60,0x0c} }, +{ 12, 0x097c, 0, {0x90,0x7f,0x96,0xe0,0xfa,0x90,0x7f,0x96,0x74,0x80,0x4a,0xf0} }, +{ 11, 0x0988, 0, {0x75,0x6e,0x00,0x75,0x6f,0x00,0xc0,0x04,0xc0,0x05,0x12} }, +{ 14, 0x0993, 0, {0x11,0x44,0xd0,0x05,0xd0,0x04,0x90,0x17,0x13,0xe0,0xfa,0x74,0x80,0x2a} }, +{ 6, 0x09a1, 0, {0xfa,0xe5,0x33,0xb4,0x04,0x29} }, +{ 3, 0x09a7, 0, {0xba,0xa0,0x00} }, +{ 2, 0x09aa, 0, {0x50,0x24} }, +{ 13, 0x09ac, 0, {0x90,0x17,0x13,0xe0,0x04,0xfb,0x0b,0x90,0x17,0x13,0xeb,0xf0,0x90} }, +{ 14, 0x09b9, 0, {0x17,0x13,0xe0,0xfb,0x90,0x17,0x15,0xf0,0xc0,0x02,0xc0,0x04,0xc0,0x05} }, +{ 9, 0x09c7, 0, {0x12,0x04,0xf7,0xd0,0x05,0xd0,0x04,0xd0,0x02} }, +{ 5, 0x09d0, 0, {0xe5,0x33,0xb4,0x02,0x26} }, +{ 6, 0x09d5, 0, {0xc3,0x74,0x04,0x9a,0x50,0x20} }, +{ 13, 0x09db, 0, {0x90,0x17,0x13,0xe0,0xfa,0x1a,0x1a,0x90,0x17,0x13,0xea,0xf0,0x90} }, +{ 13, 0x09e8, 0, {0x17,0x13,0xe0,0xfa,0x90,0x17,0x15,0xf0,0xc0,0x04,0xc0,0x05,0x12} }, +{ 6, 0x09f5, 0, {0x04,0xf7,0xd0,0x05,0xd0,0x04} }, +{ 5, 0x09fb, 0, {0xe5,0x33,0xb4,0x08,0x1d} }, +{ 4, 0x0a00, 0, {0xe5,0x34,0x70,0x19} }, +{ 10, 0x0a04, 0, {0x74,0x01,0x25,0x35,0x54,0x0f,0xf5,0x35,0x85,0x35} }, +{ 12, 0x0a0e, 0, {0x75,0x75,0x76,0x00,0xc0,0x04,0xc0,0x05,0x12,0x13,0xfe,0xd0} }, +{ 3, 0x0a1a, 0, {0x05,0xd0,0x04} }, +{ 5, 0x0a1d, 0, {0xe5,0x33,0xb4,0x01,0x1d} }, +{ 4, 0x0a22, 0, {0xe5,0x34,0x70,0x19} }, +{ 10, 0x0a26, 0, {0xe5,0x35,0x24,0xff,0x54,0x0f,0xf5,0x35,0x85,0x35} }, +{ 12, 0x0a30, 0, {0x75,0x75,0x76,0x00,0xc0,0x04,0xc0,0x05,0x12,0x13,0xfe,0xd0} }, +{ 3, 0x0a3c, 0, {0x05,0xd0,0x04} }, +{ 14, 0x0a3f, 0, {0xc0,0x04,0xc0,0x05,0x12,0x01,0xdd,0xd0,0x05,0xd0,0x04,0x90,0x7f,0x96} }, +{ 14, 0x0a4d, 0, {0xe0,0xfa,0x90,0x7f,0x96,0x74,0x7f,0x5a,0xf0,0x90,0x7f,0x97,0x74,0x08} }, +{ 10, 0x0a5b, 0, {0xf0,0xc3,0xec,0x94,0x00,0xed,0x94,0x02,0x40,0x08} }, +{ 8, 0x0a65, 0, {0x90,0x7f,0x96,0xe0,0xfa,0x20,0xe6,0x08} }, +{ 8, 0x0a6d, 0, {0xc3,0xe4,0x9c,0x74,0x08,0x9d,0x50,0x13} }, +{ 14, 0x0a75, 0, {0x90,0x7f,0x96,0xe0,0xfa,0x90,0x7f,0x96,0x74,0x40,0x65,0x02,0xf0,0x7c} }, +{ 5, 0x0a83, 0, {0x00,0x7d,0x00,0x80,0x05} }, +{ 5, 0x0a88, 0, {0x0c,0xbc,0x00,0x01,0x0d} }, +{ 5, 0x0a8d, 0, {0xe5,0x38,0xb4,0x01,0x0e} }, +{ 13, 0x0a92, 0, {0xc0,0x04,0xc0,0x05,0x12,0x04,0xf7,0xd0,0x05,0xd0,0x04,0x75,0x38} }, +{ 1, 0x0a9f, 0, {0x00} }, +{ 7, 0x0aa0, 0, {0xe5,0x31,0x70,0x03,0x02,0x09,0x2a} }, +{ 10, 0x0aa7, 0, {0x90,0x7f,0xc9,0xe0,0xfa,0x70,0x03,0x02,0x0c,0x2d} }, +{ 14, 0x0ab1, 0, {0x90,0x7f,0x96,0xe0,0xfa,0x90,0x7f,0x96,0x74,0x80,0x65,0x02,0xf0,0x90} }, +{ 9, 0x0abf, 0, {0x7d,0xc0,0xe0,0xfa,0xba,0x2c,0x02,0x80,0x03} }, +{ 3, 0x0ac8, 0, {0x02,0x0b,0x36} }, +{ 5, 0x0acb, 0, {0x75,0x32,0x00,0x7b,0x00} }, +{ 3, 0x0ad0, 0, {0xbb,0x64,0x00} }, +{ 2, 0x0ad3, 0, {0x50,0x1c} }, +{ 14, 0x0ad5, 0, {0xc0,0x02,0xc0,0x03,0xc0,0x04,0xc0,0x05,0x12,0x01,0xdd,0xd0,0x05,0xd0} }, +{ 13, 0x0ae3, 0, {0x04,0xd0,0x03,0xd0,0x02,0x90,0x88,0x0f,0xe0,0xf5,0x47,0x0b,0x80} }, +{ 1, 0x0af0, 0, {0xdf} }, +{ 13, 0x0af1, 0, {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x07,0x1e,0x12,0x03,0xe1,0x12} }, +{ 12, 0x0afe, 0, {0x04,0xf7,0xd0,0x05,0xd0,0x04,0xd0,0x02,0x75,0x6e,0x00,0x75} }, +{ 13, 0x0b0a, 0, {0x6f,0x01,0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x11,0x44,0xd0,0x05} }, +{ 9, 0x0b17, 0, {0xd0,0x04,0xd0,0x02,0x75,0x70,0x4d,0x75,0x71} }, +{ 11, 0x0b20, 0, {0x0c,0x75,0x72,0x02,0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12} }, +{ 11, 0x0b2b, 0, {0x11,0x75,0xd0,0x05,0xd0,0x04,0xd0,0x02,0x02,0x0c,0x2d} }, +{ 3, 0x0b36, 0, {0xba,0x2a,0x3b} }, +{ 13, 0x0b39, 0, {0x90,0x7f,0x98,0x74,0x20,0xf0,0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12} }, +{ 14, 0x0b46, 0, {0x01,0xdd,0xd0,0x05,0xd0,0x04,0xd0,0x02,0x90,0x7f,0x98,0x74,0x28,0xf0} }, +{ 2, 0x0b54, 0, {0x7b,0x00} }, +{ 3, 0x0b56, 0, {0xbb,0x0a,0x00} }, +{ 5, 0x0b59, 0, {0x40,0x03,0x02,0x0c,0x2d} }, +{ 14, 0x0b5e, 0, {0xc0,0x02,0xc0,0x03,0xc0,0x04,0xc0,0x05,0x12,0x01,0xdd,0xd0,0x05,0xd0} }, +{ 8, 0x0b6c, 0, {0x04,0xd0,0x03,0xd0,0x02,0x0b,0x80,0xe2} }, +{ 3, 0x0b74, 0, {0xba,0x2b,0x1a} }, +{ 8, 0x0b77, 0, {0x90,0x7f,0xc9,0xe0,0xfb,0xbb,0x40,0x12} }, +{ 14, 0x0b7f, 0, {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x12,0x05,0xd0,0x05,0xd0,0x04,0xd0} }, +{ 4, 0x0b8d, 0, {0x02,0x02,0x0c,0x2d} }, +{ 3, 0x0b91, 0, {0xba,0x10,0x1f} }, +{ 14, 0x0b94, 0, {0x90,0x7f,0x96,0xe0,0xfb,0x90,0x7f,0x96,0x74,0x80,0x65,0x03,0xf0,0xc0} }, +{ 14, 0x0ba2, 0, {0x02,0xc0,0x04,0xc0,0x05,0x12,0x10,0x3d,0xd0,0x05,0xd0,0x04,0xd0,0x02} }, +{ 3, 0x0bb0, 0, {0x02,0x0c,0x2d} }, +{ 3, 0x0bb3, 0, {0xba,0x11,0x12} }, +{ 14, 0x0bb6, 0, {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x10,0x6a,0xd0,0x05,0xd0,0x04,0xd0} }, +{ 4, 0x0bc4, 0, {0x02,0x02,0x0c,0x2d} }, +{ 3, 0x0bc8, 0, {0xba,0x12,0x12} }, +{ 14, 0x0bcb, 0, {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x10,0x8f,0xd0,0x05,0xd0,0x04,0xd0} }, +{ 4, 0x0bd9, 0, {0x02,0x02,0x0c,0x2d} }, +{ 3, 0x0bdd, 0, {0xba,0x13,0x0b} }, +{ 11, 0x0be0, 0, {0x90,0x7d,0xc1,0xe0,0xfb,0x90,0x88,0x00,0xf0,0x80,0x42} }, +{ 3, 0x0beb, 0, {0xba,0x14,0x11} }, +{ 14, 0x0bee, 0, {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x11,0xdd,0xd0,0x05,0xd0,0x04,0xd0} }, +{ 3, 0x0bfc, 0, {0x02,0x80,0x2e} }, +{ 3, 0x0bff, 0, {0xba,0x15,0x1d} }, +{ 12, 0x0c02, 0, {0x90,0x7d,0xc1,0xe0,0xf5,0x75,0x90,0x7d,0xc2,0xe0,0xf5,0x76} }, +{ 14, 0x0c0e, 0, {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x13,0xfe,0xd0,0x05,0xd0,0x04,0xd0} }, +{ 3, 0x0c1c, 0, {0x02,0x80,0x0e} }, +{ 3, 0x0c1f, 0, {0xba,0x16,0x0b} }, +{ 11, 0x0c22, 0, {0xc0,0x04,0xc0,0x05,0x12,0x13,0xa3,0xd0,0x05,0xd0,0x04} }, +{ 11, 0x0c2d, 0, {0x90,0x7f,0xc9,0xe4,0xf0,0x75,0x31,0x00,0x02,0x09,0x2a} }, +{ 1, 0x0c38, 0, {0x22} }, +{ 7, 0x0c39, 0, {0x53,0x55,0x50,0x45,0x4e,0x44,0x00} }, +{ 7, 0x0c40, 0, {0x52,0x45,0x53,0x55,0x4d,0x45,0x00} }, +{ 6, 0x0c47, 0, {0x20,0x56,0x6f,0x6c,0x20,0x00} }, +{ 13, 0x0c4d, 0, {0x44,0x41,0x42,0x55,0x53,0x42,0x20,0x76,0x31,0x2e,0x30,0x30,0x00} }, +{ 14, 0x0c5a, 0, {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0x02,0xc0,0x03,0xc0,0x04} }, +{ 14, 0x0c68, 0, {0xc0,0x05,0xc0,0x06,0xc0,0x07,0xc0,0x00,0xc0,0x01,0xc0,0xd0,0x75,0xd0} }, +{ 13, 0x0c76, 0, {0x00,0xc0,0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90} }, +{ 14, 0x0c83, 0, {0x7f,0xab,0x74,0x01,0xf0,0x90,0x7f,0xe8,0xe0,0xfa,0x90,0x7f,0xe9,0xe0} }, +{ 6, 0x0c91, 0, {0xfb,0xbb,0x00,0x02,0x80,0x03} }, +{ 3, 0x0c97, 0, {0x02,0x0d,0x38} }, +{ 3, 0x0c9a, 0, {0xba,0x80,0x14} }, +{ 14, 0x0c9d, 0, {0x90,0x7f,0x00,0x74,0x01,0xf0,0x90,0x7f,0x01,0xe4,0xf0,0x90,0x7f,0xb5} }, +{ 6, 0x0cab, 0, {0x74,0x02,0xf0,0x02,0x0e,0xcd} }, +{ 5, 0x0cb1, 0, {0xba,0x82,0x02,0x80,0x03} }, +{ 3, 0x0cb6, 0, {0x02,0x0d,0x1d} }, +{ 8, 0x0cb9, 0, {0x90,0x7f,0xec,0xe0,0xfc,0xbc,0x01,0x00} }, +{ 2, 0x0cc1, 0, {0x40,0x21} }, +{ 6, 0x0cc3, 0, {0xc3,0x74,0x07,0x9c,0x40,0x1b} }, +{ 14, 0x0cc9, 0, {0xec,0x24,0xff,0x25,0xe0,0xfd,0x24,0xc6,0xf5,0x82,0xe4,0x34,0x7f,0xf5} }, +{ 13, 0x0cd7, 0, {0x83,0xe0,0xfd,0x53,0x05,0x01,0x90,0x7f,0x00,0xed,0xf0,0x80,0x2b} }, +{ 3, 0x0ce4, 0, {0xbc,0x81,0x00} }, +{ 2, 0x0ce7, 0, {0x40,0x21} }, +{ 6, 0x0ce9, 0, {0xc3,0x74,0x87,0x9c,0x40,0x1b} }, +{ 14, 0x0cef, 0, {0xec,0x24,0x7f,0x25,0xe0,0xfc,0x24,0xb6,0xf5,0x82,0xe4,0x34,0x7f,0xf5} }, +{ 13, 0x0cfd, 0, {0x83,0xe0,0xfc,0x53,0x04,0x01,0x90,0x7f,0x00,0xec,0xf0,0x80,0x05} }, +{ 5, 0x0d0a, 0, {0x90,0x7f,0x00,0xe4,0xf0} }, +{ 14, 0x0d0f, 0, {0x90,0x7f,0x01,0xe4,0xf0,0x90,0x7f,0xb5,0x74,0x02,0xf0,0x02,0x0e,0xcd} }, +{ 5, 0x0d1d, 0, {0xba,0x81,0x02,0x80,0x03} }, +{ 3, 0x0d22, 0, {0x02,0x0e,0xc5} }, +{ 14, 0x0d25, 0, {0x90,0x7f,0x00,0xe4,0xf0,0x90,0x7f,0x01,0xe4,0xf0,0x90,0x7f,0xb5,0x74} }, +{ 5, 0x0d33, 0, {0x02,0xf0,0x02,0x0e,0xcd} }, +{ 3, 0x0d38, 0, {0xbb,0x01,0x2d} }, +{ 6, 0x0d3b, 0, {0xba,0x00,0x03,0x02,0x0e,0xcd} }, +{ 3, 0x0d41, 0, {0xba,0x02,0x11} }, +{ 13, 0x0d44, 0, {0x75,0x59,0x00,0xc0,0x02,0xc0,0x03,0x12,0x0e,0xf0,0xd0,0x03,0xd0} }, +{ 4, 0x0d51, 0, {0x02,0x02,0x0e,0xcd} }, +{ 5, 0x0d55, 0, {0xba,0x21,0x02,0x80,0x03} }, +{ 3, 0x0d5a, 0, {0x02,0x0e,0xcd} }, +{ 11, 0x0d5d, 0, {0x75,0x37,0x01,0x90,0x7f,0xc5,0xe4,0xf0,0x02,0x0e,0xcd} }, +{ 3, 0x0d68, 0, {0xbb,0x03,0x1f} }, +{ 6, 0x0d6b, 0, {0xba,0x00,0x03,0x02,0x0e,0xcd} }, +{ 5, 0x0d71, 0, {0xba,0x02,0x02,0x80,0x03} }, +{ 3, 0x0d76, 0, {0x02,0x0e,0xcd} }, +{ 13, 0x0d79, 0, {0x75,0x59,0x01,0xc0,0x02,0xc0,0x03,0x12,0x0e,0xf0,0xd0,0x03,0xd0} }, +{ 4, 0x0d86, 0, {0x02,0x02,0x0e,0xcd} }, +{ 3, 0x0d8a, 0, {0xbb,0x06,0x54} }, +{ 5, 0x0d8d, 0, {0xba,0x80,0x02,0x80,0x03} }, +{ 3, 0x0d92, 0, {0x02,0x0e,0xc5} }, +{ 8, 0x0d95, 0, {0x90,0x7f,0xeb,0xe0,0xfc,0xbc,0x01,0x15} }, +{ 12, 0x0d9d, 0, {0x7c,0xfb,0x7d,0x0f,0x8d,0x06,0x7f,0x00,0x90,0x7f,0xd4,0xee} }, +{ 9, 0x0da9, 0, {0xf0,0x90,0x7f,0xd5,0xec,0xf0,0x02,0x0e,0xcd} }, +{ 10, 0x0db2, 0, {0x90,0x7f,0xeb,0xe0,0xfc,0xbc,0x02,0x02,0x80,0x03} }, +{ 3, 0x0dbc, 0, {0x02,0x0e,0xc5} }, +{ 10, 0x0dbf, 0, {0x90,0x7f,0xea,0xe0,0xfc,0xbc,0x00,0x02,0x80,0x03} }, +{ 3, 0x0dc9, 0, {0x02,0x0e,0xc5} }, +{ 12, 0x0dcc, 0, {0x7c,0x3b,0x7d,0x0f,0x8d,0x06,0x7f,0x00,0x90,0x7f,0xd4,0xee} }, +{ 9, 0x0dd8, 0, {0xf0,0x90,0x7f,0xd5,0xec,0xf0,0x02,0x0e,0xcd} }, +{ 6, 0x0de1, 0, {0xbb,0x07,0x03,0x02,0x0e,0xc5} }, +{ 3, 0x0de7, 0, {0xbb,0x08,0x10} }, +{ 13, 0x0dea, 0, {0xac,0x48,0x90,0x7f,0x00,0xec,0xf0,0x90,0x7f,0xb5,0x74,0x01,0xf0} }, +{ 3, 0x0df7, 0, {0x02,0x0e,0xcd} }, +{ 3, 0x0dfa, 0, {0xbb,0x09,0x31} }, +{ 5, 0x0dfd, 0, {0xba,0x00,0x02,0x80,0x03} }, +{ 3, 0x0e02, 0, {0x02,0x0e,0xc5} }, +{ 14, 0x0e05, 0, {0x90,0x7f,0xea,0xe0,0xfc,0xc3,0x74,0x01,0x9c,0x50,0x03,0x02,0x0e,0xc5} }, +{ 8, 0x0e13, 0, {0x90,0x7f,0xea,0xe0,0xfc,0xbc,0x00,0x0a} }, +{ 10, 0x0e1b, 0, {0x90,0x17,0x21,0xe4,0xf0,0x90,0x17,0x22,0xe4,0xf0} }, +{ 9, 0x0e25, 0, {0x90,0x7f,0xea,0xe0,0xf5,0x48,0x02,0x0e,0xcd} }, +{ 3, 0x0e2e, 0, {0xbb,0x0a,0x27} }, +{ 5, 0x0e31, 0, {0xba,0x81,0x02,0x80,0x03} }, +{ 3, 0x0e36, 0, {0x02,0x0e,0xc5} }, +{ 14, 0x0e39, 0, {0x90,0x7f,0xec,0xe0,0xfa,0x24,0x20,0xfa,0xe4,0x34,0x17,0xfc,0x8a,0x82} }, +{ 14, 0x0e47, 0, {0x8c,0x83,0xe0,0xfa,0x90,0x7f,0x00,0xf0,0x90,0x7f,0xb5,0x74,0x01,0xf0} }, +{ 3, 0x0e55, 0, {0x02,0x0e,0xcd} }, +{ 5, 0x0e58, 0, {0xbb,0x0b,0x02,0x80,0x03} }, +{ 3, 0x0e5d, 0, {0x02,0x0e,0xa9} }, +{ 13, 0x0e60, 0, {0x90,0x17,0x20,0xe4,0xf0,0x90,0x7f,0xec,0xe0,0xfa,0xba,0x01,0x1a} }, +{ 8, 0x0e6d, 0, {0x90,0x7f,0xed,0xe0,0xfa,0xba,0x00,0x12} }, +{ 14, 0x0e75, 0, {0x90,0x7f,0xea,0xe0,0xfa,0x90,0x17,0x21,0xf0,0xc0,0x03,0x12,0x04,0xe2} }, +{ 4, 0x0e83, 0, {0xd0,0x03,0x80,0x46} }, +{ 8, 0x0e87, 0, {0x90,0x7f,0xec,0xe0,0xfa,0xba,0x02,0x3e} }, +{ 8, 0x0e8f, 0, {0x90,0x7f,0xed,0xe0,0xfa,0xba,0x00,0x36} }, +{ 13, 0x0e97, 0, {0xc0,0x03,0x12,0x04,0xef,0xd0,0x03,0x90,0x7f,0xea,0xe0,0xfa,0x90} }, +{ 5, 0x0ea4, 0, {0x17,0x22,0xf0,0x80,0x24} }, +{ 5, 0x0ea9, 0, {0xbb,0x12,0x02,0x80,0x17} }, +{ 5, 0x0eae, 0, {0xbb,0x81,0x02,0x80,0x0d} }, +{ 5, 0x0eb3, 0, {0xbb,0x83,0x02,0x80,0x08} }, +{ 5, 0x0eb8, 0, {0xbb,0x82,0x02,0x80,0x03} }, +{ 3, 0x0ebd, 0, {0xbb,0x84,0x05} }, +{ 5, 0x0ec0, 0, {0x12,0x06,0x4e,0x80,0x08} }, +{ 8, 0x0ec5, 0, {0x90,0x7f,0xb4,0x74,0x03,0xf0,0x80,0x06} }, +{ 6, 0x0ecd, 0, {0x90,0x7f,0xb4,0x74,0x02,0xf0} }, +{ 2, 0x0ed3, 0, {0xd0,0x86} }, +{ 14, 0x0ed5, 0, {0xd0,0xd0,0xd0,0x01,0xd0,0x00,0xd0,0x07,0xd0,0x06,0xd0,0x05,0xd0,0x04} }, +{ 13, 0x0ee3, 0, {0xd0,0x03,0xd0,0x02,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} }, +{ 11, 0x0ef0, 0, {0x90,0x7f,0xec,0xe0,0xf5,0x5a,0xc3,0x94,0x01,0x40,0x1d} }, +{ 7, 0x0efb, 0, {0xc3,0x74,0x07,0x95,0x5a,0x40,0x16} }, +{ 13, 0x0f02, 0, {0xe5,0x5a,0x24,0xff,0x25,0xe0,0xfa,0x24,0xc6,0xf5,0x82,0xe4,0x34} }, +{ 9, 0x0f0f, 0, {0x7f,0xf5,0x83,0xaa,0x59,0xea,0xf0,0x80,0x22} }, +{ 7, 0x0f18, 0, {0xc3,0xe5,0x5a,0x94,0x81,0x40,0x1b} }, +{ 7, 0x0f1f, 0, {0xc3,0x74,0x87,0x95,0x5a,0x40,0x14} }, +{ 13, 0x0f26, 0, {0xe5,0x5a,0x24,0xff,0x25,0xe0,0xfa,0x24,0xb6,0xf5,0x82,0xe4,0x34} }, +{ 7, 0x0f33, 0, {0x7f,0xf5,0x83,0xaa,0x59,0xea,0xf0} }, +{ 1, 0x0f3a, 0, {0x22} }, +{ 14, 0x0f3b, 0, {0x09,0x02,0xba,0x00,0x03,0x01,0x00,0x40,0x00,0x09,0x04,0x00,0x00,0x00} }, +{ 14, 0x0f49, 0, {0x01,0x01,0x00,0x00,0x09,0x24,0x01,0x00,0x01,0x3d,0x00,0x01,0x01,0x0c} }, +{ 14, 0x0f57, 0, {0x24,0x02,0x01,0x10,0x07,0x00,0x02,0x03,0x00,0x00,0x00,0x0d,0x24,0x06} }, +{ 14, 0x0f65, 0, {0x03,0x01,0x02,0x15,0x00,0x03,0x00,0x03,0x00,0x00,0x09,0x24,0x03,0x02} }, +{ 14, 0x0f73, 0, {0x01,0x01,0x00,0x01,0x00,0x09,0x24,0x03,0x04,0x02,0x03,0x00,0x03,0x00} }, +{ 14, 0x0f81, 0, {0x09,0x24,0x03,0x05,0x03,0x06,0x00,0x01,0x00,0x09,0x04,0x01,0x00,0x00} }, +{ 14, 0x0f8f, 0, {0x01,0x02,0x00,0x00,0x09,0x04,0x01,0x01,0x01,0x01,0x02,0x00,0x00,0x07} }, +{ 14, 0x0f9d, 0, {0x24,0x01,0x02,0x01,0x01,0x00,0x0b,0x24,0x02,0x01,0x02,0x02,0x10,0x01} }, +{ 14, 0x0fab, 0, {0x80,0xbb,0x00,0x09,0x05,0x88,0x05,0x00,0x01,0x01,0x00,0x00,0x07,0x25} }, +{ 14, 0x0fb9, 0, {0x01,0x00,0x00,0x00,0x00,0x09,0x04,0x02,0x00,0x02,0x00,0x00,0x00,0x00} }, +{ 14, 0x0fc7, 0, {0x07,0x05,0x82,0x02,0x40,0x00,0x00,0x07,0x05,0x02,0x02,0x40,0x00,0x00} }, +{ 14, 0x0fd5, 0, {0x09,0x04,0x02,0x01,0x03,0x00,0x00,0x00,0x00,0x07,0x05,0x82,0x02,0x40} }, +{ 14, 0x0fe3, 0, {0x00,0x00,0x07,0x05,0x02,0x02,0x40,0x00,0x00,0x09,0x05,0x89,0x05,0xa0} }, +{ 10, 0x0ff1, 0, {0x01,0x01,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00} }, +{ 14, 0x0ffb, 0, {0x12,0x01,0x00,0x01,0x00,0x00,0x00,0x40,0x47,0x05,0x99,0x99,0x00,0x01} }, +{ 14, 0x1009, 0, {0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x02,0xba} }, +{ 4, 0x1017, 0, {0x00,0x03,0x01,0x00} }, +{ 2, 0x101b, 0, {0x7a,0x00} }, +{ 3, 0x101d, 0, {0xba,0x05,0x00} }, +{ 2, 0x1020, 0, {0x50,0x17} }, +{ 8, 0x1022, 0, {0x90,0x7f,0xa5,0xe0,0xfb,0x30,0xe0,0x05} }, +{ 5, 0x102a, 0, {0x90,0x00,0x01,0x80,0x0d} }, +{ 10, 0x102f, 0, {0xc0,0x02,0x12,0x01,0xdd,0xd0,0x02,0x0a,0x80,0xe4} }, +{ 3, 0x1039, 0, {0x90,0x00,0x01} }, +{ 1, 0x103c, 0, {0x22} }, +{ 14, 0x103d, 0, {0x90,0x7d,0xc1,0xe0,0xf9,0xa3,0xe0,0xfa,0xa3,0xe0,0xfb,0x7c,0x00,0x7d} }, +{ 4, 0x104b, 0, {0x7e,0xeb,0x60,0x12} }, +{ 14, 0x104f, 0, {0x89,0x82,0x8a,0x83,0xe0,0xa3,0xa9,0x82,0xaa,0x83,0x8c,0x82,0x8d,0x83} }, +{ 4, 0x105d, 0, {0xf0,0x0c,0xdb,0xee} }, +{ 8, 0x1061, 0, {0x90,0x7d,0xc3,0xe0,0x90,0x7f,0xb9,0xf0} }, +{ 1, 0x1069, 0, {0x22} }, +{ 14, 0x106a, 0, {0x90,0x7d,0xc1,0xe0,0xf9,0xa3,0xe0,0xfa,0xa3,0xe0,0xfb,0x7c,0xc4,0x7d} }, +{ 4, 0x1078, 0, {0x7d,0xeb,0x60,0xe5} }, +{ 14, 0x107c, 0, {0x8c,0x82,0x8d,0x83,0xe0,0x0c,0x89,0x82,0x8a,0x83,0xf0,0xa3,0xa9,0x82} }, +{ 4, 0x108a, 0, {0xaa,0x83,0xdb,0xee} }, +{ 1, 0x108e, 0, {0x22} }, +{ 14, 0x108f, 0, {0x90,0x7f,0xa5,0x74,0x80,0xf0,0x05,0x86,0x90,0x7d,0xc1,0xe0,0x05,0x86} }, +{ 14, 0x109d, 0, {0xa3,0xf0,0x12,0x10,0x1b,0x90,0x7f,0xa6,0x05,0x86,0xa3,0xa3,0xe0,0xf9} }, +{ 5, 0x10ab, 0, {0x60,0x16,0xa3,0x05,0x86} }, +{ 13, 0x10b0, 0, {0x90,0x7f,0xa6,0x05,0x86,0xe0,0xa3,0x05,0x86,0xf0,0xc0,0x01,0x12} }, +{ 6, 0x10bd, 0, {0x10,0x1b,0xd0,0x01,0xd9,0xed} }, +{ 6, 0x10c3, 0, {0x90,0x7f,0xa5,0x74,0x40,0xf0} }, +{ 1, 0x10c9, 0, {0x22} }, +{ 8, 0x10ca, 0, {0x90,0x88,0x02,0x74,0x01,0xf0,0x7a,0x00} }, +{ 3, 0x10d2, 0, {0xba,0xff,0x00} }, +{ 2, 0x10d5, 0, {0x50,0x0a} }, +{ 10, 0x10d7, 0, {0xc0,0x02,0x12,0x01,0xdd,0xd0,0x02,0x0a,0x80,0xf1} }, +{ 1, 0x10e1, 0, {0x22} }, +{ 5, 0x10e2, 0, {0xe5,0x6b,0xb4,0xc0,0x08} }, +{ 8, 0x10e7, 0, {0x90,0x88,0x03,0xe5,0x6c,0xf0,0x80,0x06} }, +{ 6, 0x10ef, 0, {0x90,0x88,0x02,0xe5,0x6c,0xf0} }, +{ 4, 0x10f5, 0, {0x7a,0x00,0x7b,0x00} }, +{ 11, 0x10f9, 0, {0xc3,0xea,0x94,0x32,0xeb,0x64,0x80,0x94,0x80,0x50,0x07} }, +{ 5, 0x1104, 0, {0x0a,0xba,0x00,0x01,0x0b} }, +{ 2, 0x1109, 0, {0x80,0xee} }, +{ 1, 0x110b, 0, {0x22} }, +{ 10, 0x110c, 0, {0x90,0x88,0x03,0xe5,0x6d,0xf0,0x05,0x39,0x7a,0x00} }, +{ 3, 0x1116, 0, {0xba,0x28,0x00} }, +{ 2, 0x1119, 0, {0x50,0x03} }, +{ 3, 0x111b, 0, {0x0a,0x80,0xf8} }, +{ 5, 0x111e, 0, {0xe5,0x39,0xb4,0x10,0x08} }, +{ 8, 0x1123, 0, {0x90,0x88,0x02,0x74,0xc0,0xf0,0x80,0x0e} }, +{ 5, 0x112b, 0, {0xe5,0x39,0xb4,0x20,0x09} }, +{ 9, 0x1130, 0, {0x90,0x88,0x02,0x74,0x80,0xf0,0x75,0x39,0x00} }, +{ 2, 0x1139, 0, {0x7a,0x00} }, +{ 3, 0x113b, 0, {0xba,0x28,0x00} }, +{ 2, 0x113e, 0, {0x50,0x03} }, +{ 3, 0x1140, 0, {0x0a,0x80,0xf8} }, +{ 1, 0x1143, 0, {0x22} }, +{ 4, 0x1144, 0, {0xe5,0x6f,0x60,0x02} }, +{ 2, 0x1148, 0, {0x80,0x07} }, +{ 7, 0x114a, 0, {0x7a,0x00,0x75,0x39,0x00,0x80,0x05} }, +{ 5, 0x1151, 0, {0x7a,0x40,0x75,0x39,0x10} }, +{ 9, 0x1156, 0, {0xe5,0x6e,0x2a,0xfa,0xe5,0x6e,0x25,0x39,0xf5} }, +{ 10, 0x115f, 0, {0x39,0x90,0x88,0x02,0x74,0x80,0x2a,0xf0,0x7a,0x00} }, +{ 8, 0x1169, 0, {0xc3,0xea,0x64,0x80,0x94,0xa8,0x50,0x03} }, +{ 3, 0x1171, 0, {0x0a,0x80,0xf5} }, +{ 1, 0x1174, 0, {0x22} }, +{ 6, 0x1175, 0, {0xaa,0x70,0xab,0x71,0xac,0x72} }, +{ 12, 0x117b, 0, {0x8a,0x82,0x8b,0x83,0x8c,0xf0,0x12,0x14,0xee,0xfd,0x60,0x18} }, +{ 13, 0x1187, 0, {0x8d,0x6d,0xc0,0x02,0xc0,0x03,0xc0,0x04,0x12,0x11,0x0c,0xd0,0x04} }, +{ 9, 0x1194, 0, {0xd0,0x03,0xd0,0x02,0x0a,0xba,0x00,0x01,0x0b} }, +{ 2, 0x119d, 0, {0x80,0xdc} }, +{ 1, 0x119f, 0, {0x22} }, +{ 13, 0x11a0, 0, {0xe5,0x73,0xc4,0x54,0x0f,0xfa,0x53,0x02,0x0f,0xc3,0x74,0x09,0x9a} }, +{ 2, 0x11ad, 0, {0x50,0x06} }, +{ 6, 0x11af, 0, {0x74,0x37,0x2a,0xfb,0x80,0x04} }, +{ 4, 0x11b5, 0, {0x74,0x30,0x2a,0xfb} }, +{ 12, 0x11b9, 0, {0x8b,0x6d,0xc0,0x03,0x12,0x11,0x0c,0xd0,0x03,0xaa,0x73,0x53} }, +{ 8, 0x11c5, 0, {0x02,0x0f,0xc3,0x74,0x09,0x9a,0x50,0x06} }, +{ 6, 0x11cd, 0, {0x74,0x37,0x2a,0xfb,0x80,0x04} }, +{ 4, 0x11d3, 0, {0x74,0x30,0x2a,0xfb} }, +{ 5, 0x11d7, 0, {0x8b,0x6d,0x12,0x11,0x0c} }, +{ 1, 0x11dc, 0, {0x22} }, +{ 7, 0x11dd, 0, {0x90,0x7d,0xc3,0xe0,0xfa,0x60,0x0f} }, +{ 12, 0x11e4, 0, {0x90,0x7d,0xc1,0xe0,0xf5,0x6e,0x90,0x7d,0xc2,0xe0,0xf5,0x6f} }, +{ 3, 0x11f0, 0, {0x12,0x11,0x44} }, +{ 12, 0x11f3, 0, {0x90,0x7d,0xff,0xe4,0xf0,0x75,0x70,0xc4,0x75,0x71,0x7d,0x75} }, +{ 5, 0x11ff, 0, {0x72,0x01,0x12,0x11,0x75} }, +{ 1, 0x1204, 0, {0x22} }, +{ 2, 0x1205, 0, {0x7a,0x04} }, +{ 3, 0x1207, 0, {0xba,0x40,0x00} }, +{ 2, 0x120a, 0, {0x50,0x36} }, +{ 14, 0x120c, 0, {0xea,0x24,0xc0,0xf5,0x82,0xe4,0x34,0x7d,0xf5,0x83,0xe0,0xfb,0x7c,0x00} }, +{ 3, 0x121a, 0, {0xbc,0x08,0x00} }, +{ 2, 0x121d, 0, {0x50,0x20} }, +{ 6, 0x121f, 0, {0x8b,0x05,0xed,0x30,0xe7,0x0b} }, +{ 11, 0x1225, 0, {0x90,0x7f,0x96,0x74,0x42,0xf0,0x74,0xc3,0xf0,0x80,0x08} }, +{ 8, 0x1230, 0, {0x90,0x7f,0x96,0xe4,0xf0,0x74,0x81,0xf0} }, +{ 7, 0x1238, 0, {0xeb,0x25,0xe0,0xfb,0x0c,0x80,0xdb} }, +{ 3, 0x123f, 0, {0x0a,0x80,0xc5} }, +{ 1, 0x1242, 0, {0x22} }, +{ 4, 0x1243, 0, {0x7a,0x00,0x7b,0xef} }, +{ 3, 0x1247, 0, {0xba,0x10,0x00} }, +{ 2, 0x124a, 0, {0x50,0x20} }, +{ 14, 0x124c, 0, {0x74,0x11,0x2b,0xfb,0x24,0x00,0xfc,0xe4,0x34,0x18,0xfd,0x8c,0x82,0x8d} }, +{ 14, 0x125a, 0, {0x83,0xe4,0xf0,0xea,0x24,0x00,0xf5,0x82,0xe4,0x34,0x19,0xf5,0x83,0xe4} }, +{ 4, 0x1268, 0, {0xf0,0x0a,0x80,0xdb} }, +{ 1, 0x126c, 0, {0x22} }, +{ 14, 0x126d, 0, {0x74,0xf8,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0xe4,0xf0} }, +{ 14, 0x127b, 0, {0x74,0xf9,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0xe4,0xf0} }, +{ 14, 0x1289, 0, {0x74,0xfa,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0xe4,0xf0} }, +{ 14, 0x1297, 0, {0x74,0xfb,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0xe4,0xf0} }, +{ 14, 0x12a5, 0, {0x74,0xff,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0xe4,0xf0} }, +{ 1, 0x12b3, 0, {0x22} }, +{ 14, 0x12b4, 0, {0x12,0x03,0xcb,0x12,0x12,0x6d,0x7a,0xc0,0x7b,0x87,0x7c,0x01,0x74,0x01} }, +{ 14, 0x12c2, 0, {0x2a,0xfd,0xe4,0x3b,0xfe,0x8c,0x07,0x8a,0x82,0x8b,0x83,0x8c,0xf0,0x74} }, +{ 14, 0x12d0, 0, {0x01,0x12,0x14,0xbf,0x2d,0xfa,0xe4,0x3e,0xfb,0x8f,0x04,0x8d,0x82,0x8e} }, +{ 14, 0x12de, 0, {0x83,0x8f,0xf0,0x74,0x06,0x12,0x14,0xbf,0x74,0x01,0x2a,0xfd,0xe4,0x3b} }, +{ 14, 0x12ec, 0, {0xfe,0x8c,0x07,0x8a,0x82,0x8b,0x83,0x8c,0xf0,0xe4,0x12,0x14,0xbf,0x74} }, +{ 14, 0x12fa, 0, {0x01,0x2d,0xfa,0xe4,0x3e,0xfb,0x8f,0x04,0x8d,0x82,0x8e,0x83,0x8f,0xf0} }, +{ 14, 0x1308, 0, {0x74,0x0b,0x12,0x14,0xbf,0x74,0x01,0x2a,0xfd,0xe4,0x3b,0xfe,0x8c,0x07} }, +{ 14, 0x1316, 0, {0x8a,0x82,0x8b,0x83,0x8c,0xf0,0x74,0x08,0x12,0x14,0xbf,0x74,0x01,0x2d} }, +{ 14, 0x1324, 0, {0xfa,0xe4,0x3e,0xfb,0x8f,0x04,0x8d,0x82,0x8e,0x83,0x8f,0xf0,0x74,0x01} }, +{ 14, 0x1332, 0, {0x12,0x14,0xbf,0x2a,0xfd,0xe4,0x3b,0xfe,0x8c,0x07,0x8a,0x82,0x8b,0x83} }, +{ 14, 0x1340, 0, {0x8c,0xf0,0xe4,0x12,0x14,0xbf,0x74,0x01,0x2d,0xfa,0xe4,0x3e,0xfb,0x8f} }, +{ 14, 0x134e, 0, {0x04,0x8d,0x82,0x8e,0x83,0x8f,0xf0,0x74,0x03,0x12,0x14,0xbf,0x7d,0x00} }, +{ 3, 0x135c, 0, {0xbd,0x06,0x00} }, +{ 2, 0x135f, 0, {0x50,0x12} }, +{ 11, 0x1361, 0, {0x8a,0x82,0x8b,0x83,0x8c,0xf0,0x0a,0xba,0x00,0x01,0x0b} }, +{ 7, 0x136c, 0, {0xe4,0x12,0x14,0xbf,0x0d,0x80,0xe9} }, +{ 13, 0x1373, 0, {0x8a,0x82,0x8b,0x83,0x8c,0xf0,0xe5,0x74,0x12,0x14,0xbf,0x74,0xf9} }, +{ 14, 0x1380, 0, {0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0x74,0x0f,0xf0,0x74} }, +{ 14, 0x138e, 0, {0xfe,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0x74,0x01,0xf0} }, +{ 6, 0x139c, 0, {0x12,0x03,0xe1,0x12,0x04,0xf7} }, +{ 1, 0x13a2, 0, {0x22} }, +{ 13, 0x13a3, 0, {0x90,0x7d,0xc1,0xe0,0xfa,0x24,0x00,0xfb,0xe4,0x34,0x19,0xfc,0x90} }, +{ 14, 0x13b0, 0, {0x7d,0xc2,0xe0,0xfd,0x8b,0x82,0x8c,0x83,0xf0,0x75,0xf0,0x11,0xea,0xa4} }, +{ 3, 0x13be, 0, {0xfa,0x7b,0x00} }, +{ 3, 0x13c1, 0, {0xbb,0x10,0x00} }, +{ 2, 0x13c4, 0, {0x50,0x24} }, +{ 14, 0x13c6, 0, {0xea,0x24,0x00,0xfc,0xe4,0x34,0x18,0xfd,0xeb,0x2c,0xfc,0xe4,0x3d,0xfd} }, +{ 14, 0x13d4, 0, {0x74,0x04,0x2b,0x24,0xc0,0xf5,0x82,0xe4,0x34,0x7d,0xf5,0x83,0xe0,0xfe} }, +{ 8, 0x13e2, 0, {0x8c,0x82,0x8d,0x83,0xf0,0x0b,0x80,0xd7} }, +{ 14, 0x13ea, 0, {0xea,0x24,0x00,0xfa,0xe4,0x34,0x18,0xfb,0x74,0x10,0x2a,0xf5,0x82,0xe4} }, +{ 5, 0x13f8, 0, {0x3b,0xf5,0x83,0xe4,0xf0} }, +{ 1, 0x13fd, 0, {0x22} }, +{ 4, 0x13fe, 0, {0xe5,0x76,0x60,0x02} }, +{ 2, 0x1402, 0, {0x80,0x16} }, +{ 12, 0x1404, 0, {0x74,0x0f,0x55,0x75,0xfa,0x8a,0x75,0x24,0x00,0xf5,0x82,0xe4} }, +{ 10, 0x1410, 0, {0x34,0x19,0xf5,0x83,0xe0,0xf5,0x74,0x12,0x12,0xb4} }, +{ 10, 0x141a, 0, {0x12,0x10,0xca,0x75,0x6e,0x00,0x75,0x6f,0x00,0x12} }, +{ 6, 0x1424, 0, {0x11,0x44,0x75,0x70,0xb9,0x75} }, +{ 6, 0x142a, 0, {0x71,0x14,0x75,0x72,0x02,0x12} }, +{ 11, 0x1430, 0, {0x11,0x75,0xe5,0x76,0xb4,0x02,0x04,0x74,0x01,0x80,0x01} }, +{ 1, 0x143b, 0, {0xe4} }, +{ 3, 0x143c, 0, {0xfa,0x70,0x0f} }, +{ 12, 0x143f, 0, {0x74,0x01,0x25,0x75,0xf5,0x73,0xc0,0x02,0x12,0x11,0xa0,0xd0} }, +{ 3, 0x144b, 0, {0x02,0x80,0x0a} }, +{ 10, 0x144e, 0, {0x85,0x75,0x73,0xc0,0x02,0x12,0x11,0xa0,0xd0,0x02} }, +{ 12, 0x1458, 0, {0x75,0x6e,0x00,0x75,0x6f,0x01,0xc0,0x02,0x12,0x11,0x44,0xd0} }, +{ 4, 0x1464, 0, {0x02,0xea,0x70,0x1a} }, +{ 13, 0x1468, 0, {0x75,0xf0,0x11,0xe5,0x75,0xa4,0xfa,0x24,0x00,0xfa,0xe4,0x34,0x18} }, +{ 9, 0x1475, 0, {0xfb,0x8a,0x70,0x8b,0x71,0x75,0x72,0x01,0x12} }, +{ 4, 0x147e, 0, {0x11,0x75,0x80,0x36} }, +{ 2, 0x1482, 0, {0x7a,0x00} }, +{ 3, 0x1484, 0, {0xba,0x10,0x00} }, +{ 2, 0x1487, 0, {0x50,0x2f} }, +{ 13, 0x1489, 0, {0xea,0x24,0x00,0xf5,0x82,0xe4,0x34,0x19,0xf5,0x83,0xe0,0xfb,0xe5} }, +{ 4, 0x1496, 0, {0x75,0xb5,0x03,0x1b} }, +{ 14, 0x149a, 0, {0x75,0xf0,0x11,0xea,0xa4,0xfb,0x24,0x00,0xfb,0xe4,0x34,0x18,0xfc,0x8b} }, +{ 9, 0x14a8, 0, {0x70,0x8c,0x71,0x75,0x72,0x01,0xc0,0x02,0x12} }, +{ 4, 0x14b1, 0, {0x11,0x75,0xd0,0x02} }, +{ 3, 0x14b5, 0, {0x0a,0x80,0xcc} }, +{ 1, 0x14b8, 0, {0x22} }, +{ 6, 0x14b9, 0, {0x50,0x72,0x6f,0x67,0x20,0x00} }, +{ 14, 0x14bf, 0, {0xc8,0xc0,0xe0,0xc8,0xc0,0xe0,0xe5,0xf0,0x60,0x0b,0x14,0x60,0x0f,0x14} }, +{ 7, 0x14cd, 0, {0x60,0x11,0x14,0x60,0x12,0x80,0x15} }, +{ 7, 0x14d4, 0, {0xd0,0xe0,0xa8,0x82,0xf6,0x80,0x0e} }, +{ 5, 0x14db, 0, {0xd0,0xe0,0xf0,0x80,0x09} }, +{ 4, 0x14e0, 0, {0xd0,0xe0,0x80,0x05} }, +{ 5, 0x14e4, 0, {0xd0,0xe0,0xa8,0x82,0xf2} }, +{ 4, 0x14e9, 0, {0xc8,0xd0,0xe0,0xc8} }, +{ 1, 0x14ed, 0, {0x22} }, +{ 14, 0x14ee, 0, {0xc8,0xc0,0xe0,0xe5,0xf0,0x60,0x0d,0x14,0x60,0x0f,0x14,0x60,0x0f,0x14} }, +{ 6, 0x14fc, 0, {0x60,0x10,0x74,0xff,0x80,0x0f} }, +{ 5, 0x1502, 0, {0xa8,0x82,0xe6,0x80,0x0a} }, +{ 3, 0x1507, 0, {0xe0,0x80,0x07} }, +{ 4, 0x150a, 0, {0xe4,0x93,0x80,0x03} }, +{ 3, 0x150e, 0, {0xa8,0x82,0xe2} }, +{ 4, 0x1511, 0, {0xf8,0xd0,0xe0,0xc8} }, +{ 1, 0x1515, 0, {0x22} }, +{ 0, 0x0000, 1, {0} } + +}; + +static unsigned char bitstream[] = { + +0x00,0x09,0x0F,0xF0,0x0F,0xF0,0x0F,0xF0, 0x0F,0xF0,0x00,0x00,0x01,0x61,0x00,0x0D, +0x64,0x61,0x62,0x75,0x73,0x62,0x74,0x72, 0x2E,0x6E,0x63,0x64,0x00,0x62,0x00,0x0B, +0x73,0x31,0x30,0x78,0x6C,0x76,0x71,0x31, 0x30,0x30,0x00,0x63,0x00,0x0B,0x31,0x39, +0x39,0x39,0x2F,0x30,0x39,0x2F,0x32,0x34, 0x00,0x64,0x00,0x09,0x31,0x30,0x3A,0x34, +0x32,0x3A,0x34,0x36,0x00,0x65,0x00,0x00, 0x2E,0xC0,0xFF,0x20,0x17,0x5F,0x9F,0x5B, +0xFE,0xFB,0xBB,0xB7,0xBB,0xBB,0xFB,0xBF, 0xAF,0xEF,0xFB,0xDF,0xB7,0xFB,0xFB,0x7F, +0xBF,0xB7,0xEF,0xF2,0xFF,0xFB,0xFE,0xFF, 0xFF,0xEF,0xFF,0xFE,0xFF,0xBF,0xFF,0xFF, +0xFF,0xFF,0xAF,0xFF,0xFA,0xFF,0xFF,0xFF, 0xC9,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFB,0xFF,0xA3,0xFF,0xFB, +0xFE,0xFF,0xBF,0xEF,0xE3,0xFE,0xFF,0xBF, 0xE3,0xFE,0xFF,0xBF,0x6F,0xFB,0xF6,0xFF, +0xBF,0xFF,0x47,0xFF,0xFF,0x9F,0xEE,0xF9, 0xFE,0xCF,0x9F,0xEF,0xFB,0xCF,0x9B,0xEE, +0xF8,0xFE,0xEF,0x8F,0xEE,0xFB,0xFE,0x0B, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xBF,0xFF,0xFF,0xFB,0xFF,0xFF, 0xBF,0xFF,0xFF,0xFC,0x17,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0x7F, 0xFF,0xFF,0xFB,0xFF,0xFF,0x7F,0xFF,0xFF, +0xFC,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x5F,0xFF, 0xFF,0xFD,0xFF,0xFF,0xDB,0xFF,0xFD,0xFF, +0x77,0xFF,0xFD,0xFF,0xFF,0xDF,0xFE,0xFD, 0xFF,0xFF,0xF2,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFD,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE1, +0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xE3,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF, +0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0x67,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0x7F,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF, 0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0x2F,0xFF, +0xF3,0xFD,0xFF,0x7F,0xDE,0xF7,0xFD,0xFF, 0x7F,0xF7,0x7D,0xFF,0x7F,0xDF,0xF7,0xBD, +0xFF,0x7F,0xFF,0x1F,0xFF,0xEF,0xFB,0xFE, 0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xEF,0xFB, +0xFE,0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xFF, 0x3F,0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x7F, +0x9F,0xE7,0xFA,0x7F,0x9F,0xE7,0xF9,0xFE, 0x7F,0x9F,0xE7,0xFF,0xFC,0x7F,0xBF,0xBF, +0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB,0xB7, 0xBF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB, +0xFF,0xE0,0xFD,0xF9,0xFE,0x7F,0x9F,0xE7, 0xF9,0xFE,0x7F,0x9D,0xF9,0xFE,0x7D,0x9D, +0xE7,0xF9,0xFE,0x7F,0x9F,0xED,0xED,0xFF, 0xFD,0xFF,0x7F,0xDF,0xF7,0xFD,0xFF,0x7F, +0xDF,0xFD,0xFF,0x7F,0xDF,0xF7,0xFD,0xFF, 0x7F,0xDF,0xFF,0x9B,0xFF,0xEF,0xFB,0xFE, +0xFB,0xBF,0xEF,0xBB,0xFE,0xFF,0xAF,0xBB, 0xBE,0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xFF, +0xB7,0xBF,0xDB,0xF6,0xBD,0xBF,0x6B,0xDB, 0xF6,0xF9,0xBF,0x5B,0xD6,0xF9,0xBF,0x6F, +0xDB,0xF6,0xFD,0xBF,0xFF,0x0E,0xFF,0xFF, 0xFF,0xFF,0x5F,0xFF,0xF7,0xFF,0xFF,0x7F, +0xF7,0xBD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xDF,0x9F,0xFF,0xFF,0xFF,0xFE,0xFF, +0xFF,0xEF,0xFE,0xFE,0xFF,0xFF,0x77,0xFF, 0xFB,0xFB,0xFF,0xFF,0xFF,0xFF,0xF8,0x3F, +0xFF,0xFD,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xF4,0x7F,0xFF,0xFE,0xFD, 0xBE,0xFF,0xDF,0xFE,0xFF,0xFF,0xEF,0x7F, +0xFF,0xCF,0xFF,0xCF,0xFF,0xFF,0xFF,0xDF, 0xE6,0xFF,0xFF,0x7F,0xDF,0xF7,0xDD,0x7F, +0x7F,0xDF,0xF7,0xFF,0x7F,0xDF,0xD7,0xFD, 0xFF,0x7F,0xDF,0xF7,0xFF,0xCD,0xFF,0xF2, +0xFF,0xFF,0x4F,0x7F,0xF4,0xFF,0xFF,0xFF, 0xE7,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xBB,0xFF,0xEF,0xFF,0xFE,0xFF, 0xFF,0xFF,0xEF,0xFF,0xFF,0xEF,0xFF,0xFB, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x65, 0xEF,0xFF,0xFF,0x7F,0xFF,0xFD,0xEF,0xFF, +0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFE,0xCF,0xDF,0xFE,0xFF, +0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xF3,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFE,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xBF,0xFF, 0xFF,0xFF,0xE3,0x7F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xEF,0xEB,0xFF,0xFE,0xBF,0xFF, 0xEB,0xFF,0xFC,0x7F,0xFF,0xFF,0xFF,0xEE, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDD,0xFF, 0xD6,0xFF,0xFD,0xBF,0xFF,0xFB,0xFF,0xFE, +0xFD,0xFF,0xFF,0xFD,0xEF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xDE,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xBF,0xFF,0xFD,0xFF,0x7F,0xBF, 0xFF,0x5F,0xDF,0xFF,0xFF,0xBF,0x77,0xFF, +0xFF,0xFF,0x7F,0xD7,0xFF,0xFF,0xFF,0xFF, 0xFF,0xC3,0xFF,0xFF,0xFF,0xFF,0xDF,0xEF, +0xFF,0xFF,0xFE,0xFB,0xFF,0xFF,0xDF,0xBF, 0xFF,0xFF,0xFF,0xFF,0xED,0xFF,0xB7,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xAF,0x7F,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xDF,0xBF,0xDF,0xF3,0xFD,0xFB,0xFF,0x5B, +0xFD,0xFF,0xBF,0xEF,0xF7,0xFF,0xFF,0x7D, 0xFF,0xFF,0xFF,0xFF,0xF8,0x3B,0xFF,0xBF, +0x6F,0xFF,0xFE,0xFF,0xBF,0xFF,0xEB,0x7D, 0xFF,0xEF,0xFB,0xFE,0xFF,0xFF,0xFF,0xFF, +0xFF,0xF2,0x7F,0xFC,0xFF,0x3F,0xDF,0xED, 0xFE,0xFF,0xFF,0xFF,0xFF,0xEF,0x5F,0xF7, +0xB5,0xFF,0xEF,0xFF,0xFF,0xFF,0xE0,0x3F, 0x9F,0x9E,0xFF,0xFF,0xEF,0xFF,0xDF,0xFF, +0xBF,0x5F,0xBF,0xCF,0xF3,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0x69,0xAF,0x33,0xFD,0xFF, +0xFB,0xFF,0xFF,0xFF,0xFF,0xFC,0xFF,0x7F, 0xD9,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xF5, +0xA3,0xDF,0x6E,0xDE,0xFF,0xFF,0xBD,0xFF, 0xFF,0xFE,0xFF,0xFF,0xFF,0xFE,0xE7,0xFD, +0xFF,0xFF,0xFF,0xF9,0xEF,0xC6,0xFE,0xB7, 0xAD,0xE5,0xF9,0xFF,0xFF,0xFF,0xCF,0xFF, +0xFF,0xFF,0xCD,0xFB,0x7F,0xFF,0xFF,0xFF, 0xF9,0xF6,0x0F,0xDF,0xEC,0xCF,0x7F,0xFF, +0xFB,0x7F,0xFF,0xFF,0xFF,0xFD,0xFF,0xFE, 0xF9,0xFD,0x7F,0xFF,0x7F,0xFF,0xF9,0x5B, +0xFF,0x73,0xDC,0xFD,0x7B,0xDF,0xFF,0xFF, 0xFF,0x7B,0xFF,0xFF,0xF7,0x53,0xD6,0xFF, +0xFF,0xFF,0xFF,0xD8,0x9F,0xFE,0xFF,0xEF, 0x7F,0xEE,0xFF,0xFF,0xFF,0xFB,0xED,0xED, +0xFD,0xFF,0xFE,0xFF,0xFF,0xFB,0x7F,0xFF, 0xE2,0x7F,0xFF,0x6F,0xD8,0x57,0xF7,0xFF, +0xFF,0xFF,0xDF,0xFF,0xE8,0xFF,0xFF,0xFD, 0xFF,0xFF,0xFC,0x7F,0xFF,0xE4,0xFF,0xFB, +0xEF,0xFB,0xFE,0xDF,0xB7,0xED,0xFF,0xFE, 0xDF,0x7F,0xFF,0xFE,0x7F,0xB7,0xFF,0xFF, +0xFF,0xFF,0x89,0xFF,0xFF,0xCF,0xF3,0xFE, 0x7F,0xFF,0xEF,0xFF,0xFE,0x7E,0x7F,0xFB, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF1, 0xFF,0xEB,0x7A,0xD5,0xBF,0x6F,0xDB,0xBE, +0xFD,0xB7,0xD8,0xF6,0xE5,0xBF,0x6F,0xFB, 0xFE,0xF5,0xBD,0x7E,0x06,0xFF,0xDF,0xF7, +0xFB,0xF6,0xFF,0x3F,0xFF,0xDB,0xFF,0xFF, 0x6F,0xFB,0xF7,0xFF,0xFF,0xFF,0xFB,0xFE, +0xF7,0xAF,0xFF,0xB7,0xED,0xEF,0xF7,0xFE, 0xFF,0xFF,0xDF,0xFF,0xFE,0xFF,0xEF,0xFF, +0xFF,0xFF,0xFF,0xBF,0xF7,0xFC,0x1F,0xEE, 0xFB,0xFE,0xBD,0xFF,0x7F,0x5F,0xD7,0xFD, +0xFB,0x43,0xFF,0xFF,0xFD,0xFF,0x5F,0xFF, 0xF7,0xFF,0xF9,0x3F,0xFF,0xCF,0xF3,0xFD, +0xF7,0x7E,0xEF,0xA7,0xF9,0xFE,0x8F,0xA7, 0xE9,0xF3,0x7E,0x9F,0xFB,0xF8,0xFF,0xFF, +0x3F,0xFD,0x7F,0x5F,0xDF,0xFD,0xFF,0xFF, 0x5F,0xFF,0xFD,0x5F,0xFF,0xFF,0x7F,0xFD, +0x7F,0xFD,0x9F,0xFF,0xE0,0xFF,0xFA,0xF8, 0xBE,0x6F,0x9F,0xE6,0xF8,0xBE,0x3F,0x9A, +0xF9,0xBE,0x6F,0x9F,0xE2,0xF9,0xFE,0x6F, 0x9F,0xF9,0xFF,0xF5,0xFD,0x7F,0xCF,0xDF, +0xFD,0xFD,0x7F,0xFF,0xF5,0xFF,0xFF,0xFF, 0xF7,0xF5,0xFD,0x0F,0xDB,0xFF,0xD3,0xFF, +0xEB,0xFA,0xFF,0xFF,0xBF,0xFF,0xFA,0xFF, 0xFF,0xCB,0xFB,0xFE,0xFF,0xFF,0xEB,0xFA, +0xFE,0xFF,0xFF,0xB7,0xFF,0xFF,0xFF,0xFF, 0xBF,0xFF,0xDF,0xF5,0xFF,0xFF,0xD7,0xFF, +0xFF,0xFF,0xDF,0xD7,0xF5,0xFF,0x7F,0xFE, 0x4F,0xFF,0xFD,0xFF,0x7F,0x7F,0xFF,0xAD, +0xEB,0xFB,0xFF,0xAD,0xFF,0xFF,0xFF,0xFF, 0xAF,0xEB,0xFB,0xFF,0xFC,0x0D,0xFF,0xFF, +0xDF,0xD2,0xFD,0xFF,0xFF,0xFD,0xF6,0xFF, 0xFF,0x7F,0xFF,0xFF,0x1F,0xFF,0xFF,0xFF, +0xFF,0xFB,0x3F,0x7D,0xEB,0x32,0xFE,0xBF, 0x2F,0xEB,0xFA,0xAE,0xBD,0xE0,0xFA,0x7E, +0xBF,0xAD,0xEB,0xFA,0xFE,0xBF,0xF5,0x7F, 0xFF,0xDE,0xFE,0xE3,0xFB,0xFF,0xFF,0xFF, +0xDF,0xEF,0x4F,0xDF,0xFF,0x7F,0xDF,0xFF, 0xF7,0xFF,0xFF,0xF8,0x7F,0xFF,0xFF,0xEF, +0xFB,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xDF, 0xED,0xFB,0xDF,0xFF,0xBF,0xFF,0xFF,0xFF, +0x81,0xFF,0xFF,0xFF,0xFF,0x3F,0xFF,0xFF, 0xFF,0xFF,0xFE,0xDD,0xFE,0xEF,0xFD,0xFF, +0xFF,0xFB,0xFE,0xF7,0xFF,0x93,0xFD,0xFB, 0x7E,0xFF,0xFE,0x87,0xE9,0xFF,0x7F,0xB3, +0x9F,0xFE,0xFE,0xFF,0xAF,0xFD,0xFE,0x7E, 0x3F,0xFE,0x67,0xFF,0xFF,0xF7,0xFF,0xFF, +0xFC,0xF7,0xDF,0xFD,0xFF,0x7F,0xFF,0xFF, 0x7F,0x6D,0xFF,0xFF,0xFE,0xFF,0xFF,0x2F, +0xFF,0xBF,0xFF,0xFF,0xEE,0xFF,0xBE,0xFF, 0xFF,0xFE,0xFF,0xEF,0xFF,0xFF,0xFE,0xFF, +0xEF,0xFF,0xFF,0xFA,0x5F,0xFF,0xFF,0xFB, 0xFF,0xFF,0xEF,0xFF,0xFB,0xFE,0xFD,0xFF, +0xFE,0xFF,0xFB,0xFF,0xFF,0xFF,0x7F,0xFF, 0xFE,0xBF,0xDF,0xFF,0xFB,0xFF,0xFF,0xF7, +0xFC,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F, 0xFF,0xFF,0xFF,0xFF,0xFF,0xF2,0x7F,0xFF, +0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF, 0xF3,0xFF,0xFF,0xFF,0xEF,0xFB,0xFF,0xFF, +0xFF,0xDF,0xE2,0xFF,0xFF,0xFB,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFB,0xE7,0xFF,0xFD, +0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xED, 0xEF,0xFD,0xFF,0xFF,0xDF,0xD7,0xF5,0xFD, +0x7F,0x5D,0xFD,0xFF,0x7F,0xDF,0x97,0xF4, 0xFD,0x7B,0x5F,0xFF,0xC9,0xFF,0xFB,0xFE, +0xFF,0xBF,0xFF,0x5F,0xFF,0xFF,0xF7,0xFF, 0xEF,0xFD,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xF7,0xFF,0xD7,0xFD,0x7D,0x7F,0xFF, 0xFF,0xFF,0xFF,0xEF,0xDF,0xF7,0xFD,0xFF, +0xBB,0xFF,0xFF,0x7F,0xFF,0xFE,0xE3,0xFF, 0xF9,0xFE,0x7F,0xBF,0xEF,0xFB,0xFE,0xFF, +0xBF,0xF9,0xFE,0xFF,0x9F,0xEF,0xF9,0xFE, 0xFF,0xBF,0xF3,0xDA,0xFF,0x37,0xCD,0xF3, +0x7C,0xDF,0x37,0xCD,0xF3,0x7F,0x37,0xCD, 0xF3,0x7C,0xDF,0x37,0xCC,0xF3,0x7F,0x5A, +0xBD,0xF6,0xFD,0xBF,0x6F,0xDB,0xF6,0xFD, 0xBF,0x6F,0xDE,0xFD,0xBF,0x6F,0xDB,0xF6, +0xFD,0xBF,0x6F,0xFE,0xF1,0x6F,0xEB,0x7A, 0xDE,0xB7,0xAD,0xEB,0x7A,0xDE,0xB7,0xAF, +0x7A,0xDE,0xB7,0xAD,0xEB,0x7A,0xDE,0xB7, 0xFF,0x7E,0xFF,0xFE,0xCD,0xB3,0x6C,0xDB, +0x36,0xCD,0xB3,0x6C,0xDE,0xCD,0xB3,0x6C, 0xDB,0x36,0xCD,0xB3,0x6C,0xDF,0xC9,0xBF, +0xF7,0xBD,0xEF,0x7A,0x9E,0xA7,0xA9,0xEA, 0x7A,0xB7,0xBD,0xEA,0x7B,0xDE,0xA7,0xBD, +0xCA,0x72,0x8D,0x91,0xFF,0xEF,0xFB,0xFE, 0xFF,0xBF,0xEF,0xFB,0xFE,0xF7,0xEF,0xFB, +0xFE,0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xFE, 0x87,0xFF,0xF6,0xFD,0xBF,0x6F,0xDB,0xF6, +0xFD,0xBF,0x6F,0xF6,0xFD,0xBF,0x6F,0xDB, 0xF6,0xFD,0xBF,0x6F,0xFE,0x4F,0xFF,0xBF, +0xEF,0xBB,0xEE,0xFB,0xBE,0xEF,0xBB,0xEF, 0xBE,0xEF,0xBB,0xEE,0xFB,0xBE,0xEF,0xBB, +0xEF,0xFC,0x5F,0xFF,0xFF,0xFF,0x3F,0xCF, 0xF3,0xFC,0xFF,0x3F,0xCF,0xFC,0xFF,0x3F, +0xCF,0xF3,0xFC,0xFF,0x3F,0xCF,0xFD,0x9F, 0xFE,0xBF,0xAF,0xEB,0xFA,0xFE,0xBF,0xAF, +0xEB,0xFE,0xBF,0xAF,0xEB,0xFA,0xFE,0xBF, 0xAF,0xEB,0xFF,0xE1,0x6F,0xFD,0xFF,0x7F, +0xDF,0xF7,0xFD,0xFF,0x7F,0xDF,0xFD,0xFF, 0x7F,0xDF,0xF7,0xFD,0xFF,0x7F,0xDF,0xFF, +0x7A,0xBF,0xFB,0xFE,0xDF,0xB7,0xED,0xFB, 0x7E,0xDF,0xB7,0xFB,0x7E,0xDF,0xB7,0xED, +0xFB,0x7E,0xDF,0xB7,0xFF,0xC9,0xFF,0xFF, 0xBF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB, +0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEE, 0xFB,0xFE,0xBB,0xFF,0xFE,0xFF,0xBF,0xEF, +0xFB,0xFE,0xFF,0xBF,0xEF,0xFE,0xFF,0xBF, 0xEF,0xFB,0xFE,0xFF,0x3F,0xCF,0xFF,0xE7, +0xFE,0xFF,0xF5,0xFD,0x77,0x5D,0xD7,0x35, 0xDD,0x77,0xD7,0xF5,0xCD,0x7B,0x5D,0xD7, +0xF5,0xDD,0x77,0xFE,0x27,0xFF,0xFF,0x8B, 0xE2,0xF8,0xBE,0x2F,0x8B,0xE2,0xF9,0xAF, +0x8B,0xE2,0xF8,0xBE,0x2F,0x8B,0xE2,0xF9, 0xFE,0x1F,0xFF,0x5F,0xD7,0xF5,0xFD,0x7F, +0x5F,0xD7,0xF5,0xFF,0x5F,0xD7,0xF5,0xFD, 0x7F,0x5F,0xD7,0xF5,0xFF,0xFA,0x3F,0xFE, +0xBF,0xAF,0xEB,0xFA,0xFE,0xBF,0xAF,0xEB, 0xEC,0xBF,0xAF,0xEB,0xFA,0xFE,0xBF,0xAF, +0xEB,0xFF,0xFE,0x7F,0xFD,0x7F,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6, 0xFF,0xFA,0xDF,0xF7,0xFD,0xFF,0x7F,0xDF, +0xF7,0xFC,0xFF,0xDF,0xF7,0xFD,0xFF,0x7F, 0xDF,0xF7,0xFD,0xFF,0xF5,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0x02,0xFF,0xFE,0xBF,0xAB,0xEB,0xFA, 0xBE,0xBF,0x23,0xEB,0xDE,0x1F,0xAF,0xEA, +0xFA,0xFE,0xAF,0xAF,0xEB,0xFD,0x97,0xFF, 0xF3,0xFC,0x7B,0x1F,0xCF,0xF1,0xFC,0x7F, +0x1F,0xF1,0xFC,0x77,0x1F,0xCD,0xF1,0xFC, 0xFF,0x1F,0xFE,0x87,0xFF,0xAF,0xEF,0xFA, +0xFE,0xFF,0xAF,0xEF,0xFA,0xFD,0xBF,0x2B, 0xFB,0x7E,0xBF,0xBF,0xEB,0xFB,0xFB,0xFB, +0xDF,0xFF,0xFB,0xF7,0xFF,0xFF,0x7F,0xF7, 0xF7,0xFF,0xFD,0xDF,0xFE,0xFC,0xDF,0xFF, +0xDF,0xFF,0xFD,0xFF,0xDA,0xBF,0xFF,0xBB, 0xEF,0xFB,0xF9,0xFF,0xBE,0xEF,0xFB,0xFB, +0xBF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB, 0xFF,0xF7,0x7F,0xFD,0xD7,0xFF,0xFF,0x7F, +0xFF,0xFF,0xFF,0xFE,0xF7,0xFF,0xFE,0xFF, 0xF7,0xFF,0xFF,0x7F,0xFF,0xFF,0xEC,0xFF, +0xFF,0xFE,0xDF,0xBF,0xFF,0xFB,0xFE,0xFF, 0xBB,0x68,0xAE,0x1F,0xAE,0xFB,0xFB,0xFF, +0xFF,0xBF,0xFF,0xD5,0xFF,0x7F,0xFF,0xFF, 0xF7,0xFE,0xFE,0xFF,0xBF,0xEF,0x9F,0xFD, +0x7F,0xFF,0xCB,0xFF,0xFF,0xDF,0xFF,0xFF, 0xBB,0xF7,0xBF,0xFF,0xFF,0xFF,0xFF,0xDF, +0xFF,0xBF,0xFB,0xFF,0xFF,0xFF,0xDE,0x3F, 0xFF,0xFF,0xFF,0xFF,0xFF,0xA7,0xFF,0xFF, +0xFF,0xFF,0xEF,0xFF,0x7F,0xFB,0xFD,0xFB, 0x7F,0xFF,0xFF,0xFF,0xFF,0xCF,0xF3,0x7C, +0xFF,0x7F,0x8D,0x7F,0xFF,0xFF,0xFF,0xFF, 0xFB,0xFF,0xF7,0xFB,0xFE,0xFD,0xFF,0xFF, +0xFF,0xFF,0xF7,0xFD,0xFF,0x7F,0xFD,0x1F, 0xFD,0xFF,0xFF,0xFF,0xFF,0xBF,0xDF,0xFF, +0xFF,0xFE,0x5C,0xFF,0x6D,0xFF,0x7F,0xAB, 0xE7,0xF1,0xFF,0xFD,0x9F,0xFF,0xFF,0xAD, +0xEB,0x7A,0x3F,0x1F,0xFF,0xFF,0xFE,0xBF, 0xAF,0xF3,0xDE,0xF5,0xFF,0x8F,0xFB,0xDF, +0xE6,0x7F,0xFF,0xDF,0xF3,0xFD,0xFF,0x7E, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xF7,0xF3, +0x7F,0xDF,0xF7,0xEF,0xFF,0xF6,0x3F,0x9F, 0xDF,0xFF,0xFF,0xEE,0xFF,0xFF,0xEF,0xFB, +0xFF,0xFF,0xF9,0xFB,0xFE,0x4F,0xBF,0xEF, 0xBB,0xFF,0x69,0xAF,0xAF,0xFC,0xFF,0x3F, +0xDD,0xFF,0xFC,0xBF,0x8F,0xFF,0xFD,0xF3, 0xBF,0xED,0x9E,0xFC,0xBF,0x6F,0xF5,0xD3, +0xDF,0xFF,0xDB,0xD6,0xF5,0xEF,0xFD,0xFE, 0xFF,0xB9,0xFF,0x1F,0xD2,0xA9,0xAF,0xFF, +0xDB,0xF7,0xBF,0xEF,0x46,0xFF,0xFF,0xAD, 0xEB,0x7A,0xDF,0xEF,0xF7,0xFF,0x7F,0xF7, +0x9F,0xED,0xFF,0x7F,0xFF,0xAD,0xEB,0x7F, 0xF5,0x6F,0xFF,0xFD,0xFB,0xD6,0xF4,0xF7, +0xFB,0xF9,0x7E,0x7F,0xFF,0x5F,0xC2,0xFE, 0xBF,0xFD,0xFB,0x33,0xDF,0xF9,0x5B,0xFF, +0xFF,0xDD,0x67,0x7D,0xCF,0xEF,0xDB,0xEC, 0xFF,0x77,0xDD,0xF7,0xFD,0xFF,0xFF,0xDE, +0xA7,0xBF,0xD4,0x9F,0xFF,0xFF,0xBF,0xEF, 0xFE,0xFF,0xDF,0xEF,0xBB,0xFF,0xFF,0xEF, +0xEB,0xFA,0xFF,0xEF,0xBD,0xFB,0xFF,0xE2, 0x7F,0xFF,0xDF,0xDF,0xF7,0xFD,0xBF,0xBB, +0x73,0xF7,0xFD,0x7F,0xDF,0xDE,0xF7,0xBF, 0xEA,0xDB,0xF6,0xFF,0xD6,0xFF,0xFF,0x66, +0xFF,0xBE,0xFF,0xBF,0x6B,0xD9,0xF6,0xDF, 0xFF,0xFB,0x7E,0x7F,0xB7,0x7E,0xFF,0xFE, +0xFF,0xCD,0xFF,0xFE,0x7F,0xFF,0xFC,0xFD, 0x3F,0xFB,0xFB,0xF7,0xFF,0xFF,0xFB,0xF6, +0x7D,0xFE,0x7F,0xFF,0xFC,0xFF,0xB9,0xFF, 0xF9,0xFA,0xFE,0xBF,0xAF,0x5B,0xD6,0xED, +0xAD,0x7B,0xF6,0xF9,0xBF,0xEF,0xF8,0xFA, 0xFE,0xBF,0xFE,0xE6,0xFF,0xFF,0xF7,0xFD, +0xFF,0x7F,0xBF,0xEF,0xF3,0xFF,0xFF,0x6F, 0xF7,0xFE,0xFF,0xFF,0xF7,0xFD,0xFE,0xF7, +0xEF,0xFF,0xFB,0xEF,0xFB,0x7E,0xDE,0xFE, 0xFF,0xBF,0xFF,0xFE,0xFF,0xFF,0xFB,0xFF, +0xFF,0xEF,0xFB,0x6F,0xFC,0x1F,0xFE,0xE7, 0xFF,0xFF,0xFF,0xEF,0xFF,0xD3,0xB4,0xBB, +0xFF,0xFF,0xFD,0xBF,0x6F,0xE3,0xFE,0xFF, 0xBF,0xFC,0xBF,0xF7,0xCF,0xF7,0xFD,0xFF, +0x2F,0xDF,0xAB,0xEA,0xFF,0xDF,0xE7,0xEA, 0x9A,0xAF,0xEF,0xFB,0xFE,0xFF,0xF5,0x3F, +0xFD,0x7E,0xFF,0xD7,0xF5,0xFB,0xFF,0xFD, 0xF7,0xFF,0x7F,0xFE,0xF7,0xFD,0xFF,0xD7, +0xFF,0xD7,0x7F,0xEE,0x7F,0xFA,0x79,0xFE, 0x2F,0x8B,0xE6,0xF9,0xFE,0x3F,0x9E,0xF9, +0xBE,0x2F,0x0B,0xE7,0xF9,0xFE,0x2F,0x9F, 0xFD,0xFF,0xFE,0x7D,0x7F,0x5F,0xD7,0xFF, +0xFF,0x7F,0xFF,0xFD,0xFF,0x7F,0x5F,0x97, 0xFF,0xFD,0x7F,0x5F,0xFF,0xE3,0xFF,0xFF, +0xFA,0xFE,0xBF,0xAF,0xFB,0xFB,0xFF,0xFF, 0xCF,0xEB,0xFE,0xBF,0xAF,0xFF,0xFA,0xFE, +0xBF,0xFF,0x87,0xFF,0xFF,0xF5,0xFF,0xFF, 0xFF,0xFF,0xFD,0xFF,0x7F,0xFF,0xFF,0xFF, +0xFB,0xFF,0xFF,0xF5,0xFF,0xFF,0xFE,0x0F, 0xFF,0xFD,0xEB,0xFF,0xFF,0xF7,0xFF,0xEF, +0x7B,0xDF,0xFE,0xFF,0xFF,0xDF,0xF7,0xFD, 0xEB,0x7F,0xDF,0xFF,0x5F,0xFF,0xFF,0xFF, +0xFF,0xFD,0xBF,0xFF,0x7E,0xFA,0xBF,0xC7, 0xDB,0xF7,0xBD,0x3F,0xFB,0xFF,0xF6,0xFF, +0xFA,0xAF,0xFF,0xEB,0xFA,0xFE,0x3F,0x2F, 0xEA,0xFA,0x3E,0xAD,0xC9,0xBA,0xF6,0xAD, +0xAF,0xEB,0xFA,0xF6,0xBF,0xFE,0x7F,0xFF, 0xFF,0xFD,0xFF,0xF1,0x7F,0x3F,0xCF,0xF1, +0xEF,0xFF,0x7F,0xFF,0xBC,0xDF,0xDF,0xF7, 0xDD,0xFF,0xE0,0x7F,0xFF,0xFF,0xFE,0xFF, +0xFA,0xEC,0xBB,0x7F,0x5F,0xFF,0xFB,0xEC, 0xFF,0xEF,0xB7,0xFF,0xF7,0xFF,0xFF,0xB5, +0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xEE,0xDF, 0x5F,0xDF,0xDE,0xFF,0xAE,0xE7,0x77,0xFF, +0xFF,0xDF,0xF7,0xFF,0xE3,0xFF,0xFA,0xBB, 0xFE,0xFF,0xAF,0xFD,0xFB,0xFE,0xBF,0xAB, +0xF9,0xFE,0xFF,0xBF,0x7F,0xBF,0xFE,0xBD, 0xFE,0xD7,0xFF,0x9F,0xFD,0xFF,0xBE,0xEF, +0xFF,0xEE,0xFD,0xBB,0x5B,0xEF,0xFF,0x7F, 0xEF,0xFF,0xEF,0xFF,0x7F,0xFF,0x4F,0xFF, +0xEF,0xFB,0xBC,0xFC,0xFF,0xFF,0xFF,0xFE, 0xFE,0xFD,0xFA,0xFE,0xFB,0xFF,0xFD,0xF3, +0xFB,0xFF,0xF8,0x5F,0xFF,0xFF,0xD7,0xF5, 0xFD,0xDF,0xEF,0xFF,0xF3,0xDC,0x5F,0xCE, +0xF5,0xBD,0xFF,0xFF,0xD7,0xFF,0xFF,0xF9, 0x3F,0xFF,0xDF,0xF7,0xFF,0xFE,0xFF,0xFD, +0xFF,0xFB,0xFF,0xF7,0xB9,0x7D,0xFE,0xDF, 0xFF,0xFF,0xFF,0xFF,0xF9,0x7F,0xFF,0xFE, +0xFF,0xFF,0x7F,0xFF,0xFE,0xFF,0xFF,0xF7, 0xF6,0xFF,0xBF,0xF1,0xF8,0xFF,0xFF,0xFF, +0xFF,0xE0,0xFF,0xFF,0xFF,0xFF,0xF9,0xFF, 0xFF,0xFF,0xFF,0xFF,0xEF,0xEF,0xFF,0xFF, +0x9B,0xFB,0x7F,0xFF,0xFF,0xFF,0xC1,0xFF, 0xDF,0xFF,0x3F,0x5F,0xD7,0xBF,0xEF,0xBB, +0xDE,0xEE,0xFF,0x7F,0xDF,0xFF,0xFE,0xF5, 0x7F,0xDF,0xFF,0x99,0xFF,0xFF,0xFA,0xFF, +0xBF,0xFD,0xEB,0x7A,0xFF,0xB7,0xFE,0xFE, 0xFF,0xFF,0xEF,0xFF,0xFF,0xFD,0xBF,0xFF, +0x97,0xFF,0xFD,0xF7,0xFF,0x7F,0xF7,0xFF, 0xFF,0xFD,0x5F,0xFE,0xF3,0xF9,0xDF,0xDF, +0xFF,0xFF,0xFC,0xFF,0xFF,0x83,0xFF,0xFF, 0xFE,0xFF,0x9E,0xEC,0xFB,0xEE,0xFF,0x9F, +0xBF,0xEF,0xFF,0xFE,0xED,0x7B,0xFF,0xFF, 0xFF,0xF1,0x5A,0xFF,0xFF,0xFD,0xFF,0x7C, +0x69,0x3B,0xDF,0xFF,0x7F,0x1F,0xDF,0xFF, 0xFD,0xBA,0xFF,0xFF,0xFB,0xFF,0x5B,0xBD, +0xFF,0xFF,0xFF,0xFF,0xD7,0xB6,0xED,0xE9, 0xFF,0xD6,0xBD,0x6F,0x5F,0xFB,0xFF,0xEF, +0xFF,0x5F,0xFE,0xF6,0x6F,0xFF,0xFF,0xFF, 0xFF,0xF7,0xEB,0x7A,0xDF,0xFF,0x9F,0x7F, +0x7F,0xFF,0xB7,0xFF,0xFF,0xFE,0xDF,0xFF, 0x6C,0xFF,0xFB,0xFF,0xBB,0x6F,0xEB,0xFE, +0xCC,0xF7,0xA5,0xFA,0x5C,0xF5,0x75,0xBB, 0xB7,0xDF,0xFE,0x6F,0x5F,0xC5,0xBF,0xFD, +0x7B,0xFE,0xFF,0x95,0xE7,0x29,0xCF,0x4F, 0xF5,0x91,0xEE,0x6B,0xDF,0xEF,0xFD,0x54, +0xF5,0xBD,0xB1,0xFF,0xEF,0xEE,0xFB,0xBE, 0xBF,0xAF,0xFE,0xDE,0xBD,0x6F,0xDA,0xF2, +0xFF,0xAF,0xBE,0xFF,0xFF,0xFD,0x7E,0xA7, 0xFF,0xF7,0xFF,0xBF,0xEF,0x7B,0xF6,0xFD, +0xBD,0x4A,0xF2,0x85,0x85,0xBF,0x5B,0xFE, 0xB5,0xFD,0xFA,0xFF,0x4F,0xFF,0xFE,0xDF, +0xFF,0xED,0xFF,0xBF,0xFF,0xBF,0x7F,0xFE, 0xFF,0xB7,0x6D,0xFF,0xF7,0xBF,0xBF,0xEF, +0xFD,0x1F,0xFF,0xFE,0x7D,0xFF,0x67,0xFF, 0xFF,0xFF,0x3F,0x7F,0xFE,0xBF,0xFF,0xE7, +0xDF,0xE7,0xFF,0xEF,0x6B,0xFC,0x1F,0xFF, 0xBF,0xEF,0xFB,0xFE,0xDE,0xBF,0xAF,0xFA, +0xFF,0xB6,0xEF,0xF9,0xFE,0xFF,0x8F,0xEF, 0xDB,0xEF,0xAB,0x6F,0xFB,0xFE,0xFF,0xFF, +0xEF,0xFD,0xFF,0x7F,0xFF,0xFF,0xDE,0xFF, 0xFF,0xEF,0xFF,0xFF,0xFF,0x3F,0xFF,0x6C, +0xFF,0xBF,0xFB,0xFF,0xFE,0xFF,0xFB,0xFE, 0xDF,0xFF,0xFF,0xEF,0xFF,0xFF,0xBF,0xFF, +0xFF,0xFE,0xFB,0xFF,0xD5,0x7F,0xFF,0xFF, 0xEF,0xFB,0xFF,0xFF,0xBF,0xEF,0x43,0xB5, +0xFD,0x6F,0xCF,0xD6,0xBE,0x3F,0x7F,0xDB, 0xFE,0xC3,0xFF,0xFD,0xFF,0xAF,0xEB,0xFB, +0xFC,0xFF,0x3E,0xEF,0xE8,0xFA,0xBD,0xCD, 0xAA,0xFE,0xFE,0x7D,0xCF,0xFF,0xB7,0xFF, +0xF7,0xFF,0xFF,0xFF,0xFD,0xFF,0x75,0xCD, 0x52,0xD7,0xFD,0xFB,0xF7,0xDD,0xFB,0xEF, +0xEB,0xFF,0xFF,0x4F,0xFF,0xBF,0x9F,0xE7, 0xF9,0xFC,0x7F,0x8B,0xC3,0xF9,0xAF,0x8F, +0xE7,0xE9,0xBE,0x7F,0x9F,0xE6,0xF9,0xFC, 0x5F,0xFF,0xFF,0xF7,0xFD,0xFF,0x7A,0x5F, +0xD7,0xED,0xFF,0xFF,0xD7,0xFF,0xDD,0x7F, 0xE7,0xFF,0xFC,0xFF,0xFC,0x3F,0xFF,0xFF, +0xFF,0xFB,0xFF,0xFE,0xBF,0xAF,0xFF,0xFD, 0xFF,0xEF,0xFF,0xEB,0xFF,0xFF,0xFF,0xFF, +0xFF,0xF7,0x7F,0xFF,0x7F,0xDF,0xFF,0xFD, 0xFD,0x7F,0xFE,0xF7,0xFD,0x7F,0xDF,0xFF, +0xFD,0xFF,0xFF,0xDF,0xFB,0xFF,0xEE,0xFF, 0xFB,0xFF,0xF7,0xFD,0xFF,0x7A,0xDF,0xF5, +0xFD,0xFA,0xDF,0xF7,0xFC,0xFF,0x7F,0xDF, 0xBF,0xED,0xFF,0xC9,0xFF,0xDF,0xFF,0xBF, +0x2F,0xFB,0xFF,0xBC,0xAD,0xFF,0xF7,0xFF, 0xFF,0xEF,0xD3,0xFF,0x7D,0xBF,0x6F,0xFF, +0xFA,0xFF,0xFE,0xBF,0xAE,0xEA,0xFA,0xBE, 0xAD,0xA5,0xEB,0xCE,0xBF,0xA7,0xEB,0x5A, +0xDE,0xBD,0xAF,0x6B,0xFD,0x57,0xFF,0xFF, 0xF4,0x7F,0x1F,0x7F,0xFD,0xFF,0x7F,0x36, +0xF0,0xDF,0x79,0xFF,0xFF,0xFF,0xF7,0xFD, 0xBF,0xFF,0x87,0xFF,0xFB,0xF3,0xFC,0xFF, +0xFF,0xFF,0xFF,0x7E,0xFF,0xBF,0xDF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFD,0xBF,0xF8,0x9F, +0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFD, 0xF7,0xFC,0xBD,0xFF,0xFE,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFB,0xF9,0xBF,0xFF,0xFF,0xEB, 0xE2,0xFE,0xFF,0xBF,0xEF,0xA9,0xBA,0x2F, +0xEB,0xF9,0xFE,0x77,0xDF,0xF7,0xFF,0xFF, 0xF9,0x7F,0xFF,0xFF,0x7F,0xEF,0xD7,0xFF, +0xFD,0xFF,0xFB,0xF5,0xFF,0xBF,0x6F,0xDF, 0xFF,0xFF,0xFD,0xFF,0xFF,0xF0,0xFF,0xFF, +0xFF,0x3F,0xCF,0xFF,0xBA,0xEE,0x9B,0xBF, 0xEE,0xD7,0xFE,0xCD,0xEF,0xFF,0xDF,0xBF, +0xFF,0xFF,0xC5,0xFF,0xFF,0xFD,0x7F,0x4F, 0xFD,0xF6,0xD9,0xFF,0x4F,0xD6,0xFD,0xBF, +0x6E,0xFF,0xFF,0xF4,0x7F,0xFF,0x7F,0x8B, 0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xF9,0xFE, +0x37,0xFF,0xD9,0xFB,0xF5,0xAF,0xFD,0xFF, 0xFF,0xFB,0xFF,0xFF,0x07,0xFF,0xFF,0xFF, +0xFB,0xF7,0xFF,0xFD,0xFF,0x7C,0xFA,0x7E, 0x4F,0xFC,0xDF,0x1D,0xC7,0xFF,0xFF,0xFF, +0xFF,0xAE,0xFF,0xFF,0xFF,0xFF,0xFD,0xFB, 0xFF,0xFF,0xFE,0xFE,0xFC,0xFF,0x7F,0x7F, +0xBF,0xEF,0xFE,0xFF,0xFF,0xFF,0x5F,0xFD, 0xFF,0xFF,0xFF,0xFD,0x6F,0x5A,0xD7,0x7B, +0xBE,0x5F,0xFE,0x39,0xFF,0xF7,0xFF,0xF7, 0xFD,0xFE,0xAA,0x1F,0xFF,0xFF,0xFF,0xFF, +0xFE,0xFE,0xAB,0xAF,0xFD,0xFE,0xBF,0xFF, 0xF7,0xFF,0x7F,0xFE,0x8F,0xE3,0xFB,0xEE, +0x7F,0xFF,0xFF,0xFF,0xFF,0xEB,0xFB,0xFF, 0xFD,0xBF,0xEF,0xDF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFB,0xE4,0x3F,0xFF,0xDF, 0xFF,0xFF,0xFF,0xFF,0xF3,0xEF,0xBB,0xFB, +0xBF,0xEF,0xBB,0xFF,0xD7,0xBF,0xFF,0xFF, 0xFF,0x29,0xAF,0xF7,0xFF,0xFF,0xFB,0xFF, +0xFB,0xE6,0xFF,0x0F,0xFB,0x3F,0xDF,0x0F, 0xFF,0xAF,0xFF,0xFF,0xFF,0xF5,0xC3,0xDF, +0x5F,0xFF,0xFF,0xFF,0xFE,0x6B,0xCA,0xBE, 0xBC,0xFF,0x9F,0xF2,0xBF,0xFF,0xFE,0xFA, +0xFF,0xFF,0xEF,0x16,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFC,0xDF,0x97,0xFD,0x79,0xFF,0x37, +0xE7,0x7F,0xFF,0xFF,0xB5,0xFF,0xFF,0xF6, 0x2F,0xFF,0xFD,0xFB,0xFE,0xFF,0xFF,0xFD, +0x5F,0x57,0x5F,0xFF,0xDB,0x52,0xDF,0xFF, 0xFD,0xBF,0xFF,0xFF,0xFC,0xDB,0xFF,0x7B, +0xB5,0xFD,0x7F,0xFF,0x71,0x9C,0x6E,0xFF, 0xF6,0x35,0xA5,0x9B,0xFF,0xFF,0xFD,0xFF, +0xFF,0xDB,0x9E,0x7F,0xFE,0xEF,0xFB,0xFF, 0xFF,0xBD,0xEF,0xFF,0xDE,0xB7,0xF9,0x4B, +0xFF,0xF5,0xEF,0xFF,0xFF,0xFF,0xE8,0x7E, 0xFF,0xEA,0xDF,0xF7,0xFF,0xFD,0x69,0x5B, +0xFC,0x9F,0xEF,0x78,0xD6,0xFF,0xEB,0xEF, 0xFF,0xFF,0xFF,0xE8,0xFF,0xFF,0xED,0xFF, +0xFF,0xFF,0xFF,0xE3,0xF9,0xF6,0xBF,0xFF, 0xFF,0xFE,0xDF,0xFF,0x7F,0xFF,0xFF,0xFF, +0xD1,0xFF,0xFF,0xE7,0xFF,0xFF,0xFF,0xFF, 0xE7,0xF9,0xFF,0xBF,0x7F,0xD9,0xFF,0xFD, +0xFE,0x7F,0xFF,0xFE,0xFF,0xF9,0xFF,0xFB, 0xD6,0xDF,0xBF,0xEF,0x5B,0xD6,0xFF,0xBF, +0xFB,0xF6,0xFF,0xBF,0xEF,0xF8,0xF6,0xDD, 0xBE,0xFE,0x16,0xFF,0xBF,0xEF,0xFF,0xFE, +0xFF,0xBF,0xEF,0xFF,0xFF,0xFF,0x6F,0xFB, 0xFF,0xFF,0xFF,0x6F,0xF3,0xFF,0xF7,0xEF, +0xFB,0xFF,0xBF,0xFF,0xEF,0xFE,0xFF,0xBF, 0xFF,0xFF,0xFF,0xBE,0xBF,0xFF,0xEF,0xFF, +0x7F,0xEF,0xFF,0xFD,0x17,0xFB,0x7B,0xFF, 0xFF,0xFD,0x7F,0xDB,0xF6,0xF4,0x7F,0xFA, +0xFE,0xF5,0xBF,0xEB,0xE3,0xF7,0xFF,0xFF, 0xE9,0xBF,0xFF,0xAF,0xF7,0xFD,0xF3,0x7E, +0x8F,0xA3,0xEA,0xFF,0xCB,0xF3,0xEE,0xFF, 0xBF,0xEF,0xF7,0xF9,0xFF,0xFE,0x7F,0xFF, +0xFF,0xFF,0xFF,0xF5,0xFB,0xF6,0xFF,0xF5, 0x2F,0xFE,0xFB,0xD7,0xBF,0xFF,0xBE,0xDF, +0x9F,0xFF,0xF0,0xFF,0xFF,0xF9,0xFE,0x7F, 0x8F,0xA3,0xF8,0xFE,0x6F,0x9F,0xF9,0xF6, +0x2F,0x9F,0xE7,0xF9,0xFE,0x2F,0x9F,0xE1, 0xFF,0xFF,0xFF,0x7F,0xDF,0xF7,0xF5,0xFD, +0x7F,0x7F,0xF5,0xFF,0x9F,0x5F,0xFB,0xFE, 0xFF,0x7F,0xFF,0xFF,0xCB,0xFF,0xFF,0xFB, +0xFE,0xFF,0xBF,0xAF,0xFB,0xFE,0xFF,0xDF, 0xFE,0xFE,0xBF,0xF7,0xFF,0xFF,0xFF,0xFF, +0xFF,0xC7,0xFF,0xFF,0xFD,0xFF,0x7F,0xDD, 0xF7,0xFD,0xFF,0xFF,0xD7,0xFF,0xFD,0x7F, +0xFF,0xFB,0xFD,0xFF,0xFF,0xFE,0xEF,0x7F, 0xFD,0xEF,0xFB,0xFE,0xFB,0xFD,0xFF,0x7F, +0xDF,0xFD,0xFF,0x7A,0xDF,0xF7,0xFD,0xFF, 0xFF,0xFF,0xFF,0x1F,0xFF,0xFF,0xD3,0xF7, +0xFF,0xFF,0x6F,0xDB,0xFF,0xFF,0xEF,0xCB, 0xF4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, +0x29,0xFF,0xE8,0xDA,0x76,0x9F,0xAF,0x6A, 0xDA,0xFE,0x35,0xEB,0xDA,0xD6,0xBF,0xAB, +0xEB,0x7A,0xDE,0xBF,0xD7,0x7F,0xFF,0xFE, 0xFF,0xBF,0xEF,0xFD,0xDF,0x77,0xBF,0xFD, +0x37,0xEF,0xFF,0xEF,0xFF,0x3F,0xFF,0xFF, 0xFF,0xFE,0x7F,0xFF,0xFF,0xFF,0xF7,0x7E, +0xDF,0xFF,0xFF,0xFF,0xFA,0xB7,0x7F,0xFF, 0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0x89,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0x9F,0xFB,0xFF,0xFF,0xFF,0xE7,0xFF, +0xFF,0xFF,0xFF,0xAA,0xFF,0xAB,0xFB,0xFA, 0xEF,0xBF,0xFF,0xDF,0xFA,0x7B,0xB9,0xFE, +0xFE,0xFF,0xFD,0xFF,0xF7,0xFE,0x3F,0xFF, 0xB7,0xFF,0xF7,0xEE,0xFF,0x7F,0xEF,0xFF, +0xFF,0x7F,0xFF,0x1F,0xFB,0xFF,0xBF,0xFB, 0xFE,0xFF,0xBD,0xFF,0xFF,0x2F,0xFF,0xBF, +0xFF,0x7F,0xDF,0xFA,0xFF,0xFF,0xFC,0xEE, 0xF5,0xF3,0xBE,0xFB,0x0F,0xEF,0xF3,0xBE, +0xEF,0xFC,0x5F,0xFF,0x5A,0xFF,0xF7,0xDF, 0xFF,0xFF,0xFE,0xD5,0xFC,0x5F,0xFB,0xF2, +0xFF,0xFF,0x2F,0xBB,0xF3,0xFF,0xFF,0xBF, 0xFF,0xEF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF, +0xBF,0xFF,0xFF,0xFD,0x7B,0xFF,0xDF,0xB9, 0xFF,0xFB,0xFF,0xD8,0x7F,0xFF,0xFF,0xFF, +0xFB,0xFF,0xFC,0x7F,0x1F,0xBF,0xE0,0xDF, 0xF7,0xEF,0xFF,0xFD,0x7F,0xFE,0xDF,0xFF, +0xE0,0xFF,0xFF,0xFD,0xEF,0xFB,0xFF,0xFE, 0xF7,0xDF,0xFF,0xEB,0x5F,0xFF,0xF7,0xFF, +0xFF,0xFF,0xFF,0xBF,0xFF,0xFD,0xFF,0xFD, 0xFF,0xFF,0xFF,0xF7,0xFD,0xFF,0x3B,0xDC, +0xFD,0x6D,0x7B,0x5F,0x57,0xF5,0xFD,0x7F, 0x5F,0xFF,0xB1,0xFF,0xEB,0xFF,0xFF,0xFF, +0xFB,0xFB,0xFE,0xFF,0xBF,0xFB,0xBE,0xFF, 0xBF,0xEF,0xFB,0xFE,0xFF,0xAF,0xFE,0xF7, +0xDF,0xDF,0xFF,0xFF,0xFF,0x7F,0xCF,0xF3, 0xF8,0xFF,0xD7,0xFB,0xFF,0x5F,0xBF,0xF7, +0xFB,0xFF,0x7F,0xFE,0x23,0xFF,0xFF,0xFE, 0x7F,0xF3,0xFF,0xFB,0xFE,0xFF,0xFF,0xF3, +0xFF,0xFF,0xF5,0xF9,0xFF,0x3F,0xFF,0xFF, 0xF0,0x9A,0xFF,0xBE,0x7F,0xFF,0xFC,0xF9, +0xFF,0xFD,0xAF,0xEB,0xFE,0xBF,0xFF,0xCF, 0xF3,0xFE,0x7F,0xFF,0xFF,0x5B,0xBD,0xFF, +0xBC,0xEB,0xFF,0xD7,0xD4,0xAF,0xAF,0xFD, 0xFF,0xCF,0xF7,0xFD,0xFF,0x7F,0xDF,0xF7, +0xFD,0xFE,0xFF,0x6F,0xFF,0xFB,0xFF,0xFF, 0xFF,0xFD,0x7F,0x5E,0xFD,0xBF,0xDB,0xF6, +0xFD,0xBF,0x6F,0xFB,0xEE,0xFD,0xFF,0x7A, 0xFF,0xFA,0xFB,0xFF,0x3F,0xFB,0xB7,0x5F, +0xD6,0xF7,0x1F,0x71,0xDC,0x77,0x1D,0xC7, 0x31,0xDC,0x77,0xDF,0xF9,0xBF,0xF5,0x5B, +0xF4,0xD7,0x9D,0xAE,0xFF,0xBF,0xFD,0xBF, 0xDB,0xF6,0xFD,0xBF,0x6F,0xDB,0xF6,0xFE, +0x3D,0x81,0xFF,0xEB,0xFE,0xFE,0xFE,0xFF, 0xEB,0x7A,0xDF,0x7D,0x77,0x7D,0xF5,0x79, +0xDF,0x57,0xDD,0xF5,0x7D,0x7E,0xE6,0xFF, 0xD6,0x3F,0xBF,0x7F,0xFF,0xD4,0xF5,0x3F, +0xBF,0xFB,0xBE,0xEF,0xB3,0xEE,0xFB,0x9E, 0xEF,0xBB,0xFE,0x8B,0xFF,0xFE,0xDF,0xB7, +0xED,0xFF,0xF7,0xFD,0xFE,0xFF,0xEF,0xBB, 0xEE,0xFF,0xBE,0xEF,0xBB,0xEE,0xEB,0xFC, +0x1F,0xFF,0xFF,0xFD,0xFF,0xE7,0xFF,0xF7, 0xFD,0xFF,0xEF,0xFE,0xFF,0xBF,0xEF,0xFB, +0xFE,0xFF,0xBF,0xEB,0xFA,0x1F,0xFF,0xB7, 0xEF,0x5B,0xFE,0xFF,0xAF,0xEB,0xDD,0xE7, +0xDE,0x77,0x9D,0xE7,0x79,0xDE,0x77,0x9D, 0xBF,0xE6,0x6F,0xFF,0xFE,0xFF,0xBF,0xEF, +0xFB,0xFE,0xFD,0xBF,0x6F,0xF6,0xFD,0xBF, 0x6F,0xDB,0xF6,0xFD,0xBF,0xFF,0x7E,0xFF, +0xFF,0xFB,0xFE,0xFE,0xFF,0xEF,0xFB,0xFD, 0xEF,0x7E,0xF7,0xBD,0xEF,0x7B,0xDE,0xF7, +0xBD,0xEF,0xFF,0xD5,0xFF,0xBF,0xFF,0xEF, 0xFE,0xFF,0xFC,0x3F,0x0F,0xE7,0xFE,0x7F, +0x9F,0xE7,0xF9,0xFE,0x7F,0x9F,0xE7,0xFE, 0xF3,0xFF,0xFE,0xDF,0xAD,0xDF,0x67,0xEE, +0xFB,0xBF,0xEF,0xFE,0xFF,0xBF,0xEF,0xFB, 0xFE,0xFF,0xBF,0xEF,0xFF,0x23,0xFF,0xFF, +0xFF,0xFF,0x7F,0xFF,0xF3,0xBC,0xDB,0xFE, 0xFB,0xFF,0xFB,0xBE,0xF7,0xFB,0xFF,0x7F, +0xDF,0xFF,0xCF,0xFB,0xFF,0x9F,0xE3,0xF9, 0xBE,0x3F,0x8F,0xE7,0x79,0xFF,0x9D,0xE7, +0xF9,0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x5F, 0xFF,0xCF,0xF7,0xFF,0xFF,0xFF,0xDF,0xF7, +0xFE,0x7F,0xE7,0xF9,0xFE,0x7F,0xFF,0xFF, 0xFB,0xFE,0xFF,0xFF,0xBF,0xFF,0xBF,0xBF, +0xFF,0xFE,0xFF,0xBF,0xEF,0xFF,0xFD,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFD,0xFF, +0xFF,0x3F,0xFF,0xBF,0xFF,0xF7,0xFF,0xFF, 0x7F,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xE8,0xEF,0xFF, 0x5F,0xF7,0xBF,0xF9,0xFE,0xDF,0xB7,0xFD, +0xFF,0xDF,0xF7,0xFD,0xFF,0x7F,0xDF,0xF7, 0xFD,0xFF,0xDD,0xFF,0xF2,0xFF,0xBF,0xFF, +0xFF,0xBF,0xFF,0xFF,0x2F,0xF2,0xFF,0xBF, 0x2F,0x7B,0xD2,0xF7,0xBF,0x2F,0xFF,0xBB, +0xFF,0xEE,0x8F,0xAF,0xEB,0xFA,0xFE,0x3F, 0xA7,0x69,0xCE,0x8F,0xA4,0xEA,0xFA,0xEE, +0xB7,0xAE,0xEB,0xFD,0xC7,0xFF,0xF7,0xF7, 0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x3E,0xF3, +0x74,0xFF,0x3F,0x4F,0xFF,0xE7,0xFF,0x3F, 0xFE,0xA7,0xFF,0xFF,0xDF,0xF7,0xB7,0xFF, +0xF7,0xFF,0xBA,0xEF,0x37,0xEB,0xFB,0xFE, 0xBF,0xFB,0xFE,0xF3,0xFF,0xF9,0xDF,0xFF, +0xBF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF, 0xFD,0xDF,0xFF,0xFD,0xFF,0xFF,0xFB,0xFE, +0xFD,0xFF,0xFB,0xBF,0xFE,0x3F,0xED,0xFF, 0xDF,0xBE,0x3D,0xA7,0xFB,0xFA,0x3F,0xE6, +0xE1,0xFE,0xFE,0x3F,0xEF,0xE3,0xDF,0xF5, 0x7F,0xFE,0xFF,0x7E,0xFF,0xFF,0xFF,0xFF, +0xEF,0x6F,0xF6,0xFF,0x7D,0xEF,0xD7,0xDE, 0xFF,0x7D,0xEF,0xFF,0xF2,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0x7B,0xDE,0xFB,0xE6,0xEE, 0xEF,0x37,0x6E,0xF3,0x7E,0xEB,0x37,0xEF, +0xFF,0xC1,0xFF,0xFE,0xFF,0xF7,0xEF,0xFF, 0xFF,0xFF,0xBF,0x3F,0xD2,0xDF,0xBF,0x2F, +0x7B,0xE2,0xFF,0xFE,0x3B,0xBD,0xDB,0xFF, 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFE, +0xFF,0xFB,0xFF,0xFF,0xBF,0xFF,0xFB,0xDF, 0xFF,0xBF,0xFF,0xB7,0xFF,0xFF,0xBF,0xEF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0xFF, 0x7F,0xFF,0x1F,0xEF,0xF1,0xFD,0xFF,0xF6, +0xAF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF, 0xFF,0xFF,0xFE,0x9F,0xFF,0xFF,0xFF,0x77, +0xEF,0xF7,0xFB,0xFF,0xFE,0x5F,0xFF,0xFF, 0xBF,0xCF,0xFB,0xF7,0xDD,0xF7,0xF5,0xFF, +0x5F,0xD5,0xF5,0xFD,0x7F,0x5F,0xD7,0xF5, 0xFF,0xFB,0x0F,0xFF,0xFF,0xA9,0xEA,0x7A, +0xFF,0xAF,0x8F,0xFE,0xDF,0xAF,0xEF,0xFB, 0xFE,0xFF,0xBF,0xEF,0xFB,0xDF,0xE5,0x5F, +0xFF,0xFF,0xFF,0xFF,0xFF,0xBD,0x57,0xFF, 0xFF,0x6F,0x77,0xBF,0xF7,0xFB,0xFF,0x7F, +0xBF,0xF7,0xFF,0xFC,0xBF,0xFF,0x9F,0xFF, 0xFF,0xEF,0xFF,0xFE,0xFF,0xFF,0xFF,0x1F, +0xCF,0xFF,0xFC,0xFF,0xFF,0xFF,0xFF,0xFB, 0x65,0xAF,0xF3,0x7C,0xFF,0x3F,0xDF,0xFF, +0xFD,0xE9,0xFE,0x7F,0xE7,0xFF,0xFE,0x7F, 0xFF,0xFF,0xFF,0xFF,0xFD,0xE3,0xDF,0xFB, +0xDB,0xF6,0xFD,0xEF,0x5B,0xFB,0xFF,0xDF, 0xFC,0xFF,0x3F,0xDF,0xF3,0xFD,0xFF,0x7F, +0xDF,0xEF,0x66,0xFF,0xDF,0xAD,0xEB,0x7A, 0xDE,0xF7,0xF7,0xE7,0xD9,0xFD,0x9F,0x67, +0xD9,0xF6,0x7D,0x9F,0xE7,0xDF,0xF5,0x47, 0xFD,0x65,0x5B,0xD6,0xF4,0xFE,0xFF,0xEF, +0xFF,0x6D,0xF6,0xDD,0xB7,0x6D,0xDB,0x76, 0xDC,0xB7,0x7D,0xFA,0x9B,0xF6,0x6D,0x9D, +0x67,0x59,0xDF,0xF7,0xDD,0xFF,0xEB,0xFE, 0xBF,0xAF,0xEB,0xFA,0xFE,0xBF,0xAF,0xE3, +0xD1,0x9F,0xFF,0xBD,0xBF,0xEF,0xFE,0xF7, 0xBF,0xBF,0xF7,0xD7,0x7F,0xDD,0xF7,0x9D, +0xDF,0x7F,0xDF,0xF7,0xFF,0xE0,0x7F,0xFD, 0xC1,0xDF,0xF7,0xFD,0xC7,0x7F,0x7F,0xFB, +0xFF,0xBB,0xEC,0xFB,0x3E,0xFF,0xBF,0xEC, 0xFB,0xFF,0xD8,0x7F,0xBF,0x6C,0xFF,0xBE, +0xFF,0xBF,0xED,0xFF,0xEF,0xFE,0xFB,0xBF, 0xEF,0xFB,0xFE,0xFF,0xBF,0xEE,0xFF,0xC5, +0xFF,0xAF,0x6F,0xFF,0xFC,0xFD,0x3F,0xE7, 0xFF,0xFE,0xFF,0xEF,0xFB,0xFE,0xFF,0xBF, +0xEF,0xFB,0xFE,0xBF,0x89,0xFE,0xFA,0xBA, 0xFE,0xBF,0xAF,0xFB,0xF6,0xF5,0xD9,0x7D, +0x97,0x65,0xD9,0x74,0x5D,0x97,0x65,0xD3, 0xFE,0xD6,0xFF,0xBF,0xF7,0xFD,0xFF,0x7F, +0xBF,0xCF,0xFB,0xFE,0xFF,0xEF,0xFB,0xFE, 0xFF,0xBF,0xEF,0xFB,0xFF,0xF6,0x8F,0xFB, +0xFF,0xEF,0xFB,0x7E,0xDB,0xFE,0xFF,0xBE, 0xEF,0xEE,0xFB,0xBE,0xEF,0xBB,0xEE,0xFB, +0xBE,0xFF,0xFF,0xDF,0xFF,0x43,0xFF,0xFF, 0xFB,0xEF,0x5F,0xB7,0xFE,0x7F,0xE7,0xF9, +0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x7F,0xF9, 0xBF,0xFE,0xAF,0x77,0xFD,0xFF,0x2F,0xAF, +0xA7,0xFE,0xFF,0xEF,0xFB,0xFE,0xFF,0xBF, 0xEF,0xFB,0xFE,0xFF,0xF1,0x7F,0xEF,0xDF, +0xFF,0x97,0xF5,0xEF,0xFF,0xDF,0xFF,0xFF, 0xBF,0xFF,0xBF,0xFF,0xFF,0xFE,0xFF,0xFF, +0xFF,0xE0,0xFF,0xFF,0xF9,0xFE,0x2F,0x8B, 0xE3,0xF8,0xBE,0x77,0x9F,0xF9,0xDA,0x77, +0x9D,0xE7,0x79,0xDE,0x77,0x9F,0xDD,0xFF, 0xFD,0xFD,0x7F,0x5F,0xD7,0xFD,0xFF,0x7F, +0xE7,0xFE,0x7F,0x97,0xE7,0xFB,0xFE,0xFF, 0xBF,0xEF,0xFF,0xAB,0xFF,0xEF,0xFA,0xFE, +0xBF,0xAF,0xFF,0xFA,0xFF,0xFF,0xDF,0xFF, 0xFB,0xFF,0xF7,0xFD,0xFF,0x7F,0xDF,0xFF, +0x67,0xFF,0xF7,0xF5,0xFF,0xFF,0xFF,0xDF, 0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xBD, 0xEB,0xFF,0xFF,0xF7,0xAD,0xEB,0xFF,0xDF, +0xFD,0xFF,0x3F,0xDF,0xF7,0xFD,0xFF,0x7F, 0xDF,0xFF,0x5F,0xFF,0xF7,0xFF,0xFF,0xFD, +0xBF,0xFF,0xCB,0xF4,0xFF,0x7F,0xD3,0xF7, 0xFD,0x3F,0x7F,0xD3,0xF7,0xFF,0xFC,0x3F, +0xFF,0xEA,0xFA,0xBE,0xAF,0xAB,0xEB,0xBA, 0xF4,0x95,0x6B,0x52,0xD4,0xAD,0x2F,0x4A, +0xD2,0xF6,0xBF,0xD2,0x7F,0xF7,0x3F,0xFF, 0xFF,0xF3,0x7F,0xFF,0xFF,0xF7,0xFF,0xBA, +0xDF,0xFB,0xFD,0xFF,0xBF,0xFF,0xFB,0xFF, 0xF8,0x7F,0xEA,0xFF,0xFE,0xFE,0xDF,0xFF, +0xF7,0xFF,0x7F,0xBB,0xFF,0xFF,0xBF,0xDF, 0xFB,0xFF,0xFF,0xBF,0xFF,0xB1,0x7F,0xFF, +0xFB,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF, 0xCF,0xFE,0xFF,0xFF,0xEF,0xFF,0xF7,0xFF, +0xFF,0xFF,0xF1,0xFF,0x69,0xBE,0xFA,0xBF, 0xAF,0xE2,0xFF,0xFE,0xFD,0xAF,0xF3,0xFE, +0xFF,0xBF,0xEF,0xFB,0xFC,0xFF,0xFF,0x07, 0xFD,0x95,0xDB,0xDF,0x7F,0xDF,0xAF,0xFF, +0xF7,0xAF,0x36,0xFE,0xBF,0x65,0xEB,0xF6, 0xFE,0x9F,0x6F,0xFE,0x07,0xFF,0xCF,0xFF, +0xF8,0xFE,0xFF,0xCF,0xFF,0xF6,0xFA,0xE7, 0xFB,0xFE,0xFF,0xBB,0xED,0xF9,0xFF,0xFF, +0xFF,0x5F,0xFF,0xFF,0xFF,0x75,0xFF,0xEF, 0x7E,0xFD,0xE0,0xE8,0x5E,0xD3,0xE5,0xF9, +0x3E,0x5F,0xD7,0xF7,0xFF,0xFA,0x2F,0xFB, 0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0x7F, +0x7F,0xD7,0xF5,0x7D,0x5F,0x57,0xD5,0xF5, 0xEF,0xFF,0xF3,0x7F,0xFC,0x7F,0xFF,0xC7, +0xF1,0xFF,0xFF,0x1F,0xCF,0xB0,0xFF,0x3F, 0xCF,0xF3,0xFC,0xFF,0x3F,0xCE,0xFF,0xE4, +0xFF,0xDF,0x7F,0xFE,0xF7,0xBB,0xFF,0xFF, 0xDF,0xEF,0xEE,0xFF,0xBF,0xEF,0xFB,0xFE, +0xBF,0xBF,0xEF,0xFF,0xD1,0xFF,0xFF,0xFF, 0xFD,0xFB,0xFF,0xFD,0xFF,0xFB,0x9F,0xE9, +0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x7F,0xBF, 0xFF,0xB3,0xFF,0xFF,0xF7,0xFF,0xFF,0xAF, +0xF7,0xFF,0xB6,0x3F,0xEB,0xFA,0xFE,0xBF, 0xAF,0xEB,0xFA,0xFE,0xBF,0xFE,0xA7,0xFF, +0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF, 0xFE,0x9F,0xF7,0xF9,0xFF,0x7F,0x9F,0xE7, +0xFF,0xFF,0xFE,0xAF,0x6F,0xFF,0xFF,0xFF, 0x9F,0xFF,0xDF,0xFF,0x7D,0x5F,0xDD,0xFF, +0xFB,0xBF,0xE7,0xBB,0xFF,0xFB,0xDF,0x6D, 0x5F,0x7E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xEB,0xF7,0xFF,0xE7,0xEF,0xF7,0xFF,0xFF, 0x7F,0xFF,0xF7,0xFF,0xFC,0x8F,0xFF,0xEF, +0xFD,0xFE,0xFF,0xBE,0xF4,0xF2,0x7D,0xD7, 0xCF,0xFF,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xCF,0x6B,0xFF,0xBF,0x3F,0xFB,0xF2, 0xFC,0x7F,0xEB,0xFF,0x9F,0xFA,0xFF,0xFF, +0x3F,0xFF,0xF3,0xFF,0xFF,0xFD,0x70,0xF7, 0xFF,0xFF,0xBF,0xFF,0xFB,0xD7,0xFE,0xF5, +0x77,0xFF,0x15,0xDD,0x77,0xFD,0xFF,0x7F, 0xDF,0xF7,0xFB,0xCD,0xBF,0xFF,0xFD,0xFF, +0xFF,0xDF,0x37,0xCD,0xF9,0xEC,0xFE,0xEF, 0xBB,0xF4,0xFB,0x3F,0x4F,0xB3,0xFF,0xFD, +0xCB,0xFF,0xE9,0x7E,0x54,0x9F,0xE5,0x4B, 0xB7,0xFF,0xDD,0x7D,0xC7,0x71,0xDD,0x77, +0x5D,0xD7,0x75,0xCD,0x7F,0xD6,0xFF,0xD3, 0xF6,0xF9,0x3F,0x6D,0x95,0xAF,0x7F,0xFE, +0xFF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB, 0xFE,0xF6,0xC7,0xFF,0xAD,0x7B,0xCA,0xFF, +0xBF,0xBF,0xEF,0xFD,0xE3,0xDF,0xB7,0xED, 0xFB,0x7E,0xDF,0x37,0xED,0xE3,0xFB,0xDF, +0xFF,0x52,0x5C,0x15,0xFD,0xCF,0x7F,0xDF, 0xFE,0xEF,0xEF,0xFB,0xFE,0xFF,0xBF,0xEC, +0x7B,0xFE,0xFF,0xFE,0x3E,0x7F,0xDA,0xF7, 0xFD,0xFF,0x7F,0xFF,0xFF,0xFB,0xEF,0xBB, +0x6F,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB,0xFF, 0xF7,0x7D,0xFF,0xD8,0xFF,0xFD,0xBF,0x7F, +0xFB,0xFF,0xFF,0x9F,0xFB,0xFE,0x7F,0x9F, 0xE7,0xF9,0xFE,0x7F,0x9F,0xEA,0x7F,0xF6, +0xBF,0xBD,0x6A,0x5A,0xF6,0xE5,0xBF,0x77, 0x5F,0x6D,0xDD,0x77,0x5D,0xD7,0x75,0xDD, +0x77,0xFF,0xA5,0xBF,0xCF,0xFB,0xFF,0xFF, 0xBF,0xCF,0xFB,0xFD,0xFF,0xBF,0xF3,0xFE, +0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xFD,0xAB, 0xFF,0xBF,0xBF,0xFF,0xFB,0xFF,0x7F,0xEF, +0xFF,0xBE,0xFB,0xEE,0xFB,0xBE,0xEF,0xBB, 0xEE,0xFB,0xBF,0xFF,0xB5,0xFF,0xD0,0xBC, +0xFD,0x2F,0x4B,0xF7,0xFF,0xFF,0x9F,0xF9, 0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x7F,0x9F, +0xFA,0x8F,0xFD,0xAB,0xFA,0xDA,0xBF,0xAF, 0xB3,0xFD,0xFF,0xBF,0xFB,0xFE,0xFF,0xBF, +0xEF,0xFB,0xFE,0xF7,0xBF,0xFF,0x9F,0xFF, 0x77,0xF7,0xBD,0xFD,0x77,0xDF,0xFF,0x7E, +0xDF,0xED,0xBB,0xFE,0xFF,0xBE,0xEF,0xFB, 0xFE,0xFF,0xFA,0x3F,0xFF,0xBE,0x6F,0x8F, +0xE6,0xF9,0xFE,0x7F,0x9F,0xC7,0xFE,0x7F, 0x9F,0xE7,0xF9,0xFE,0x7F,0x9F,0xE7,0xFB, +0x7F,0xFF,0x7F,0xCF,0xFF,0xFD,0xFF,0xFF, 0xDF,0xFB,0xAF,0xBF,0xEF,0xFF,0xFE,0xFF, +0x9F,0xEF,0xFB,0xFF,0xFC,0xFF,0xFB,0xFE, 0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xF7, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xF5,0xFF,0xFF,0xFF,0x3F,0xDF,0xF7, +0xFF,0xFF,0x7F,0xEF,0xFE,0xFF,0xBF,0xFF, 0xFB,0xFF,0xFF,0xBF,0xEF,0xFF,0xB3,0x7F, +0xFF,0x7B,0x5E,0xF7,0xFD,0xFF,0x7B,0x7F, 0xF7,0xFF,0x7F,0xDF,0xF7,0xFD,0xFF,0x7F, +0xDF,0xF7,0xFF,0x17,0xFF,0xFF,0xFF,0x7F, 0xFF,0xFF,0xDD,0xF6,0xFC,0xBF,0xCB,0xF2, +0xBC,0xBF,0x2F,0xCB,0xF2,0xFC,0xBF,0xFE, 0x8F,0xFF,0xFA,0x7E,0xBF,0xA7,0xEB,0xDA, +0xFC,0xBF,0xAF,0x7A,0xFE,0xBF,0xAF,0xEA, 0xFA,0xFE,0xBF,0xAF,0xF4,0xDF,0xFE,0xFF, +0xF3,0x3C,0x7F,0x3E,0xFF,0xCF,0xF8,0xBF, 0x8F,0xE3,0xF8,0xFE,0x3F,0x8F,0xE7,0xE8, +0xFF,0xFC,0x9F,0xFF,0xFF,0xCF,0xEB,0xB3, 0xE7,0xFB,0x7B,0xF3,0xFE,0xFF,0xCF,0xDB, +0xFB,0xFB,0xBF,0x6F,0x6F,0xDF,0xEC,0x7F, 0xFF,0xFF,0xF7,0xFD,0xFD,0xFF,0xFF,0xFF, +0xFF,0xB2,0xBF,0xFF,0xDE,0xFD,0xBD,0xEF, 0xFB,0xF6,0xDF,0xEA,0xE7,0xDB,0xFE,0xBB, +0xFF,0xEB,0xFB,0xBF,0x9F,0x8F,0xE8,0xFE, 0x3F,0x8F,0xA3,0xF8,0xFE,0x3F,0x8F,0xFF, +0xF8,0x7E,0xFD,0xFD,0x7F,0xFF,0xFB,0xCD, 0xFF,0xFD,0xFF,0x5F,0xEF,0xFD,0xFF,0xFF, +0xDF,0xF7,0xFD,0xFF,0xBE,0x90,0xFF,0xFF, 0xEE,0xFF,0x3F,0xBF,0xF3,0xBB,0xFE,0xB7, +0xAB,0xFA,0xFE,0xAF,0xAD,0xEA,0xFA,0xDE, 0xAB,0xFF,0x63,0xFF,0xFE,0xF2,0xFF,0xB3, +0xFF,0xDF,0xEE,0x7D,0xFF,0x03,0xF1,0xF4, 0x3F,0x1F,0xC3,0xF1,0xEC,0x7F,0xFE,0x6F, +0xFF,0xFB,0xFB,0xFF,0x9F,0xFF,0xBF,0xFF, 0x7B,0x5F,0xFD,0xFF,0xDF,0xF7,0xFD,0xFD, +0x7F,0x7F,0xDF,0xFE,0xCF,0xFB,0xFF,0xFF, 0xAF,0xFB,0xFF,0x1F,0xEF,0xA5,0xFD,0xBF, +0xDF,0xFB,0x7D,0xFF,0xBF,0xDF,0xFB,0xFF, 0xFD,0x3B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD, +0xAF,0xF3,0xFF,0xFB,0x7F,0xBF,0xD7,0xFB, 0xBF,0x7F,0xBB,0xF7,0xFF,0xF8,0x7F,0xFF, +0xFA,0x5F,0xD7,0xFF,0xDF,0x7F,0xEF,0xFF, 0xFF,0x7F,0xDB,0xF7,0xFD,0xFF,0x7F,0xDF, +0xB7,0xFB,0xEC,0xFF,0xFF,0xF7,0xBF,0xEF, 0xFD,0xFC,0xFB,0xFF,0xEF,0xF0,0xFE,0x3F, +0x8F,0xE3,0xF8,0xFE,0x3F,0x8F,0xEF,0x8D, 0xFF,0xFF,0xEF,0x7F,0xBF,0xFF,0xFB,0xFF, +0xDB,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xEF,0xD8,0xFF,0x2E,0x7F, +0xBE,0xEF,0xFE,0x6E,0xFF,0xBF,0xF9,0xFF, 0xFF,0xF3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFC,0x66,0xBE,0x47,0xF3,0x7F,0xDF,0xFE, 0x87,0x9F,0xFF,0xFF,0xFF,0xFF,0xE7,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xD6,0x6F,0x7C, 0xFB,0x4F,0xD2,0xFF,0xFD,0x2B,0xFE,0xFF, +0xFF,0xFD,0x5F,0xD7,0xD5,0xF5,0x7D,0xFF, 0xFF,0xFF,0xBF,0x9B,0xFF,0xFF,0xDF,0xB7, +0xFF,0xFF,0xDF,0xFF,0x3F,0xCF,0xFE,0x7F, 0xBF,0xEF,0xFB,0xFC,0xFF,0x3F,0xFF,0xD9, +0xBF,0xFE,0x97,0xEC,0x8F,0xB7,0xFE,0x9B, 0x7D,0xFD,0xB7,0xDD,0x77,0x1D,0xC7,0x71, +0xDD,0x77,0x5D,0xD7,0xF3,0x6F,0xFD,0x3F, 0x73,0xDD,0xAF,0xFD,0x7A,0xFF,0xFF,0xAF, +0xFE,0xFD,0xBF,0xEF,0xFB,0xFE,0xFF,0xBF, 0xEF,0x66,0x7F,0xFF,0xFF,0xBF,0xBF,0xFF, +0xFB,0xFF,0xF7,0xDF,0xFD,0xFB,0x7D,0xDF, 0xB7,0xCD,0xF3,0x7C,0x5F,0x3F,0x91,0x3F, +0xFF,0x3D,0xEF,0x7B,0xFF,0xFC,0xFF,0xCA, 0xEF,0xFE,0xFF,0xBD,0xEF,0xFB,0x1E,0xE7, +0xBB,0xEC,0x7F,0xB3,0xFF,0xFD,0x9F,0xFF, 0xFF,0xFE,0xFF,0xFF,0x7F,0xBF,0xFB,0xFE, +0xFF,0xBF,0xEF,0xFB,0xEE,0xFB,0xBF,0xDF, 0x67,0xFF,0xFF,0xBF,0xEF,0xDB,0xFF,0xBC, +0xFE,0x7F,0xFB,0xFF,0x9F,0xEF,0xF9,0xFE, 0x7F,0x9F,0xE7,0xF9,0xFE,0x87,0xFF,0xEE, +0xFB,0xBE,0xE5,0xBF,0xEF,0xF9,0xD7,0x65, 0xF7,0xDD,0xE7,0x7D,0xDF,0x77,0x5D,0xD7, +0x7F,0xF8,0x9B,0xFE,0xFF,0xBF,0xEF,0xFB, 0xFF,0xFF,0xBF,0xEF,0xFB,0xFF,0x7F,0xCF, +0xF3,0xFC,0xFF,0xBF,0xEF,0xFF,0xDB,0x3F, 0xEF,0xFB,0xFE,0xFF,0xDF,0xFF,0xFE,0xFB, +0xBB,0xEF,0xBF,0xEF,0xBB,0xEE,0xFB,0xBE, 0xEF,0xBB,0xFF,0xFC,0x7F,0xFD,0x3B,0x5B, +0xD6,0xE5,0xFD,0x4F,0xC3,0xFB,0xFF,0xBF, 0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB,0xFF, +0xB4,0xFF,0xFA,0xBC,0x8F,0xB2,0xE9,0xD2, 0x2E,0xCF,0xFB,0xFF,0xBF,0xEF,0xFB,0xFE, +0xFF,0xBF,0xEF,0xFB,0xFF,0xEC,0xFF,0xFD, 0xFD,0x7F,0xDF,0xF7,0xE4,0xDF,0x5F,0xFF, +0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xC3,0xFF,0xEF,0xE6,0xF8,0xFE, +0x3F,0x8B,0x83,0xF9,0xFE,0x7F,0xE7,0xF9, 0xFE,0x7F,0x9F,0xE7,0xF9,0xFE,0x7F,0x17, +0xFD,0xFF,0xFF,0xFF,0x7F,0x5F,0xF7,0x2C, 0xFF,0xFF,0xFF,0xFE,0x7F,0xFF,0xE7,0xF9, +0xFE,0x7F,0x9F,0xFE,0x2F,0xFF,0xFF,0xEF, 0xFF,0xFE,0xBF,0xEF,0xAD,0xFF,0xFF,0x7F, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFE,0xDF,0xFF,0xDF,0xFF,0xFD,0xFD,0x7F, +0xDF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFA,0x3F,0xFE, +0xF7,0xFD,0xEF,0x7A,0xFF,0xB1,0xBD,0xFF, 0x7F,0xF7,0xFD,0xFF,0x7F,0xDF,0xF7,0xFD, +0xFF,0x7F,0xF3,0x27,0xFF,0xDF,0xFF,0xDD, 0xFF,0xFC,0x9B,0xFF,0xCB,0xFC,0xBF,0x2F, +0xCB,0xF2,0xFC,0xBF,0x2F,0xC9,0xFF,0xDE, 0xFF,0xDF,0xAF,0xEB,0xDA,0xFE,0xBB,0xAF, +0xEB,0xF8,0xF7,0xAF,0xE8,0xFA,0xFE,0xBF, 0xAF,0xEB,0xF2,0xFF,0xFD,0xFF,0xFF,0xEF, +0xBD,0xD7,0xBF,0xFF,0xFF,0xDE,0x8F,0xB8, 0xDE,0x37,0x8D,0xA3,0x78,0xDA,0x3F,0x8F, +0xFF,0xA1,0xFF,0xFF,0xFB,0xFB,0xFF,0xFF, 0xFF,0xFF,0xA7,0xBD,0xFB,0x76,0xFD,0xBF, +0xEF,0xDB,0xFE,0xBB,0xBF,0xFE,0x27,0x7F, 0xFF,0xFE,0xFE,0xFD,0xF5,0xFF,0xEF,0xF5, +0xDF,0x1F,0xE7,0xFD,0xFF,0x7F,0xDF,0xF7, 0xFD,0xFF,0xFF,0xCD,0xFD,0xAE,0xFF,0xFA, +0x3E,0x3F,0xAB,0xFD,0xF8,0x7E,0x8F,0xE3, 0xF8,0xFE,0x3E,0x8F,0xE3,0xF8,0xFF,0xFE, +0x1F,0xEF,0xDF,0xBF,0xFE,0xDE,0xDF,0xD9, 0xFF,0xDF,0xBC,0xFF,0xFF,0x7F,0xFF,0xEF, +0xFD,0x7F,0xDF,0xF7,0xF9,0x3F,0xFE,0xFF, 0xFF,0x6F,0xFE,0xDE,0xBF,0xF7,0xED,0xEA, +0xFD,0x8F,0x83,0xF8,0xEA,0x3F,0x8F,0xEF, 0xFF,0xF4,0x7F,0xFF,0xEF,0xEF,0x7B,0xF3, +0xF1,0x5F,0xFF,0xFF,0xF1,0x3B,0x7F,0xDF, 0xF7,0xFD,0xFF,0xFF,0xFF,0xFF,0xE0,0xFF, +0xFF,0xFF,0xF7,0xFF,0x6F,0xFF,0x7F,0xFF, 0xFF,0xF7,0xDE,0xF7,0xBF,0xEF,0xFB,0xF7, +0xFD,0xFF,0xFF,0xF5,0xFA,0xFF,0xFF,0xFB, 0xE7,0xFF,0xF3,0xF8,0x7F,0xF3,0xDF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F,0xEF, 0xBB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD, +0xFF,0x7F,0xFF,0x9F,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xCF,0xFF,0x37,0xFF,0xFF, +0x7F,0xDF,0x77,0x5D,0xE7,0xFC,0xFF,0xBF, 0xF7,0xF5,0xFB,0xFF,0xFF,0xD7,0xF5,0xFB, +0xFF,0xFF,0x45,0xFD,0x7F,0xEA,0xFD,0xBE, 0xBF,0xDF,0xF7,0xFF,0xFF,0xDB,0xFB,0xFE, +0xFF,0xBF,0xEF,0xFF,0xFF,0xFF,0xFB,0x5F, 0x7F,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFE,0xFF,0xEF,0xFD,0xFF,0x7F,0xDF, 0xFF,0xEF,0xFB,0xF8,0x0F,0xF3,0xFF,0xF9, +0x2E,0xFB,0xFE,0xFC,0xF3,0xEF,0xFF,0xFF, 0xBF,0xFF,0xFB,0xE7,0xFF,0xFE,0x7E,0xFF, +0xC0,0x6B,0xCF,0xFF,0x34,0xDF,0xF1,0xFD, 0xFF,0xEF,0xFF,0xFF,0xFF,0xDF,0xF7,0xFD, +0xCF,0x7F,0x9C,0xFD,0xFD,0x6C,0xF7,0xFF, 0xF6,0xFD,0xEB,0x2B,0x9F,0xFF,0xFC,0xFE, +0x7E,0xFF,0xFF,0xFF,0xFF,0xD7,0xF3,0xF7, 0xFF,0xFB,0xE1,0xBF,0xFF,0xEB,0x7A,0xDE, +0xD7,0xFB,0xFF,0xF9,0xFE,0xFF,0xFF,0xF3, 0xDE,0x7F,0xFD,0xE7,0x7F,0xFF,0xFD,0xBB, +0xFF,0xFF,0x7E,0xCC,0xF6,0xAF,0x5F,0x7F, 0xFE,0xF4,0x7D,0xF7,0xFD,0xBB,0x6E,0xDB, +0xB7,0xFF,0xF7,0xDF,0x66,0xFF,0xFF,0xF7, 0x3D,0xCF,0xDE,0xBD,0xFF,0xFF,0xDE,0xDB, +0x8D,0xF7,0x7E,0xDF,0xB7,0xEF,0x7F,0xFF, 0xF6,0x87,0xFF,0xFF,0xEF,0xFE,0xDE,0xBF, +0xFF,0xFF,0xFF,0xBB,0xEF,0xFD,0xFF,0x7B, 0xDE,0xF7,0x3F,0xFF,0xBF,0xFB,0xDB,0xFF, +0xF2,0xB6,0xFD,0xBD,0x7F,0xE7,0xFF,0xFF, 0xFF,0x6F,0xF7,0xFF,0xFF,0xFF,0xFE,0x77, +0xFF,0xBF,0xF8,0xAF,0xFF,0xDF,0xBF,0xFF, 0xBF,0x7F,0xFB,0xFF,0xFF,0xFF,0xDB,0xFE, +0xFF,0xBF,0xFF,0xFA,0xFF,0xFD,0xFF,0xF6, 0x7F,0xFF,0x9F,0xFF,0xFF,0x3F,0xEF,0xF8, +0xEE,0x7E,0x9F,0xBA,0xFE,0xBF,0x8F,0xEF, 0xFE,0xFE,0xF9,0xFF,0xFA,0x7F,0xFE,0x7E, +0xBF,0xAF,0xFB,0x96,0xFD,0x9F,0xEF,0x5E, 0x65,0xBE,0xEF,0x5B,0xB6,0xFF,0xBE,0xE3, +0xFF,0xB5,0xBF,0xFF,0xFD,0xFF,0x7F,0xFF, 0xEF,0xDF,0xFE,0xFF,0xBF,0xFB,0xFE,0xFF, +0xBF,0xCF,0xFF,0xFF,0xFF,0xFD,0x9B,0xFF, 0xFE,0xFB,0xFE,0xDF,0xFF,0x7F,0xFF,0xF7, +0xFE,0xFF,0xDF,0xFB,0xFB,0xFE,0xFF,0xFF, 0xFF,0xFF,0xFF,0xB7,0xFE,0xFA,0xFF,0xAB, +0xEF,0xFF,0xFD,0xB5,0x7B,0x7F,0xFB,0xF7, 0xFD,0xFF,0xFF,0xDD,0xFF,0xEF,0x8F,0xFF, +0x2F,0xFF,0xFB,0x7C,0xFF,0x3F,0xDF,0x73, 0xEB,0xFE,0x3F,0xFF,0xEF,0xFB,0xFE,0xFF, +0xEF,0xFD,0xFF,0xBF,0xFD,0x0F,0xFF,0xFF, 0xFF,0xF5,0xF9,0xFF,0x7F,0xD7,0xFD,0xFF, +0xDF,0xFF,0xF7,0xFB,0xFF,0x7F,0xBF,0xFF, 0xFF,0xF0,0x9F,0xFF,0xFE,0x7F,0x8B,0xE3, +0xF9,0xDE,0x27,0x9B,0xE6,0xBE,0x7F,0x9B, 0xC3,0xF8,0xDE,0x7F,0x9D,0xE7,0xFE,0x7F, +0xFF,0xFF,0x5F,0xD7,0xFF,0xFF,0xFF,0x4F, 0xFB,0xFF,0xFF,0x7F,0xFF,0xAF,0xFF,0x9F, +0x7F,0xFB,0xFF,0xE8,0xFF,0xFF,0xFE,0xBF, 0xAF,0xFF,0xFF,0xFE,0xBF,0xEF,0xF7,0xFF, +0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF, 0xFC,0xFF,0xFF,0xFD,0x7F,0xFF,0xFF,0xFF, +0xFD,0x3F,0xCF,0xFF,0xFF,0xFF,0xFF,0xF7, 0xFF,0xFD,0x7F,0xFF,0xFF,0x93,0xFF,0xFF, +0x7A,0xDF,0xF7,0xFF,0xFF,0x7B,0x7F,0xB7, 0xEF,0xFF,0xFF,0xFD,0xBF,0xFD,0xFB,0xFF, +0xF7,0xFF,0xD7,0xFF,0xFF,0xFF,0xFC,0x9F, 0x6F,0xCB,0xFF,0xF4,0xBB,0xDF,0xD6,0xFD, +0xBF,0x2F,0xD3,0xF7,0xFF,0xDF,0xFF,0xCF, 0xFF,0xFA,0xBE,0xBD,0xAF,0x6A,0xDA,0xBE, +0xBB,0xAB,0x3A,0xBE,0x2D,0xAE,0xEB,0xDA, 0xF6,0x3F,0xAD,0xF5,0xDD,0xFF,0xCF,0xF1, +0xFF,0xF9,0x7F,0xFF,0x73,0xFE,0xFF,0xCF, 0xC3,0xF4,0xF7,0x2F,0xF3,0xFF,0xFC,0xFF, +0x7C,0x1F,0xFF,0x3F,0x4F,0xFF,0x7E,0xFF, 0xEF,0xBD,0xF6,0xFE,0xFF,0x2B,0xEF,0xDC, +0xFB,0xFD,0xFF,0xFB,0xFF,0xEA,0x7B,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFB,0xF7,0xDF,0xFF, +0xE3,0x7D,0xFF,0xB7,0xFF,0xBF,0xFF,0xFF, 0xDF,0xFF,0xF8,0xFF,0xBF,0xFF,0xBF,0xEB, +0xE7,0xFA,0xFE,0x3D,0xBF,0xE9,0xFC,0xBF, 0xFF,0xFA,0xFB,0xFE,0xFF,0xFF,0xFF,0xD9, +0xFF,0xFF,0xFF,0xF6,0x7F,0xFF,0xF6,0x7D, 0xFF,0xDF,0xCF,0xFD,0xBF,0xFB,0xEF,0x7E, +0xFF,0x7F,0xFF,0xFF,0xD3,0xFF,0xFD,0xFB, 0xFF,0xFB,0xFF,0xFF,0xFF,0xEF,0xFF,0xBF, +0xFE,0xFF,0xF7,0xEF,0xFF,0xFF,0xFF,0xFB, 0xFF,0x87,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF, +0x7B,0xFE,0xFF,0xFE,0x3B,0xF7,0xF7,0xFF, 0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0xFF, +0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xF7, 0xFF,0xFF,0xAD,0xFF,0xFE,0xF7,0xFF,0xFF, +0x5F,0xFF,0xFF,0xDF,0xFF,0xFD,0xFF,0xF5, 0xFF,0xDF,0xFF,0xBD,0xFF,0xE9,0xFF,0xC7, +0xF3,0xFF,0xFF,0xF7,0xFF,0xF3,0xFF,0xF8, 0x3B,0xFF,0xFF,0x7B,0xDF,0xBF,0xFB,0xEF, +0xFB,0xFF,0xFB,0xF7,0xF7,0xBB,0xFF,0xFF, 0xFF,0xFF,0xFB,0xFF,0xFE,0x7F,0xF3,0x7F, +0x5E,0xB7,0xBF,0xFD,0x7F,0xFF,0xF9,0x7F, 0xFB,0xFF,0xEB,0xFD,0x7F,0x7F,0xFF,0xEF, +0xFB,0xE0,0x3F,0xFE,0xBF,0xBF,0xDF,0xFF, 0x7E,0xFF,0xF7,0xFF,0xFF,0xFE,0xBF,0xFF, +0xDB,0x78,0xFF,0xFF,0xFF,0xEE,0xA1,0xBF, 0xF5,0xDE,0xFB,0xF7,0xFF,0xFB,0xFF,0xFF, +0xFF,0xFF,0xFB,0xFF,0xFF,0xD7,0xFF,0xFF, 0xFF,0xFF,0xEF,0xF0,0xFF,0xFF,0xFF,0xF3, +0xF7,0xFF,0xEF,0xFF,0xE7,0xCF,0xFF,0xFB, 0xFF,0xEF,0xFF,0xFF,0x9F,0x9F,0xEF,0xFC, +0x16,0xBF,0xFE,0xF3,0xE4,0xFF,0xFF,0xC6, 0xFF,0xE7,0xFF,0xFF,0xFD,0xFF,0xBF,0xFF, +0xFF,0x3F,0xFF,0xBF,0xD6,0xAF,0x7F,0xFE, 0x6B,0x7E,0x7F,0xFF,0xAF,0xFF,0xFF,0xBF, +0xFF,0x5F,0xFF,0xFE,0xFF,0xFF,0xFE,0xFF, 0xFF,0xBD,0xDB,0xFF,0xFE,0x5F,0xF2,0xFF, +0xFF,0x5F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xEF,0x7F,0xFF,0xFF,0xFF,0xFF,0xDE,0xBF, +0xFF,0xFF,0xEF,0xFB,0x77,0xFE,0xBD,0x7F, 0x5F,0xFF,0xFF,0xFF,0xDF,0x6F,0xED,0xFF, +0xFD,0xFF,0x7F,0xFD,0x6F,0xFF,0xFF,0x77, 0xDA,0xCF,0xFD,0x5F,0xFF,0xBF,0xFF,0xFF, +0xDF,0x7F,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF, 0x66,0x7F,0xFF,0xFE,0xBF,0xE7,0xBF,0xFA, +0xFF,0xFE,0xFF,0xFF,0xFF,0xDF,0xFF,0x59, 0xEF,0xFF,0xEF,0xFB,0x7F,0x89,0xFF,0xFF, +0xE9,0xFF,0x6F,0xFF,0xF5,0xFF,0xFF,0xFF, 0xFF,0xFF,0x7F,0xF2,0xF7,0xFF,0xFF,0xEF, +0xF8,0x7F,0xFB,0xFF,0xFD,0xFF,0xFF,0xD9, 0xFF,0xEF,0xBB,0xFF,0xFF,0xFF,0xBF,0xEF, +0xDE,0xFF,0xFF,0x9F,0x7F,0xDF,0xFF,0xF7, 0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xAF, +0xFF,0xFF,0xF7,0x3F,0xEB,0x9F,0xFE,0x7F, 0x9E,0x7F,0x9F,0xFE,0x87,0xFF,0xED,0xDB, +0x56,0xFF,0xBF,0xAF,0x0B,0xD2,0xFF,0xEF, 0xDB,0x6E,0x7D,0xBD,0x6F,0xF8,0xFE,0x3F, +0xFA,0x5B,0xFF,0xFD,0xBF,0xEF,0xFF,0xBF, 0x6F,0xDB,0xE6,0xFF,0xFF,0x3F,0xFF,0xDF, +0xFE,0xFF,0xFF,0xFF,0xFF,0xDA,0x3F,0xFF, 0xFB,0xFE,0xFE,0xFF,0xFF,0xDF,0xF7,0xBD, +0xFF,0xFD,0xFF,0xFE,0xFF,0xFB,0xFF,0xFF, 0xFF,0xFF,0xF1,0x5F,0xFD,0x9F,0xDF,0xFD, +0xFF,0xFD,0x7F,0xFF,0xFF,0xFF,0xFF,0x76, 0xFA,0xFF,0xFF,0x7F,0xE3,0xF8,0xFF,0xAE, +0xFF,0xFB,0x7E,0x9D,0x73,0xFF,0xFA,0x7F, 0xDF,0xFF,0xFF,0x7F,0xFF,0xFB,0xCD,0xFF, +0x7F,0xEF,0xFB,0xFF,0xFD,0xFF,0xF7,0x7F, 0x7F,0xEF,0xFF,0xED,0xFF,0xFF,0xFF,0xB5, +0xFF,0xBF,0xFF,0xBF,0xFD,0xEF,0xDB,0xF7, 0xFF,0x93,0xFF,0xEF,0xE2,0xF9,0xBE,0x7F, +0x8B,0xE7,0xF9,0xFE,0x6B,0xE7,0xF9,0xFE, 0x7F,0x9F,0xE7,0xF9,0xFE,0x7F,0x47,0xFF, +0xFF,0xFD,0xFF,0x9F,0xFF,0xD7,0xFF,0xFF, 0xFF,0xFF,0xF5,0xFF,0x9F,0xFF,0xF7,0xFE, +0xFF,0xBF,0xFE,0x6F,0xFF,0xFF,0xFB,0xFF, 0xFF,0xFF,0xAF,0xFF,0xFF,0xFF,0x7F,0xFB, +0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD, 0xDF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF,0xDF, +0xFF,0xFF,0xFF,0x5F,0xFF,0xFF,0xFF,0xFF, 0x5F,0xFB,0xFE,0xFF,0xF8,0x37,0xFF,0xFF, +0xEF,0xFF,0x7F,0xFE,0xBF,0xFF,0xFF,0xFE, 0xBF,0xFF,0xFF,0x7F,0xFF,0xBF,0xFD,0xFF, +0x7F,0xFA,0x7F,0xFF,0xFF,0x6F,0xFF,0xFF, 0x7D,0xFF,0xCF,0xFF,0xFF,0xFF,0x4F,0xFF, +0xF2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFA,0xBF, 0xFF,0xAE,0xEB,0xFA,0xFE,0xBB,0xAD,0xEB, +0xFA,0xF7,0xAF,0x6B,0xFA,0xF6,0xBF,0x25, 0xE9,0xF2,0x7F,0x45,0xFF,0xFF,0xFD,0xF7, +0xF7,0xBF,0xFF,0xDF,0xFF,0xFF,0xBF,0xFB, 0xFF,0xDF,0xF3,0xFF,0xF7,0x3F,0xCF,0xFF, +0xA1,0xFF,0xFF,0xBF,0xE7,0xFF,0xFF,0x7F, 0xFF,0x3D,0xFF,0xFF,0xFF,0xF7,0xFF,0x2F, +0xFF,0xFB,0xF5,0x7F,0xFE,0x57,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7, +0x3F,0xFF,0xFE,0xFF,0xFF,0xFF,0xFD,0xFE, 0xF7,0xEE,0xAF,0xFE,0xEE,0xE7,0xFA,0xFF, +0xFE,0x9D,0xF9,0x5E,0xFE,0xFF,0xEB,0xFF, 0xFF,0xDF,0xA7,0xFF,0xFF,0xFF,0xFC,0xDB, +0xFF,0xFF,0xFF,0x7E,0xFB,0xFF,0xFF,0xEF, 0xFB,0xFD,0xFF,0xDB,0xFF,0xFF,0xFF,0xEF, +0xFF,0xFF,0xFF,0xFD,0xBF,0xFE,0xBF,0xFF, 0x6F,0x7F,0xFF,0xF7,0xFF,0xFF,0xF9,0xFF, +0xF7,0xFF,0xBF,0xDE,0xF7,0xFF,0xFF,0xFF, 0xFA,0x7F,0xFD,0xBF,0x5F,0xFF,0xFF,0xBF, +0xFF,0xED,0xFF,0xF7,0xBF,0xFF,0xFF,0xEF, 0xFF,0xDF,0xFF,0xFF,0xFF,0xE6,0xFF,0xFB, +0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEB,0xFF, +0xFD,0xFF,0xF5,0xFF,0xF6,0x7F,0xDF,0xBD, 0xCF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF, +0xFF,0xF9,0xFF,0xFF,0xFF,0xFF,0xFF,0xE3, 0xFF,0xEE,0xBF,0xFF,0x7D,0xEF,0xFE,0xFF, +0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFE, 0xFF,0xFF,0xFF,0xFF,0xE7,0xFF,0xB5,0xAE, +0xFF,0xFF,0xB6,0xFE,0xBF,0xFF,0xFF,0xBF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0x27,0xFF,0xEF,0xFE,0x7F,0xDF,0xFF, 0x7E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFD,0xFF,0xF7,0xF9,0x9F,0xFF, 0x5F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F, +0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0x0F,0xFF,0xE7,0xBF,0xFE, +0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFC,0xBF, 0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xC4, +0x6B,0xFF,0x29,0x1F,0xFB,0xAF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xEF,0x1B,0xFE,0xFF,0xFC, +0x6F,0xFF,0xFF,0xFD,0x6A,0xF7,0xD7,0xF5, 0xBF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFE,0xBF,0xFF,0xFF,0xFA,0xFF,0xFF,0xF7, 0xFB,0xDD,0xBF,0xFF,0xE7,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x7F,0xFF, 0xFF,0xF5,0xFF,0xFF,0xF7,0xFD,0xB3,0xEF, +0xFD,0x7E,0x5D,0xFF,0xFD,0xFF,0xFF,0xFF, 0xFD,0x7F,0xD2,0xF5,0xFB,0x7E,0xCB,0xB7, +0xFF,0xFF,0xFF,0xC6,0xFF,0xFD,0xEE,0x63, 0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0xFD,0x65, +0x5B,0xDF,0xFF,0xD5,0xFF,0xFF,0xFF,0xF6, 0xE7,0xBF,0xF7,0xA9,0xFF,0xFF,0xED,0xFF, +0xFF,0xFF,0xFF,0xFF,0xEB,0xFF,0xFF,0xFF, 0xAF,0xFF,0xFF,0xFF,0xF8,0x1B,0xFF,0xE3, +0xD0,0xBF,0xFF,0xE1,0xFF,0xFF,0xFF,0xFF, 0xFF,0xD7,0xFF,0xFF,0xFF,0x5F,0xFF,0xFF, +0xFF,0xFF,0xAF,0xFF,0xDB,0x76,0xBF,0xFF, 0x7F,0xFF,0xBF,0xEF,0xFE,0xFF,0xBF,0xEF, +0xFB,0xFE,0xFF,0xFF,0xFF,0xBF,0xF2,0x7F, 0xFF,0x9F,0xFE,0xBD,0xFE,0x7F,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xF7,0x3F,0xEC,0x7F,0xF6,0x95,0xBB, +0xEF,0xF8,0xFE,0xFC,0xBF,0x2F,0xDA,0xFC, 0xBF,0x2F,0xCB,0xF2,0xFC,0xBF,0xEF,0xFF, +0xA9,0xBF,0xCF,0xFB,0xFF,0xFF,0xFF,0xFE, 0xDD,0xB7,0x6D,0xF6,0xD9,0xB6,0x6D,0x9B, +0x76,0xD9,0xBF,0xFB,0xFD,0xA3,0xFF,0xBF, 0xEF,0xFF,0xEF,0xFF,0xFF,0xFF,0x7F,0xDF, +0xFD,0xEF,0x7B,0xDE,0xF7,0xFD,0xEF,0x7F, 0xFF,0xFF,0x05,0xFF,0xFA,0xFE,0x7F,0xEF, +0xE3,0xFF,0xFF,0xFD,0x7F,0xFF,0xFF,0xFF, 0xFF,0x5F,0xFF,0xFF,0xFD,0x7F,0xFB,0xAF, +0xFF,0x63,0xC8,0xFF,0xBF,0xEF,0xFF,0xFF, 0xFA,0x7F,0xFF,0xFF,0xFF,0xFE,0x9F,0xF7, +0xFF,0xFA,0xBF,0xFE,0x9F,0xFB,0x7F,0xFF, 0xFF,0xEF,0xD7,0xFF,0xFF,0xF5,0xFF,0xFF, +0xFF,0xFF,0xFD,0x7F,0xFF,0xFF,0xBF,0xFF, 0xF9,0xBF,0xFF,0xBE,0x27,0x9F,0xE7,0xF9, +0xFE,0x7F,0x8B,0xE7,0xFE,0x7F,0x9F,0xE2, 0xF9,0xFE,0x7F,0x9F,0xE7,0xF1,0x7F,0xFF, +0xFF,0xFF,0xFB,0xFE,0xFF,0xFF,0xFF,0xD7, 0xFF,0xFF,0xFF,0xFF,0xF5,0xFF,0xFF,0xFF, +0xD7,0xFF,0xFA,0xFF,0xFE,0xFF,0xFF,0xFF, 0xFD,0xFF,0xFF,0xFF,0xAF,0xF7,0xFF,0xFF, +0xFF,0xEB,0xFF,0xFF,0xFF,0xAF,0xFF,0xC4, 0xFF,0xF7,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF, +0xFF,0x5F,0xFF,0xFF,0xFF,0xFF,0xD7,0xFF, 0xFF,0xFF,0xFF,0xFF,0xEB,0xFF,0xFB,0x7A, +0xDF,0xF7,0xFD,0xFF,0xFF,0xFE,0xBF,0xFF, 0xFF,0x7F,0xFF,0xAF,0xFF,0xFF,0xFF,0xF7, +0xEF,0xE3,0xFF,0xDD,0xD2,0xFF,0xDF,0xFF, 0xFF,0xF2,0xFC,0xBF,0xCB,0xF6,0xFD,0xBF, +0x2F,0xCB,0xFF,0x7F,0xDF,0xDE,0xAF,0xFF, 0xDA,0xEE,0xBF,0xAF,0xE9,0xFA,0xF4,0xBD, +0xAF,0x5A,0xAE,0xBB,0xAB,0x6B,0xDA,0xDE, 0xBF,0xAD,0xD7,0x5E,0xFF,0xFF,0xBF,0xFC, +0xFF,0xDF,0xFD,0xFF,0xFF,0xFF,0xFF,0xDF, 0xF7,0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFA, +0x1F,0xFF,0xFE,0xFB,0xEF,0xBF,0xFD,0xFF, 0xFD,0xBD,0x77,0xFF,0xFF,0xFF,0xFF,0x9D, +0xEF,0xFF,0xFF,0xFF,0xEF,0x7D,0xFF,0xFB, 0xFE,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEE, 0xBF,0xE4,0xFB,0xFF,0xFE,0x3F,0xFE,0xFF, +0xFF,0xFF,0xFF,0xAF,0xEA,0xFE,0xBF,0xAF, 0xEB,0xFA,0xFE,0xFF,0xFF,0xFF,0x55,0xF6, +0xFF,0xFE,0xF7,0xFF,0x7F,0xFF,0xEB,0xF7, 0x5F,0xC5,0xFD,0x7F,0x5F,0xD7,0xF5,0xFF, +0x6F,0xFB,0xFF,0x8A,0xFF,0xFF,0xFF,0xFF, 0xEB,0xFF,0xFF,0xFF,0xFF,0xFB,0xBF,0xBF, +0xEF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF, 0x77,0xDF,0xFB,0xFF,0xFD,0x7F,0xEF,0xFF, +0xFF,0xFF,0xBF,0x7F,0xFF,0xDF,0xBF,0xFF, 0xFB,0xFF,0xFF,0xFF,0xFE,0xEF,0xDF,0xFF, +0xFE,0xFF,0x9F,0xEF,0x7D,0xFF,0xF7,0xFF, 0x7F,0xFF,0xFF,0xDF,0xF7,0xFD,0xFF,0xEF, +0xDF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFB, +0xFD,0xFF,0xBF,0xDF,0xD1,0xFF,0xF8,0x3B, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0x7E,0xDB,0xFD,0xFF,0x77,0xDB,0xB7,0x7D, 0xBF,0xFB,0xFF,0xF8,0x7F,0xED,0x7B,0x5E, +0xFF,0xFE,0xFF,0xFF,0x4F,0xD7,0xFD,0x7F, 0xDF,0xD7,0xF5,0xFF,0x7F,0xFF,0xFF,0xFF, +0xF2,0x3F,0xFE,0xFF,0xBF,0xFF,0xFF,0xFF, 0xFF,0xBF,0xEF,0xFE,0xFF,0x3B,0xEE,0xFF, +0xFC,0xEF,0xFF,0xFF,0xFF,0x85,0xFF,0xFD, 0xFE,0xFF,0xF5,0xFF,0xFF,0xFE,0xFF,0xDF, +0xFB,0xFF,0x5F,0xBF,0xFF,0xFD,0xFF,0xFF, 0xFF,0xFF,0xA8,0xFF,0xFF,0x9F,0x9E,0xFF, +0xFF,0xFF,0x7F,0xF3,0xFF,0xFF,0xCF,0xFF, 0xF7,0xFD,0xFF,0x7F,0xFF,0xFF,0xFC,0x16, +0xBF,0xCF,0xA3,0xE5,0xEF,0x7F,0xFF,0xF3, 0xE4,0xFF,0xCF,0x93,0xFC,0xFF,0x3F,0xCF, +0xFF,0xFF,0xFF,0xD6,0x0F,0x7D,0xBF,0x6E, 0xFB,0xF4,0xFC,0xAF,0x6D,0xDB,0x77,0xB7, +0x6D,0xDB,0xF6,0xFD,0xBF,0xFF,0xFF,0xFF, 0xBF,0x9B,0xFA,0xDE,0xB7,0xB7,0xED,0xF9, +0x7E,0xB7,0xAC,0xEB,0xD6,0xB3,0xAD,0xEB, 0x7A,0xDF,0xFF,0xFF,0xFF,0xD8,0xBF,0xFF, +0xB7,0xED,0x9F,0x6F,0xDD,0xF7,0x68,0xDB, 0x37,0xB3,0x6C,0xDB,0x36,0xCD,0xB3,0x7F, +0xFF,0x7F,0xF5,0x6F,0xFD,0xEF,0x79,0x3D, 0xF7,0x93,0xE4,0x7A,0x9E,0xAD,0xEA,0x7A, +0x9E,0xF7,0xBD,0xEF,0xFF,0xFF,0xFF,0x76, 0x7F,0xFB,0xC6,0xFF,0xBB,0xEF,0xDA,0xFE, +0xFD,0xBF,0xFB,0xFE,0xFF,0xBF,0xEF,0xFB, 0xFF,0xFF,0xFB,0xFF,0xA5,0xFF,0xFD,0xAB, +0x6F,0x78,0xDE,0x17,0x8F,0x79,0xDF,0xFD, 0xFF,0x7F,0xDF,0xF7,0xFD,0xFF,0xFF,0xFB, +0xFF,0xFB,0xFF,0xEF,0xFB,0xEF,0xFB,0xFE, 0xFF,0xBB,0xDA,0xF3,0xEF,0x3B,0xCE,0xF3, +0xBC,0xEF,0x3F,0xCF,0xDF,0xFF,0xB7,0xFF, 0xFF,0xFF,0xCF,0x73,0xFF,0xBF,0xEF,0xFF, +0xF3,0xFF,0x3F,0xCF,0xF3,0xFC,0xFF,0x3D, 0xCF,0x9F,0xFE,0x07,0xFF,0xAF,0xEB,0xFE, +0xFD,0xBF,0xEF,0xEB,0xFA,0xFF,0xAF,0xEB, 0xFA,0xFE,0xBF,0xAF,0xFB,0xFE,0x3F,0xFB, +0x9B,0xFF,0x7F,0xDF,0xFF,0xF3,0xFE,0xFF, 0xDE,0xF7,0xBF,0x7B,0xDE,0xF7,0xBD,0xEF, +0x7B,0xFE,0xFF,0xFF,0xDF,0x3F,0xFE,0xFF, 0xB7,0xFF,0xEF,0xF7,0xFF,0xBF,0xED,0xFE, +0xDF,0xB7,0xED,0xFB,0x7E,0xDF,0xFF,0xFF, 0xFF,0xFD,0x5F,0xEF,0xEB,0xFA,0xFE,0xF5, +0xBF,0x6F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFE,0xF8,0xFF,0xA8,0xFF, +0xFF,0xBF,0xEF,0xFB,0x6A,0xFB,0xB7,0xEF, 0xFB,0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xBF, +0xEF,0xFB,0xFF,0xE0,0xFF,0xFF,0xFD,0x7F, 0x5C,0xD7,0x7D,0xDF,0xF3,0x5C,0xF5,0xCD, +0x73,0x5E,0xD7,0xB5,0xFD,0x7F,0xEF,0xFF, 0xDB,0xFF,0xFF,0xE2,0xF8,0xBE,0x2F,0x8F, +0xE7,0xF8,0xBE,0x6B,0xE2,0xF8,0xBE,0x2F, 0x8B,0xE2,0xF9,0xFE,0x7F,0xE7,0xFF,0xD7, +0xF5,0xFD,0x7F,0xFF,0xF7,0xF5,0xFD,0x7F, 0xD7,0xF5,0xFD,0x7F,0x5F,0xD7,0xF5,0xFF, +0xFF,0xFF,0x8F,0xFF,0xAF,0xEB,0xFA,0xFF, 0xFF,0xBF,0xEB,0xFA,0xFF,0x2F,0xEB,0xFA, +0xFE,0xBF,0xAF,0xEB,0xFF,0xFF,0xFE,0x5F, 0xFF,0x5F,0xFF,0xFF,0xFD,0xFF,0xFF,0xD7, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xBF,0xFE,0xB7,0xFD, +0xFF,0x7E,0xDF,0xF7,0xAD,0xFF,0x7F,0xF7, 0xFD,0xFF,0x7F,0xDF,0xF7,0xFD,0xFF,0x7F, +0xF6,0x7F,0xFF,0xFF,0xFF,0xDB,0xF6,0xFC, 0xAF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xEC,0xBF,0xFF, 0xAF,0xEB,0xFA,0xF6,0xAB,0x8F,0xEB,0xFA, +0xF7,0xA5,0xEB,0xFA,0xBE,0xBF,0xAF,0xEB, 0xFA,0xFF,0x6D,0xFF,0xFF,0x7F,0xDF,0x33, +0xDD,0xFF,0x7F,0xFE,0xF7,0xFC,0x7F,0xFB, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA9, +0xFF,0xFD,0xFF,0xFF,0xFE,0xFF,0xFF,0xDF, 0xFF,0xFF,0xEF,0xEF,0xFD,0xFF,0x7F,0xFF, +0xFF,0xFF,0xFF,0xFE,0xA7,0xFF,0xFF,0xFF, 0x77,0xDF,0xF7,0xFD,0x9F,0x7F,0xFE,0x77, +0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xAF,0xBF,0xAF,0xFF,0xF9,0xBE,0xBF, +0x8F,0xFB,0xFE,0xFE,0xEF,0xFB,0xFE,0xFF, 0xBF,0xEF,0xFB,0xFF,0xFF,0xFD,0xDF,0x6F, +0xEF,0xFF,0x7F,0xFF,0xBF,0xBF,0xDF,0xFF, 0xFC,0xFF,0xDF,0xF7,0xFD,0xEF,0x7F,0xDF, +0xFF,0xFF,0xFF,0x3F,0xF6,0xFF,0xCF,0xFF, 0xDB,0xFB,0xF7,0xFF,0xEB,0x7A,0xFF,0xFF, +0xFF,0xBF,0xEF,0xFB,0xFF,0xFF,0xFF,0xFE, 0x6D,0xFD,0xFF,0x5F,0xFB,0xFF,0xFF,0xF7, +0xFF,0x5F,0xF5,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xF8,0xFF,0xFB,0xFF, +0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xE7,0xF6, 0xBF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xFF, +0xFF,0xC9,0xFF,0xFF,0xFF,0xBD,0xFF,0xBF, 0xAF,0xEF,0xEF,0x3F,0xD1,0xFC,0x7F,0xFB, +0xC7,0xFF,0xFF,0xFF,0xFF,0xFF,0xE3,0xFF, 0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0x77,0xFF, +0xDF,0xB7,0xFD,0xF7,0xFD,0xF7,0xFF,0xFF, 0xFF,0xFF,0xFF,0x57,0xFF,0xF7,0xA5,0xFD, +0x3F,0xDF,0xBF,0xBF,0xFE,0x7F,0xFF,0xFF, 0xFF,0xDF,0xFA,0xFD,0xFF,0xFF,0xFF,0xFE, +0x87,0xFF,0xE9,0xFF,0xFE,0xEF,0xBF,0xEF, 0xFE,0xFE,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFA,0x9F,0xFF,0x3F, 0xFF,0xFD,0xFD,0x57,0xDF,0xFD,0xF3,0xFF, +0xDF,0xFD,0xFF,0x5F,0xDF,0xF5,0xFD,0xFF, 0xFF,0xF9,0x8F,0xFF,0xFF,0xFF,0xEE,0x7F, +0xFF,0xFF,0xBF,0x5E,0xFE,0xEC,0xFB,0x3F, 0x7F,0x9F,0xEF,0xF9,0xFF,0xFF,0xCD,0x6B, +0xFF,0xFF,0xFF,0xC5,0xF3,0xFC,0xFA,0x38, 0xFF,0xAF,0x3F,0xEE,0x7F,0x9F,0xFF,0xD9, +0xFF,0xFF,0xFD,0x7A,0xF7,0xFF,0xF3,0xFF, 0xAF,0x6F,0xDB,0xF2,0xB9,0xE9,0xFB,0xFF, +0xFF,0xFF,0xFE,0xFF,0xFF,0xEF,0xFF,0xFB, 0xC5,0xBF,0xFF,0xEF,0xFF,0x5E,0xB7,0xAD, +0xCD,0x79,0x7C,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFD,0x93,0xFF,0xEF, +0xEA,0xFE,0xBF,0xEF,0x5B,0xD2,0xCD,0xF5, 0x6D,0x77,0xDF,0xF7,0xFD,0xFF,0x7F,0xDF, +0xFF,0xFF,0x66,0xFF,0xD5,0x65,0x7D,0x5F, 0x75,0x9D,0x65,0x7F,0xD6,0xFB,0x4F,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0xC7, 0xFF,0xBF,0xEF,0xFA,0xFE,0xFF,0xBF,0xEB, +0xFF,0xDF,0xFF,0x7E,0xFF,0xFF,0xEF,0xFD, 0x7E,0xD7,0xFF,0x78,0xDF,0xFF,0x5F,0xDF, +0xF5,0xBF,0x7F,0xDF,0xC5,0xFF,0x3F,0xF6, 0x7E,0xFF,0x0F,0xEF,0xF2,0x3E,0xBF,0xFF, +0xFB,0x3F,0xFF,0xFB,0x7F,0xFF,0xB3,0xFE, 0xFB,0xF6,0xFD,0xFF,0xDA,0xF7,0xFD,0xFF, +0x7F,0xDF,0xF7,0xBF,0xFF,0xFA,0x7F,0xFF, 0xFF,0xFF,0xFF,0x9F,0xFF,0xF3,0xDC,0xF9, +0xBF,0xCE,0xE7,0xF9,0xFE,0x7F,0x9F,0xE7, 0xFF,0xFF,0xE2,0x7F,0xFE,0xFF,0xBF,0xEF, +0xEB,0xFA,0xFF,0x9F,0x67,0x1E,0xFF,0x8F, 0xE7,0xF8,0xFE,0x7F,0x8F,0xEF,0xFF,0xBD, +0xBF,0xFF,0xFB,0xFF,0xFF,0xDF,0xF7,0xFF, 0xFC,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFD,0xB3,0xFF,0xFF,0xEF, 0xFF,0xFF,0xBF,0xED,0xFF,0xFB,0xEE,0xFE, +0xFF,0xFF,0xEF,0xFF,0xFE,0xFF,0xFF,0xFF, 0xFF,0xB5,0xFF,0xB7,0xFD,0xFD,0x6E,0xFF, +0xFF,0xFE,0xFD,0x2F,0xD8,0xFE,0xBF,0x8F, 0xEB,0xF9,0xFE,0x3F,0xFF,0xFA,0xCF,0xFF, +0xE7,0xD9,0xFA,0xBF,0xDF,0x77,0xFC,0xFB, 0x3F,0xAB,0xFE,0xFF,0xBF,0xEF,0xFB,0xFE, +0xFF,0xFF,0xEE,0x1F,0xFF,0xDF,0xF7,0xFF, 0xFF,0xFF,0x5F,0x97,0x35,0xBF,0x5E,0xFE, +0xBF,0xEF,0xFF,0xF7,0xFD,0xFF,0xFF,0xFA, 0xBF,0xFF,0xBE,0x6F,0x9F,0xE7,0xF8,0xBE, +0x2F,0x8B,0x66,0x94,0x7D,0x9D,0xE7,0xF9, 0xFE,0x7F,0x9F,0xE7,0xF1,0x7F,0xFF,0xFF, +0xFF,0xF7,0xF5,0xFD,0x7F,0x5F,0xFB,0xFD, 0x9E,0xFF,0xFB,0xFE,0xFF,0xFF,0xEF,0xFF, +0xFF,0xA0,0xFF,0xFF,0xFF,0xBF,0xEF,0xEB, 0xFA,0xFE,0xBF,0xB7,0xF7,0xF7,0xFF,0xFF, +0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xDD,0xFF, 0xFD,0xFF,0xFF,0xFF,0xD7,0xFF,0xFF,0xFF, +0x7F,0xF5,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF, 0xBF,0xFF,0xFF,0xAB,0xFE,0xFB,0xFE,0xFF, +0xF7,0xAF,0xFF,0xFF,0xDE,0xF7,0xEB,0x5F, 0xDF,0xF7,0xFD,0xFF,0x7F,0xDF,0xFF,0xFF, +0xB3,0xFF,0xC9,0xFE,0xFF,0xFF,0xFF,0xFF, 0xD6,0xFF,0xFF,0xCB,0xFF,0xFF,0xDF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFC,0x8F,0xFF,0xBA, 0xBE,0xBF,0xAF,0xEB,0x78,0xFE,0xB7,0xAD, +0x3A,0xFE,0xB7,0xAF,0xEB,0x7A,0xFE,0xBF, 0xAF,0xFF,0x9F,0xFF,0xFF,0xDF,0xFC,0xFF, +0xFF,0xFE,0xC3,0xFE,0xFF,0xFF,0x33,0xFC, 0xFF,0xBF,0xDF,0xF3,0xFF,0xFF,0xBB,0x9F, +0xFF,0xFF,0xFF,0xEB,0xDF,0xFF,0xFF,0xAF, 0xF7,0x6F,0xF9,0xBF,0xEF,0xFD,0xFF,0xFF, +0xFF,0xFF,0xFF,0xE3,0x7F,0xFF,0xFF,0xFF, 0xFB,0xFF,0xFF,0xBF,0xFD,0xFB,0xF7,0xFF, +0xDF,0xF7,0xFF,0xFE,0xEF,0x5F,0xBD,0xFF, 0xFA,0xFF,0xF8,0xFF,0xBF,0xAF,0xFB,0xFE, +0xFE,0x3F,0xEF,0xE8,0xFF,0xDF,0xF3,0xFD, 0xFF,0xFF,0xFF,0xFF,0xFF,0xED,0xFF,0xFB, +0xFD,0xFF,0xAF,0xFF,0xFF,0xFE,0xFE,0xBF, 0xDB,0xFF,0xFF,0xFF,0xBF,0xFF,0xDF,0xFF, +0xFD,0xFF,0xCB,0xFF,0xFF,0xFF,0xFF,0xFF, 0xBF,0x6F,0xFF,0x7F,0xB7,0xB3,0xFF,0xFF, +0xDF,0xFF,0xFB,0xEF,0xFF,0xFF,0xFF,0x07, 0xFF,0xFB,0xFF,0xFF,0xFF,0xED,0xFF,0xF5, +0x7C,0xFF,0x7F,0xFE,0xFF,0xFF,0xEF,0xCF, 0xFF,0xFB,0xFF,0xFF,0x2F,0xFF,0xFF,0xFF, +0xFF,0xF3,0xFF,0xFB,0xFF,0xFE,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF, +0xFD,0x1B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFE,0x7C,0xFF,0xFF,0xFF,0xFF, +0xEF,0xFF,0xFF,0xFF,0xFF,0xFB,0xBF,0x7F, 0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xDB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD, 0xFF,0xFF,0xF0,0x7F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xDF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xBF,0xFE, +0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xEF,0xFE,0xFF,0xBF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xEF,0xFA,0xB5,0xFF,0xFF,0xFF, 0xF7,0xF7,0xFF,0xFF,0xFF,0xFF,0xDF,0xFB, +0xFC,0xFF,0xFF,0xFE,0xFF,0x7F,0xDF,0xBF, 0xFF,0xCB,0xBF,0xF9,0xFE,0x7F,0x9F,0xE7, +0xF9,0xFE,0x7F,0x97,0xE1,0xFE,0x79,0x9F, 0xE7,0xFD,0xFE,0x7F,0xDF,0xFE,0x37,0xFF, +0xFB,0xDE,0xDE,0xBD,0xEF,0xF3,0xFE,0xFB, 0xAF,0xEB,0xFE,0xFF,0xFF,0xCF,0xFF,0xFE, +0xFF,0xBF,0xFF,0x8F,0xFF,0xEF,0xFB,0xFE, 0xFF,0xBF,0xE7,0xF9,0x5E,0x7F,0xEF,0xFB, +0xDA,0xFF,0xBF,0xEF,0xFB,0xFE,0xFF,0xFD, 0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF, +0xFF,0xFF,0x7F,0xFF,0xFF,0xF7,0xFB,0x7F, 0xFF,0xFF,0xFF,0xFF,0xFC,0x3F,0xFF,0xBF, +0xEF,0xFB,0xFE,0xFF,0xBF,0xEF,0x7B,0x7F, 0xBF,0xEF,0xFB,0xFE,0xFF,0xB5,0xEF,0xFB, +0xBF,0xFA,0x7F,0xFC,0xFF,0x3F,0xCF,0xF3, 0xFC,0xFF,0x3F,0xCF,0xBC,0xFF,0x3F,0xEF, +0xF3,0xFC,0xFE,0x3F,0xCF,0xFF,0xEE,0xEF, 0xFB,0xFE,0xFF,0xBF,0xEF,0xFB,0x6A,0xD7, +0xB7,0xFB,0xF8,0xFF,0xB7,0xEF,0xBA,0xFE, 0xFF,0xBF,0x7F,0xE9,0xFF,0xF9,0x7E,0x5F, +0x97,0xE5,0xF9,0xFE,0x7F,0xBF,0xF9,0x7E, 0x5F,0x9F,0xE5,0xFB,0xFE,0x5F,0xB7,0xFF, +0xA3,0xFF,0xF7,0xFD,0xFF,0x7F,0xDF,0xF7, 0xFD,0xFF,0x5E,0xF7,0x7D,0xFF,0x77,0xDF, +0xF7,0xFD,0xFF,0x7F,0xFF,0xD7,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFD,0xDF,0xFB,0x7F, +0xFF,0xFF,0xEF,0xFF,0xFE,0xFB,0xFF,0xFF, 0xBF,0xFE,0x8F,0xFF,0xDF,0xF7,0xFD,0xFD, +0x7F,0xDF,0xF7,0xFD,0x3E,0xDF,0xF5,0xBD, 0xFF,0x7F,0xDF,0xF7,0xFD,0xF7,0xFF,0x9F, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFD,0xFF,0xBE,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFD,0x3F,0xFF,0xDF,0xF7, 0xFD,0xFF,0x7F,0xDF,0xF7,0xFD,0xFF,0xCF, +0x77,0xFC,0xFF,0x5F,0xDF,0xF7,0xFD,0xFF, 0xF4,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFD,0xFF,0xFF,0xFF,0xEE,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xED,0xFB,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xE9,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFB,0xFF,0xFF,0xFF,0xD3,0xFF,0xFF, +0xBF,0x3F,0xFB,0xFF,0xFF,0xFF,0xFB,0xF3, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xF7, 0xFF,0xFF,0xFF,0xFF,0x17,0xFF,0xFF,0xFF, +0xDF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF, 0xDF,0xDF,0xFF,0xFD,0xFF,0xFF,0xDF,0xF7, +0xFF,0x4F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFD, +0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0x9F,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF, 0xFF,0xFF,0x7A,0x3F,0xFF,0xFF,0xFF,0xFF, +0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF2, +0x7F,0xFF,0xFB,0xFE,0xFF,0xBF,0xEF,0xF8, 0xFE,0xFF,0xBF,0xFB,0xFE,0xFF,0x8F,0xEC, +0xFB,0xFE,0xFF,0xBF,0xF8,0xF7,0xFE,0xFF, 0xBF,0xEF,0xFB,0xFE,0xFD,0xBF,0xCF,0xEC, +0xFF,0x3F,0xEF,0xDB,0xF8,0xFF,0xBF,0xCF, 0xFF,0xF9,0xFF,0xFF,0xBF,0xFF,0xFB,0xFF, +0xFF,0xFF,0xEF,0xFB,0xDF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xBB,0xFF, +0xEF,0xFB,0xFE,0xEF,0xBF,0xEE,0xEB,0xFB, 0xFE,0xFF,0xEF,0xFE,0xEE,0xBF,0xFE,0xEB, +0xFF,0xEF,0xFF,0x17,0xFF,0x7E,0xEB,0xBB, 0xFE,0xBF,0xBE,0xFB,0xEF,0x5B,0xF7,0xBD, +0xFB,0xCF,0xBF,0xBF,0xBB,0xFB,0x7E,0xCC, 0xEF,0xFF + +}; diff --git a/drivers/usb/dabusb.c b/drivers/usb/dabusb.c index a9fb06dbe..56e7cc400 100644 --- a/drivers/usb/dabusb.c +++ b/drivers/usb/dabusb.c @@ -44,8 +44,7 @@ #include "usb.h" #include "dabusb.h" -#include "bitstream.h" -#include "firmware.h" +#include "dabfirmware.h" /* --------------------------------------------------------------------- */ #define NRDABUSB 4 diff --git a/drivers/usb/dc2xx.c b/drivers/usb/dc2xx.c index a290f7c4d..7cc2caf9f 100644 --- a/drivers/usb/dc2xx.c +++ b/drivers/usb/dc2xx.c @@ -148,7 +148,7 @@ static ssize_t camera_read (struct file *file, * they matter in the application protocol. */ for (retries = 0; retries < MAX_READ_RETRY; retries++) { - unsigned long count; + int count; int result; if (signal_pending (current)) { @@ -216,7 +216,7 @@ static ssize_t camera_write (struct file *file, } while (thistime) { int result; - unsigned long count; + int count; if (signal_pending (current)) { if (!bytes_written) diff --git a/drivers/usb/devices.c b/drivers/usb/devices.c index 1fc6d5001..483a770f4 100644 --- a/drivers/usb/devices.c +++ b/drivers/usb/devices.c @@ -309,7 +309,7 @@ static char *usb_dump_device_strings (char *start, char *end, struct usb_device return start; } -static char *usb_dump_desc(char *start, char *end, const struct usb_device *dev) +static char *usb_dump_desc(char *start, char *end, struct usb_device *dev) { int i; @@ -365,7 +365,7 @@ static char *usb_dump_string(char *start, char *end, const struct usb_device *de /*****************************************************************/ -static char *usb_device_dump(char *start, char *end, const struct usb_device *usbdev, +static char *usb_device_dump(char *start, char *end, struct usb_device *usbdev, int bus, int level, int index, int count) { int chix; diff --git a/drivers/usb/firmware.h b/drivers/usb/firmware.h deleted file mode 100644 index a742558fb..000000000 --- a/drivers/usb/firmware.h +++ /dev/null @@ -1,3213 +0,0 @@ -//$Id: firmware.h,v 1.1 1999/12/17 08:55:05 fliegl Exp $ -static INTEL_HEX_RECORD firmware[] = { -{ 2, - 0x0, - 0, - {0x21,0x57} -}, -{ 3, - 0x3, - 0, - {0x02,0x01,0x66} -}, -{ 3, - 0xb, - 0, - {0x02,0x01,0x66} -}, -{ 3, - 0x13, - 0, - {0x02,0x01,0x66} -}, -{ 3, - 0x1b, - 0, - {0x02,0x01,0x66} -}, -{ 3, - 0x23, - 0, - {0x02,0x01,0x66} -}, -{ 3, - 0x2b, - 0, - {0x02,0x01,0x66} -}, -{ 3, - 0x33, - 0, - {0x02,0x03,0x0f} -}, -{ 3, - 0x3b, - 0, - {0x02,0x01,0x66} -}, -{ 3, - 0x43, - 0, - {0x02,0x01,0x00} -}, -{ 3, - 0x4b, - 0, - {0x02,0x01,0x66} -}, -{ 3, - 0x53, - 0, - {0x02,0x01,0x66} -}, -{ 3, - 0x5b, - 0, - {0x02,0x04,0xbd} -}, -{ 3, - 0x63, - 0, - {0x02,0x01,0x67} -}, -{ 3, - 0x100, - 0, - {0x02,0x0c,0x5a} -}, -{ 3, - 0x104, - 0, - {0x02,0x01,0xed} -}, -{ 3, - 0x108, - 0, - {0x02,0x02,0x51} -}, -{ 3, - 0x10c, - 0, - {0x02,0x02,0x7c} -}, -{ 3, - 0x110, - 0, - {0x02,0x02,0xe4} -}, -{ 1, - 0x114, - 0, - {0x32} -}, -{ 1, - 0x118, - 0, - {0x32} -}, -{ 3, - 0x11c, - 0, - {0x02,0x05,0xfd} -}, -{ 3, - 0x120, - 0, - {0x02,0x00,0x00} -}, -{ 3, - 0x124, - 0, - {0x02,0x00,0x00} -}, -{ 3, - 0x128, - 0, - {0x02,0x04,0x3c} -}, -{ 3, - 0x12c, - 0, - {0x02,0x04,0x6a} -}, -{ 3, - 0x130, - 0, - {0x02,0x00,0x00} -}, -{ 3, - 0x134, - 0, - {0x02,0x00,0x00} -}, -{ 3, - 0x138, - 0, - {0x02,0x00,0x00} -}, -{ 3, - 0x13c, - 0, - {0x02,0x00,0x00} -}, -{ 3, - 0x140, - 0, - {0x02,0x00,0x00} -}, -{ 3, - 0x144, - 0, - {0x02,0x00,0x00} -}, -{ 3, - 0x148, - 0, - {0x02,0x00,0x00} -}, -{ 3, - 0x14c, - 0, - {0x02,0x00,0x00} -}, -{ 3, - 0x150, - 0, - {0x02,0x00,0x00} -}, -{ 3, - 0x154, - 0, - {0x02,0x00,0x00} -}, -{ 10, - 0x157, - 0, - {0x75,0x81,0x7f,0xe5,0x82,0x60,0x03,0x02,0x01,0x61} -}, -{ 5, - 0x161, - 0, - {0x12,0x07,0x6f,0x21,0x64} -}, -{ 1, - 0x166, - 0, - {0x32} -}, -{ 14, - 0x167, - 0, - {0xc0,0xd0,0xc0,0x86,0xc0,0x82,0xc0,0x83,0xc0,0xe0,0x90,0x7f,0x97,0xe0} -}, -{ 14, - 0x175, - 0, - {0x44,0x80,0xf0,0x90,0x7f,0x69,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0} -}, -{ 14, - 0x183, - 0, - {0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0} -}, -{ 14, - 0x191, - 0, - {0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x90,0x7f,0x97,0xe0} -}, -{ 3, - 0x19f, - 0, - {0x55,0x7f,0xf0} -}, -{ 14, - 0x1a2, - 0, - {0x90,0x7f,0x9a,0xe0,0x30,0xe4,0x23,0x90,0x7f,0x68,0xf0,0xf0,0xf0,0xf0} -}, -{ 14, - 0x1b0, - 0, - {0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0} -}, -{ 14, - 0x1be, - 0, - {0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0} -}, -{ 14, - 0x1cc, - 0, - {0xe5,0xd8,0xc2,0xe3,0xf5,0xd8,0xd0,0xe0,0xd0,0x83,0xd0,0x82,0xd0,0x86} -}, -{ 3, - 0x1da, - 0, - {0xd0,0xd0,0x32} -}, -{ 8, - 0x1dd, - 0, - {0x75,0x86,0x00,0x90,0xff,0xc3,0x7c,0x05} -}, -{ 7, - 0x1e5, - 0, - {0xa3,0xe5,0x82,0x45,0x83,0x70,0xf9} -}, -{ 1, - 0x1ec, - 0, - {0x22} -}, -{ 14, - 0x1ed, - 0, - {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0x02,0xc0,0x03,0xc0,0xd0} -}, -{ 14, - 0x1fb, - 0, - {0x75,0xd0,0x00,0xc0,0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91} -}, -{ 13, - 0x209, - 0, - {0x90,0x88,0x00,0xe0,0xf5,0x41,0x90,0x7f,0xab,0x74,0x02,0xf0,0x90} -}, -{ 9, - 0x216, - 0, - {0x7f,0xab,0x74,0x02,0xf0,0xe5,0x32,0x60,0x21} -}, -{ 4, - 0x21f, - 0, - {0x7a,0x00,0x7b,0x00} -}, -{ 11, - 0x223, - 0, - {0xc3,0xea,0x94,0x18,0xeb,0x64,0x80,0x94,0x80,0x50,0x12} -}, -{ 14, - 0x22e, - 0, - {0x90,0x7f,0x69,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x0a,0xba,0x00} -}, -{ 2, - 0x23c, - 0, - {0x01,0x0b} -}, -{ 2, - 0x23e, - 0, - {0x80,0xe3} -}, -{ 2, - 0x240, - 0, - {0xd0,0x86} -}, -{ 14, - 0x242, - 0, - {0xd0,0xd0,0xd0,0x03,0xd0,0x02,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0} -}, -{ 1, - 0x250, - 0, - {0x32} -}, -{ 14, - 0x251, - 0, - {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} -}, -{ 14, - 0x25f, - 0, - {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90,0x7f,0xab,0x74} -}, -{ 4, - 0x26d, - 0, - {0x04,0xf0,0xd0,0x86} -}, -{ 11, - 0x271, - 0, - {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} -}, -{ 14, - 0x27c, - 0, - {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0x02,0xc0,0x03,0xc0,0x04} -}, -{ 14, - 0x28a, - 0, - {0xc0,0x05,0xc0,0x06,0xc0,0x07,0xc0,0x00,0xc0,0x01,0xc0,0xd0,0x75,0xd0} -}, -{ 13, - 0x298, - 0, - {0x00,0xc0,0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90} -}, -{ 12, - 0x2a5, - 0, - {0x7f,0xab,0x74,0x08,0xf0,0x75,0x6e,0x00,0x75,0x6f,0x02,0x12} -}, -{ 6, - 0x2b1, - 0, - {0x11,0x44,0x75,0x70,0x39,0x75} -}, -{ 6, - 0x2b7, - 0, - {0x71,0x0c,0x75,0x72,0x02,0x12} -}, -{ 12, - 0x2bd, - 0, - {0x11,0x75,0x90,0x7f,0xd6,0xe4,0xf0,0x75,0xd8,0x20,0xd0,0x86} -}, -{ 14, - 0x2c9, - 0, - {0xd0,0xd0,0xd0,0x01,0xd0,0x00,0xd0,0x07,0xd0,0x06,0xd0,0x05,0xd0,0x04} -}, -{ 13, - 0x2d7, - 0, - {0xd0,0x03,0xd0,0x02,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} -}, -{ 14, - 0x2e4, - 0, - {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} -}, -{ 14, - 0x2f2, - 0, - {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90,0x7f,0xab,0x74} -}, -{ 4, - 0x300, - 0, - {0x10,0xf0,0xd0,0x86} -}, -{ 11, - 0x304, - 0, - {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} -}, -{ 14, - 0x30f, - 0, - {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0x02,0xc0,0x03,0xc0,0x04} -}, -{ 14, - 0x31d, - 0, - {0xc0,0x05,0xc0,0x06,0xc0,0x07,0xc0,0x00,0xc0,0x01,0xc0,0xd0,0x75,0xd0} -}, -{ 12, - 0x32b, - 0, - {0x00,0xc0,0x86,0x75,0x86,0x00,0x75,0x6e,0x00,0x75,0x6f,0x02} -}, -{ 7, - 0x337, - 0, - {0x12,0x11,0x44,0x75,0x70,0x40,0x75} -}, -{ 6, - 0x33e, - 0, - {0x71,0x0c,0x75,0x72,0x02,0x12} -}, -{ 14, - 0x344, - 0, - {0x11,0x75,0x90,0x7f,0xd6,0x74,0x02,0xf0,0x90,0x7f,0xd6,0x74,0x06,0xf0} -}, -{ 5, - 0x352, - 0, - {0x75,0xd8,0x10,0xd0,0x86} -}, -{ 14, - 0x357, - 0, - {0xd0,0xd0,0xd0,0x01,0xd0,0x00,0xd0,0x07,0xd0,0x06,0xd0,0x05,0xd0,0x04} -}, -{ 13, - 0x365, - 0, - {0xd0,0x03,0xd0,0x02,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} -}, -{ 13, - 0x372, - 0, - {0x90,0x7f,0xa5,0x74,0x80,0xf0,0x90,0x7f,0xa6,0x74,0x9a,0xf0,0x12} -}, -{ 12, - 0x37f, - 0, - {0x10,0x1b,0x90,0x7f,0xa6,0xe5,0x42,0xf0,0x12,0x10,0x1b,0x90} -}, -{ 13, - 0x38b, - 0, - {0x7f,0xa6,0xe5,0x43,0xf0,0x12,0x10,0x1b,0x90,0x7f,0xa5,0x74,0x40} -}, -{ 1, - 0x398, - 0, - {0xf0} -}, -{ 1, - 0x399, - 0, - {0x22} -}, -{ 13, - 0x39a, - 0, - {0x90,0x7f,0xa5,0x74,0x80,0xf0,0x90,0x7f,0xa6,0x74,0x9a,0xf0,0x12} -}, -{ 12, - 0x3a7, - 0, - {0x10,0x1b,0x90,0x7f,0xa6,0xe5,0x44,0xf0,0x12,0x10,0x1b,0x90} -}, -{ 12, - 0x3b3, - 0, - {0x7f,0xa6,0xe5,0x45,0xf0,0x12,0x10,0x1b,0x90,0x7f,0xa6,0xe5} -}, -{ 11, - 0x3bf, - 0, - {0x46,0xf0,0x12,0x10,0x1b,0x90,0x7f,0xa5,0x74,0x40,0xf0} -}, -{ 1, - 0x3ca, - 0, - {0x22} -}, -{ 10, - 0x3cb, - 0, - {0x75,0x44,0x02,0x75,0x45,0x00,0x75,0x46,0x00,0x12} -}, -{ 9, - 0x3d5, - 0, - {0x03,0x9a,0x75,0x42,0x03,0x75,0x43,0x00,0x12} -}, -{ 2, - 0x3de, - 0, - {0x03,0x72} -}, -{ 1, - 0x3e0, - 0, - {0x22} -}, -{ 12, - 0x3e1, - 0, - {0x90,0x88,0x00,0xe5,0x36,0xf0,0x90,0x88,0x00,0x74,0x10,0x25} -}, -{ 9, - 0x3ed, - 0, - {0x36,0xf0,0x12,0x01,0xdd,0x75,0x42,0x01,0x75} -}, -{ 9, - 0x3f6, - 0, - {0x43,0x18,0x12,0x03,0x72,0x75,0x44,0x02,0x75} -}, -{ 9, - 0x3ff, - 0, - {0x45,0x00,0x75,0x46,0x00,0x12,0x03,0x9a,0x75} -}, -{ 8, - 0x408, - 0, - {0x42,0x03,0x75,0x43,0x44,0x12,0x03,0x72} -}, -{ 1, - 0x410, - 0, - {0x22} -}, -{ 14, - 0x411, - 0, - {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} -}, -{ 14, - 0x41f, - 0, - {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90,0x7f,0xaa,0x74} -}, -{ 4, - 0x42d, - 0, - {0x02,0xf0,0xd0,0x86} -}, -{ 11, - 0x431, - 0, - {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} -}, -{ 14, - 0x43c, - 0, - {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} -}, -{ 14, - 0x44a, - 0, - {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90,0x7f,0xa9,0x74} -}, -{ 7, - 0x458, - 0, - {0x04,0xf0,0x75,0x30,0x01,0xd0,0x86} -}, -{ 11, - 0x45f, - 0, - {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} -}, -{ 14, - 0x46a, - 0, - {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} -}, -{ 14, - 0x478, - 0, - {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90,0x7f,0xaa,0x74} -}, -{ 7, - 0x486, - 0, - {0x04,0xf0,0x75,0x31,0x01,0xd0,0x86} -}, -{ 11, - 0x48d, - 0, - {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} -}, -{ 14, - 0x498, - 0, - {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} -}, -{ 12, - 0x4a6, - 0, - {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe5,0xf5,0x91,0xd0,0x86} -}, -{ 11, - 0x4b2, - 0, - {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} -}, -{ 14, - 0x4bd, - 0, - {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0x75,0xd0,0x00,0xc0} -}, -{ 12, - 0x4cb, - 0, - {0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe7,0xf5,0x91,0xd0,0x86} -}, -{ 11, - 0x4d7, - 0, - {0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} -}, -{ 12, - 0x4e2, - 0, - {0x90,0x7f,0xea,0xe0,0xfa,0x8a,0x20,0x90,0x7f,0x96,0xe4,0xf0} -}, -{ 1, - 0x4ee, - 0, - {0x22} -}, -{ 7, - 0x4ef, - 0, - {0x90,0x7f,0xea,0xe0,0xfa,0x8a,0x21} -}, -{ 1, - 0x4f6, - 0, - {0x22} -}, -{ 14, - 0x4f7, - 0, - {0x90,0x17,0x13,0xe0,0xfa,0x90,0x17,0x15,0xe0,0xfb,0x74,0x80,0x2a,0xfa} -}, -{ 14, - 0x505, - 0, - {0x74,0x80,0x2b,0xfb,0xea,0x03,0x03,0x54,0x3f,0xfc,0xea,0xc4,0x23,0x54} -}, -{ 14, - 0x513, - 0, - {0x1f,0xfa,0x2c,0xfa,0xeb,0x03,0x03,0x54,0x3f,0xfc,0xeb,0xc4,0x23,0x54} -}, -{ 11, - 0x521, - 0, - {0x1f,0xfb,0x2c,0xfb,0x90,0x17,0x0a,0xe0,0xfc,0x60,0x02} -}, -{ 2, - 0x52c, - 0, - {0x7a,0x00} -}, -{ 7, - 0x52e, - 0, - {0x90,0x17,0x0c,0xe0,0xfc,0x60,0x02} -}, -{ 2, - 0x535, - 0, - {0x7b,0x00} -}, -{ 11, - 0x537, - 0, - {0xea,0x2b,0xfc,0xc3,0x13,0xf5,0x3a,0x75,0x44,0x02,0x8b} -}, -{ 7, - 0x542, - 0, - {0x45,0x8a,0x46,0x12,0x03,0x9a,0x75} -}, -{ 9, - 0x549, - 0, - {0x6e,0x08,0x75,0x6f,0x00,0x12,0x11,0x44,0x75} -}, -{ 4, - 0x552, - 0, - {0x70,0x47,0x75,0x71} -}, -{ 8, - 0x556, - 0, - {0x0c,0x75,0x72,0x02,0x12,0x11,0x75,0x85} -}, -{ 5, - 0x55e, - 0, - {0x3a,0x73,0x12,0x11,0xa0} -}, -{ 1, - 0x563, - 0, - {0x22} -}, -{ 14, - 0x564, - 0, - {0x90,0x7f,0x96,0xe0,0xfa,0x90,0x7f,0x96,0x74,0x80,0x65,0x02,0xf0,0x90} -}, -{ 14, - 0x572, - 0, - {0x7f,0xeb,0xe0,0xfa,0x90,0x7f,0xea,0xe0,0xfb,0x90,0x7f,0xef,0xe0,0xfc} -}, -{ 14, - 0x580, - 0, - {0x33,0x95,0xe0,0xfd,0x8c,0x05,0x7c,0x00,0x90,0x7f,0xee,0xe0,0xfe,0x33} -}, -{ 14, - 0x58e, - 0, - {0x95,0xe0,0xff,0xec,0x2e,0xfc,0xed,0x3f,0xfd,0x90,0x7f,0xe9,0xe0,0xfe} -}, -{ 5, - 0x59c, - 0, - {0xbe,0x01,0x02,0x80,0x03} -}, -{ 3, - 0x5a1, - 0, - {0x02,0x05,0xf9} -}, -{ 6, - 0x5a4, - 0, - {0xbc,0x01,0x21,0xbd,0x00,0x1e} -}, -{ 14, - 0x5aa, - 0, - {0xea,0xc4,0x03,0x54,0xf8,0xfc,0xeb,0x25,0xe0,0xfd,0x2c,0x24,0x00,0xfc} -}, -{ 14, - 0x5b8, - 0, - {0xe4,0x34,0x17,0xfd,0x90,0x7e,0xc0,0xe0,0xfe,0x8c,0x82,0x8d,0x83,0xf0} -}, -{ 2, - 0x5c6, - 0, - {0x80,0x31} -}, -{ 14, - 0x5c8, - 0, - {0xea,0xc4,0x03,0x54,0xf8,0xfa,0xeb,0x25,0xe0,0xfb,0x2a,0xfa,0x24,0x00} -}, -{ 14, - 0x5d6, - 0, - {0xfb,0xe4,0x34,0x17,0xfc,0x90,0x7e,0xc0,0xe0,0xfd,0x8b,0x82,0x8c,0x83} -}, -{ 14, - 0x5e4, - 0, - {0xf0,0x74,0x01,0x2a,0x24,0x00,0xfa,0xe4,0x34,0x17,0xfb,0x90,0x7e,0xc1} -}, -{ 7, - 0x5f2, - 0, - {0xe0,0xfc,0x8a,0x82,0x8b,0x83,0xf0} -}, -{ 3, - 0x5f9, - 0, - {0x75,0x38,0x01} -}, -{ 1, - 0x5fc, - 0, - {0x22} -}, -{ 14, - 0x5fd, - 0, - {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0x02,0xc0,0x03,0xc0,0x04} -}, -{ 14, - 0x60b, - 0, - {0xc0,0x05,0xc0,0x06,0xc0,0x07,0xc0,0x00,0xc0,0x01,0xc0,0xd0,0x75,0xd0} -}, -{ 13, - 0x619, - 0, - {0x00,0xc0,0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90} -}, -{ 13, - 0x626, - 0, - {0x7f,0xaa,0x74,0x01,0xf0,0x12,0x05,0x64,0x75,0x37,0x00,0xd0,0x86} -}, -{ 14, - 0x633, - 0, - {0xd0,0xd0,0xd0,0x01,0xd0,0x00,0xd0,0x07,0xd0,0x06,0xd0,0x05,0xd0,0x04} -}, -{ 13, - 0x641, - 0, - {0xd0,0x03,0xd0,0x02,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} -}, -{ 14, - 0x64e, - 0, - {0x90,0x7f,0xeb,0xe0,0xfa,0x90,0x7f,0xea,0xe0,0xfb,0x90,0x7f,0xee,0xe0} -}, -{ 14, - 0x65c, - 0, - {0xfc,0x33,0x95,0xe0,0xfd,0x90,0x7f,0x96,0xe0,0xfe,0x90,0x7f,0x96,0x74} -}, -{ 14, - 0x66a, - 0, - {0x80,0x65,0x06,0xf0,0x90,0x7f,0x00,0x74,0x01,0xf0,0xea,0xc4,0x03,0x54} -}, -{ 14, - 0x678, - 0, - {0xf8,0xfe,0xeb,0x25,0xe0,0xfb,0x2e,0xfe,0x24,0x00,0xfb,0xe4,0x34,0x17} -}, -{ 14, - 0x686, - 0, - {0xff,0x8b,0x82,0x8f,0x83,0xe0,0xfb,0x74,0x01,0x2e,0x24,0x00,0xfe,0xe4} -}, -{ 14, - 0x694, - 0, - {0x34,0x17,0xff,0x8e,0x82,0x8f,0x83,0xe0,0xfe,0x90,0x7f,0xe9,0xe0,0xff} -}, -{ 3, - 0x6a2, - 0, - {0xbf,0x81,0x0a} -}, -{ 10, - 0x6a5, - 0, - {0x90,0x7f,0x00,0xeb,0xf0,0x90,0x7f,0x01,0xee,0xf0} -}, -{ 8, - 0x6af, - 0, - {0x90,0x7f,0xe9,0xe0,0xfb,0xbb,0x82,0x1a} -}, -{ 3, - 0x6b7, - 0, - {0xba,0x01,0x0c} -}, -{ 12, - 0x6ba, - 0, - {0x90,0x7f,0x00,0xe4,0xf0,0x90,0x7f,0x01,0xe4,0xf0,0x80,0x0b} -}, -{ 11, - 0x6c6, - 0, - {0x90,0x7f,0x00,0xe4,0xf0,0x90,0x7f,0x01,0x74,0xb5,0xf0} -}, -{ 8, - 0x6d1, - 0, - {0x90,0x7f,0xe9,0xe0,0xfb,0xbb,0x83,0x1b} -}, -{ 3, - 0x6d9, - 0, - {0xba,0x01,0x0d} -}, -{ 13, - 0x6dc, - 0, - {0x90,0x7f,0x00,0x74,0x01,0xf0,0x90,0x7f,0x01,0xe4,0xf0,0x80,0x0b} -}, -{ 11, - 0x6e9, - 0, - {0x90,0x7f,0x00,0xe4,0xf0,0x90,0x7f,0x01,0x74,0x12,0xf0} -}, -{ 8, - 0x6f4, - 0, - {0x90,0x7f,0xe9,0xe0,0xfb,0xbb,0x84,0x1c} -}, -{ 3, - 0x6fc, - 0, - {0xba,0x01,0x0d} -}, -{ 13, - 0x6ff, - 0, - {0x90,0x7f,0x00,0x74,0x01,0xf0,0x90,0x7f,0x01,0xe4,0xf0,0x80,0x0c} -}, -{ 12, - 0x70c, - 0, - {0x90,0x7f,0x00,0x74,0x80,0xf0,0x90,0x7f,0x01,0x74,0x01,0xf0} -}, -{ 5, - 0x718, - 0, - {0x90,0x7f,0xb5,0xec,0xf0} -}, -{ 1, - 0x71d, - 0, - {0x22} -}, -{ 12, - 0x71e, - 0, - {0x75,0x36,0x0d,0x90,0x88,0x00,0x74,0x1d,0xf0,0x75,0x6b,0x80} -}, -{ 10, - 0x72a, - 0, - {0x75,0x6c,0x3c,0x12,0x10,0xe2,0x75,0x6b,0x80,0x75} -}, -{ 9, - 0x734, - 0, - {0x6c,0x0f,0x12,0x10,0xe2,0x75,0x6b,0x80,0x75} -}, -{ 9, - 0x73d, - 0, - {0x6c,0x06,0x12,0x10,0xe2,0x75,0x6b,0x80,0x75} -}, -{ 7, - 0x746, - 0, - {0x6c,0x01,0x12,0x10,0xe2,0x7a,0x00} -}, -{ 3, - 0x74d, - 0, - {0xba,0xff,0x00} -}, -{ 2, - 0x750, - 0, - {0x50,0x0a} -}, -{ 10, - 0x752, - 0, - {0xc0,0x02,0x12,0x01,0xdd,0xd0,0x02,0x0a,0x80,0xf1} -}, -{ 10, - 0x75c, - 0, - {0x75,0x6b,0x80,0x75,0x6c,0x3c,0x12,0x10,0xe2,0x75} -}, -{ 8, - 0x766, - 0, - {0x6b,0x80,0x75,0x6c,0x0f,0x12,0x10,0xe2} -}, -{ 1, - 0x76e, - 0, - {0x22} -}, -{ 14, - 0x76f, - 0, - {0x90,0x7f,0xa1,0xe4,0xf0,0x90,0x7f,0xaf,0x74,0x01,0xf0,0x90,0x7f,0x92} -}, -{ 14, - 0x77d, - 0, - {0x74,0x02,0xf0,0x75,0x8e,0x31,0x75,0x89,0x21,0x75,0x88,0x00,0x75,0xc8} -}, -{ 14, - 0x78b, - 0, - {0x00,0x75,0x8d,0x40,0x75,0x98,0x40,0x75,0xc0,0x40,0x75,0x87,0x00,0x75} -}, -{ 9, - 0x799, - 0, - {0x20,0x00,0x75,0x21,0x00,0x75,0x22,0x00,0x75} -}, -{ 5, - 0x7a2, - 0, - {0x23,0x00,0x75,0x47,0x00} -}, -{ 7, - 0x7a7, - 0, - {0xc3,0xe5,0x47,0x94,0x20,0x50,0x11} -}, -{ 13, - 0x7ae, - 0, - {0xe5,0x47,0x24,0x00,0xf5,0x82,0xe4,0x34,0x17,0xf5,0x83,0xe4,0xf0} -}, -{ 4, - 0x7bb, - 0, - {0x05,0x47,0x80,0xe8} -}, -{ 9, - 0x7bf, - 0, - {0xe4,0xf5,0x40,0xf5,0x3f,0xe4,0xf5,0x3c,0xf5} -}, -{ 7, - 0x7c8, - 0, - {0x3b,0xe4,0xf5,0x3e,0xf5,0x3d,0x75} -}, -{ 11, - 0x7cf, - 0, - {0x32,0x00,0x75,0x37,0x00,0x75,0x39,0x00,0x90,0x7f,0x93} -}, -{ 14, - 0x7da, - 0, - {0x74,0x3c,0xf0,0x90,0x7f,0x9c,0x74,0xff,0xf0,0x90,0x7f,0x96,0x74,0x80} -}, -{ 14, - 0x7e8, - 0, - {0xf0,0x90,0x7f,0x94,0x74,0x70,0xf0,0x90,0x7f,0x9d,0x74,0x8f,0xf0,0x90} -}, -{ 14, - 0x7f6, - 0, - {0x7f,0x97,0xe4,0xf0,0x90,0x7f,0x95,0x74,0xc2,0xf0,0x90,0x7f,0x98,0x74} -}, -{ 14, - 0x804, - 0, - {0x28,0xf0,0x90,0x7f,0x9e,0x74,0x28,0xf0,0x90,0x7f,0xf0,0xe4,0xf0,0x90} -}, -{ 14, - 0x812, - 0, - {0x7f,0xf1,0xe4,0xf0,0x90,0x7f,0xf2,0xe4,0xf0,0x90,0x7f,0xf3,0xe4,0xf0} -}, -{ 14, - 0x820, - 0, - {0x90,0x7f,0xf4,0xe4,0xf0,0x90,0x7f,0xf5,0xe4,0xf0,0x90,0x7f,0xf6,0xe4} -}, -{ 14, - 0x82e, - 0, - {0xf0,0x90,0x7f,0xf7,0xe4,0xf0,0x90,0x7f,0xf8,0xe4,0xf0,0x90,0x7f,0xf9} -}, -{ 14, - 0x83c, - 0, - {0x74,0x38,0xf0,0x90,0x7f,0xfa,0x74,0xa0,0xf0,0x90,0x7f,0xfb,0x74,0xa0} -}, -{ 14, - 0x84a, - 0, - {0xf0,0x90,0x7f,0xfc,0x74,0xa0,0xf0,0x90,0x7f,0xfd,0x74,0xa0,0xf0,0x90} -}, -{ 14, - 0x858, - 0, - {0x7f,0xfe,0x74,0xa0,0xf0,0x90,0x7f,0xff,0x74,0xa0,0xf0,0x90,0x7f,0xe0} -}, -{ 14, - 0x866, - 0, - {0x74,0x03,0xf0,0x90,0x7f,0xe1,0x74,0x01,0xf0,0x90,0x7f,0xdd,0x74,0x80} -}, -{ 11, - 0x874, - 0, - {0xf0,0x12,0x12,0x43,0x12,0x07,0x1e,0x7a,0x00,0x7b,0x00} -}, -{ 9, - 0x87f, - 0, - {0xc3,0xea,0x94,0x1e,0xeb,0x94,0x00,0x50,0x17} -}, -{ 12, - 0x888, - 0, - {0x90,0x88,0x00,0xe0,0xf5,0x47,0x90,0x88,0x0b,0xe0,0xf5,0x47} -}, -{ 9, - 0x894, - 0, - {0x90,0x7f,0x68,0xf0,0x0a,0xba,0x00,0x01,0x0b} -}, -{ 2, - 0x89d, - 0, - {0x80,0xe0} -}, -{ 12, - 0x89f, - 0, - {0x12,0x03,0xe1,0x90,0x7f,0xd6,0xe4,0xf0,0x7a,0x00,0x7b,0x00} -}, -{ 13, - 0x8ab, - 0, - {0x8a,0x04,0x8b,0x05,0xc3,0xea,0x94,0xe0,0xeb,0x94,0x2e,0x50,0x1a} -}, -{ 14, - 0x8b8, - 0, - {0xc0,0x02,0xc0,0x03,0xc0,0x04,0xc0,0x05,0x12,0x01,0xdd,0xd0,0x05,0xd0} -}, -{ 10, - 0x8c6, - 0, - {0x04,0xd0,0x03,0xd0,0x02,0x0a,0xba,0x00,0x01,0x0b} -}, -{ 2, - 0x8d0, - 0, - {0x80,0xd9} -}, -{ 13, - 0x8d2, - 0, - {0x90,0x7f,0xd6,0x74,0x02,0xf0,0x90,0x7f,0xd6,0x74,0x06,0xf0,0x90} -}, -{ 14, - 0x8df, - 0, - {0x7f,0xde,0x74,0x05,0xf0,0x90,0x7f,0xdf,0x74,0x05,0xf0,0x90,0x7f,0xac} -}, -{ 14, - 0x8ed, - 0, - {0xe4,0xf0,0x90,0x7f,0xad,0x74,0x05,0xf0,0x75,0xa8,0x80,0x75,0xf8,0x10} -}, -{ 13, - 0x8fb, - 0, - {0x90,0x7f,0xae,0x74,0x0b,0xf0,0x90,0x7f,0xe2,0x74,0x88,0xf0,0x90} -}, -{ 12, - 0x908, - 0, - {0x7f,0xab,0x74,0x08,0xf0,0x75,0xe8,0x11,0x75,0x32,0x01,0x75} -}, -{ 12, - 0x914, - 0, - {0x31,0x00,0x75,0x30,0x00,0xc0,0x04,0xc0,0x05,0x12,0x04,0xf7} -}, -{ 10, - 0x920, - 0, - {0xd0,0x05,0xd0,0x04,0x75,0x34,0x00,0x75,0x35,0x01} -}, -{ 13, - 0x92a, - 0, - {0x90,0x7f,0xae,0x74,0x03,0xf0,0x8c,0x02,0xba,0x00,0x02,0x80,0x03} -}, -{ 3, - 0x937, - 0, - {0x02,0x0a,0x3f} -}, -{ 12, - 0x93a, - 0, - {0x85,0x33,0x34,0x90,0x7f,0x9d,0x74,0x8f,0xf0,0x90,0x7f,0x97} -}, -{ 14, - 0x946, - 0, - {0x74,0x08,0xf0,0x90,0x7f,0x9d,0x74,0x88,0xf0,0x90,0x7f,0x9a,0xe0,0xfa} -}, -{ 12, - 0x954, - 0, - {0x74,0x05,0x5a,0xf5,0x33,0x90,0x7f,0x9d,0x74,0x8f,0xf0,0x90} -}, -{ 13, - 0x960, - 0, - {0x7f,0x97,0x74,0x02,0xf0,0x90,0x7f,0x9d,0x74,0x82,0xf0,0xe5,0x33} -}, -{ 13, - 0x96d, - 0, - {0x25,0xe0,0xfa,0x90,0x7f,0x9a,0xe0,0x54,0x05,0xfb,0x4a,0xf5,0x33} -}, -{ 2, - 0x97a, - 0, - {0x60,0x0c} -}, -{ 12, - 0x97c, - 0, - {0x90,0x7f,0x96,0xe0,0xfa,0x90,0x7f,0x96,0x74,0x80,0x4a,0xf0} -}, -{ 11, - 0x988, - 0, - {0x75,0x6e,0x00,0x75,0x6f,0x00,0xc0,0x04,0xc0,0x05,0x12} -}, -{ 14, - 0x993, - 0, - {0x11,0x44,0xd0,0x05,0xd0,0x04,0x90,0x17,0x13,0xe0,0xfa,0x74,0x80,0x2a} -}, -{ 6, - 0x9a1, - 0, - {0xfa,0xe5,0x33,0xb4,0x04,0x29} -}, -{ 3, - 0x9a7, - 0, - {0xba,0xa0,0x00} -}, -{ 2, - 0x9aa, - 0, - {0x50,0x24} -}, -{ 13, - 0x9ac, - 0, - {0x90,0x17,0x13,0xe0,0x04,0xfb,0x0b,0x90,0x17,0x13,0xeb,0xf0,0x90} -}, -{ 14, - 0x9b9, - 0, - {0x17,0x13,0xe0,0xfb,0x90,0x17,0x15,0xf0,0xc0,0x02,0xc0,0x04,0xc0,0x05} -}, -{ 9, - 0x9c7, - 0, - {0x12,0x04,0xf7,0xd0,0x05,0xd0,0x04,0xd0,0x02} -}, -{ 5, - 0x9d0, - 0, - {0xe5,0x33,0xb4,0x02,0x26} -}, -{ 6, - 0x9d5, - 0, - {0xc3,0x74,0x04,0x9a,0x50,0x20} -}, -{ 13, - 0x9db, - 0, - {0x90,0x17,0x13,0xe0,0xfa,0x1a,0x1a,0x90,0x17,0x13,0xea,0xf0,0x90} -}, -{ 13, - 0x9e8, - 0, - {0x17,0x13,0xe0,0xfa,0x90,0x17,0x15,0xf0,0xc0,0x04,0xc0,0x05,0x12} -}, -{ 6, - 0x9f5, - 0, - {0x04,0xf7,0xd0,0x05,0xd0,0x04} -}, -{ 5, - 0x9fb, - 0, - {0xe5,0x33,0xb4,0x08,0x1d} -}, -{ 4, - 0xa00, - 0, - {0xe5,0x34,0x70,0x19} -}, -{ 10, - 0xa04, - 0, - {0x74,0x01,0x25,0x35,0x54,0x0f,0xf5,0x35,0x85,0x35} -}, -{ 12, - 0xa0e, - 0, - {0x75,0x75,0x76,0x00,0xc0,0x04,0xc0,0x05,0x12,0x13,0xfe,0xd0} -}, -{ 3, - 0xa1a, - 0, - {0x05,0xd0,0x04} -}, -{ 5, - 0xa1d, - 0, - {0xe5,0x33,0xb4,0x01,0x1d} -}, -{ 4, - 0xa22, - 0, - {0xe5,0x34,0x70,0x19} -}, -{ 10, - 0xa26, - 0, - {0xe5,0x35,0x24,0xff,0x54,0x0f,0xf5,0x35,0x85,0x35} -}, -{ 12, - 0xa30, - 0, - {0x75,0x75,0x76,0x00,0xc0,0x04,0xc0,0x05,0x12,0x13,0xfe,0xd0} -}, -{ 3, - 0xa3c, - 0, - {0x05,0xd0,0x04} -}, -{ 14, - 0xa3f, - 0, - {0xc0,0x04,0xc0,0x05,0x12,0x01,0xdd,0xd0,0x05,0xd0,0x04,0x90,0x7f,0x96} -}, -{ 14, - 0xa4d, - 0, - {0xe0,0xfa,0x90,0x7f,0x96,0x74,0x7f,0x5a,0xf0,0x90,0x7f,0x97,0x74,0x08} -}, -{ 10, - 0xa5b, - 0, - {0xf0,0xc3,0xec,0x94,0x00,0xed,0x94,0x02,0x40,0x08} -}, -{ 8, - 0xa65, - 0, - {0x90,0x7f,0x96,0xe0,0xfa,0x20,0xe6,0x08} -}, -{ 8, - 0xa6d, - 0, - {0xc3,0xe4,0x9c,0x74,0x08,0x9d,0x50,0x13} -}, -{ 14, - 0xa75, - 0, - {0x90,0x7f,0x96,0xe0,0xfa,0x90,0x7f,0x96,0x74,0x40,0x65,0x02,0xf0,0x7c} -}, -{ 5, - 0xa83, - 0, - {0x00,0x7d,0x00,0x80,0x05} -}, -{ 5, - 0xa88, - 0, - {0x0c,0xbc,0x00,0x01,0x0d} -}, -{ 5, - 0xa8d, - 0, - {0xe5,0x38,0xb4,0x01,0x0e} -}, -{ 13, - 0xa92, - 0, - {0xc0,0x04,0xc0,0x05,0x12,0x04,0xf7,0xd0,0x05,0xd0,0x04,0x75,0x38} -}, -{ 1, - 0xa9f, - 0, - {0x00} -}, -{ 7, - 0xaa0, - 0, - {0xe5,0x31,0x70,0x03,0x02,0x09,0x2a} -}, -{ 10, - 0xaa7, - 0, - {0x90,0x7f,0xc9,0xe0,0xfa,0x70,0x03,0x02,0x0c,0x2d} -}, -{ 14, - 0xab1, - 0, - {0x90,0x7f,0x96,0xe0,0xfa,0x90,0x7f,0x96,0x74,0x80,0x65,0x02,0xf0,0x90} -}, -{ 9, - 0xabf, - 0, - {0x7d,0xc0,0xe0,0xfa,0xba,0x2c,0x02,0x80,0x03} -}, -{ 3, - 0xac8, - 0, - {0x02,0x0b,0x36} -}, -{ 5, - 0xacb, - 0, - {0x75,0x32,0x00,0x7b,0x00} -}, -{ 3, - 0xad0, - 0, - {0xbb,0x64,0x00} -}, -{ 2, - 0xad3, - 0, - {0x50,0x1c} -}, -{ 14, - 0xad5, - 0, - {0xc0,0x02,0xc0,0x03,0xc0,0x04,0xc0,0x05,0x12,0x01,0xdd,0xd0,0x05,0xd0} -}, -{ 13, - 0xae3, - 0, - {0x04,0xd0,0x03,0xd0,0x02,0x90,0x88,0x0f,0xe0,0xf5,0x47,0x0b,0x80} -}, -{ 1, - 0xaf0, - 0, - {0xdf} -}, -{ 13, - 0xaf1, - 0, - {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x07,0x1e,0x12,0x03,0xe1,0x12} -}, -{ 12, - 0xafe, - 0, - {0x04,0xf7,0xd0,0x05,0xd0,0x04,0xd0,0x02,0x75,0x6e,0x00,0x75} -}, -{ 13, - 0xb0a, - 0, - {0x6f,0x01,0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x11,0x44,0xd0,0x05} -}, -{ 9, - 0xb17, - 0, - {0xd0,0x04,0xd0,0x02,0x75,0x70,0x4d,0x75,0x71} -}, -{ 11, - 0xb20, - 0, - {0x0c,0x75,0x72,0x02,0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12} -}, -{ 11, - 0xb2b, - 0, - {0x11,0x75,0xd0,0x05,0xd0,0x04,0xd0,0x02,0x02,0x0c,0x2d} -}, -{ 3, - 0xb36, - 0, - {0xba,0x2a,0x3b} -}, -{ 13, - 0xb39, - 0, - {0x90,0x7f,0x98,0x74,0x20,0xf0,0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12} -}, -{ 14, - 0xb46, - 0, - {0x01,0xdd,0xd0,0x05,0xd0,0x04,0xd0,0x02,0x90,0x7f,0x98,0x74,0x28,0xf0} -}, -{ 2, - 0xb54, - 0, - {0x7b,0x00} -}, -{ 3, - 0xb56, - 0, - {0xbb,0x0a,0x00} -}, -{ 5, - 0xb59, - 0, - {0x40,0x03,0x02,0x0c,0x2d} -}, -{ 14, - 0xb5e, - 0, - {0xc0,0x02,0xc0,0x03,0xc0,0x04,0xc0,0x05,0x12,0x01,0xdd,0xd0,0x05,0xd0} -}, -{ 8, - 0xb6c, - 0, - {0x04,0xd0,0x03,0xd0,0x02,0x0b,0x80,0xe2} -}, -{ 3, - 0xb74, - 0, - {0xba,0x2b,0x1a} -}, -{ 8, - 0xb77, - 0, - {0x90,0x7f,0xc9,0xe0,0xfb,0xbb,0x40,0x12} -}, -{ 14, - 0xb7f, - 0, - {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x12,0x05,0xd0,0x05,0xd0,0x04,0xd0} -}, -{ 4, - 0xb8d, - 0, - {0x02,0x02,0x0c,0x2d} -}, -{ 3, - 0xb91, - 0, - {0xba,0x10,0x1f} -}, -{ 14, - 0xb94, - 0, - {0x90,0x7f,0x96,0xe0,0xfb,0x90,0x7f,0x96,0x74,0x80,0x65,0x03,0xf0,0xc0} -}, -{ 14, - 0xba2, - 0, - {0x02,0xc0,0x04,0xc0,0x05,0x12,0x10,0x3d,0xd0,0x05,0xd0,0x04,0xd0,0x02} -}, -{ 3, - 0xbb0, - 0, - {0x02,0x0c,0x2d} -}, -{ 3, - 0xbb3, - 0, - {0xba,0x11,0x12} -}, -{ 14, - 0xbb6, - 0, - {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x10,0x6a,0xd0,0x05,0xd0,0x04,0xd0} -}, -{ 4, - 0xbc4, - 0, - {0x02,0x02,0x0c,0x2d} -}, -{ 3, - 0xbc8, - 0, - {0xba,0x12,0x12} -}, -{ 14, - 0xbcb, - 0, - {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x10,0x8f,0xd0,0x05,0xd0,0x04,0xd0} -}, -{ 4, - 0xbd9, - 0, - {0x02,0x02,0x0c,0x2d} -}, -{ 3, - 0xbdd, - 0, - {0xba,0x13,0x0b} -}, -{ 11, - 0xbe0, - 0, - {0x90,0x7d,0xc1,0xe0,0xfb,0x90,0x88,0x00,0xf0,0x80,0x42} -}, -{ 3, - 0xbeb, - 0, - {0xba,0x14,0x11} -}, -{ 14, - 0xbee, - 0, - {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x11,0xdd,0xd0,0x05,0xd0,0x04,0xd0} -}, -{ 3, - 0xbfc, - 0, - {0x02,0x80,0x2e} -}, -{ 3, - 0xbff, - 0, - {0xba,0x15,0x1d} -}, -{ 12, - 0xc02, - 0, - {0x90,0x7d,0xc1,0xe0,0xf5,0x75,0x90,0x7d,0xc2,0xe0,0xf5,0x76} -}, -{ 14, - 0xc0e, - 0, - {0xc0,0x02,0xc0,0x04,0xc0,0x05,0x12,0x13,0xfe,0xd0,0x05,0xd0,0x04,0xd0} -}, -{ 3, - 0xc1c, - 0, - {0x02,0x80,0x0e} -}, -{ 3, - 0xc1f, - 0, - {0xba,0x16,0x0b} -}, -{ 11, - 0xc22, - 0, - {0xc0,0x04,0xc0,0x05,0x12,0x13,0xa3,0xd0,0x05,0xd0,0x04} -}, -{ 11, - 0xc2d, - 0, - {0x90,0x7f,0xc9,0xe4,0xf0,0x75,0x31,0x00,0x02,0x09,0x2a} -}, -{ 1, - 0xc38, - 0, - {0x22} -}, -{ 7, - 0xc39, - 0, - {0x53,0x55,0x50,0x45,0x4e,0x44,0x00} -}, -{ 7, - 0xc40, - 0, - {0x52,0x45,0x53,0x55,0x4d,0x45,0x00} -}, -{ 6, - 0xc47, - 0, - {0x20,0x56,0x6f,0x6c,0x20,0x00} -}, -{ 13, - 0xc4d, - 0, - {0x44,0x41,0x42,0x55,0x53,0x42,0x20,0x76,0x31,0x2e,0x30,0x30,0x00} -}, -{ 14, - 0xc5a, - 0, - {0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0x02,0xc0,0x03,0xc0,0x04} -}, -{ 14, - 0xc68, - 0, - {0xc0,0x05,0xc0,0x06,0xc0,0x07,0xc0,0x00,0xc0,0x01,0xc0,0xd0,0x75,0xd0} -}, -{ 13, - 0xc76, - 0, - {0x00,0xc0,0x86,0x75,0x86,0x00,0xe5,0x91,0xc2,0xe4,0xf5,0x91,0x90} -}, -{ 14, - 0xc83, - 0, - {0x7f,0xab,0x74,0x01,0xf0,0x90,0x7f,0xe8,0xe0,0xfa,0x90,0x7f,0xe9,0xe0} -}, -{ 6, - 0xc91, - 0, - {0xfb,0xbb,0x00,0x02,0x80,0x03} -}, -{ 3, - 0xc97, - 0, - {0x02,0x0d,0x38} -}, -{ 3, - 0xc9a, - 0, - {0xba,0x80,0x14} -}, -{ 14, - 0xc9d, - 0, - {0x90,0x7f,0x00,0x74,0x01,0xf0,0x90,0x7f,0x01,0xe4,0xf0,0x90,0x7f,0xb5} -}, -{ 6, - 0xcab, - 0, - {0x74,0x02,0xf0,0x02,0x0e,0xcd} -}, -{ 5, - 0xcb1, - 0, - {0xba,0x82,0x02,0x80,0x03} -}, -{ 3, - 0xcb6, - 0, - {0x02,0x0d,0x1d} -}, -{ 8, - 0xcb9, - 0, - {0x90,0x7f,0xec,0xe0,0xfc,0xbc,0x01,0x00} -}, -{ 2, - 0xcc1, - 0, - {0x40,0x21} -}, -{ 6, - 0xcc3, - 0, - {0xc3,0x74,0x07,0x9c,0x40,0x1b} -}, -{ 14, - 0xcc9, - 0, - {0xec,0x24,0xff,0x25,0xe0,0xfd,0x24,0xc6,0xf5,0x82,0xe4,0x34,0x7f,0xf5} -}, -{ 13, - 0xcd7, - 0, - {0x83,0xe0,0xfd,0x53,0x05,0x01,0x90,0x7f,0x00,0xed,0xf0,0x80,0x2b} -}, -{ 3, - 0xce4, - 0, - {0xbc,0x81,0x00} -}, -{ 2, - 0xce7, - 0, - {0x40,0x21} -}, -{ 6, - 0xce9, - 0, - {0xc3,0x74,0x87,0x9c,0x40,0x1b} -}, -{ 14, - 0xcef, - 0, - {0xec,0x24,0x7f,0x25,0xe0,0xfc,0x24,0xb6,0xf5,0x82,0xe4,0x34,0x7f,0xf5} -}, -{ 13, - 0xcfd, - 0, - {0x83,0xe0,0xfc,0x53,0x04,0x01,0x90,0x7f,0x00,0xec,0xf0,0x80,0x05} -}, -{ 5, - 0xd0a, - 0, - {0x90,0x7f,0x00,0xe4,0xf0} -}, -{ 14, - 0xd0f, - 0, - {0x90,0x7f,0x01,0xe4,0xf0,0x90,0x7f,0xb5,0x74,0x02,0xf0,0x02,0x0e,0xcd} -}, -{ 5, - 0xd1d, - 0, - {0xba,0x81,0x02,0x80,0x03} -}, -{ 3, - 0xd22, - 0, - {0x02,0x0e,0xc5} -}, -{ 14, - 0xd25, - 0, - {0x90,0x7f,0x00,0xe4,0xf0,0x90,0x7f,0x01,0xe4,0xf0,0x90,0x7f,0xb5,0x74} -}, -{ 5, - 0xd33, - 0, - {0x02,0xf0,0x02,0x0e,0xcd} -}, -{ 3, - 0xd38, - 0, - {0xbb,0x01,0x2d} -}, -{ 6, - 0xd3b, - 0, - {0xba,0x00,0x03,0x02,0x0e,0xcd} -}, -{ 3, - 0xd41, - 0, - {0xba,0x02,0x11} -}, -{ 13, - 0xd44, - 0, - {0x75,0x59,0x00,0xc0,0x02,0xc0,0x03,0x12,0x0e,0xf0,0xd0,0x03,0xd0} -}, -{ 4, - 0xd51, - 0, - {0x02,0x02,0x0e,0xcd} -}, -{ 5, - 0xd55, - 0, - {0xba,0x21,0x02,0x80,0x03} -}, -{ 3, - 0xd5a, - 0, - {0x02,0x0e,0xcd} -}, -{ 11, - 0xd5d, - 0, - {0x75,0x37,0x01,0x90,0x7f,0xc5,0xe4,0xf0,0x02,0x0e,0xcd} -}, -{ 3, - 0xd68, - 0, - {0xbb,0x03,0x1f} -}, -{ 6, - 0xd6b, - 0, - {0xba,0x00,0x03,0x02,0x0e,0xcd} -}, -{ 5, - 0xd71, - 0, - {0xba,0x02,0x02,0x80,0x03} -}, -{ 3, - 0xd76, - 0, - {0x02,0x0e,0xcd} -}, -{ 13, - 0xd79, - 0, - {0x75,0x59,0x01,0xc0,0x02,0xc0,0x03,0x12,0x0e,0xf0,0xd0,0x03,0xd0} -}, -{ 4, - 0xd86, - 0, - {0x02,0x02,0x0e,0xcd} -}, -{ 3, - 0xd8a, - 0, - {0xbb,0x06,0x54} -}, -{ 5, - 0xd8d, - 0, - {0xba,0x80,0x02,0x80,0x03} -}, -{ 3, - 0xd92, - 0, - {0x02,0x0e,0xc5} -}, -{ 8, - 0xd95, - 0, - {0x90,0x7f,0xeb,0xe0,0xfc,0xbc,0x01,0x15} -}, -{ 12, - 0xd9d, - 0, - {0x7c,0xfb,0x7d,0x0f,0x8d,0x06,0x7f,0x00,0x90,0x7f,0xd4,0xee} -}, -{ 9, - 0xda9, - 0, - {0xf0,0x90,0x7f,0xd5,0xec,0xf0,0x02,0x0e,0xcd} -}, -{ 10, - 0xdb2, - 0, - {0x90,0x7f,0xeb,0xe0,0xfc,0xbc,0x02,0x02,0x80,0x03} -}, -{ 3, - 0xdbc, - 0, - {0x02,0x0e,0xc5} -}, -{ 10, - 0xdbf, - 0, - {0x90,0x7f,0xea,0xe0,0xfc,0xbc,0x00,0x02,0x80,0x03} -}, -{ 3, - 0xdc9, - 0, - {0x02,0x0e,0xc5} -}, -{ 12, - 0xdcc, - 0, - {0x7c,0x3b,0x7d,0x0f,0x8d,0x06,0x7f,0x00,0x90,0x7f,0xd4,0xee} -}, -{ 9, - 0xdd8, - 0, - {0xf0,0x90,0x7f,0xd5,0xec,0xf0,0x02,0x0e,0xcd} -}, -{ 6, - 0xde1, - 0, - {0xbb,0x07,0x03,0x02,0x0e,0xc5} -}, -{ 3, - 0xde7, - 0, - {0xbb,0x08,0x10} -}, -{ 13, - 0xdea, - 0, - {0xac,0x48,0x90,0x7f,0x00,0xec,0xf0,0x90,0x7f,0xb5,0x74,0x01,0xf0} -}, -{ 3, - 0xdf7, - 0, - {0x02,0x0e,0xcd} -}, -{ 3, - 0xdfa, - 0, - {0xbb,0x09,0x31} -}, -{ 5, - 0xdfd, - 0, - {0xba,0x00,0x02,0x80,0x03} -}, -{ 3, - 0xe02, - 0, - {0x02,0x0e,0xc5} -}, -{ 14, - 0xe05, - 0, - {0x90,0x7f,0xea,0xe0,0xfc,0xc3,0x74,0x01,0x9c,0x50,0x03,0x02,0x0e,0xc5} -}, -{ 8, - 0xe13, - 0, - {0x90,0x7f,0xea,0xe0,0xfc,0xbc,0x00,0x0a} -}, -{ 10, - 0xe1b, - 0, - {0x90,0x17,0x21,0xe4,0xf0,0x90,0x17,0x22,0xe4,0xf0} -}, -{ 9, - 0xe25, - 0, - {0x90,0x7f,0xea,0xe0,0xf5,0x48,0x02,0x0e,0xcd} -}, -{ 3, - 0xe2e, - 0, - {0xbb,0x0a,0x27} -}, -{ 5, - 0xe31, - 0, - {0xba,0x81,0x02,0x80,0x03} -}, -{ 3, - 0xe36, - 0, - {0x02,0x0e,0xc5} -}, -{ 14, - 0xe39, - 0, - {0x90,0x7f,0xec,0xe0,0xfa,0x24,0x20,0xfa,0xe4,0x34,0x17,0xfc,0x8a,0x82} -}, -{ 14, - 0xe47, - 0, - {0x8c,0x83,0xe0,0xfa,0x90,0x7f,0x00,0xf0,0x90,0x7f,0xb5,0x74,0x01,0xf0} -}, -{ 3, - 0xe55, - 0, - {0x02,0x0e,0xcd} -}, -{ 5, - 0xe58, - 0, - {0xbb,0x0b,0x02,0x80,0x03} -}, -{ 3, - 0xe5d, - 0, - {0x02,0x0e,0xa9} -}, -{ 13, - 0xe60, - 0, - {0x90,0x17,0x20,0xe4,0xf0,0x90,0x7f,0xec,0xe0,0xfa,0xba,0x01,0x1a} -}, -{ 8, - 0xe6d, - 0, - {0x90,0x7f,0xed,0xe0,0xfa,0xba,0x00,0x12} -}, -{ 14, - 0xe75, - 0, - {0x90,0x7f,0xea,0xe0,0xfa,0x90,0x17,0x21,0xf0,0xc0,0x03,0x12,0x04,0xe2} -}, -{ 4, - 0xe83, - 0, - {0xd0,0x03,0x80,0x46} -}, -{ 8, - 0xe87, - 0, - {0x90,0x7f,0xec,0xe0,0xfa,0xba,0x02,0x3e} -}, -{ 8, - 0xe8f, - 0, - {0x90,0x7f,0xed,0xe0,0xfa,0xba,0x00,0x36} -}, -{ 13, - 0xe97, - 0, - {0xc0,0x03,0x12,0x04,0xef,0xd0,0x03,0x90,0x7f,0xea,0xe0,0xfa,0x90} -}, -{ 5, - 0xea4, - 0, - {0x17,0x22,0xf0,0x80,0x24} -}, -{ 5, - 0xea9, - 0, - {0xbb,0x12,0x02,0x80,0x17} -}, -{ 5, - 0xeae, - 0, - {0xbb,0x81,0x02,0x80,0x0d} -}, -{ 5, - 0xeb3, - 0, - {0xbb,0x83,0x02,0x80,0x08} -}, -{ 5, - 0xeb8, - 0, - {0xbb,0x82,0x02,0x80,0x03} -}, -{ 3, - 0xebd, - 0, - {0xbb,0x84,0x05} -}, -{ 5, - 0xec0, - 0, - {0x12,0x06,0x4e,0x80,0x08} -}, -{ 8, - 0xec5, - 0, - {0x90,0x7f,0xb4,0x74,0x03,0xf0,0x80,0x06} -}, -{ 6, - 0xecd, - 0, - {0x90,0x7f,0xb4,0x74,0x02,0xf0} -}, -{ 2, - 0xed3, - 0, - {0xd0,0x86} -}, -{ 14, - 0xed5, - 0, - {0xd0,0xd0,0xd0,0x01,0xd0,0x00,0xd0,0x07,0xd0,0x06,0xd0,0x05,0xd0,0x04} -}, -{ 13, - 0xee3, - 0, - {0xd0,0x03,0xd0,0x02,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32} -}, -{ 11, - 0xef0, - 0, - {0x90,0x7f,0xec,0xe0,0xf5,0x5a,0xc3,0x94,0x01,0x40,0x1d} -}, -{ 7, - 0xefb, - 0, - {0xc3,0x74,0x07,0x95,0x5a,0x40,0x16} -}, -{ 13, - 0xf02, - 0, - {0xe5,0x5a,0x24,0xff,0x25,0xe0,0xfa,0x24,0xc6,0xf5,0x82,0xe4,0x34} -}, -{ 9, - 0xf0f, - 0, - {0x7f,0xf5,0x83,0xaa,0x59,0xea,0xf0,0x80,0x22} -}, -{ 7, - 0xf18, - 0, - {0xc3,0xe5,0x5a,0x94,0x81,0x40,0x1b} -}, -{ 7, - 0xf1f, - 0, - {0xc3,0x74,0x87,0x95,0x5a,0x40,0x14} -}, -{ 13, - 0xf26, - 0, - {0xe5,0x5a,0x24,0xff,0x25,0xe0,0xfa,0x24,0xb6,0xf5,0x82,0xe4,0x34} -}, -{ 7, - 0xf33, - 0, - {0x7f,0xf5,0x83,0xaa,0x59,0xea,0xf0} -}, -{ 1, - 0xf3a, - 0, - {0x22} -}, -{ 14, - 0xf3b, - 0, - {0x09,0x02,0xba,0x00,0x03,0x01,0x00,0x40,0x00,0x09,0x04,0x00,0x00,0x00} -}, -{ 14, - 0xf49, - 0, - {0x01,0x01,0x00,0x00,0x09,0x24,0x01,0x00,0x01,0x3d,0x00,0x01,0x01,0x0c} -}, -{ 14, - 0xf57, - 0, - {0x24,0x02,0x01,0x10,0x07,0x00,0x02,0x03,0x00,0x00,0x00,0x0d,0x24,0x06} -}, -{ 14, - 0xf65, - 0, - {0x03,0x01,0x02,0x15,0x00,0x03,0x00,0x03,0x00,0x00,0x09,0x24,0x03,0x02} -}, -{ 14, - 0xf73, - 0, - {0x01,0x01,0x00,0x01,0x00,0x09,0x24,0x03,0x04,0x02,0x03,0x00,0x03,0x00} -}, -{ 14, - 0xf81, - 0, - {0x09,0x24,0x03,0x05,0x03,0x06,0x00,0x01,0x00,0x09,0x04,0x01,0x00,0x00} -}, -{ 14, - 0xf8f, - 0, - {0x01,0x02,0x00,0x00,0x09,0x04,0x01,0x01,0x01,0x01,0x02,0x00,0x00,0x07} -}, -{ 14, - 0xf9d, - 0, - {0x24,0x01,0x02,0x01,0x01,0x00,0x0b,0x24,0x02,0x01,0x02,0x02,0x10,0x01} -}, -{ 14, - 0xfab, - 0, - {0x80,0xbb,0x00,0x09,0x05,0x88,0x05,0x00,0x01,0x01,0x00,0x00,0x07,0x25} -}, -{ 14, - 0xfb9, - 0, - {0x01,0x00,0x00,0x00,0x00,0x09,0x04,0x02,0x00,0x02,0x00,0x00,0x00,0x00} -}, -{ 14, - 0xfc7, - 0, - {0x07,0x05,0x82,0x02,0x40,0x00,0x00,0x07,0x05,0x02,0x02,0x40,0x00,0x00} -}, -{ 14, - 0xfd5, - 0, - {0x09,0x04,0x02,0x01,0x03,0x00,0x00,0x00,0x00,0x07,0x05,0x82,0x02,0x40} -}, -{ 14, - 0xfe3, - 0, - {0x00,0x00,0x07,0x05,0x02,0x02,0x40,0x00,0x00,0x09,0x05,0x89,0x05,0xa0} -}, -{ 10, - 0xff1, - 0, - {0x01,0x01,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00} -}, -{ 14, - 0xffb, - 0, - {0x12,0x01,0x00,0x01,0x00,0x00,0x00,0x40,0x47,0x05,0x99,0x99,0x00,0x01} -}, -{ 14, - 0x1009, - 0, - {0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x02,0xba} -}, -{ 4, - 0x1017, - 0, - {0x00,0x03,0x01,0x00} -}, -{ 2, - 0x101b, - 0, - {0x7a,0x00} -}, -{ 3, - 0x101d, - 0, - {0xba,0x05,0x00} -}, -{ 2, - 0x1020, - 0, - {0x50,0x17} -}, -{ 8, - 0x1022, - 0, - {0x90,0x7f,0xa5,0xe0,0xfb,0x30,0xe0,0x05} -}, -{ 5, - 0x102a, - 0, - {0x90,0x00,0x01,0x80,0x0d} -}, -{ 10, - 0x102f, - 0, - {0xc0,0x02,0x12,0x01,0xdd,0xd0,0x02,0x0a,0x80,0xe4} -}, -{ 3, - 0x1039, - 0, - {0x90,0x00,0x01} -}, -{ 1, - 0x103c, - 0, - {0x22} -}, -{ 14, - 0x103d, - 0, - {0x90,0x7d,0xc1,0xe0,0xf9,0xa3,0xe0,0xfa,0xa3,0xe0,0xfb,0x7c,0x00,0x7d} -}, -{ 4, - 0x104b, - 0, - {0x7e,0xeb,0x60,0x12} -}, -{ 14, - 0x104f, - 0, - {0x89,0x82,0x8a,0x83,0xe0,0xa3,0xa9,0x82,0xaa,0x83,0x8c,0x82,0x8d,0x83} -}, -{ 4, - 0x105d, - 0, - {0xf0,0x0c,0xdb,0xee} -}, -{ 8, - 0x1061, - 0, - {0x90,0x7d,0xc3,0xe0,0x90,0x7f,0xb9,0xf0} -}, -{ 1, - 0x1069, - 0, - {0x22} -}, -{ 14, - 0x106a, - 0, - {0x90,0x7d,0xc1,0xe0,0xf9,0xa3,0xe0,0xfa,0xa3,0xe0,0xfb,0x7c,0xc4,0x7d} -}, -{ 4, - 0x1078, - 0, - {0x7d,0xeb,0x60,0xe5} -}, -{ 14, - 0x107c, - 0, - {0x8c,0x82,0x8d,0x83,0xe0,0x0c,0x89,0x82,0x8a,0x83,0xf0,0xa3,0xa9,0x82} -}, -{ 4, - 0x108a, - 0, - {0xaa,0x83,0xdb,0xee} -}, -{ 1, - 0x108e, - 0, - {0x22} -}, -{ 14, - 0x108f, - 0, - {0x90,0x7f,0xa5,0x74,0x80,0xf0,0x05,0x86,0x90,0x7d,0xc1,0xe0,0x05,0x86} -}, -{ 14, - 0x109d, - 0, - {0xa3,0xf0,0x12,0x10,0x1b,0x90,0x7f,0xa6,0x05,0x86,0xa3,0xa3,0xe0,0xf9} -}, -{ 5, - 0x10ab, - 0, - {0x60,0x16,0xa3,0x05,0x86} -}, -{ 13, - 0x10b0, - 0, - {0x90,0x7f,0xa6,0x05,0x86,0xe0,0xa3,0x05,0x86,0xf0,0xc0,0x01,0x12} -}, -{ 6, - 0x10bd, - 0, - {0x10,0x1b,0xd0,0x01,0xd9,0xed} -}, -{ 6, - 0x10c3, - 0, - {0x90,0x7f,0xa5,0x74,0x40,0xf0} -}, -{ 1, - 0x10c9, - 0, - {0x22} -}, -{ 8, - 0x10ca, - 0, - {0x90,0x88,0x02,0x74,0x01,0xf0,0x7a,0x00} -}, -{ 3, - 0x10d2, - 0, - {0xba,0xff,0x00} -}, -{ 2, - 0x10d5, - 0, - {0x50,0x0a} -}, -{ 10, - 0x10d7, - 0, - {0xc0,0x02,0x12,0x01,0xdd,0xd0,0x02,0x0a,0x80,0xf1} -}, -{ 1, - 0x10e1, - 0, - {0x22} -}, -{ 5, - 0x10e2, - 0, - {0xe5,0x6b,0xb4,0xc0,0x08} -}, -{ 8, - 0x10e7, - 0, - {0x90,0x88,0x03,0xe5,0x6c,0xf0,0x80,0x06} -}, -{ 6, - 0x10ef, - 0, - {0x90,0x88,0x02,0xe5,0x6c,0xf0} -}, -{ 4, - 0x10f5, - 0, - {0x7a,0x00,0x7b,0x00} -}, -{ 11, - 0x10f9, - 0, - {0xc3,0xea,0x94,0x32,0xeb,0x64,0x80,0x94,0x80,0x50,0x07} -}, -{ 5, - 0x1104, - 0, - {0x0a,0xba,0x00,0x01,0x0b} -}, -{ 2, - 0x1109, - 0, - {0x80,0xee} -}, -{ 1, - 0x110b, - 0, - {0x22} -}, -{ 10, - 0x110c, - 0, - {0x90,0x88,0x03,0xe5,0x6d,0xf0,0x05,0x39,0x7a,0x00} -}, -{ 3, - 0x1116, - 0, - {0xba,0x28,0x00} -}, -{ 2, - 0x1119, - 0, - {0x50,0x03} -}, -{ 3, - 0x111b, - 0, - {0x0a,0x80,0xf8} -}, -{ 5, - 0x111e, - 0, - {0xe5,0x39,0xb4,0x10,0x08} -}, -{ 8, - 0x1123, - 0, - {0x90,0x88,0x02,0x74,0xc0,0xf0,0x80,0x0e} -}, -{ 5, - 0x112b, - 0, - {0xe5,0x39,0xb4,0x20,0x09} -}, -{ 9, - 0x1130, - 0, - {0x90,0x88,0x02,0x74,0x80,0xf0,0x75,0x39,0x00} -}, -{ 2, - 0x1139, - 0, - {0x7a,0x00} -}, -{ 3, - 0x113b, - 0, - {0xba,0x28,0x00} -}, -{ 2, - 0x113e, - 0, - {0x50,0x03} -}, -{ 3, - 0x1140, - 0, - {0x0a,0x80,0xf8} -}, -{ 1, - 0x1143, - 0, - {0x22} -}, -{ 4, - 0x1144, - 0, - {0xe5,0x6f,0x60,0x02} -}, -{ 2, - 0x1148, - 0, - {0x80,0x07} -}, -{ 7, - 0x114a, - 0, - {0x7a,0x00,0x75,0x39,0x00,0x80,0x05} -}, -{ 5, - 0x1151, - 0, - {0x7a,0x40,0x75,0x39,0x10} -}, -{ 9, - 0x1156, - 0, - {0xe5,0x6e,0x2a,0xfa,0xe5,0x6e,0x25,0x39,0xf5} -}, -{ 10, - 0x115f, - 0, - {0x39,0x90,0x88,0x02,0x74,0x80,0x2a,0xf0,0x7a,0x00} -}, -{ 8, - 0x1169, - 0, - {0xc3,0xea,0x64,0x80,0x94,0xa8,0x50,0x03} -}, -{ 3, - 0x1171, - 0, - {0x0a,0x80,0xf5} -}, -{ 1, - 0x1174, - 0, - {0x22} -}, -{ 6, - 0x1175, - 0, - {0xaa,0x70,0xab,0x71,0xac,0x72} -}, -{ 12, - 0x117b, - 0, - {0x8a,0x82,0x8b,0x83,0x8c,0xf0,0x12,0x14,0xee,0xfd,0x60,0x18} -}, -{ 13, - 0x1187, - 0, - {0x8d,0x6d,0xc0,0x02,0xc0,0x03,0xc0,0x04,0x12,0x11,0x0c,0xd0,0x04} -}, -{ 9, - 0x1194, - 0, - {0xd0,0x03,0xd0,0x02,0x0a,0xba,0x00,0x01,0x0b} -}, -{ 2, - 0x119d, - 0, - {0x80,0xdc} -}, -{ 1, - 0x119f, - 0, - {0x22} -}, -{ 13, - 0x11a0, - 0, - {0xe5,0x73,0xc4,0x54,0x0f,0xfa,0x53,0x02,0x0f,0xc3,0x74,0x09,0x9a} -}, -{ 2, - 0x11ad, - 0, - {0x50,0x06} -}, -{ 6, - 0x11af, - 0, - {0x74,0x37,0x2a,0xfb,0x80,0x04} -}, -{ 4, - 0x11b5, - 0, - {0x74,0x30,0x2a,0xfb} -}, -{ 12, - 0x11b9, - 0, - {0x8b,0x6d,0xc0,0x03,0x12,0x11,0x0c,0xd0,0x03,0xaa,0x73,0x53} -}, -{ 8, - 0x11c5, - 0, - {0x02,0x0f,0xc3,0x74,0x09,0x9a,0x50,0x06} -}, -{ 6, - 0x11cd, - 0, - {0x74,0x37,0x2a,0xfb,0x80,0x04} -}, -{ 4, - 0x11d3, - 0, - {0x74,0x30,0x2a,0xfb} -}, -{ 5, - 0x11d7, - 0, - {0x8b,0x6d,0x12,0x11,0x0c} -}, -{ 1, - 0x11dc, - 0, - {0x22} -}, -{ 7, - 0x11dd, - 0, - {0x90,0x7d,0xc3,0xe0,0xfa,0x60,0x0f} -}, -{ 12, - 0x11e4, - 0, - {0x90,0x7d,0xc1,0xe0,0xf5,0x6e,0x90,0x7d,0xc2,0xe0,0xf5,0x6f} -}, -{ 3, - 0x11f0, - 0, - {0x12,0x11,0x44} -}, -{ 12, - 0x11f3, - 0, - {0x90,0x7d,0xff,0xe4,0xf0,0x75,0x70,0xc4,0x75,0x71,0x7d,0x75} -}, -{ 5, - 0x11ff, - 0, - {0x72,0x01,0x12,0x11,0x75} -}, -{ 1, - 0x1204, - 0, - {0x22} -}, -{ 2, - 0x1205, - 0, - {0x7a,0x04} -}, -{ 3, - 0x1207, - 0, - {0xba,0x40,0x00} -}, -{ 2, - 0x120a, - 0, - {0x50,0x36} -}, -{ 14, - 0x120c, - 0, - {0xea,0x24,0xc0,0xf5,0x82,0xe4,0x34,0x7d,0xf5,0x83,0xe0,0xfb,0x7c,0x00} -}, -{ 3, - 0x121a, - 0, - {0xbc,0x08,0x00} -}, -{ 2, - 0x121d, - 0, - {0x50,0x20} -}, -{ 6, - 0x121f, - 0, - {0x8b,0x05,0xed,0x30,0xe7,0x0b} -}, -{ 11, - 0x1225, - 0, - {0x90,0x7f,0x96,0x74,0x42,0xf0,0x74,0xc3,0xf0,0x80,0x08} -}, -{ 8, - 0x1230, - 0, - {0x90,0x7f,0x96,0xe4,0xf0,0x74,0x81,0xf0} -}, -{ 7, - 0x1238, - 0, - {0xeb,0x25,0xe0,0xfb,0x0c,0x80,0xdb} -}, -{ 3, - 0x123f, - 0, - {0x0a,0x80,0xc5} -}, -{ 1, - 0x1242, - 0, - {0x22} -}, -{ 4, - 0x1243, - 0, - {0x7a,0x00,0x7b,0xef} -}, -{ 3, - 0x1247, - 0, - {0xba,0x10,0x00} -}, -{ 2, - 0x124a, - 0, - {0x50,0x20} -}, -{ 14, - 0x124c, - 0, - {0x74,0x11,0x2b,0xfb,0x24,0x00,0xfc,0xe4,0x34,0x18,0xfd,0x8c,0x82,0x8d} -}, -{ 14, - 0x125a, - 0, - {0x83,0xe4,0xf0,0xea,0x24,0x00,0xf5,0x82,0xe4,0x34,0x19,0xf5,0x83,0xe4} -}, -{ 4, - 0x1268, - 0, - {0xf0,0x0a,0x80,0xdb} -}, -{ 1, - 0x126c, - 0, - {0x22} -}, -{ 14, - 0x126d, - 0, - {0x74,0xf8,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0xe4,0xf0} -}, -{ 14, - 0x127b, - 0, - {0x74,0xf9,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0xe4,0xf0} -}, -{ 14, - 0x1289, - 0, - {0x74,0xfa,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0xe4,0xf0} -}, -{ 14, - 0x1297, - 0, - {0x74,0xfb,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0xe4,0xf0} -}, -{ 14, - 0x12a5, - 0, - {0x74,0xff,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0xe4,0xf0} -}, -{ 1, - 0x12b3, - 0, - {0x22} -}, -{ 14, - 0x12b4, - 0, - {0x12,0x03,0xcb,0x12,0x12,0x6d,0x7a,0xc0,0x7b,0x87,0x7c,0x01,0x74,0x01} -}, -{ 14, - 0x12c2, - 0, - {0x2a,0xfd,0xe4,0x3b,0xfe,0x8c,0x07,0x8a,0x82,0x8b,0x83,0x8c,0xf0,0x74} -}, -{ 14, - 0x12d0, - 0, - {0x01,0x12,0x14,0xbf,0x2d,0xfa,0xe4,0x3e,0xfb,0x8f,0x04,0x8d,0x82,0x8e} -}, -{ 14, - 0x12de, - 0, - {0x83,0x8f,0xf0,0x74,0x06,0x12,0x14,0xbf,0x74,0x01,0x2a,0xfd,0xe4,0x3b} -}, -{ 14, - 0x12ec, - 0, - {0xfe,0x8c,0x07,0x8a,0x82,0x8b,0x83,0x8c,0xf0,0xe4,0x12,0x14,0xbf,0x74} -}, -{ 14, - 0x12fa, - 0, - {0x01,0x2d,0xfa,0xe4,0x3e,0xfb,0x8f,0x04,0x8d,0x82,0x8e,0x83,0x8f,0xf0} -}, -{ 14, - 0x1308, - 0, - {0x74,0x0b,0x12,0x14,0xbf,0x74,0x01,0x2a,0xfd,0xe4,0x3b,0xfe,0x8c,0x07} -}, -{ 14, - 0x1316, - 0, - {0x8a,0x82,0x8b,0x83,0x8c,0xf0,0x74,0x08,0x12,0x14,0xbf,0x74,0x01,0x2d} -}, -{ 14, - 0x1324, - 0, - {0xfa,0xe4,0x3e,0xfb,0x8f,0x04,0x8d,0x82,0x8e,0x83,0x8f,0xf0,0x74,0x01} -}, -{ 14, - 0x1332, - 0, - {0x12,0x14,0xbf,0x2a,0xfd,0xe4,0x3b,0xfe,0x8c,0x07,0x8a,0x82,0x8b,0x83} -}, -{ 14, - 0x1340, - 0, - {0x8c,0xf0,0xe4,0x12,0x14,0xbf,0x74,0x01,0x2d,0xfa,0xe4,0x3e,0xfb,0x8f} -}, -{ 14, - 0x134e, - 0, - {0x04,0x8d,0x82,0x8e,0x83,0x8f,0xf0,0x74,0x03,0x12,0x14,0xbf,0x7d,0x00} -}, -{ 3, - 0x135c, - 0, - {0xbd,0x06,0x00} -}, -{ 2, - 0x135f, - 0, - {0x50,0x12} -}, -{ 11, - 0x1361, - 0, - {0x8a,0x82,0x8b,0x83,0x8c,0xf0,0x0a,0xba,0x00,0x01,0x0b} -}, -{ 7, - 0x136c, - 0, - {0xe4,0x12,0x14,0xbf,0x0d,0x80,0xe9} -}, -{ 13, - 0x1373, - 0, - {0x8a,0x82,0x8b,0x83,0x8c,0xf0,0xe5,0x74,0x12,0x14,0xbf,0x74,0xf9} -}, -{ 14, - 0x1380, - 0, - {0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0x74,0x0f,0xf0,0x74} -}, -{ 14, - 0x138e, - 0, - {0xfe,0x24,0x00,0xf5,0x82,0x74,0x03,0x34,0x84,0xf5,0x83,0x74,0x01,0xf0} -}, -{ 6, - 0x139c, - 0, - {0x12,0x03,0xe1,0x12,0x04,0xf7} -}, -{ 1, - 0x13a2, - 0, - {0x22} -}, -{ 13, - 0x13a3, - 0, - {0x90,0x7d,0xc1,0xe0,0xfa,0x24,0x00,0xfb,0xe4,0x34,0x19,0xfc,0x90} -}, -{ 14, - 0x13b0, - 0, - {0x7d,0xc2,0xe0,0xfd,0x8b,0x82,0x8c,0x83,0xf0,0x75,0xf0,0x11,0xea,0xa4} -}, -{ 3, - 0x13be, - 0, - {0xfa,0x7b,0x00} -}, -{ 3, - 0x13c1, - 0, - {0xbb,0x10,0x00} -}, -{ 2, - 0x13c4, - 0, - {0x50,0x24} -}, -{ 14, - 0x13c6, - 0, - {0xea,0x24,0x00,0xfc,0xe4,0x34,0x18,0xfd,0xeb,0x2c,0xfc,0xe4,0x3d,0xfd} -}, -{ 14, - 0x13d4, - 0, - {0x74,0x04,0x2b,0x24,0xc0,0xf5,0x82,0xe4,0x34,0x7d,0xf5,0x83,0xe0,0xfe} -}, -{ 8, - 0x13e2, - 0, - {0x8c,0x82,0x8d,0x83,0xf0,0x0b,0x80,0xd7} -}, -{ 14, - 0x13ea, - 0, - {0xea,0x24,0x00,0xfa,0xe4,0x34,0x18,0xfb,0x74,0x10,0x2a,0xf5,0x82,0xe4} -}, -{ 5, - 0x13f8, - 0, - {0x3b,0xf5,0x83,0xe4,0xf0} -}, -{ 1, - 0x13fd, - 0, - {0x22} -}, -{ 4, - 0x13fe, - 0, - {0xe5,0x76,0x60,0x02} -}, -{ 2, - 0x1402, - 0, - {0x80,0x16} -}, -{ 12, - 0x1404, - 0, - {0x74,0x0f,0x55,0x75,0xfa,0x8a,0x75,0x24,0x00,0xf5,0x82,0xe4} -}, -{ 10, - 0x1410, - 0, - {0x34,0x19,0xf5,0x83,0xe0,0xf5,0x74,0x12,0x12,0xb4} -}, -{ 10, - 0x141a, - 0, - {0x12,0x10,0xca,0x75,0x6e,0x00,0x75,0x6f,0x00,0x12} -}, -{ 6, - 0x1424, - 0, - {0x11,0x44,0x75,0x70,0xb9,0x75} -}, -{ 6, - 0x142a, - 0, - {0x71,0x14,0x75,0x72,0x02,0x12} -}, -{ 11, - 0x1430, - 0, - {0x11,0x75,0xe5,0x76,0xb4,0x02,0x04,0x74,0x01,0x80,0x01} -}, -{ 1, - 0x143b, - 0, - {0xe4} -}, -{ 3, - 0x143c, - 0, - {0xfa,0x70,0x0f} -}, -{ 12, - 0x143f, - 0, - {0x74,0x01,0x25,0x75,0xf5,0x73,0xc0,0x02,0x12,0x11,0xa0,0xd0} -}, -{ 3, - 0x144b, - 0, - {0x02,0x80,0x0a} -}, -{ 10, - 0x144e, - 0, - {0x85,0x75,0x73,0xc0,0x02,0x12,0x11,0xa0,0xd0,0x02} -}, -{ 12, - 0x1458, - 0, - {0x75,0x6e,0x00,0x75,0x6f,0x01,0xc0,0x02,0x12,0x11,0x44,0xd0} -}, -{ 4, - 0x1464, - 0, - {0x02,0xea,0x70,0x1a} -}, -{ 13, - 0x1468, - 0, - {0x75,0xf0,0x11,0xe5,0x75,0xa4,0xfa,0x24,0x00,0xfa,0xe4,0x34,0x18} -}, -{ 9, - 0x1475, - 0, - {0xfb,0x8a,0x70,0x8b,0x71,0x75,0x72,0x01,0x12} -}, -{ 4, - 0x147e, - 0, - {0x11,0x75,0x80,0x36} -}, -{ 2, - 0x1482, - 0, - {0x7a,0x00} -}, -{ 3, - 0x1484, - 0, - {0xba,0x10,0x00} -}, -{ 2, - 0x1487, - 0, - {0x50,0x2f} -}, -{ 13, - 0x1489, - 0, - {0xea,0x24,0x00,0xf5,0x82,0xe4,0x34,0x19,0xf5,0x83,0xe0,0xfb,0xe5} -}, -{ 4, - 0x1496, - 0, - {0x75,0xb5,0x03,0x1b} -}, -{ 14, - 0x149a, - 0, - {0x75,0xf0,0x11,0xea,0xa4,0xfb,0x24,0x00,0xfb,0xe4,0x34,0x18,0xfc,0x8b} -}, -{ 9, - 0x14a8, - 0, - {0x70,0x8c,0x71,0x75,0x72,0x01,0xc0,0x02,0x12} -}, -{ 4, - 0x14b1, - 0, - {0x11,0x75,0xd0,0x02} -}, -{ 3, - 0x14b5, - 0, - {0x0a,0x80,0xcc} -}, -{ 1, - 0x14b8, - 0, - {0x22} -}, -{ 6, - 0x14b9, - 0, - {0x50,0x72,0x6f,0x67,0x20,0x00} -}, -{ 14, - 0x14bf, - 0, - {0xc8,0xc0,0xe0,0xc8,0xc0,0xe0,0xe5,0xf0,0x60,0x0b,0x14,0x60,0x0f,0x14} -}, -{ 7, - 0x14cd, - 0, - {0x60,0x11,0x14,0x60,0x12,0x80,0x15} -}, -{ 7, - 0x14d4, - 0, - {0xd0,0xe0,0xa8,0x82,0xf6,0x80,0x0e} -}, -{ 5, - 0x14db, - 0, - {0xd0,0xe0,0xf0,0x80,0x09} -}, -{ 4, - 0x14e0, - 0, - {0xd0,0xe0,0x80,0x05} -}, -{ 5, - 0x14e4, - 0, - {0xd0,0xe0,0xa8,0x82,0xf2} -}, -{ 4, - 0x14e9, - 0, - {0xc8,0xd0,0xe0,0xc8} -}, -{ 1, - 0x14ed, - 0, - {0x22} -}, -{ 14, - 0x14ee, - 0, - {0xc8,0xc0,0xe0,0xe5,0xf0,0x60,0x0d,0x14,0x60,0x0f,0x14,0x60,0x0f,0x14} -}, -{ 6, - 0x14fc, - 0, - {0x60,0x10,0x74,0xff,0x80,0x0f} -}, -{ 5, - 0x1502, - 0, - {0xa8,0x82,0xe6,0x80,0x0a} -}, -{ 3, - 0x1507, - 0, - {0xe0,0x80,0x07} -}, -{ 4, - 0x150a, - 0, - {0xe4,0x93,0x80,0x03} -}, -{ 3, - 0x150e, - 0, - {0xa8,0x82,0xe2} -}, -{ 4, - 0x1511, - 0, - {0xf8,0xd0,0xe0,0xc8} -}, -{ 1, - 0x1515, - 0, - {0x22} -}, -{ 0, - 0x0, - 1, - {0} -} -}; diff --git a/drivers/usb/graphire.c b/drivers/usb/graphire.c index cfda14d5c..8921c7db8 100644 --- a/drivers/usb/graphire.c +++ b/drivers/usb/graphire.c @@ -1,11 +1,16 @@ /* - * graphire.c Version 0.1 + * graphire.c Version 0.2 * - * Copyright (c) 1999 Vojtech Pavlik + * Copyright (c) 2000 Vojtech Pavlik + * Copyright (c) 2000 Andreas Bach Aaen * * USB Wacom Graphire tablet support * * Sponsored by SuSE + * + * ChangeLog: + * v0.1 (vp) - Initial release + * v0.2 (aba) - Support for all buttons / combinations */ /* @@ -57,14 +62,19 @@ MODULE_AUTHOR("Vojtech Pavlik "); * byte 7: pen presure high bits / mouse distance * * There are also two single-byte feature reports (2 and 3). + * + * Resolution: + * X: 0 - 10206 + * Y: 0 - 7422 + * + * (0,0) is upper left corner */ -#define USB_VENDOR_ID_WACOM 0xffff /* FIXME */ -#define USB_DEVICE_ID_WACOM_GRAPHIRE 0xffff /* FIXME */ +#define USB_VENDOR_ID_WACOM 0x056a +#define USB_DEVICE_ID_WACOM_GRAPHIRE 0x0010 struct graphire { signed char data[8]; - int oldx, oldy; struct input_dev dev; struct urb irq; }; @@ -80,44 +90,38 @@ static void graphire_irq(struct urb *urb) 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)); + if ( data[1] & 0x80 ) { + input_report_abs(dev, ABS_X, data[2] | ((__u32)data[3] << 8)); + input_report_abs(dev, ABS_Y, 7422 - (data[4] | ((__u32)data[5] << 8))); + } 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_key(dev, BTN_TOOL_PEN, !!(data[1] & 0x80)); + input_report_key(dev, BTN_TOUCH, !!(data[1] & 0x01)); + input_report_key(dev, BTN_STYLUS, !!(data[1] & 0x02)); + input_report_key(dev, BTN_STYLUS2, !!(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_key(dev, BTN_TOOL_RUBBER, !!(data[1] & 0x80)); + input_report_key(dev, BTN_TOUCH, !!(data[1] & 0x01)); + input_report_key(dev, BTN_STYLUS, !!(data[1] & 0x02)); + input_report_key(dev, BTN_STYLUS2, !!(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_key(dev, BTN_TOOL_MOUSE, data[7] > 24); + input_report_key(dev, BTN_LEFT, !!(data[1] & 0x01)); + input_report_key(dev, BTN_RIGHT, !!(data[1] & 0x02)); + input_report_key(dev, BTN_MIDDLE, !!(data[1] & 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) @@ -136,11 +140,16 @@ static void *graphire_probe(struct usb_device *dev, unsigned int ifnum) 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.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE); + graphire->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2); + graphire->dev.relbit[0] |= BIT(REL_WHEEL); graphire->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | BIT(ABS_DISTANCE); + graphire->dev.absmax[ABS_X] = 10206; + graphire->dev.absmax[ABS_Y] = 7422; + graphire->dev.absmax[ABS_PRESSURE] = 511; + graphire->dev.absmax[ABS_DISTANCE] = 32; + FILL_INT_URB(&graphire->irq, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress), graphire->data, 8, graphire_irq, graphire, endpoint->bInterval); @@ -151,7 +160,7 @@ static void *graphire_probe(struct usb_device *dev, unsigned int ifnum) input_register_device(&graphire->dev); - printk(KERN_INFO "input%d: Wacom Graphire USB\n", graphire->dev.number); + printk(KERN_INFO "input%d: Wacom Graphire\n", graphire->dev.number); return graphire; } diff --git a/drivers/usb/hid.c b/drivers/usb/hid.c index ec1a4639d..28c4cc507 100644 --- a/drivers/usb/hid.c +++ b/drivers/usb/hid.c @@ -742,7 +742,11 @@ static void hid_configure_usage(struct hid_device *device, struct hid_field *fie switch (device->application) { case HID_GD_GAMEPAD: usage->code += 0x10; case HID_GD_JOYSTICK: usage->code += 0x10; - case HID_GD_MOUSE: usage->code += 0x10; + case HID_GD_MOUSE: usage->code += 0x10; break; + default: + if (field->physical == HID_GD_POINTER) + usage->code += 0x10; + break; } break; @@ -769,7 +773,49 @@ static void hid_configure_usage(struct hid_device *device, struct hid_field *fie usage->type = EV_LED; bit = input->ledbit; max = LED_MAX; break; + case HID_UP_DIGITIZER: + + switch (usage->hid & 0xff) { + + case 0x30: /* TipPressure */ + + usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX; + usage->code = ABS_PRESSURE; + clear_bit(usage->code, bit); + break; + + case 0x32: /* InRange */ + + usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; + switch (field->physical & 0xff) { + case 0x21: usage->code = BTN_TOOL_MOUSE; break; + case 0x22: usage->code = BTN_TOOL_FINGER; break; + default: usage->code = BTN_TOOL_PEN; break; + } + break; + + case 0x33: /* Touch */ + case 0x42: /* TipSwitch */ + case 0x43: /* TipSwitch2 */ + + usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; + usage->code = BTN_TOUCH; + clear_bit(usage->code, bit); + break; + + case 0x44: /* BarrelSwitch */ + + usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; + usage->code = BTN_STYLUS; + clear_bit(usage->code, bit); + break; + + default: goto unknown; + } + break; + default: + unknown: if (field->flags & HID_MAIN_ITEM_RELATIVE) { usage->code = REL_MISC; @@ -777,7 +823,7 @@ static void hid_configure_usage(struct hid_device *device, struct hid_field *fie break; } - if (field->logical_minimum == 0 && field->logical_maximum == 1) { + if (field->report_size == 1) { usage->code = BTN_MISC; usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; break; @@ -959,7 +1005,7 @@ 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 + hid->report_enum[HID_INPUT_REPORT].numbered; + int rlen = ((report->size - 1) >> 3) + 1; char rdata[rlen]; struct urb urb; int read, j; @@ -973,7 +1019,7 @@ static void hid_read_report(struct hid_device *hid, struct hid_report *report) dbg("getting report type %d id %d len %d", report->type + 1, report->id, rlen); - if ((read = usb_get_report(hid->dev, report->type + 1, report->id, hid->ifnum, rdata, rlen)) != rlen) { + if ((read = usb_get_report(hid->dev, hid->ifnum, report->type + 1, report->id, rdata, rlen)) != rlen) { dbg("reading report failed rlen %d read %d", rlen, read); #ifdef DEBUG printk(KERN_DEBUG __FILE__ ": report = "); @@ -1013,13 +1059,6 @@ static void hid_output_field(struct hid_field *field, __u8 *data) 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); }; @@ -1142,7 +1181,7 @@ static void hid_init_input(struct hid_device *hid) 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); + usb_set_idle(hid->dev, hid->ifnum, report->id, 0); hid_read_report(hid, report); } } @@ -1151,7 +1190,7 @@ static void hid_init_input(struct hid_device *hid) 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_interface_descriptor *interface = dev->actconfig->interface[ifnum].altsetting + 0; struct hid_descriptor *hdesc; struct hid_device *hid; unsigned rsize = 0; @@ -1178,7 +1217,7 @@ static struct hid_device *usb_hid_configure(struct usb_device *dev, int ifnum) { __u8 rdesc[rsize]; - if ((n = usb_get_class_descriptor(dev, USB_DT_REPORT, 0, ifnum, rdesc, rsize)) < 0) { + if ((n = usb_get_class_descriptor(dev, interface->bInterfaceNumber, USB_DT_REPORT, 0, rdesc, rsize)) < 0) { dbg("reading report descriptor failed"); return NULL; } @@ -1226,19 +1265,22 @@ static struct hid_device *usb_hid_configure(struct usb_device *dev, int ifnum) return NULL; } + hid->version = hdesc->bcdHID; + hid->country = hdesc->bCountryCode; + hid->dev = dev; + hid->ifnum = interface->bInterfaceNumber; + 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.index = hid->ifnum; 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; - hid->ifnum = ifnum; + if (interface->bInterfaceSubClass == 1) + usb_set_protocol(dev, hid->ifnum, 1); return hid; } diff --git a/drivers/usb/hid.h b/drivers/usb/hid.h index ab652442f..e53135f1e 100644 --- a/drivers/usb/hid.h +++ b/drivers/usb/hid.h @@ -30,7 +30,6 @@ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic */ -#include #include #include #include @@ -164,6 +163,7 @@ struct hid_item { #define HID_USAGE 0x0000ffff +#define HID_GD_POINTER 0x00010001 #define HID_GD_MOUSE 0x00010002 #define HID_GD_JOYSTICK 0x00010004 #define HID_GD_GAMEPAD 0x00010005 diff --git a/drivers/usb/hub.c b/drivers/usb/hub.c index c066c3c43..3eca7a857 100644 --- a/drivers/usb/hub.c +++ b/drivers/usb/hub.c @@ -5,7 +5,7 @@ * (C) Copyright 1999 Johannes Erdfelt * (C) Copyright 1999 Gregory P. Smith * - * $Id: hub.c,v 1.15 1999/12/27 15:17:45 acher Exp $ + * $Id: hub.c,v 1.21 2000/01/16 21:19:44 acher Exp $ */ #include @@ -22,15 +22,6 @@ #include "usb.h" #include "hub.h" -#ifdef __alpha -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) -extern long __kernel_thread(unsigned long, int (*)(void *), void *); -static inline long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) -{ - return __kernel_thread(flags | CLONE_VM, fn, arg); -} -#endif -#endif /* Wakes up khubd */ static spinlock_t hub_event_lock = SPIN_LOCK_UNLOCKED; @@ -112,6 +103,16 @@ static int hub_irq(int status, void *__buffer, int len, void *dev_id) return 1; } +static void usb_hub_power_on(struct usb_hub *hub) +{ + int i; + + /* Enable power to the ports */ + dbg("enabling power on all ports"); + for (i = 0; i < hub->nports; i++) + usb_set_port_feature(hub->dev, i + 1, USB_PORT_FEAT_POWER); +} + static int usb_hub_configure(struct usb_hub *hub) { struct usb_device *dev = hub->dev; @@ -191,10 +192,8 @@ static int usb_hub_configure(struct usb_hub *hub) dbg("%sover-current condition exists", (le16_to_cpu(hubsts->wHubStatus) & HUB_STATUS_OVERCURRENT) ? "" : "no "); - /* Enable power to the ports */ - dbg("enabling power on all ports"); - for (i = 0; i < hub->nports; i++) - usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER); + usb_hub_power_on(hub); + return 0; } @@ -322,13 +321,17 @@ static void usb_hub_port_connect_change(struct usb_device *hub, int port) portchange = le16_to_cpu(portsts.wPortChange); dbg("portstatus %x, change %x, %s", portstatus, portchange, portstatus&(1<children[port])) { usb_disconnect(&hub->children[port]); - /* We're done now, we already disconnected the device */ - return; + /* Return now if nothing is connected */ + if (!(portstatus & USB_PORT_STAT_CONNECTION)) + return; } wait_ms(400); @@ -350,7 +353,11 @@ static void usb_hub_port_connect_change(struct usb_device *hub, int port) dbg("portstatus %x, change %x, %s", portstatus ,portchange, portstatus&(1<bus); @@ -432,8 +442,6 @@ static void usb_hub_events(void) if (portchange & USB_PORT_STAT_C_CONNECTION) { dbg("port %d connection change", i + 1); - usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_CONNECTION); - usb_hub_port_connect_change(dev, i); } @@ -442,12 +450,15 @@ static void usb_hub_events(void) usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_ENABLE); } - if (portchange & USB_PORT_STAT_C_SUSPEND) + if (portstatus & USB_PORT_STAT_SUSPEND) { dbg("port %d suspend change", i + 1); - + usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_SUSPEND); + } + if (portchange & USB_PORT_STAT_C_OVERCURRENT) { - dbg("port %d over-current change", i + 1); + err("port %d over-current change", i + 1); usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_OVER_CURRENT); + usb_hub_power_on(hub); } if (portchange & USB_PORT_STAT_C_RESET) { @@ -468,7 +479,9 @@ static void usb_hub_events(void) } if (hubchange & HUB_CHANGE_OVERCURRENT) { dbg("hub overcurrent change"); + wait_ms(500); //Cool down usb_clear_hub_feature(dev, C_HUB_OVER_CURRENT); + usb_hub_power_on(hub); } } } /* end while (1) */ @@ -491,6 +504,7 @@ static int usb_hub_thread(void *__hub) * This thread doesn't need any user-level access, * so get rid of all our resources */ + exit_files(current); /* daemonize doesn't do exit_files */ daemonize(); /* Setup a nice name */ diff --git a/drivers/usb/ibmcam.c b/drivers/usb/ibmcam.c new file mode 100644 index 000000000..2e9d43fa8 --- /dev/null +++ b/drivers/usb/ibmcam.c @@ -0,0 +1,2346 @@ +/* + * USB IBM C-It Video Camera driver + * + * Supports IBM C-It Video Camera. + * + * This driver is based on earlier work of: + * + * (C) Copyright 1999 Johannes Erdfelt + * (C) Copyright 1999 Randy Dunlap + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "usb.h" +#include "ibmcam.h" + +#define ENABLE_HEXDUMP 0 /* Enable if you need it */ +static int debug = 0; + +/* Completion states of the data parser */ +typedef enum { + scan_Continue, /* Just parse next item */ + scan_NextFrame, /* Frame done, send it to V4L */ + scan_Out, /* Not enough data for frame */ + scan_EndParse /* End parsing */ +} scan_state_t; + +/* Bit flags (options) */ +#define FLAGS_RETRY_VIDIOCSYNC (1 << 0) +#define FLAGS_MONOCHROME (1 << 1) +#define FLAGS_DISPLAY_HINTS (1 << 2) +#define FLAGS_OVERLAY_STATS (1 << 3) +#define FLAGS_FORCE_TESTPATTERN (1 << 4) + +static int flags = 0; /* FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */ + +/* This is the size of V4L frame that we provide */ +static const int imgwidth = V4L_FRAME_WIDTH_USED; +static const int imgheight = V4L_FRAME_HEIGHT; +static const int min_imgwidth = 8; +static const int min_imgheight = 4; + +#define LIGHTING_MIN 0 /* 0=Bright 1=Med 2=Low */ +#define LIGHTING_MAX 2 +static int lighting = (LIGHTING_MIN + LIGHTING_MAX) / 2; /* Medium */ + +#define SHARPNESS_MIN 0 +#define SHARPNESS_MAX 6 +static int sharpness = 4; /* Low noise, good details */ + +#define FRAMERATE_MIN 0 +#define FRAMERATE_MAX 6 +static int framerate = 2; /* Lower, reliable frame rate (8-12 fps) */ + +enum { + VIDEOSIZE_128x96 = 0, + VIDEOSIZE_176x144, + VIDEOSIZE_352x288 +}; + +static int videosize = VIDEOSIZE_352x288; + +/* + * The value of 'scratchbufsize' affects quality of the picture + * in many ways. Shorter buffers may cause loss of data when client + * is too slow. Larger buffers are memory-consuming and take longer + * to work with. This setting can be adjusted, but the default value + * should be OK for most desktop users. + */ +#define DEFAULT_SCRATCH_BUF_SIZE (0x10000) /* 64 KB */ +static const int scratchbufsize = DEFAULT_SCRATCH_BUF_SIZE; + +/* + * Here we define several initialization variables. They may + * be used to automatically set color, hue, brightness and + * contrast to desired values. This is particularly useful in + * case of webcams (which have no controls and no on-screen + * output) and also when a client V4L software is used that + * does not have some of those controls. In any case it's + * good to have startup values as options. + * + * These values are all in [0..255] range. This simplifies + * operation. Note that actual values of V4L variables may + * be scaled up (as much as << 8). User can see that only + * on overlay output, however, or through a V4L client. + */ +static int init_brightness = 128; +static int init_contrast = 192; +static int init_color = 128; +static int init_hue = 128; + +MODULE_PARM(debug, "i"); +MODULE_PARM(flags, "i"); +MODULE_PARM(framerate, "i"); +MODULE_PARM(lighting, "i"); +MODULE_PARM(sharpness, "i"); +MODULE_PARM(videosize, "i"); +MODULE_PARM(init_brightness, "i"); +MODULE_PARM(init_contrast, "i"); +MODULE_PARM(init_color, "i"); +MODULE_PARM(init_hue, "i"); + +MODULE_AUTHOR ("module author"); +MODULE_DESCRIPTION ("IBM/Xirlink C-it USB Camera Driver for Linux (c) 2000"); + +/* Still mysterious i2c commands */ +static const unsigned short unknown_88 = 0x0088; +static const unsigned short unknown_89 = 0x0089; +static const unsigned short bright_3x[3] = { 0x0031, 0x0032, 0x0033 }; +static const unsigned short contrast_14 = 0x0014; +static const unsigned short light_27 = 0x0027; +static const unsigned short sharp_13 = 0x0013; + +/*******************************/ +/* Memory management functions */ +/*******************************/ + +#define MDEBUG(x) do { } while(0) /* Debug memory management */ + +static struct usb_driver ibmcam_driver; + +/* Given PGD from the address space's page table, return the kernel + * virtual mapping of the physical memory mapped at ADR. + */ +static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr) +{ + unsigned long ret = 0UL; + pmd_t *pmd; + pte_t *ptep, pte; + + if (!pgd_none(*pgd)) { + pmd = pmd_offset(pgd, adr); + if (!pmd_none(*pmd)) { + ptep = pte_offset(pmd, adr); + pte = *ptep; + if (pte_present(pte)) + ret = page_address(pte_page(pte)) | (adr & (PAGE_SIZE-1)); + } + } + MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret)); + return ret; +} + +static inline unsigned long uvirt_to_bus(unsigned long adr) +{ + unsigned long kva, ret; + + kva = uvirt_to_kva(pgd_offset(current->mm, adr), adr); + ret = virt_to_bus((void *)kva); + MDEBUG(printk("uv2b(%lx-->%lx)", adr, ret)); + return ret; +} + +static inline unsigned long kvirt_to_bus(unsigned long adr) +{ + unsigned long va, kva, ret; + + va = VMALLOC_VMADDR(adr); + kva = uvirt_to_kva(pgd_offset_k(va), va); + ret = virt_to_bus((void *)kva); + MDEBUG(printk("kv2b(%lx-->%lx)", adr, ret)); + return ret; +} + +/* Here we want the physical address of the memory. + * This is used when initializing the contents of the + * area and marking the pages as reserved. + */ +static inline unsigned long kvirt_to_pa(unsigned long adr) +{ + unsigned long va, kva, ret; + + va = VMALLOC_VMADDR(adr); + kva = uvirt_to_kva(pgd_offset_k(va), va); + ret = __pa(kva); + MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret)); + return ret; +} + +static void *rvmalloc(unsigned long size) +{ + void *mem; + unsigned long adr, page; + + /* Round it off to PAGE_SIZE */ + size += (PAGE_SIZE - 1); + size &= ~(PAGE_SIZE - 1); + + mem = vmalloc(size); + if (!mem) + return NULL; + + memset(mem, 0, size); /* Clear the ram out, no junk to the user */ + adr = (unsigned long) mem; + while (size > 0) { + page = kvirt_to_pa(adr); + mem_map_reserve(MAP_NR(__va(page))); + adr += PAGE_SIZE; + if (size > PAGE_SIZE) + size -= PAGE_SIZE; + else + size = 0; + } + + return mem; +} + +static void rvfree(void *mem, unsigned long size) +{ + unsigned long adr, page; + + if (!mem) + return; + + size += (PAGE_SIZE - 1); + size &= ~(PAGE_SIZE - 1); + + adr=(unsigned long) mem; + while (size > 0) { + page = kvirt_to_pa(adr); + mem_map_unreserve(MAP_NR(__va(page))); + adr += PAGE_SIZE; + if (size > PAGE_SIZE) + size -= PAGE_SIZE; + else + size = 0; + } + vfree(mem); +} + +/* + * usb_ibmcam_overlaychar() + * + * History: + * 1/2/00 Created. + */ +void usb_ibmcam_overlaychar( + struct usb_ibmcam *ibmcam, + struct ibmcam_frame *frame, + int x, int y, int ch) +{ + static const unsigned short digits[16] = { + 0xF6DE, /* 0 */ + 0x2492, /* 1 */ + 0xE7CE, /* 2 */ + 0xE79E, /* 3 */ + 0xB792, /* 4 */ + 0xF39E, /* 5 */ + 0xF3DE, /* 6 */ + 0xF492, /* 7 */ + 0xF7DE, /* 8 */ + 0xF79E, /* 9 */ + 0x77DA, /* a */ + 0xD75C, /* b */ + 0xF24E, /* c */ + 0xD6DC, /* d */ + 0xF34E, /* e */ + 0xF348 /* f */ + }; + unsigned short digit; + int ix, iy; + + if ((ibmcam == NULL) || (frame == NULL)) + return; + + if (ch >= '0' && ch <= '9') + ch -= '0'; + else if (ch >= 'A' && ch <= 'F') + ch = 10 + (ch - 'A'); + else if (ch >= 'a' && ch <= 'f') + ch = 10 + (ch - 'a'); + else + return; + digit = digits[ch]; + + for (iy=0; iy < 5; iy++) { + for (ix=0; ix < 3; ix++) { + if (digit & 0x8000) { + IBMCAM_PUTPIXEL(frame, x+ix, y+iy, 0xFF, 0xFF, 0xFF); + } + digit = digit << 1; + } + } +} + +/* + * usb_ibmcam_overlaystring() + * + * History: + * 1/2/00 Created. + */ +void usb_ibmcam_overlaystring( + struct usb_ibmcam *ibmcam, + struct ibmcam_frame *frame, + int x, int y, const char *str) +{ + while (*str) { + usb_ibmcam_overlaychar(ibmcam, frame, x, y, *str); + str++; + x += 4; /* 3 pixels character + 1 space */ + } +} + +/* + * usb_ibmcam_overlaystats() + * + * Overlays important debugging information. + * + * History: + * 1/2/00 Created. + */ +void usb_ibmcam_overlaystats(struct usb_ibmcam *ibmcam, struct ibmcam_frame *frame) +{ + const int y_diff = 8; + char tmp[16]; + int x = 10; + int y = 10; + + sprintf(tmp, "%8x", ibmcam->frame_num); + usb_ibmcam_overlaystring(ibmcam, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8lx", ibmcam->urb_count); + usb_ibmcam_overlaystring(ibmcam, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8lx", ibmcam->urb_length); + usb_ibmcam_overlaystring(ibmcam, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8lx", ibmcam->data_count); + usb_ibmcam_overlaystring(ibmcam, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8lx", ibmcam->header_count); + usb_ibmcam_overlaystring(ibmcam, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8lx", ibmcam->scratch_ovf_count); + usb_ibmcam_overlaystring(ibmcam, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8lx", ibmcam->iso_skip_count); + usb_ibmcam_overlaystring(ibmcam, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8lx", ibmcam->iso_err_count); + usb_ibmcam_overlaystring(ibmcam, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8x", ibmcam->vpic.colour); + usb_ibmcam_overlaystring(ibmcam, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8x", ibmcam->vpic.hue); + usb_ibmcam_overlaystring(ibmcam, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8x", ibmcam->vpic.brightness >> 8); + usb_ibmcam_overlaystring(ibmcam, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8x", ibmcam->vpic.contrast >> 12); + usb_ibmcam_overlaystring(ibmcam, frame, x, y, tmp); + y += y_diff; + + sprintf(tmp, "%8d", ibmcam->vpic.whiteness >> 8); + usb_ibmcam_overlaystring(ibmcam, frame, x, y, tmp); + y += y_diff; +} + +/* + * usb_ibmcam_testpattern() + * + * Procedure forms a test pattern (yellow grid on blue background). + * + * Parameters: + * fullframe: if TRUE then entire frame is filled, otherwise the procedure + * continues from the current scanline. + * pmode 0: fill the frame with solid blue color (like on VCR or TV) + * 1: Draw a colored grid + * + * History: + * 1/2/00 Created. + */ +void usb_ibmcam_testpattern(struct usb_ibmcam *ibmcam, int fullframe, int pmode) +{ + static const char proc[] = "usb_ibmcam_testpattern"; + struct ibmcam_frame *frame; + unsigned char *f; + int num_cell = 0; + int scan_length = 0; + static int num_pass = 0; + + if (ibmcam == NULL) { + printk(KERN_ERR "%s: ibmcam == NULL\n", proc); + return; + } + if ((ibmcam->curframe < 0) || (ibmcam->curframe >= IBMCAM_NUMFRAMES)) { + printk(KERN_ERR "%s: ibmcam->curframe=%d.\n", proc, ibmcam->curframe); + return; + } + + /* Grab the current frame */ + frame = &ibmcam->frame[ibmcam->curframe]; + + /* Optionally start at the beginning */ + if (fullframe) { + frame->curline = 0; + frame->scanlength = 0; + } + + /* Form every scan line */ + for (; frame->curline < imgheight; frame->curline++) { + int i; + + f = frame->data + (imgwidth * 3 * frame->curline); + for (i=0; i < imgwidth; i++) { + unsigned char cb=0x80; + unsigned char cg = 0; + unsigned char cr = 0; + + if (pmode == 1) { + if (frame->curline % 32 == 0) + cb = 0, cg = cr = 0xFF; + else if (i % 32 == 0) { + if (frame->curline % 32 == 1) + num_cell++; + cb = 0, cg = cr = 0xFF; + } else { + cb = ((num_cell*7) + num_pass) & 0xFF; + cg = ((num_cell*5) + num_pass*2) & 0xFF; + cr = ((num_cell*3) + num_pass*3) & 0xFF; + } + } else { + /* Just the blue screen */ + } + + *f++ = cb; + *f++ = cg; + *f++ = cr; + scan_length += 3; + } + } + + frame->grabstate = FRAME_DONE; + frame->scanlength += scan_length; + ++num_pass; + + /* We do this unconditionally, regardless of FLAGS_OVERLAY_STATS */ + usb_ibmcam_overlaystats(ibmcam, frame); +} + +static unsigned char *ibmcam_find_header(const unsigned char hdr_sig, unsigned char *data, int len) +{ + while (len >= 4) + { + if ((data[0] == 0x00) && (data[1] == 0xFF) && (data[2] == 0x00)) + { +#if 0 + /* This code helps to detect new frame markers */ + printk(KERN_DEBUG "Header sig: 00 FF 00 %02X\n", data[3]); +#endif + if (data[3] == hdr_sig) { + if (debug > 2) + printk(KERN_DEBUG "Header found.\n"); + return data; + } + } + ++data; + --len; + } + return NULL; +} + +/* How much data is left in the scratch buf? */ +#define scratch_left(x) (ibmcam->scratchlen - (int)((char *)x - (char *)ibmcam->scratch)) + +/* Grab the remaining */ +static void usb_ibmcam_align_scratch(struct usb_ibmcam *ibmcam, unsigned char *data) +{ + unsigned long left; + + left = scratch_left(data); + memmove(ibmcam->scratch, data, left); + ibmcam->scratchlen = left; +} + +/* + * usb_ibmcam_find_header() + * + * Locate one of supported header markers in the scratch buffer. + * Once found, remove all preceding bytes AND the marker (4 bytes) + * from the scratch buffer. Whatever follows must be video lines. + * + * History: + * 1/21/00 Created. + */ +static scan_state_t usb_ibmcam_find_header(struct usb_ibmcam *ibmcam) +{ + struct ibmcam_frame *frame; + unsigned char *data, *tmp; + + data = ibmcam->scratch; + frame = &ibmcam->frame[ibmcam->curframe]; + tmp = ibmcam_find_header(frame->hdr_sig, data, scratch_left(data)); + + if (tmp == NULL) { + /* No header - entire scratch buffer is useless! */ + if (debug > 2) + printk(KERN_DEBUG "Skipping frame, no header\n"); + ibmcam->scratchlen = 0; + return scan_EndParse; + } + /* Header found */ + data = tmp+4; + + ibmcam->has_hdr = 1; + ibmcam->header_count++; + frame->scanstate = STATE_LINES; + frame->curline = 0; + + if (flags & FLAGS_FORCE_TESTPATTERN) { + usb_ibmcam_testpattern(ibmcam, 1, 1); + return scan_NextFrame; + } + usb_ibmcam_align_scratch(ibmcam, data); + return scan_Continue; +} + +/* + * usb_ibmcam_parse_lines() + * + * Parse one line (TODO: more than one!) from the scratch buffer, put + * decoded RGB value into the current frame buffer and add the written + * number of bytes (RGB) to the *pcopylen. + * + * History: + * 1/21/00 Created. + */ +static scan_state_t usb_ibmcam_parse_lines(struct usb_ibmcam *ibmcam, long *pcopylen) +{ + struct ibmcam_frame *frame; + unsigned char *data, *f, *chromaLine; + unsigned int len; + const int v4l_linesize = imgwidth * V4L_BYTES_PER_PIXEL; /* V4L line offset */ + int y, u, v, i, frame_done=0, mono_plane, hue_corr, color_corr; + + hue_corr = (ibmcam->vpic.hue - 0x8000) >> 10; /* -32..+31 */ + color_corr = (ibmcam->vpic.colour - 0x8000) >> 10; /* -32..+31 */ + + data = ibmcam->scratch; + frame = &ibmcam->frame[ibmcam->curframe]; + + len = frame->frmwidth * 3; /* 1 line of mono + 1 line of color */ + /*printk(KERN_DEBUG "len=%d. left=%d.\n",len,scratch_left(data));*/ + + mono_plane = ((frame->curline & 1) == 0); + + /* + * Lines are organized this way (or are they?) + * + * I420: + * ~~~~ + * ___________________________________ + * |-----Y-----|---UVUVUV...UVUV-----| \ + * |-----------+---------------------| \ + * |<-- 176 -->|<------ 176*2 ------>| Total 72. pairs of lines + * |... ... ...| / + * |___________|_____________________| / + * - odd line- ------- even line --- + * + * another format: + * ~~~~~~~~~~~~~~ + * ___________________________________ + * |-----Y-----|---UVUVUV...UVUV-----| \ + * |-----------+---------------------| \ + * |<-- 352 -->|<------ 352*2 ------>| Total 144. pairs of lines + * |... ... ...| / + * |___________|_____________________| / + * - odd line- ------- even line --- + */ + + /* Make sure there's enough data for the entire line */ + if (scratch_left(data) < (len+1024)) { + /*printk(KERN_DEBUG "out of data, need %u.\n", len);*/ + return scan_Out; + } + + /* + * Make sure that our writing into output buffer + * will not exceed the buffer. Mind that we may write + * not into current output scanline but in several after + * it as well (if we enlarge image vertically.) + */ + if ((frame->curline + 1) >= V4L_FRAME_HEIGHT) + return scan_NextFrame; + + /* + * Now we are sure that entire line (representing all 'frame->frmwidth' + * pixels from the camera) is available in the scratch buffer. We + * start copying the line left-aligned to the V4L buffer (which + * might be larger - not smaller, hopefully). If the camera + * line is shorter then we should pad the V4L buffer with something + * (black in this case) to complete the line. + */ + f = frame->data + (v4l_linesize * frame->curline); + + /* + * chromaLine points to 1st pixel of the line with chrominance. + * If current line is monochrome then chromaLine points to next + * line after monochrome one. If current line has chrominance + * then chromaLine points to this very line. Such method allows + * to access chrominance data uniformly. + * + * To obtain chrominance data from the 'chromaLine' use this: + * v = chromaLine[0]; // 0-1:[0], 2-3:[4], 4-5:[8]... + * u = chromaLine[2]; // 0-1:[2], 2-3:[6], 4-5:[10]... + * + * Indices must be calculated this way: + * v_index = (i >> 1) << 2; + * u_index = (i >> 1) << 2 + 2; + * + * where 'i' is the column number [0..frame->frmwidth-1] + */ + chromaLine = data; + if (mono_plane) + chromaLine += frame->frmwidth; + + for (i = 0; i < frame->frmwidth; i++, data += (mono_plane ? 1 : 2)) + { + unsigned char rv, gv, bv; /* RGB components */ + + /* + * Search for potential Start-Of-Frame marker. It should + * not be here, of course, but if your formats don't match + * you might exceed the frame. We must match the marker to + * each byte of multi-byte data element if it is multi-byte. + */ +#if 1 + if (scratch_left(data) >= (4+2)) { + unsigned char *dp; + int j; + + for (j=0, dp=data; j < 2; j++, dp++) { + if ((dp[0] == 0x00) && (dp[1] == 0xFF) && + (dp[2] == 0x00) && (dp[3] == frame->hdr_sig)) { + ibmcam->has_hdr = 2; + frame_done++; + break; + } + } + } +#endif + + /* Check for various visual debugging hints (colorized pixels) */ + if ((flags & FLAGS_DISPLAY_HINTS) && (ibmcam->has_hdr)) { + /* + * This is bad and should not happen. This means that + * we somehow overshoot the line and encountered new + * frame! Obviously our camera/V4L frame size is out + * of whack. This cyan dot will help you to figure + * out where exactly the new frame arrived. + */ + if (ibmcam->has_hdr == 1) { + bv = 0; /* Yellow marker */ + gv = 0xFF; + rv = 0xFF; + } else { + bv = 0xFF; /* Cyan marker */ + gv = 0xFF; + rv = 0; + } + ibmcam->has_hdr = 0; + goto make_pixel; + } + + y = mono_plane ? data[0] : data[1]; + + if (flags & FLAGS_MONOCHROME) /* Use monochrome for debugging */ + rv = gv = bv = y; + else { + if (frame->order_uv) { + u = chromaLine[(i >> 1) << 2] + hue_corr; + v = chromaLine[((i >> 1) << 2) + 2] + color_corr; + } else { + v = chromaLine[(i >> 1) << 2] + color_corr; + u = chromaLine[((i >> 1) << 2) + 2] + hue_corr; + } + YUV_TO_RGB_BY_THE_BOOK(y, u, v, rv, gv, bv); + } + + make_pixel: + /* + * The purpose of creating the pixel here, in one, + * dedicated place is that we may need to make the + * pixel wider and taller than it actually is. This + * may be used if camera generates small frames for + * sake of frame rate (or any other reason.) + * + * The output data consists of B, G, R bytes + * (in this order). + */ +#if USES_IBMCAM_PUTPIXEL + IBMCAM_PUTPIXEL(frame, i, frame->curline, rv, gv, bv); +#else + *f++ = bv; + *f++ = gv; + *f++ = rv; +#endif + /* + * Typically we do not decide within a legitimate frame + * that we want to end the frame. However debugging code + * may detect marker of new frame within the data. Then + * this condition activates. The 'data' pointer is already + * pointing at the new marker, so we'd better leave it as is. + */ + if (frame_done) + break; /* End scanning of lines */ + } + /* + * Account for number of bytes that we wrote into output V4L frame. + * We do it here, after we are done with the scanline, because we + * may fill more than one output scanline if we do vertical + * enlargement. + */ + frame->curline++; + *pcopylen += v4l_linesize; + usb_ibmcam_align_scratch(ibmcam, data); + + if (frame_done || (frame->curline >= frame->frmheight)) + return scan_NextFrame; + else + return scan_Continue; +} + +/* + * ibmcam_parse_data() + * + * Generic routine to parse the scratch buffer. It employs either + * usb_ibmcam_find_header() or usb_ibmcam_parse_lines() to do most + * of work. + * + * History: + * 1/21/00 Created. + */ +static void ibmcam_parse_data(struct usb_ibmcam *ibmcam) +{ + struct ibmcam_frame *frame; + unsigned char *data = ibmcam->scratch; + scan_state_t newstate; + long copylen = 0; + + /* Grab the current frame and the previous frame */ + frame = &ibmcam->frame[ibmcam->curframe]; + + /* printk(KERN_DEBUG "parsing %u.\n", ibmcam->scratchlen); */ + + while (1) { + + newstate = scan_Out; + if (scratch_left(data)) { + if (frame->scanstate == STATE_SCANNING) + newstate = usb_ibmcam_find_header(ibmcam); + else if (frame->scanstate == STATE_LINES) + newstate = usb_ibmcam_parse_lines(ibmcam, ©len); + } + if (newstate == scan_Continue) + continue; + else if ((newstate == scan_NextFrame) || (newstate == scan_Out)) + break; + else + return; /* scan_EndParse */ + } + + if (newstate == scan_NextFrame) { + frame->grabstate = FRAME_DONE; + ibmcam->curframe = -1; + ibmcam->frame_num++; + + /* Optionally display statistics on the screen */ + if (flags & FLAGS_OVERLAY_STATS) + usb_ibmcam_overlaystats(ibmcam, frame); + + /* This will cause the process to request another frame. */ + if (waitqueue_active(&frame->wq)) + wake_up_interruptible(&frame->wq); + } + + /* Update the frame's uncompressed length. */ + frame->scanlength += copylen; +} + +#if ENABLE_HEXDUMP +static void ibmcam_hexdump(const unsigned char *data, int len) +{ + char tmp[80]; + int i, k; + + for (i=k=0; len > 0; i++, len--) { + if (i > 0 && (i%16 == 0)) { + printk("%s\n", tmp); + k=0; + } + k += sprintf(&tmp[k], "%02x ", data[i]); + } + if (k > 0) + printk("%s\n", tmp); +} +#endif + +/* + * Make all of the blocks of data contiguous + */ +static int ibmcam_compress_isochronous(struct usb_ibmcam *ibmcam, urb_t *urb) +{ + unsigned char *cdata, *data, *data0; + int i, totlen = 0; + + data = data0 = ibmcam->scratch + ibmcam->scratchlen; + for (i = 0; i < urb->number_of_packets; i++) { + int n = urb->iso_frame_desc[i].actual_length; + int st = urb->iso_frame_desc[i].status; + + cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset; + + /* Detect and ignore errored packets */ + if (st < 0) { + if (debug >= 1) { + printk(KERN_ERR "ibmcam data error: [%d] len=%d, status=%X\n", + i, n, st); + } + ibmcam->iso_err_count++; + continue; + } + + /* Detect and ignore empty packets */ + if (n <= 0) { + ibmcam->iso_skip_count++; + continue; + } + + /* + * If camera continues to feed us with data but there is no + * consumption (if, for example, V4L client fell asleep) we + * may overflow the buffer. We have to move old data over to + * free room for new data. This is bad for old data. If we + * just drop new data then it's bad for new data... choose + * your favorite evil here. + */ + if ((ibmcam->scratchlen + n) > scratchbufsize) { +#if 0 + ibmcam->scratch_ovf_count++; + if (debug >= 3) + printk(KERN_ERR "ibmcam: scratch buf overflow! " + "scr_len: %d, n: %d\n", ibmcam->scratchlen, n ); + return totlen; +#else + int mv; + + ibmcam->scratch_ovf_count++; + if (debug >= 3) { + printk(KERN_ERR "ibmcam: scratch buf overflow! " + "scr_len: %d, n: %d\n", ibmcam->scratchlen, n ); + } + mv = (ibmcam->scratchlen + n) - scratchbufsize; + if (ibmcam->scratchlen >= mv) { + int newslen = ibmcam->scratchlen - mv; + memmove(ibmcam->scratch, ibmcam->scratch + mv, newslen); + ibmcam->scratchlen = newslen; + data = data0 = ibmcam->scratch + ibmcam->scratchlen; + } else { + printk(KERN_ERR "ibmcam: scratch buf too small\n"); + return totlen; + } +#endif + } + + /* Now we know that there is enough room in scratch buffer */ + memmove(data, cdata, n); + data += n; + totlen += n; + ibmcam->scratchlen += n; + } +#if 0 + if (totlen > 0) { + static int foo=0; + if (foo < 1) { + printk(KERN_DEBUG "+%d.\n", totlen); + ibmcam_hexdump(data0, (totlen > 64) ? 64:totlen); + ++foo; + } + } +#endif + return totlen; +} + +static void ibmcam_isoc_irq(struct urb *urb) +{ + int len; + struct usb_ibmcam *ibmcam = urb->context; + struct ibmcam_sbuf *sbuf; + int i; + + /* We don't want to do anything if we are about to be removed! */ + if (ibmcam->remove_pending) + return; + +#if 0 + if (urb->actual_length > 0) { + printk(KERN_DEBUG "ibmcam_isoc_irq: %p status %d, " + " errcount = %d, length = %d\n", urb, urb->status, + urb->error_count, urb->actual_length); + } else { + static int c = 0; + if (c++ % 100 == 0) + printk(KERN_DEBUG "ibmcam_isoc_irq: no data\n"); + } +#endif + + if (!ibmcam->streaming) { + if (debug >= 1) + printk(KERN_DEBUG "ibmcam: oops, not streaming, but interrupt\n"); + return; + } + + sbuf = &ibmcam->sbuf[ibmcam->cursbuf]; + + /* Copy the data received into our scratch buffer */ + len = ibmcam_compress_isochronous(ibmcam, urb); + + ibmcam->urb_count++; + ibmcam->urb_length = len; + ibmcam->data_count += len; + +#if 0 /* This code prints few initial bytes of ISO data: used to decode markers */ + if (ibmcam->urb_count % 64 == 1) { + if (ibmcam->urb_count == 1) { + ibmcam_hexdump(ibmcam->scratch, + (ibmcam->scratchlen > 32) ? 32 : ibmcam->scratchlen); + } + } +#endif + + /* If we collected enough data let's parse! */ + if (ibmcam->scratchlen) { + /* If we don't have a frame we're current working on, complain */ + if (ibmcam->curframe >= 0) + ibmcam_parse_data(ibmcam); + else { + if (debug >= 1) + printk(KERN_DEBUG "ibmcam: received data, but no frame available\n"); + } + } + + 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; + } + + /* Move to the next sbuf */ + ibmcam->cursbuf = (ibmcam->cursbuf + 1) % IBMCAM_NUMSBUF; + + return; +} + +static int usb_ibmcam_veio( + struct usb_device *dev, + unsigned char req, + unsigned short value, + unsigned short index) +{ + static const char proc[] = "usb_ibmcam_veio"; + unsigned char cp[8] = { 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef }; + const unsigned short len = sizeof(cp); + int i; + + if (req == 1) { + i = usb_control_msg( + dev, + usb_rcvctrlpipe(dev, 0), + req, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, + value, + index, + cp, + len, + HZ); +#if 0 + printk(KERN_DEBUG "USB => %02x%02x%02x%02x%02x%02x%02x%02x " + "(req=$%02x val=$%04x ind=$%04x len=%d.)\n", + cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7], + req, value, index, len); +#endif + } else { + i = usb_control_msg( + dev, + usb_sndctrlpipe(dev, 0), + req, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, + value, + index, + NULL, + 0, + HZ); + } + if (i < 0) + printk(KERN_ERR "%s: ERROR=%d.\n", proc, i); + return i; +} + +/* + * usb_ibmcam_calculate_fps() + * + * This procedure roughly calculates the real frame rate based + * on FPS code (framerate=NNN option). Actual FPS differs + * slightly depending on lighting conditions, so that actual frame + * rate is determined by the camera. Since I don't know how to ask + * the camera what FPS is now I have to use the FPS code instead. + * + * The FPS code is in range [0..6], 0 is slowest, 6 is fastest. + * Corresponding real FPS should be in range [3..30] frames per second. + * The conversion formula is obvious: + * + * real_fps = 3 + (fps_code * 4.5) + * + * History: + * 1/18/00 Created. + */ +static int usb_ibmcam_calculate_fps(void) +{ + return 3 + framerate*4 + framerate/2; +} + +/* + * usb_ibmcam_send_FF_04_02() + * + * This procedure sends magic 3-command prefix to the camera. + * The purpose of this prefix is not known. + * + * History: + * 1/2/00 Created. + */ +static void usb_ibmcam_send_FF_04_02(struct usb_device *dev) +{ + usb_ibmcam_veio(dev, 0, 0x00FF, 0x0127); + usb_ibmcam_veio(dev, 0, 0x0004, 0x0124); + usb_ibmcam_veio(dev, 0, 0x0002, 0x0124); +} + +static void usb_ibmcam_send_00_04_06(struct usb_device *dev) +{ + usb_ibmcam_veio(dev, 0, 0x0000, 0x0127); + usb_ibmcam_veio(dev, 0, 0x0004, 0x0124); + usb_ibmcam_veio(dev, 0, 0x0006, 0x0124); +} + +static void usb_ibmcam_send_x_00(struct usb_device *dev, unsigned short x) +{ + usb_ibmcam_veio(dev, 0, x, 0x0127); + usb_ibmcam_veio(dev, 0, 0x0000, 0x0124); +} + +static void usb_ibmcam_send_x_00_05(struct usb_device *dev, unsigned short x) +{ + usb_ibmcam_send_x_00(dev, x); + usb_ibmcam_veio(dev, 0, 0x0005, 0x0124); +} + +static void usb_ibmcam_send_x_00_05_02(struct usb_device *dev, unsigned short x) +{ + usb_ibmcam_veio(dev, 0, x, 0x0127); + usb_ibmcam_veio(dev, 0, 0x0000, 0x0124); + usb_ibmcam_veio(dev, 0, 0x0005, 0x0124); + usb_ibmcam_veio(dev, 0, 0x0002, 0x0124); +} + +static void usb_ibmcam_send_x_01_00_05(struct usb_device *dev, unsigned short x) +{ + usb_ibmcam_veio(dev, 0, x, 0x0127); + usb_ibmcam_veio(dev, 0, 0x0001, 0x0124); + usb_ibmcam_veio(dev, 0, 0x0000, 0x0124); + usb_ibmcam_veio(dev, 0, 0x0005, 0x0124); +} + +static void usb_ibmcam_send_x_00_05_02_01(struct usb_device *dev, unsigned short x) +{ + usb_ibmcam_veio(dev, 0, x, 0x0127); + usb_ibmcam_veio(dev, 0, 0x0000, 0x0124); + usb_ibmcam_veio(dev, 0, 0x0005, 0x0124); + usb_ibmcam_veio(dev, 0, 0x0002, 0x0124); + usb_ibmcam_veio(dev, 0, 0x0001, 0x0124); +} + +static void usb_ibmcam_send_x_00_05_02_08_01(struct usb_device *dev, unsigned short x) +{ + usb_ibmcam_veio(dev, 0, x, 0x0127); + usb_ibmcam_veio(dev, 0, 0x0000, 0x0124); + usb_ibmcam_veio(dev, 0, 0x0005, 0x0124); + usb_ibmcam_veio(dev, 0, 0x0002, 0x0124); + usb_ibmcam_veio(dev, 0, 0x0008, 0x0124); + usb_ibmcam_veio(dev, 0, 0x0001, 0x0124); +} + +static void usb_ibmcam_Packet_Format1(struct usb_device *dev, unsigned char fkey, unsigned char val) +{ + usb_ibmcam_send_x_01_00_05 (dev, unknown_88); + usb_ibmcam_send_x_00_05 (dev, fkey); + usb_ibmcam_send_x_00_05_02_08_01(dev, val); + usb_ibmcam_send_x_00_05 (dev, unknown_88); + usb_ibmcam_send_x_00_05_02_01 (dev, fkey); + usb_ibmcam_send_x_00_05 (dev, unknown_89); + usb_ibmcam_send_x_00 (dev, fkey); + usb_ibmcam_send_00_04_06 (dev); + usb_ibmcam_veio (dev, 1, 0x0000, 0x0126); + usb_ibmcam_send_FF_04_02 (dev); +} + +static void usb_ibmcam_PacketFormat2(struct usb_device *dev, unsigned char fkey, unsigned char val) +{ + usb_ibmcam_send_x_01_00_05 (dev, unknown_88); + usb_ibmcam_send_x_00_05 (dev, fkey); + usb_ibmcam_send_x_00_05_02 (dev, val); +} + +/* + * usb_ibmcam_adjust_contrast() + * + * The contrast value changes from 0 (high contrast) to 15 (low contrast). + * This is in reverse to usual order of things (such as TV controls), so + * we reverse it again here. + * + * TODO: we probably don't need to send the setup 5 times... + * + * History: + * 1/2/00 Created. + */ +static void usb_ibmcam_adjust_contrast(struct usb_ibmcam *ibmcam) +{ + struct usb_device *dev = ibmcam->dev; + unsigned char new_contrast = ibmcam->vpic.contrast >> 12; + const int ntries = 5; + + if (new_contrast >= 16) + new_contrast = 15; + new_contrast = 15 - new_contrast; + if (new_contrast != ibmcam->vpic_old.contrast) { + int i; + ibmcam->vpic_old.contrast = new_contrast; + for (i=0; i < ntries; i++) { + usb_ibmcam_Packet_Format1(dev, contrast_14, new_contrast); + usb_ibmcam_send_FF_04_02(dev); + } + /*usb_ibmcam_veio(dev, 0, 0x00FF, 0x0127);*/ + } +} + +/* + * usb_ibmcam_change_lighting_conditions() + * + * We have 3 levels of lighting conditions: 0=Bright, 1=Medium, 2=Low. + * Low lighting forces slower FPS. Lighting is set as a module parameter. + * + * History: + * 1/5/00 Created. + */ +static void usb_ibmcam_change_lighting_conditions(struct usb_ibmcam *ibmcam) +{ + static const char proc[] = "usb_ibmcam_change_lighting_conditions"; + struct usb_device *dev = ibmcam->dev; + const int ntries = 5; + int i; + + RESTRICT_TO_RANGE(lighting, LIGHTING_MIN, LIGHTING_MAX); + if (debug > 0) + printk(KERN_INFO "%s: Set lighting to %hu.\n", proc, lighting); + + for (i=0; i < ntries; i++) + usb_ibmcam_Packet_Format1(dev, light_27, (unsigned short) lighting); +} + +static void usb_ibmcam_set_sharpness(struct usb_ibmcam *ibmcam) +{ + static const char proc[] = "usb_ibmcam_set_sharpness"; + struct usb_device *dev = ibmcam->dev; + static const unsigned short sa[] = { 0x11, 0x13, 0x16, 0x18, 0x1a, 0x8, 0x0a }; + unsigned short i, sv; + + RESTRICT_TO_RANGE(sharpness, SHARPNESS_MIN, SHARPNESS_MAX); + if (debug > 0) + printk(KERN_INFO "%s: Set sharpness to %hu.\n", proc, sharpness); + + sv = sa[sharpness - SHARPNESS_MIN]; + for (i=0; i < 2; i++) { + usb_ibmcam_send_x_01_00_05 (dev, unknown_88); + usb_ibmcam_send_x_00_05 (dev, sharp_13); + usb_ibmcam_send_x_00_05_02 (dev, sv); + } +} + +static void usb_ibmcam_set_brightness(struct usb_ibmcam *ibmcam) +{ + static const char proc[] = "usb_ibmcam_set_brightness"; + struct usb_device *dev = ibmcam->dev; + static const unsigned short n = 1; + unsigned short i, j, bv[3]; + + bv[0] = bv[1] = bv[2] = ibmcam->vpic.brightness >> 10; + if (bv[0] == (ibmcam->vpic_old.brightness >> 10)) + return; + ibmcam->vpic_old.brightness = ibmcam->vpic.brightness; + + if (debug > 0) + printk(KERN_INFO "%s: Set brightness to (%hu,%hu,%hu)\n", + proc, bv[0], bv[1], bv[2]); + + for (j=0; j < 3; j++) + for (i=0; i < n; i++) + usb_ibmcam_Packet_Format1(dev, bright_3x[j], bv[j]); +} + +static void usb_ibmcam_adjust_picture(struct usb_ibmcam *ibmcam) +{ + usb_ibmcam_adjust_contrast(ibmcam); + usb_ibmcam_set_brightness(ibmcam); +} + +static int usb_ibmcam_setup(struct usb_ibmcam *ibmcam) +{ + struct usb_device *dev = ibmcam->dev; + const int ntries = 5; + int i; + + usb_ibmcam_veio(dev, 1, 0, 0x128); + usb_ibmcam_veio(dev, 1, 0x00, 0x0100); + usb_ibmcam_veio(dev, 0, 0x01, 0x0100); /* LED On */ + usb_ibmcam_veio(dev, 1, 0x00, 0x0100); + usb_ibmcam_veio(dev, 0, 0x81, 0x0100); /* LED Off */ + usb_ibmcam_veio(dev, 1, 0x00, 0x0100); + usb_ibmcam_veio(dev, 0, 0x01, 0x0100); /* LED On */ + usb_ibmcam_veio(dev, 0, 0x01, 0x0108); + + usb_ibmcam_veio(dev, 0, 0x03, 0x0112); + usb_ibmcam_veio(dev, 1, 0x00, 0x0115); + usb_ibmcam_veio(dev, 0, 0x06, 0x0115); + usb_ibmcam_veio(dev, 1, 0x00, 0x0116); + usb_ibmcam_veio(dev, 0, 0x44, 0x0116); + usb_ibmcam_veio(dev, 1, 0x00, 0x0116); + usb_ibmcam_veio(dev, 0, 0x40, 0x0116); + usb_ibmcam_veio(dev, 1, 0x00, 0x0115); + usb_ibmcam_veio(dev, 0, 0x0e, 0x0115); + usb_ibmcam_veio(dev, 0, 0x19, 0x012c); + + usb_ibmcam_Packet_Format1(dev, 0x00, 0x1e); + usb_ibmcam_Packet_Format1(dev, 0x39, 0x0d); + usb_ibmcam_Packet_Format1(dev, 0x39, 0x09); + usb_ibmcam_Packet_Format1(dev, 0x3b, 0x00); + usb_ibmcam_Packet_Format1(dev, 0x28, 0x22); + usb_ibmcam_Packet_Format1(dev, light_27, 0); + usb_ibmcam_Packet_Format1(dev, 0x2b, 0x1f); + usb_ibmcam_Packet_Format1(dev, 0x39, 0x08); + + for (i=0; i < ntries; i++) + usb_ibmcam_Packet_Format1(dev, 0x2c, 0x00); + + for (i=0; i < ntries; i++) + usb_ibmcam_Packet_Format1(dev, 0x30, 0x14); + + usb_ibmcam_PacketFormat2(dev, 0x39, 0x02); + usb_ibmcam_PacketFormat2(dev, 0x01, 0xe1); + usb_ibmcam_PacketFormat2(dev, 0x02, 0xcd); + usb_ibmcam_PacketFormat2(dev, 0x03, 0xcd); + usb_ibmcam_PacketFormat2(dev, 0x04, 0xfa); + usb_ibmcam_PacketFormat2(dev, 0x3f, 0xff); + usb_ibmcam_PacketFormat2(dev, 0x39, 0x00); + + usb_ibmcam_PacketFormat2(dev, 0x39, 0x02); + usb_ibmcam_PacketFormat2(dev, 0x0a, 0x37); + usb_ibmcam_PacketFormat2(dev, 0x0b, 0xb8); + usb_ibmcam_PacketFormat2(dev, 0x0c, 0xf3); + usb_ibmcam_PacketFormat2(dev, 0x0d, 0xe3); + usb_ibmcam_PacketFormat2(dev, 0x0e, 0x0d); + usb_ibmcam_PacketFormat2(dev, 0x0f, 0xf2); + usb_ibmcam_PacketFormat2(dev, 0x10, 0xd5); + usb_ibmcam_PacketFormat2(dev, 0x11, 0xba); + usb_ibmcam_PacketFormat2(dev, 0x12, 0x53); + usb_ibmcam_PacketFormat2(dev, 0x3f, 0xff); + usb_ibmcam_PacketFormat2(dev, 0x39, 0x00); + + usb_ibmcam_PacketFormat2(dev, 0x39, 0x02); + usb_ibmcam_PacketFormat2(dev, 0x16, 0x00); + usb_ibmcam_PacketFormat2(dev, 0x17, 0x28); + usb_ibmcam_PacketFormat2(dev, 0x18, 0x7d); + usb_ibmcam_PacketFormat2(dev, 0x19, 0xbe); + usb_ibmcam_PacketFormat2(dev, 0x3f, 0xff); + usb_ibmcam_PacketFormat2(dev, 0x39, 0x00); + + for (i=0; i < ntries; i++) + usb_ibmcam_Packet_Format1(dev, 0x00, 0x18); + for (i=0; i < ntries; i++) + usb_ibmcam_Packet_Format1(dev, 0x13, 0x18); + for (i=0; i < ntries; i++) + usb_ibmcam_Packet_Format1(dev, 0x14, 0x06); + + /* This is default brightness */ + for (i=0; i < ntries; i++) + usb_ibmcam_Packet_Format1(dev, 0x31, 0x37); + for (i=0; i < ntries; i++) + usb_ibmcam_Packet_Format1(dev, 0x32, 0x46); + for (i=0; i < ntries; i++) + usb_ibmcam_Packet_Format1(dev, 0x33, 0x55); + + usb_ibmcam_Packet_Format1(dev, 0x2e, 0x04); + for (i=0; i < ntries; i++) + usb_ibmcam_Packet_Format1(dev, 0x2d, 0x04); + for (i=0; i < ntries; i++) + usb_ibmcam_Packet_Format1(dev, 0x29, 0x80); + usb_ibmcam_Packet_Format1(dev, 0x2c, 0x01); + usb_ibmcam_Packet_Format1(dev, 0x30, 0x17); + usb_ibmcam_Packet_Format1(dev, 0x39, 0x08); + for (i=0; i < ntries; i++) + usb_ibmcam_Packet_Format1(dev, 0x34, 0x00); + + usb_ibmcam_veio(dev, 0, 0x00, 0x0101); + usb_ibmcam_veio(dev, 0, 0x00, 0x010a); + + switch (videosize) { + case VIDEOSIZE_128x96: + usb_ibmcam_veio(dev, 0, 0x80, 0x0103); + usb_ibmcam_veio(dev, 0, 0x60, 0x0105); + usb_ibmcam_veio(dev, 0, 0x0c, 0x010b); + usb_ibmcam_veio(dev, 0, 0x04, 0x011b); /* Same everywhere */ + usb_ibmcam_veio(dev, 0, 0x0b, 0x011d); + usb_ibmcam_veio(dev, 0, 0x00, 0x011e); /* Same everywhere */ + usb_ibmcam_veio(dev, 0, 0x00, 0x0129); + break; + case VIDEOSIZE_176x144: + usb_ibmcam_veio(dev, 0, 0xb0, 0x0103); + usb_ibmcam_veio(dev, 0, 0x8f, 0x0105); + usb_ibmcam_veio(dev, 0, 0x06, 0x010b); + usb_ibmcam_veio(dev, 0, 0x04, 0x011b); /* Same everywhere */ + usb_ibmcam_veio(dev, 0, 0x0d, 0x011d); + usb_ibmcam_veio(dev, 0, 0x00, 0x011e); /* Same everywhere */ + usb_ibmcam_veio(dev, 0, 0x03, 0x0129); + break; + case VIDEOSIZE_352x288: + usb_ibmcam_veio(dev, 0, 0xb0, 0x0103); + usb_ibmcam_veio(dev, 0, 0x90, 0x0105); + usb_ibmcam_veio(dev, 0, 0x02, 0x010b); + usb_ibmcam_veio(dev, 0, 0x04, 0x011b); /* Same everywhere */ + usb_ibmcam_veio(dev, 0, 0x05, 0x011d); + usb_ibmcam_veio(dev, 0, 0x00, 0x011e); /* Same everywhere */ + usb_ibmcam_veio(dev, 0, 0x00, 0x0129); + break; + } + + usb_ibmcam_veio(dev, 0, 0xff, 0x012b); + + /* This is another brightness - don't know why */ + for (i=0; i < ntries; i++) + usb_ibmcam_Packet_Format1(dev, 0x31, 0xc3); + for (i=0; i < ntries; i++) + usb_ibmcam_Packet_Format1(dev, 0x32, 0xd2); + for (i=0; i < ntries; i++) + usb_ibmcam_Packet_Format1(dev, 0x33, 0xe1); + + /* Default contrast */ + for (i=0; i < ntries; i++) + usb_ibmcam_Packet_Format1(dev, contrast_14, 0x0a); + + /* Default sharpness */ + for (i=0; i < 2; i++) + usb_ibmcam_PacketFormat2(dev, sharp_13, 0x1a); /* Level 4 FIXME */ + + /* Default lighting conditions */ + usb_ibmcam_Packet_Format1(dev, light_27, lighting); /* 0=Bright 2=Low */ + + /* Assorted init */ + + switch (videosize) { + case VIDEOSIZE_128x96: + usb_ibmcam_Packet_Format1(dev, 0x2b, 0x1e); + usb_ibmcam_veio(dev, 0, 0xc9, 0x0119); /* Same everywhere */ + usb_ibmcam_veio(dev, 0, 0x80, 0x0109); /* Same everywhere */ + usb_ibmcam_veio(dev, 0, 0x36, 0x0102); + usb_ibmcam_veio(dev, 0, 0x1a, 0x0104); + usb_ibmcam_veio(dev, 0, 0x04, 0x011a); /* Same everywhere */ + usb_ibmcam_veio(dev, 0, 0x2b, 0x011c); + usb_ibmcam_veio(dev, 0, 0x23, 0x012a); /* Same everywhere */ +#if 0 + usb_ibmcam_veio(dev, 0, 0x00, 0x0106); + usb_ibmcam_veio(dev, 0, 0x38, 0x0107); +#else + usb_ibmcam_veio(dev, 0, 0x02, 0x0106); + usb_ibmcam_veio(dev, 0, 0x2a, 0x0107); +#endif + break; + case VIDEOSIZE_176x144: + usb_ibmcam_Packet_Format1(dev, 0x2b, 0x1e); + usb_ibmcam_veio(dev, 0, 0xc9, 0x0119); /* Same everywhere */ + usb_ibmcam_veio(dev, 0, 0x80, 0x0109); /* Same everywhere */ + usb_ibmcam_veio(dev, 0, 0x04, 0x0102); + usb_ibmcam_veio(dev, 0, 0x02, 0x0104); + usb_ibmcam_veio(dev, 0, 0x04, 0x011a); /* Same everywhere */ + usb_ibmcam_veio(dev, 0, 0x2b, 0x011c); + usb_ibmcam_veio(dev, 0, 0x23, 0x012a); /* Same everywhere */ + usb_ibmcam_veio(dev, 0, 0x01, 0x0106); + usb_ibmcam_veio(dev, 0, 0xca, 0x0107); + break; + case VIDEOSIZE_352x288: + usb_ibmcam_Packet_Format1(dev, 0x2b, 0x1f); + usb_ibmcam_veio(dev, 0, 0xc9, 0x0119); /* Same everywhere */ + usb_ibmcam_veio(dev, 0, 0x80, 0x0109); /* Same everywhere */ + usb_ibmcam_veio(dev, 0, 0x08, 0x0102); + usb_ibmcam_veio(dev, 0, 0x01, 0x0104); + usb_ibmcam_veio(dev, 0, 0x04, 0x011a); /* Same everywhere */ + usb_ibmcam_veio(dev, 0, 0x2f, 0x011c); + usb_ibmcam_veio(dev, 0, 0x23, 0x012a); /* Same everywhere */ + usb_ibmcam_veio(dev, 0, 0x03, 0x0106); + usb_ibmcam_veio(dev, 0, 0xf6, 0x0107); + break; + } + return 0; /* TODO: return actual completion status! */ +} + +/* + * usb_ibmcam_setup_after_video_if() + * + * This code adds finishing touches to the video data interface. + * Here we configure the frame rate and turn on the LED. + */ +static void usb_ibmcam_setup_after_video_if(struct usb_device *dev) +{ + unsigned short internal_frame_rate; + + RESTRICT_TO_RANGE(framerate, FRAMERATE_MIN, FRAMERATE_MAX); + internal_frame_rate = FRAMERATE_MAX - framerate; /* 0=Fast 6=Slow */ + usb_ibmcam_veio(dev, 0, 0x01, 0x0100); /* LED On */ + usb_ibmcam_veio(dev, 0, internal_frame_rate, 0x0111); + usb_ibmcam_veio(dev, 0, 0x01, 0x0114); + usb_ibmcam_veio(dev, 0, 0xc0, 0x010c); +} + +/* + * usb_ibmcam_setup_video_stop() + * + * This code tells camera to stop streaming. The interface remains + * configured and bandwidth - claimed. + */ +static void usb_ibmcam_setup_video_stop(struct usb_device *dev) +{ + usb_ibmcam_veio(dev, 0, 0x00, 0x010c); + usb_ibmcam_veio(dev, 0, 0x00, 0x010c); + usb_ibmcam_veio(dev, 0, 0x01, 0x0114); + usb_ibmcam_veio(dev, 0, 0xc0, 0x010c); + usb_ibmcam_veio(dev, 0, 0x00, 0x010c); + usb_ibmcam_send_FF_04_02(dev); + usb_ibmcam_veio(dev, 1, 0x00, 0x0100); + usb_ibmcam_veio(dev, 0, 0x81, 0x0100); /* LED Off */ +} + +/* + * usb_ibmcam_reinit_iso() + * + * This procedure sends couple of commands to the camera and then + * resets the video pipe. This sequence was observed to reinit the + * camera or, at least, to initiate ISO data stream. + * + * History: + * 1/2/00 Created. + */ +static void usb_ibmcam_reinit_iso(struct usb_ibmcam *ibmcam, int do_stop) +{ + if (do_stop) + usb_ibmcam_setup_video_stop(ibmcam->dev); + + usb_ibmcam_veio(ibmcam->dev, 0, 0x0001, 0x0114); + usb_ibmcam_veio(ibmcam->dev, 0, 0x00c0, 0x010c); + usb_clear_halt(ibmcam->dev, ibmcam->video_endp); + usb_ibmcam_setup_after_video_if(ibmcam->dev); +} + +static int ibmcam_init_isoc(struct usb_ibmcam *ibmcam) +{ + struct usb_device *dev = ibmcam->dev; + urb_t *urb; + int fx, err; + + ibmcam->compress = 0; + ibmcam->curframe = -1; + ibmcam->cursbuf = 0; + ibmcam->scratchlen = 0; + + /* Alternate interface 1 is is the biggest frame size */ + if (usb_set_interface(ibmcam->dev, 2, 1) < 0) { + printk(KERN_ERR "usb_set_interface error\n"); + return -EBUSY; + } + usb_ibmcam_change_lighting_conditions(ibmcam); + usb_ibmcam_set_sharpness(ibmcam); + usb_ibmcam_reinit_iso(ibmcam, 0); + + /* We double buffer the Iso lists */ + urb = usb_alloc_urb(FRAMES_PER_DESC); + + if (!urb) { + printk(KERN_ERR "ibmcam_init_isoc: usb_init_isoc ret %d\n", + 0); + return -ENOMEM; + } + ibmcam->sbuf[0].urb = urb; + urb->dev = dev; + urb->context = ibmcam; + urb->pipe = usb_rcvisocpipe(dev, ibmcam->video_endp); + urb->transfer_flags = USB_ISO_ASAP; + urb->transfer_buffer = ibmcam->sbuf[0].data; + urb->complete = ibmcam_isoc_irq; + urb->number_of_packets = FRAMES_PER_DESC; + urb->transfer_buffer_length = ibmcam->iso_packet_len * FRAMES_PER_DESC; + for (fx = 0; fx < FRAMES_PER_DESC; fx++) { + urb->iso_frame_desc[fx].offset = ibmcam->iso_packet_len * fx; + urb->iso_frame_desc[fx].length = ibmcam->iso_packet_len; + } + urb = usb_alloc_urb(FRAMES_PER_DESC); + if (!urb) { + printk(KERN_ERR "ibmcam_init_isoc: usb_init_isoc ret %d\n", + 0); + return -ENOMEM; + } + ibmcam->sbuf[1].urb = urb; + urb->dev = dev; + urb->context = ibmcam; + urb->pipe = usb_rcvisocpipe(dev, ibmcam->video_endp); + urb->transfer_flags = USB_ISO_ASAP; + urb->transfer_buffer = ibmcam->sbuf[1].data; + urb->complete = ibmcam_isoc_irq; + urb->number_of_packets = FRAMES_PER_DESC; + urb->transfer_buffer_length = ibmcam->iso_packet_len * FRAMES_PER_DESC; + for (fx = 0; fx < FRAMES_PER_DESC; fx++) { + urb->iso_frame_desc[fx].offset = ibmcam->iso_packet_len * fx; + urb->iso_frame_desc[fx].length = ibmcam->iso_packet_len; + } + + ibmcam->sbuf[1].urb->next = ibmcam->sbuf[0].urb; + ibmcam->sbuf[0].urb->next = ibmcam->sbuf[1].urb; + + err = usb_submit_urb(ibmcam->sbuf[0].urb); + if (err) + printk(KERN_ERR "ibmcam_init_isoc: usb_run_isoc(0) ret %d\n", + err); + err = usb_submit_urb(ibmcam->sbuf[1].urb); + if (err) + printk(KERN_ERR "ibmcam_init_isoc: usb_run_isoc(1) ret %d\n", + err); + + ibmcam->streaming = 1; + // printk(KERN_DEBUG "streaming=1 ibmcam->video_endp=$%02x\n", ibmcam->video_endp); + return 0; +} + +/* + * ibmcam_stop_isoc() + * + * This procedure stops streaming and deallocates URBs. Then it + * activates zero-bandwidth alt. setting of the video interface. + * + * History: + * 1/22/00 Corrected order of actions to work after surprise removal. + */ +static void ibmcam_stop_isoc(struct usb_ibmcam *ibmcam) +{ + if (!ibmcam->streaming) + return; + + /* Unschedule all of the iso td's */ + usb_unlink_urb(ibmcam->sbuf[1].urb); + usb_unlink_urb(ibmcam->sbuf[0].urb); + + /* printk(KERN_DEBUG "streaming=0\n"); */ + ibmcam->streaming = 0; + + /* Delete them all */ + usb_free_urb(ibmcam->sbuf[1].urb); + usb_free_urb(ibmcam->sbuf[0].urb); + + usb_ibmcam_setup_video_stop(ibmcam->dev); + + /* Set packet size to 0 */ + if (usb_set_interface(ibmcam->dev, 2, 0) < 0) + printk(KERN_ERR "usb_set_interface error\n"); +} + +static int ibmcam_new_frame(struct usb_ibmcam *ibmcam, int framenum) +{ + struct ibmcam_frame *frame; + int n, width, height; + + /* If we're not grabbing a frame right now and the other frame is */ + /* ready to be grabbed into, then use it instead */ + if (ibmcam->curframe != -1) + return 0; + + n = (framenum - 1 + IBMCAM_NUMFRAMES) % IBMCAM_NUMFRAMES; + if (ibmcam->frame[n].grabstate == FRAME_READY) + framenum = n; + + frame = &ibmcam->frame[framenum]; + + frame->grabstate = FRAME_GRABBING; + frame->scanstate = STATE_SCANNING; + frame->scanlength = 0; /* Accumulated in ibmcam_parse_data() */ + ibmcam->curframe = framenum; +#if 0 + /* This provides a "clean" frame but slows things down */ + memset(frame->data, 0, MAX_FRAME_SIZE); +#endif + switch (videosize) { + case VIDEOSIZE_128x96: + frame->frmwidth = 128; + frame->frmheight = 96; + frame->order_uv = 1; /* U Y V Y ... */ + frame->hdr_sig = 0x06; /* 00 FF 00 06 */ + break; + case VIDEOSIZE_176x144: + frame->frmwidth = 176; + frame->frmheight = 144; + frame->order_uv = 1; /* U Y V Y ... */ + frame->hdr_sig = 0x0E; /* 00 FF 00 0E */ + break; + case VIDEOSIZE_352x288: + frame->frmwidth = 352; + frame->frmheight = 288; + frame->order_uv = 0; /* V Y U Y ... */ + frame->hdr_sig = 0x00; /* 00 FF 00 00 */ + break; + } + + width = frame->width; + RESTRICT_TO_RANGE(width, min_imgwidth, imgwidth); + width &= ~7; /* Multiple of 8 */ + + height = frame->height; + RESTRICT_TO_RANGE(height, min_imgheight, imgheight); + height &= ~3; /* Multiple of 4 */ + + return 0; +} + +/* + * ibmcam_open() + * + * This is part of Video 4 Linux API. The driver can be opened by one + * client only (checks internal counter 'ibmcam->user'). The procedure + * then allocates buffers needed for video processing. + * + * History: + * 1/22/00 Rewrote, moved scratch buffer allocation here. Now the + * camera is also initialized here (once per connect), at + * expense of V4L client (it waits on open() call). + */ +static int ibmcam_open(struct video_device *dev, int flags) +{ + struct usb_ibmcam *ibmcam = (struct usb_ibmcam *)dev; + const int nbuffers = 2; + const int sb_size = FRAMES_PER_DESC * ibmcam->iso_packet_len; + int i, err = 0; + + down(&ibmcam->lock); + + if (ibmcam->user) + err = -EBUSY; + else { + /* Clean pointers so we know if we allocated something */ + for (i=0; i < nbuffers; i++) + ibmcam->sbuf[i].data = NULL; + + /* Allocate memory for the frame buffers */ + ibmcam->fbuf_size = nbuffers * MAX_FRAME_SIZE; + ibmcam->fbuf = rvmalloc(ibmcam->fbuf_size); + ibmcam->scratch = kmalloc(scratchbufsize, GFP_KERNEL); + ibmcam->scratchlen = 0; + if ((ibmcam->fbuf == NULL) || (ibmcam->scratch == NULL)) + err = -ENOMEM; + else { + /* Allocate all buffers */ + for (i=0; i < nbuffers; i++) { + ibmcam->frame[i].grabstate = FRAME_UNUSED; + ibmcam->frame[i].data = ibmcam->fbuf + i*MAX_FRAME_SIZE; + + ibmcam->sbuf[i].data = kmalloc(sb_size, GFP_KERNEL); + if (ibmcam->sbuf[i].data == NULL) { + err = -ENOMEM; + break; + } + /* + * Set default sizes in case IOCTL (VIDIOCMCAPTURE) + * is not used (using read() instead). + */ + ibmcam->frame[i].width = imgwidth; + ibmcam->frame[i].height = imgheight; + ibmcam->frame[i].bytes_read = 0; + } + } + if (err) { + /* Have to free all that memory */ + if (ibmcam->fbuf != NULL) { + rvfree(ibmcam->fbuf, ibmcam->fbuf_size); + ibmcam->fbuf = NULL; + } + if (ibmcam->scratch != NULL) { + kfree(ibmcam->scratch); + ibmcam->scratch = NULL; + } + for (i=0; i < nbuffers; i++) { + if (ibmcam->sbuf[i].data != NULL) { + kfree (ibmcam->sbuf[i].data); + ibmcam->sbuf[i].data = NULL; + } + } + } + } + + /* If so far no errors then we shall start the camera */ + if (!err) { + err = ibmcam_init_isoc(ibmcam); + if (!err) { + /* Send init sequence only once, it's large! */ + if (!ibmcam->initialized) { + err = usb_ibmcam_setup(ibmcam); + if (!err) + ibmcam->initialized = 1; + } + if (!err) { + ibmcam->user++; + MOD_INC_USE_COUNT; + } + } + } + + up(&ibmcam->lock); + return err; +} + +/* + * ibmcam_close() + * + * This is part of Video 4 Linux API. The procedure + * stops streaming and deallocates all buffers that were earlier + * allocated in ibmcam_open(). + * + * History: + * 1/22/00 Moved scratch buffer deallocation here. + */ +static void ibmcam_close(struct video_device *dev) +{ + struct usb_ibmcam *ibmcam = (struct usb_ibmcam *)dev; + + down(&ibmcam->lock); + + ibmcam_stop_isoc(ibmcam); + + rvfree(ibmcam->fbuf, ibmcam->fbuf_size); + kfree(ibmcam->scratch); + kfree(ibmcam->sbuf[1].data); + kfree(ibmcam->sbuf[0].data); + + ibmcam->user--; + MOD_DEC_USE_COUNT; + + up(&ibmcam->lock); +} + +static int ibmcam_init_done(struct video_device *dev) +{ + return 0; +} + +static long ibmcam_write(struct video_device *dev, const char *buf, unsigned long count, int noblock) +{ + return -EINVAL; +} + +/* + * ibmcam_ioctl() + * + * This is part of Video 4 Linux API. The procedure handles ioctl() calls. + * + * History: + * 1/22/00 Corrected VIDIOCSPICT to reject unsupported settings. + */ +static int ibmcam_ioctl(struct video_device *dev, unsigned int cmd, void *arg) +{ + struct usb_ibmcam *ibmcam = (struct usb_ibmcam *)dev; + + if (ibmcam->remove_pending) + return -EFAULT; + + switch (cmd) { + case VIDIOCGCAP: + { + if (copy_to_user(arg, &ibmcam->vcap, sizeof(ibmcam->vcap))) + return -EFAULT; + return 0; + } + case VIDIOCGCHAN: + { + if (copy_to_user(arg, &ibmcam->vchan, sizeof(ibmcam->vchan))) + return -EFAULT; + return 0; + } + case VIDIOCSCHAN: + { + int v; + + if (copy_from_user(&v, arg, sizeof(v))) + return -EFAULT; + if ((v < 0) || (v >= 3)) /* 3 grades of lighting conditions */ + return -EINVAL; + if (v != ibmcam->vchan.channel) { + ibmcam->vchan.channel = v; + usb_ibmcam_change_lighting_conditions(ibmcam); + } + return 0; + } + case VIDIOCGPICT: + { + if (copy_to_user(arg, &ibmcam->vpic, sizeof(ibmcam->vpic))) + return -EFAULT; + return 0; + } + case VIDIOCSPICT: + { + struct video_picture tmp; + /* + * Use temporary 'video_picture' structure to preserve our + * own settings (such as color depth, palette) that we + * aren't allowing everyone (V4L client) to change. + */ + if (copy_from_user(&tmp, arg, sizeof(tmp))) + return -EFAULT; + ibmcam->vpic.brightness = tmp.brightness; + ibmcam->vpic.hue = tmp.hue; + ibmcam->vpic.colour = tmp.colour; + ibmcam->vpic.contrast = tmp.contrast; + usb_ibmcam_adjust_picture(ibmcam); + return 0; + } + case VIDIOCSWIN: + { + struct video_window vw; + + if (copy_from_user(&vw, arg, sizeof(vw))) + return -EFAULT; + if (vw.flags) + return -EINVAL; + if (vw.clipcount) + return -EINVAL; + if (vw.height != imgheight) + return -EINVAL; + if (vw.width != imgwidth) + return -EINVAL; + + ibmcam->compress = 0; + + return 0; + } + case VIDIOCGWIN: + { + struct video_window vw; + + vw.x = 0; + vw.y = 0; + vw.width = imgwidth; + vw.height = imgheight; + vw.chromakey = 0; + vw.flags = usb_ibmcam_calculate_fps(); + + if (copy_to_user(arg, &vw, sizeof(vw))) + return -EFAULT; + + return 0; + } + case VIDIOCGMBUF: + { + struct video_mbuf vm; + + memset(&vm, 0, sizeof(vm)); + vm.size = MAX_FRAME_SIZE * 2; + vm.frames = 2; + vm.offsets[0] = 0; + vm.offsets[1] = MAX_FRAME_SIZE; + + if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm))) + return -EFAULT; + + return 0; + } + case VIDIOCMCAPTURE: + { + struct video_mmap vm; + + if (copy_from_user((void *)&vm, (void *)arg, sizeof(vm))) + return -EFAULT; + + if (debug >= 1) + printk(KERN_DEBUG "frame: %d, size: %dx%d, format: %d\n", + vm.frame, vm.width, vm.height, vm.format); + + if (vm.format != VIDEO_PALETTE_RGB24) + return -EINVAL; + + if ((vm.frame != 0) && (vm.frame != 1)) + return -EINVAL; + + if (ibmcam->frame[vm.frame].grabstate == FRAME_GRABBING) + return -EBUSY; + + /* Don't compress if the size changed */ + if ((ibmcam->frame[vm.frame].width != vm.width) || + (ibmcam->frame[vm.frame].height != vm.height)) + ibmcam->compress = 0; + + ibmcam->frame[vm.frame].width = vm.width; + ibmcam->frame[vm.frame].height = vm.height; + + /* Mark it as ready */ + ibmcam->frame[vm.frame].grabstate = FRAME_READY; + + return ibmcam_new_frame(ibmcam, vm.frame); + } + case VIDIOCSYNC: + { + int frame; + + if (copy_from_user((void *)&frame, arg, sizeof(int))) + return -EFAULT; + + if (debug >= 1) + printk(KERN_DEBUG "ibmcam: syncing to frame %d\n", frame); + + switch (ibmcam->frame[frame].grabstate) { + case FRAME_UNUSED: + return -EINVAL; + case FRAME_READY: + case FRAME_GRABBING: + case FRAME_ERROR: + { + int ntries; + redo: + ntries = 0; + do { + interruptible_sleep_on(&ibmcam->frame[frame].wq); + if (signal_pending(current)) { + if (flags & FLAGS_RETRY_VIDIOCSYNC) { + /* Polling apps will destroy frames with that! */ + ibmcam_new_frame(ibmcam, frame); + usb_ibmcam_testpattern(ibmcam, 1, 0); + ibmcam->curframe = -1; + ibmcam->frame_num++; + + /* This will request another frame. */ + if (waitqueue_active(&ibmcam->frame[frame].wq)) + wake_up_interruptible(&ibmcam->frame[frame].wq); + return 0; + } else { + /* Standard answer: not ready yet! */ + return -EINTR; + } + } + } while (ibmcam->frame[frame].grabstate == FRAME_GRABBING); + + if (ibmcam->frame[frame].grabstate == FRAME_ERROR) { + int ret = ibmcam_new_frame(ibmcam, frame); + if (ret < 0) + return ret; + goto redo; + } + } + case FRAME_DONE: + ibmcam->frame[frame].grabstate = FRAME_UNUSED; + break; + } + + ibmcam->frame[frame].grabstate = FRAME_UNUSED; + + return 0; + } + case VIDIOCGFBUF: + { + struct video_buffer vb; + + memset(&vb, 0, sizeof(vb)); + vb.base = NULL; /* frame buffer not supported, not used */ + + if (copy_to_user((void *)arg, (void *)&vb, sizeof(vb))) + return -EFAULT; + + return 0; + } + case VIDIOCKEY: + return 0; + + case VIDIOCCAPTURE: + return -EINVAL; + + case VIDIOCSFBUF: + + case VIDIOCGTUNER: + case VIDIOCSTUNER: + + case VIDIOCGFREQ: + case VIDIOCSFREQ: + + case VIDIOCGAUDIO: + case VIDIOCSAUDIO: + return -EINVAL; + + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static long ibmcam_read(struct video_device *dev, char *buf, unsigned long count, int noblock) +{ + struct usb_ibmcam *ibmcam = (struct usb_ibmcam *)dev; + int frmx = -1; + volatile struct ibmcam_frame *frame; + + if (debug >= 1) + printk(KERN_DEBUG "ibmcam_read: %ld bytes, noblock=%d\n", count, noblock); + + if (ibmcam->remove_pending) + return -EFAULT; + + if (!dev || !buf) + return -EFAULT; + + /* See if a frame is completed, then use it. */ + if (ibmcam->frame[0].grabstate >= FRAME_DONE) /* _DONE or _ERROR */ + frmx = 0; + else if (ibmcam->frame[1].grabstate >= FRAME_DONE)/* _DONE or _ERROR */ + frmx = 1; + + if (noblock && (frmx == -1)) + return -EAGAIN; + + /* If no FRAME_DONE, look for a FRAME_GRABBING state. */ + /* See if a frame is in process (grabbing), then use it. */ + if (frmx == -1) { + if (ibmcam->frame[0].grabstate == FRAME_GRABBING) + frmx = 0; + else if (ibmcam->frame[1].grabstate == FRAME_GRABBING) + frmx = 1; + } + + /* If no frame is active, start one. */ + if (frmx == -1) + ibmcam_new_frame(ibmcam, frmx = 0); + + frame = &ibmcam->frame[frmx]; + +restart: + while (frame->grabstate == FRAME_GRABBING) { + interruptible_sleep_on((void *)&frame->wq); + if (signal_pending(current)) + return -EINTR; + } + + if (frame->grabstate == FRAME_ERROR) { + frame->bytes_read = 0; + if (ibmcam_new_frame(ibmcam, frmx)) + printk(KERN_ERR "ibmcam_read: ibmcam_new_frame error\n"); + goto restart; + } + + if (debug >= 1) + printk(KERN_DEBUG "ibmcam_read: frmx=%d, bytes_read=%ld, scanlength=%ld\n", + frmx, frame->bytes_read, frame->scanlength); + + /* copy bytes to user space; we allow for partials reads */ + if ((count + frame->bytes_read) > frame->scanlength) + count = frame->scanlength - frame->bytes_read; + + if (copy_to_user(buf, frame->data + frame->bytes_read, count)) + return -EFAULT; + + frame->bytes_read += count; + if (debug >= 1) + printk(KERN_DEBUG "ibmcam_read: {copy} count used=%ld, new bytes_read=%ld\n", + count, frame->bytes_read); + + if (frame->bytes_read >= frame->scanlength) { /* All data has been read */ + frame->bytes_read = 0; + + /* Mark it as available to be used again. */ + ibmcam->frame[frmx].grabstate = FRAME_UNUSED; + if (ibmcam_new_frame(ibmcam, frmx ? 0 : 1)) + printk(KERN_ERR "ibmcam_read: ibmcam_new_frame returned error\n"); + } + + return count; +} + +static int ibmcam_mmap(struct video_device *dev, const char *adr, unsigned long size) +{ + struct usb_ibmcam *ibmcam = (struct usb_ibmcam *)dev; + unsigned long start = (unsigned long)adr; + unsigned long page, pos; + + if (ibmcam->remove_pending) + return -EFAULT; + + if (size > (((2 * MAX_FRAME_SIZE) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) + return -EINVAL; + + pos = (unsigned long)ibmcam->fbuf; + while (size > 0) { + page = kvirt_to_pa(pos); + if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) + return -EAGAIN; + + start += PAGE_SIZE; + pos += PAGE_SIZE; + if (size > PAGE_SIZE) + size -= PAGE_SIZE; + else + size = 0; + } + + return 0; +} + +static struct video_device ibmcam_template = { + "CPiA USB Camera", + VID_TYPE_CAPTURE, + VID_HARDWARE_CPIA, + ibmcam_open, + ibmcam_close, + ibmcam_read, + ibmcam_write, + NULL, + ibmcam_ioctl, + ibmcam_mmap, + ibmcam_init_done, + NULL, + 0, + 0 +}; + +static void usb_ibmcam_configure_video(struct usb_ibmcam *ibmcam) +{ + if (ibmcam == NULL) + return; + + RESTRICT_TO_RANGE(init_brightness, 0, 255); + RESTRICT_TO_RANGE(init_contrast, 0, 255); + RESTRICT_TO_RANGE(init_color, 0, 255); + RESTRICT_TO_RANGE(init_hue, 0, 255); + + memset(&ibmcam->vpic, 0, sizeof(ibmcam->vpic)); + memset(&ibmcam->vpic_old, 0x55, sizeof(ibmcam->vpic_old)); + + ibmcam->vpic.colour = init_color << 8; + ibmcam->vpic.hue = init_hue << 8; + ibmcam->vpic.brightness = init_brightness << 8; + ibmcam->vpic.contrast = init_contrast << 8; + ibmcam->vpic.whiteness = 105 << 8; /* This one isn't used */ + ibmcam->vpic.depth = 24; + ibmcam->vpic.palette = VIDEO_PALETTE_RGB24; + + memset(&ibmcam->vcap, 0, sizeof(ibmcam->vcap)); + strcpy(ibmcam->vcap.name, "IBM USB Camera"); + ibmcam->vcap.type = VID_TYPE_CAPTURE /*| VID_TYPE_SUBCAPTURE*/; + ibmcam->vcap.channels = 1; + ibmcam->vcap.audios = 0; + ibmcam->vcap.maxwidth = imgwidth; + ibmcam->vcap.maxheight = imgheight; + ibmcam->vcap.minwidth = min_imgwidth; + ibmcam->vcap.minheight = min_imgheight; + + memset(&ibmcam->vchan, 0, sizeof(ibmcam->vchan)); + ibmcam->vchan.flags = 0; + ibmcam->vchan.tuners = 0; + ibmcam->vchan.channel = 0; + ibmcam->vchan.type = VIDEO_TYPE_CAMERA; + strcpy(ibmcam->vchan.name, "Camera"); +} + +/* + * usb_ibmcam_probe() + * + * This procedure queries device descriptor and accepts the interface + * if it looks like IBM C-it camera. + * + * History: + * 1/22/00 Moved camera init code to ibmcam_open() + */ +static void *usb_ibmcam_probe(struct usb_device *dev, unsigned int ifnum) +{ + struct usb_ibmcam *ibmcam = NULL; + struct usb_interface_descriptor *interface; + + if (debug >= 1) + printk(KERN_DEBUG "ibmcam_probe(%p,%u.)\n", dev, ifnum); + + /* We don't handle multi-config cameras */ + if (dev->descriptor.bNumConfigurations != 1) + return NULL; + + /* Is it an IBM camera? */ + if ((dev->descriptor.idVendor != 0x0545) || + (dev->descriptor.idProduct != 0x8080)) + return NULL; + + /* Camera confirmed. We claim only interface 2 (video data) */ + if (ifnum != 2) + return NULL; + + /* We found an IBM camera */ + printk(KERN_INFO "IBM USB camera found (interface %u.)\n", ifnum); + + if (debug >= 1) + printk(KERN_DEBUG "ibmcam_probe: new ibmcam alloc\n"); + ibmcam = kmalloc(sizeof(*ibmcam), GFP_KERNEL); + if (ibmcam == NULL) { + printk(KERN_ERR "couldn't kmalloc ibmcam struct\n"); + return NULL; + } + memset(ibmcam, 0, sizeof(struct usb_ibmcam)); + ibmcam->dev = dev; + interface = &dev->actconfig->interface[ifnum].altsetting[0]; + ibmcam->iface = interface->bInterfaceNumber; + ibmcam->video_endp = 0x82; + init_waitqueue_head (&ibmcam->remove_ok); + ibmcam->iso_packet_len = 1014; + + memcpy(&ibmcam->vdev, &ibmcam_template, sizeof(ibmcam_template)); + usb_ibmcam_configure_video(ibmcam); + + init_waitqueue_head(&ibmcam->frame[0].wq); + init_waitqueue_head(&ibmcam->frame[1].wq); + + if (video_register_device(&ibmcam->vdev, VFL_TYPE_GRABBER) == -1) { + printk(KERN_ERR "video_register_device failed\n"); + return NULL; + } + if (debug > 1) + printk(KERN_DEBUG "video_register_device() successful\n"); + + ibmcam->compress = 0; + ibmcam->user=0; + init_MUTEX(&ibmcam->lock); /* to 1 == available */ + + return ibmcam; +} + +/* + * usb_ibmcam_disconnect() + * + * This procedure stops all driver activity, deallocates interface-private + * structure (pointed by 'ptr') and after that driver should be removable + * with no ill consequences. + * + * TODO: This code behaves badly on surprise removal! + * + * History: + * 1/22/00 Added polling of MOD_IN_USE to delay removal until all users gone. + */ +static void usb_ibmcam_disconnect(struct usb_device *dev, void *ptr) +{ + static const char proc[] = "usb_ibmcam_disconnect"; + struct usb_ibmcam *ibmcam = (struct usb_ibmcam *) ptr; + wait_queue_head_t wq; /* Wait here until removal is safe */ + + if (debug > 0) + printk(KERN_DEBUG "%s(%p,%p.)\n", proc, dev, ptr); + + init_waitqueue_head(&wq); + ibmcam->remove_pending = 1; /* Now all ISO data will be ignored */ + + /* At this time we ask to cancel outstanding URBs */ + ibmcam_stop_isoc(ibmcam); + + if (MOD_IN_USE) { + printk(KERN_INFO "%s: In use, disconnect pending.\n", proc); + while (MOD_IN_USE) + interruptible_sleep_on_timeout (&wq, HZ); + printk(KERN_INFO "%s: Released, wait.\n", proc); +// interruptible_sleep_on_timeout (&wq, HZ*10); + } + video_unregister_device(&ibmcam->vdev); + printk(KERN_INFO "%s: Video dereg'd, wait.\n", proc); +// interruptible_sleep_on_timeout (&wq, HZ*10); + + /* Free the memory */ + if (debug > 0) + printk(KERN_DEBUG "%s: freeing ibmcam=%p\n", proc, ibmcam); + kfree(ibmcam); + + printk(KERN_INFO "%s: Memory freed, wait.\n", proc); +// interruptible_sleep_on_timeout (&wq, HZ*10); + + printk(KERN_INFO "IBM USB camera disconnected.\n"); +} + +static struct usb_driver ibmcam_driver = { + "ibmcam", + usb_ibmcam_probe, + usb_ibmcam_disconnect, + { NULL, NULL } +}; + +int usb_ibmcam_init(void) +{ + return usb_register(&ibmcam_driver); +} + +void usb_ibmcam_cleanup(void) +{ + usb_deregister(&ibmcam_driver); +} + +#ifdef MODULE +int init_module(void) +{ + return usb_ibmcam_init(); +} + +void cleanup_module(void) +{ + usb_ibmcam_cleanup(); +} +#endif diff --git a/drivers/usb/ibmcam.h b/drivers/usb/ibmcam.h new file mode 100644 index 000000000..6eb1d99ba --- /dev/null +++ b/drivers/usb/ibmcam.h @@ -0,0 +1,222 @@ +/* + * Header file for USB IBM C-It Video Camera driver. + * + * Supports IBM C-It Video Camera. + * + * This driver is based on earlier work of: + * + * (C) Copyright 1999 Johannes Erdfelt + * (C) Copyright 1999 Randy Dunlap + */ + +#ifndef __LINUX_IBMCAM_H +#define __LINUX_IBMCAM_H + +#include + +#define USES_IBMCAM_PUTPIXEL 0 /* 0=Fast/oops 1=Slow/secure */ + +/* Video Size 384 x 288 x 3 bytes for RGB */ +/* 384 because xawtv tries to grab 384 even though we tell it 352 is our max */ +#define V4L_FRAME_WIDTH 384 +#define V4L_FRAME_WIDTH_USED 352 +#define V4L_FRAME_HEIGHT 288 +#define V4L_BYTES_PER_PIXEL 3 +#define MAX_FRAME_SIZE (V4L_FRAME_WIDTH * V4L_FRAME_HEIGHT * V4L_BYTES_PER_PIXEL) + +/* Camera capabilities (maximum) */ +#define CAMERA_IMAGE_WIDTH 352 +#define CAMERA_IMAGE_HEIGHT 288 +#define CAMERA_IMAGE_LINE_SZ ((CAMERA_IMAGE_WIDTH * 3) / 2) /* Bytes */ +#define CAMERA_URB_FRAMES 32 +#define CAMERA_MAX_ISO_PACKET 1023 /* 1022 actually sent by camera */ + +#define IBMCAM_NUMFRAMES 2 +#define IBMCAM_NUMSBUF 2 + +#define FRAMES_PER_DESC (CAMERA_URB_FRAMES) +#define FRAME_SIZE_PER_DESC (CAMERA_MAX_ISO_PACKET) + +/* This macro restricts an int variable to an inclusive range */ +#define RESTRICT_TO_RANGE(v,mi,ma) { if ((v) < (mi)) (v) = (mi); else if ((v) > (ma)) (v) = (ma); } + +/* + * This macro performs bounds checking - use it when working with + * new formats, or else you may get oopses all over the place. + * If pixel falls out of bounds then it gets shoved back (as close + * to place of offence as possible) and is painted bright red. + */ +#define IBMCAM_PUTPIXEL(fr, ix, iy, vr, vg, vb) { \ + register unsigned char *pf; \ + int limiter = 0, mx, my; \ + mx = ix; \ + my = iy; \ + if (mx < 0) { \ + mx=0; \ + limiter++; \ + } else if (mx >= 352) { \ + mx=351; \ + limiter++; \ + } \ + if (my < 0) { \ + my = 0; \ + limiter++; \ + } else if (my >= V4L_FRAME_HEIGHT) { \ + my = V4L_FRAME_HEIGHT - 1; \ + limiter++; \ + } \ + pf = (fr)->data + V4L_BYTES_PER_PIXEL*((iy)*352 + (ix)); \ + if (limiter) { \ + *pf++ = 0; \ + *pf++ = 0; \ + *pf++ = 0xFF; \ + } else { \ + *pf++ = (vb); \ + *pf++ = (vg); \ + *pf++ = (vr); \ + } \ +} + +/* + * We use macros to do YUV -> RGB conversion because this is + * very important for speed and totally unimportant for size. + * + * YUV -> RGB Conversion + * --------------------- + * + * B = 1.164*(Y-16) + 2.018*(V-128) + * G = 1.164*(Y-16) - 0.813*(U-128) - 0.391*(V-128) + * R = 1.164*(Y-16) + 1.596*(U-128) + * + * If you fancy integer arithmetics (as you should), hear this: + * + * 65536*B = 76284*(Y-16) + 132252*(V-128) + * 65536*G = 76284*(Y-16) - 53281*(U-128) - 25625*(V-128) + * 65536*R = 76284*(Y-16) + 104595*(U-128) + * + * Make sure the output values are within [0..255] range. + */ +#define LIMIT_RGB(x) (((x) < 0) ? 0 : (((x) > 255) ? 255 : (x))) +#define YUV_TO_RGB_BY_THE_BOOK(my,mu,mv,mr,mg,mb) { \ + int mm_y, mm_yc, mm_u, mm_v, mm_r, mm_g, mm_b; \ + mm_y = (my) - 16; \ + mm_u = (mu) - 128; \ + mm_v = (mv) - 128; \ + mm_yc= mm_y * 76284; \ + mm_b = (mm_yc + 132252*mm_v ) >> 16; \ + mm_g = (mm_yc - 53281*mm_u - 25625*mm_v ) >> 16; \ + mm_r = (mm_yc + 104595*mm_u ) >> 16; \ + mb = LIMIT_RGB(mm_b); \ + mg = LIMIT_RGB(mm_g); \ + mr = LIMIT_RGB(mm_r); \ +} + +/* Debugging aid */ +#define IBMCAM_SAY_AND_WAIT(what) { \ + wait_queue_head_t wq; \ + init_waitqueue_head(&wq); \ + printk(KERN_INFO "Say: %s\n", what); \ + interruptible_sleep_on_timeout (&wq, HZ*3); \ +} + +enum { + STATE_SCANNING, /* Scanning for header */ + STATE_LINES, /* Parsing lines */ +}; + +enum { + FRAME_UNUSED, /* Unused (no MCAPTURE) */ + FRAME_READY, /* Ready to start grabbing */ + FRAME_GRABBING, /* In the process of being grabbed into */ + FRAME_DONE, /* Finished grabbing, but not been synced yet */ + FRAME_ERROR, /* Something bad happened while processing */ +}; + +struct usb_device; + +struct ibmcam_sbuf { + char *data; + urb_t *urb; +}; + +struct ibmcam_frame { + char *data; /* Frame buffer */ + int order_uv; /* True=UV False=VU */ + unsigned char hdr_sig; /* "00 FF 00 ??" where 'hdr_sig' is '??' */ + + int width; /* Width application is expecting */ + int height; /* Height */ + + int frmwidth; /* Width the frame actually is */ + int frmheight; /* Height */ + + volatile int grabstate; /* State of grabbing */ + int scanstate; /* State of scanning */ + + int curline; /* Line of frame we're working on */ + + long scanlength; /* uncompressed, raw data length of frame */ + long bytes_read; /* amount of scanlength that has been read from *data */ + + wait_queue_head_t wq; /* Processes waiting */ +}; + +struct usb_ibmcam { + struct video_device vdev; + + /* Device structure */ + struct usb_device *dev; + + unsigned char iface; + + struct semaphore lock; + int user; /* user count for exclusive use */ + + int initialized; /* Had we already sent init sequence? */ + int streaming; /* Are we streaming Isochronous? */ + int grabbing; /* Are we grabbing? */ + + int compress; /* Should the next frame be compressed? */ + + char *fbuf; /* Videodev buffer area */ + int fbuf_size; /* Videodev buffer size */ + + int curframe; + struct ibmcam_frame frame[IBMCAM_NUMFRAMES]; /* Double buffering */ + + int cursbuf; /* Current receiving sbuf */ + struct ibmcam_sbuf sbuf[IBMCAM_NUMSBUF]; /* Double buffering */ + volatile int remove_pending; /* If set then about to exit */ + wait_queue_head_t remove_ok; /* Wait here until removal is safe */ + + /* + * Scratch space from the Isochronous pipe. + * Scratch buffer should contain at least one pair of lines + * (CAMERA_IMAGE_LINE_SZ). We set it to two pairs here. + * This will be approximately 2 KB. HOWEVER in reality this + * buffer must be as large as hundred of KB because otherwise + * you'll get lots of overflows because V4L client may request + * frames not as uniformly as USB sources them. + */ + unsigned char *scratch; + int scratchlen; + + struct video_picture vpic, vpic_old; /* Picture settings */ + struct video_capability vcap; /* Video capabilities */ + struct video_channel vchan; /* May be used for tuner support */ + unsigned char video_endp; /* 0x82 for IBM camera */ + int has_hdr; + int frame_num; + int iso_packet_len; /* Videomode-dependent, saves bus bandwidth */ + + /* Statistics that can be overlayed on screen */ + unsigned long urb_count; /* How many URBs we received so far */ + unsigned long urb_length; /* Length of last URB */ + unsigned long data_count; /* How many bytes we received */ + unsigned long header_count; /* How many frame headers we found */ + unsigned long scratch_ovf_count;/* How many times we overflowed scratch */ + unsigned long iso_skip_count; /* How many empty ISO packets received */ + unsigned long iso_err_count; /* How many bad ISO packets received */ +}; + +#endif /* __LINUX_IBMCAM_H */ diff --git a/drivers/usb/keybdev.c b/drivers/usb/keybdev.c index 34da92941..f45f7032f 100644 --- a/drivers/usb/keybdev.c +++ b/drivers/usb/keybdev.c @@ -50,11 +50,11 @@ 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,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, + 11, 45, 46, 43, 47, 44,123, 67, 58, 49, 57,122,120, 99,118, 96, 97, 98,100,101,109, 71,107, 89, 91, 92, 78, 86, 87, 88, 69, 83, - 84, 85, 82, 65, 42, 0, 10,103,111, 0, 0, 0, 0, 0, 0, 0, + 84, 85, 82, 65, 42,105, 10,103,111, 0, 0, 0, 0, 0, 0, 0, 76,125, 75, 0,124, 0,115, 62,116, 59, 60,119, 61,121,114,117, - 0, 0, 0, 0,127, 81, 0,113 }; + 0, 0, 0, 0,127, 24, 0,113, 0, 0, 0, 0, 0, 55, 55, 0 }; #endif diff --git a/drivers/usb/mousedev.c b/drivers/usb/mousedev.c index c10b76557..95623c986 100644 --- a/drivers/usb/mousedev.c +++ b/drivers/usb/mousedev.c @@ -38,6 +38,13 @@ #include #include +#ifndef CONFIG_MOUSEDEV_SCREEN_X +#define CONFIG_MOUSEDEV_SCREEN_X 1024 +#endif +#ifndef CONFIG_MOUSEDEV_SCREEN_Y +#define CONFIG_MOUSEDEV_SCREEN_Y 768 +#endif + struct mousedev { char name[32]; int used; @@ -51,8 +58,8 @@ struct mousedev_list { struct fasync_struct *fasync; struct mousedev *mousedev; struct mousedev_list *next; - int dx, dy, dz; - unsigned char ps2[6]; + int dx, dy, dz, oldx, oldy; + char ps2[6]; unsigned long buttons; unsigned char ready, buffer, bufsiz; unsigned char mode, genseq, impseq; @@ -75,10 +82,26 @@ static void mousedev_event(struct input_handle *handle, unsigned int type, unsig { struct mousedev *mousedev = handle->private; struct mousedev_list *list = mousedev->list; - int index; + int index, size; while (list) { switch (type) { + case EV_ABS: + if (test_bit(EV_REL, handle->dev->evbit) && test_bit(REL_X, handle->dev->relbit)) + return; + switch (code) { + case ABS_X: + size = handle->dev->absmax[ABS_X] - handle->dev->absmin[ABS_X]; + list->dx += (value * CONFIG_MOUSEDEV_SCREEN_X - list->oldx) / size; + list->oldx += list->dx * size; + break; + case ABS_Y: + size = handle->dev->absmax[ABS_Y] - handle->dev->absmin[ABS_Y]; + list->dy += (value * CONFIG_MOUSEDEV_SCREEN_Y - list->oldy) / size; + list->oldy += list->dy * size; + break; + } + break; case EV_REL: switch (code) { case REL_X: list->dx += value; break; @@ -89,12 +112,20 @@ static void mousedev_event(struct input_handle *handle, unsigned int type, unsig case EV_KEY: switch (code) { + case BTN_0: + case BTN_TOUCH: case BTN_LEFT: index = 0; break; + case BTN_4: case BTN_EXTRA: if (list->mode > 1) { index = 4; break; } + case BTN_STYLUS: + case BTN_1: case BTN_RIGHT: index = 1; break; + case BTN_3: case BTN_SIDE: if (list->mode > 1) { index = 3; break; } + case BTN_2: + case BTN_STYLUS2: case BTN_MIDDLE: index = 2; break; - default: index = 0; + default: return; } switch (value) { case 0: clear_bit(index, &list->buttons); break; @@ -186,7 +217,8 @@ static void mousedev_packet(struct mousedev_list *list, unsigned char off) list->ps2[off] = 0x08 | ((list->dx < 0) << 4) | ((list->dy < 0) << 5) | (list->buttons & 0x07); list->ps2[off + 1] = (list->dx > 127 ? 127 : (list->dx < -127 ? -127 : list->dx)); list->ps2[off + 2] = (list->dy > 127 ? 127 : (list->dy < -127 ? -127 : list->dy)); - list->dx = list->dy = 0; + list->dx -= list->ps2[off + 1]; + list->dy -= list->ps2[off + 2]; list->bufsiz = off + 3; if (list->mode > 1) @@ -195,9 +227,9 @@ static void mousedev_packet(struct mousedev_list *list, unsigned char off) if (list->mode) { list->ps2[off + 3] = (list->dz > 127 ? 127 : (list->dz < -127 ? -127 : list->dz)); list->bufsiz++; - list->dz = 0; + list->dz -= list->ps2[off + 3]; } - list->ready = 0; + if (!list->dx && !list->dy && (!list->mode || !list->dz)) list->ready = 0; list->buffer = list->bufsiz; } @@ -330,15 +362,14 @@ struct file_operations mousedev_fops = { static int mousedev_connect(struct input_handler *handler, struct input_dev *dev) { - if (!(test_bit(EV_KEY, dev->evbit) && test_bit(EV_REL, dev->evbit))) /* The device must have both rels and keys */ + if (!test_bit(EV_KEY, dev->evbit) || + (!test_bit(BTN_LEFT, dev->keybit) && !test_bit(BTN_TOUCH, dev->keybit))) return -1; - if (!(test_bit(REL_X, dev->relbit) && test_bit(REL_Y, dev->relbit))) /* It must be a pointer device */ + if ((!test_bit(EV_REL, dev->evbit) || !test_bit(REL_X, dev->relbit)) && + (!test_bit(EV_ABS, dev->evbit) || !test_bit(ABS_X, dev->absbit))) return -1; - if (!test_bit(BTN_LEFT, dev->keybit)) /* And have at least one mousebutton */ - return -1; - #ifdef CONFIG_INPUT_MOUSEDEV_MIX { struct input_handle *handle; diff --git a/drivers/usb/ohci-hcd.c b/drivers/usb/ohci-hcd.c deleted file mode 100644 index 30274cb85..000000000 --- a/drivers/usb/ohci-hcd.c +++ /dev/null @@ -1,1823 +0,0 @@ -/* - * URB OHCI HCD (Host Controller Driver) for USB. - * - * (C) Copyright 1999 Roman Weissgaerber - * - * [ Initialisation is based on Linus' ] - * [ uhci code and gregs ohci fragments ] - * [ (C) Copyright 1999 Linus Torvalds ] - * [ (C) Copyright 1999 Gregory P. Smith] - * - * - * History: - * - * v5.2 1999/12/07 URB 3rd preview, - * v5.1 1999/11/30 URB 2nd preview, cpia, (usb-scsi) - * v5.0 1999/11/22 URB Technical preview, Paul Mackerras powerbook susp/resume - * i386: HUB, Keyboard, Mouse, Printer - * - * v4.3 1999/10/27 multiple HCs, bulk_request - * v4.2 1999/09/05 ISO API alpha, new dev alloc, neg Error-codes - * v4.1 1999/08/27 Randy Dunlap's - ISO API first impl. - * v4.0 1999/08/18 - * v3.0 1999/06/25 - * v2.1 1999/05/09 code clean up - * v2.0 1999/05/04 - * v1.0 1999/04/27 initial release - * - - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* for in_interrupt() */ - -#include -#include -#include - -#undef DEBUG -#define OHCI_USE_NPS - -#include "usb.h" -#include "ohci-hcd.h" - -#ifdef CONFIG_APM -#include -static int handle_apm_event (apm_event_t event); -#endif - -#ifdef CONFIG_PMAC_PBOOK -#include -#include -#endif - -static DECLARE_WAIT_QUEUE_HEAD (op_wakeup); -static LIST_HEAD (ohci_hcd_list); -spinlock_t usb_ed_lock = SPIN_LOCK_UNLOCKED; - -/*-------------------------------------------------------------------------* - * URB support functions - *-------------------------------------------------------------------------*/ - -/* free the private part of an URB */ - -static void urb_rm_priv (urb_t * urb) -{ - urb_priv_t * urb_priv = urb->hcpriv; - int i; - void * wait; - - if (!urb_priv) return; - - wait = urb_priv->wait; - - for (i = 0; i < urb_priv->length; i++) { - if (urb_priv->td [i]) { - OHCI_FREE (urb_priv->td [i]); - } - } - kfree (urb->hcpriv); - urb->hcpriv = NULL; - - if (wait) { - add_wait_queue (&op_wakeup, wait); - wake_up (&op_wakeup); - } -} - -/*-------------------------------------------------------------------------*/ - -#ifdef DEBUG -static int sohci_get_current_frame_number (struct usb_device * dev); - -/* debug| print the main components of an URB - * small: 0) header + data packets 1) just header */ - -static void urb_print (urb_t * urb, char * str, int small) -{ - unsigned int pipe= urb->pipe; - int i, len; - - if (!urb->dev || !urb->dev->bus) { - dbg("%s URB: no dev", str); - return; - } - - dbg("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,flags:%4x,len:%d/%d,stat:%d(%x)", - str, - sohci_get_current_frame_number (urb->dev), - usb_pipedevice (pipe), - usb_pipeendpoint (pipe), - usb_pipeout (pipe)? 'O': 'I', - usb_pipetype (pipe) < 2? (usb_pipeint (pipe)? "INTR": "ISOC"): - (usb_pipecontrol (pipe)? "CTRL": "BULK"), - urb->transfer_flags, - urb->actual_length, - urb->transfer_buffer_length, - urb->status, urb->status); - if (!small) { - if (usb_pipecontrol (pipe)) { - printk (KERN_DEBUG __FILE__ ": cmd(8):"); - for (i = 0; i < 8 ; i++) - printk (" %02x", ((__u8 *) urb->setup_packet) [i]); - printk ("\n"); - } - if (urb->transfer_buffer_length > 0 && urb->transfer_buffer) { - printk (KERN_DEBUG __FILE__ ": data(%d/%d):", - urb->actual_length, - urb->transfer_buffer_length); - len = usb_pipeout (pipe)? - urb->transfer_buffer_length: urb->actual_length; - for (i = 0; i < 16 && i < len; i++) - printk (" %02x", ((__u8 *) urb->transfer_buffer) [i]); - printk ("%s stat:%d\n", i < len? "...": "", urb->status); - } - } - -} -/* just for debugging; prints all 32 branches of the int ed tree inclusive iso eds*/ -void ep_print_int_eds (ohci_t * ohci, char * str) { - int i, j; - __u32 * ed_p; - for (i= 0; i < 32; i++) { - j = 5; - printk (KERN_DEBUG __FILE__ " %s branch int %2d(%2x):", str, i, i); - ed_p = &(ohci->hcca.int_table [i]); - while (*ed_p != 0 && j--) { - ed_t *ed = (ed_t *) bus_to_virt(le32_to_cpup(ed_p)); - printk (" ed: %4x;", ed->hwINFO); - ed_p = &ed->hwNextED; - } - printk ("\n"); - } -} - - -#endif - -/*-------------------------------------------------------------------------* - * Interface functions (URB) - *-------------------------------------------------------------------------*/ - -/* return a request to the completion handler */ - -static int sohci_return_urb (urb_t * urb) -{ - urb_priv_t * urb_priv = urb->hcpriv; - urb_t * urbt; - unsigned long flags; - int i; - - /* just to be sure */ - if (!urb->complete) { - urb_rm_priv (urb); - usb_dec_dev_use (urb->dev); - return -1; - } - - if (!urb_priv) return -1; /* urb already unlinked */ - -#ifdef DEBUG - urb_print (urb, "RET", usb_pipeout (urb->pipe)); -#endif - - switch (usb_pipetype (urb->pipe)) { - case PIPE_INTERRUPT: - urb->complete (urb); /* call complete and requeue URB */ - urb->actual_length = 0; - urb->status = USB_ST_URB_PENDING; - if (urb_priv->state != URB_DEL) - td_submit_urb (urb); - break; - - case PIPE_ISOCHRONOUS: - for (urbt = urb->next; urbt && (urbt != urb); urbt = urbt->next); - if (urbt) { /* send the reply and requeue URB */ - urb->complete (urb); - - spin_lock_irqsave (&usb_ed_lock, flags); - urb->actual_length = 0; - urb->status = USB_ST_URB_PENDING; - urb->start_frame = urb_priv->ed->last_iso + 1; - if (urb_priv->state != URB_DEL) { - for (i = 0; i < urb->number_of_packets; i++) { - urb->iso_frame_desc[i].actual_length = 0; - urb->iso_frame_desc[i].status = -EXDEV; - } - td_submit_urb (urb); - } - spin_unlock_irqrestore (&usb_ed_lock, flags); - - } else { /* unlink URB, call complete */ - urb_rm_priv (urb); - usb_dec_dev_use (urb->dev); - urb->complete (urb); - } - break; - - case PIPE_BULK: - case PIPE_CONTROL: /* unlink URB, call complete */ - urb_rm_priv (urb); - usb_dec_dev_use (urb->dev); - urb->complete (urb); - break; - } - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* get a transfer request */ - -static int sohci_submit_urb (urb_t * urb) -{ - ohci_t * ohci; - ed_t * ed; - urb_priv_t * urb_priv; - unsigned int pipe = urb->pipe; - int i, size = 0; - unsigned long flags; - - if (!urb->dev || !urb->dev->bus) return -EINVAL; - - if (urb->hcpriv) return -EINVAL; /* urb already in use */ - - usb_inc_dev_use (urb->dev); - ohci = (ohci_t *) urb->dev->bus->hcpriv; - -#ifdef DEBUG - urb_print (urb, "SUB", usb_pipein (pipe)); -#endif - - if (usb_pipedevice (pipe) == ohci->rh.devnum) - return rh_submit_urb (urb); /* a request to the virtual root hub */ - - /* every endpoint has a ed, locate and fill it */ - if (!(ed = ep_add_ed (urb->dev, pipe, urb->interval, 1))) { - usb_dec_dev_use (urb->dev); - return -ENOMEM; - } - - /* for the private part of the URB we need the number of TDs (size) */ - switch (usb_pipetype (pipe)) { - case PIPE_BULK: /* one TD for every 4096 Byte */ - size = (urb->transfer_buffer_length - 1) / 4096 + 1; - break; - case PIPE_ISOCHRONOUS: /* number of packets from URB */ - size = urb->number_of_packets; - for (i = 0; i < urb->number_of_packets; i++) { - urb->iso_frame_desc[i].actual_length = 0; - urb->iso_frame_desc[i].status = -EXDEV; - } - break; - case PIPE_CONTROL: /* 1 TD for setup, 1 for ACK and 1 for every 4096 B */ - size = (urb->transfer_buffer_length == 0)? 2: - (urb->transfer_buffer_length - 1) / 4096 + 3; - break; - case PIPE_INTERRUPT: /* one TD */ - size = 1; - - break; - } - - /* allocate the private part or the URB */ - urb_priv = kmalloc (sizeof (urb_priv_t) + size * sizeof (td_t *), - in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); - if (!urb_priv) { - usb_dec_dev_use (urb->dev); - return -ENOMEM; - } - memset (urb_priv, 0, sizeof (urb_priv_t) + size * sizeof (td_t *)); - - /* fill the private part of the URB */ - urb->hcpriv = urb_priv; - urb_priv->length = size; - urb_priv->td_cnt = 0; - urb_priv->state = 0; - urb_priv->ed = ed; - urb_priv->wait = NULL; - - /* allocate the TDs */ - for (i = 0; i < size; i++) { - OHCI_ALLOC (urb_priv->td[i], sizeof (td_t)); - if (!urb_priv->td[i]) { - usb_dec_dev_use (urb->dev); - urb_rm_priv (urb); - return -ENOMEM; - } - } - spin_lock_irqsave (&usb_ed_lock, flags); - if (ed->state == ED_NEW || (ed->state & ED_DEL)) { - urb_rm_priv(urb); - usb_dec_dev_use (urb->dev); - return -EINVAL; - } - - /* for ISOC transfers calculate start frame index */ - if (urb->transfer_flags & USB_ISO_ASAP) { - urb->start_frame = ((ed->state == ED_OPER)? (ed->last_iso + 1): - (le16_to_cpu (ohci->hcca.frame_no) + 10)) & 0xffff; - } - - td_submit_urb (urb); /* fill the TDs and link it to the ed */ - - if (ed->state != ED_OPER) /* link the ed into a chain if is not already */ - ep_link (ohci, ed); - spin_unlock_irqrestore (&usb_ed_lock, flags); - - urb->status = USB_ST_URB_PENDING; - // queue_urb(s, &urb->urb_list); - - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* deactivate all TDs and remove the private part of the URB */ - -static int sohci_unlink_urb (urb_t * urb) -{ - unsigned long flags; - ohci_t * ohci; - DECLARE_WAITQUEUE (wait, current); - - if (!urb) /* just to be sure */ - return -EINVAL; - -#ifdef DEBUG - urb_print (urb, "UNLINK", 1); -#endif - - ohci = (ohci_t *) urb->dev->bus->hcpriv; - - if (usb_pipedevice (urb->pipe) == ohci->rh.devnum) - return rh_unlink_urb (urb); /* a request to the virtual root hub */ - - if (urb->hcpriv) { - if (urb->status == USB_ST_URB_PENDING) { /* URB active? */ - urb_priv_t * urb_priv = urb->hcpriv; - urb_priv->state = URB_DEL; - /* we want to delete the TDs of an URB from an ed - * request the deletion, it will be handled at the next USB-frame */ - urb_priv->wait = &wait; - - spin_lock_irqsave (&usb_ed_lock, flags); - ep_rm_ed (urb->dev, urb_priv->ed); - urb_priv->ed->state |= ED_URB_DEL; - spin_unlock_irqrestore (&usb_ed_lock, flags); - - current->state = TASK_UNINTERRUPTIBLE; - if(schedule_timeout (HZ / 10)) /* wait until all TDs are deleted */ - remove_wait_queue (&op_wakeup, &wait); - else - err("unlink URB timeout!"); - } else - urb_rm_priv (urb); - usb_dec_dev_use (urb->dev); - } - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* allocate private data space for a usb device */ - -static int sohci_alloc_dev (struct usb_device *usb_dev) -{ - struct ohci_device * dev; - - dev = kmalloc (sizeof (*dev), GFP_KERNEL); - if (!dev) - return -ENOMEM; - - memset (dev, 0, sizeof (*dev)); - - usb_dev->hcpriv = dev; - - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* free private data space of usb device */ - -static int sohci_free_dev (struct usb_device * usb_dev) -{ - unsigned long flags; - int i, cnt = 0; - ed_t * ed; - DECLARE_WAITQUEUE (wait, current); - struct ohci_device * dev = usb_to_ohci (usb_dev); - ohci_t * ohci = usb_dev->bus->hcpriv; - - if (!dev) return 0; - - if (usb_dev->devnum >= 0) { - - /* delete all TDs of all EDs */ - spin_lock_irqsave (&usb_ed_lock, flags); - for(i = 0; i < NUM_EDS; i++) { - ed = &(dev->ed[i]); - if (ed->state != ED_NEW) { - if (ed->state == ED_OPER) ep_unlink (ohci, ed); - ep_rm_ed (usb_dev, ed); - ed->state = ED_DEL; - cnt++; - } - } - spin_unlock_irqrestore (&usb_ed_lock, flags); - - if (cnt > 0) { - dev->wait = &wait; - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout (HZ / 10); - remove_wait_queue (&op_wakeup, &wait); - } - } - kfree (dev); - - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* tell us the current USB frame number */ - -static int sohci_get_current_frame_number (struct usb_device *usb_dev) -{ - ohci_t * ohci = usb_dev->bus->hcpriv; - - return le16_to_cpu (ohci->hcca.frame_no); -} - -/*-------------------------------------------------------------------------*/ - -struct usb_operations sohci_device_operations = { - sohci_alloc_dev, - sohci_free_dev, - sohci_get_current_frame_number, - sohci_submit_urb, - sohci_unlink_urb -}; - -/*-------------------------------------------------------------------------* - * ED handling functions - *-------------------------------------------------------------------------*/ - -/* search for the right branch to insert an interrupt ed into the int tree - * do some load ballancing; - * returns the branch and - * sets the interval to interval = 2^integer (ld (interval)) */ - -static int ep_int_ballance (ohci_t * ohci, int interval, int load) -{ - int i, branch = 0; - - /* search for the least loaded interrupt endpoint branch of all 32 branches */ - for (i = 0; i < 32; i++) - if (ohci->ohci_int_load [branch] > ohci->ohci_int_load [i]) branch = i; - - branch = branch % interval; - for (i = branch; i < 32; i += interval) ohci->ohci_int_load [i] += load; - - return branch; -} - -/*-------------------------------------------------------------------------*/ - -/* 2^int( ld (inter)) */ - -static int ep_2_n_interval (int inter) -{ - int i; - for (i = 0; ((inter >> i) > 1 ) && (i < 5); i++); - return 1 << i; -} - -/*-------------------------------------------------------------------------*/ - -/* the int tree is a binary tree - * in order to process it sequentially the indexes of the branches have to be mapped - * the mapping reverses the bits of a word of num_bits length */ - -static int ep_rev (int num_bits, int word) -{ - int i, wout = 0; - - for (i = 0; i < num_bits; i++) wout |= (((word >> i) & 1) << (num_bits - i - 1)); - return wout; -} - -/*-------------------------------------------------------------------------*/ - -/* link an ed into one of the HC chains */ - -static int ep_link (ohci_t * ohci, ed_t * edi) -{ - int int_branch; - int i; - int inter; - int interval; - int load; - __u32 * ed_p; - volatile ed_t * ed = edi; - - ed->state = ED_OPER; - - switch (ed->type) { - case CTRL: - ed->hwNextED = 0; - if (ohci->ed_controltail == NULL) { - writel (virt_to_bus (ed), &ohci->regs->ed_controlhead); - } else { - ohci->ed_controltail->hwNextED = cpu_to_le32 (virt_to_bus (ed)); - } - ed->ed_prev = ohci->ed_controltail; - ohci->ed_controltail = ed; - break; - - case BULK: - ed->hwNextED = 0; - if (ohci->ed_bulktail == NULL) { - writel (virt_to_bus (ed), &ohci->regs->ed_bulkhead); - } else { - ohci->ed_bulktail->hwNextED = cpu_to_le32 (virt_to_bus (ed)); - } - ed->ed_prev = ohci->ed_bulktail; - ohci->ed_bulktail = ed; - break; - - case INT: - load = ed->int_load; - interval = ep_2_n_interval (ed->int_period); - ed->int_interval = interval; - int_branch = ep_int_ballance (ohci, interval, load); - ed->int_branch = int_branch; - - 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_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)); - } -#ifdef DEBUG - ep_print_int_eds (ohci, "LINK_INT"); -#endif - break; - - case ISO: - ed->hwNextED = 0; - ed->int_interval = 1; - if (ohci->ed_isotail != NULL) { - ohci->ed_isotail->hwNextED = cpu_to_le32 (virt_to_bus (ed)); - ed->ed_prev = ohci->ed_isotail; - } else { - for ( i = 0; i < 32; i += inter) { - 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_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; - } - ohci->ed_isotail = ed; -#ifdef DEBUG - ep_print_int_eds (ohci, "LINK_ISO"); -#endif - break; - } - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* unlink an ed from one of the HC chains. - * just the link to the ed is unlinked. - * the link from the ed still points to another operational ed or 0 - * so the HC can eventually finish the processing of the unlinked ed */ - -static int ep_unlink (ohci_t * ohci, ed_t * ed) -{ - int int_branch; - int i; - int inter; - int interval; - __u32 * ed_p; - - - switch (ed->type) { - case CTRL: - if (ed->ed_prev == NULL) { - 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_cpup (&ed->hwNextED)))->ed_prev = ed->ed_prev; - } - break; - - case BULK: - if (ed->ed_prev == NULL) { - 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_cpup (&ed->hwNextED)))->ed_prev = ed->ed_prev; - } - break; - - case INT: - int_branch = ed->int_branch; - interval = ed->int_interval; - - 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_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; - } - } - } - for (i = int_branch; i < 32; i += interval) ohci->ohci_int_load[i] -= ed->int_load; -#ifdef DEBUG - ep_print_int_eds (ohci, "UNLINK_INT"); -#endif break; - - case ISO: - if (ohci->ed_isotail == ed) - ohci->ed_isotail = ed->ed_prev; - if (ed->hwNextED != 0) - ((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; - } else { - for (i = 0; i < 32; i += inter) { - 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_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; - } - } - } - } -#ifdef DEBUG - ep_print_int_eds (ohci, "UNLINK_ISO"); -#endif - break; - } - ed->state = ED_UNLINK; - return 0; -} - - -/*-------------------------------------------------------------------------*/ - -/* add/reinit an endpoint; this should be done once at the usb_set_configuration command, - * but the USB stack is a little bit stateless so we do it at every transaction - * if the state of the ed is ED_NEW then a dummy td is added and the state is changed to ED_UNLINK - * in all other cases the state is left unchanged - * the ed info fields are setted anyway even though most of them should not change */ - -static ed_t * ep_add_ed (struct usb_device * usb_dev, unsigned int pipe, int interval, int load) -{ - ohci_t * ohci = usb_dev->bus->hcpriv; - td_t * td; - volatile ed_t * ed; - - - spin_lock (&usb_ed_lock); - - ed = &(usb_to_ohci (usb_dev)->ed[(usb_pipeendpoint (pipe) << 1) | - (usb_pipecontrol (pipe)? 0: usb_pipeout (pipe))]); - - if((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) - return NULL; /* pending delete request */ - - if (ed->state == ED_NEW) { - ed->hwINFO = cpu_to_le32 (OHCI_ED_SKIP); /* skip ed */ - OHCI_ALLOC (td, sizeof (*td)); /* dummy td; end of td list for ed */ - if(!td) return NULL; /* out of memory */ - ed->hwTailP = cpu_to_le32 (virt_to_bus (td)); - ed->hwHeadP = ed->hwTailP; - ed->state = ED_UNLINK; - ed->type = usb_pipetype (pipe); - usb_to_ohci (usb_dev)->ed_cnt++; - } - - ohci->dev[usb_pipedevice (pipe)] = usb_dev; - - ed->hwINFO = cpu_to_le32 (usb_pipedevice (pipe) - | usb_pipeendpoint (pipe) << 7 - | (usb_pipeisoc (pipe)? 0x8000: 0) - | (usb_pipecontrol (pipe)? 0: (usb_pipeout (pipe)? 0x800: 0x1000)) - | usb_pipeslow (pipe) << 13 - | usb_maxpacket (usb_dev, pipe, usb_pipeout (pipe)) << 16); - - if (ed->type == INT && ed->state == ED_UNLINK) { - ed->int_period = interval; - ed->int_load = load; - } - - spin_unlock(&usb_ed_lock); - return ed; -} - -/*-------------------------------------------------------------------------*/ - -/* request the removal of an endpoint - * put the ep on the rm_list and request a stop of the bulk or ctrl list - * real removal is done at the next start of frame (SOF) hardware interrupt */ - -static void ep_rm_ed (struct usb_device * usb_dev, ed_t * ed) -{ - unsigned int frame; - ohci_t * ohci = usb_dev->bus->hcpriv; - - if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) return; - - ed->hwINFO |= cpu_to_le32 (OHCI_ED_SKIP); - - writel (OHCI_INTR_SF, &ohci->regs->intrstatus); - writel (OHCI_INTR_SF, &ohci->regs->intrenable); /* enable sof interrupt */ - - frame = le16_to_cpu (ohci->hcca.frame_no) & 0x1; - ed->ed_rm_list = ohci->ed_rm_list[frame]; - ohci->ed_rm_list[frame] = ed; - - switch (ed->type) { - case CTRL: /* stop CTRL list */ - writel (ohci->hc_control &= ~(0x01 << 4), &ohci->regs->control); - break; - case BULK: /* stop BULK list */ - writel (ohci->hc_control &= ~(0x01 << 5), &ohci->regs->control); - break; - } -} - -/*-------------------------------------------------------------------------* - * TD handling functions - *-------------------------------------------------------------------------*/ - -/* prepare a TD */ - -static void td_fill (unsigned int info, void * data, int len, urb_t * urb, int type, int index) -{ - volatile td_t * td, * td_pt; - urb_priv_t * urb_priv = urb->hcpriv; - - if (index >= urb_priv->length) { - err("internal OHCI error: TD index > length"); - return; - } - - td_pt = urb_priv->td [index]; - /* fill the old dummy TD */ - 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; - td->hwINFO = cpu_to_le32 (info); - td->type = type; - if ((td->ed->type & 3) == PIPE_ISOCHRONOUS) { - td->hwCBP = cpu_to_le32 (((!data || !len)? - 0 : virt_to_bus (data)) & 0xFFFFF000); - td->ed->last_iso = info & 0xffff; - } else { - td->hwCBP = cpu_to_le32 (((!data || !len)? 0 : virt_to_bus (data))); - } - td->hwBE = cpu_to_le32 ((!data || !len )? 0: virt_to_bus (data + len - 1)); - td->hwNextTD = cpu_to_le32 (virt_to_bus (td_pt)); - td->hwPSW [0] = cpu_to_le16 ((virt_to_bus (data) & 0x0FFF) | 0xE000); - td_pt->hwNextTD = 0; - td->ed->hwTailP = td->hwNextTD; - urb_priv->td [index] = td; - - td->next_dl_td = NULL; //td_pt; -} - -/*-------------------------------------------------------------------------*/ - -/* prepare all TDs of a transfer */ - -static void td_submit_urb (urb_t * urb) -{ - urb_priv_t * urb_priv = urb->hcpriv; - ohci_t * ohci = (ohci_t *) urb->dev->bus->hcpriv; - void * ctrl = urb->setup_packet; - void * data = urb->transfer_buffer; - int data_len = urb->transfer_buffer_length; - int cnt = 0; - __u32 info = 0; - - - urb_priv->td_cnt = 0; - - switch (usb_pipetype (urb->pipe)) { - case PIPE_BULK: - info = usb_pipeout (urb->pipe)? - TD_CC | TD_DP_OUT | TD_T_TOGGLE: TD_CC | TD_DP_IN | TD_T_TOGGLE; - while(data_len > 4096) { - td_fill (info, data, 4096, urb, (cnt? 0: ST_ADDR) | ADD_LEN, cnt); - data += 4096; data_len -= 4096; cnt++; - } - info = usb_pipeout (urb->pipe)? - TD_CC | TD_DP_OUT | TD_T_TOGGLE: TD_CC | TD_R | TD_DP_IN | TD_T_TOGGLE; - td_fill (info, data, data_len, urb, (cnt? 0: ST_ADDR) | ADD_LEN, cnt); - cnt++; - writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */ - break; - - case PIPE_INTERRUPT: - info = usb_pipeout (urb->pipe)? - TD_CC | TD_DP_OUT | TD_T_TOGGLE: TD_CC | TD_R | TD_DP_IN | TD_T_TOGGLE; - td_fill (info, data, data_len, urb, ST_ADDR | ADD_LEN, cnt++); - break; - - case PIPE_CONTROL: - info = TD_CC | TD_DP_SETUP | TD_T_DATA0; - td_fill (info, ctrl, 8, urb, ST_ADDR, cnt++); - if (data_len > 0) { - info = usb_pipeout (urb->pipe)? - TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 : TD_CC | TD_R | TD_DP_IN | TD_T_DATA1; - td_fill (info, data, data_len, urb, ADD_LEN, cnt++); - } - info = usb_pipeout (urb->pipe)? - TD_CC | TD_DP_IN | TD_T_DATA1: TD_CC | TD_DP_OUT | TD_T_DATA1; - td_fill (info, NULL, 0, urb, 0, cnt++); - writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */ - break; - - case PIPE_ISOCHRONOUS: - for (cnt = 0; cnt < urb->number_of_packets; cnt++) { - td_fill (TD_CC|TD_ISO | ((urb->start_frame + cnt) & 0xffff), - (__u8 *) data + urb->iso_frame_desc[cnt].offset, - urb->iso_frame_desc[cnt].length, urb, (cnt? 0: ST_ADDR) | ADD_LEN, cnt); - } - break; - } - if (urb_priv->length != cnt) - dbg("TD LENGTH %d != CNT %d", urb_priv->length, cnt); -} - -/*-------------------------------------------------------------------------* - * Done List handling functions - *-------------------------------------------------------------------------*/ - -/* replies to the request have to be on a FIFO basis so - * we reverse the reversed done-list */ - -static td_t * dl_reverse_done_list (ohci_t * ohci) -{ - __u32 td_list_hc; - td_t * td_rev = NULL; - td_t * td_list = NULL; - urb_priv_t * urb_priv = NULL; - unsigned long flags; - - spin_lock_irqsave (&usb_ed_lock, flags); - - 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_cpup (&td_list->hwINFO))) { - urb_priv = (urb_priv_t *) td_list->urb->hcpriv; - dbg(" USB-error/status: %x : %p", - 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 = - (urb_priv->td[urb_priv->length - 1]->hwNextTD & cpu_to_le32 (0xfffffff0)) | - (td_list->ed->hwHeadP & cpu_to_le32 (0x2)); - urb_priv->td_cnt += urb_priv->length - td_list->index - 1; - } else - td_list->ed->hwHeadP &= cpu_to_le32 (0xfffffff2); - } - } - - td_list->next_dl_td = td_rev; - td_rev = td_list; - td_list_hc = le32_to_cpup (&td_list->hwNextTD) & 0xfffffff0; - } - spin_unlock_irqrestore (&usb_ed_lock, flags); - return td_list; -} - -/*-------------------------------------------------------------------------*/ - -/* there are some pending requests to remove - * - some of the eds (if ed->state & ED_DEL (set by sohci_free_dev) - * - some URBs/TDs if urb_priv->state == URB_DEL */ - -static void dl_del_list (ohci_t * ohci, unsigned int frame) -{ - unsigned long flags; - ed_t * ed; - __u32 edINFO; - td_t * td = NULL, * td_next = NULL, * tdHeadP = NULL, * tdTailP; - __u32 * td_p; - int ctrl = 0, bulk = 0; - - 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_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_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) - urb_rm_priv (urb); - } else { - td_p = &td->hwNextTD; - } - - } - if (ed->state & ED_DEL) { /* set by sohci_free_dev */ - struct ohci_device * dev = usb_to_ohci (ohci->dev[edINFO & 0x7F]); - OHCI_FREE (tdTailP); /* free dummy td */ - ed->hwINFO = cpu_to_le32 (OHCI_ED_SKIP); - ed->state = ED_NEW; - /* if all eds are removed wake up sohci_free_dev */ - if ((! --dev->ed_cnt) && dev->wait) { - add_wait_queue (&op_wakeup, dev->wait); - wake_up (&op_wakeup); - } - } - else { - ed->state &= ~ED_URB_DEL; - ed->hwINFO &= ~cpu_to_le32 (OHCI_ED_SKIP); - } - - if ((ed->type & 3) == CTRL) ctrl |= 1; - if ((ed->type & 3) == BULK) bulk |= 1; - } - - if (ctrl) writel (0, &ohci->regs->ed_controlcurrent); /* reset CTRL list */ - if (bulk) writel (0, &ohci->regs->ed_bulkcurrent); /* reset BULK list */ - if (!ohci->ed_rm_list[!frame]) /* start CTRL u. BULK list */ - writel (ohci->hc_control |= (0x03<<4), &ohci->regs->control); - ohci->ed_rm_list[frame] = NULL; - - spin_unlock_irqrestore (&usb_ed_lock, flags); -} - -/*-------------------------------------------------------------------------*/ - -/* td done list */ - -static void dl_done_list (ohci_t * ohci, td_t * td_list) -{ - td_t * td_list_next = NULL; - ed_t * ed; - int dlen = 0; - int cc = 0; - urb_t * urb; - urb_priv_t * urb_priv; - __u32 tdINFO, tdBE, tdCBP, edHeadP, edTailP; - __u16 tdPSW; - 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_cpup (&td_list->hwINFO); - tdBE = le32_to_cpup (&td_list->hwBE); - tdCBP = le32_to_cpup (&td_list->hwCBP); - - ed = td_list->ed; - - if (td_list->type & ST_ADDR) - urb->actual_length = 0; - - if (td_list->type & ADD_LEN) { /* accumulate length of multi td transfers */ - if (tdINFO & TD_ISO) { - tdPSW = le16_to_cpu (td_list->hwPSW[0]); - cc = (tdPSW >> 12) & 0xF; - if (cc < 0xE) { - if (usb_pipeout(urb->pipe)) { - dlen = urb->iso_frame_desc[td_list->index].length; - } else { - dlen = tdPSW & 0x3ff; - } - urb->actual_length += dlen; - urb->iso_frame_desc[td_list->index].actual_length = dlen; - if (!(urb->transfer_flags & USB_DISABLE_SPD) && (cc == TD_DATAUNDERRUN)) - cc = TD_CC_NOERROR; - - urb->iso_frame_desc[td_list->index].status = cc_to_error[cc]; - } - } else { - if (tdBE != 0) { - dlen = (bus_to_virt (tdBE) - urb->transfer_buffer + 1); - if (td_list->hwCBP == 0) - urb->actual_length += dlen; - else - urb->actual_length += (bus_to_virt(tdCBP) - urb->transfer_buffer); - } - } - } - /* error code of transfer */ - cc = TD_CC_GET (tdINFO); - if (!(urb->transfer_flags & USB_DISABLE_SPD) && (cc == TD_DATAUNDERRUN)) - cc = TD_CC_NOERROR; - if (++(urb_priv->td_cnt) == urb_priv->length) { - if (urb_priv->state != URB_DEL && !(ed->state & ED_DEL) && ed->state != ED_NEW) { - urb->status = cc_to_error[cc]; - sohci_return_urb (urb); - } else { - urb_rm_priv (urb); - } - } - - spin_lock_irqsave (&usb_ed_lock, flags); - if (ed->state != ED_NEW) { - 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 */ - - } - spin_unlock_irqrestore (&usb_ed_lock, flags); - - td_list = td_list_next; - } -} - - - - -/*-------------------------------------------------------------------------* - * Virtual Root Hub - *-------------------------------------------------------------------------*/ - -static __u8 root_hub_dev_des[] = -{ - 0x12, /* __u8 bLength; */ - 0x01, /* __u8 bDescriptorType; Device */ - 0x00, /* __u16 bcdUSB; v1.0 */ - 0x01, - 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ - 0x00, /* __u8 bDeviceSubClass; */ - 0x00, /* __u8 bDeviceProtocol; */ - 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ - 0x00, /* __u16 idVendor; */ - 0x00, - 0x00, /* __u16 idProduct; */ - 0x00, - 0x00, /* __u16 bcdDevice; */ - 0x00, - 0x00, /* __u8 iManufacturer; */ - 0x00, /* __u8 iProduct; */ - 0x00, /* __u8 iSerialNumber; */ - 0x01 /* __u8 bNumConfigurations; */ -}; - - -/* Configuration descriptor */ -static __u8 root_hub_config_des[] = -{ - 0x09, /* __u8 bLength; */ - 0x02, /* __u8 bDescriptorType; Configuration */ - 0x19, /* __u16 wTotalLength; */ - 0x00, - 0x01, /* __u8 bNumInterfaces; */ - 0x01, /* __u8 bConfigurationValue; */ - 0x00, /* __u8 iConfiguration; */ - 0x40, /* __u8 bmAttributes; - Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */ - 0x00, /* __u8 MaxPower; */ - - /* interface */ - 0x09, /* __u8 if_bLength; */ - 0x04, /* __u8 if_bDescriptorType; Interface */ - 0x00, /* __u8 if_bInterfaceNumber; */ - 0x00, /* __u8 if_bAlternateSetting; */ - 0x01, /* __u8 if_bNumEndpoints; */ - 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */ - 0x00, /* __u8 if_bInterfaceSubClass; */ - 0x00, /* __u8 if_bInterfaceProtocol; */ - 0x00, /* __u8 if_iInterface; */ - - /* endpoint */ - 0x07, /* __u8 ep_bLength; */ - 0x05, /* __u8 ep_bDescriptorType; Endpoint */ - 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ - 0x03, /* __u8 ep_bmAttributes; Interrupt */ - 0x08, /* __u16 ep_wMaxPacketSize; 8 Bytes */ - 0x00, - 0xff /* __u8 ep_bInterval; 255 ms */ -}; - -/* -For OHCI we need just the 2nd Byte, so we -don't need this constant byte-array - -static __u8 root_hub_hub_des[] = -{ - 0x00, * __u8 bLength; * - 0x29, * __u8 bDescriptorType; Hub-descriptor * - 0x02, * __u8 bNbrPorts; * - 0x00, * __u16 wHubCharacteristics; * - 0x00, - 0x01, * __u8 bPwrOn2pwrGood; 2ms * - 0x00, * __u8 bHubContrCurrent; 0 mA * - 0x00, * __u8 DeviceRemovable; *** 8 Ports max *** * - 0xff * __u8 PortPwrCtrlMask; *** 8 ports max *** * -}; -*/ - -/*-------------------------------------------------------------------------*/ - -/* prepare Interrupt pipe data; HUB INTERRUPT ENDPOINT */ - -static int rh_send_irq (ohci_t * ohci, void * rh_data, int rh_len) -{ - int num_ports; - int i; - int ret; - int len; - - __u8 data[8]; - - num_ports = readl (&ohci->regs->roothub.a) & 0xff; - *(__u8 *) data = (readl (&ohci->regs->roothub.status) & 0x00030000) > 0? 1: 0; - ret = *(__u8 *) data; - - for ( i = 0; i < num_ports; i++) { - *(__u8 *) (data + (i + 1) / 8) |= - ((readl (&ohci->regs->roothub.portstatus[i]) & 0x001f0000) > 0? 1: 0) << ((i + 1) % 8); - ret += *(__u8 *) (data + (i + 1) / 8); - } - len = i/8 + 1; - - if (ret > 0) { - memcpy (rh_data, data, min (len, min (rh_len, sizeof(data)))); - return len; - } - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* Virtual Root Hub INTs are polled by this timer every "intervall" ms */ - -static void rh_int_timer_do (unsigned long ptr) -{ - int len; - - urb_t * urb = (urb_t *) ptr; - ohci_t * ohci = urb->dev->bus->hcpriv; - - if(ohci->rh.send) { - len = rh_send_irq (ohci, urb->transfer_buffer, urb->transfer_buffer_length); - if (len > 0) { - urb->actual_length = len; -#ifdef DEBUG - urb_print (urb, "RET(rh)", usb_pipeout (urb->pipe)); -#endif - if (urb->complete) urb->complete (urb); - } - } - rh_init_int_timer (urb); -} - -/*-------------------------------------------------------------------------*/ - -/* Root Hub INTs are polled by this timer */ - -static int rh_init_int_timer (urb_t * urb) -{ - ohci_t * ohci = urb->dev->bus->hcpriv; - - ohci->rh.interval = urb->interval; - init_timer (&ohci->rh.rh_int_timer); - ohci->rh.rh_int_timer.function = rh_int_timer_do; - ohci->rh.rh_int_timer.data = (unsigned long) urb; - ohci->rh.rh_int_timer.expires = - jiffies + (HZ * (urb->interval < 30? 30: urb->interval)) / 1000; - add_timer (&ohci->rh.rh_int_timer); - - return 0; -} - -/*-------------------------------------------------------------------------*/ - -#define OK(x) len = (x); break -#define WR_RH_STAT(x) writel((x), &ohci->regs->roothub.status) -#define WR_RH_PORTSTAT(x) writel((x), &ohci->regs->roothub.portstatus[wIndex-1]) -#define RD_RH_STAT readl(&ohci->regs->roothub.status) -#define RD_RH_PORTSTAT readl(&ohci->regs->roothub.portstatus[wIndex-1]) - -/* request to virtual root hub */ - -static int rh_submit_urb (urb_t * urb) -{ - struct usb_device * usb_dev = urb->dev; - ohci_t * ohci = usb_dev->bus->hcpriv; - unsigned int pipe = urb->pipe; - devrequest * cmd = (devrequest *) urb->setup_packet; - void * data = urb->transfer_buffer; - int leni = urb->transfer_buffer_length; - int len = 0; - int status = TD_CC_NOERROR; - - __u8 datab[16]; - __u8 * data_buf = datab; - - __u16 bmRType_bReq; - __u16 wValue; - __u16 wIndex; - __u16 wLength; - - if (usb_pipeint(pipe)) { - - ohci->rh.urb = urb; - ohci->rh.send = 1; - ohci->rh.interval = urb->interval; - rh_init_int_timer(urb); - urb->status = cc_to_error [TD_CC_NOERROR]; - - return 0; - } - - bmRType_bReq = cmd->requesttype | (cmd->request << 8); - wValue = le16_to_cpu (cmd->value); - wIndex = le16_to_cpu (cmd->index); - wLength = le16_to_cpu (cmd->length); - switch (bmRType_bReq) { - /* Request Destination: - without flags: Device, - RH_INTERFACE: interface, - RH_ENDPOINT: endpoint, - RH_CLASS means HUB here, - RH_OTHER | RH_CLASS almost ever means HUB_PORT here - */ - - case RH_GET_STATUS: - *(__u16 *) data_buf = cpu_to_le16 (1); OK (2); - case RH_GET_STATUS | RH_INTERFACE: - *(__u16 *) data_buf = cpu_to_le16 (0); OK (2); - case RH_GET_STATUS | RH_ENDPOINT: - *(__u16 *) data_buf = cpu_to_le16 (0); OK (2); - case RH_GET_STATUS | RH_CLASS: - *(__u32 *) data_buf = cpu_to_le32 (RD_RH_STAT & 0x7fff7fff); OK (4); - case RH_GET_STATUS | RH_OTHER | RH_CLASS: - *(__u32 *) data_buf = cpu_to_le32 (RD_RH_PORTSTAT); OK (4); - - case RH_CLEAR_FEATURE | RH_ENDPOINT: - switch (wValue) { - case (RH_ENDPOINT_STALL): OK (0); - } - break; - - 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_HS_OCIC); OK (0); - } - break; - - case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: - switch (wValue) { - case (RH_PORT_ENABLE): - WR_RH_PORTSTAT (RH_PS_CCS ); OK (0); - case (RH_PORT_SUSPEND): - WR_RH_PORTSTAT (RH_PS_POCI); OK (0); - case (RH_PORT_POWER): - WR_RH_PORTSTAT (RH_PS_LSDA); OK (0); - case (RH_C_PORT_CONNECTION): - WR_RH_PORTSTAT (RH_PS_CSC ); OK (0); - case (RH_C_PORT_ENABLE): - WR_RH_PORTSTAT (RH_PS_PESC); OK (0); - case (RH_C_PORT_SUSPEND): - WR_RH_PORTSTAT (RH_PS_PSSC); OK (0); - case (RH_C_PORT_OVER_CURRENT): - WR_RH_PORTSTAT (RH_PS_OCIC); OK (0); - case (RH_C_PORT_RESET): - WR_RH_PORTSTAT (RH_PS_PRSC); OK (0); - } - break; - - case RH_SET_FEATURE | RH_OTHER | RH_CLASS: - switch (wValue) { - case (RH_PORT_SUSPEND): - WR_RH_PORTSTAT (RH_PS_PSS ); OK (0); - case (RH_PORT_RESET): /* BUG IN HUP CODE *********/ - if((RD_RH_PORTSTAT &1) != 0) WR_RH_PORTSTAT (RH_PS_PRS ); OK (0); - case (RH_PORT_POWER): - WR_RH_PORTSTAT (RH_PS_PPS ); OK (0); - case (RH_PORT_ENABLE): /* BUG IN HUP CODE *********/ - if((RD_RH_PORTSTAT &1) != 0) WR_RH_PORTSTAT (RH_PS_PES ); OK (0); - } - break; - - case RH_SET_ADDRESS: ohci->rh.devnum = wValue; OK(0); - - case RH_GET_DESCRIPTOR: - switch ((wValue & 0xff00) >> 8) { - case (0x01): /* device descriptor */ - len = min (leni, min (sizeof (root_hub_dev_des), wLength)); - data_buf = root_hub_dev_des; OK(len); - case (0x02): /* configuration descriptor */ - len = min (leni, min (sizeof (root_hub_config_des), wLength)); - data_buf = root_hub_config_des; OK(len); - case (0x03): /* string descriptors */ - default: - status = TD_CC_STALL; - } - break; - - case RH_GET_DESCRIPTOR | RH_CLASS: - *(__u8 *) (data_buf+1) = 0x29; - *(__u32 *) (data_buf+2) = cpu_to_le32 (readl (&ohci->regs->roothub.a)); - *(__u8 *) data_buf = (*(__u8 *) (data_buf + 2) / 8) * 2 + 9; /* length of descriptor */ - - len = min (leni, min(*(__u8 *) data_buf, wLength)); - *(__u8 *) (data_buf+6) = 0; /* Root Hub needs no current from bus */ - if (*(__u8 *) (data_buf+2) < 8) { /* less than 8 Ports */ - *(__u8 *) (data_buf+7) = readl (&ohci->regs->roothub.b) & 0xff; - *(__u8 *) (data_buf+8) = (readl (&ohci->regs->roothub.b) & 0xff0000) >> 16; - } else { - *(__u32 *) (data_buf+7) = cpu_to_le32 (readl(&ohci->regs->roothub.b)); - } - OK (len); - - case RH_GET_CONFIGURATION: *(__u8 *) data_buf = 0x01; OK (1); - - case RH_SET_CONFIGURATION: WR_RH_STAT (0x10000); OK (0); - - default: - status = TD_CC_STALL; - } - - dbg("USB HC roothubstat1: %x", readl ( &(ohci->regs->roothub.portstatus[0]) )); - dbg("USB HC roothubstat2: %x", readl ( &(ohci->regs->roothub.portstatus[1]) )); - - len = min(len, leni); - memcpy (data, data_buf, len); - urb->actual_length = len; - urb->status = cc_to_error [status]; - -#ifdef DEBUG - urb_print (urb, "RET(rh)", usb_pipeout (urb->pipe)); -#endif - - if (urb->complete) urb->complete (urb); - return 0; -} - -/*-------------------------------------------------------------------------*/ - -static int rh_unlink_urb (urb_t * urb) -{ - ohci_t * ohci = urb->dev->bus->hcpriv; - - ohci->rh.send = 0; - del_timer (&ohci->rh.rh_int_timer); - return 0; -} - -/*-------------------------------------------------------------------------* - * HC functions - *-------------------------------------------------------------------------*/ - -/* reset the HC not the BUS */ - -static void hc_reset (ohci_t * ohci) -{ - int timeout = 30; - int smm_timeout = 50; /* 0,5 sec */ - - if (readl (&ohci->regs->control) & 0x100) { /* SMM owns the HC */ - writel (0x08, &ohci->regs->cmdstatus); /* request ownership */ - dbg("USB HC TakeOver from SMM"); - while (readl (&ohci->regs->control) & 0x100) { - wait_ms (10); - if (--smm_timeout == 0) { - err("USB HC TakeOver failed!"); - break; - } - } - } - - writel ((1 << 31), &ohci->regs->intrdisable); /* Disable HC interrupts */ - dbg("USB HC reset_hc: %x ;", readl (&ohci->regs->control)); - /* this seems to be needed for the lucent controller on powerbooks.. */ - writel (0, &ohci->regs->control); /* Move USB to reset state */ - - writel (1, &ohci->regs->cmdstatus); /* HC Reset */ - while ((readl (&ohci->regs->cmdstatus) & 0x01) != 0) { /* 10us Reset */ - if (--timeout == 0) { - err("USB HC reset timed out!"); - return; - } - udelay (1); - } -} - -/*-------------------------------------------------------------------------*/ - -/* Start an OHCI controller, set the BUS operational - * enable interrupts - * connect the virtual root hub */ - -static int hc_start (ohci_t * ohci) -{ - unsigned int mask; - unsigned int fminterval; - struct usb_device * usb_dev; - struct ohci_device * dev; - - /* Tell the controller where the control and bulk lists are - * The lists are empty now. */ - - writel (0, &ohci->regs->ed_controlhead); - writel (0, &ohci->regs->ed_bulkhead); - - writel (virt_to_bus (&ohci->hcca), &ohci->regs->hcca); /* a reset clears this */ - - fminterval = 0x2edf; - writel ((fminterval * 9) / 10, &ohci->regs->periodicstart); - fminterval |= ((((fminterval - 210) * 6) / 7) << 16); - writel (fminterval, &ohci->regs->fminterval); - writel (0x628, &ohci->regs->lsthresh); - - /* Choose the interrupts we care about now, others later on demand */ - mask = OHCI_INTR_MIE | OHCI_INTR_WDH | OHCI_INTR_SO; - - 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 */ - - usb_dev = usb_alloc_dev (NULL, ohci->bus); - if (!usb_dev) return -1; - - dev = usb_to_ohci (usb_dev); - ohci->bus->root_hub = usb_dev; - usb_connect (usb_dev); - if (usb_new_device (usb_dev) != 0) { - usb_free_dev (usb_dev); - return -1; - } - - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* an interrupt happens */ - -static void hc_interrupt (int irq, void * __ohci, struct pt_regs * r) -{ - ohci_t * ohci = __ohci; - struct ohci_regs * regs = ohci->regs; - int ints; - - 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) - return; - } - - dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca.frame_no)); - - if (ints & OHCI_INTR_WDH) { - writel (OHCI_INTR_WDH, ®s->intrdisable); - dl_done_list (ohci, dl_reverse_done_list (ohci)); - writel (OHCI_INTR_WDH, ®s->intrenable); - } - - if (ints & OHCI_INTR_SO) { - dbg("USB Schedule overrun"); - writel (OHCI_INTR_SO, ®s->intrenable); - } - - if (ints & OHCI_INTR_SF) { - unsigned int frame = le16_to_cpu (ohci->hcca.frame_no) & 1; - writel (OHCI_INTR_SF, ®s->intrdisable); - if (ohci->ed_rm_list[!frame] != NULL) { - dl_del_list (ohci, !frame); - } - if (ohci->ed_rm_list[frame] != NULL) writel (OHCI_INTR_SF, ®s->intrenable); - } - writel (ints, ®s->intrstatus); - writel (OHCI_INTR_MIE, ®s->intrenable); -} - -/*-------------------------------------------------------------------------*/ - -/* allocate OHCI */ - -static ohci_t * hc_alloc_ohci (void * mem_base) -{ - int i; - ohci_t * ohci; - struct usb_bus * bus; - - ohci = (ohci_t *) __get_free_pages (GFP_KERNEL, 1); - if (!ohci) - return NULL; - - memset (ohci, 0, sizeof (ohci_t)); - - ohci->irq = -1; - ohci->regs = mem_base; - - /* for load ballancing of the interrupt branches */ - for (i = 0; i < NUM_INTS; i++) ohci->ohci_int_load[i] = 0; - for (i = 0; i < NUM_INTS; i++) ohci->hcca.int_table[i] = 0; - - /* end of control and bulk lists */ - ohci->ed_isotail = NULL; - ohci->ed_controltail = NULL; - ohci->ed_bulktail = NULL; - - bus = usb_alloc_bus (&sohci_device_operations); - if (!bus) { - free_pages ((unsigned long) ohci, 1); - return NULL; - } - - ohci->bus = bus; - bus->hcpriv = (void *) ohci; - - return ohci; -} - -/*-------------------------------------------------------------------------*/ - -/* De-allocate all resources.. */ - -static void hc_release_ohci (ohci_t * ohci) -{ - dbg("USB HC release ohci"); - - /* disconnect all devices */ - if (ohci->bus->root_hub) usb_disconnect (&ohci->bus->root_hub); - - hc_reset (ohci); - writel (OHCI_USB_RESET, &ohci->regs->control); - wait_ms (10); - - if (ohci->irq >= 0) { - free_irq (ohci->irq, ohci); - ohci->irq = -1; - } - - usb_deregister_bus (ohci->bus); - usb_free_bus (ohci->bus); - - /* unmap the IO address space */ - iounmap (ohci->regs); - - free_pages ((unsigned long) ohci, 1); -} - -/*-------------------------------------------------------------------------*/ - -/* Increment the module usage count, start the control thread and - * return success. */ - -static int hc_found_ohci (int irq, void * mem_base) -{ - ohci_t * ohci; - dbg("USB HC found: irq= %d membase= %lx", irq, (unsigned long) mem_base); - - ohci = hc_alloc_ohci (mem_base); - if (!ohci) { - return -ENOMEM; - } - - INIT_LIST_HEAD (&ohci->ohci_hcd_list); - list_add (&ohci->ohci_hcd_list, &ohci_hcd_list); - - hc_reset (ohci); - writel (ohci->hc_control = OHCI_USB_RESET, &ohci->regs->control); - wait_ms (10); - usb_register_bus (ohci->bus); - - if (request_irq (irq, hc_interrupt, SA_SHIRQ, "ohci-usb", ohci) == 0) { - ohci->irq = irq; - hc_start (ohci); - return 0; - } - err("request interrupt %d failed", irq); - hc_release_ohci (ohci); - return -EBUSY; -} - -/*-------------------------------------------------------------------------*/ - -static int hc_start_ohci (struct pci_dev * dev) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - unsigned long mem_base = dev->resource[0].start; -#else - 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 long) ioremap_nocache (mem_base, 4096); - - if (!mem_base) { - err("Error mapping OHCI memory"); - return -EFAULT; - } - return hc_found_ohci (dev->irq, (void *) mem_base); -} - -/*-------------------------------------------------------------------------*/ - -#ifdef CONFIG_PMAC_PBOOK - -/* On Powerbooks, put the controller into suspend mode when going - * to sleep, and do a resume when waking up. */ - -static int ohci_sleep_notify (struct pmu_sleep_notifier * self, int when) -{ - struct list_head * ohci_l; - ohci_t * ohci; - - for (ohci_l = ohci_hcd_list.next; ohci_l != &ohci_hcd_list; ohci_l = ohci_l->next) { - ohci = list_entry (ohci_l, ohci_t, ohci_hcd_list); - - switch (when) { - case PBOOK_SLEEP_NOW: - disable_irq (ohci->irq); - writel (ohci->hc_control = OHCI_USB_SUSPEND, &ohci->regs->control); - wait_ms (10); - break; - case PBOOK_WAKE: - writel (ohci->hc_control = OHCI_USB_RESUME, &ohci->regs->control); - wait_ms (20); - writel (ohci->hc_control = 0xBF, &ohci->regs->control); - enable_irq (ohci->irq); - break; - } - } - return PBOOK_SLEEP_OK; -} - -static struct pmu_sleep_notifier ohci_sleep_notifier = { - ohci_sleep_notify, SLEEP_LEVEL_MISC, -}; -#endif /* CONFIG_PMAC_PBOOK */ - -/*-------------------------------------------------------------------------*/ - -#ifdef CONFIG_APM -static int handle_apm_event (apm_event_t event) -{ - static int down = 0; - ohci_t * ohci; - struct list_head * ohci_l; - - switch (event) { - case APM_SYS_SUSPEND: - case APM_USER_SUSPEND: - if (down) { - dbg("received extra suspend event"); - break; - } - for (ohci_l = ohci_hcd_list.next; ohci_l != &ohci_hcd_list; ohci_l = ohci_l->next) { - ohci = list_entry (ohci_l, ohci_t, ohci_hcd_list); - dbg("USB-Bus suspend: %p", ohci); - writel (ohci->hc_control = 0xFF, &ohci->regs->control); - } - wait_ms (10); - down = 1; - break; - case APM_NORMAL_RESUME: - case APM_CRITICAL_RESUME: - if (!down) { - dbg("received bogus resume event"); - break; - } - for (ohci_l = ohci_hcd_list.next; ohci_l != &ohci_hcd_list; ohci_l = ohci_l->next) { - ohci = list_entry(ohci_l, ohci_t, ohci_hcd_list); - dbg("USB-Bus resume: %p", ohci); - writel (ohci->hc_control = 0x7F, &ohci->regs->control); - } - wait_ms (20); - for (ohci_l = ohci_hcd_list.next; ohci_l != &ohci_hcd_list; ohci_l = ohci_l->next) { - ohci = list_entry (ohci_l, ohci_t, ohci_hcd_list); - writel (ohci->hc_control = 0xBF, &ohci->regs->control); - } - down = 0; - break; - } - return 0; -} -#endif - -/*-------------------------------------------------------------------------*/ - -#define PCI_CLASS_SERIAL_USB_OHCI 0x0C0310 - -int ohci_hcd_init (void) -{ - int ret = -ENODEV; - struct pci_dev * dev = NULL; - - while ((dev = pci_find_class (PCI_CLASS_SERIAL_USB_OHCI, dev))) { - if (hc_start_ohci(dev) >= 0) ret = 0; - } - -#ifdef CONFIG_APM - apm_register_callback (&handle_apm_event); -#endif - -#ifdef CONFIG_PMAC_PBOOK - pmu_register_sleep_notifier (&ohci_sleep_notifier); -#endif - return ret; -} - -/*-------------------------------------------------------------------------*/ - -#ifdef MODULE -int init_module (void) -{ - return ohci_hcd_init (); -} - -/*-------------------------------------------------------------------------*/ - -void cleanup_module (void) -{ - ohci_t * ohci; - -#ifdef CONFIG_APM - apm_unregister_callback (&handle_apm_event); -#endif - -#ifdef CONFIG_PMAC_PBOOK - pmu_unregister_sleep_notifier (&ohci_sleep_notifier); -#endif - - while (!list_empty (&ohci_hcd_list)) { - ohci = list_entry (ohci_hcd_list.next, ohci_t, ohci_hcd_list); - list_del (&ohci->ohci_hcd_list); - INIT_LIST_HEAD (&ohci->ohci_hcd_list); - hc_release_ohci (ohci); - } -} -#endif //MODULE - diff --git a/drivers/usb/ohci-hcd.h b/drivers/usb/ohci-hcd.h deleted file mode 100644 index f3d71154f..000000000 --- a/drivers/usb/ohci-hcd.h +++ /dev/null @@ -1,407 +0,0 @@ - /* - * URB OHCI HCD (Host Controller Driver) for USB. - * - *(C) Copyright 1999 Roman Weissgaerber - * - * ohci-hcd.h - * - */ - - -#define MODSTR "ohci: " - - -static int cc_to_error[16] = { - -/* mapping of the OHCI CC status to error codes */ -#ifdef USB_ST_CRC /* status codes */ - /* No Error */ USB_ST_NOERROR, - /* CRC Error */ USB_ST_CRC, - /* Bit Stuff */ USB_ST_BITSTUFF, - /* Data Togg */ USB_ST_CRC, - /* Stall */ USB_ST_STALL, - /* DevNotResp */ USB_ST_NORESPONSE, - /* PIDCheck */ USB_ST_BITSTUFF, - /* UnExpPID */ USB_ST_BITSTUFF, - /* DataOver */ USB_ST_DATAOVERRUN, - /* DataUnder */ USB_ST_DATAUNDERRUN, - /* reservd */ USB_ST_NORESPONSE, - /* reservd */ USB_ST_NORESPONSE, - /* BufferOver */ USB_ST_BUFFEROVERRUN, - /* BuffUnder */ USB_ST_BUFFERUNDERRUN, - /* Not Access */ USB_ST_NORESPONSE, - /* Not Access */ USB_ST_NORESPONSE -}; - -#else /* error codes */ - /* No Error */ 0, - /* CRC Error */ -EILSEQ, - /* Bit Stuff */ -EPROTO, - /* Data Togg */ -EILSEQ, - /* Stall */ -EPIPE, - /* DevNotResp */ -ETIMEDOUT, - /* PIDCheck */ -EPROTO, - /* UnExpPID */ -EPROTO, - /* DataOver */ -EOVERFLOW, - /* DataUnder */ -EREMOTEIO, - /* reservd */ -ETIMEDOUT, - /* reservd */ -ETIMEDOUT, - /* BufferOver */ -ECOMM, - /* BuffUnder */ -ECOMM, - /* Not Access */ -ETIMEDOUT, - /* Not Access */ -ETIMEDOUT -}; -#define USB_ST_URB_PENDING -EINPROGRESS -#endif - - - -struct ed; -struct td; -/* for ED and TD structures */ - -/* ED States */ - -#define ED_NEW 0x00 -#define ED_UNLINK 0x01 -#define ED_OPER 0x02 -#define ED_DEL 0x04 -#define ED_URB_DEL 0x08 - -/* usb_ohci_ed */ -typedef struct ed { - __u32 hwINFO; - __u32 hwTailP; - __u32 hwHeadP; - __u32 hwNextED; - - struct ed * ed_prev; - __u8 int_period; - __u8 int_branch; - __u8 int_load; - __u8 int_interval; - __u8 state; - __u8 type; - __u16 last_iso; - struct ed * ed_rm_list; - -} ed_t; - - -/* TD info field */ -#define TD_CC 0xf0000000 -#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f) -#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28) -#define TD_EC 0x0C000000 -#define TD_T 0x03000000 -#define TD_T_DATA0 0x02000000 -#define TD_T_DATA1 0x03000000 -#define TD_T_TOGGLE 0x00000000 -#define TD_R 0x00040000 -#define TD_DI 0x00E00000 -#define TD_DI_SET(X) (((X) & 0x07)<< 21) -#define TD_DP 0x00180000 -#define TD_DP_SETUP 0x00000000 -#define TD_DP_IN 0x00100000 -#define TD_DP_OUT 0x00080000 - -#define TD_ISO 0x00010000 -#define TD_DEL 0x00020000 - -/* CC Codes */ -#define TD_CC_NOERROR 0x00 -#define TD_CC_CRC 0x01 -#define TD_CC_BITSTUFFING 0x02 -#define TD_CC_DATATOGGLEM 0x03 -#define TD_CC_STALL 0x04 -#define TD_DEVNOTRESP 0x05 -#define TD_PIDCHECKFAIL 0x06 -#define TD_UNEXPECTEDPID 0x07 -#define TD_DATAOVERRUN 0x08 -#define TD_DATAUNDERRUN 0x09 -#define TD_BUFFEROVERRUN 0x0C -#define TD_BUFFERUNDERRUN 0x0D -#define TD_NOTACCESSED 0x0F - - -#define MAXPSW 1 - -typedef struct td { - __u32 hwINFO; - __u32 hwCBP; /* Current Buffer Pointer */ - __u32 hwNextTD; /* Next TD Pointer */ - __u32 hwBE; /* Memory Buffer End Pointer */ - __u16 hwPSW[MAXPSW]; - - __u8 type; - __u8 index; - struct ed * ed; - struct td * next_dl_td; - urb_t * urb; -} td_t; - - -/* TD types */ -#define BULK 0x03 -#define INT 0x01 -#define CTRL 0x02 -#define ISO 0x00 - -#define SEND 0x01 -#define ST_ADDR 0x02 -#define ADD_LEN 0x04 -#define DEL 0x08 - - -#define OHCI_ED_SKIP (1 << 14) - -/* - * The HCCA (Host Controller Communications Area) is a 256 byte - * structure defined in the OHCI spec. that the host controller is - * told the base address of. It must be 256-byte aligned. - */ - -#define NUM_INTS 32 /* part of the OHCI standard */ -struct ohci_hcca { - __u32 int_table[NUM_INTS]; /* Interrupt ED table */ - __u16 frame_no; /* current frame number */ - __u16 pad1; /* set to 0 on each frame_no change */ - __u32 done_head; /* info returned for an interrupt */ - u8 reserved_for_hc[116]; -} __attribute((aligned(256))); - - -/* - * Maximum number of root hub ports. - */ -#define MAX_ROOT_PORTS 15 /* maximum OHCI root hub ports */ - -/* - * This is the structure of the OHCI controller's memory mapped I/O - * region. This is Memory Mapped I/O. You must use the readl() and - * writel() macros defined in asm/io.h to access these!! - */ -struct ohci_regs { - /* control and status registers */ - __u32 revision; - __u32 control; - __u32 cmdstatus; - __u32 intrstatus; - __u32 intrenable; - __u32 intrdisable; - /* memory pointers */ - __u32 hcca; - __u32 ed_periodcurrent; - __u32 ed_controlhead; - __u32 ed_controlcurrent; - __u32 ed_bulkhead; - __u32 ed_bulkcurrent; - __u32 donehead; - /* frame counters */ - __u32 fminterval; - __u32 fmremaining; - __u32 fmnumber; - __u32 periodicstart; - __u32 lsthresh; - /* Root hub ports */ - struct ohci_roothub_regs { - __u32 a; - __u32 b; - __u32 status; - __u32 portstatus[MAX_ROOT_PORTS]; - } roothub; -} __attribute((aligned(32))); - -/* - * cmdstatus register */ -#define OHCI_CLF 0x02 -#define OHCI_BLF 0x04 - -/* - * Interrupt register masks - */ -#define OHCI_INTR_SO (1) -#define OHCI_INTR_WDH (1 << 1) -#define OHCI_INTR_SF (1 << 2) -#define OHCI_INTR_RD (1 << 3) -#define OHCI_INTR_UE (1 << 4) -#define OHCI_INTR_FNO (1 << 5) -#define OHCI_INTR_RHSC (1 << 6) -#define OHCI_INTR_OC (1 << 30) -#define OHCI_INTR_MIE (1 << 31) - -/* - * Control register masks - */ -#define OHCI_USB_RESET 0 -#define OHCI_USB_RESUME (1 << 6) -#define OHCI_USB_OPER (2 << 6) -#define OHCI_USB_SUSPEND (3 << 6) - - -/* Virtual Root HUB */ -struct virt_root_hub { - int devnum; /* Address of Root Hub endpoint */ - void * urb; - void * int_addr; - int send; - int interval; - struct timer_list rh_int_timer; -}; - -/* destination of request */ -#define RH_INTERFACE 0x01 -#define RH_ENDPOINT 0x02 -#define RH_OTHER 0x03 - -#define RH_CLASS 0x20 -#define RH_VENDOR 0x40 - -/* Requests: bRequest << 8 | bmRequestType */ -#define RH_GET_STATUS 0x0080 -#define RH_CLEAR_FEATURE 0x0100 -#define RH_SET_FEATURE 0x0300 -#define RH_SET_ADDRESS 0x0500 -#define RH_GET_DESCRIPTOR 0x0680 -#define RH_SET_DESCRIPTOR 0x0700 -#define RH_GET_CONFIGURATION 0x0880 -#define RH_SET_CONFIGURATION 0x0900 -#define RH_GET_STATE 0x0280 -#define RH_GET_INTERFACE 0x0A80 -#define RH_SET_INTERFACE 0x0B00 -#define RH_SYNC_FRAME 0x0C80 -/* Our Vendor Specific Request */ -#define RH_SET_EP 0x2000 - - -/* Hub port features */ -#define RH_PORT_CONNECTION 0x00 -#define RH_PORT_ENABLE 0x01 -#define RH_PORT_SUSPEND 0x02 -#define RH_PORT_OVER_CURRENT 0x03 -#define RH_PORT_RESET 0x04 -#define RH_PORT_POWER 0x08 -#define RH_PORT_LOW_SPEED 0x09 -#define RH_C_PORT_CONNECTION 0x10 -#define RH_C_PORT_ENABLE 0x11 -#define RH_C_PORT_SUSPEND 0x12 -#define RH_C_PORT_OVER_CURRENT 0x13 -#define RH_C_PORT_RESET 0x14 - -/* Hub features */ -#define RH_C_HUB_LOCAL_POWER 0x00 -#define RH_C_HUB_OVER_CURRENT 0x01 - -#define RH_DEVICE_REMOTE_WAKEUP 0x00 -#define RH_ENDPOINT_STALL 0x01 - -#define RH_ACK 0x01 -#define RH_REQ_ERR -1 -#define RH_NACK 0x00 - -/* Root-Hub Register info */ - -#define RH_PS_CCS 0x00000001 -#define RH_PS_PES 0x00000002 -#define RH_PS_PSS 0x00000004 -#define RH_PS_POCI 0x00000008 -#define RH_PS_PRS 0x00000010 -#define RH_PS_PPS 0x00000100 -#define RH_PS_LSDA 0x00000200 -#define RH_PS_CSC 0x00010000 -#define RH_PS_PESC 0x00020000 -#define RH_PS_PSSC 0x00040000 -#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)) - - -/* urb */ -typedef struct -{ - ed_t * ed; - __u16 length; // number of tds associated with this request - __u16 td_cnt; // number of tds already serviced - int state; - void * wait; - td_t * td[0]; // list pointer to all corresponding TDs associated with this request - -} urb_priv_t; -#define URB_DEL 1 - -/* - * This is the full ohci controller description - * - * Note how the "proper" USB information is just - * a subset of what the full implementation needs. (Linus) - */ - - -typedef struct ohci { - struct ohci_hcca hcca; /* hcca */ - - int irq; - struct ohci_regs * regs; /* OHCI controller's memory */ - struct list_head ohci_hcd_list; /* list of all ohci_hcd */ - - struct ohci * next; // chain of uhci device contexts - struct list_head urb_list; // list of all pending urbs - spinlock_t urb_list_lock; // lock to keep consistency - - int ohci_int_load[32]; /* load of the 32 Interrupt Chains (for load ballancing)*/ - ed_t * ed_rm_list[2]; /* lists of all endpoints to be removed */ - ed_t * ed_bulktail; /* last endpoint of bulk list */ - ed_t * ed_controltail; /* last endpoint of control list */ - ed_t * ed_isotail; /* last endpoint of iso list */ - int intrstatus; - __u32 hc_control; /* copy of the hc control reg */ - struct usb_bus * bus; - struct usb_device * dev[128]; - struct virt_root_hub rh; -} ohci_t; - - -#define NUM_TDS 0 /* num of preallocated transfer descriptors */ -#define NUM_EDS 32 /* num of preallocated endpoint descriptors */ - -struct ohci_device { - ed_t ed[NUM_EDS]; - int ed_cnt; - void * wait; -}; - -// #define ohci_to_usb(ohci) ((ohci)->usb) -#define usb_to_ohci(usb) ((struct ohci_device *)(usb)->hcpriv) - -/* hcd */ -/* endpoint */ -static int ep_link(ohci_t * ohci, ed_t * ed); -static int ep_unlink(ohci_t * ohci, ed_t * ed); -static ed_t * ep_add_ed(struct usb_device * usb_dev, unsigned int pipe, int interval, int load); -static void ep_rm_ed(struct usb_device * usb_dev, ed_t * ed); -/* td */ -static void td_fill(unsigned int info, void * data, int len, urb_t * urb, int type, int index); -static void td_submit_urb(urb_t * urb); -/* root hub */ -static int rh_submit_urb(urb_t * urb); -static int rh_unlink_urb(urb_t * urb); -static int rh_init_int_timer(urb_t * urb); - -#ifdef DEBUG -#define OHCI_FREE(x) kfree(x); printk("OHCI FREE: %d: %4x\n", -- __ohci_free_cnt, (unsigned int) x) -#define OHCI_ALLOC(x,size) (x) = kmalloc(size, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); printk("OHCI ALLO: %d: %4x\n", ++ __ohci_free_cnt,(unsigned int) x) -static int __ohci_free_cnt = 0; -#else -#define OHCI_FREE(x) kfree(x) -#define OHCI_ALLOC(x,size) (x) = kmalloc(size, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL) -#endif - diff --git a/drivers/usb/ov511.c b/drivers/usb/ov511.c index c26f96132..6ec72d502 100644 --- a/drivers/usb/ov511.c +++ b/drivers/usb/ov511.c @@ -1,6 +1,6 @@ /* * OmniVision OV511 Camera-to-USB Bridge Driver - * Copyright 1999 Mark W. McClelland + * Copyright 1999/2000 Mark W. McClelland * * Based on the Linux CPiA driver. * @@ -11,7 +11,7 @@ * DEBUG - Debugging code. * FIXME - Something that is broken or needs improvement. * - * Version: 1.05 + * Version: 1.06 * * Please see the file: linux/Documentation/usb/ov511.txt * and the website at: http://people.delphi.com/mmcclelland/linux/ @@ -533,7 +533,7 @@ static int ov511_mode_init_regs(struct usb_ov511 *ov511, 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, 0x26, 0x00); /* was 0x70 */ ov511_i2c_write(dev, 0x28, 0x24); /* 24 */ ov511_i2c_write(dev, 0x2b, 0xac); ov511_i2c_write(dev, 0x2c, 0xfe); @@ -737,20 +737,16 @@ static int ov511_move_data(struct usb_ov511 *ov511, urb_t *urb) int aPackNum[10]; struct ov511_frame *frame; - if (ov511->curframe == -1) { - return 0; - } - for (i = 0; i < urb->number_of_packets; i++) { int n = urb->iso_frame_desc[i].actual_length; int st = urb->iso_frame_desc[i].status; - + urb->iso_frame_desc[i].actual_length = 0; + urb->iso_frame_desc[i].status = 0; cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset; - if (!n) continue; - aPackNum[i] = n ? cdata[992] : -1; + if (!n || ov511->curframe == -1) continue; if (st) PDEBUG("data error: [%d] len=%d, status=%d", i, n, st); @@ -767,14 +763,27 @@ static int ov511_move_data(struct usb_ov511 *ov511, urb_t *urb) #endif if (frame->scanstate == STATE_LINES) { + int iFrameNext; if (waitqueue_active(&frame->wq)) { #if 0 PDEBUG("About to wake up waiting processes"); #endif frame->grabstate = FRAME_DONE; - ov511->curframe = -1; wake_up_interruptible(&frame->wq); } + /* If next frame is ready or grabbing, point to it */ + iFrameNext = (ov511->curframe + 1) % OV511_NUMFRAMES; + if (ov511->frame[iFrameNext].grabstate== FRAME_READY || + ov511->frame[iFrameNext].grabstate== FRAME_GRABBING) { + ov511->curframe = iFrameNext; + frame->scanstate = STATE_SCANNING; + } else { +#if 0 + PDEBUG("Frame not ready? state = %d", + ov511->frame[iFrameNext].grabstate); +#endif + ov511->curframe = -1; + } } } @@ -1624,6 +1633,9 @@ static void* ov511_probe(struct usb_device *dev, unsigned int ifnum) case 102: printk("ov511: Camera is a AverMedia InterCam Elite\n"); break; + case 112: + printk("ov511: Camera is a MediaForte MV300\n"); + break; default: err("Specific camera type (%d) not recognized", rc); err("Please contact mmcclelland@delphi.com to request"); diff --git a/drivers/usb/scanner.c b/drivers/usb/scanner.c index 97399bc2d..ec45a6fb9 100644 --- a/drivers/usb/scanner.c +++ b/drivers/usb/scanner.c @@ -1,7 +1,11 @@ /* -*- linux-c -*- */ /* - * Driver for USB Scanners (linux-2.3.33) + * Driver for USB Scanners (linux-2.3.41) + * + * Copyright (C) 1999, 2000 David E. Nelson + * + * Portions may be copyright Brad Keryan and Michael Gee. * * David E. Nelson (dnelson@jump.net) * @@ -19,9 +23,10 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Based upon mouse.c (Brad Keryan) and printer.c (Michael Gee). + * Originally based upon mouse.c (Brad Keryan) and printer.c (Michael Gee). * * History + * * 0.1 8/31/1999 * * Developed/tested using linux-2.3.15 with minor ohci.c changes to @@ -30,18 +35,18 @@ * testing was performed with uhci but I was unable to get it to * work. Initial relase to the linux-usb development effort. * + * * 0.2 10/16/1999 * - * FIXED: * - Device can't be opened unless a scanner is plugged into the USB. * - Finally settled on a reasonable value for the I/O buffer's. * - Cleaned up write_scanner() * - Disabled read/write stats * - A little more code cleanup * + * * 0.3 10/18/1999 * - * FIXED: * - Device registration changed to reflect new device * allocation/registration for linux-2.3.22+. * - Adopted David Brownell's technique for @@ -52,19 +57,21 @@ * - Added user specified verdor:product USB ID's which can be passed * as module parameters. * + * * 0.3.1 - * FIXED: + * * - Applied patches for linux-2.3.25. * - Error number reporting changed to reflect negative return codes. * + * * 0.3.2 - * FIXED: + * * - Applied patches for linux-2.3.26 to scanner_init(). * - Debug read/write stats now report values as signed decimal. * * * 0.3.3 - * FIXED: + * * - Updated the bulk_msg() calls to usb usb_bulk_msg(). * - Added a small delay in the write_scanner() method to aid in * avoiding NULL data reads on HP scanners. We'll see how this works. @@ -75,13 +82,42 @@ * - kfree()'d the pointer after using usb_string() as documented in * linux-usb-api.txt. * - Added usb_set_configuration(). It got lost in version 0.3 -- ack! - * - Added the HP 5200C USB Vendor/Product ID's + * - Added the HP 5200C USB Vendor/Product ID's. + * + * + * 0.3.4 + * + * - Added Greg K-H's patch for better handling of + * Product/Vendor detection. + * - The driver now autoconfigures its endpoints including interrupt + * endpoints if one is detected. The concept was originally based + * upon David Brownell's method. + * - Added some Seiko/Epson ID's. Thanks to Karl Heinz + * Kremer . + * - Added some preliminary ioctl() calls for the PV8630 which is used + * by the HP4200. The ioctl()'s still have to be registered. Thanks + * to Adrian Perez Jorge . + * - Moved/migrated stuff to scanner.h + * - Removed the usb_set_configuration() since this is handled by + * the usb_new_device() routine in usb.c. + * - Added the HP 3300C. Thanks to Bruce Tenison. + * - Changed user specified vendor/product id so that root hub doesn't + * get falsely attached to. Thanks to Greg K-H. + * - Added some Mustek ID's. Thanks to Gernot Hoyler + * . + * - Modified the usb_string() reporting. See kfree() comment above. + * - Added Umax Astra 2000U. Thanks to Doug Alcorn. + * - Updated the printk()'s to use the info/warn/dbg macros. + * - Updated usb_bulk_msg() argument types to correct gcc warnings. + * * * TODO + * * - Simultaneous multiple device attachment - * - ioctl()'s ? + * * * Thanks to: + * * - All the folks on the linux-usb list who put up with me. :) This * has been a great learning experience for me. * - To Linus Torvalds for this great OS. @@ -90,58 +126,28 @@ * - And anybody else who chimed in with reports and suggestions. * * Performance: + * * System: Pentium 120, 80 MB RAM, OHCI, Linux 2.3.23, HP 4100C USB Scanner * 300 dpi scan of the entire bed * 24 Bit Color ~ 70 secs - 3.6 Mbit/sec * 8 Bit Gray ~ 17 secs - 4.2 Mbit/sec * */ -#include -#include -#include -#include -#include -#include - -#undef DEBUG /* Enable to print results of read/write_scanner() calls */ -#undef RD_DATA_DUMP /* Enable to dump data - limited to 24 bytes */ -#undef WR_DATA_DUMP - -#include "usb.h" - -#define IBUF_SIZE 32768 -#define OBUF_SIZE 4096 - -struct hpscan_usb_data { - struct usb_device *hpscan_dev; - int isopen; /* Not zero if the device is open */ - int present; /* Device is present on the bus */ - char *obuf, *ibuf; /* transfer buffers */ - char iep, oep; /* I/O Endpoints */ -}; - -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=0x05f9, 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"); +#include "scanner.h" static int open_scanner(struct inode * inode, struct file * file) { struct hpscan_usb_data *hps = &hpscan; + struct usb_device *dev; - if (!hps->present) { + dev = hps->hpscan_dev; + + if (!dev) { return -ENODEV; } - if (!hps->hpscan_dev) { + if (!hps->present) { return -ENODEV; } @@ -173,18 +179,18 @@ write_scanner(struct file * file, const char * buffer, size_t count, loff_t *ppos) { struct hpscan_usb_data *hps = &hpscan; - - unsigned long copy_size; - unsigned long bytes_written = 0; - unsigned long partial; - + struct usb_device *dev; + + ssize_t bytes_written = 0; ssize_t ret = 0; + int copy_size; + int partial; int result = 0; char *obuf = hps->obuf; - set_current_state(TASK_INTERRUPTIBLE); + dev = hps->hpscan_dev; while (count > 0) { @@ -200,8 +206,8 @@ write_scanner(struct file * file, const char * buffer, break; } - result = usb_bulk_msg(hps->hpscan_dev,usb_sndbulkpipe(hps->hpscan_dev, hps->oep), obuf, copy_size, &partial, 30*HZ); - dbg("write stats: result:%d copy_size:%lu partial:%lu", (int)result, copy_size, partial); + result = usb_bulk_msg(dev,usb_sndbulkpipe(dev, hps->bulk_out_ep), obuf, copy_size, &partial, 60*HZ); + dbg("write stats: result:%d copy_size:%d partial:%d", result, copy_size, partial); if (result == USB_ST_TIMEOUT) { /* NAK -- shouldn't happen */ warn("write_scanner: NAK recieved."); @@ -217,7 +223,7 @@ write_scanner(struct file * file, const char * buffer, if (partial) { unsigned char cnt, cnt_max; cnt_max = (partial > 24) ? 24 : partial; - printk(KERN_DEBUG __FILE__ ": dump: "); + printk(KERN_DEBUG "dump: "); for (cnt=0; cnt < cnt_max; cnt++) { printk("%X ", obuf[cnt]); } @@ -239,8 +245,7 @@ write_scanner(struct file * file, const char * buffer, break; } } -// mdelay(5); - set_current_state(TASK_RUNNING); + mdelay(5); return ret ? ret : bytes_written; } @@ -249,18 +254,19 @@ read_scanner(struct file * file, char * buffer, size_t count, loff_t *ppos) { struct hpscan_usb_data *hps = &hpscan; + struct usb_device *dev; ssize_t read_count, ret = 0; - unsigned long partial; - + int partial; int this_read; int result; char *ibuf = hps->ibuf; + dev = hps->hpscan_dev; + read_count = 0; - set_current_state(TASK_INTERRUPTIBLE); while (count) { if (signal_pending(current)) { @@ -270,8 +276,8 @@ read_scanner(struct file * file, char * buffer, this_read = (count > IBUF_SIZE) ? IBUF_SIZE : count; - result = usb_bulk_msg(hps->hpscan_dev, usb_rcvbulkpipe(hps->hpscan_dev, hps->iep), ibuf, this_read, &partial, 60*HZ); - dbg("read stats: result:%d this_read:%u partial:%lu", (int)result, this_read, partial); + result = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, hps->bulk_in_ep), ibuf, this_read, &partial, 60*HZ); + dbg("read stats: result:%d this_read:%d partial:%d", result, this_read, partial); if (result == USB_ST_TIMEOUT) { /* NAK -- shouldn't happen */ warn("read_scanner: NAK received"); @@ -287,7 +293,7 @@ read_scanner(struct file * file, char * buffer, if (partial) { unsigned char cnt, cnt_max; cnt_max = (partial > 24) ? 24 : partial; - printk(KERN_DEBUG __FILE__ ": dump: "); + printk(KERN_DEBUG "dump: "); for (cnt=0; cnt < cnt_max; cnt++) { printk("%X ", ibuf[cnt]); } @@ -313,7 +319,6 @@ read_scanner(struct file * file, char * buffer, buffer += this_read; } } - set_current_state(TASK_RUNNING); return ret ? ret : read_count; } @@ -321,103 +326,174 @@ static void * probe_scanner(struct usb_device *dev, unsigned int ifnum) { struct hpscan_usb_data *hps = &hpscan; + struct usb_interface_descriptor *interface; struct usb_endpoint_descriptor *endpoint; + + int ep_cnt; char *ident; + char valid_device = 0; + char have_bulk_in, have_bulk_out, have_intr; hps->present = 0; - if (vendor != 0 || product != 0) - info("USB Scanner Vendor:Product - %x:%x\n", vendor, product); + if (vendor != -1 && product != -1) { + info("probe_scanner: User specified USB scanner -- Vendor:Product - %x:%x", vendor, product); + } + +/* + * 1. Check Vendor/Product + * 2. Determine/Assign Bulk Endpoints + * 3. Determine/Assign Intr Endpoint + */ -/* There doesn't seem to be an imaging class defined in the USB +/* + * There doesn't seem to be an imaging class defined in the USB * Spec. (yet). If there is, HP isn't following it and it doesn't * look like anybody else is either. Therefore, we have to test the - * Vendor and Product ID's to see what we have. This makes this - * driver a high maintenance driver since it has to be updated with - * each release of a product. Also, other scanners may be able to use - * this driver but again, their Vendor and Product ID's must be added. + * Vendor and Product ID's to see what we have. Also, other scanners + * may be able to use this driver by specifying both vendor and + * product ID's as options to the scanner module in conf.modules. * * NOTE: Just because a product is supported here does not mean that * applications exist that support the product. It's in the hopes * that this will allow developers a means to produce applications * that will support USB products. * - * Until we detect a device which is pleasing, we silently punt. - * */ + * Until we detect a device which is pleasing, we silently punt. */ + + do { + if (dev->descriptor.idVendor == 0x03f0) { /* Hewlett Packard */ + if (dev->descriptor.idProduct == 0x0205 || /* 3300C */ + dev->descriptor.idProduct == 0x0101 || /* 4100C */ + dev->descriptor.idProduct == 0x0105 || /* 4200C */ + dev->descriptor.idProduct == 0x0202 || /* PhotoSmart S20 */ + dev->descriptor.idProduct == 0x0401 || /* 5200C */ + dev->descriptor.idProduct == 0x0201 || /* 6200C */ + dev->descriptor.idProduct == 0x0601) { /* 6300C */ + valid_device = 1; + break; + } + } + + if (dev->descriptor.idVendor == 0x06bd && /* AGFA */ + dev->descriptor.idProduct == 0x0001) { /* SnapScan 1212U */ + valid_device = 1; + break; + } + + if (dev->descriptor.idVendor == 0x1606 && /* Umax */ + dev->descriptor.idProduct == 0x0030) { /* Astra 2000U */ + valid_device = 1; + break; + } + + if (dev->descriptor.idVendor == 0x04b8) { /* Seiko/Epson Corp. */ + if (dev->descriptor.idProduct == 0x0101 || /* Perfection 636 */ + dev->descriptor.idProduct == 0x0104) { /* Perfection 1200U */ + valid_device = 1; + break; + } + } - if (dev->descriptor.idVendor != 0x03f0 && /* Hewlett Packard */ - dev->descriptor.idVendor != 0x06bd && /* AGFA */ - dev->descriptor.idVendor != 0x1606 && /* UMAX */ - dev->descriptor.idVendor != vendor ) { /* User specified */ - return NULL; - } + if (dev->descriptor.idVendor == 0x055f) { /* Mustek */ + if (dev->descriptor.idProduct == 0x0001) { /* 1200 CU */ + valid_device = 1; + break; + } + } - if (dev->descriptor.idProduct != 0x0101 && /* HP 4100C */ - dev->descriptor.idProduct != 0x0102 && /* HP 4200C & PhotoSmart S20? */ - dev->descriptor.idProduct != 0x0202 && /* HP 5100C */ - dev->descriptor.idProduct != 0x0401 && /* HP 5200C */ - dev->descriptor.idProduct != 0x0201 && /* HP 6200C */ - dev->descriptor.idProduct != 0x0601 && /* HP 6300C */ - dev->descriptor.idProduct != 0x0001 && /* AGFA SnapScan 1212U */ - dev->descriptor.idProduct != 0x0030 && /* Umax 2000U */ - dev->descriptor.idProduct != product) { /* User specified */ + if (dev->descriptor.idVendor == vendor && /* User specified */ + dev->descriptor.idProduct == product) { /* User specified */ + valid_device = 1; + break; + } + } while (0); + + if (!valid_device) return NULL; - } -/* After this point we can be a little noisy about what we are trying to - * configure. */ - if (dev->descriptor.bNumConfigurations != 1 || - dev->config[0].bNumInterfaces != 1) { - dbg("probe_scanner: only simple configurations supported"); +/* + * After this point we can be a little noisy about what we are trying to + * configure. + */ + + if (dev->descriptor.bNumConfigurations != 1) { + info("probe_scanner: Only one configuration is supported."); return NULL; } - endpoint = dev->config[0].interface[0].altsetting[0].endpoint; - - if (endpoint[0].bmAttributes != USB_ENDPOINT_XFER_BULK - || endpoint [1].bmAttributes != USB_ENDPOINT_XFER_BULK) { - dbg("probe_scanner: invalid bulk endpoints"); + if (dev->config[0].bNumInterfaces != 1) { + info("probe_scanner: Only one interface is supported."); return NULL; } - if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) { - dbg("probe_scanner: failed usb_set_configuration"); - hps->hpscan_dev = NULL; - return NULL; - } + interface = dev->config[0].interface[0].altsetting; + endpoint = interface[0].endpoint; -/* By the time we get here, we should be dealing with a fairly simple - * device that supports at least two bulk endpoints on endpoints 1 and - * 2. - * - * We determine the bulk endpoints so that the read_*() and write_*() - * procedures can recv/send data to the correct endpoint. - * */ +/* + * Start checking for two bulk endpoints OR two bulk endpoints *and* one + * interrupt endpoint. If we have an interrupt endpoint go ahead and + * setup the handler. FIXME: This is a future enhancement... + */ - hps->iep = hps->oep = 0; - if ((endpoint[0].bEndpointAddress & 0x80) == 0x80) { - hps->iep = endpoint[0].bEndpointAddress & 0x7f; - } else { - hps->oep = endpoint[0].bEndpointAddress; - } + dbg("probe_scanner: Number of Endpoints: %d", (int) interface->bNumEndpoints); - if ((endpoint[1].bEndpointAddress & 0x80) == 0x80) { - hps->iep = endpoint[1].bEndpointAddress & 0x7f; - } else { - hps->oep = endpoint[1].bEndpointAddress; + if ((interface->bNumEndpoints != 2) && (interface->bNumEndpoints != 3)) { + info("probe_scanner: Only two or three endpoints supported."); + return NULL; } - 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); + ep_cnt = have_bulk_in = have_bulk_out = have_intr = 0; + + while (ep_cnt < interface->bNumEndpoints) { + + if (!have_bulk_in && IS_EP_BULK_IN(endpoint[ep_cnt])) { + have_bulk_in = 1; + hps->bulk_in_ep = ep_cnt + 1; + ep_cnt++; + dbg("probe_scanner: bulk_in_ep: %d", (int)hps->bulk_in_ep); + continue; + } + + if (!have_bulk_out && IS_EP_BULK_OUT(endpoint[ep_cnt])) { + have_bulk_out = 1; + hps->bulk_out_ep = ep_cnt + 1; + ep_cnt++; + dbg("probe_scanner: bulk_out_ep: %d", (int)hps->bulk_out_ep); + continue; + } + + if (!have_intr && IS_EP_INTR(endpoint[ep_cnt])) { + have_intr = 1; + hps->intr_ep = ep_cnt + 1; + ep_cnt++; + dbg("probe_scanner: intr_ep: %d", (int)hps->intr_ep); + continue; + } + info("probe_scanner: Undetected endpoint. Notify the maintainer."); + return NULL; /* Shouldn't ever get here unless we have something weird */ } - dbg("probe_scanner: using bulk endpoints - In: %x Out: %x", hps->iep, hps->oep); + switch(interface->bNumEndpoints) { + case 2: + if (!have_bulk_in || !have_bulk_out) { + info("probe_scanner: Two bulk endpoints required."); + return NULL; + } + break; + case 3: + if (!have_bulk_in || !have_bulk_out || !have_intr) { + info("probe_scanner: Two bulk endpoints and one interrupt endpoint required."); + return NULL; + } + break; + default: + info("probe_scanner: Endpoint determination failed. Notify the maintainer."); + return NULL; + } hps->present = 1; hps->hpscan_dev = dev; @@ -449,6 +525,71 @@ disconnect_scanner(struct usb_device *dev, void *ptr) hps->present = 0; } +static int +ioctl_scanner(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct hpscan_usb_data *hps = &hpscan; + struct usb_device *dev; + + int result; + + dev = hps->hpscan_dev; + + switch (cmd) + { + case PV8630_RECEIVE : + { + struct { + unsigned char data; + __u16 value; + __u16 index; + } args; + + if (copy_from_user(&args, (void *)arg, sizeof(args))) + return -EFAULT; + + result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 0x0, + USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_DIR_IN, + args.value, args.index, &args.data, 1, HZ); + + dbg("ioctl_scanner recv: args.data:%x args.value:%x args.index:%x", + args.data, args.value, args.index); + + if (copy_to_user((void *)arg, &args, sizeof(args))) + return -EFAULT; + + dbg("ioctl_scanner recv: result:%d", result); + + return result; + } + case PV8630_SEND : + { + struct { + __u16 value; + __u16 index; + } args; + + if (copy_from_user(&args, (void *)arg, sizeof(args))) + return -EFAULT; + + dbg("ioctl_scanner send: args.value:%x args.index:%x", args.value, args.index); + + result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0x1 /* Vendor Specific bRequest */, + USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_DIR_OUT /* 0x40 */, + args.value, args.index, NULL, 0, HZ); + + dbg("ioctl_scanner send: result:%d", result); + + + return result; + } + default: + return -ENOIOCTLCMD; + } + return 0; +} + static struct file_operations usb_scanner_fops = { NULL, /* seek */ @@ -456,7 +597,7 @@ file_operations usb_scanner_fops = { write_scanner, NULL, /* readdir */ NULL, /* poll */ - NULL, /* ioctl */ + ioctl_scanner, /* ioctl */ NULL, /* mmap */ open_scanner, NULL, /* flush */ diff --git a/drivers/usb/scanner.h b/drivers/usb/scanner.h new file mode 100644 index 000000000..996eb7f59 --- /dev/null +++ b/drivers/usb/scanner.h @@ -0,0 +1,55 @@ +#include +#include +#include +#include +#include +#include +#include + +// #define DEBUG + +#include "usb.h" + +// #define RD_DATA_DUMP /* Enable to dump data - limited to 24 bytes */ +// #define WR_DATA_DUMP /* DEBUG does not have to be defined. */ + +#define IS_EP_BULK(ep) ((ep).bmAttributes == USB_ENDPOINT_XFER_BULK ? 1 : 0) +#define IS_EP_BULK_IN(ep) (IS_EP_BULK(ep) && ((ep).bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) +#define IS_EP_BULK_OUT(ep) (IS_EP_BULK(ep) && ((ep).bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) +#define IS_EP_INTR(ep) ((ep).bmAttributes == USB_ENDPOINT_XFER_INT ? 1 : 0) + +#ifdef DEBUG +#define SCN_DEBUG(X) X +#else +#define SCN_DEBUG(X) +#endif + +#define IBUF_SIZE 32768 +#define OBUF_SIZE 4096 + + +/* FIXME: These are NOT registered ioctls()'s */ + +#define PV8630_RECEIVE 69 +#define PV8630_SEND 70 + +struct hpscan_usb_data { + struct usb_device *hpscan_dev; + int isopen; /* Not zero if the device is open */ + int present; /* Device is present on the bus */ + char *obuf, *ibuf; /* transfer buffers */ + char bulk_in_ep, bulk_out_ep, intr_ep; /* Endpoint assignments */ + char *button; /* Front panel button buffer */ +}; + +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 __s32 vendor=-1, product=-1; +MODULE_PARM(vendor, "i"); +MODULE_PARM_DESC(vendor, "User specified USB idVendor"); + +MODULE_PARM(product, "i"); +MODULE_PARM_DESC(product, "User specified USB idProduct"); diff --git a/drivers/usb/uhci-debug.c b/drivers/usb/uhci-debug.c deleted file mode 100644 index 2ecd611e6..000000000 --- a/drivers/usb/uhci-debug.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - * $Id: uhci-debug.c,v 1.12 1999/12/13 15:24:42 fliegl Exp $ - */ - -#include -#include -#include - -#define DEBUG - -#include "usb.h" -#include "uhci.h" - -void dump_urb (purb_t purb) -{ - dbg("urb :%p", purb); - dbg("next :%p", purb->next); - dbg("dev :%p", purb->dev); - dbg("pipe :%08X", purb->pipe); - dbg("status :%d", purb->status); - dbg("transfer_flags :%08X", purb->transfer_flags); - dbg("transfer_buffer :%p", purb->transfer_buffer); - dbg("transfer_buffer_length:%d", purb->transfer_buffer_length); - dbg("actual_length :%d", purb->actual_length); - dbg("setup_packet :%p", purb->setup_packet); - dbg("start_frame :%d", purb->start_frame); - dbg("number_of_packets :%d", purb->number_of_packets); - dbg("interval :%d", purb->interval); - dbg("error_count :%d", purb->error_count); - dbg("context :%p", purb->context); - dbg("complete :%p", purb->complete); -} - -void beep (long freq) -{ - long v; - char low, high; - - if (!freq) - outb (inb (0x61) & 252, 0x61); - else { - outb (inb (0x61) | 0x3, 0x61); - - v = 1193180L / freq; - - low = (char) (v & 255); - high = (char) ((v >> 8) & 255); - - outb (182, 0x43); - outb (low, 0x42); - outb (high, 0x42); - } -} - -void uhci_show_qh (puhci_desc_t qh) -{ - if (qh->type != QH_TYPE) { - dbg("qh has not QH_TYPE"); - return; - } - dbg("uhci_show_qh %p (%08lX):", qh, virt_to_bus (qh)); - - if (qh->hw.qh.head & UHCI_PTR_TERM) - dbg("Head Terminate"); - else { - if (qh->hw.qh.head & UHCI_PTR_QH) - dbg("Head points to QH"); - else - dbg("Head points to TD"); - - dbg("head: %08X", qh->hw.qh.head & ~UHCI_PTR_BITS); - } - if (qh->hw.qh.element & UHCI_PTR_TERM) - dbg("Element Terminate"); - else { - - if (qh->hw.qh.element & UHCI_PTR_QH) - dbg("Element points to QH"); - else - dbg("Element points to TD"); - dbg("element: %08X", qh->hw.qh.element & ~UHCI_PTR_BITS); - } -} - -void uhci_show_td (puhci_desc_t td) -{ - char *spid; - - switch (td->hw.td.info & 0xff) { - case USB_PID_SETUP: - spid = "SETUP"; - break; - case USB_PID_OUT: - spid = " OUT "; - break; - case USB_PID_IN: - spid = " IN "; - break; - default: - spid = " ? "; - break; - } - - dbg("uhci_show_td %p (%08lX) MaxLen=%02x DT%d EndPt=%x Dev=%x, PID=%x(%s) (buf=%08x)", - td, - virt_to_bus(td), - td->hw.td.info >> 21, - ((td->hw.td.info >> 19) & 1), - (td->hw.td.info >> 15) & 15, - (td->hw.td.info >> 8) & 127, - (td->hw.td.info & 0xff), - spid, - td->hw.td.buffer); - - dbg("Len=%02x e%d %s%s%s%s%s%s%s%s%s%s", - td->hw.td.status & 0x7ff, - ((td->hw.td.status >> 27) & 3), - (td->hw.td.status & TD_CTRL_SPD) ? "SPD " : "", - (td->hw.td.status & TD_CTRL_LS) ? "LS " : "", - (td->hw.td.status & TD_CTRL_IOC) ? "IOC " : "", - (td->hw.td.status & TD_CTRL_ACTIVE) ? "Active " : "", - (td->hw.td.status & TD_CTRL_STALLED) ? "Stalled " : "", - (td->hw.td.status & TD_CTRL_DBUFERR) ? "DataBufErr " : "", - (td->hw.td.status & TD_CTRL_BABBLE) ? "Babble " : "", - (td->hw.td.status & TD_CTRL_NAK) ? "NAK " : "", - (td->hw.td.status & TD_CTRL_CRCTIMEO) ? "CRC/Timeo " : "", - (td->hw.td.status & TD_CTRL_BITSTUFF) ? "BitStuff " : "" - ); - - if (td->hw.td.link & UHCI_PTR_TERM) - dbg("Link Terminate"); - else { - if (td->hw.td.link & UHCI_PTR_QH) - dbg("%s, link points to QH @ %08x", - (td->hw.td.link & UHCI_PTR_DEPTH ? "Depth first" : " Breadth first"), - td->hw.td.link & ~UHCI_PTR_BITS); - else - dbg("%s, link points to TD @ %08x", - (td->hw.td.link & UHCI_PTR_DEPTH ? "Depth first" : " Breadth first"), - td->hw.td.link & ~UHCI_PTR_BITS); - } -} - -void uhci_show_td_queue (puhci_desc_t td) -{ - dbg("uhci_show_td_queue %p (%08lX):", td, virt_to_bus (td)); - while (1) { - uhci_show_td (td); - if (td->hw.td.link & UHCI_PTR_TERM) - break; - //if(!(td->hw.td.link&UHCI_PTR_DEPTH)) - // break; - if (td != bus_to_virt (td->hw.td.link & ~UHCI_PTR_BITS)) - td = bus_to_virt (td->hw.td.link & ~UHCI_PTR_BITS); - else { - dbg("td points to itself!"); - break; - } -// schedule(); - } -} - -void uhci_show_queue (puhci_desc_t qh) -{ - dbg("uhci_show_queue %p:", qh); - while (1) { - uhci_show_qh (qh); - - if (qh->hw.qh.element & UHCI_PTR_QH) - dbg("Warning: qh->element points to qh!"); - else if (!(qh->hw.qh.element & UHCI_PTR_TERM)) - uhci_show_td_queue (bus_to_virt (qh->hw.qh.element & ~UHCI_PTR_BITS)); - - if (qh->hw.qh.head & UHCI_PTR_TERM) - break; - - if (qh != bus_to_virt (qh->hw.qh.head & ~UHCI_PTR_BITS)) - qh = bus_to_virt (qh->hw.qh.head & ~UHCI_PTR_BITS); - else { - dbg("qh points to itself!"); - break; - } - } -} - -static void uhci_show_sc (int port, unsigned short status) -{ - dbg(" stat%d = %04x %s%s%s%s%s%s%s%s", - port, - status, - (status & USBPORTSC_SUSP) ? "PortSuspend " : "", - (status & USBPORTSC_PR) ? "PortReset " : "", - (status & USBPORTSC_LSDA) ? "LowSpeed " : "", - (status & USBPORTSC_RD) ? "ResumeDetect " : "", - (status & USBPORTSC_PEC) ? "EnableChange " : "", - (status & USBPORTSC_PE) ? "PortEnabled " : "", - (status & USBPORTSC_CSC) ? "ConnectChange " : "", - (status & USBPORTSC_CCS) ? "PortConnected " : ""); -} - -void uhci_show_status (puhci_t s) -{ - unsigned int io_addr = s->io_addr; - unsigned short usbcmd, usbstat, usbint, usbfrnum; - unsigned int flbaseadd; - unsigned char sof; - unsigned short portsc1, portsc2; - - usbcmd = inw (io_addr + 0); - usbstat = inw (io_addr + 2); - usbint = inw (io_addr + 4); - usbfrnum = inw (io_addr + 6); - flbaseadd = inl (io_addr + 8); - sof = inb (io_addr + 12); - portsc1 = inw (io_addr + 16); - portsc2 = inw (io_addr + 18); - - dbg(" usbcmd = %04x %s%s%s%s%s%s%s%s", - usbcmd, - (usbcmd & USBCMD_MAXP) ? "Maxp64 " : "Maxp32 ", - (usbcmd & USBCMD_CF) ? "CF " : "", - (usbcmd & USBCMD_SWDBG) ? "SWDBG " : "", - (usbcmd & USBCMD_FGR) ? "FGR " : "", - (usbcmd & USBCMD_EGSM) ? "EGSM " : "", - (usbcmd & USBCMD_GRESET) ? "GRESET " : "", - (usbcmd & USBCMD_HCRESET) ? "HCRESET " : "", - (usbcmd & USBCMD_RS) ? "RS " : ""); - - dbg(" usbstat = %04x %s%s%s%s%s%s", - usbstat, - (usbstat & USBSTS_HCH) ? "HCHalted " : "", - (usbstat & USBSTS_HCPE) ? "HostControllerProcessError " : "", - (usbstat & USBSTS_HSE) ? "HostSystemError " : "", - (usbstat & USBSTS_RD) ? "ResumeDetect " : "", - (usbstat & USBSTS_ERROR) ? "USBError " : "", - (usbstat & USBSTS_USBINT) ? "USBINT " : ""); - - dbg(" usbint = %04x", usbint); - dbg(" usbfrnum = (%d)%03x", (usbfrnum >> 10) & 1, - 0xfff & (4 * (unsigned int) usbfrnum)); - dbg(" flbaseadd = %08x", flbaseadd); - dbg(" sof = %02x", sof); - uhci_show_sc (1, portsc1); - uhci_show_sc (2, portsc2); -} diff --git a/drivers/usb/uhci-debug.h b/drivers/usb/uhci-debug.h index aebc836aa..73d16937a 100644 --- a/drivers/usb/uhci-debug.h +++ b/drivers/usb/uhci-debug.h @@ -1,7 +1,195 @@ -void uhci_show_qh(puhci_desc_t qh); -void uhci_show_td(puhci_desc_t td); -void uhci_show_td_queue(puhci_desc_t td); -void uhci_show_queue(puhci_desc_t qh); -void uhci_show_status(puhci_t s); -void beep(long freq); -void dump_urb (purb_t purb); \ No newline at end of file +#ifdef DEBUG + +static void uhci_show_qh (puhci_desc_t qh) +{ + if (qh->type != QH_TYPE) { + dbg("qh has not QH_TYPE"); + return; + } + dbg("uhci_show_qh %p (%08lX):", qh, virt_to_bus (qh)); + + if (qh->hw.qh.head & UHCI_PTR_TERM) + dbg("Head Terminate"); + else { + if (qh->hw.qh.head & UHCI_PTR_QH) + dbg("Head points to QH"); + else + dbg("Head points to TD"); + + dbg("head: %08X", qh->hw.qh.head & ~UHCI_PTR_BITS); + } + if (qh->hw.qh.element & UHCI_PTR_TERM) + dbg("Element Terminate"); + else { + + if (qh->hw.qh.element & UHCI_PTR_QH) + dbg("Element points to QH"); + else + dbg("Element points to TD"); + dbg("element: %08X", qh->hw.qh.element & ~UHCI_PTR_BITS); + } +} +#endif + +static void uhci_show_td (puhci_desc_t td) +{ + char *spid; + warn("uhci_show_td %p (%08lX) ", td, virt_to_bus (td)); + + switch (td->hw.td.info & 0xff) { + case USB_PID_SETUP: + spid = "SETUP"; + break; + case USB_PID_OUT: + spid = " OUT "; + break; + case USB_PID_IN: + spid = " IN "; + break; + default: + spid = " ? "; + break; + } + + warn("MaxLen=%02x DT%d EndPt=%x Dev=%x, PID=%x(%s) (buf=%08x)", + td->hw.td.info >> 21, + ((td->hw.td.info >> 19) & 1), + (td->hw.td.info >> 15) & 15, + (td->hw.td.info >> 8) & 127, + (td->hw.td.info & 0xff), + spid, + td->hw.td.buffer); + + warn("Len=%02x e%d %s%s%s%s%s%s%s%s%s%s", + td->hw.td.status & 0x7ff, + ((td->hw.td.status >> 27) & 3), + (td->hw.td.status & TD_CTRL_SPD) ? "SPD " : "", + (td->hw.td.status & TD_CTRL_LS) ? "LS " : "", + (td->hw.td.status & TD_CTRL_IOC) ? "IOC " : "", + (td->hw.td.status & TD_CTRL_ACTIVE) ? "Active " : "", + (td->hw.td.status & TD_CTRL_STALLED) ? "Stalled " : "", + (td->hw.td.status & TD_CTRL_DBUFERR) ? "DataBufErr " : "", + (td->hw.td.status & TD_CTRL_BABBLE) ? "Babble " : "", + (td->hw.td.status & TD_CTRL_NAK) ? "NAK " : "", + (td->hw.td.status & TD_CTRL_CRCTIMEO) ? "CRC/Timeo " : "", + (td->hw.td.status & TD_CTRL_BITSTUFF) ? "BitStuff " : "" + ); +#if 1 + if (td->hw.td.link & UHCI_PTR_TERM) + warn("Link Terminate"); + else { + if (td->hw.td.link & UHCI_PTR_QH) + warn("%s, link points to QH @ %08x", + (td->hw.td.link & UHCI_PTR_DEPTH ? "Depth first" : " Breadth first"), + td->hw.td.link & ~UHCI_PTR_BITS); + else + warn("%s, link points to TD @ %08x", + (td->hw.td.link & UHCI_PTR_DEPTH ? "Depth first" : " Breadth first"), + td->hw.td.link & ~UHCI_PTR_BITS); + } +#endif +} +#ifdef DEBUG +static void uhci_show_td_queue (puhci_desc_t td) +{ + dbg("uhci_show_td_queue %p (%08lX):", td, virt_to_bus (td)); + while (1) { + uhci_show_td (td); + if (td->hw.td.link & UHCI_PTR_TERM) + break; + //if(!(td->hw.td.link&UHCI_PTR_DEPTH)) + // break; + if (td != bus_to_virt (td->hw.td.link & ~UHCI_PTR_BITS)) + td = bus_to_virt (td->hw.td.link & ~UHCI_PTR_BITS); + else { + dbg("td points to itself!"); + break; + } +// schedule(); + } +} + +static void uhci_show_queue (puhci_desc_t qh) +{ + dbg("uhci_show_queue %p:", qh); + while (1) { + uhci_show_qh (qh); + + if (qh->hw.qh.element & UHCI_PTR_QH) + dbg("Warning: qh->element points to qh!"); + else if (!(qh->hw.qh.element & UHCI_PTR_TERM)) + uhci_show_td_queue (bus_to_virt (qh->hw.qh.element & ~UHCI_PTR_BITS)); + + if (qh->hw.qh.head & UHCI_PTR_TERM) + break; + + if (qh != bus_to_virt (qh->hw.qh.head & ~UHCI_PTR_BITS)) + qh = bus_to_virt (qh->hw.qh.head & ~UHCI_PTR_BITS); + else { + dbg("qh points to itself!"); + break; + } + } +} + +static void uhci_show_sc (int port, unsigned short status) +{ + dbg(" stat%d = %04x %s%s%s%s%s%s%s%s", + port, + status, + (status & USBPORTSC_SUSP) ? "PortSuspend " : "", + (status & USBPORTSC_PR) ? "PortReset " : "", + (status & USBPORTSC_LSDA) ? "LowSpeed " : "", + (status & USBPORTSC_RD) ? "ResumeDetect " : "", + (status & USBPORTSC_PEC) ? "EnableChange " : "", + (status & USBPORTSC_PE) ? "PortEnabled " : "", + (status & USBPORTSC_CSC) ? "ConnectChange " : "", + (status & USBPORTSC_CCS) ? "PortConnected " : ""); +} + +void uhci_show_status (puhci_t s) +{ + unsigned int io_addr = s->io_addr; + unsigned short usbcmd, usbstat, usbint, usbfrnum; + unsigned int flbaseadd; + unsigned char sof; + unsigned short portsc1, portsc2; + + usbcmd = inw (io_addr + 0); + usbstat = inw (io_addr + 2); + usbint = inw (io_addr + 4); + usbfrnum = inw (io_addr + 6); + flbaseadd = inl (io_addr + 8); + sof = inb (io_addr + 12); + portsc1 = inw (io_addr + 16); + portsc2 = inw (io_addr + 18); + + dbg(" usbcmd = %04x %s%s%s%s%s%s%s%s", + usbcmd, + (usbcmd & USBCMD_MAXP) ? "Maxp64 " : "Maxp32 ", + (usbcmd & USBCMD_CF) ? "CF " : "", + (usbcmd & USBCMD_SWDBG) ? "SWDBG " : "", + (usbcmd & USBCMD_FGR) ? "FGR " : "", + (usbcmd & USBCMD_EGSM) ? "EGSM " : "", + (usbcmd & USBCMD_GRESET) ? "GRESET " : "", + (usbcmd & USBCMD_HCRESET) ? "HCRESET " : "", + (usbcmd & USBCMD_RS) ? "RS " : ""); + + dbg(" usbstat = %04x %s%s%s%s%s%s", + usbstat, + (usbstat & USBSTS_HCH) ? "HCHalted " : "", + (usbstat & USBSTS_HCPE) ? "HostControllerProcessError " : "", + (usbstat & USBSTS_HSE) ? "HostSystemError " : "", + (usbstat & USBSTS_RD) ? "ResumeDetect " : "", + (usbstat & USBSTS_ERROR) ? "USBError " : "", + (usbstat & USBSTS_USBINT) ? "USBINT " : ""); + + dbg(" usbint = %04x", usbint); + dbg(" usbfrnum = (%d)%03x", (usbfrnum >> 10) & 1, + 0xfff & (4 * (unsigned int) usbfrnum)); + dbg(" flbaseadd = %08x", flbaseadd); + dbg(" sof = %02x", sof); + uhci_show_sc (1, portsc1); + uhci_show_sc (2, portsc2); +} +#endif diff --git a/drivers/usb/uhci.c b/drivers/usb/uhci.c deleted file mode 100644 index 09dc04283..000000000 --- a/drivers/usb/uhci.c +++ /dev/null @@ -1,2336 +0,0 @@ -/* - * Universal Host Controller Interface driver for USB (take II). - * - * (c) 1999 Georg Acher, acher@in.tum.de (executive slave) (base guitar) - * Deti Fliegl, deti@fliegl.de (executive slave) (lead voice) - * Thomas Sailer, sailer@ife.ee.ethz.ch (chief consultant) (cheer leader) - * Roman Weissgaerber, weissg@vienna.at (virt root hub) (studio porter) - * - * HW-initalization based on material of - * - * (C) Copyright 1999 Linus Torvalds - * (C) Copyright 1999 Johannes Erdfelt - * (C) Copyright 1999 Randy Dunlap - * - * $Id: uhci.c,v 1.149 1999/12/26 20:57:14 acher Exp $ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* for in_interrupt() */ -#include - -#include -#include -#include -#include - -#undef DEBUG - -#include "usb.h" -#include "uhci.h" -#include "uhci-debug.h" - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) -#define __init -#define __exit -#endif - -#ifdef __alpha -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) -extern long __kernel_thread (unsigned long, int (*)(void *), void *); -static inline long kernel_thread (int (*fn) (void *), void *arg, unsigned long flags) -{ - return __kernel_thread (flags | CLONE_VM, fn, arg); -} -#undef CONFIG_APM -#endif -#endif - -#ifdef CONFIG_APM -#include -static int handle_apm_event (apm_event_t event); -#endif - -/* We added an UHCI_SLAB slab support just for debugging purposes. In real - life this compile option is NOT recommended, because slab caches are not - suitable for modules. -*/ - -// #define _UHCI_SLAB -#ifdef _UHCI_SLAB -static kmem_cache_t *uhci_desc_kmem; -static kmem_cache_t *urb_priv_kmem; -#endif - -static int rh_submit_urb (purb_t purb); -static int rh_unlink_urb (purb_t purb); -static puhci_t devs = NULL; - -/*-------------------------------------------------------------------*/ -static void queue_urb (puhci_t s, struct list_head *p, int do_lock) -{ - unsigned long flags=0; - - if (do_lock) - spin_lock_irqsave (&s->urb_list_lock, flags); - - list_add_tail (p, &s->urb_list); - - if (do_lock) - spin_unlock_irqrestore (&s->urb_list_lock, flags); -} - -/*-------------------------------------------------------------------*/ -static void dequeue_urb (puhci_t s, struct list_head *p, int do_lock) -{ - unsigned long flags=0; - - if (do_lock) - spin_lock_irqsave (&s->urb_list_lock, flags); - - list_del (p); - - if (do_lock) - spin_unlock_irqrestore (&s->urb_list_lock, flags); -} - -/*-------------------------------------------------------------------*/ -static int alloc_td (puhci_desc_t * new, int flags) -{ -#ifdef _UHCI_SLAB - *new= kmem_cache_alloc(uhci_desc_kmem, in_interrupt ()? SLAB_ATOMIC : SLAB_KERNEL); -#else - *new = (uhci_desc_t *) kmalloc (sizeof (uhci_desc_t), in_interrupt ()? GFP_ATOMIC : GFP_KERNEL); -#endif - if (!*new) - return -ENOMEM; - - memset (*new, 0, sizeof (uhci_desc_t)); - (*new)->hw.td.link = UHCI_PTR_TERM | (flags & UHCI_PTR_BITS); // last by default - - (*new)->type = TD_TYPE; - INIT_LIST_HEAD (&(*new)->vertical); - INIT_LIST_HEAD (&(*new)->horizontal); - - return 0; -} -/*-------------------------------------------------------------------*/ -/* insert td at last position in td-list of qh (vertical) */ -static int insert_td (puhci_t s, puhci_desc_t qh, puhci_desc_t new, int flags) -{ - uhci_desc_t *prev; - unsigned long xxx; - - spin_lock_irqsave (&s->td_lock, xxx); - - list_add_tail (&new->vertical, &qh->vertical); - - if (qh->hw.qh.element & UHCI_PTR_TERM) { - // virgin qh without any tds - qh->hw.qh.element = virt_to_bus (new); /* QH's cannot have the DEPTH bit set */ - } - else { - // already tds inserted - prev = list_entry (new->vertical.prev, uhci_desc_t, vertical); - // implicitely remove TERM bit of prev - prev->hw.td.link = virt_to_bus (new) | (flags & UHCI_PTR_DEPTH); - } - - spin_unlock_irqrestore (&s->td_lock, xxx); - - return 0; -} -/*-------------------------------------------------------------------*/ -/* insert new_td after td (horizontal) */ -static int insert_td_horizontal (puhci_t s, puhci_desc_t td, puhci_desc_t new, int flags) -{ - uhci_desc_t *next; - unsigned long xxx; - - spin_lock_irqsave (&s->td_lock, xxx); - - next = list_entry (td->horizontal.next, uhci_desc_t, horizontal); - new->hw.td.link = td->hw.td.link; - list_add (&new->horizontal, &td->horizontal); - td->hw.td.link = virt_to_bus (new); - - spin_unlock_irqrestore (&s->td_lock, xxx); - - return 0; -} -/*-------------------------------------------------------------------*/ -static int unlink_td (puhci_t s, puhci_desc_t element) -{ - uhci_desc_t *next, *prev; - int dir = 0; - unsigned long xxx; - - spin_lock_irqsave (&s->td_lock, xxx); - - next = list_entry (element->vertical.next, uhci_desc_t, vertical); - - if (next == element) { - dir = 1; - next = list_entry (element->horizontal.next, uhci_desc_t, horizontal); - prev = list_entry (element->horizontal.prev, uhci_desc_t, horizontal); - } - else { - prev = list_entry (element->vertical.prev, uhci_desc_t, vertical); - } - - if (prev->type == TD_TYPE) - prev->hw.td.link = element->hw.td.link; - else - prev->hw.qh.element = element->hw.td.link; - - wmb (); - - if (dir == 0) - list_del (&element->vertical); - else - list_del (&element->horizontal); - - spin_unlock_irqrestore (&s->td_lock, xxx); - - return 0; -} -/*-------------------------------------------------------------------*/ -static int delete_desc (puhci_desc_t element) -{ -#ifdef _UHCI_SLAB - kmem_cache_free(uhci_desc_kmem, element); -#else - kfree (element); -#endif - return 0; -} -/*-------------------------------------------------------------------*/ -// Allocates qh element -static int alloc_qh (puhci_desc_t * new) -{ -#ifdef _UHCI_SLAB - *new= kmem_cache_alloc(uhci_desc_kmem, in_interrupt ()? SLAB_ATOMIC : SLAB_KERNEL); -#else - *new = (uhci_desc_t *) kmalloc (sizeof (uhci_desc_t), in_interrupt ()? GFP_ATOMIC : GFP_KERNEL); -#endif - if (!*new) - return -ENOMEM; - - memset (*new, 0, sizeof (uhci_desc_t)); - (*new)->hw.qh.head = UHCI_PTR_TERM; - (*new)->hw.qh.element = UHCI_PTR_TERM; - (*new)->type = QH_TYPE; - INIT_LIST_HEAD (&(*new)->horizontal); - INIT_LIST_HEAD (&(*new)->vertical); - - dbg("Allocated qh @ %p", *new); - - return 0; -} -/*-------------------------------------------------------------------*/ -// inserts new qh before/after the qh at pos -// flags: 0: insert before pos, 1: insert after pos (for low speed transfers) -static int insert_qh (puhci_t s, puhci_desc_t pos, puhci_desc_t new, int flags) -{ - puhci_desc_t old; - unsigned long xxx; - - spin_lock_irqsave (&s->qh_lock, xxx); - - if (!flags) { - // (OLD) (POS) -> (OLD) (NEW) (POS) - old = list_entry (pos->horizontal.prev, uhci_desc_t, horizontal); - list_add_tail (&new->horizontal, &pos->horizontal); - new->hw.qh.head = MAKE_QH_ADDR (pos) ; - - if (!(old->hw.qh.head & UHCI_PTR_TERM)) - old->hw.qh.head = MAKE_QH_ADDR (new) ; - } - else { - // (POS) (OLD) -> (POS) (NEW) (OLD) - old = list_entry (pos->horizontal.next, uhci_desc_t, horizontal); - list_add (&new->horizontal, &pos->horizontal); - pos->hw.qh.head = MAKE_QH_ADDR (new) ; - new->hw.qh.head = MAKE_QH_ADDR (old); - } - - wmb (); - - spin_unlock_irqrestore (&s->qh_lock, xxx); - - return 0; -} -/*-------------------------------------------------------------------*/ -static int unlink_qh (puhci_t s, puhci_desc_t element) -{ - puhci_desc_t next, prev; - unsigned long xxx; - - spin_lock_irqsave (&s->qh_lock, xxx); - - next = list_entry (element->horizontal.next, uhci_desc_t, horizontal); - prev = list_entry (element->horizontal.prev, uhci_desc_t, horizontal); - prev->hw.qh.head = element->hw.qh.head; - wmb (); - list_del (&element->horizontal); - - spin_unlock_irqrestore (&s->qh_lock, xxx); - - return 0; -} -/*-------------------------------------------------------------------*/ -static int delete_qh (puhci_t s, puhci_desc_t qh) -{ - puhci_desc_t td; - struct list_head *p; - - list_del (&qh->horizontal); - - while ((p = qh->vertical.next) != &qh->vertical) { - td = list_entry (p, uhci_desc_t, vertical); - unlink_td (s, td); - delete_desc (td); - } - - delete_desc (qh); - - return 0; -} -/*-------------------------------------------------------------------*/ -void clean_td_chain (puhci_desc_t td) -{ - struct list_head *p; - puhci_desc_t td1; - - if (!td) - return; - - while ((p = td->horizontal.next) != &td->horizontal) { - td1 = list_entry (p, uhci_desc_t, horizontal); - delete_desc (td1); - } - - delete_desc (td); -} -/*-------------------------------------------------------------------*/ -// Removes ALL qhs in chain (paranoia!) -static void cleanup_skel (puhci_t s) -{ - unsigned int n; - puhci_desc_t td; - - dbg("cleanup_skel"); - - for (n = 0; n < 8; n++) { - td = s->int_chain[n]; - clean_td_chain (td); - } - - if (s->iso_td) { - for (n = 0; n < 1024; n++) { - td = s->iso_td[n]; - clean_td_chain (td); - } - kfree (s->iso_td); - } - - if (s->framelist) - free_page ((unsigned long) s->framelist); - - if (s->control_chain) { - // completed init_skel? - struct list_head *p; - puhci_desc_t qh, qh1; - - qh = s->control_chain; - while ((p = qh->horizontal.next) != &qh->horizontal) { - qh1 = list_entry (p, uhci_desc_t, horizontal); - delete_qh (s, qh1); - } - delete_qh (s, qh); - } - else { - if (s->control_chain) - kfree (s->control_chain); - if (s->bulk_chain) - kfree (s->bulk_chain); - if (s->chain_end) - kfree (s->chain_end); - } -} -/*-------------------------------------------------------------------*/ -// allocates framelist and qh-skeletons -// only HW-links provide continous linking, SW-links stay in their domain (ISO/INT) -static int init_skel (puhci_t s) -{ - int n, ret; - puhci_desc_t qh, td; - - dbg("init_skel"); - - s->framelist = (__u32 *) get_free_page (GFP_KERNEL); - - if (!s->framelist) - return -ENOMEM; - - memset (s->framelist, 0, 4096); - - dbg("allocating iso desc pointer list"); - s->iso_td = (puhci_desc_t *) kmalloc (1024 * sizeof (puhci_desc_t), GFP_KERNEL); - - if (!s->iso_td) - goto init_skel_cleanup; - - s->control_chain = NULL; - s->bulk_chain = NULL; - s->chain_end = NULL; - - dbg("allocating iso descs"); - for (n = 0; n < 1024; n++) { - // allocate skeleton iso/irq-tds - ret = alloc_td (&td, 0); - if (ret) - goto init_skel_cleanup; - s->iso_td[n] = td; - s->framelist[n] = ((__u32) virt_to_bus (td)); - } - - dbg("allocating qh: chain_end"); - ret = alloc_qh (&qh); - - if (ret) - goto init_skel_cleanup; - - s->chain_end = qh; - - dbg("allocating qh: bulk_chain"); - ret = alloc_qh (&qh); - - if (ret) - goto init_skel_cleanup; - - insert_qh (s, s->chain_end, qh, 0); - s->bulk_chain = qh; - dbg("allocating qh: control_chain"); - ret = alloc_qh (&qh); - - if (ret) - goto init_skel_cleanup; - - insert_qh (s, s->bulk_chain, qh, 0); - s->control_chain = qh; - for (n = 0; n < 8; n++) - s->int_chain[n] = 0; - - dbg("allocating skeleton INT-TDs"); - - for (n = 0; n < 8; n++) { - puhci_desc_t td; - - alloc_td (&td, 0); - if (!td) - goto init_skel_cleanup; - s->int_chain[n] = td; - if (n == 0) { - s->int_chain[0]->hw.td.link = virt_to_bus (s->control_chain); - } - else { - s->int_chain[n]->hw.td.link = virt_to_bus (s->int_chain[0]); - } - } - - dbg("linking skeleton INT-TDs"); - - for (n = 0; n < 1024; n++) { - // link all iso-tds to the interrupt chains - int m, o; - //dbg("framelist[%i]=%x",n,s->framelist[n]); - for (o = 1, m = 2; m <= 128; o++, m += m) { - // n&(m-1) = n%m - if ((n & (m - 1)) == ((m - 1) / 2)) { - ((puhci_desc_t) s->iso_td[n])->hw.td.link = virt_to_bus (s->int_chain[o]); - } - } - } - - //uhci_show_queue(s->control_chain); - dbg("init_skel exit"); - return 0; // OK - - init_skel_cleanup: - cleanup_skel (s); - return -ENOMEM; -} - -/*-------------------------------------------------------------------*/ -static void fill_td (puhci_desc_t td, int status, int info, __u32 buffer) -{ - td->hw.td.status = status; - td->hw.td.info = info; - td->hw.td.buffer = buffer; -} - -/*-------------------------------------------------------------------*/ -// LOW LEVEL STUFF -// assembles QHs und TDs for control, bulk and iso -/*-------------------------------------------------------------------*/ -static int uhci_submit_control_urb (purb_t purb) -{ - puhci_desc_t qh, td; - puhci_t s = (puhci_t) purb->dev->bus->hcpriv; - purb_priv_t purb_priv = purb->hcpriv; - unsigned long destination, status; - int maxsze = usb_maxpacket (purb->dev, purb->pipe, usb_pipeout (purb->pipe)); - unsigned long len, bytesrequested; - char *data; - - dbg("uhci_submit_control start"); - alloc_qh (&qh); // alloc qh for this request - - if (!qh) - return -ENOMEM; - - alloc_td (&td, UHCI_PTR_DEPTH); // get td for setup stage - - if (!td) { - delete_qh (s, qh); - return -ENOMEM; - } - - /* The "pipe" thing contains the destination in bits 8--18 */ - destination = (purb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP; - - /* 3 errors */ - status = (purb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | - (purb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27); - - /* Build the TD for the control request, try forever, 8 bytes of data */ - fill_td (td, status, destination | (7 << 21), virt_to_bus (purb->setup_packet)); - - /* If direction is "send", change the frame from SETUP (0x2D) - to OUT (0xE1). Else change it from SETUP to IN (0x69). */ - - destination ^= (USB_PID_SETUP ^ USB_PID_IN); /* SETUP -> IN */ - - if (usb_pipeout (purb->pipe)) - destination ^= (USB_PID_IN ^ USB_PID_OUT); /* IN -> OUT */ - - insert_td (s, qh, td, 0); // queue 'setup stage'-td in qh -#if 0 - dbg("SETUP to pipe %x: %x %x %x %x %x %x %x %x", purb->pipe, - purb->setup_packet[0], purb->setup_packet[1], purb->setup_packet[2], purb->setup_packet[3], - purb->setup_packet[4], purb->setup_packet[5], purb->setup_packet[6], purb->setup_packet[7]); - //uhci_show_td(td); -#endif - /* Build the DATA TD's */ - len = purb->transfer_buffer_length; - bytesrequested = len; - data = purb->transfer_buffer; - - while (len > 0) { - int pktsze = len; - - alloc_td (&td, UHCI_PTR_DEPTH); - if (!td) { - delete_qh (s, qh); - return -ENOMEM; - } - - if (pktsze > maxsze) - pktsze = maxsze; - - destination ^= 1 << TD_TOKEN_TOGGLE; // toggle DATA0/1 - - fill_td (td, status, destination | ((pktsze - 1) << 21), - virt_to_bus (data)); // Status, pktsze bytes of data - - insert_td (s, qh, td, UHCI_PTR_DEPTH); // queue 'data stage'-td in qh - - data += pktsze; - len -= pktsze; - } - - /* Build the final TD for control status */ - /* It's only IN if the pipe is out AND we aren't expecting data */ - destination &= ~0xFF; - - if (usb_pipeout (purb->pipe) | (bytesrequested == 0)) - destination |= USB_PID_IN; - else - destination |= USB_PID_OUT; - - destination |= 1 << TD_TOKEN_TOGGLE; /* End in Data1 */ - - alloc_td (&td, UHCI_PTR_DEPTH); - - if (!td) { - delete_qh (s, qh); - return -ENOMEM; - } - - /* no limit on errors on final packet , 0 bytes of data */ - fill_td (td, status | TD_CTRL_IOC, destination | (UHCI_NULL_DATA_SIZE << 21), - 0); - - insert_td (s, qh, td, UHCI_PTR_DEPTH); // queue status td - - - list_add (&qh->desc_list, &purb_priv->desc_list); - - /* Start it up... put low speed first */ - if (purb->pipe & TD_CTRL_LS) - insert_qh (s, s->control_chain, qh, 1); // insert after control chain - else - insert_qh (s, s->bulk_chain, qh, 0); // insert before bulk chain - //uhci_show_queue(s->control_chain); - - dbg("uhci_submit_control end"); - return 0; -} -/*-------------------------------------------------------------------*/ -static int uhci_submit_bulk_urb (purb_t purb) -{ - puhci_t s = (puhci_t) purb->dev->bus->hcpriv; - purb_priv_t purb_priv = purb->hcpriv; - puhci_desc_t qh, td; - unsigned long destination, status; - char *data; - unsigned int pipe = purb->pipe; - int maxsze = usb_maxpacket (purb->dev, pipe, usb_pipeout (pipe)); - int info, len; - - /* shouldn't the clear_halt be done in the USB core or in the client driver? - Thomas */ - if (usb_endpoint_halted (purb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)) && - usb_clear_halt (purb->dev, usb_pipeendpoint (pipe) | (pipe & USB_DIR_IN))) - return -EPIPE; - - if (!maxsze) - return -EMSGSIZE; - /* FIXME: should tell the client that the endpoint is invalid, i.e. not in the descriptor */ - - alloc_qh (&qh); // get qh for this request - - if (!qh) - return -ENOMEM; - - /* The "pipe" thing contains the destination in bits 8--18. */ - destination = (pipe & PIPE_DEVEP_MASK) | usb_packetid (pipe); - - /* 3 errors */ - status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | - ((purb->transfer_flags & USB_DISABLE_SPD) ? 0 : TD_CTRL_SPD) | (3 << 27); - - /* Build the TDs for the bulk request */ - len = purb->transfer_buffer_length; - data = purb->transfer_buffer; - dbg("uhci_submit_bulk_urb: pipe %x, len %d", pipe, len); - - while (len > 0) { - int pktsze = len; - - alloc_td (&td, UHCI_PTR_DEPTH); - - if (!td) { - delete_qh (s, qh); - return -ENOMEM; - } - - if (pktsze > maxsze) - pktsze = maxsze; - - // pktsze bytes of data - info = destination | ((pktsze - 1) << 21) | - (usb_gettoggle (purb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)) << TD_TOKEN_TOGGLE); - - fill_td (td, status, info, virt_to_bus (data)); - - data += pktsze; - len -= pktsze; - - if (!len) - td->hw.td.status |= TD_CTRL_IOC; // last one generates INT - //dbg("insert td %p, len %i",td,pktsze); - - insert_td (s, qh, td, UHCI_PTR_DEPTH); - - /* Alternate Data0/1 (start with Data0) */ - usb_dotoggle (purb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)); - } - - list_add (&qh->desc_list, &purb_priv->desc_list); - - insert_qh (s, s->chain_end, qh, 0); // insert before end marker - //uhci_show_queue(s->bulk_chain); - - dbg("uhci_submit_bulk_urb: exit"); - return 0; -} -/*-------------------------------------------------------------------*/ -// unlinks an urb by dequeuing its qh, waits some frames and forgets it -// Problem: unlinking in interrupt requires waiting for one frame (udelay) -// to allow the whole structures to be safely removed -static int uhci_unlink_urb (purb_t purb) -{ - puhci_t s; - puhci_desc_t qh; - puhci_desc_t td; - purb_priv_t purb_priv; - unsigned long flags=0; - struct list_head *p; - - if (!purb) // you never know... - return -1; - - s = (puhci_t) purb->dev->bus->hcpriv; // get pointer to uhci struct - - if (usb_pipedevice (purb->pipe) == s->rh.devnum) - return rh_unlink_urb (purb); - - if(!in_interrupt()) { - // is the following really necessary? dequeue_urb has its own spinlock (GA) - spin_lock_irqsave (&s->unlink_urb_lock, flags); // do not allow interrupts - } - - //dbg("unlink_urb called %p",purb); - if (purb->status == USB_ST_URB_PENDING) { - // URB probably still in work - purb_priv = purb->hcpriv; - dequeue_urb (s, &purb->urb_list,1); - purb->status = USB_ST_URB_KILLED; // mark urb as killed - - if(!in_interrupt()) { - spin_unlock_irqrestore (&s->unlink_urb_lock, flags); // allow interrupts from here - } - - switch (usb_pipetype (purb->pipe)) { - case PIPE_ISOCHRONOUS: - case PIPE_INTERRUPT: - for (p = purb_priv->desc_list.next; p != &purb_priv->desc_list; p = p->next) { - td = list_entry (p, uhci_desc_t, desc_list); - unlink_td (s, td); - } - // wait at least 1 Frame - if (in_interrupt ()) - udelay (1000); - else - schedule_timeout (1 + 1 * HZ / 1000); - while ((p = purb_priv->desc_list.next) != &purb_priv->desc_list) { - td = list_entry (p, uhci_desc_t, desc_list); - list_del (p); - delete_desc (td); - } - break; - - case PIPE_BULK: - case PIPE_CONTROL: - qh = list_entry (purb_priv->desc_list.next, uhci_desc_t, desc_list); - - unlink_qh (s, qh); // remove this qh from qh-list - // wait at least 1 Frame - - if (in_interrupt ()) - udelay (1000); - else - schedule_timeout (1 + 1 * HZ / 1000); - delete_qh (s, qh); // remove it physically - - } - -#ifdef _UHCI_SLAB - kmem_cache_free(urb_priv_kmem, purb->hcpriv); -#else - kfree (purb->hcpriv); -#endif - if (purb->complete) { - dbg("unlink_urb: calling completion"); - purb->complete ((struct urb *) purb); - usb_dec_dev_use (purb->dev); - } - return 0; - } - else { - if(!in_interrupt()) - spin_unlock_irqrestore (&s->unlink_urb_lock, flags); // allow interrupts from here - } - - return 0; -} -/*-------------------------------------------------------------------*/ -// In case of ASAP iso transfer, search the URB-list for already queued URBs -// for this EP and calculate the earliest start frame for the new -// URB (easy seamless URB continuation!) -static int find_iso_limits (purb_t purb, unsigned int *start, unsigned int *end) -{ - purb_t u, last_urb = NULL; - puhci_t s = (puhci_t) purb->dev->bus->hcpriv; - struct list_head *p = s->urb_list.next; - int ret=-1; - unsigned long flags; - - spin_lock_irqsave (&s->urb_list_lock, flags); - - for (; p != &s->urb_list; p = p->next) { - u = list_entry (p, urb_t, urb_list); - // look for pending URBs with identical pipe handle - // works only because iso doesn't toggle the data bit! - if ((purb->pipe == u->pipe) && (purb->dev == u->dev) && (u->status == USB_ST_URB_PENDING)) { - if (!last_urb) - *start = u->start_frame; - last_urb = u; - } - } - - if (last_urb) { - *end = (last_urb->start_frame + last_urb->number_of_packets) & 1023; - ret=0; - } - - spin_unlock_irqrestore(&s->urb_list_lock, flags); - - return ret; // no previous urb found - -} -/*-------------------------------------------------------------------*/ -// adjust start_frame according to scheduling constraints (ASAP etc) - -static void jnx_show_desc (puhci_desc_t d) -{ - switch (d->type) { - case TD_TYPE: - dbg("td @ 0x%08lx: link 0x%08x status 0x%08x info 0x%08x buffer 0x%08x", - (unsigned long) d, d->hw.td.link, d->hw.td.status, d->hw.td.info, d->hw.td.buffer); - if (!(d->hw.td.link & UHCI_PTR_TERM)) - jnx_show_desc ((puhci_desc_t) bus_to_virt (d->hw.td.link & ~UHCI_PTR_BITS)); - break; - - case QH_TYPE: - dbg("qh @ 0x%08lx: head 0x%08x element 0x%08x", - (unsigned long) d, d->hw.qh.head, d->hw.qh.element); - if (!(d->hw.qh.element & UHCI_PTR_TERM)) - jnx_show_desc ((puhci_desc_t) bus_to_virt (d->hw.qh.element & ~UHCI_PTR_BITS)); - if (!(d->hw.qh.head & UHCI_PTR_TERM)) - jnx_show_desc ((puhci_desc_t) bus_to_virt (d->hw.qh.head & ~UHCI_PTR_BITS)); - break; - - default: - dbg("desc @ 0x%08lx: invalid type %u", (unsigned long) d, d->type); - } -} - -/*-------------------------------------------------------------------*/ -static int iso_find_start (purb_t purb) -{ - puhci_t s = (puhci_t) purb->dev->bus->hcpriv; - unsigned int now; - unsigned int start_limit = 0, stop_limit = 0, queued_size; - int limits; - - now = UHCI_GET_CURRENT_FRAME (s) & 1023; - - if ((unsigned) purb->number_of_packets > 900) - return -EFBIG; - - limits = find_iso_limits (purb, &start_limit, &stop_limit); - queued_size = (stop_limit - start_limit) & 1023; - - if (purb->transfer_flags & USB_ISO_ASAP) { - // first iso - if (limits) { - // 10ms setup should be enough //FIXME! - purb->start_frame = (now + 10) & 1023; - } - else { - purb->start_frame = stop_limit; //seamless linkage - - if (((now - purb->start_frame) & 1023) <= (unsigned) purb->number_of_packets) { - dbg("iso_find_start: warning, ASAP gap, should not happen"); - dbg("iso_find_start: now %u start_frame %u number_of_packets %u pipe 0x%08x", - now, purb->start_frame, purb->number_of_packets, purb->pipe); - { - puhci_t s = (puhci_t) purb->dev->bus->hcpriv; - struct list_head *p; - purb_t u; - int a = -1, b = -1; - unsigned long flags; - - spin_lock_irqsave (&s->urb_list_lock, flags); - p=s->urb_list.next; - - for (; p != &s->urb_list; p = p->next) { - u = list_entry (p, urb_t, urb_list); - if (purb->dev != u->dev) - continue; - dbg("urb: pipe 0x%08x status %d start_frame %u number_of_packets %u", - u->pipe, u->status, u->start_frame, u->number_of_packets); - if (!usb_pipeisoc (u->pipe)) - continue; - if (a == -1) - a = u->start_frame; - b = (u->start_frame + u->number_of_packets - 1) & 1023; - } - spin_unlock_irqrestore(&s->urb_list_lock, flags); -#if 0 - if (a != -1 && b != -1) { - do { - jnx_show_desc (s->iso_td[a]); - a = (a + 1) & 1023; - } - while (a != b); - } -#endif - } - purb->start_frame = (now + 5) & 1023; // 5ms setup should be enough //FIXME! - //return -EAGAIN; //FIXME - - } - } - } - else { - purb->start_frame &= 1023; - if (((now - purb->start_frame) & 1023) < (unsigned) purb->number_of_packets) { - dbg("iso_find_start: now between start_frame and end"); - return -EAGAIN; - } - } - - /* check if either start_frame or start_frame+number_of_packets-1 lies between start_limit and stop_limit */ - if (limits) - return 0; - if (((purb->start_frame - start_limit) & 1023) < queued_size || - ((purb->start_frame + purb->number_of_packets - 1 - start_limit) & 1023) < queued_size) { - dbg("iso_find_start: start_frame %u number_of_packets %u start_limit %u stop_limit %u", - purb->start_frame, purb->number_of_packets, start_limit, stop_limit); - return -EAGAIN; - } - - return 0; -} -/*-------------------------------------------------------------------*/ -// submits USB interrupt (ie. polling ;-) -// ASAP-flag set implicitely -// if period==0, the the transfer is only done once (usb_scsi need this...) - -static int uhci_submit_int_urb (purb_t purb) -{ - puhci_t s = (puhci_t) purb->dev->bus->hcpriv; - purb_priv_t purb_priv = purb->hcpriv; - int nint, n, ret; - puhci_desc_t td; - int status, destination; - int now; - int info; - unsigned int pipe = purb->pipe; - - //dbg("SUBMIT INT"); - - if (purb->interval < 0 || purb->interval >= 256) - return -EINVAL; - - if (purb->interval == 0) - nint = 0; - else { - for (nint = 0, n = 1; nint <= 8; nint++, n += n) // round interval down to 2^n - { - if (purb->interval < n) { - purb->interval = n / 2; - break; - } - } - nint--; - } - dbg("Rounded interval to %i, chain %i", purb->interval, nint); - - now = UHCI_GET_CURRENT_FRAME (s) & 1023; - purb->start_frame = now; // remember start frame, just in case... - - purb->number_of_packets = 1; - - // INT allows only one packet - if (purb->transfer_buffer_length > usb_maxpacket (purb->dev, pipe, usb_pipeout (pipe))) - return -EINVAL; - - ret = alloc_td (&td, UHCI_PTR_DEPTH); - - if (ret) - return -ENOMEM; - - status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC | - (purb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (1 << 27); - - destination = (purb->pipe & PIPE_DEVEP_MASK) | usb_packetid (purb->pipe) | - (((purb->transfer_buffer_length - 1) & 0x7ff) << 21); - - - info = destination | (usb_gettoggle (purb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)) << TD_TOKEN_TOGGLE); - - fill_td (td, status, info, virt_to_bus (purb->transfer_buffer)); - list_add_tail (&td->desc_list, &purb_priv->desc_list); - insert_td_horizontal (s, s->int_chain[nint], td, UHCI_PTR_DEPTH); // store in INT-TDs - - usb_dotoggle (purb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)); - -#if 0 - td = tdm[purb->number_of_packets]; - fill_td (td, TD_CTRL_IOC, 0, 0); - insert_td_horizontal (s, s->iso_td[(purb->start_frame + (purb->number_of_packets) * purb->interval + 1) & 1023], td, UHCI_PTR_DEPTH); - list_add_tail (&td->desc_list, &purb_priv->desc_list); -#endif - - return 0; -} -/*-------------------------------------------------------------------*/ -static int uhci_submit_iso_urb (purb_t purb) -{ - puhci_t s = (puhci_t) purb->dev->bus->hcpriv; - purb_priv_t purb_priv = purb->hcpriv; - int n, ret; - puhci_desc_t td, *tdm; - int status, destination; - unsigned long flags; - spinlock_t lock; - - spin_lock_init (&lock); - spin_lock_irqsave (&lock, flags); // Disable IRQs to schedule all ISO-TDs in time - - ret = iso_find_start (purb); // adjusts purb->start_frame for later use - - if (ret) - goto err; - - tdm = (puhci_desc_t *) kmalloc (purb->number_of_packets * sizeof (puhci_desc_t), in_interrupt ()? GFP_ATOMIC : GFP_KERNEL); - - if (!tdm) { - ret = -ENOMEM; - goto err; - } - - // First try to get all TDs - for (n = 0; n < purb->number_of_packets; n++) { - dbg("n:%d purb->iso_frame_desc[n].length:%d", n, purb->iso_frame_desc[n].length); - if (!purb->iso_frame_desc[n].length) { - // allows ISO striping by setting length to zero in iso_descriptor - tdm[n] = 0; - continue; - } - ret = alloc_td (&td, UHCI_PTR_DEPTH); - if (ret) { - int i; // Cleanup allocated TDs - - for (i = 0; i < n; n++) - if (tdm[i]) - kfree (tdm[i]); - kfree (tdm); - ret = -ENOMEM; - goto err; - } - tdm[n] = td; - } - - status = TD_CTRL_ACTIVE | TD_CTRL_IOS; //| (purb->transfer_flags&USB_DISABLE_SPD?0:TD_CTRL_SPD); - - destination = (purb->pipe & PIPE_DEVEP_MASK) | usb_packetid (purb->pipe); - - // Queue all allocated TDs - for (n = 0; n < purb->number_of_packets; n++) { - td = tdm[n]; - if (!td) - continue; - if (n + 1 >= purb->number_of_packets) - status |= TD_CTRL_IOC; - - fill_td (td, status, destination | (((purb->iso_frame_desc[n].length - 1) & 0x7ff) << 21), - virt_to_bus (purb->transfer_buffer + purb->iso_frame_desc[n].offset)); - list_add_tail (&td->desc_list, &purb_priv->desc_list); - insert_td_horizontal (s, s->iso_td[(purb->start_frame + n) & 1023], td, UHCI_PTR_DEPTH); // store in iso-tds - //uhci_show_td(td); - - } - - kfree (tdm); - dbg("ISO-INT# %i, start %i, now %i", purb->number_of_packets, purb->start_frame, UHCI_GET_CURRENT_FRAME (s) & 1023); - ret = 0; - - err: - spin_unlock_irqrestore (&lock, flags); - return ret; - -} -/*-------------------------------------------------------------------*/ -static int search_dev_ep (puhci_t s, purb_t purb) -{ - unsigned long flags; - struct list_head *p = s->urb_list.next; - purb_t tmp; - - dbg("search_dev_ep:"); - spin_lock_irqsave (&s->urb_list_lock, flags); - - for (; p != &s->urb_list; p = p->next) { - tmp = list_entry (p, urb_t, urb_list); - dbg("urb: %p", tmp); - // we can accept this urb if it is not queued at this time - // or if non-iso transfer requests should be scheduled for the same device and pipe - if ((usb_pipetype (purb->pipe) != PIPE_ISOCHRONOUS && - tmp->dev == purb->dev && tmp->pipe == purb->pipe) || (purb == tmp)) { - spin_unlock_irqrestore (&s->urb_list_lock, flags); - return 1; // found another urb already queued for processing - } - } - - spin_unlock_irqrestore (&s->urb_list_lock, flags); - - return 0; -} -/*-------------------------------------------------------------------*/ -static int uhci_submit_urb (purb_t purb) -{ - puhci_t s; - purb_priv_t purb_priv; - int ret = 0; - - if (!purb->dev || !purb->dev->bus) - return -ENODEV; - - s = (puhci_t) purb->dev->bus->hcpriv; - //dbg("submit_urb: %p type %d",purb,usb_pipetype(purb->pipe)); - - if (usb_pipedevice (purb->pipe) == s->rh.devnum) - return rh_submit_urb (purb); /* virtual root hub */ - - usb_inc_dev_use (purb->dev); - - if (search_dev_ep (s, purb)) { - usb_dec_dev_use (purb->dev); - return -ENXIO; // urb already queued - - } - -#ifdef _UHCI_SLAB - purb_priv = kmem_cache_alloc(urb_priv_kmem, in_interrupt ()? SLAB_ATOMIC : SLAB_KERNEL); -#else - purb_priv = kmalloc (sizeof (urb_priv_t), in_interrupt ()? GFP_ATOMIC : GFP_KERNEL); -#endif - if (!purb_priv) { - usb_dec_dev_use (purb->dev); - return -ENOMEM; - } - - purb->hcpriv = purb_priv; - INIT_LIST_HEAD (&purb_priv->desc_list); - purb_priv->short_control_packet=0; - dbg("submit_urb: scheduling %p", purb); - - switch (usb_pipetype (purb->pipe)) { - case PIPE_ISOCHRONOUS: - ret = uhci_submit_iso_urb (purb); - break; - case PIPE_INTERRUPT: - ret = uhci_submit_int_urb (purb); - break; - case PIPE_CONTROL: - //dump_urb (purb); - ret = uhci_submit_control_urb (purb); - break; - case PIPE_BULK: - ret = uhci_submit_bulk_urb (purb); - break; - default: - ret = -EINVAL; - } - - dbg("submit_urb: scheduled with ret: %d", ret); - - if (ret != USB_ST_NOERROR) { - usb_dec_dev_use (purb->dev); -#ifdef _UHCI_SLAB - kmem_cache_free(urb_priv_kmem, purb_priv); -#else - kfree (purb_priv); -#endif - return ret; - } - - purb->status = USB_ST_URB_PENDING; - queue_urb (s, &purb->urb_list,1); - dbg("submit_urb: exit"); - - return 0; -} -/*------------------------------------------------------------------- - Virtual Root Hub - -------------------------------------------------------------------*/ - -static __u8 root_hub_dev_des[] = -{ - 0x12, /* __u8 bLength; */ - 0x01, /* __u8 bDescriptorType; Device */ - 0x00, /* __u16 bcdUSB; v1.0 */ - 0x01, - 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ - 0x00, /* __u8 bDeviceSubClass; */ - 0x00, /* __u8 bDeviceProtocol; */ - 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ - 0x00, /* __u16 idVendor; */ - 0x00, - 0x00, /* __u16 idProduct; */ - 0x00, - 0x00, /* __u16 bcdDevice; */ - 0x00, - 0x00, /* __u8 iManufacturer; */ - 0x00, /* __u8 iProduct; */ - 0x00, /* __u8 iSerialNumber; */ - 0x01 /* __u8 bNumConfigurations; */ -}; - - -/* Configuration descriptor */ -static __u8 root_hub_config_des[] = -{ - 0x09, /* __u8 bLength; */ - 0x02, /* __u8 bDescriptorType; Configuration */ - 0x19, /* __u16 wTotalLength; */ - 0x00, - 0x01, /* __u8 bNumInterfaces; */ - 0x01, /* __u8 bConfigurationValue; */ - 0x00, /* __u8 iConfiguration; */ - 0x40, /* __u8 bmAttributes; - Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */ - 0x00, /* __u8 MaxPower; */ - - /* interface */ - 0x09, /* __u8 if_bLength; */ - 0x04, /* __u8 if_bDescriptorType; Interface */ - 0x00, /* __u8 if_bInterfaceNumber; */ - 0x00, /* __u8 if_bAlternateSetting; */ - 0x01, /* __u8 if_bNumEndpoints; */ - 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */ - 0x00, /* __u8 if_bInterfaceSubClass; */ - 0x00, /* __u8 if_bInterfaceProtocol; */ - 0x00, /* __u8 if_iInterface; */ - - /* endpoint */ - 0x07, /* __u8 ep_bLength; */ - 0x05, /* __u8 ep_bDescriptorType; Endpoint */ - 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ - 0x03, /* __u8 ep_bmAttributes; Interrupt */ - 0x08, /* __u16 ep_wMaxPacketSize; 8 Bytes */ - 0x00, - 0xff /* __u8 ep_bInterval; 255 ms */ -}; - - -static __u8 root_hub_hub_des[] = -{ - 0x09, /* __u8 bLength; */ - 0x29, /* __u8 bDescriptorType; Hub-descriptor */ - 0x02, /* __u8 bNbrPorts; */ - 0x00, /* __u16 wHubCharacteristics; */ - 0x00, - 0x01, /* __u8 bPwrOn2pwrGood; 2ms */ - 0x00, /* __u8 bHubContrCurrent; 0 mA */ - 0x00, /* __u8 DeviceRemovable; *** 7 Ports max *** */ - 0xff /* __u8 PortPwrCtrlMask; *** 7 ports max *** */ -}; - -/*-------------------------------------------------------------------------*/ -/* prepare Interrupt pipe transaction data; HUB INTERRUPT ENDPOINT */ -static int rh_send_irq (purb_t purb) -{ - - int len = 1; - int i; - puhci_t uhci = purb->dev->bus->hcpriv; - unsigned int io_addr = uhci->io_addr; - __u16 data = 0; - - for (i = 0; i < uhci->rh.numports; i++) { - data |= ((inw (io_addr + USBPORTSC1 + i * 2) & 0xa) > 0 ? (1 << (i + 1)) : 0); - len = (i + 1) / 8 + 1; - } - - *(__u16 *) purb->transfer_buffer = cpu_to_le16 (data); - purb->actual_length = len; - purb->status = USB_ST_NOERROR; - - if ((data > 0) && (uhci->rh.send != 0)) { - dbg("Root-Hub INT complete: port1: %x port2: %x data: %x", - inw (io_addr + USBPORTSC1), inw (io_addr + USBPORTSC2), data); - purb->complete (purb); - - } - return USB_ST_NOERROR; -} - -/*-------------------------------------------------------------------------*/ -/* Virtual Root Hub INTs are polled by this timer every "intervall" ms */ -static int rh_init_int_timer (purb_t purb); - -static void rh_int_timer_do (unsigned long ptr) -{ - int len; - - purb_t purb = (purb_t) ptr; - puhci_t uhci = purb->dev->bus->hcpriv; - - if (uhci->rh.send) { - len = rh_send_irq (purb); - if (len > 0) { - purb->actual_length = len; - if (purb->complete) - purb->complete (purb); - } - } - rh_init_int_timer (purb); -} - -/*-------------------------------------------------------------------------*/ -/* Root Hub INTs are polled by this timer */ -static int rh_init_int_timer (purb_t purb) -{ - puhci_t uhci = purb->dev->bus->hcpriv; - - uhci->rh.interval = purb->interval; - init_timer (&uhci->rh.rh_int_timer); - uhci->rh.rh_int_timer.function = rh_int_timer_do; - uhci->rh.rh_int_timer.data = (unsigned long) purb; - uhci->rh.rh_int_timer.expires = jiffies + (HZ * (purb->interval < 30 ? 30 : purb->interval)) / 1000; - add_timer (&uhci->rh.rh_int_timer); - - return 0; -} - -/*-------------------------------------------------------------------------*/ -#define OK(x) len = (x); break - -#define CLR_RH_PORTSTAT(x) \ - status = inw(io_addr+USBPORTSC1+2*(wIndex-1)); \ - status = (status & 0xfff5) & ~(x); \ - outw(status, io_addr+USBPORTSC1+2*(wIndex-1)) - -#define SET_RH_PORTSTAT(x) \ - status = inw(io_addr+USBPORTSC1+2*(wIndex-1)); \ - status = (status & 0xfff5) | (x); \ - outw(status, io_addr+USBPORTSC1+2*(wIndex-1)) - - -/*-------------------------------------------------------------------------*/ -/**** - ** Root Hub Control Pipe - *************************/ - - -static int rh_submit_urb (purb_t purb) -{ - struct usb_device *usb_dev = purb->dev; - puhci_t uhci = usb_dev->bus->hcpriv; - unsigned int pipe = purb->pipe; - devrequest *cmd = (devrequest *) purb->setup_packet; - void *data = purb->transfer_buffer; - int leni = purb->transfer_buffer_length; - int len = 0; - int status = 0; - int stat = USB_ST_NOERROR; - int i; - unsigned int io_addr = uhci->io_addr; - __u16 cstatus; - - __u16 bmRType_bReq; - __u16 wValue; - __u16 wIndex; - __u16 wLength; - - if (usb_pipetype (pipe) == PIPE_INTERRUPT) { - dbg("Root-Hub submit IRQ: every %d ms", purb->interval); - uhci->rh.urb = purb; - uhci->rh.send = 1; - uhci->rh.interval = purb->interval; - rh_init_int_timer (purb); - - return USB_ST_NOERROR; - } - - - bmRType_bReq = cmd->requesttype | cmd->request << 8; - wValue = le16_to_cpu (cmd->value); - wIndex = le16_to_cpu (cmd->index); - wLength = le16_to_cpu (cmd->length); - - for (i = 0; i < 8; i++) - uhci->rh.c_p_r[i] = 0; - - dbg("Root-Hub: adr: %2x cmd(%1x): %04x %04x %04x %04x", - uhci->rh.devnum, 8, bmRType_bReq, wValue, wIndex, wLength); - - switch (bmRType_bReq) { - /* Request Destination: - without flags: Device, - RH_INTERFACE: interface, - RH_ENDPOINT: endpoint, - RH_CLASS means HUB here, - RH_OTHER | RH_CLASS almost ever means HUB_PORT here - */ - - case RH_GET_STATUS: - *(__u16 *) data = cpu_to_le16 (1); - OK (2); - case RH_GET_STATUS | RH_INTERFACE: - *(__u16 *) data = cpu_to_le16 (0); - OK (2); - case RH_GET_STATUS | RH_ENDPOINT: - *(__u16 *) data = cpu_to_le16 (0); - OK (2); - case RH_GET_STATUS | RH_CLASS: - *(__u32 *) data = cpu_to_le32 (0); - OK (4); /* hub power ** */ - case RH_GET_STATUS | RH_OTHER | RH_CLASS: - status = inw (io_addr + USBPORTSC1 + 2 * (wIndex - 1)); - cstatus = ((status & USBPORTSC_CSC) >> (1 - 0)) | - ((status & USBPORTSC_PEC) >> (3 - 1)) | - (uhci->rh.c_p_r[wIndex - 1] << (0 + 4)); - status = (status & USBPORTSC_CCS) | - ((status & USBPORTSC_PE) >> (2 - 1)) | - ((status & USBPORTSC_SUSP) >> (12 - 2)) | - ((status & USBPORTSC_PR) >> (9 - 4)) | - (1 << 8) | /* power on ** */ - ((status & USBPORTSC_LSDA) << (-8 + 9)); - - *(__u16 *) data = cpu_to_le16 (status); - *(__u16 *) (data + 2) = cpu_to_le16 (cstatus); - OK (4); - - case RH_CLEAR_FEATURE | RH_ENDPOINT: - switch (wValue) { - case (RH_ENDPOINT_STALL): - OK (0); - } - break; - - case RH_CLEAR_FEATURE | RH_CLASS: - switch (wValue) { - case (RH_C_HUB_OVER_CURRENT): - OK (0); /* hub power over current ** */ - } - break; - - case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: - switch (wValue) { - case (RH_PORT_ENABLE): - CLR_RH_PORTSTAT (USBPORTSC_PE); - OK (0); - case (RH_PORT_SUSPEND): - CLR_RH_PORTSTAT (USBPORTSC_SUSP); - OK (0); - case (RH_PORT_POWER): - OK (0); /* port power ** */ - case (RH_C_PORT_CONNECTION): - SET_RH_PORTSTAT (USBPORTSC_CSC); - OK (0); - case (RH_C_PORT_ENABLE): - SET_RH_PORTSTAT (USBPORTSC_PEC); - OK (0); - case (RH_C_PORT_SUSPEND): -/*** WR_RH_PORTSTAT(RH_PS_PSSC); */ - OK (0); - case (RH_C_PORT_OVER_CURRENT): - OK (0); /* port power over current ** */ - case (RH_C_PORT_RESET): - uhci->rh.c_p_r[wIndex - 1] = 0; - OK (0); - } - break; - - case RH_SET_FEATURE | RH_OTHER | RH_CLASS: - switch (wValue) { - case (RH_PORT_SUSPEND): - SET_RH_PORTSTAT (USBPORTSC_SUSP); - OK (0); - case (RH_PORT_RESET): - SET_RH_PORTSTAT (USBPORTSC_PR); - wait_ms (10); - uhci->rh.c_p_r[wIndex - 1] = 1; - CLR_RH_PORTSTAT (USBPORTSC_PR); - udelay (10); - SET_RH_PORTSTAT (USBPORTSC_PE); - wait_ms (10); - SET_RH_PORTSTAT (0xa); - OK (0); - case (RH_PORT_POWER): - OK (0); /* port power ** */ - case (RH_PORT_ENABLE): - SET_RH_PORTSTAT (USBPORTSC_PE); - OK (0); - } - break; - - case RH_SET_ADDRESS: - uhci->rh.devnum = wValue; - OK (0); - - case RH_GET_DESCRIPTOR: - switch ((wValue & 0xff00) >> 8) { - case (0x01): /* device descriptor */ - len = min (leni, min (sizeof (root_hub_dev_des), wLength)); - memcpy (data, root_hub_dev_des, len); - OK (len); - case (0x02): /* configuration descriptor */ - len = min (leni, min (sizeof (root_hub_config_des), wLength)); - memcpy (data, root_hub_config_des, len); - OK (len); - case (0x03): /*string descriptors */ - stat = -EPIPE; - } - break; - - case RH_GET_DESCRIPTOR | RH_CLASS: - root_hub_hub_des[2] = uhci->rh.numports; - len = min (leni, min (sizeof (root_hub_hub_des), wLength)); - memcpy (data, root_hub_hub_des, len); - OK (len); - - case RH_GET_CONFIGURATION: - *(__u8 *) data = 0x01; - OK (1); - - case RH_SET_CONFIGURATION: - OK (0); - default: - stat = -EPIPE; - } - - - dbg("Root-Hub stat port1: %x port2: %x", - inw (io_addr + USBPORTSC1), inw (io_addr + USBPORTSC2)); - - purb->actual_length = len; - purb->status = stat; - if (purb->complete) - purb->complete (purb); - return USB_ST_NOERROR; -} -/*-------------------------------------------------------------------------*/ - -static int rh_unlink_urb (purb_t purb) -{ - puhci_t uhci = purb->dev->bus->hcpriv; - - dbg("Root-Hub unlink IRQ"); - uhci->rh.send = 0; - del_timer (&uhci->rh.rh_int_timer); - return 0; -} -/*-------------------------------------------------------------------*/ - -#define UHCI_DEBUG - -/* - * Map status to standard result codes - * - * is (td->status & 0xFE0000) [a.k.a. uhci_status_bits(td->status) - * is True for output TDs and False for input TDs. - */ -static int uhci_map_status (int status, int dir_out) -{ - if (!status) - return USB_ST_NOERROR; - if (status & TD_CTRL_BITSTUFF) /* Bitstuff error */ - return USB_ST_BITSTUFF; - if (status & TD_CTRL_CRCTIMEO) { /* CRC/Timeout */ - if (dir_out) - return USB_ST_NORESPONSE; - else - return USB_ST_CRC; - } - if (status & TD_CTRL_NAK) /* NAK */ - return USB_ST_TIMEOUT; - if (status & TD_CTRL_BABBLE) /* Babble */ - return -EPIPE; - if (status & TD_CTRL_DBUFERR) /* Buffer error */ - return USB_ST_BUFFERUNDERRUN; - if (status & TD_CTRL_STALLED) /* Stalled */ - return -EPIPE; - if (status & TD_CTRL_ACTIVE) /* Active */ - return USB_ST_NOERROR; - - return USB_ST_INTERNALERROR; -} - -/* - * Only the USB core should call uhci_alloc_dev and uhci_free_dev - */ -static int uhci_alloc_dev (struct usb_device *usb_dev) -{ - return 0; -} - -static int uhci_free_dev (struct usb_device *usb_dev) -{ - return 0; -} - -/* - * uhci_get_current_frame_number() - * - * returns the current frame number for a USB bus/controller. - */ -static int uhci_get_current_frame_number (struct usb_device *usb_dev) -{ - return UHCI_GET_CURRENT_FRAME ((puhci_t) usb_dev->bus->hcpriv); -} - -struct usb_operations uhci_device_operations = -{ - uhci_alloc_dev, - uhci_free_dev, - uhci_get_current_frame_number, - uhci_submit_urb, - uhci_unlink_urb -}; - -/* - * For IN-control transfers, process_transfer gets a bit more complicated, - * since there are devices that return less data (eg. strings) than they - * have announced. This leads to a queue abort due to the short packet, - * the status stage is not executed. If this happens, the status stage - * is manually re-executed. - * FIXME: Stall-condition may override 'nearly' successful CTRL-IN-transfer - * when the transfered length fits exactly in maxsze-packets. A bit - * more intelligence is needed to detect this and finish without error. - */ -static int process_transfer (puhci_t s, purb_t purb) -{ - int ret = USB_ST_NOERROR; - purb_priv_t purb_priv = purb->hcpriv; - struct list_head *qhl = purb_priv->desc_list.next; - puhci_desc_t qh = list_entry (qhl, uhci_desc_t, desc_list); - struct list_head *p = qh->vertical.next; - puhci_desc_t desc= list_entry (purb_priv->desc_list.prev, uhci_desc_t, desc_list); - puhci_desc_t last_desc = list_entry (desc->vertical.prev, uhci_desc_t, vertical); - int data_toggle = usb_gettoggle (purb->dev, usb_pipeendpoint (purb->pipe), usb_pipeout (purb->pipe)); // save initial data_toggle - - - // extracted and remapped info from TD - int maxlength; - int actual_length; - int status = USB_ST_NOERROR; - - dbg("process_transfer: urb contains bulk/control request"); - - - /* if the status phase has been retriggered and the - queue is empty or the last status-TD is inactive, the retriggered - status stage is completed - */ -#if 1 - if (purb_priv->short_control_packet && - ((qh->hw.qh.element == UHCI_PTR_TERM) ||(!(last_desc->hw.td.status & TD_CTRL_ACTIVE)))) - goto transfer_finished; -#endif - purb->actual_length=0; - - for (; p != &qh->vertical; p = p->next) { - desc = list_entry (p, uhci_desc_t, vertical); - - if (desc->hw.td.status & TD_CTRL_ACTIVE) // do not process active TDs - return ret; - - // extract transfer parameters from TD - actual_length = (desc->hw.td.status + 1) & 0x7ff; - maxlength = (((desc->hw.td.info >> 21) & 0x7ff) + 1) & 0x7ff; - status = uhci_map_status (uhci_status_bits (desc->hw.td.status), usb_pipeout (purb->pipe)); - - // see if EP is stalled - if (status == -EPIPE) { - // set up stalled condition - usb_endpoint_halt (purb->dev, usb_pipeendpoint (purb->pipe), usb_pipeout (purb->pipe)); - } - - // if any error occured stop processing of further TDs - if (status != USB_ST_NOERROR) { - // only set ret if status returned an error - uhci_show_td (desc); - ret = status; - purb->error_count++; - break; - } - else if ((desc->hw.td.info & 0xff) != USB_PID_SETUP) - purb->actual_length += actual_length; - -#if 0 - if (i++==0) - uhci_show_td (desc); // show first TD of each transfer -#endif - - // got less data than requested - if ( (actual_length < maxlength)) { - if (purb->transfer_flags & USB_DISABLE_SPD) { - ret = USB_ST_SHORT_PACKET; // treat as real error - dbg("process_transfer: SPD!!"); - break; // exit after this TD because SP was detected - } - - // short read during control-IN: re-start status stage - if ((usb_pipetype (purb->pipe) == PIPE_CONTROL)) { - if (uhci_packetid(last_desc->hw.td.info) == USB_PID_OUT) { - uhci_show_td (last_desc); - qh->hw.qh.element = virt_to_bus (last_desc); // re-trigger status stage - info("short packet during control transfer, retrigger status stage @ %p",last_desc); - purb_priv->short_control_packet=1; - return 0; - } - } - // all other cases: short read is OK - data_toggle = uhci_toggle (desc->hw.td.info); - break; - } - - data_toggle = uhci_toggle (desc->hw.td.info); - //dbg("process_transfer: len:%d status:%x mapped:%x toggle:%d", actual_length, desc->hw.td.status,status, data_toggle); - - } - usb_settoggle (purb->dev, usb_pipeendpoint (purb->pipe), usb_pipeout (purb->pipe), !data_toggle); - transfer_finished: - - /* APC BackUPS Pro kludge */ - /* It tries to send all of the descriptor instead of */ - /* the amount we requested */ - if (desc->hw.td.status & TD_CTRL_IOC && - status & TD_CTRL_ACTIVE && - status & TD_CTRL_NAK ) - { - ret=0; - status=0; - } - - unlink_qh (s, qh); - delete_qh (s, qh); - - purb->status = status; - - dbg("process_transfer: urb %p, wanted len %d, len %d status %x err %d", - purb,purb->transfer_buffer_length,purb->actual_length, purb->status, purb->error_count); - //dbg("process_transfer: exit"); - return ret; -} - -static int process_interrupt (puhci_t s, purb_t purb) -{ - int i, ret = USB_ST_URB_PENDING; - purb_priv_t purb_priv = purb->hcpriv; - struct list_head *p = purb_priv->desc_list.next; - puhci_desc_t desc = list_entry (purb_priv->desc_list.prev, uhci_desc_t, desc_list); - int data_toggle = usb_gettoggle (purb->dev, usb_pipeendpoint (purb->pipe), - usb_pipeout (purb->pipe)); // save initial data_toggle - // extracted and remapped info from TD - - int actual_length; - int status = USB_ST_NOERROR; - - //dbg("urb contains interrupt request"); - - for (i = 0; p != &purb_priv->desc_list; p = p->next, i++) // Maybe we allow more than one TD later ;-) - { - desc = list_entry (p, uhci_desc_t, desc_list); - - if (desc->hw.td.status & TD_CTRL_ACTIVE) { - // do not process active TDs - //dbg("TD ACT Status @%p %08x",desc,desc->hw.td.status); - break; - } - - if (!desc->hw.td.status & TD_CTRL_IOC) { - // do not process one-shot TDs, no recycling - break; - } - // extract transfer parameters from TD - - actual_length = (desc->hw.td.status + 1) & 0x7ff; - status = uhci_map_status (uhci_status_bits (desc->hw.td.status), usb_pipeout (purb->pipe)); - - // see if EP is stalled - if (status == -EPIPE) { - // set up stalled condition - usb_endpoint_halt (purb->dev, usb_pipeendpoint (purb->pipe), usb_pipeout (purb->pipe)); - } - - // if any error occured: ignore this td, and continue - if (status != USB_ST_NOERROR) { - purb->error_count++; - goto recycle; - } - else - purb->actual_length = actual_length; - - // FIXME: SPD? - - data_toggle = uhci_toggle (desc->hw.td.info); - - if (purb->complete && status != USB_ST_TIMEOUT) { - // for last td, no user completion is needed - dbg("process_interrupt: calling completion"); - purb->status = status; - purb->complete ((struct urb *) purb); - purb->status = USB_ST_URB_PENDING; - } - recycle: - // Recycle INT-TD if interval!=0, else mark TD as one-shot - if (purb->interval) { - desc->hw.td.status |= TD_CTRL_ACTIVE; - desc->hw.td.info &= ~(1 << TD_TOKEN_TOGGLE); - desc->hw.td.info |= (usb_gettoggle (purb->dev, usb_pipeendpoint (purb->pipe), - usb_pipeout (purb->pipe)) << TD_TOKEN_TOGGLE); - usb_dotoggle (purb->dev, usb_pipeendpoint (purb->pipe), usb_pipeout (purb->pipe)); - } - else { - desc->hw.td.status &= ~TD_CTRL_IOC; // inactivate TD - } - } - - return ret; -} - - -static int process_iso (puhci_t s, purb_t purb) -{ - int i; - int ret = USB_ST_NOERROR; - purb_priv_t purb_priv = purb->hcpriv; - struct list_head *p = purb_priv->desc_list.next; - puhci_desc_t desc = list_entry (purb_priv->desc_list.prev, uhci_desc_t, desc_list); - - dbg("urb contains iso request"); - if (desc->hw.td.status & TD_CTRL_ACTIVE) - return USB_ST_PARTIAL_ERROR; // last TD not finished - - purb->error_count = 0; - purb->actual_length = 0; - purb->status = USB_ST_NOERROR; - - for (i = 0; p != &purb_priv->desc_list; p = p->next, i++) { - desc = list_entry (p, uhci_desc_t, desc_list); - - //uhci_show_td(desc); - if (desc->hw.td.status & TD_CTRL_ACTIVE) { - // means we have completed the last TD, but not the TDs before - dbg("TD still active (%x)- grrr. paranoia!", desc->hw.td.status); - ret = USB_ST_PARTIAL_ERROR; - purb->iso_frame_desc[i].status = ret; - unlink_td (s, desc); - goto err; - } - - unlink_td (s, desc); - - if (purb->number_of_packets <= i) { - dbg("purb->number_of_packets (%d)<=(%d)", purb->number_of_packets, i); - ret = USB_ST_URB_INVALID_ERROR; - goto err; - } - - if (purb->iso_frame_desc[i].offset + purb->transfer_buffer != bus_to_virt (desc->hw.td.buffer)) { - // Hm, something really weird is going on - dbg("Pointer Paranoia: %p!=%p", purb->iso_frame_desc[i].offset + purb->transfer_buffer, bus_to_virt (desc->hw.td.buffer)); - ret = USB_ST_URB_INVALID_ERROR; - purb->iso_frame_desc[i].status = ret; - goto err; - } - purb->iso_frame_desc[i].actual_length = (desc->hw.td.status + 1) & 0x7ff; - purb->iso_frame_desc[i].status = uhci_map_status (uhci_status_bits (desc->hw.td.status), usb_pipeout (purb->pipe)); - purb->actual_length += purb->iso_frame_desc[i].actual_length; - - err: - - if (purb->iso_frame_desc[i].status != USB_ST_NOERROR) { - purb->error_count++; - purb->status = purb->iso_frame_desc[i].status; - } - dbg("process_iso: len:%d status:%x", - purb->iso_frame_desc[i].length, purb->iso_frame_desc[i].status); - - delete_desc (desc); - list_del (p); - } - dbg("process_iso: exit %i (%d)", i, ret); - return ret; -} - - -static int process_urb (puhci_t s, struct list_head *p) -{ - int ret = USB_ST_NOERROR; - purb_t purb; - - spin_lock(&s->urb_list_lock); - purb=list_entry (p, urb_t, urb_list); - dbg("found queued urb: %p", purb); - - switch (usb_pipetype (purb->pipe)) { - case PIPE_CONTROL: - case PIPE_BULK: - ret = process_transfer (s, purb); - break; - case PIPE_ISOCHRONOUS: - ret = process_iso (s, purb); - break; - case PIPE_INTERRUPT: - ret = process_interrupt (s, purb); - break; - } - - spin_unlock(&s->urb_list_lock); - - if (purb->status != USB_ST_URB_PENDING) { - int proceed = 0; - dbg("dequeued urb: %p", purb); - dequeue_urb (s, p, 1); - -#ifdef _UHCI_SLAB - kmem_cache_free(urb_priv_kmem, purb->hcpriv); -#else - kfree (purb->hcpriv); -#endif - - if ((usb_pipetype (purb->pipe) != PIPE_INTERRUPT)) { - purb_t tmp = purb->next; // pointer to first urb - int is_ring = 0; - - if (purb->next) { - do { - if (tmp->status != USB_ST_URB_PENDING) { - proceed = 1; - break; - } - tmp = tmp->next; - } - while (tmp != NULL && tmp != purb->next); - if (tmp == purb->next) - is_ring = 1; - } - - // In case you need the current URB status for your completion handler - if (purb->complete && (!proceed || (purb->transfer_flags & USB_URB_EARLY_COMPLETE))) { - dbg("process_transfer: calling early completion"); - purb->complete ((struct urb *) purb); - if (!proceed && is_ring && (purb->status != USB_ST_URB_KILLED)) - uhci_submit_urb (purb); - } - - if (proceed && purb->next) { - // if there are linked urbs - handle submitting of them right now. - tmp = purb->next; // pointer to first urb - - do { - if ((tmp->status != USB_ST_URB_PENDING) && (tmp->status != USB_ST_URB_KILLED) && uhci_submit_urb (tmp) != USB_ST_NOERROR) - break; - tmp = tmp->next; - } - while (tmp != NULL && tmp != purb->next); // submit until we reach NULL or our own pointer or submit fails - - if (purb->complete && !(purb->transfer_flags & USB_URB_EARLY_COMPLETE)) { - dbg("process_transfer: calling completion"); - purb->complete ((struct urb *) purb); - } - } - usb_dec_dev_use (purb->dev); - } - } - - return ret; -} - -static void uhci_interrupt (int irq, void *__uhci, struct pt_regs *regs) -{ - puhci_t s = __uhci; - unsigned int io_addr = s->io_addr; - unsigned short status; - struct list_head *p, *p2; - - /* - * Read the interrupt status, and write it back to clear the - * interrupt cause - */ - dbg("interrupt"); - status = inw (io_addr + USBSTS); - - if (!status) /* shared interrupt, not mine */ - return; - - if (status != 1) { - dbg("interrupt, status %x", status); - //uhci_show_status (s); - } - //beep(1000); - /* - * the following is very subtle and was blatantly wrong before - * traverse the list in *reverse* direction, because new entries - * may be added at the end. - * also, because process_urb may unlink the current urb, - * we need to advance the list before - * - Thomas Sailer - */ - - spin_lock(&s->unlink_urb_lock); - spin_lock (&s->urb_list_lock); - p = s->urb_list.prev; - spin_unlock (&s->urb_list_lock); - - while (p != &s->urb_list) { - p2 = p; - p = p->prev; - process_urb (s, p2); - } - - spin_unlock(&s->unlink_urb_lock); - - outw (status, io_addr + USBSTS); -#ifdef __alpha - mb (); // ? -#endif - dbg("done"); -} - -static void reset_hc (puhci_t s) -{ - unsigned int io_addr = s->io_addr; - - s->apm_state = 0; - /* Global reset for 50ms */ - outw (USBCMD_GRESET, io_addr + USBCMD); - wait_ms (50); - outw (0, io_addr + USBCMD); - wait_ms (10); -} - -static void start_hc (puhci_t s) -{ - unsigned int io_addr = s->io_addr; - int timeout = 1000; - - /* - * Reset the HC - this will force us to get a - * new notification of any already connected - * ports due to the virtual disconnect that it - * implies. - */ - outw (USBCMD_HCRESET, io_addr + USBCMD); - - while (inw (io_addr + USBCMD) & USBCMD_HCRESET) { - if (!--timeout) { - err("USBCMD_HCRESET timed out!"); - break; - } - } - - /* Turn on all interrupts */ - outw (USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP, io_addr + USBINTR); - - /* Start at frame 0 */ - outw (0, io_addr + USBFRNUM); - outl (virt_to_bus (s->framelist), io_addr + USBFLBASEADD); - - /* Run and mark it configured with a 64-byte max packet */ - outw (USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD); - s->apm_state = 1; -} - -static void __exit uhci_cleanup_dev(puhci_t s) -{ - struct usb_device *root_hub = s->bus->root_hub; - if (root_hub) - usb_disconnect (&root_hub); - - usb_deregister_bus (s->bus); - - reset_hc (s); - release_region (s->io_addr, s->io_size); - free_irq (s->irq, s); - usb_free_bus (s->bus); - cleanup_skel (s); - kfree (s); - -} - -static int __init uhci_start_usb (puhci_t s) -{ /* start it up */ - /* connect the virtual root hub */ - struct usb_device *usb_dev; - - usb_dev = usb_alloc_dev (NULL, s->bus); - if (!usb_dev) - return -1; - - s->bus->root_hub = usb_dev; - usb_connect (usb_dev); - - if (usb_new_device (usb_dev) != 0) { - usb_free_dev (usb_dev); - return -1; - } - - return 0; -} - -static int __init alloc_uhci (int irq, unsigned int io_addr, unsigned int io_size) -{ - puhci_t s; - struct usb_bus *bus; - - s = kmalloc (sizeof (uhci_t), GFP_KERNEL); - if (!s) - return -1; - - memset (s, 0, sizeof (uhci_t)); - INIT_LIST_HEAD (&s->urb_list); - spin_lock_init (&s->urb_list_lock); - spin_lock_init (&s->qh_lock); - spin_lock_init (&s->td_lock); - spin_lock_init (&s->unlink_urb_lock); - s->irq = -1; - s->io_addr = io_addr; - s->io_size = io_size; - s->next = devs; //chain new uhci device into global list - - bus = usb_alloc_bus (&uhci_device_operations); - if (!bus) { - kfree (s); - return -1; - } - - s->bus = bus; - bus->hcpriv = s; - - /* UHCI specs says devices must have 2 ports, but goes on to say */ - /* they may have more but give no way to determine how many they */ - /* have, so default to 2 */ - /* According to the UHCI spec, Bit 7 is always set to 1. So we try */ - /* to use this to our advantage */ - - for (s->maxports = 0; s->maxports < (io_size - 0x10) / 2; s->maxports++) { - unsigned int portstatus; - - portstatus = inw (io_addr + 0x10 + (s->maxports * 2)); - dbg("port %i, adr %x status %x", s->maxports, - io_addr + 0x10 + (s->maxports * 2), portstatus); - if (!(portstatus & 0x0080)) - break; - } - dbg("Detected %d ports", s->maxports); - - /* This is experimental so anything less than 2 or greater than 8 is */ - /* something weird and we'll ignore it */ - if (s->maxports < 2 || s->maxports > 8) { - dbg("Port count misdetected, forcing to 2 ports"); - s->maxports = 2; - } - - s->rh.numports = s->maxports; - - if (init_skel (s)) { - usb_free_bus (bus); - kfree(s); - return -1; - } - - request_region (s->io_addr, io_size, MODNAME); - reset_hc (s); - usb_register_bus (s->bus); - - start_hc (s); - - if (request_irq (irq, uhci_interrupt, SA_SHIRQ, MODNAME, s)) { - err("request_irq %d failed!",irq); - usb_free_bus (bus); - reset_hc (s); - release_region (s->io_addr, s->io_size); - cleanup_skel(s); - kfree(s); - return -1; - } - - s->irq = irq; - - if(uhci_start_usb (s) < 0) { - uhci_cleanup_dev(s); - return -1; - } - - //chain new uhci device into global list - devs = s; - - return 0; -} - -static int __init start_uhci (struct pci_dev *dev) -{ - int i; - - /* Search for the IO base address.. */ - for (i = 0; i < 6; i++) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,8) - unsigned int io_addr = dev->resource[i].start; - unsigned int io_size = - dev->resource[i].end - dev->resource[i].start + 1; - if (!(dev->resource[i].flags & 1)) - continue; -#else - unsigned int io_addr = dev->base_address[i]; - unsigned int io_size = 0x14; - if (!(io_addr & 1)) - continue; - io_addr &= ~1; -#endif - - /* Is it already in use? */ - if (check_region (io_addr, io_size)) - break; - /* disable legacy emulation */ - pci_write_config_word (dev, USBLEGSUP, USBLEGSUP_DEFAULT); - - return alloc_uhci(dev->irq, io_addr, io_size); - } - return -1; -} - -#ifdef CONFIG_APM -static int handle_apm_event (apm_event_t event) -{ - static int down = 0; - puhci_t s = devs; - dbg("handle_apm_event(%d)", event); - switch (event) { - case APM_SYS_SUSPEND: - case APM_USER_SUSPEND: - if (down) { - dbg("received extra suspend event"); - break; - } - while (s) { - reset_hc (s); - s = s->next; - } - down = 1; - break; - case APM_NORMAL_RESUME: - case APM_CRITICAL_RESUME: - if (!down) { - dbg("received bogus resume event"); - break; - } - down = 0; - while (s) { - start_hc (s); - s = s->next; - } - break; - } - return 0; -} -#endif - -int __init uhci_init (void) -{ - int retval = -ENODEV; - struct pci_dev *dev = NULL; - u8 type; - int i=0; - -#ifdef _UHCI_SLAB - char *slabname=kmalloc(16, GFP_KERNEL); - - if(!slabname) - return -ENOMEM; - - strcpy(slabname, "uhci_desc"); - uhci_desc_kmem = kmem_cache_create(slabname, sizeof(uhci_desc_t), 0, SLAB_HWCACHE_ALIGN, NULL, NULL); - - if(!uhci_desc_kmem) { - err("kmem_cache_create for uhci_desc failed (out of memory)"); - return -ENOMEM; - } - - slabname=kmalloc(16, GFP_KERNEL); - - if(!slabname) - return -ENOMEM; - - strcpy(slabname, "urb_priv"); - urb_priv_kmem = kmem_cache_create(slabname, sizeof(urb_priv_t), 0, SLAB_HWCACHE_ALIGN, NULL, NULL); - - if(!urb_priv_kmem) { - err("kmem_cache_create for urb_priv_t failed (out of memory)"); - return -ENOMEM; - } -#endif - info(VERSTR); - - for (;;) { - dev = pci_find_class (PCI_CLASS_SERIAL_USB << 8, dev); - if (!dev) - break; - - /* Is it UHCI */ - pci_read_config_byte (dev, PCI_CLASS_PROG, &type); - if (type != 0) - continue; - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,8) - pci_enable_device (dev); -#endif - if(!dev->irq) - { - err("Found UHCI device with no IRQ assigned. Check BIOS settings!"); - continue; - } - - /* Ok set it up */ - retval = start_uhci (dev); - - if (!retval) - i++; - - } - -#ifdef CONFIG_APM - if(i) - apm_register_callback (&handle_apm_event); -#endif - return retval; -} - -void __exit uhci_cleanup (void) -{ - puhci_t s; - while ((s = devs)) { - devs = devs->next; - uhci_cleanup_dev(s); - } -#ifdef _UHCI_SLAB - kmem_cache_shrink(uhci_desc_kmem); - kmem_cache_shrink(urb_priv_kmem); -#endif -} - -#ifdef MODULE -int init_module (void) -{ - return uhci_init (); -} - -void cleanup_module (void) -{ -#ifdef CONFIG_APM - apm_unregister_callback (&handle_apm_event); -#endif - uhci_cleanup (); -} - -#endif //MODULE diff --git a/drivers/usb/uhci.h b/drivers/usb/uhci.h deleted file mode 100644 index d8ef7f038..000000000 --- a/drivers/usb/uhci.h +++ /dev/null @@ -1,251 +0,0 @@ -#ifndef __LINUX_UHCI_H -#define __LINUX_UHCI_H - -/* - $Id: uhci.h,v 1.30 1999/12/15 17:57:25 fliegl Exp $ - */ -#define MODNAME "usb-uhci" -#define VERSTR "version v0.9 time " __TIME__ " " __DATE__ - -/* Command register */ -#define USBCMD 0 -#define USBCMD_RS 0x0001 /* Run/Stop */ -#define USBCMD_HCRESET 0x0002 /* Host reset */ -#define USBCMD_GRESET 0x0004 /* Global reset */ -#define USBCMD_EGSM 0x0008 /* Global Suspend Mode */ -#define USBCMD_FGR 0x0010 /* Force Global Resume */ -#define USBCMD_SWDBG 0x0020 /* SW Debug mode */ -#define USBCMD_CF 0x0040 /* Config Flag (sw only) */ -#define USBCMD_MAXP 0x0080 /* Max Packet (0 = 32, 1 = 64) */ - -/* Status register */ -#define USBSTS 2 -#define USBSTS_USBINT 0x0001 /* Interrupt due to IOC */ -#define USBSTS_ERROR 0x0002 /* Interrupt due to error */ -#define USBSTS_RD 0x0004 /* Resume Detect */ -#define USBSTS_HSE 0x0008 /* Host System Error - basically PCI problems */ -#define USBSTS_HCPE 0x0010 /* Host Controller Process Error - the scripts were buggy */ -#define USBSTS_HCH 0x0020 /* HC Halted */ - -/* Interrupt enable register */ -#define USBINTR 4 -#define USBINTR_TIMEOUT 0x0001 /* Timeout/CRC error enable */ -#define USBINTR_RESUME 0x0002 /* Resume interrupt enable */ -#define USBINTR_IOC 0x0004 /* Interrupt On Complete enable */ -#define USBINTR_SP 0x0008 /* Short packet interrupt enable */ - -#define USBFRNUM 6 -#define USBFLBASEADD 8 -#define USBSOF 12 - -/* USB port status and control registers */ -#define USBPORTSC1 16 -#define USBPORTSC2 18 -#define USBPORTSC_CCS 0x0001 /* Current Connect Status ("device present") */ -#define USBPORTSC_CSC 0x0002 /* Connect Status Change */ -#define USBPORTSC_PE 0x0004 /* Port Enable */ -#define USBPORTSC_PEC 0x0008 /* Port Enable Change */ -#define USBPORTSC_LS 0x0030 /* Line Status */ -#define USBPORTSC_RD 0x0040 /* Resume Detect */ -#define USBPORTSC_LSDA 0x0100 /* Low Speed Device Attached */ -#define USBPORTSC_PR 0x0200 /* Port Reset */ -#define USBPORTSC_SUSP 0x1000 /* Suspend */ - -/* Legacy support register */ -#define USBLEGSUP 0xc0 -#define USBLEGSUP_DEFAULT 0x2000 /* only PIRQ enable set */ - -#define UHCI_NULL_DATA_SIZE 0x7ff /* for UHCI controller TD */ - -#define UHCI_PTR_BITS 0x000F -#define UHCI_PTR_TERM 0x0001 -#define UHCI_PTR_QH 0x0002 -#define UHCI_PTR_DEPTH 0x0004 - -#define UHCI_NUMFRAMES 1024 /* in the frame list [array] */ -#define UHCI_MAX_SOF_NUMBER 2047 /* in an SOF packet */ -#define CAN_SCHEDULE_FRAMES 1000 /* how far future frames can be scheduled */ - -/* - * for TD : - */ -#define TD_CTRL_SPD (1 << 29) /* Short Packet Detect */ -#define TD_CTRL_C_ERR_MASK (3 << 27) /* Error Counter bits */ -#define TD_CTRL_LS (1 << 26) /* Low Speed Device */ -#define TD_CTRL_IOS (1 << 25) /* Isochronous Select */ -#define TD_CTRL_IOC (1 << 24) /* Interrupt on Complete */ -#define TD_CTRL_ACTIVE (1 << 23) /* TD Active */ -#define TD_CTRL_STALLED (1 << 22) /* TD Stalled */ -#define TD_CTRL_DBUFERR (1 << 21) /* Data Buffer Error */ -#define TD_CTRL_BABBLE (1 << 20) /* Babble Detected */ -#define TD_CTRL_NAK (1 << 19) /* NAK Received */ -#define TD_CTRL_CRCTIMEO (1 << 18) /* CRC/Time Out Error */ -#define TD_CTRL_BITSTUFF (1 << 17) /* Bit Stuff Error */ -#define TD_CTRL_ACTLEN_MASK 0x7ff /* actual length, encoded as n - 1 */ - -#define TD_CTRL_ANY_ERROR (TD_CTRL_STALLED | TD_CTRL_DBUFERR | \ - TD_CTRL_BABBLE | TD_CTRL_CRCTIME | TD_CTRL_BITSTUFF) - -#define uhci_status_bits(ctrl_sts) (ctrl_sts & 0xFE0000) -#define uhci_actual_length(ctrl_sts) ((ctrl_sts + 1) & TD_CTRL_ACTLEN_MASK) /* 1-based */ -#define uhci_ptr_to_virt(x) bus_to_virt(x & ~UHCI_PTR_BITS) - -/* - * for TD : - */ -#define UHCI_TD_REMOVE 0x0001 /* Remove when done */ - -/* - * for TD : (a.k.a. Token) - */ -#define TD_TOKEN_TOGGLE 19 - -#define uhci_maxlen(token) ((token) >> 21) -#define uhci_toggle(token) (((token) >> TD_TOKEN_TOGGLE) & 1) -#define uhci_endpoint(token) (((token) >> 15) & 0xf) -#define uhci_devaddr(token) (((token) >> 8) & 0x7f) -#define uhci_devep(token) (((token) >> 8) & 0x7ff) -#define uhci_packetid(token) ((token) & 0xff) -#define uhci_packetout(token) (uhci_packetid(token) != USB_PID_IN) -#define uhci_packetin(token) (uhci_packetid(token) == USB_PID_IN) - -/* ------------------------------------------------------------------------------------ - New TD/QH-structures - ------------------------------------------------------------------------------------ */ -typedef enum { - TD_TYPE, QH_TYPE -} uhci_desc_type_t; - -typedef struct { - __u32 link; - __u32 status; - __u32 info; - __u32 buffer; -} uhci_td_t, *puhci_td_t; - -typedef struct { - __u32 head; - __u32 element; /* Queue element pointer */ -} uhci_qh_t, *puhci_qh_t; - -typedef struct { - union { - uhci_td_t td; - uhci_qh_t qh; - } hw; - uhci_desc_type_t type; - struct list_head horizontal; - struct list_head vertical; - struct list_head desc_list; -} uhci_desc_t, *puhci_desc_t; - -typedef struct { - struct list_head desc_list; // list pointer to all corresponding TDs/QHs associated with this request - int short_control_packet; -} urb_priv_t, *purb_priv_t; - -struct virt_root_hub { - int devnum; /* Address of Root Hub endpoint */ - void *urb; - void *int_addr; - int send; - int interval; - int numports; - int c_p_r[8]; - struct timer_list rh_int_timer; -}; - -typedef struct uhci { - int irq; - unsigned int io_addr; - unsigned int io_size; - unsigned int maxports; - - int apm_state; - - struct uhci *next; // chain of uhci device contexts - - struct list_head urb_list; // list of all pending urbs - - spinlock_t urb_list_lock; // lock to keep consistency - - struct usb_bus *bus; // our bus - - spinlock_t unlink_urb_lock; // lock for unlink_urb - - __u32 *framelist; - uhci_desc_t **iso_td; - uhci_desc_t *int_chain[8]; - uhci_desc_t *control_chain; - uhci_desc_t *bulk_chain; - uhci_desc_t *chain_end; - spinlock_t qh_lock; - spinlock_t td_lock; - struct virt_root_hub rh; //private data of the virtual root hub -} uhci_t, *puhci_t; - - -#define MAKE_TD_ADDR(a) (virt_to_bus(a)&~UHCI_PTR_QH) -#define MAKE_QH_ADDR(a) (virt_to_bus(a)|UHCI_PTR_QH) -#define UHCI_GET_CURRENT_FRAME(uhci) (inw ((uhci)->io_addr + USBFRNUM)) - -/* ------------------------------------------------------------------------------------ - Virtual Root HUB - ------------------------------------------------------------------------------------ */ -/* destination of request */ -#define RH_INTERFACE 0x01 -#define RH_ENDPOINT 0x02 -#define RH_OTHER 0x03 - -#define RH_CLASS 0x20 -#define RH_VENDOR 0x40 - -/* Requests: bRequest << 8 | bmRequestType */ -#define RH_GET_STATUS 0x0080 -#define RH_CLEAR_FEATURE 0x0100 -#define RH_SET_FEATURE 0x0300 -#define RH_SET_ADDRESS 0x0500 -#define RH_GET_DESCRIPTOR 0x0680 -#define RH_SET_DESCRIPTOR 0x0700 -#define RH_GET_CONFIGURATION 0x0880 -#define RH_SET_CONFIGURATION 0x0900 -#define RH_GET_STATE 0x0280 -#define RH_GET_INTERFACE 0x0A80 -#define RH_SET_INTERFACE 0x0B00 -#define RH_SYNC_FRAME 0x0C80 -/* Our Vendor Specific Request */ -#define RH_SET_EP 0x2000 - - -/* Hub port features */ -#define RH_PORT_CONNECTION 0x00 -#define RH_PORT_ENABLE 0x01 -#define RH_PORT_SUSPEND 0x02 -#define RH_PORT_OVER_CURRENT 0x03 -#define RH_PORT_RESET 0x04 -#define RH_PORT_POWER 0x08 -#define RH_PORT_LOW_SPEED 0x09 -#define RH_C_PORT_CONNECTION 0x10 -#define RH_C_PORT_ENABLE 0x11 -#define RH_C_PORT_SUSPEND 0x12 -#define RH_C_PORT_OVER_CURRENT 0x13 -#define RH_C_PORT_RESET 0x14 - -/* Hub features */ -#define RH_C_HUB_LOCAL_POWER 0x00 -#define RH_C_HUB_OVER_CURRENT 0x01 - -#define RH_DEVICE_REMOTE_WAKEUP 0x00 -#define RH_ENDPOINT_STALL 0x01 - -/* Our Vendor Specific feature */ -#define RH_REMOVE_EP 0x00 - - -#define RH_ACK 0x01 -#define RH_REQ_ERR -1 -#define RH_NACK 0x00 - -#define min(a,b) (((a)<(b))?(a):(b)) - -#endif diff --git a/drivers/usb/usb-core.c b/drivers/usb/usb-core.c index f0b30bf93..68927a086 100644 --- a/drivers/usb/usb-core.c +++ b/drivers/usb/usb-core.c @@ -32,6 +32,7 @@ void usb_major_cleanup(void); int usb_acm_init(void); int usb_audio_init(void); int usb_cpia_init(void); +int usb_ibmcam_init(void); int usb_ov511_init(void); int usb_dc2xx_init(void); int usb_scanner_init(void); @@ -98,13 +99,16 @@ int usb_init(void) #ifdef CONFIG_USB_CPIA usb_cpia_init(); #endif +#ifdef CONFIG_USB_IBMCAM + usb_ibmcam_init(); +#endif #ifdef CONFIG_USB_OV511 usb_ov511_init(); #endif #ifdef CONFIG_USB_DC2XX usb_dc2xx_init(); #endif -#ifdef CONFIG_USB_SCSI +#ifdef CONFIG_USB_STORAGE usb_stor_init(); #endif #ifdef CONFIG_USB_DABUSB @@ -128,7 +132,7 @@ int usb_init(void) #ifdef CONFIG_USB_UHCI uhci_init(); #endif -#ifdef CONFIG_USB_OHCI_HCD +#ifdef CONFIG_USB_OHCI ohci_hcd_init(); #endif #endif diff --git a/drivers/usb/usb-debug.c b/drivers/usb/usb-debug.c index 2cca35151..356a4373b 100644 --- a/drivers/usb/usb-debug.c +++ b/drivers/usb/usb-debug.c @@ -6,8 +6,8 @@ */ #include #include -#include - +#include +#include #define DEBUG #include "usb.h" @@ -59,6 +59,11 @@ void usb_show_device(struct usb_device *dev) */ void usb_show_device_descriptor(struct usb_device_descriptor *desc) { + if (!desc) + { + printk("Invalid USB device descriptor (NULL POINTER)\n"); + return; + } printk(" Length = %2d%s\n", desc->bLength, desc->bLength == USB_DT_DEVICE_SIZE ? "" : " (!!!)"); printk(" DescriptorType = %02x\n", desc->bDescriptorType); @@ -160,6 +165,8 @@ void usb_show_string(struct usb_device *dev, char *id, int index) { char *buf; + if (!index) + return; if (!(buf = kmalloc(256, GFP_KERNEL))) return; if (usb_string(dev, index, buf, 256) > 0) @@ -167,3 +174,23 @@ void usb_show_string(struct usb_device *dev, char *id, int index) kfree(buf); } +void usb_dump_urb (purb_t purb) +{ + printk ("urb :%p\n", purb); + printk ("next :%p\n", purb->next); + printk ("dev :%p\n", purb->dev); + printk ("pipe :%08X\n", purb->pipe); + printk ("status :%d\n", purb->status); + printk ("transfer_flags :%08X\n", purb->transfer_flags); + printk ("transfer_buffer :%p\n", purb->transfer_buffer); + printk ("transfer_buffer_length:%d\n", purb->transfer_buffer_length); + printk ("actual_length :%d\n", purb->actual_length); + printk ("setup_packet :%p\n", purb->setup_packet); + printk ("start_frame :%d\n", purb->start_frame); + printk ("number_of_packets :%d\n", purb->number_of_packets); + printk ("interval :%d\n", purb->interval); + printk ("error_count :%d\n", purb->error_count); + printk ("context :%p\n", purb->context); + printk ("complete :%p\n", purb->complete); +} + diff --git a/drivers/usb/usb-ohci.c b/drivers/usb/usb-ohci.c new file mode 100644 index 000000000..509c49903 --- /dev/null +++ b/drivers/usb/usb-ohci.c @@ -0,0 +1,1822 @@ +/* + * URB OHCI HCD (Host Controller Driver) for USB. + * + * (C) Copyright 1999 Roman Weissgaerber + * + * [ Initialisation is based on Linus' ] + * [ uhci code and gregs ohci fragments ] + * [ (C) Copyright 1999 Linus Torvalds ] + * [ (C) Copyright 1999 Gregory P. Smith] + * + * + * History: + * + * v5.2 1999/12/07 URB 3rd preview, + * v5.1 1999/11/30 URB 2nd preview, cpia, (usb-scsi) + * v5.0 1999/11/22 URB Technical preview, Paul Mackerras powerbook susp/resume + * i386: HUB, Keyboard, Mouse, Printer + * + * v4.3 1999/10/27 multiple HCs, bulk_request + * v4.2 1999/09/05 ISO API alpha, new dev alloc, neg Error-codes + * v4.1 1999/08/27 Randy Dunlap's - ISO API first impl. + * v4.0 1999/08/18 + * v3.0 1999/06/25 + * v2.1 1999/05/09 code clean up + * v2.0 1999/05/04 + * v1.0 1999/04/27 initial release + * + + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for in_interrupt() */ + +#include +#include +#include + +#undef DEBUG +#define OHCI_USE_NPS + +#include "usb.h" +#include "usb-ohci.h" + +#ifdef CONFIG_APM +#include +static int handle_apm_event (apm_event_t event); +#endif + +#ifdef CONFIG_PMAC_PBOOK +#include +#include +#endif + +static DECLARE_WAIT_QUEUE_HEAD (op_wakeup); +static LIST_HEAD (ohci_hcd_list); +spinlock_t usb_ed_lock = SPIN_LOCK_UNLOCKED; + +/*-------------------------------------------------------------------------* + * URB support functions + *-------------------------------------------------------------------------*/ + +/* free the private part of an URB */ + +static void urb_rm_priv (urb_t * urb) +{ + urb_priv_t * urb_priv = urb->hcpriv; + int i; + void * wait; + + if (!urb_priv) return; + + wait = urb_priv->wait; + + for (i = 0; i < urb_priv->length; i++) { + if (urb_priv->td [i]) { + OHCI_FREE (urb_priv->td [i]); + } + } + kfree (urb->hcpriv); + urb->hcpriv = NULL; + + if (wait) { + add_wait_queue (&op_wakeup, wait); + wake_up (&op_wakeup); + } +} + +/*-------------------------------------------------------------------------*/ + +#ifdef DEBUG +static int sohci_get_current_frame_number (struct usb_device * dev); + +/* debug| print the main components of an URB + * small: 0) header + data packets 1) just header */ + +static void urb_print (urb_t * urb, char * str, int small) +{ + unsigned int pipe= urb->pipe; + int i, len; + + if (!urb->dev || !urb->dev->bus) { + dbg("%s URB: no dev", str); + return; + } + + dbg("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,flags:%4x,len:%d/%d,stat:%d(%x)", + str, + sohci_get_current_frame_number (urb->dev), + usb_pipedevice (pipe), + usb_pipeendpoint (pipe), + usb_pipeout (pipe)? 'O': 'I', + usb_pipetype (pipe) < 2? (usb_pipeint (pipe)? "INTR": "ISOC"): + (usb_pipecontrol (pipe)? "CTRL": "BULK"), + urb->transfer_flags, + urb->actual_length, + urb->transfer_buffer_length, + urb->status, urb->status); + if (!small) { + if (usb_pipecontrol (pipe)) { + printk (KERN_DEBUG __FILE__ ": cmd(8):"); + for (i = 0; i < 8 ; i++) + printk (" %02x", ((__u8 *) urb->setup_packet) [i]); + printk ("\n"); + } + if (urb->transfer_buffer_length > 0 && urb->transfer_buffer) { + printk (KERN_DEBUG __FILE__ ": data(%d/%d):", + urb->actual_length, + urb->transfer_buffer_length); + len = usb_pipeout (pipe)? + urb->transfer_buffer_length: urb->actual_length; + for (i = 0; i < 16 && i < len; i++) + printk (" %02x", ((__u8 *) urb->transfer_buffer) [i]); + printk ("%s stat:%d\n", i < len? "...": "", urb->status); + } + } + +} +/* just for debugging; prints all 32 branches of the int ed tree inclusive iso eds*/ +void ep_print_int_eds (ohci_t * ohci, char * str) { + int i, j; + __u32 * ed_p; + for (i= 0; i < 32; i++) { + j = 5; + printk (KERN_DEBUG __FILE__ " %s branch int %2d(%2x):", str, i, i); + ed_p = &(ohci->hcca.int_table [i]); + while (*ed_p != 0 && j--) { + ed_t *ed = (ed_t *) bus_to_virt(le32_to_cpup(ed_p)); + printk (" ed: %4x;", ed->hwINFO); + ed_p = &ed->hwNextED; + } + printk ("\n"); + } +} + + +#endif + +/*-------------------------------------------------------------------------* + * Interface functions (URB) + *-------------------------------------------------------------------------*/ + +/* return a request to the completion handler */ + +static int sohci_return_urb (urb_t * urb) +{ + urb_priv_t * urb_priv = urb->hcpriv; + urb_t * urbt; + unsigned long flags; + int i; + + /* just to be sure */ + if (!urb->complete) { + urb_rm_priv (urb); + usb_dec_dev_use (urb->dev); + return -1; + } + + if (!urb_priv) return -1; /* urb already unlinked */ + +#ifdef DEBUG + urb_print (urb, "RET", usb_pipeout (urb->pipe)); +#endif + + switch (usb_pipetype (urb->pipe)) { + case PIPE_INTERRUPT: + urb->complete (urb); /* call complete and requeue URB */ + urb->actual_length = 0; + urb->status = USB_ST_URB_PENDING; + if (urb_priv->state != URB_DEL) + td_submit_urb (urb); + break; + + case PIPE_ISOCHRONOUS: + for (urbt = urb->next; urbt && (urbt != urb); urbt = urbt->next); + if (urbt) { /* send the reply and requeue URB */ + urb->complete (urb); + + spin_lock_irqsave (&usb_ed_lock, flags); + urb->actual_length = 0; + urb->status = USB_ST_URB_PENDING; + urb->start_frame = urb_priv->ed->last_iso + 1; + if (urb_priv->state != URB_DEL) { + for (i = 0; i < urb->number_of_packets; i++) { + urb->iso_frame_desc[i].actual_length = 0; + urb->iso_frame_desc[i].status = -EXDEV; + } + td_submit_urb (urb); + } + spin_unlock_irqrestore (&usb_ed_lock, flags); + + } else { /* unlink URB, call complete */ + urb_rm_priv (urb); + usb_dec_dev_use (urb->dev); + urb->complete (urb); + } + break; + + case PIPE_BULK: + case PIPE_CONTROL: /* unlink URB, call complete */ + urb_rm_priv (urb); + usb_dec_dev_use (urb->dev); + urb->complete (urb); + break; + } + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* get a transfer request */ + +static int sohci_submit_urb (urb_t * urb) +{ + ohci_t * ohci; + ed_t * ed; + urb_priv_t * urb_priv; + unsigned int pipe = urb->pipe; + int i, size = 0; + unsigned long flags; + + if (!urb->dev || !urb->dev->bus) return -EINVAL; + + if (urb->hcpriv) return -EINVAL; /* urb already in use */ + + usb_inc_dev_use (urb->dev); + ohci = (ohci_t *) urb->dev->bus->hcpriv; + +#ifdef DEBUG + urb_print (urb, "SUB", usb_pipein (pipe)); +#endif + + if (usb_pipedevice (pipe) == ohci->rh.devnum) + return rh_submit_urb (urb); /* a request to the virtual root hub */ + + /* every endpoint has a ed, locate and fill it */ + if (!(ed = ep_add_ed (urb->dev, pipe, urb->interval, 1))) { + usb_dec_dev_use (urb->dev); + return -ENOMEM; + } + + /* for the private part of the URB we need the number of TDs (size) */ + switch (usb_pipetype (pipe)) { + case PIPE_BULK: /* one TD for every 4096 Byte */ + size = (urb->transfer_buffer_length - 1) / 4096 + 1; + break; + case PIPE_ISOCHRONOUS: /* number of packets from URB */ + size = urb->number_of_packets; + for (i = 0; i < urb->number_of_packets; i++) { + urb->iso_frame_desc[i].actual_length = 0; + urb->iso_frame_desc[i].status = -EXDEV; + } + break; + case PIPE_CONTROL: /* 1 TD for setup, 1 for ACK and 1 for every 4096 B */ + size = (urb->transfer_buffer_length == 0)? 2: + (urb->transfer_buffer_length - 1) / 4096 + 3; + break; + case PIPE_INTERRUPT: /* one TD */ + size = 1; + + break; + } + + /* allocate the private part or the URB */ + urb_priv = kmalloc (sizeof (urb_priv_t) + size * sizeof (td_t *), + in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); + if (!urb_priv) { + usb_dec_dev_use (urb->dev); + return -ENOMEM; + } + memset (urb_priv, 0, sizeof (urb_priv_t) + size * sizeof (td_t *)); + + /* fill the private part of the URB */ + urb->hcpriv = urb_priv; + urb_priv->length = size; + urb_priv->td_cnt = 0; + urb_priv->state = 0; + urb_priv->ed = ed; + urb_priv->wait = NULL; + + /* allocate the TDs */ + for (i = 0; i < size; i++) { + OHCI_ALLOC (urb_priv->td[i], sizeof (td_t)); + if (!urb_priv->td[i]) { + usb_dec_dev_use (urb->dev); + urb_rm_priv (urb); + return -ENOMEM; + } + } + spin_lock_irqsave (&usb_ed_lock, flags); + if (ed->state == ED_NEW || (ed->state & ED_DEL)) { + urb_rm_priv(urb); + usb_dec_dev_use (urb->dev); + return -EINVAL; + } + + /* for ISOC transfers calculate start frame index */ + if (urb->transfer_flags & USB_ISO_ASAP) { + urb->start_frame = ((ed->state == ED_OPER)? (ed->last_iso + 1): + (le16_to_cpu (ohci->hcca.frame_no) + 10)) & 0xffff; + } + + td_submit_urb (urb); /* fill the TDs and link it to the ed */ + + if (ed->state != ED_OPER) /* link the ed into a chain if is not already */ + ep_link (ohci, ed); + spin_unlock_irqrestore (&usb_ed_lock, flags); + + urb->status = USB_ST_URB_PENDING; + // queue_urb(s, &urb->urb_list); + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* deactivate all TDs and remove the private part of the URB */ + +static int sohci_unlink_urb (urb_t * urb) +{ + unsigned long flags; + ohci_t * ohci; + DECLARE_WAITQUEUE (wait, current); + + if (!urb) /* just to be sure */ + return -EINVAL; + +#ifdef DEBUG + urb_print (urb, "UNLINK", 1); +#endif + + ohci = (ohci_t *) urb->dev->bus->hcpriv; + + if (usb_pipedevice (urb->pipe) == ohci->rh.devnum) + return rh_unlink_urb (urb); /* a request to the virtual root hub */ + + if (urb->hcpriv) { + if (urb->status == USB_ST_URB_PENDING) { /* URB active? */ + urb_priv_t * urb_priv = urb->hcpriv; + urb_priv->state = URB_DEL; + /* we want to delete the TDs of an URB from an ed + * request the deletion, it will be handled at the next USB-frame */ + urb_priv->wait = &wait; + + spin_lock_irqsave (&usb_ed_lock, flags); + ep_rm_ed (urb->dev, urb_priv->ed); + urb_priv->ed->state |= ED_URB_DEL; + spin_unlock_irqrestore (&usb_ed_lock, flags); + + current->state = TASK_UNINTERRUPTIBLE; + if(schedule_timeout (HZ / 10)) /* wait until all TDs are deleted */ + remove_wait_queue (&op_wakeup, &wait); + else + err("unlink URB timeout!"); + } else + urb_rm_priv (urb); + usb_dec_dev_use (urb->dev); + } + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* allocate private data space for a usb device */ + +static int sohci_alloc_dev (struct usb_device *usb_dev) +{ + struct ohci_device * dev; + + dev = kmalloc (sizeof (*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + + memset (dev, 0, sizeof (*dev)); + + usb_dev->hcpriv = dev; + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* free private data space of usb device */ + +static int sohci_free_dev (struct usb_device * usb_dev) +{ + unsigned long flags; + int i, cnt = 0; + ed_t * ed; + DECLARE_WAITQUEUE (wait, current); + struct ohci_device * dev = usb_to_ohci (usb_dev); + ohci_t * ohci = usb_dev->bus->hcpriv; + + if (!dev) return 0; + + if (usb_dev->devnum >= 0) { + + /* delete all TDs of all EDs */ + spin_lock_irqsave (&usb_ed_lock, flags); + for(i = 0; i < NUM_EDS; i++) { + ed = &(dev->ed[i]); + if (ed->state != ED_NEW) { + if (ed->state == ED_OPER) ep_unlink (ohci, ed); + ep_rm_ed (usb_dev, ed); + ed->state = ED_DEL; + cnt++; + } + } + spin_unlock_irqrestore (&usb_ed_lock, flags); + + if (cnt > 0) { + dev->wait = &wait; + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout (HZ / 10); + remove_wait_queue (&op_wakeup, &wait); + } + } + kfree (dev); + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* tell us the current USB frame number */ + +static int sohci_get_current_frame_number (struct usb_device *usb_dev) +{ + ohci_t * ohci = usb_dev->bus->hcpriv; + + return le16_to_cpu (ohci->hcca.frame_no); +} + +/*-------------------------------------------------------------------------*/ + +struct usb_operations sohci_device_operations = { + sohci_alloc_dev, + sohci_free_dev, + sohci_get_current_frame_number, + sohci_submit_urb, + sohci_unlink_urb +}; + +/*-------------------------------------------------------------------------* + * ED handling functions + *-------------------------------------------------------------------------*/ + +/* search for the right branch to insert an interrupt ed into the int tree + * do some load ballancing; + * returns the branch and + * sets the interval to interval = 2^integer (ld (interval)) */ + +static int ep_int_ballance (ohci_t * ohci, int interval, int load) +{ + int i, branch = 0; + + /* search for the least loaded interrupt endpoint branch of all 32 branches */ + for (i = 0; i < 32; i++) + if (ohci->ohci_int_load [branch] > ohci->ohci_int_load [i]) branch = i; + + branch = branch % interval; + for (i = branch; i < 32; i += interval) ohci->ohci_int_load [i] += load; + + return branch; +} + +/*-------------------------------------------------------------------------*/ + +/* 2^int( ld (inter)) */ + +static int ep_2_n_interval (int inter) +{ + int i; + for (i = 0; ((inter >> i) > 1 ) && (i < 5); i++); + return 1 << i; +} + +/*-------------------------------------------------------------------------*/ + +/* the int tree is a binary tree + * in order to process it sequentially the indexes of the branches have to be mapped + * the mapping reverses the bits of a word of num_bits length */ + +static int ep_rev (int num_bits, int word) +{ + int i, wout = 0; + + for (i = 0; i < num_bits; i++) wout |= (((word >> i) & 1) << (num_bits - i - 1)); + return wout; +} + +/*-------------------------------------------------------------------------*/ + +/* link an ed into one of the HC chains */ + +static int ep_link (ohci_t * ohci, ed_t * edi) +{ + int int_branch; + int i; + int inter; + int interval; + int load; + __u32 * ed_p; + volatile ed_t * ed = edi; + + ed->state = ED_OPER; + + switch (ed->type) { + case CTRL: + ed->hwNextED = 0; + if (ohci->ed_controltail == NULL) { + writel (virt_to_bus (ed), &ohci->regs->ed_controlhead); + } else { + ohci->ed_controltail->hwNextED = cpu_to_le32 (virt_to_bus (ed)); + } + ed->ed_prev = ohci->ed_controltail; + ohci->ed_controltail = edi; + break; + + case BULK: + ed->hwNextED = 0; + if (ohci->ed_bulktail == NULL) { + writel (virt_to_bus (ed), &ohci->regs->ed_bulkhead); + } else { + ohci->ed_bulktail->hwNextED = cpu_to_le32 (virt_to_bus (ed)); + } + ed->ed_prev = ohci->ed_bulktail; + ohci->ed_bulktail = edi; + break; + + case INT: + load = ed->int_load; + interval = ep_2_n_interval (ed->int_period); + ed->int_interval = interval; + int_branch = ep_int_ballance (ohci, interval, load); + ed->int_branch = int_branch; + + 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_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)); + } +#ifdef DEBUG + ep_print_int_eds (ohci, "LINK_INT"); +#endif + break; + + case ISO: + ed->hwNextED = 0; + ed->int_interval = 1; + if (ohci->ed_isotail != NULL) { + ohci->ed_isotail->hwNextED = cpu_to_le32 (virt_to_bus (ed)); + ed->ed_prev = ohci->ed_isotail; + } else { + for ( i = 0; i < 32; i += inter) { + 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_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; + } + ohci->ed_isotail = edi; +#ifdef DEBUG + ep_print_int_eds (ohci, "LINK_ISO"); +#endif + break; + } + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* unlink an ed from one of the HC chains. + * just the link to the ed is unlinked. + * the link from the ed still points to another operational ed or 0 + * so the HC can eventually finish the processing of the unlinked ed */ + +static int ep_unlink (ohci_t * ohci, ed_t * ed) +{ + int int_branch; + int i; + int inter; + int interval; + __u32 * ed_p; + + + switch (ed->type) { + case CTRL: + if (ed->ed_prev == NULL) { + 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_cpup (&ed->hwNextED)))->ed_prev = ed->ed_prev; + } + break; + + case BULK: + if (ed->ed_prev == NULL) { + 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_cpup (&ed->hwNextED)))->ed_prev = ed->ed_prev; + } + break; + + case INT: + int_branch = ed->int_branch; + interval = ed->int_interval; + + 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_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; + } + } + } + for (i = int_branch; i < 32; i += interval) ohci->ohci_int_load[i] -= ed->int_load; +#ifdef DEBUG + ep_print_int_eds (ohci, "UNLINK_INT"); +#endif break; + + case ISO: + if (ohci->ed_isotail == ed) + ohci->ed_isotail = ed->ed_prev; + if (ed->hwNextED != 0) + ((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; + } else { + for (i = 0; i < 32; i += inter) { + 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_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; + } + } + } + } +#ifdef DEBUG + ep_print_int_eds (ohci, "UNLINK_ISO"); +#endif + break; + } + ed->state = ED_UNLINK; + return 0; +} + + +/*-------------------------------------------------------------------------*/ + +/* add/reinit an endpoint; this should be done once at the usb_set_configuration command, + * but the USB stack is a little bit stateless so we do it at every transaction + * if the state of the ed is ED_NEW then a dummy td is added and the state is changed to ED_UNLINK + * in all other cases the state is left unchanged + * the ed info fields are setted anyway even though most of them should not change */ + +static ed_t * ep_add_ed (struct usb_device * usb_dev, unsigned int pipe, int interval, int load) +{ + ohci_t * ohci = usb_dev->bus->hcpriv; + td_t * td; + ed_t * ed_ret; + volatile ed_t * ed; + + + spin_lock (&usb_ed_lock); + + ed = ed_ret = &(usb_to_ohci (usb_dev)->ed[(usb_pipeendpoint (pipe) << 1) | + (usb_pipecontrol (pipe)? 0: usb_pipeout (pipe))]); + + if((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) + return NULL; /* pending delete request */ + + if (ed->state == ED_NEW) { + ed->hwINFO = cpu_to_le32 (OHCI_ED_SKIP); /* skip ed */ + OHCI_ALLOC (td, sizeof (*td)); /* dummy td; end of td list for ed */ + if(!td) return NULL; /* out of memory */ + ed->hwTailP = cpu_to_le32 (virt_to_bus (td)); + ed->hwHeadP = ed->hwTailP; + ed->state = ED_UNLINK; + ed->type = usb_pipetype (pipe); + usb_to_ohci (usb_dev)->ed_cnt++; + } + + ohci->dev[usb_pipedevice (pipe)] = usb_dev; + + ed->hwINFO = cpu_to_le32 (usb_pipedevice (pipe) + | usb_pipeendpoint (pipe) << 7 + | (usb_pipeisoc (pipe)? 0x8000: 0) + | (usb_pipecontrol (pipe)? 0: (usb_pipeout (pipe)? 0x800: 0x1000)) + | usb_pipeslow (pipe) << 13 + | usb_maxpacket (usb_dev, pipe, usb_pipeout (pipe)) << 16); + + if (ed->type == INT && ed->state == ED_UNLINK) { + ed->int_period = interval; + ed->int_load = load; + } + + spin_unlock(&usb_ed_lock); + return ed_ret; +} + +/*-------------------------------------------------------------------------*/ + +/* request the removal of an endpoint + * put the ep on the rm_list and request a stop of the bulk or ctrl list + * real removal is done at the next start of frame (SOF) hardware interrupt */ + +static void ep_rm_ed (struct usb_device * usb_dev, ed_t * ed) +{ + unsigned int frame; + ohci_t * ohci = usb_dev->bus->hcpriv; + + if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) return; + + ed->hwINFO |= cpu_to_le32 (OHCI_ED_SKIP); + + writel (OHCI_INTR_SF, &ohci->regs->intrstatus); + writel (OHCI_INTR_SF, &ohci->regs->intrenable); /* enable sof interrupt */ + + frame = le16_to_cpu (ohci->hcca.frame_no) & 0x1; + ed->ed_rm_list = ohci->ed_rm_list[frame]; + ohci->ed_rm_list[frame] = ed; + + switch (ed->type) { + case CTRL: /* stop CTRL list */ + writel (ohci->hc_control &= ~(0x01 << 4), &ohci->regs->control); + break; + case BULK: /* stop BULK list */ + writel (ohci->hc_control &= ~(0x01 << 5), &ohci->regs->control); + break; + } +} + +/*-------------------------------------------------------------------------* + * TD handling functions + *-------------------------------------------------------------------------*/ + +/* prepare a TD */ + +static void td_fill (unsigned int info, void * data, int len, urb_t * urb, int type, int index) +{ + volatile td_t * td, * td_pt; + urb_priv_t * urb_priv = urb->hcpriv; + + if (index >= urb_priv->length) { + err("internal OHCI error: TD index > length"); + return; + } + + td_pt = urb_priv->td [index]; + /* fill the old dummy TD */ + td = urb_priv->td [index] = (td_t *) bus_to_virt (le32_to_cpup (&urb_priv->ed->hwTailP) & 0xfffffff0); + td->ed = urb_priv->ed; + td->index = index; + td->urb = urb; + td->hwINFO = cpu_to_le32 (info); + td->type = type; + if ((td->ed->type & 3) == PIPE_ISOCHRONOUS) { + td->hwCBP = cpu_to_le32 (((!data || !len)? + 0 : virt_to_bus (data)) & 0xFFFFF000); + td->ed->last_iso = info & 0xffff; + } else { + td->hwCBP = cpu_to_le32 (((!data || !len)? 0 : virt_to_bus (data))); + } + td->hwBE = cpu_to_le32 ((!data || !len )? 0: virt_to_bus (data + len - 1)); + td->hwNextTD = cpu_to_le32 (virt_to_bus (td_pt)); + td->hwPSW [0] = cpu_to_le16 ((virt_to_bus (data) & 0x0FFF) | 0xE000); + td_pt->hwNextTD = 0; + td->ed->hwTailP = td->hwNextTD; + + td->next_dl_td = NULL; //td_pt; +} + +/*-------------------------------------------------------------------------*/ + +/* prepare all TDs of a transfer */ + +static void td_submit_urb (urb_t * urb) +{ + urb_priv_t * urb_priv = urb->hcpriv; + ohci_t * ohci = (ohci_t *) urb->dev->bus->hcpriv; + void * ctrl = urb->setup_packet; + void * data = urb->transfer_buffer; + int data_len = urb->transfer_buffer_length; + int cnt = 0; + __u32 info = 0; + + + urb_priv->td_cnt = 0; + + switch (usb_pipetype (urb->pipe)) { + case PIPE_BULK: + info = usb_pipeout (urb->pipe)? + TD_CC | TD_DP_OUT | TD_T_TOGGLE: TD_CC | TD_DP_IN | TD_T_TOGGLE; + while(data_len > 4096) { + td_fill (info, data, 4096, urb, (cnt? 0: ST_ADDR) | ADD_LEN, cnt); + data += 4096; data_len -= 4096; cnt++; + } + info = usb_pipeout (urb->pipe)? + TD_CC | TD_DP_OUT | TD_T_TOGGLE: TD_CC | TD_R | TD_DP_IN | TD_T_TOGGLE; + td_fill (info, data, data_len, urb, (cnt? 0: ST_ADDR) | ADD_LEN, cnt); + cnt++; + writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */ + break; + + case PIPE_INTERRUPT: + info = usb_pipeout (urb->pipe)? + TD_CC | TD_DP_OUT | TD_T_TOGGLE: TD_CC | TD_R | TD_DP_IN | TD_T_TOGGLE; + td_fill (info, data, data_len, urb, ST_ADDR | ADD_LEN, cnt++); + break; + + case PIPE_CONTROL: + info = TD_CC | TD_DP_SETUP | TD_T_DATA0; + td_fill (info, ctrl, 8, urb, ST_ADDR, cnt++); + if (data_len > 0) { + info = usb_pipeout (urb->pipe)? + TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 : TD_CC | TD_R | TD_DP_IN | TD_T_DATA1; + td_fill (info, data, data_len, urb, ADD_LEN, cnt++); + } + info = usb_pipeout (urb->pipe)? + TD_CC | TD_DP_IN | TD_T_DATA1: TD_CC | TD_DP_OUT | TD_T_DATA1; + td_fill (info, NULL, 0, urb, 0, cnt++); + writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */ + break; + + case PIPE_ISOCHRONOUS: + for (cnt = 0; cnt < urb->number_of_packets; cnt++) { + td_fill (TD_CC|TD_ISO | ((urb->start_frame + cnt) & 0xffff), + (__u8 *) data + urb->iso_frame_desc[cnt].offset, + urb->iso_frame_desc[cnt].length, urb, (cnt? 0: ST_ADDR) | ADD_LEN, cnt); + } + break; + } + if (urb_priv->length != cnt) + dbg("TD LENGTH %d != CNT %d", urb_priv->length, cnt); +} + +/*-------------------------------------------------------------------------* + * Done List handling functions + *-------------------------------------------------------------------------*/ + +/* replies to the request have to be on a FIFO basis so + * we reverse the reversed done-list */ + +static td_t * dl_reverse_done_list (ohci_t * ohci) +{ + __u32 td_list_hc; + td_t * td_rev = NULL; + td_t * td_list = NULL; + urb_priv_t * urb_priv = NULL; + unsigned long flags; + + spin_lock_irqsave (&usb_ed_lock, flags); + + 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_cpup (&td_list->hwINFO))) { + urb_priv = (urb_priv_t *) td_list->urb->hcpriv; + dbg(" USB-error/status: %x : %p", + 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 = + (urb_priv->td[urb_priv->length - 1]->hwNextTD & cpu_to_le32 (0xfffffff0)) | + (td_list->ed->hwHeadP & cpu_to_le32 (0x2)); + urb_priv->td_cnt += urb_priv->length - td_list->index - 1; + } else + td_list->ed->hwHeadP &= cpu_to_le32 (0xfffffff2); + } + } + + td_list->next_dl_td = td_rev; + td_rev = td_list; + td_list_hc = le32_to_cpup (&td_list->hwNextTD) & 0xfffffff0; + } + spin_unlock_irqrestore (&usb_ed_lock, flags); + return td_list; +} + +/*-------------------------------------------------------------------------*/ + +/* there are some pending requests to remove + * - some of the eds (if ed->state & ED_DEL (set by sohci_free_dev) + * - some URBs/TDs if urb_priv->state == URB_DEL */ + +static void dl_del_list (ohci_t * ohci, unsigned int frame) +{ + unsigned long flags; + ed_t * ed; + __u32 edINFO; + td_t * td = NULL, * td_next = NULL, * tdHeadP = NULL, * tdTailP; + __u32 * td_p; + int ctrl = 0, bulk = 0; + + 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_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_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) + urb_rm_priv (urb); + } else { + td_p = &td->hwNextTD; + } + + } + if (ed->state & ED_DEL) { /* set by sohci_free_dev */ + struct ohci_device * dev = usb_to_ohci (ohci->dev[edINFO & 0x7F]); + OHCI_FREE (tdTailP); /* free dummy td */ + ed->hwINFO = cpu_to_le32 (OHCI_ED_SKIP); + ed->state = ED_NEW; + /* if all eds are removed wake up sohci_free_dev */ + if ((! --dev->ed_cnt) && dev->wait) { + add_wait_queue (&op_wakeup, dev->wait); + wake_up (&op_wakeup); + } + } + else { + ed->state &= ~ED_URB_DEL; + ed->hwINFO &= ~cpu_to_le32 (OHCI_ED_SKIP); + } + + if ((ed->type & 3) == CTRL) ctrl |= 1; + if ((ed->type & 3) == BULK) bulk |= 1; + } + + if (ctrl) writel (0, &ohci->regs->ed_controlcurrent); /* reset CTRL list */ + if (bulk) writel (0, &ohci->regs->ed_bulkcurrent); /* reset BULK list */ + if (!ohci->ed_rm_list[!frame]) /* start CTRL u. BULK list */ + writel (ohci->hc_control |= (0x03<<4), &ohci->regs->control); + ohci->ed_rm_list[frame] = NULL; + + spin_unlock_irqrestore (&usb_ed_lock, flags); +} + +/*-------------------------------------------------------------------------*/ + +/* td done list */ + +static void dl_done_list (ohci_t * ohci, td_t * td_list) +{ + td_t * td_list_next = NULL; + ed_t * ed; + int dlen = 0; + int cc = 0; + urb_t * urb; + urb_priv_t * urb_priv; + __u32 tdINFO, tdBE, tdCBP, edHeadP, edTailP; + __u16 tdPSW; + 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_cpup (&td_list->hwINFO); + tdBE = le32_to_cpup (&td_list->hwBE); + tdCBP = le32_to_cpup (&td_list->hwCBP); + + ed = td_list->ed; + + if (td_list->type & ST_ADDR) + urb->actual_length = 0; + + if (td_list->type & ADD_LEN) { /* accumulate length of multi td transfers */ + if (tdINFO & TD_ISO) { + tdPSW = le16_to_cpu (td_list->hwPSW[0]); + cc = (tdPSW >> 12) & 0xF; + if (cc < 0xE) { + if (usb_pipeout(urb->pipe)) { + dlen = urb->iso_frame_desc[td_list->index].length; + } else { + dlen = tdPSW & 0x3ff; + } + urb->actual_length += dlen; + urb->iso_frame_desc[td_list->index].actual_length = dlen; + if (!(urb->transfer_flags & USB_DISABLE_SPD) && (cc == TD_DATAUNDERRUN)) + cc = TD_CC_NOERROR; + + urb->iso_frame_desc[td_list->index].status = cc_to_error[cc]; + } + } else { + if (tdBE != 0) { + if (td_list->hwCBP == 0) + urb->actual_length = bus_to_virt (tdBE) - urb->transfer_buffer + 1; + else + urb->actual_length = bus_to_virt (tdCBP) - urb->transfer_buffer; + } + } + } + /* error code of transfer */ + cc = TD_CC_GET (tdINFO); + if (!(urb->transfer_flags & USB_DISABLE_SPD) && (cc == TD_DATAUNDERRUN)) + cc = TD_CC_NOERROR; + if (++(urb_priv->td_cnt) == urb_priv->length) { + if (urb_priv->state != URB_DEL && !(ed->state & ED_DEL) && ed->state != ED_NEW) { + urb->status = cc_to_error[cc]; + sohci_return_urb (urb); + } else { + urb_rm_priv (urb); + } + } + + spin_lock_irqsave (&usb_ed_lock, flags); + if (ed->state != ED_NEW) { + 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 */ + + } + spin_unlock_irqrestore (&usb_ed_lock, flags); + + td_list = td_list_next; + } +} + + + + +/*-------------------------------------------------------------------------* + * Virtual Root Hub + *-------------------------------------------------------------------------*/ + +static __u8 root_hub_dev_des[] = +{ + 0x12, /* __u8 bLength; */ + 0x01, /* __u8 bDescriptorType; Device */ + 0x00, /* __u16 bcdUSB; v1.0 */ + 0x01, + 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ + 0x00, /* __u8 bDeviceSubClass; */ + 0x00, /* __u8 bDeviceProtocol; */ + 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ + 0x00, /* __u16 idVendor; */ + 0x00, + 0x00, /* __u16 idProduct; */ + 0x00, + 0x00, /* __u16 bcdDevice; */ + 0x00, + 0x00, /* __u8 iManufacturer; */ + 0x00, /* __u8 iProduct; */ + 0x00, /* __u8 iSerialNumber; */ + 0x01 /* __u8 bNumConfigurations; */ +}; + + +/* Configuration descriptor */ +static __u8 root_hub_config_des[] = +{ + 0x09, /* __u8 bLength; */ + 0x02, /* __u8 bDescriptorType; Configuration */ + 0x19, /* __u16 wTotalLength; */ + 0x00, + 0x01, /* __u8 bNumInterfaces; */ + 0x01, /* __u8 bConfigurationValue; */ + 0x00, /* __u8 iConfiguration; */ + 0x40, /* __u8 bmAttributes; + Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */ + 0x00, /* __u8 MaxPower; */ + + /* interface */ + 0x09, /* __u8 if_bLength; */ + 0x04, /* __u8 if_bDescriptorType; Interface */ + 0x00, /* __u8 if_bInterfaceNumber; */ + 0x00, /* __u8 if_bAlternateSetting; */ + 0x01, /* __u8 if_bNumEndpoints; */ + 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */ + 0x00, /* __u8 if_bInterfaceSubClass; */ + 0x00, /* __u8 if_bInterfaceProtocol; */ + 0x00, /* __u8 if_iInterface; */ + + /* endpoint */ + 0x07, /* __u8 ep_bLength; */ + 0x05, /* __u8 ep_bDescriptorType; Endpoint */ + 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ + 0x03, /* __u8 ep_bmAttributes; Interrupt */ + 0x08, /* __u16 ep_wMaxPacketSize; 8 Bytes */ + 0x00, + 0xff /* __u8 ep_bInterval; 255 ms */ +}; + +/* +For OHCI we need just the 2nd Byte, so we +don't need this constant byte-array + +static __u8 root_hub_hub_des[] = +{ + 0x00, * __u8 bLength; * + 0x29, * __u8 bDescriptorType; Hub-descriptor * + 0x02, * __u8 bNbrPorts; * + 0x00, * __u16 wHubCharacteristics; * + 0x00, + 0x01, * __u8 bPwrOn2pwrGood; 2ms * + 0x00, * __u8 bHubContrCurrent; 0 mA * + 0x00, * __u8 DeviceRemovable; *** 8 Ports max *** * + 0xff * __u8 PortPwrCtrlMask; *** 8 ports max *** * +}; +*/ + +/*-------------------------------------------------------------------------*/ + +/* prepare Interrupt pipe data; HUB INTERRUPT ENDPOINT */ + +static int rh_send_irq (ohci_t * ohci, void * rh_data, int rh_len) +{ + int num_ports; + int i; + int ret; + int len; + + __u8 data[8]; + + num_ports = readl (&ohci->regs->roothub.a) & 0xff; + *(__u8 *) data = (readl (&ohci->regs->roothub.status) & 0x00030000) > 0? 1: 0; + ret = *(__u8 *) data; + + for ( i = 0; i < num_ports; i++) { + *(__u8 *) (data + (i + 1) / 8) |= + ((readl (&ohci->regs->roothub.portstatus[i]) & 0x001f0000) > 0? 1: 0) << ((i + 1) % 8); + ret += *(__u8 *) (data + (i + 1) / 8); + } + len = i/8 + 1; + + if (ret > 0) { + memcpy (rh_data, data, min (len, min (rh_len, sizeof(data)))); + return len; + } + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* Virtual Root Hub INTs are polled by this timer every "intervall" ms */ + +static void rh_int_timer_do (unsigned long ptr) +{ + int len; + + urb_t * urb = (urb_t *) ptr; + ohci_t * ohci = urb->dev->bus->hcpriv; + + if(ohci->rh.send) { + len = rh_send_irq (ohci, urb->transfer_buffer, urb->transfer_buffer_length); + if (len > 0) { + urb->actual_length = len; +#ifdef DEBUG + urb_print (urb, "RET(rh)", usb_pipeout (urb->pipe)); +#endif + if (urb->complete) urb->complete (urb); + } + } + rh_init_int_timer (urb); +} + +/*-------------------------------------------------------------------------*/ + +/* Root Hub INTs are polled by this timer */ + +static int rh_init_int_timer (urb_t * urb) +{ + ohci_t * ohci = urb->dev->bus->hcpriv; + + ohci->rh.interval = urb->interval; + init_timer (&ohci->rh.rh_int_timer); + ohci->rh.rh_int_timer.function = rh_int_timer_do; + ohci->rh.rh_int_timer.data = (unsigned long) urb; + ohci->rh.rh_int_timer.expires = + jiffies + (HZ * (urb->interval < 30? 30: urb->interval)) / 1000; + add_timer (&ohci->rh.rh_int_timer); + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +#define OK(x) len = (x); break +#define WR_RH_STAT(x) writel((x), &ohci->regs->roothub.status) +#define WR_RH_PORTSTAT(x) writel((x), &ohci->regs->roothub.portstatus[wIndex-1]) +#define RD_RH_STAT readl(&ohci->regs->roothub.status) +#define RD_RH_PORTSTAT readl(&ohci->regs->roothub.portstatus[wIndex-1]) + +/* request to virtual root hub */ + +static int rh_submit_urb (urb_t * urb) +{ + struct usb_device * usb_dev = urb->dev; + ohci_t * ohci = usb_dev->bus->hcpriv; + unsigned int pipe = urb->pipe; + devrequest * cmd = (devrequest *) urb->setup_packet; + void * data = urb->transfer_buffer; + int leni = urb->transfer_buffer_length; + int len = 0; + int status = TD_CC_NOERROR; + + __u8 datab[16]; + __u8 * data_buf = datab; + + __u16 bmRType_bReq; + __u16 wValue; + __u16 wIndex; + __u16 wLength; + + if (usb_pipeint(pipe)) { + + ohci->rh.urb = urb; + ohci->rh.send = 1; + ohci->rh.interval = urb->interval; + rh_init_int_timer(urb); + urb->status = cc_to_error [TD_CC_NOERROR]; + + return 0; + } + + bmRType_bReq = cmd->requesttype | (cmd->request << 8); + wValue = le16_to_cpu (cmd->value); + wIndex = le16_to_cpu (cmd->index); + wLength = le16_to_cpu (cmd->length); + switch (bmRType_bReq) { + /* Request Destination: + without flags: Device, + RH_INTERFACE: interface, + RH_ENDPOINT: endpoint, + RH_CLASS means HUB here, + RH_OTHER | RH_CLASS almost ever means HUB_PORT here + */ + + case RH_GET_STATUS: + *(__u16 *) data_buf = cpu_to_le16 (1); OK (2); + case RH_GET_STATUS | RH_INTERFACE: + *(__u16 *) data_buf = cpu_to_le16 (0); OK (2); + case RH_GET_STATUS | RH_ENDPOINT: + *(__u16 *) data_buf = cpu_to_le16 (0); OK (2); + case RH_GET_STATUS | RH_CLASS: + *(__u32 *) data_buf = cpu_to_le32 (RD_RH_STAT & 0x7fff7fff); OK (4); + case RH_GET_STATUS | RH_OTHER | RH_CLASS: + *(__u32 *) data_buf = cpu_to_le32 (RD_RH_PORTSTAT); OK (4); + + case RH_CLEAR_FEATURE | RH_ENDPOINT: + switch (wValue) { + case (RH_ENDPOINT_STALL): OK (0); + } + break; + + 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_HS_OCIC); OK (0); + } + break; + + case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: + switch (wValue) { + case (RH_PORT_ENABLE): + WR_RH_PORTSTAT (RH_PS_CCS ); OK (0); + case (RH_PORT_SUSPEND): + WR_RH_PORTSTAT (RH_PS_POCI); OK (0); + case (RH_PORT_POWER): + WR_RH_PORTSTAT (RH_PS_LSDA); OK (0); + case (RH_C_PORT_CONNECTION): + WR_RH_PORTSTAT (RH_PS_CSC ); OK (0); + case (RH_C_PORT_ENABLE): + WR_RH_PORTSTAT (RH_PS_PESC); OK (0); + case (RH_C_PORT_SUSPEND): + WR_RH_PORTSTAT (RH_PS_PSSC); OK (0); + case (RH_C_PORT_OVER_CURRENT): + WR_RH_PORTSTAT (RH_PS_OCIC); OK (0); + case (RH_C_PORT_RESET): + WR_RH_PORTSTAT (RH_PS_PRSC); OK (0); + } + break; + + case RH_SET_FEATURE | RH_OTHER | RH_CLASS: + switch (wValue) { + case (RH_PORT_SUSPEND): + WR_RH_PORTSTAT (RH_PS_PSS ); OK (0); + case (RH_PORT_RESET): /* BUG IN HUP CODE *********/ + if((RD_RH_PORTSTAT &1) != 0) WR_RH_PORTSTAT (RH_PS_PRS ); OK (0); + case (RH_PORT_POWER): + WR_RH_PORTSTAT (RH_PS_PPS ); OK (0); + case (RH_PORT_ENABLE): /* BUG IN HUP CODE *********/ + if((RD_RH_PORTSTAT &1) != 0) WR_RH_PORTSTAT (RH_PS_PES ); OK (0); + } + break; + + case RH_SET_ADDRESS: ohci->rh.devnum = wValue; OK(0); + + case RH_GET_DESCRIPTOR: + switch ((wValue & 0xff00) >> 8) { + case (0x01): /* device descriptor */ + len = min (leni, min (sizeof (root_hub_dev_des), wLength)); + data_buf = root_hub_dev_des; OK(len); + case (0x02): /* configuration descriptor */ + len = min (leni, min (sizeof (root_hub_config_des), wLength)); + data_buf = root_hub_config_des; OK(len); + case (0x03): /* string descriptors */ + default: + status = TD_CC_STALL; + } + break; + + case RH_GET_DESCRIPTOR | RH_CLASS: + *(__u8 *) (data_buf+1) = 0x29; + *(__u32 *) (data_buf+2) = cpu_to_le32 (readl (&ohci->regs->roothub.a)); + *(__u8 *) data_buf = (*(__u8 *) (data_buf + 2) / 8) * 2 + 9; /* length of descriptor */ + + len = min (leni, min(*(__u8 *) data_buf, wLength)); + *(__u8 *) (data_buf+6) = 0; /* Root Hub needs no current from bus */ + if (*(__u8 *) (data_buf+2) < 8) { /* less than 8 Ports */ + *(__u8 *) (data_buf+7) = readl (&ohci->regs->roothub.b) & 0xff; + *(__u8 *) (data_buf+8) = (readl (&ohci->regs->roothub.b) & 0xff0000) >> 16; + } else { + *(__u32 *) (data_buf+7) = cpu_to_le32 (readl(&ohci->regs->roothub.b)); + } + OK (len); + + case RH_GET_CONFIGURATION: *(__u8 *) data_buf = 0x01; OK (1); + + case RH_SET_CONFIGURATION: WR_RH_STAT (0x10000); OK (0); + + default: + status = TD_CC_STALL; + } + + dbg("USB HC roothubstat1: %x", readl ( &(ohci->regs->roothub.portstatus[0]) )); + dbg("USB HC roothubstat2: %x", readl ( &(ohci->regs->roothub.portstatus[1]) )); + + len = min(len, leni); + memcpy (data, data_buf, len); + urb->actual_length = len; + urb->status = cc_to_error [status]; + +#ifdef DEBUG + urb_print (urb, "RET(rh)", usb_pipeout (urb->pipe)); +#endif + + if (urb->complete) urb->complete (urb); + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static int rh_unlink_urb (urb_t * urb) +{ + ohci_t * ohci = urb->dev->bus->hcpriv; + + ohci->rh.send = 0; + del_timer (&ohci->rh.rh_int_timer); + return 0; +} + +/*-------------------------------------------------------------------------* + * HC functions + *-------------------------------------------------------------------------*/ + +/* reset the HC not the BUS */ + +static void hc_reset (ohci_t * ohci) +{ + int timeout = 30; + int smm_timeout = 50; /* 0,5 sec */ + + if (readl (&ohci->regs->control) & 0x100) { /* SMM owns the HC */ + writel (0x08, &ohci->regs->cmdstatus); /* request ownership */ + dbg("USB HC TakeOver from SMM"); + while (readl (&ohci->regs->control) & 0x100) { + wait_ms (10); + if (--smm_timeout == 0) { + err("USB HC TakeOver failed!"); + break; + } + } + } + + writel ((1 << 31), &ohci->regs->intrdisable); /* Disable HC interrupts */ + dbg("USB HC reset_hc: %x ;", readl (&ohci->regs->control)); + /* this seems to be needed for the lucent controller on powerbooks.. */ + writel (0, &ohci->regs->control); /* Move USB to reset state */ + + writel (1, &ohci->regs->cmdstatus); /* HC Reset */ + while ((readl (&ohci->regs->cmdstatus) & 0x01) != 0) { /* 10us Reset */ + if (--timeout == 0) { + err("USB HC reset timed out!"); + return; + } + udelay (1); + } +} + +/*-------------------------------------------------------------------------*/ + +/* Start an OHCI controller, set the BUS operational + * enable interrupts + * connect the virtual root hub */ + +static int hc_start (ohci_t * ohci) +{ + unsigned int mask; + unsigned int fminterval; + struct usb_device * usb_dev; + struct ohci_device * dev; + + /* Tell the controller where the control and bulk lists are + * The lists are empty now. */ + + writel (0, &ohci->regs->ed_controlhead); + writel (0, &ohci->regs->ed_bulkhead); + + writel (virt_to_bus (&ohci->hcca), &ohci->regs->hcca); /* a reset clears this */ + + fminterval = 0x2edf; + writel ((fminterval * 9) / 10, &ohci->regs->periodicstart); + fminterval |= ((((fminterval - 210) * 6) / 7) << 16); + writel (fminterval, &ohci->regs->fminterval); + writel (0x628, &ohci->regs->lsthresh); + + /* Choose the interrupts we care about now, others later on demand */ + mask = OHCI_INTR_MIE | OHCI_INTR_WDH | OHCI_INTR_SO; + + 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 */ + + usb_dev = usb_alloc_dev (NULL, ohci->bus); + if (!usb_dev) return -1; + + dev = usb_to_ohci (usb_dev); + ohci->bus->root_hub = usb_dev; + usb_connect (usb_dev); + if (usb_new_device (usb_dev) != 0) { + usb_free_dev (usb_dev); + return -1; + } + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* an interrupt happens */ + +static void hc_interrupt (int irq, void * __ohci, struct pt_regs * r) +{ + ohci_t * ohci = __ohci; + struct ohci_regs * regs = ohci->regs; + int ints; + + 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) + return; + } + + dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca.frame_no)); + + if (ints & OHCI_INTR_WDH) { + writel (OHCI_INTR_WDH, ®s->intrdisable); + dl_done_list (ohci, dl_reverse_done_list (ohci)); + writel (OHCI_INTR_WDH, ®s->intrenable); + } + + if (ints & OHCI_INTR_SO) { + dbg("USB Schedule overrun"); + writel (OHCI_INTR_SO, ®s->intrenable); + } + + if (ints & OHCI_INTR_SF) { + unsigned int frame = le16_to_cpu (ohci->hcca.frame_no) & 1; + writel (OHCI_INTR_SF, ®s->intrdisable); + if (ohci->ed_rm_list[!frame] != NULL) { + dl_del_list (ohci, !frame); + } + if (ohci->ed_rm_list[frame] != NULL) writel (OHCI_INTR_SF, ®s->intrenable); + } + writel (ints, ®s->intrstatus); + writel (OHCI_INTR_MIE, ®s->intrenable); +} + +/*-------------------------------------------------------------------------*/ + +/* allocate OHCI */ + +static ohci_t * hc_alloc_ohci (void * mem_base) +{ + int i; + ohci_t * ohci; + struct usb_bus * bus; + + ohci = (ohci_t *) __get_free_pages (GFP_KERNEL, 1); + if (!ohci) + return NULL; + + memset (ohci, 0, sizeof (ohci_t)); + + ohci->irq = -1; + ohci->regs = mem_base; + + /* for load ballancing of the interrupt branches */ + for (i = 0; i < NUM_INTS; i++) ohci->ohci_int_load[i] = 0; + for (i = 0; i < NUM_INTS; i++) ohci->hcca.int_table[i] = 0; + + /* end of control and bulk lists */ + ohci->ed_isotail = NULL; + ohci->ed_controltail = NULL; + ohci->ed_bulktail = NULL; + + bus = usb_alloc_bus (&sohci_device_operations); + if (!bus) { + free_pages ((unsigned long) ohci, 1); + return NULL; + } + + ohci->bus = bus; + bus->hcpriv = (void *) ohci; + + return ohci; +} + +/*-------------------------------------------------------------------------*/ + +/* De-allocate all resources.. */ + +static void hc_release_ohci (ohci_t * ohci) +{ + dbg("USB HC release ohci"); + + /* disconnect all devices */ + if (ohci->bus->root_hub) usb_disconnect (&ohci->bus->root_hub); + + hc_reset (ohci); + writel (OHCI_USB_RESET, &ohci->regs->control); + wait_ms (10); + + if (ohci->irq >= 0) { + free_irq (ohci->irq, ohci); + ohci->irq = -1; + } + + usb_deregister_bus (ohci->bus); + usb_free_bus (ohci->bus); + + /* unmap the IO address space */ + iounmap (ohci->regs); + + free_pages ((unsigned long) ohci, 1); +} + +/*-------------------------------------------------------------------------*/ + +/* Increment the module usage count, start the control thread and + * return success. */ + +static int hc_found_ohci (int irq, void * mem_base) +{ + ohci_t * ohci; + dbg("USB HC found: irq= %d membase= %lx", irq, (unsigned long) mem_base); + + ohci = hc_alloc_ohci (mem_base); + if (!ohci) { + return -ENOMEM; + } + + INIT_LIST_HEAD (&ohci->ohci_hcd_list); + list_add (&ohci->ohci_hcd_list, &ohci_hcd_list); + + hc_reset (ohci); + writel (ohci->hc_control = OHCI_USB_RESET, &ohci->regs->control); + wait_ms (10); + usb_register_bus (ohci->bus); + + if (request_irq (irq, hc_interrupt, SA_SHIRQ, "ohci-usb", ohci) == 0) { + ohci->irq = irq; + hc_start (ohci); + return 0; + } + err("request interrupt %d failed", irq); + hc_release_ohci (ohci); + return -EBUSY; +} + +/*-------------------------------------------------------------------------*/ + +static int hc_start_ohci (struct pci_dev * dev) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) + unsigned long mem_base = dev->resource[0].start; +#else + 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 long) ioremap_nocache (mem_base, 4096); + + if (!mem_base) { + err("Error mapping OHCI memory"); + return -EFAULT; + } + return hc_found_ohci (dev->irq, (void *) mem_base); +} + +/*-------------------------------------------------------------------------*/ + +#ifdef CONFIG_PMAC_PBOOK + +/* On Powerbooks, put the controller into suspend mode when going + * to sleep, and do a resume when waking up. */ + +static int ohci_sleep_notify (struct pmu_sleep_notifier * self, int when) +{ + struct list_head * ohci_l; + ohci_t * ohci; + + for (ohci_l = ohci_hcd_list.next; ohci_l != &ohci_hcd_list; ohci_l = ohci_l->next) { + ohci = list_entry (ohci_l, ohci_t, ohci_hcd_list); + + switch (when) { + case PBOOK_SLEEP_NOW: + disable_irq (ohci->irq); + writel (ohci->hc_control = OHCI_USB_SUSPEND, &ohci->regs->control); + wait_ms (10); + break; + case PBOOK_WAKE: + writel (ohci->hc_control = OHCI_USB_RESUME, &ohci->regs->control); + wait_ms (20); + writel (ohci->hc_control = 0xBF, &ohci->regs->control); + enable_irq (ohci->irq); + break; + } + } + return PBOOK_SLEEP_OK; +} + +static struct pmu_sleep_notifier ohci_sleep_notifier = { + ohci_sleep_notify, SLEEP_LEVEL_MISC, +}; +#endif /* CONFIG_PMAC_PBOOK */ + +/*-------------------------------------------------------------------------*/ + +#ifdef CONFIG_APM +static int handle_apm_event (apm_event_t event) +{ + static int down = 0; + ohci_t * ohci; + struct list_head * ohci_l; + + switch (event) { + case APM_SYS_SUSPEND: + case APM_USER_SUSPEND: + if (down) { + dbg("received extra suspend event"); + break; + } + for (ohci_l = ohci_hcd_list.next; ohci_l != &ohci_hcd_list; ohci_l = ohci_l->next) { + ohci = list_entry (ohci_l, ohci_t, ohci_hcd_list); + dbg("USB-Bus suspend: %p", ohci); + writel (ohci->hc_control = 0xFF, &ohci->regs->control); + } + wait_ms (10); + down = 1; + break; + case APM_NORMAL_RESUME: + case APM_CRITICAL_RESUME: + if (!down) { + dbg("received bogus resume event"); + break; + } + for (ohci_l = ohci_hcd_list.next; ohci_l != &ohci_hcd_list; ohci_l = ohci_l->next) { + ohci = list_entry(ohci_l, ohci_t, ohci_hcd_list); + dbg("USB-Bus resume: %p", ohci); + writel (ohci->hc_control = 0x7F, &ohci->regs->control); + } + wait_ms (20); + for (ohci_l = ohci_hcd_list.next; ohci_l != &ohci_hcd_list; ohci_l = ohci_l->next) { + ohci = list_entry (ohci_l, ohci_t, ohci_hcd_list); + writel (ohci->hc_control = 0xBF, &ohci->regs->control); + } + down = 0; + break; + } + return 0; +} +#endif + +/*-------------------------------------------------------------------------*/ + +#define PCI_CLASS_SERIAL_USB_OHCI 0x0C0310 + +int ohci_hcd_init (void) +{ + int ret = -ENODEV; + struct pci_dev * dev = NULL; + + while ((dev = pci_find_class (PCI_CLASS_SERIAL_USB_OHCI, dev))) { + if (hc_start_ohci(dev) >= 0) ret = 0; + } + +#ifdef CONFIG_APM + apm_register_callback (&handle_apm_event); +#endif + +#ifdef CONFIG_PMAC_PBOOK + pmu_register_sleep_notifier (&ohci_sleep_notifier); +#endif + return ret; +} + +/*-------------------------------------------------------------------------*/ + +#ifdef MODULE +int init_module (void) +{ + return ohci_hcd_init (); +} + +/*-------------------------------------------------------------------------*/ + +void cleanup_module (void) +{ + ohci_t * ohci; + +#ifdef CONFIG_APM + apm_unregister_callback (&handle_apm_event); +#endif + +#ifdef CONFIG_PMAC_PBOOK + pmu_unregister_sleep_notifier (&ohci_sleep_notifier); +#endif + + while (!list_empty (&ohci_hcd_list)) { + ohci = list_entry (ohci_hcd_list.next, ohci_t, ohci_hcd_list); + list_del (&ohci->ohci_hcd_list); + INIT_LIST_HEAD (&ohci->ohci_hcd_list); + hc_release_ohci (ohci); + } +} +#endif //MODULE + diff --git a/drivers/usb/usb-ohci.h b/drivers/usb/usb-ohci.h new file mode 100644 index 000000000..6098f0b39 --- /dev/null +++ b/drivers/usb/usb-ohci.h @@ -0,0 +1,407 @@ + /* + * URB OHCI HCD (Host Controller Driver) for USB. + * + *(C) Copyright 1999 Roman Weissgaerber + * + * usb-ohci.h + * + */ + + +#define MODSTR "ohci: " + + +static int cc_to_error[16] = { + +/* mapping of the OHCI CC status to error codes */ +#ifdef USB_ST_CRC /* status codes */ + /* No Error */ USB_ST_NOERROR, + /* CRC Error */ USB_ST_CRC, + /* Bit Stuff */ USB_ST_BITSTUFF, + /* Data Togg */ USB_ST_CRC, + /* Stall */ USB_ST_STALL, + /* DevNotResp */ USB_ST_NORESPONSE, + /* PIDCheck */ USB_ST_BITSTUFF, + /* UnExpPID */ USB_ST_BITSTUFF, + /* DataOver */ USB_ST_DATAOVERRUN, + /* DataUnder */ USB_ST_DATAUNDERRUN, + /* reservd */ USB_ST_NORESPONSE, + /* reservd */ USB_ST_NORESPONSE, + /* BufferOver */ USB_ST_BUFFEROVERRUN, + /* BuffUnder */ USB_ST_BUFFERUNDERRUN, + /* Not Access */ USB_ST_NORESPONSE, + /* Not Access */ USB_ST_NORESPONSE +}; + +#else /* error codes */ + /* No Error */ 0, + /* CRC Error */ -EILSEQ, + /* Bit Stuff */ -EPROTO, + /* Data Togg */ -EILSEQ, + /* Stall */ -EPIPE, + /* DevNotResp */ -ETIMEDOUT, + /* PIDCheck */ -EPROTO, + /* UnExpPID */ -EPROTO, + /* DataOver */ -EOVERFLOW, + /* DataUnder */ -EREMOTEIO, + /* reservd */ -ETIMEDOUT, + /* reservd */ -ETIMEDOUT, + /* BufferOver */ -ECOMM, + /* BuffUnder */ -ECOMM, + /* Not Access */ -ETIMEDOUT, + /* Not Access */ -ETIMEDOUT +}; +#define USB_ST_URB_PENDING -EINPROGRESS +#endif + + + +struct ed; +struct td; +/* for ED and TD structures */ + +/* ED States */ + +#define ED_NEW 0x00 +#define ED_UNLINK 0x01 +#define ED_OPER 0x02 +#define ED_DEL 0x04 +#define ED_URB_DEL 0x08 + +/* usb_ohci_ed */ +typedef struct ed { + __u32 hwINFO; + __u32 hwTailP; + __u32 hwHeadP; + __u32 hwNextED; + + struct ed * ed_prev; + __u8 int_period; + __u8 int_branch; + __u8 int_load; + __u8 int_interval; + __u8 state; + __u8 type; + __u16 last_iso; + struct ed * ed_rm_list; + +} ed_t; + + +/* TD info field */ +#define TD_CC 0xf0000000 +#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f) +#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28) +#define TD_EC 0x0C000000 +#define TD_T 0x03000000 +#define TD_T_DATA0 0x02000000 +#define TD_T_DATA1 0x03000000 +#define TD_T_TOGGLE 0x00000000 +#define TD_R 0x00040000 +#define TD_DI 0x00E00000 +#define TD_DI_SET(X) (((X) & 0x07)<< 21) +#define TD_DP 0x00180000 +#define TD_DP_SETUP 0x00000000 +#define TD_DP_IN 0x00100000 +#define TD_DP_OUT 0x00080000 + +#define TD_ISO 0x00010000 +#define TD_DEL 0x00020000 + +/* CC Codes */ +#define TD_CC_NOERROR 0x00 +#define TD_CC_CRC 0x01 +#define TD_CC_BITSTUFFING 0x02 +#define TD_CC_DATATOGGLEM 0x03 +#define TD_CC_STALL 0x04 +#define TD_DEVNOTRESP 0x05 +#define TD_PIDCHECKFAIL 0x06 +#define TD_UNEXPECTEDPID 0x07 +#define TD_DATAOVERRUN 0x08 +#define TD_DATAUNDERRUN 0x09 +#define TD_BUFFEROVERRUN 0x0C +#define TD_BUFFERUNDERRUN 0x0D +#define TD_NOTACCESSED 0x0F + + +#define MAXPSW 1 + +typedef struct td { + __u32 hwINFO; + __u32 hwCBP; /* Current Buffer Pointer */ + __u32 hwNextTD; /* Next TD Pointer */ + __u32 hwBE; /* Memory Buffer End Pointer */ + __u16 hwPSW[MAXPSW]; + + __u8 type; + __u8 index; + struct ed * ed; + struct td * next_dl_td; + urb_t * urb; +} td_t; + + +/* TD types */ +#define BULK 0x03 +#define INT 0x01 +#define CTRL 0x02 +#define ISO 0x00 + +#define SEND 0x01 +#define ST_ADDR 0x02 +#define ADD_LEN 0x04 +#define DEL 0x08 + + +#define OHCI_ED_SKIP (1 << 14) + +/* + * The HCCA (Host Controller Communications Area) is a 256 byte + * structure defined in the OHCI spec. that the host controller is + * told the base address of. It must be 256-byte aligned. + */ + +#define NUM_INTS 32 /* part of the OHCI standard */ +struct ohci_hcca { + __u32 int_table[NUM_INTS]; /* Interrupt ED table */ + __u16 frame_no; /* current frame number */ + __u16 pad1; /* set to 0 on each frame_no change */ + __u32 done_head; /* info returned for an interrupt */ + u8 reserved_for_hc[116]; +} __attribute((aligned(256))); + + +/* + * Maximum number of root hub ports. + */ +#define MAX_ROOT_PORTS 15 /* maximum OHCI root hub ports */ + +/* + * This is the structure of the OHCI controller's memory mapped I/O + * region. This is Memory Mapped I/O. You must use the readl() and + * writel() macros defined in asm/io.h to access these!! + */ +struct ohci_regs { + /* control and status registers */ + __u32 revision; + __u32 control; + __u32 cmdstatus; + __u32 intrstatus; + __u32 intrenable; + __u32 intrdisable; + /* memory pointers */ + __u32 hcca; + __u32 ed_periodcurrent; + __u32 ed_controlhead; + __u32 ed_controlcurrent; + __u32 ed_bulkhead; + __u32 ed_bulkcurrent; + __u32 donehead; + /* frame counters */ + __u32 fminterval; + __u32 fmremaining; + __u32 fmnumber; + __u32 periodicstart; + __u32 lsthresh; + /* Root hub ports */ + struct ohci_roothub_regs { + __u32 a; + __u32 b; + __u32 status; + __u32 portstatus[MAX_ROOT_PORTS]; + } roothub; +} __attribute((aligned(32))); + +/* + * cmdstatus register */ +#define OHCI_CLF 0x02 +#define OHCI_BLF 0x04 + +/* + * Interrupt register masks + */ +#define OHCI_INTR_SO (1) +#define OHCI_INTR_WDH (1 << 1) +#define OHCI_INTR_SF (1 << 2) +#define OHCI_INTR_RD (1 << 3) +#define OHCI_INTR_UE (1 << 4) +#define OHCI_INTR_FNO (1 << 5) +#define OHCI_INTR_RHSC (1 << 6) +#define OHCI_INTR_OC (1 << 30) +#define OHCI_INTR_MIE (1 << 31) + +/* + * Control register masks + */ +#define OHCI_USB_RESET 0 +#define OHCI_USB_RESUME (1 << 6) +#define OHCI_USB_OPER (2 << 6) +#define OHCI_USB_SUSPEND (3 << 6) + + +/* Virtual Root HUB */ +struct virt_root_hub { + int devnum; /* Address of Root Hub endpoint */ + void * urb; + void * int_addr; + int send; + int interval; + struct timer_list rh_int_timer; +}; + +/* destination of request */ +#define RH_INTERFACE 0x01 +#define RH_ENDPOINT 0x02 +#define RH_OTHER 0x03 + +#define RH_CLASS 0x20 +#define RH_VENDOR 0x40 + +/* Requests: bRequest << 8 | bmRequestType */ +#define RH_GET_STATUS 0x0080 +#define RH_CLEAR_FEATURE 0x0100 +#define RH_SET_FEATURE 0x0300 +#define RH_SET_ADDRESS 0x0500 +#define RH_GET_DESCRIPTOR 0x0680 +#define RH_SET_DESCRIPTOR 0x0700 +#define RH_GET_CONFIGURATION 0x0880 +#define RH_SET_CONFIGURATION 0x0900 +#define RH_GET_STATE 0x0280 +#define RH_GET_INTERFACE 0x0A80 +#define RH_SET_INTERFACE 0x0B00 +#define RH_SYNC_FRAME 0x0C80 +/* Our Vendor Specific Request */ +#define RH_SET_EP 0x2000 + + +/* Hub port features */ +#define RH_PORT_CONNECTION 0x00 +#define RH_PORT_ENABLE 0x01 +#define RH_PORT_SUSPEND 0x02 +#define RH_PORT_OVER_CURRENT 0x03 +#define RH_PORT_RESET 0x04 +#define RH_PORT_POWER 0x08 +#define RH_PORT_LOW_SPEED 0x09 +#define RH_C_PORT_CONNECTION 0x10 +#define RH_C_PORT_ENABLE 0x11 +#define RH_C_PORT_SUSPEND 0x12 +#define RH_C_PORT_OVER_CURRENT 0x13 +#define RH_C_PORT_RESET 0x14 + +/* Hub features */ +#define RH_C_HUB_LOCAL_POWER 0x00 +#define RH_C_HUB_OVER_CURRENT 0x01 + +#define RH_DEVICE_REMOTE_WAKEUP 0x00 +#define RH_ENDPOINT_STALL 0x01 + +#define RH_ACK 0x01 +#define RH_REQ_ERR -1 +#define RH_NACK 0x00 + +/* Root-Hub Register info */ + +#define RH_PS_CCS 0x00000001 +#define RH_PS_PES 0x00000002 +#define RH_PS_PSS 0x00000004 +#define RH_PS_POCI 0x00000008 +#define RH_PS_PRS 0x00000010 +#define RH_PS_PPS 0x00000100 +#define RH_PS_LSDA 0x00000200 +#define RH_PS_CSC 0x00010000 +#define RH_PS_PESC 0x00020000 +#define RH_PS_PSSC 0x00040000 +#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)) + + +/* urb */ +typedef struct +{ + ed_t * ed; + __u16 length; // number of tds associated with this request + __u16 td_cnt; // number of tds already serviced + int state; + void * wait; + td_t * td[0]; // list pointer to all corresponding TDs associated with this request + +} urb_priv_t; +#define URB_DEL 1 + +/* + * This is the full ohci controller description + * + * Note how the "proper" USB information is just + * a subset of what the full implementation needs. (Linus) + */ + + +typedef struct ohci { + struct ohci_hcca hcca; /* hcca */ + + int irq; + struct ohci_regs * regs; /* OHCI controller's memory */ + struct list_head ohci_hcd_list; /* list of all ohci_hcd */ + + struct ohci * next; // chain of uhci device contexts + struct list_head urb_list; // list of all pending urbs + spinlock_t urb_list_lock; // lock to keep consistency + + int ohci_int_load[32]; /* load of the 32 Interrupt Chains (for load ballancing)*/ + ed_t * ed_rm_list[2]; /* lists of all endpoints to be removed */ + ed_t * ed_bulktail; /* last endpoint of bulk list */ + ed_t * ed_controltail; /* last endpoint of control list */ + ed_t * ed_isotail; /* last endpoint of iso list */ + int intrstatus; + __u32 hc_control; /* copy of the hc control reg */ + struct usb_bus * bus; + struct usb_device * dev[128]; + struct virt_root_hub rh; +} ohci_t; + + +#define NUM_TDS 0 /* num of preallocated transfer descriptors */ +#define NUM_EDS 32 /* num of preallocated endpoint descriptors */ + +struct ohci_device { + ed_t ed[NUM_EDS]; + int ed_cnt; + void * wait; +}; + +// #define ohci_to_usb(ohci) ((ohci)->usb) +#define usb_to_ohci(usb) ((struct ohci_device *)(usb)->hcpriv) + +/* hcd */ +/* endpoint */ +static int ep_link(ohci_t * ohci, ed_t * ed); +static int ep_unlink(ohci_t * ohci, ed_t * ed); +static ed_t * ep_add_ed(struct usb_device * usb_dev, unsigned int pipe, int interval, int load); +static void ep_rm_ed(struct usb_device * usb_dev, ed_t * ed); +/* td */ +static void td_fill(unsigned int info, void * data, int len, urb_t * urb, int type, int index); +static void td_submit_urb(urb_t * urb); +/* root hub */ +static int rh_submit_urb(urb_t * urb); +static int rh_unlink_urb(urb_t * urb); +static int rh_init_int_timer(urb_t * urb); + +#ifdef DEBUG +#define OHCI_FREE(x) kfree(x); printk("OHCI FREE: %d: %4x\n", -- __ohci_free_cnt, (unsigned int) x) +#define OHCI_ALLOC(x,size) (x) = kmalloc(size, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); printk("OHCI ALLO: %d: %4x\n", ++ __ohci_free_cnt,(unsigned int) x) +static int __ohci_free_cnt = 0; +#else +#define OHCI_FREE(x) kfree(x) +#define OHCI_ALLOC(x,size) (x) = kmalloc(size, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL) +#endif + diff --git a/drivers/usb/usb-serial.c b/drivers/usb/usb-serial.c index 8826bc522..9f37fcc9e 100644 --- a/drivers/usb/usb-serial.c +++ b/drivers/usb/usb-serial.c @@ -14,6 +14,24 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (01/25/2000) gkh + * Added initial framework for FTDI serial converter so that Bill Ryder + * has a place to put his code. + * Added the vendor specific info from Handspring. Now we can print out + * informational debug messages as well as understand what is happening. + * + * (01/23/2000) gkh + * Fixed problem of crash when trying to open a port that didn't have a + * device assigned to it. Made the minor node finding a little smarter, + * now it looks to find a continous space for the new device. + * + * (01/21/2000) gkh + * Fixed bug in visor_startup with patch from Miles Lott (milos@insync.net) + * Fixed get_serial_by_minor which was all messed up for multi port + * devices. Fixed multi port problem for generic devices. Now the number + * of ports is determined by the number of bulk out endpoints for the + * generic device. + * * (01/19/2000) gkh * Removed lots of cruft that was around from the old (pre urb) driver * interface. @@ -141,15 +159,16 @@ static void usb_serial_disconnect(struct usb_device *dev, void *ptr); /* USB Serial devices vendor ids and device ids that this driver supports */ #define BELKIN_VENDOR_ID 0x056c -#define BELKIN_SERIAL_CONVERTER 0x8007 +#define BELKIN_SERIAL_CONVERTER_ID 0x8007 #define PERACOM_VENDOR_ID 0x0565 -#define PERACOM_SERIAL_CONVERTER 0x0001 +#define PERACOM_SERIAL_CONVERTER_ID 0x0001 #define CONNECT_TECH_VENDOR_ID 0x0710 #define CONNECT_TECH_FAKE_WHITE_HEAT_ID 0x0001 #define CONNECT_TECH_WHITE_HEAT_ID 0x8001 #define HANDSPRING_VENDOR_ID 0x082d #define HANDSPRING_VISOR_ID 0x0100 - +#define FTDI_VENDOR_ID 0x0403 +#define FTDI_SERIAL_CONVERTER_ID 0x8372 #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 */ @@ -267,7 +286,7 @@ static void etek_serial_close (struct tty_struct *tty, struct file *filp); #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; +static __u16 belkin_product_id = BELKIN_SERIAL_CONVERTER_ID; static struct usb_serial_device_type belkin_device = { name: "Belkin", idVendor: &belkin_vendor_id, /* the Belkin vendor id */ @@ -291,7 +310,7 @@ static struct usb_serial_device_type belkin_device = { #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; +static __u16 peracom_product_id = PERACOM_SERIAL_CONVERTER_ID; static struct usb_serial_device_type peracom_device = { name: "Peracom", idVendor: &peracom_vendor_id, /* the Peracom vendor id */ @@ -359,6 +378,58 @@ static struct usb_serial_device_type whiteheat_device = { #ifdef CONFIG_USB_SERIAL_VISOR + +/**************************************************************************** + * Handspring Visor Vendor specific request codes (bRequest values) + * A big thank you to Handspring for providing the following information. + * If anyone wants the original file where these values and structures came + * from, send email to . + ****************************************************************************/ + +/**************************************************************************** + * VISOR_REQUEST_BYTES_AVAILABLE asks the visor for the number of bytes that + * are available to be transfered to the host for the specified endpoint. + * Currently this is not used, and always returns 0x0001 + ****************************************************************************/ +#define VISOR_REQUEST_BYTES_AVAILABLE 0x01 + +/**************************************************************************** + * VISOR_CLOSE_NOTIFICATION is set to the device to notify it that the host + * is now closing the pipe. An empty packet is sent in response. + ****************************************************************************/ +#define VISOR_CLOSE_NOTIFICATION 0x02 + +/**************************************************************************** + * VISOR_GET_CONNECTION_INFORMATION is sent by the host during enumeration to + * get the endpoints used by the connection. + ****************************************************************************/ +#define VISOR_GET_CONNECTION_INFORMATION 0x03 + + +/**************************************************************************** + * VISOR_GET_CONNECTION_INFORMATION returns data in the following format + ****************************************************************************/ +struct visor_connection_info { + __u16 num_ports; + struct { + __u8 port_function_id; + __u8 port; + } connections[2]; +}; + + +/* struct visor_connection_info.connection[x].port defines: */ +#define VISOR_ENDPOINT_1 0x01 +#define VISOR_ENDPOINT_2 0x02 + +/* struct visor_connection_info.connection[x].port_function_id defines: */ +#define VISOR_FUNCTION_GENERIC 0x00 +#define VISOR_FUNCTION_DEBUGGER 0x01 +#define VISOR_FUNCTION_HOTSYNC 0x02 +#define VISOR_FUNCTION_CONSOLE 0x03 +#define VISOR_FUNCTION_REMOTE_FILE_SYS 0x04 + + /* 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); @@ -391,6 +462,34 @@ static struct usb_serial_device_type handspring_device = { }; #endif + +#ifdef CONFIG_USB_SERIAL_FTDI +/* function prototypes for a FTDI serial converter */ +static int ftdi_serial_open (struct tty_struct *tty, struct file *filp); +static void ftdi_serial_close (struct tty_struct *tty, struct file *filp); + +/* All of the device info needed for the Handspring Visor */ +static __u16 ftdi_vendor_id = FTDI_VENDOR_ID; +static __u16 ftdi_product_id = FTDI_SERIAL_CONVERTER_ID; +static struct usb_serial_device_type ftdi_device = { + name: "FTDI", + idVendor: &ftdi_vendor_id, /* the FTDI vendor ID */ + idProduct: &ftdi_product_id, /* the FTDI product id */ + needs_interrupt_in: MUST_HAVE_NOT, /* this device must not 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_interrupt_in: 0, + num_bulk_in: 1, + num_bulk_out: 1, + num_ports: 1, + open: ftdi_serial_open, + close: ftdi_serial_close, + write: generic_serial_write, + write_room: generic_write_room, + chars_in_buffer: generic_chars_in_buffer +}; +#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. */ @@ -410,6 +509,9 @@ static struct usb_serial_device_type *usb_serial_devices[] = { #endif #ifdef CONFIG_USB_SERIAL_VISOR &handspring_device, +#endif +#ifdef CONFIG_USB_SERIAL_FTDI + &ftdi_device, #endif NULL }; @@ -438,20 +540,27 @@ static struct usb_serial *get_serial_by_minor (int minor) 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]); + if (serial_table[minor] == NULL) + return (NULL); - return (NULL); + if (serial_table[minor] != SERIAL_PTR_EMPTY) + return (serial_table[minor]); + + i = minor; + while (serial_table[i] == SERIAL_PTR_EMPTY) { + if (i == 0) + return (NULL); + --i; + } + return (serial_table[i]); } static struct usb_serial *get_free_serial (int num_ports, int *minor) { struct usb_serial *serial = NULL; - int i; + int i, j; + int good_spot; dbg("get_free_serial %d", num_ports); @@ -459,6 +568,14 @@ static struct usb_serial *get_free_serial (int num_ports, int *minor) for (i = 0; i < SERIAL_TTY_MINORS; ++i) { if (serial_table[i]) continue; + + good_spot = 1; + for (j = 0; j < num_ports-1; ++j) + if (serial_table[i+j]) + good_spot = 0; + if (good_spot == 0) + continue; + if (!(serial = kmalloc(sizeof(struct usb_serial), GFP_KERNEL))) { err("Out of memory"); return NULL; @@ -467,7 +584,7 @@ static struct usb_serial *get_free_serial (int num_ports, int *minor) serial_table[i] = serial; *minor = i; dbg("minor base = %d", *minor); - for (i = *minor+1; (i < num_ports) && (i < SERIAL_TTY_MINORS); ++i) + for (i = *minor+1; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) serial_table[i] = SERIAL_PTR_EMPTY; return (serial); } @@ -538,6 +655,9 @@ static int serial_open (struct tty_struct *tty, struct file * filp) dbg("serial_open"); + /* initialize the pointer incase something fails */ + tty->driver_data = NULL; + /* get the serial object associated with this tty pointer */ serial = get_serial_by_minor (MINOR(tty->device)); @@ -567,15 +687,20 @@ 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 *serial = (struct usb_serial *) tty->driver_data; - int port = MINOR(tty->device) - serial->minor; + int port; + + dbg("serial_close"); - dbg("serial_close port %d", port); - - /* do some sanity checking that we really have a device present */ if (!serial) { dbg("serial == NULL!"); return; } + + 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->type) { dbg("serial->type == NULL!"); return; @@ -997,9 +1122,18 @@ static void visor_serial_close(struct tty_struct *tty, struct file * filp) { struct usb_serial *serial = (struct usb_serial *) tty->driver_data; int port = MINOR(tty->device) - serial->minor; + unsigned char *transfer_buffer = kmalloc (0x12, GFP_KERNEL); dbg("visor_serial_close port %d", port); + if (!transfer_buffer) { + err("visor_serial_close: kmalloc(%d) failed.\n", 0x12); + } else { + /* send a shutdown message to the device */ + usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_CLOSE_NOTIFICATION, + 0xc2, 0x0000, 0x0000, transfer_buffer, 0x12, 300); + } + /* shutdown our bulk reads and writes */ usb_unlink_urb (&serial->write_urb[port]); usb_unlink_urb (&serial->read_urb[port]); @@ -1034,51 +1168,10 @@ static void visor_unthrottle (struct tty_struct * tty) } -/* - 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; + int i; unsigned char *transfer_buffer = kmalloc (256, GFP_KERNEL); if (!transfer_buffer) { @@ -1091,18 +1184,44 @@ static int visor_startup (struct usb_serial *serial) 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); + /* send a get connection info request */ + response = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_GET_CONNECTION_INFORMATION, + 0xc2, 0x0000, 0x0000, transfer_buffer, 0x12, 300); if (response < 0) { - err("visor_startup: error getting first vendor specific message"); + err("visor_startup: error getting connection information"); } else { - dbg("visor_startup: First vendor specific message successful"); +#ifdef DEBUG + struct visor_connection_info *connection_info = (struct visor_connection_info *)transfer_buffer; + char *string; + dbg("%s: Number of ports: %d", serial->type->name, connection_info->num_ports); + for (i = 0; i < connection_info->num_ports; ++i) { + switch (connection_info->connections[i].port_function_id) { + case VISOR_FUNCTION_GENERIC: + string = "Generic"; + break; + case VISOR_FUNCTION_DEBUGGER: + string = "Debugger"; + break; + case VISOR_FUNCTION_HOTSYNC: + string = "HotSync"; + break; + case VISOR_FUNCTION_REMOTE_FILE_SYS: + string = "Remote File System"; + break; + default: + string = "unknown"; + break; + } + dbg("%s: port %d, is for %s", serial->type->name, connection_info->connections[i].port, string); + } +#endif } - response = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), 0x01, 0xc2, 0x0000, 0x0005, transfer_buffer, 0x02, 300); + /* ask for the number of bytes available, but ignore the response as it is broken */ + response = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_REQUEST_BYTES_AVAILABLE, + 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"); + err("visor_startup: error getting bytes available request"); } kfree (transfer_buffer); @@ -1115,6 +1234,54 @@ static int visor_startup (struct usb_serial *serial) #endif /* CONFIG_USB_SERIAL_VISOR*/ +#ifdef CONFIG_USB_SERIAL_FTDI +/****************************************************************************** + * FTDI Serial Converter specific driver functions + ******************************************************************************/ +static int ftdi_serial_open (struct tty_struct *tty, struct file *filp) +{ + struct usb_serial *serial = (struct usb_serial *) tty->driver_data; + int port = MINOR(tty->device) - serial->minor; + + dbg("ftdi_serial_open port %d", port); + + if (serial->active[port]) { + dbg ("device already open"); + return -EINVAL; + } + serial->active[port] = 1; + + /*Start reading from the device*/ + 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.) */ + /* FIXME!!! */ + + return (0); +} + + +static void ftdi_serial_close (struct tty_struct *tty, struct file *filp) +{ + struct usb_serial *serial = (struct usb_serial *) tty->driver_data; + int port = MINOR(tty->device) - serial->minor; + + dbg("ftdi_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[port]); + usb_unlink_urb (&serial->read_urb[port]); + serial->active[port] = 0; +} + + +#endif + + /***************************************************************************** * generic devices specific driver functions *****************************************************************************/ @@ -1260,6 +1427,7 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum) int num_interrupt_in = 0; int num_bulk_in = 0; int num_bulk_out = 0; + int num_ports; /* loop through our list of known serial converters, and see if this device matches */ device_num = 0; @@ -1317,7 +1485,14 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum) /* found all that we need */ info("%s converter detected", type->name); - serial = get_free_serial (type->num_ports, &minor); +#ifdef CONFIG_USB_SERIAL_GENERIC + if (type == &generic_device) + num_ports = num_bulk_out; + else +#endif + num_ports = type->num_ports; + + serial = get_free_serial (num_ports, &minor); if (serial == NULL) { err("No more free serial devices"); return NULL; @@ -1326,7 +1501,7 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum) serial->dev = dev; serial->type = type; serial->minor = minor; - serial->num_ports = type->num_ports; + serial->num_ports = num_ports; serial->num_bulk_in = num_bulk_in; serial->num_bulk_out = num_bulk_out; serial->num_interrupt_in = num_interrupt_in; @@ -1350,7 +1525,7 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum) } for (i = 0; i < num_bulk_out; ++i) { - serial->bulk_out_size[i] = bulk_out_endpoint[i]->wMaxPacketSize; + serial->bulk_out_size[i] = bulk_out_endpoint[i]->wMaxPacketSize * 2; 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"); @@ -1417,6 +1592,7 @@ static void usb_serial_disconnect(struct usb_device *dev, void *ptr) usb_unlink_urb (&serial->write_urb[i]); usb_unlink_urb (&serial->read_urb[i]); serial->active[i] = 0; + serial_table[serial->minor + i] = NULL; } /* free up any memory that we allocated */ @@ -1434,7 +1610,6 @@ static void usb_serial_disconnect(struct usb_device *dev, void *ptr) info("%s converter now disconnected from ttyUSB%d", serial->type->name, serial->minor + i); } - serial_table[serial->minor] = NULL; kfree (serial); } else { diff --git a/drivers/usb/usb-uhci.c b/drivers/usb/usb-uhci.c new file mode 100644 index 000000000..3fe469699 --- /dev/null +++ b/drivers/usb/usb-uhci.c @@ -0,0 +1,2359 @@ +/* + * Universal Host Controller Interface driver for USB (take II). + * + * (c) 1999 Georg Acher, acher@in.tum.de (executive slave) (base guitar) + * Deti Fliegl, deti@fliegl.de (executive slave) (lead voice) + * Thomas Sailer, sailer@ife.ee.ethz.ch (chief consultant) (cheer leader) + * Roman Weissgaerber, weissg@vienna.at (virt root hub) (studio porter) + * + * HW-initalization based on material of + * + * (C) Copyright 1999 Linus Torvalds + * (C) Copyright 1999 Johannes Erdfelt + * (C) Copyright 1999 Randy Dunlap + * + * $Id: usb-uhci.c,v 1.169 2000/01/20 19:50:11 acher Exp $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for in_interrupt() */ +#include + +#include +#include +#include +#include + +/* This enables debug printks */ +//#define DEBUG +/* This enables all symbols to be exported, to ease debugging oopses */ +#define DEBUG_SYMBOLS +/* This enables an extra UHCI slab for memory debugging */ +//#define DEBUG_SLAB + +#include "usb.h" +#include "usb-uhci.h" +#include "uhci-debug.h" + +#ifdef CONFIG_APM +#include +static int handle_apm_event (apm_event_t event); +#endif + +#ifdef DEBUG_SYMBOLS +#define _static +#ifndef EXPORT_SYMTAB +#define EXPORT_SYMTAB +#endif +#else +#define _static static +#endif + +#ifdef DEBUG_SLAB +static kmem_cache_t *uhci_desc_kmem; +static kmem_cache_t *urb_priv_kmem; +#endif + +_static int rh_submit_urb (purb_t purb); +_static int rh_unlink_urb (purb_t purb); +static puhci_t devs = NULL; + +/* used by userspace UHCI data structure dumper */ +puhci_t *uhci_devices = &devs; + +/*-------------------------------------------------------------------*/ +_static void queue_urb (puhci_t s, struct list_head *p, int do_lock) +{ + unsigned long flags=0; + + if (do_lock) + spin_lock_irqsave (&s->urb_list_lock, flags); + + list_add_tail (p, &s->urb_list); + + if (do_lock) + spin_unlock_irqrestore (&s->urb_list_lock, flags); +} + +/*-------------------------------------------------------------------*/ +_static void dequeue_urb (puhci_t s, struct list_head *p, int do_lock) +{ + unsigned long flags=0; + + if (do_lock) + spin_lock_irqsave (&s->urb_list_lock, flags); + + list_del (p); + + if (do_lock) + spin_unlock_irqrestore (&s->urb_list_lock, flags); +} + +/*-------------------------------------------------------------------*/ +_static int alloc_td (puhci_desc_t * new, int flags) +{ +#ifdef DEBUG_SLAB + *new= kmem_cache_alloc(uhci_desc_kmem, in_interrupt ()? SLAB_ATOMIC : SLAB_KERNEL); +#else + *new = (uhci_desc_t *) kmalloc (sizeof (uhci_desc_t), in_interrupt ()? GFP_ATOMIC : GFP_KERNEL); +#endif + if (!*new) + return -ENOMEM; + + memset (*new, 0, sizeof (uhci_desc_t)); + (*new)->hw.td.link = UHCI_PTR_TERM | (flags & UHCI_PTR_BITS); // last by default + + (*new)->type = TD_TYPE; + mb(); + INIT_LIST_HEAD (&(*new)->vertical); + INIT_LIST_HEAD (&(*new)->horizontal); + + return 0; +} +/*-------------------------------------------------------------------*/ +/* insert td at last position in td-list of qh (vertical) */ +_static int insert_td (puhci_t s, puhci_desc_t qh, puhci_desc_t new, int flags) +{ + uhci_desc_t *prev; + unsigned long xxx; + + spin_lock_irqsave (&s->td_lock, xxx); + + list_add_tail (&new->vertical, &qh->vertical); + + if (qh->hw.qh.element & UHCI_PTR_TERM) { + // virgin qh without any tds + qh->hw.qh.element = virt_to_bus (new); /* QH's cannot have the DEPTH bit set */ + } + else { + // already tds inserted + prev = list_entry (new->vertical.prev, uhci_desc_t, vertical); + // implicitely remove TERM bit of prev + prev->hw.td.link = virt_to_bus (new) | (flags & UHCI_PTR_DEPTH); + } + mb(); + spin_unlock_irqrestore (&s->td_lock, xxx); + + return 0; +} +/*-------------------------------------------------------------------*/ +/* insert new_td after td (horizontal) */ +_static int insert_td_horizontal (puhci_t s, puhci_desc_t td, puhci_desc_t new, int flags) +{ + uhci_desc_t *next; + unsigned long xxx; + + spin_lock_irqsave (&s->td_lock, xxx); + + next = list_entry (td->horizontal.next, uhci_desc_t, horizontal); + new->hw.td.link = td->hw.td.link; + mb(); + list_add (&new->horizontal, &td->horizontal); + td->hw.td.link = virt_to_bus (new); + mb(); + spin_unlock_irqrestore (&s->td_lock, xxx); + + return 0; +} +/*-------------------------------------------------------------------*/ +_static int unlink_td (puhci_t s, puhci_desc_t element) +{ + uhci_desc_t *next, *prev; + int dir = 0; + unsigned long xxx; + + spin_lock_irqsave (&s->td_lock, xxx); + + next = list_entry (element->vertical.next, uhci_desc_t, vertical); + + if (next == element) { + dir = 1; + next = list_entry (element->horizontal.next, uhci_desc_t, horizontal); + prev = list_entry (element->horizontal.prev, uhci_desc_t, horizontal); + } + else { + prev = list_entry (element->vertical.prev, uhci_desc_t, vertical); + } + + if (prev->type == TD_TYPE) + prev->hw.td.link = element->hw.td.link; + else + prev->hw.qh.element = element->hw.td.link; + + mb (); + + if (dir == 0) + list_del (&element->vertical); + else + list_del (&element->horizontal); + + spin_unlock_irqrestore (&s->td_lock, xxx); + + return 0; +} +/*-------------------------------------------------------------------*/ +_static int delete_desc (puhci_desc_t element) +{ +#ifdef DEBUG_SLAB + kmem_cache_free(uhci_desc_kmem, element); +#else + kfree (element); +#endif + return 0; +} +/*-------------------------------------------------------------------*/ +// Allocates qh element +_static int alloc_qh (puhci_desc_t * new) +{ +#ifdef DEBUG_SLAB + *new= kmem_cache_alloc(uhci_desc_kmem, in_interrupt ()? SLAB_ATOMIC : SLAB_KERNEL); +#else + *new = (uhci_desc_t *) kmalloc (sizeof (uhci_desc_t), in_interrupt ()? GFP_ATOMIC : GFP_KERNEL); +#endif + if (!*new) + return -ENOMEM; + + memset (*new, 0, sizeof (uhci_desc_t)); + (*new)->hw.qh.head = UHCI_PTR_TERM; + (*new)->hw.qh.element = UHCI_PTR_TERM; + (*new)->type = QH_TYPE; + mb(); + INIT_LIST_HEAD (&(*new)->horizontal); + INIT_LIST_HEAD (&(*new)->vertical); + + dbg("Allocated qh @ %p", *new); + + return 0; +} +/*-------------------------------------------------------------------*/ +// inserts new qh before/after the qh at pos +// flags: 0: insert before pos, 1: insert after pos (for low speed transfers) +_static int insert_qh (puhci_t s, puhci_desc_t pos, puhci_desc_t new, int flags) +{ + puhci_desc_t old; + unsigned long xxx; + + spin_lock_irqsave (&s->qh_lock, xxx); + + if (!flags) { + // (OLD) (POS) -> (OLD) (NEW) (POS) + old = list_entry (pos->horizontal.prev, uhci_desc_t, horizontal); + list_add_tail (&new->horizontal, &pos->horizontal); + new->hw.qh.head = MAKE_QH_ADDR (pos) ; + mb(); + if (!(old->hw.qh.head & UHCI_PTR_TERM)) + old->hw.qh.head = MAKE_QH_ADDR (new) ; + } + else { + // (POS) (OLD) -> (POS) (NEW) (OLD) + old = list_entry (pos->horizontal.next, uhci_desc_t, horizontal); + list_add (&new->horizontal, &pos->horizontal); + new->hw.qh.head = MAKE_QH_ADDR (old); + mb(); + pos->hw.qh.head = MAKE_QH_ADDR (new) ; + } + + mb (); + + spin_unlock_irqrestore (&s->qh_lock, xxx); + + return 0; +} +/*-------------------------------------------------------------------*/ +_static int unlink_qh (puhci_t s, puhci_desc_t element) +{ + puhci_desc_t next, prev; + unsigned long xxx; + + spin_lock_irqsave (&s->qh_lock, xxx); + + next = list_entry (element->horizontal.next, uhci_desc_t, horizontal); + prev = list_entry (element->horizontal.prev, uhci_desc_t, horizontal); + prev->hw.qh.head = element->hw.qh.head; + mb (); + list_del (&element->horizontal); + + spin_unlock_irqrestore (&s->qh_lock, xxx); + + return 0; +} +/*-------------------------------------------------------------------*/ +_static int delete_qh (puhci_t s, puhci_desc_t qh) +{ + puhci_desc_t td; + struct list_head *p; + + list_del (&qh->horizontal); + + while ((p = qh->vertical.next) != &qh->vertical) { + td = list_entry (p, uhci_desc_t, vertical); + unlink_td (s, td); + delete_desc (td); + } + + delete_desc (qh); + + return 0; +} +/*-------------------------------------------------------------------*/ +_static void clean_td_chain (puhci_desc_t td) +{ + struct list_head *p; + puhci_desc_t td1; + + if (!td) + return; + + while ((p = td->horizontal.next) != &td->horizontal) { + td1 = list_entry (p, uhci_desc_t, horizontal); + delete_desc (td1); + } + + delete_desc (td); +} +/*-------------------------------------------------------------------*/ +// Removes ALL qhs in chain (paranoia!) +_static void cleanup_skel (puhci_t s) +{ + unsigned int n; + puhci_desc_t td; + + dbg("cleanup_skel"); + + for (n = 0; n < 8; n++) { + td = s->int_chain[n]; + clean_td_chain (td); + } + + if (s->iso_td) { + for (n = 0; n < 1024; n++) { + td = s->iso_td[n]; + clean_td_chain (td); + } + kfree (s->iso_td); + } + + if (s->framelist) + free_page ((unsigned long) s->framelist); + + if (s->control_chain) { + // completed init_skel? + struct list_head *p; + puhci_desc_t qh, qh1; + + qh = s->control_chain; + while ((p = qh->horizontal.next) != &qh->horizontal) { + qh1 = list_entry (p, uhci_desc_t, horizontal); + delete_qh (s, qh1); + } + delete_qh (s, qh); + } + else { + if (s->control_chain) + kfree (s->control_chain); + if (s->bulk_chain) + kfree (s->bulk_chain); + if (s->chain_end) + kfree (s->chain_end); + } + dbg("cleanup_skel finished"); +} +/*-------------------------------------------------------------------*/ +// allocates framelist and qh-skeletons +// only HW-links provide continous linking, SW-links stay in their domain (ISO/INT) +_static int init_skel (puhci_t s) +{ + int n, ret; + puhci_desc_t qh, td; + + dbg("init_skel"); + + s->framelist = (__u32 *) get_free_page (GFP_KERNEL); + + if (!s->framelist) + return -ENOMEM; + + memset (s->framelist, 0, 4096); + + dbg("allocating iso desc pointer list"); + s->iso_td = (puhci_desc_t *) kmalloc (1024 * sizeof (puhci_desc_t), GFP_KERNEL); + + if (!s->iso_td) + goto init_skel_cleanup; + + s->control_chain = NULL; + s->bulk_chain = NULL; + s->chain_end = NULL; + + dbg("allocating iso descs"); + for (n = 0; n < 1024; n++) { + // allocate skeleton iso/irq-tds + ret = alloc_td (&td, 0); + if (ret) + goto init_skel_cleanup; + s->iso_td[n] = td; + s->framelist[n] = ((__u32) virt_to_bus (td)); + } + + dbg("allocating qh: chain_end"); + ret = alloc_qh (&qh); + + if (ret) + goto init_skel_cleanup; + + s->chain_end = qh; + + dbg("allocating qh: bulk_chain"); + ret = alloc_qh (&qh); + + if (ret) + goto init_skel_cleanup; + + insert_qh (s, s->chain_end, qh, 0); + s->bulk_chain = qh; + dbg("allocating qh: control_chain"); + ret = alloc_qh (&qh); + + if (ret) + goto init_skel_cleanup; + + insert_qh (s, s->bulk_chain, qh, 0); + s->control_chain = qh; + for (n = 0; n < 8; n++) + s->int_chain[n] = 0; + + dbg("allocating skeleton INT-TDs"); + + for (n = 0; n < 8; n++) { + puhci_desc_t td; + + alloc_td (&td, 0); + if (!td) + goto init_skel_cleanup; + s->int_chain[n] = td; + if (n == 0) { + s->int_chain[0]->hw.td.link = virt_to_bus (s->control_chain) | UHCI_PTR_QH; + } + else { + s->int_chain[n]->hw.td.link = virt_to_bus (s->int_chain[0]); + } + } + + dbg("Linking skeleton INT-TDs"); + + for (n = 0; n < 1024; n++) { + // link all iso-tds to the interrupt chains + int m, o; + dbg("framelist[%i]=%x",n,s->framelist[n]); + if ((n&127)==127) + ((puhci_desc_t) s->iso_td[n])->hw.td.link = virt_to_bus(s->int_chain[0]); + else { + for (o = 1, m = 2; m <= 128; o++, m += m) { + // n&(m-1) = n%m + if ((n & (m - 1)) == ((m - 1) / 2)) { + ((puhci_desc_t) s->iso_td[n])->hw.td.link = virt_to_bus (s->int_chain[o]); + } + } + } + } + + mb(); + //uhci_show_queue(s->control_chain); + dbg("init_skel exit"); + return 0; // OK + + init_skel_cleanup: + cleanup_skel (s); + return -ENOMEM; +} + +/*-------------------------------------------------------------------*/ +_static void fill_td (puhci_desc_t td, int status, int info, __u32 buffer) +{ + td->hw.td.status = status; + td->hw.td.info = info; + td->hw.td.buffer = buffer; +} + +/*-------------------------------------------------------------------*/ +// LOW LEVEL STUFF +// assembles QHs und TDs for control, bulk and iso +/*-------------------------------------------------------------------*/ +_static int uhci_submit_control_urb (purb_t purb) +{ + puhci_desc_t qh, td; + puhci_t s = (puhci_t) purb->dev->bus->hcpriv; + purb_priv_t purb_priv = purb->hcpriv; + unsigned long destination, status; + int maxsze = usb_maxpacket (purb->dev, purb->pipe, usb_pipeout (purb->pipe)); + unsigned long len, bytesrequested; + char *data; + + dbg("uhci_submit_control start"); + alloc_qh (&qh); // alloc qh for this request + + if (!qh) + return -ENOMEM; + + alloc_td (&td, UHCI_PTR_DEPTH); // get td for setup stage + + if (!td) { + delete_qh (s, qh); + return -ENOMEM; + } + + /* The "pipe" thing contains the destination in bits 8--18 */ + destination = (purb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP; + + /* 3 errors */ + status = (purb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | + (purb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27); + + /* Build the TD for the control request, try forever, 8 bytes of data */ + fill_td (td, status, destination | (7 << 21), virt_to_bus (purb->setup_packet)); + + /* If direction is "send", change the frame from SETUP (0x2D) + to OUT (0xE1). Else change it from SETUP to IN (0x69). */ + + destination ^= (USB_PID_SETUP ^ USB_PID_IN); /* SETUP -> IN */ + + if (usb_pipeout (purb->pipe)) + destination ^= (USB_PID_IN ^ USB_PID_OUT); /* IN -> OUT */ + + insert_td (s, qh, td, 0); // queue 'setup stage'-td in qh +#if 0 + dbg("SETUP to pipe %x: %x %x %x %x %x %x %x %x", purb->pipe, + purb->setup_packet[0], purb->setup_packet[1], purb->setup_packet[2], purb->setup_packet[3], + purb->setup_packet[4], purb->setup_packet[5], purb->setup_packet[6], purb->setup_packet[7]); + //uhci_show_td(td); +#endif + + /* Build the DATA TD's */ + len = purb->transfer_buffer_length; + bytesrequested = len; + data = purb->transfer_buffer; + + while (len > 0) { + int pktsze = len; + + alloc_td (&td, UHCI_PTR_DEPTH); + if (!td) { + delete_qh (s, qh); + return -ENOMEM; + } + + if (pktsze > maxsze) + pktsze = maxsze; + + destination ^= 1 << TD_TOKEN_TOGGLE; // toggle DATA0/1 + + fill_td (td, status, destination | ((pktsze - 1) << 21), + virt_to_bus (data)); // Status, pktsze bytes of data + + insert_td (s, qh, td, UHCI_PTR_DEPTH); // queue 'data stage'-td in qh + + data += pktsze; + len -= pktsze; + } + + /* Build the final TD for control status */ + /* It's only IN if the pipe is out AND we aren't expecting data */ + destination &= ~0xFF; + + if (usb_pipeout (purb->pipe) | (bytesrequested == 0)) + destination |= USB_PID_IN; + else + destination |= USB_PID_OUT; + + destination |= 1 << TD_TOKEN_TOGGLE; /* End in Data1 */ + + alloc_td (&td, UHCI_PTR_DEPTH); + + if (!td) { + delete_qh (s, qh); + return -ENOMEM; + } + + /* no limit on errors on final packet , 0 bytes of data */ + fill_td (td, status | TD_CTRL_IOC, destination | (UHCI_NULL_DATA_SIZE << 21), + 0); + + insert_td (s, qh, td, UHCI_PTR_DEPTH); // queue status td + + + list_add (&qh->desc_list, &purb_priv->desc_list); + + purb->status = USB_ST_URB_PENDING; + queue_urb (s, &purb->urb_list,1); // queue before inserting in desc chain + + //uhci_show_queue(qh); + + /* Start it up... put low speed first */ + if (purb->pipe & TD_CTRL_LS) + insert_qh (s, s->control_chain, qh, 1); // insert after control chain + else + insert_qh (s, s->bulk_chain, qh, 0); // insert before bulk chain + + //uhci_show_queue(qh); + dbg("uhci_submit_control end"); + return 0; +} +/*-------------------------------------------------------------------*/ +_static int uhci_submit_bulk_urb (purb_t purb) +{ + puhci_t s = (puhci_t) purb->dev->bus->hcpriv; + purb_priv_t purb_priv = purb->hcpriv; + puhci_desc_t qh, td; + unsigned long destination, status; + char *data; + unsigned int pipe = purb->pipe; + int maxsze = usb_maxpacket (purb->dev, pipe, usb_pipeout (pipe)); + int info, len; + + /* shouldn't the clear_halt be done in the USB core or in the client driver? - Thomas */ + if (usb_endpoint_halted (purb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)) && + usb_clear_halt (purb->dev, usb_pipeendpoint (pipe) | (pipe & USB_DIR_IN))) + return -EPIPE; + + if (!maxsze) + return -EMSGSIZE; + /* FIXME: should tell the client that the endpoint is invalid, i.e. not in the descriptor */ + + alloc_qh (&qh); // get qh for this request + + if (!qh) + return -ENOMEM; + + /* The "pipe" thing contains the destination in bits 8--18. */ + destination = (pipe & PIPE_DEVEP_MASK) | usb_packetid (pipe); + + /* 3 errors */ + status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | + ((purb->transfer_flags & USB_DISABLE_SPD) ? 0 : TD_CTRL_SPD) | (3 << 27); + + /* Build the TDs for the bulk request */ + len = purb->transfer_buffer_length; + data = purb->transfer_buffer; + dbg("uhci_submit_bulk_urb: pipe %x, len %d", pipe, len); + + while (len > 0) { + int pktsze = len; + + alloc_td (&td, UHCI_PTR_DEPTH); + + if (!td) { + delete_qh (s, qh); + return -ENOMEM; + } + + if (pktsze > maxsze) + pktsze = maxsze; + + // pktsze bytes of data + info = destination | ((pktsze - 1) << 21) | + (usb_gettoggle (purb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)) << TD_TOKEN_TOGGLE); + + fill_td (td, status, info, virt_to_bus (data)); + + data += pktsze; + len -= pktsze; + + if (!len) + td->hw.td.status |= TD_CTRL_IOC; // last one generates INT + //dbg("insert td %p, len %i",td,pktsze); + + insert_td (s, qh, td, UHCI_PTR_DEPTH); + + /* Alternate Data0/1 (start with Data0) */ + usb_dotoggle (purb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)); + } + + list_add (&qh->desc_list, &purb_priv->desc_list); + + purb->status = USB_ST_URB_PENDING; + queue_urb (s, &purb->urb_list,1); + + insert_qh (s, s->chain_end, qh, 0); // insert before end marker + //uhci_show_queue(s->bulk_chain); + + dbg("uhci_submit_bulk_urb: exit"); + return 0; +} +/*-------------------------------------------------------------------*/ +// unlinks an urb by dequeuing its qh, waits some frames and forgets it +// Problem: unlinking in interrupt requires waiting for one frame (udelay) +// to allow the whole structures to be safely removed +_static int uhci_unlink_urb (purb_t purb) +{ + puhci_t s; + puhci_desc_t qh; + puhci_desc_t td; + purb_priv_t purb_priv; + unsigned long flags=0; + struct list_head *p; + + if (!purb) // you never know... + return -1; + + s = (puhci_t) purb->dev->bus->hcpriv; // get pointer to uhci struct + + if (usb_pipedevice (purb->pipe) == s->rh.devnum) + return rh_unlink_urb (purb); + + if(!in_interrupt()) { + spin_lock_irqsave (&s->unlink_urb_lock, flags); // do not allow interrupts + } + + //dbg("unlink_urb called %p",purb); + if (purb->status == USB_ST_URB_PENDING) { + // URB probably still in work + purb_priv = purb->hcpriv; + dequeue_urb (s, &purb->urb_list,1); + purb->status = USB_ST_URB_KILLED; // mark urb as killed + + if(!in_interrupt()) { + spin_unlock_irqrestore (&s->unlink_urb_lock, flags); // allow interrupts from here + } + + switch (usb_pipetype (purb->pipe)) { + case PIPE_ISOCHRONOUS: + case PIPE_INTERRUPT: + for (p = purb_priv->desc_list.next; p != &purb_priv->desc_list; p = p->next) { + td = list_entry (p, uhci_desc_t, desc_list); + unlink_td (s, td); + } + // wait at least 1 Frame + if (in_interrupt ()) + udelay (1000); + else + wait_ms(1); + while ((p = purb_priv->desc_list.next) != &purb_priv->desc_list) { + td = list_entry (p, uhci_desc_t, desc_list); + list_del (p); + delete_desc (td); + } + break; + + case PIPE_BULK: + case PIPE_CONTROL: + qh = list_entry (purb_priv->desc_list.next, uhci_desc_t, desc_list); + + unlink_qh (s, qh); // remove this qh from qh-list + // wait at least 1 Frame + + if (in_interrupt ()) + udelay (1000); + else + wait_ms(1); + delete_qh (s, qh); // remove it physically + + } + +#ifdef DEBUG_SLAB + kmem_cache_free(urb_priv_kmem, purb->hcpriv); +#else + kfree (purb->hcpriv); +#endif + if (purb->complete) { + dbg("unlink_urb: calling completion"); + purb->complete ((struct urb *) purb); + usb_dec_dev_use (purb->dev); + } + return 0; + } + else { + if(!in_interrupt()) + spin_unlock_irqrestore (&s->unlink_urb_lock, flags); // allow interrupts from here + } + + return 0; +} +/*-------------------------------------------------------------------*/ +// In case of ASAP iso transfer, search the URB-list for already queued URBs +// for this EP and calculate the earliest start frame for the new +// URB (easy seamless URB continuation!) +_static int find_iso_limits (purb_t purb, unsigned int *start, unsigned int *end) +{ + purb_t u, last_urb = NULL; + puhci_t s = (puhci_t) purb->dev->bus->hcpriv; + struct list_head *p = s->urb_list.next; + int ret=-1; + unsigned long flags; + + spin_lock_irqsave (&s->urb_list_lock, flags); + + for (; p != &s->urb_list; p = p->next) { + u = list_entry (p, urb_t, urb_list); + // look for pending URBs with identical pipe handle + // works only because iso doesn't toggle the data bit! + if ((purb->pipe == u->pipe) && (purb->dev == u->dev) && (u->status == USB_ST_URB_PENDING)) { + if (!last_urb) + *start = u->start_frame; + last_urb = u; + } + } + + if (last_urb) { + *end = (last_urb->start_frame + last_urb->number_of_packets) & 1023; + ret=0; + } + + spin_unlock_irqrestore(&s->urb_list_lock, flags); + + return ret; // no previous urb found + +} +/*-------------------------------------------------------------------*/ +// adjust start_frame according to scheduling constraints (ASAP etc) + +_static int iso_find_start (purb_t purb) +{ + puhci_t s = (puhci_t) purb->dev->bus->hcpriv; + unsigned int now; + unsigned int start_limit = 0, stop_limit = 0, queued_size; + int limits; + + now = UHCI_GET_CURRENT_FRAME (s) & 1023; + + if ((unsigned) purb->number_of_packets > 900) + return -EFBIG; + + limits = find_iso_limits (purb, &start_limit, &stop_limit); + queued_size = (stop_limit - start_limit) & 1023; + + if (purb->transfer_flags & USB_ISO_ASAP) { + // first iso + if (limits) { + // 10ms setup should be enough //FIXME! + purb->start_frame = (now + 10) & 1023; + } + else { + purb->start_frame = stop_limit; //seamless linkage + + if (((now - purb->start_frame) & 1023) <= (unsigned) purb->number_of_packets) { + dbg("iso_find_start: warning, ASAP gap, should not happen"); + dbg("iso_find_start: now %u start_frame %u number_of_packets %u pipe 0x%08x", + now, purb->start_frame, purb->number_of_packets, purb->pipe); +// The following code is only for debugging purposes... +#if 0 + { + puhci_t s = (puhci_t) purb->dev->bus->hcpriv; + struct list_head *p; + purb_t u; + int a = -1, b = -1; + unsigned long flags; + + spin_lock_irqsave (&s->urb_list_lock, flags); + p=s->urb_list.next; + + for (; p != &s->urb_list; p = p->next) { + u = list_entry (p, urb_t, urb_list); + if (purb->dev != u->dev) + continue; + dbg("urb: pipe 0x%08x status %d start_frame %u number_of_packets %u", + u->pipe, u->status, u->start_frame, u->number_of_packets); + if (!usb_pipeisoc (u->pipe)) + continue; + if (a == -1) + a = u->start_frame; + b = (u->start_frame + u->number_of_packets - 1) & 1023; + } + spin_unlock_irqrestore(&s->urb_list_lock, flags); + } +#endif + purb->start_frame = (now + 5) & 1023; // 5ms setup should be enough //FIXME! + //return -EAGAIN; //FIXME + } + } + } + else { + purb->start_frame &= 1023; + if (((now - purb->start_frame) & 1023) < (unsigned) purb->number_of_packets) { + dbg("iso_find_start: now between start_frame and end"); + return -EAGAIN; + } + } + + /* check if either start_frame or start_frame+number_of_packets-1 lies between start_limit and stop_limit */ + if (limits) + return 0; + + if (((purb->start_frame - start_limit) & 1023) < queued_size || + ((purb->start_frame + purb->number_of_packets - 1 - start_limit) & 1023) < queued_size) { + dbg("iso_find_start: start_frame %u number_of_packets %u start_limit %u stop_limit %u", + purb->start_frame, purb->number_of_packets, start_limit, stop_limit); + return -EAGAIN; + } + + return 0; +} +/*-------------------------------------------------------------------*/ +// submits USB interrupt (ie. polling ;-) +// ASAP-flag set implicitely +// if period==0, the the transfer is only done once (usb_scsi need this...) + +_static int uhci_submit_int_urb (purb_t purb) +{ + puhci_t s = (puhci_t) purb->dev->bus->hcpriv; + purb_priv_t purb_priv = purb->hcpriv; + int nint, n, ret; + puhci_desc_t td; + int status, destination; + int now; + int info; + unsigned int pipe = purb->pipe; + + //dbg("SUBMIT INT"); + + if (purb->interval < 0 || purb->interval >= 256) + return -EINVAL; + + if (purb->interval == 0) + nint = 0; + else { + for (nint = 0, n = 1; nint <= 8; nint++, n += n) // round interval down to 2^n + { + if (purb->interval < n) { + purb->interval = n / 2; + break; + } + } + nint--; + } + dbg("Rounded interval to %i, chain %i", purb->interval, nint); + + now = UHCI_GET_CURRENT_FRAME (s) & 1023; + purb->start_frame = now; // remember start frame, just in case... + + purb->number_of_packets = 1; + + // INT allows only one packet + if (purb->transfer_buffer_length > usb_maxpacket (purb->dev, pipe, usb_pipeout (pipe))) + return -EINVAL; + + ret = alloc_td (&td, UHCI_PTR_DEPTH); + + if (ret) + return -ENOMEM; + + status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC | + (purb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27); + + destination = (purb->pipe & PIPE_DEVEP_MASK) | usb_packetid (purb->pipe) | + (((purb->transfer_buffer_length - 1) & 0x7ff) << 21); + + + info = destination | (usb_gettoggle (purb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)) << TD_TOKEN_TOGGLE); + + fill_td (td, status, info, virt_to_bus (purb->transfer_buffer)); + list_add_tail (&td->desc_list, &purb_priv->desc_list); + + purb->status = USB_ST_URB_PENDING; + queue_urb (s, &purb->urb_list,1); + + insert_td_horizontal (s, s->int_chain[nint], td, UHCI_PTR_DEPTH); // store in INT-TDs + + usb_dotoggle (purb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)); + +#if 0 + td = tdm[purb->number_of_packets]; + fill_td (td, TD_CTRL_IOC, 0, 0); + insert_td_horizontal (s, s->iso_td[(purb->start_frame + (purb->number_of_packets) * purb->interval + 1) & 1023], td, UHCI_PTR_DEPTH); + list_add_tail (&td->desc_list, &purb_priv->desc_list); +#endif + + return 0; +} +/*-------------------------------------------------------------------*/ +_static int uhci_submit_iso_urb (purb_t purb) +{ + puhci_t s = (puhci_t) purb->dev->bus->hcpriv; + purb_priv_t purb_priv = purb->hcpriv; + int pipe=purb->pipe; + int maxsze = usb_maxpacket (purb->dev, pipe, usb_pipeout (pipe)); + int n, ret, last=0; + puhci_desc_t td, *tdm; + int status, destination; + unsigned long flags; + spinlock_t lock; + + spin_lock_init (&lock); + spin_lock_irqsave (&lock, flags); // Disable IRQs to schedule all ISO-TDs in time + + ret = iso_find_start (purb); // adjusts purb->start_frame for later use + + if (ret) + goto err; + + tdm = (puhci_desc_t *) kmalloc (purb->number_of_packets * sizeof (puhci_desc_t), in_interrupt ()? GFP_ATOMIC : GFP_KERNEL); + + if (!tdm) { + ret = -ENOMEM; + goto err; + } + + // First try to get all TDs + for (n = 0; n < purb->number_of_packets; n++) { + dbg("n:%d purb->iso_frame_desc[n].length:%d", n, purb->iso_frame_desc[n].length); + if (!purb->iso_frame_desc[n].length) { + // allows ISO striping by setting length to zero in iso_descriptor + tdm[n] = 0; + continue; + } + if(purb->iso_frame_desc[n].length > maxsze) { + err("submit_iso: purb->iso_frame_desc[%d].length(%d)>%d",n , purb->iso_frame_desc[n].length, maxsze); + tdm[n] = 0; + continue; + } + ret = alloc_td (&td, UHCI_PTR_DEPTH); + if (ret) { + int i; // Cleanup allocated TDs + + for (i = 0; i < n; n++) + if (tdm[i]) + kfree (tdm[i]); + kfree (tdm); + ret = -ENOMEM; + goto err; + } + last=n; + tdm[n] = td; + } + + status = TD_CTRL_ACTIVE | TD_CTRL_IOS; //| (purb->transfer_flags&USB_DISABLE_SPD?0:TD_CTRL_SPD); + + destination = (purb->pipe & PIPE_DEVEP_MASK) | usb_packetid (purb->pipe); + + + // Queue all allocated TDs + for (n = 0; n < purb->number_of_packets; n++) { + td = tdm[n]; + if (!td) + continue; + + if (n == last) + status |= TD_CTRL_IOC; + + fill_td (td, status, destination | (((purb->iso_frame_desc[n].length - 1) & 0x7ff) << 21), + virt_to_bus (purb->transfer_buffer + purb->iso_frame_desc[n].offset)); + list_add_tail (&td->desc_list, &purb_priv->desc_list); + + if (n == last) { + purb->status = USB_ST_URB_PENDING; + queue_urb (s, &purb->urb_list,1); + } + insert_td_horizontal (s, s->iso_td[(purb->start_frame + n) & 1023], td, UHCI_PTR_DEPTH); // store in iso-tds + //uhci_show_td(td); + + } + + kfree (tdm); + dbg("ISO-INT# %i, start %i, now %i", purb->number_of_packets, purb->start_frame, UHCI_GET_CURRENT_FRAME (s) & 1023); + ret = 0; + + err: + spin_unlock_irqrestore (&lock, flags); + return ret; + +} +/*-------------------------------------------------------------------*/ +_static int search_dev_ep (puhci_t s, purb_t purb) +{ + unsigned long flags; + struct list_head *p = s->urb_list.next; + purb_t tmp; + unsigned int mask = usb_pipecontrol(purb->pipe) ? (~USB_DIR_IN) : (~0); + + dbg("search_dev_ep:"); + spin_lock_irqsave (&s->urb_list_lock, flags); + for (; p != &s->urb_list; p = p->next) { + tmp = list_entry (p, urb_t, urb_list); + dbg("urb: %p", tmp); + // we can accept this urb if it is not queued at this time + // or if non-iso transfer requests should be scheduled for the same device and pipe + if ((!usb_pipeisoc(purb->pipe) && tmp->dev == purb->dev && !((tmp->pipe ^ purb->pipe) & mask)) || + (purb == tmp)) { + spin_unlock_irqrestore (&s->urb_list_lock, flags); + return 1; // found another urb already queued for processing + } + } + spin_unlock_irqrestore (&s->urb_list_lock, flags); + return 0; +} +/*-------------------------------------------------------------------*/ +_static int uhci_submit_urb (purb_t purb) +{ + puhci_t s; + purb_priv_t purb_priv; + int ret = 0; + + if (!purb->dev || !purb->dev->bus) + return -ENODEV; + + s = (puhci_t) purb->dev->bus->hcpriv; + //dbg("submit_urb: %p type %d",purb,usb_pipetype(purb->pipe)); + + if (usb_pipedevice (purb->pipe) == s->rh.devnum) + return rh_submit_urb (purb); /* virtual root hub */ + + usb_inc_dev_use (purb->dev); + + if (search_dev_ep (s, purb)) { + usb_dec_dev_use (purb->dev); + return -ENXIO; // urb already queued + + } + +#ifdef DEBUG_SLAB + purb_priv = kmem_cache_alloc(urb_priv_kmem, in_interrupt ()? SLAB_ATOMIC : SLAB_KERNEL); +#else + purb_priv = kmalloc (sizeof (urb_priv_t), in_interrupt ()? GFP_ATOMIC : GFP_KERNEL); +#endif + if (!purb_priv) { + usb_dec_dev_use (purb->dev); + return -ENOMEM; + } + + purb->hcpriv = purb_priv; + INIT_LIST_HEAD (&purb_priv->desc_list); + purb_priv->short_control_packet=0; + dbg("submit_urb: scheduling %p", purb); + + switch (usb_pipetype (purb->pipe)) { + case PIPE_ISOCHRONOUS: + ret = uhci_submit_iso_urb (purb); + break; + case PIPE_INTERRUPT: + ret = uhci_submit_int_urb (purb); + break; + case PIPE_CONTROL: + //dump_urb (purb); + ret = uhci_submit_control_urb (purb); + break; + case PIPE_BULK: + ret = uhci_submit_bulk_urb (purb); + break; + default: + ret = -EINVAL; + } + + dbg("submit_urb: scheduled with ret: %d", ret); + + if (ret != USB_ST_NOERROR) { + usb_dec_dev_use (purb->dev); +#ifdef DEBUG_SLAB + kmem_cache_free(urb_priv_kmem, purb_priv); +#else + kfree (purb_priv); +#endif + return ret; + } +/* + purb->status = USB_ST_URB_PENDING; + queue_urb (s, &purb->urb_list,1); + dbg("submit_urb: exit"); +*/ + return 0; +} +/*------------------------------------------------------------------- + Virtual Root Hub + -------------------------------------------------------------------*/ + +_static __u8 root_hub_dev_des[] = +{ + 0x12, /* __u8 bLength; */ + 0x01, /* __u8 bDescriptorType; Device */ + 0x00, /* __u16 bcdUSB; v1.0 */ + 0x01, + 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ + 0x00, /* __u8 bDeviceSubClass; */ + 0x00, /* __u8 bDeviceProtocol; */ + 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ + 0x00, /* __u16 idVendor; */ + 0x00, + 0x00, /* __u16 idProduct; */ + 0x00, + 0x00, /* __u16 bcdDevice; */ + 0x00, + 0x00, /* __u8 iManufacturer; */ + 0x00, /* __u8 iProduct; */ + 0x00, /* __u8 iSerialNumber; */ + 0x01 /* __u8 bNumConfigurations; */ +}; + + +/* Configuration descriptor */ +_static __u8 root_hub_config_des[] = +{ + 0x09, /* __u8 bLength; */ + 0x02, /* __u8 bDescriptorType; Configuration */ + 0x19, /* __u16 wTotalLength; */ + 0x00, + 0x01, /* __u8 bNumInterfaces; */ + 0x01, /* __u8 bConfigurationValue; */ + 0x00, /* __u8 iConfiguration; */ + 0x40, /* __u8 bmAttributes; + Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */ + 0x00, /* __u8 MaxPower; */ + + /* interface */ + 0x09, /* __u8 if_bLength; */ + 0x04, /* __u8 if_bDescriptorType; Interface */ + 0x00, /* __u8 if_bInterfaceNumber; */ + 0x00, /* __u8 if_bAlternateSetting; */ + 0x01, /* __u8 if_bNumEndpoints; */ + 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */ + 0x00, /* __u8 if_bInterfaceSubClass; */ + 0x00, /* __u8 if_bInterfaceProtocol; */ + 0x00, /* __u8 if_iInterface; */ + + /* endpoint */ + 0x07, /* __u8 ep_bLength; */ + 0x05, /* __u8 ep_bDescriptorType; Endpoint */ + 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ + 0x03, /* __u8 ep_bmAttributes; Interrupt */ + 0x08, /* __u16 ep_wMaxPacketSize; 8 Bytes */ + 0x00, + 0xff /* __u8 ep_bInterval; 255 ms */ +}; + + +_static __u8 root_hub_hub_des[] = +{ + 0x09, /* __u8 bLength; */ + 0x29, /* __u8 bDescriptorType; Hub-descriptor */ + 0x02, /* __u8 bNbrPorts; */ + 0x00, /* __u16 wHubCharacteristics; */ + 0x00, + 0x01, /* __u8 bPwrOn2pwrGood; 2ms */ + 0x00, /* __u8 bHubContrCurrent; 0 mA */ + 0x00, /* __u8 DeviceRemovable; *** 7 Ports max *** */ + 0xff /* __u8 PortPwrCtrlMask; *** 7 ports max *** */ +}; + +/*-------------------------------------------------------------------------*/ +/* prepare Interrupt pipe transaction data; HUB INTERRUPT ENDPOINT */ +_static int rh_send_irq (purb_t purb) +{ + + int len = 1; + int i; + puhci_t uhci = purb->dev->bus->hcpriv; + unsigned int io_addr = uhci->io_addr; + __u16 data = 0; + + for (i = 0; i < uhci->rh.numports; i++) { + data |= ((inw (io_addr + USBPORTSC1 + i * 2) & 0xa) > 0 ? (1 << (i + 1)) : 0); + len = (i + 1) / 8 + 1; + } + + *(__u16 *) purb->transfer_buffer = cpu_to_le16 (data); + purb->actual_length = len; + purb->status = USB_ST_NOERROR; + + if ((data > 0) && (uhci->rh.send != 0)) { + dbg("Root-Hub INT complete: port1: %x port2: %x data: %x", + inw (io_addr + USBPORTSC1), inw (io_addr + USBPORTSC2), data); + purb->complete (purb); + + } + return USB_ST_NOERROR; +} + +/*-------------------------------------------------------------------------*/ +/* Virtual Root Hub INTs are polled by this timer every "intervall" ms */ +_static int rh_init_int_timer (purb_t purb); + +_static void rh_int_timer_do (unsigned long ptr) +{ + int len; + + purb_t purb = (purb_t) ptr; + puhci_t uhci = purb->dev->bus->hcpriv; + + if (uhci->rh.send) { + len = rh_send_irq (purb); + if (len > 0) { + purb->actual_length = len; + if (purb->complete) + purb->complete (purb); + } + } + rh_init_int_timer (purb); +} + +/*-------------------------------------------------------------------------*/ +/* Root Hub INTs are polled by this timer */ +_static int rh_init_int_timer (purb_t purb) +{ + puhci_t uhci = purb->dev->bus->hcpriv; + + uhci->rh.interval = purb->interval; + init_timer (&uhci->rh.rh_int_timer); + uhci->rh.rh_int_timer.function = rh_int_timer_do; + uhci->rh.rh_int_timer.data = (unsigned long) purb; + uhci->rh.rh_int_timer.expires = jiffies + (HZ * (purb->interval < 30 ? 30 : purb->interval)) / 1000; + add_timer (&uhci->rh.rh_int_timer); + + return 0; +} + +/*-------------------------------------------------------------------------*/ +#define OK(x) len = (x); break + +#define CLR_RH_PORTSTAT(x) \ + status = inw(io_addr+USBPORTSC1+2*(wIndex-1)); \ + status = (status & 0xfff5) & ~(x); \ + outw(status, io_addr+USBPORTSC1+2*(wIndex-1)) + +#define SET_RH_PORTSTAT(x) \ + status = inw(io_addr+USBPORTSC1+2*(wIndex-1)); \ + status = (status & 0xfff5) | (x); \ + outw(status, io_addr+USBPORTSC1+2*(wIndex-1)) + + +/*-------------------------------------------------------------------------*/ +/**** + ** Root Hub Control Pipe + *************************/ + + +_static int rh_submit_urb (purb_t purb) +{ + struct usb_device *usb_dev = purb->dev; + puhci_t uhci = usb_dev->bus->hcpriv; + unsigned int pipe = purb->pipe; + devrequest *cmd = (devrequest *) purb->setup_packet; + void *data = purb->transfer_buffer; + int leni = purb->transfer_buffer_length; + int len = 0; + int status = 0; + int stat = USB_ST_NOERROR; + int i; + unsigned int io_addr = uhci->io_addr; + __u16 cstatus; + + __u16 bmRType_bReq; + __u16 wValue; + __u16 wIndex; + __u16 wLength; + + if (usb_pipetype (pipe) == PIPE_INTERRUPT) { + dbg("Root-Hub submit IRQ: every %d ms", purb->interval); + uhci->rh.urb = purb; + uhci->rh.send = 1; + uhci->rh.interval = purb->interval; + rh_init_int_timer (purb); + + return USB_ST_NOERROR; + } + + + bmRType_bReq = cmd->requesttype | cmd->request << 8; + wValue = le16_to_cpu (cmd->value); + wIndex = le16_to_cpu (cmd->index); + wLength = le16_to_cpu (cmd->length); + + for (i = 0; i < 8; i++) + uhci->rh.c_p_r[i] = 0; + + dbg("Root-Hub: adr: %2x cmd(%1x): %04x %04x %04x %04x", + uhci->rh.devnum, 8, bmRType_bReq, wValue, wIndex, wLength); + + switch (bmRType_bReq) { + /* Request Destination: + without flags: Device, + RH_INTERFACE: interface, + RH_ENDPOINT: endpoint, + RH_CLASS means HUB here, + RH_OTHER | RH_CLASS almost ever means HUB_PORT here + */ + + case RH_GET_STATUS: + *(__u16 *) data = cpu_to_le16 (1); + OK (2); + case RH_GET_STATUS | RH_INTERFACE: + *(__u16 *) data = cpu_to_le16 (0); + OK (2); + case RH_GET_STATUS | RH_ENDPOINT: + *(__u16 *) data = cpu_to_le16 (0); + OK (2); + case RH_GET_STATUS | RH_CLASS: + *(__u32 *) data = cpu_to_le32 (0); + OK (4); /* hub power ** */ + case RH_GET_STATUS | RH_OTHER | RH_CLASS: + status = inw (io_addr + USBPORTSC1 + 2 * (wIndex - 1)); + cstatus = ((status & USBPORTSC_CSC) >> (1 - 0)) | + ((status & USBPORTSC_PEC) >> (3 - 1)) | + (uhci->rh.c_p_r[wIndex - 1] << (0 + 4)); + status = (status & USBPORTSC_CCS) | + ((status & USBPORTSC_PE) >> (2 - 1)) | + ((status & USBPORTSC_SUSP) >> (12 - 2)) | + ((status & USBPORTSC_PR) >> (9 - 4)) | + (1 << 8) | /* power on ** */ + ((status & USBPORTSC_LSDA) << (-8 + 9)); + + *(__u16 *) data = cpu_to_le16 (status); + *(__u16 *) (data + 2) = cpu_to_le16 (cstatus); + OK (4); + + case RH_CLEAR_FEATURE | RH_ENDPOINT: + switch (wValue) { + case (RH_ENDPOINT_STALL): + OK (0); + } + break; + + case RH_CLEAR_FEATURE | RH_CLASS: + switch (wValue) { + case (RH_C_HUB_OVER_CURRENT): + OK (0); /* hub power over current ** */ + } + break; + + case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: + switch (wValue) { + case (RH_PORT_ENABLE): + CLR_RH_PORTSTAT (USBPORTSC_PE); + OK (0); + case (RH_PORT_SUSPEND): + CLR_RH_PORTSTAT (USBPORTSC_SUSP); + OK (0); + case (RH_PORT_POWER): + OK (0); /* port power ** */ + case (RH_C_PORT_CONNECTION): + SET_RH_PORTSTAT (USBPORTSC_CSC); + OK (0); + case (RH_C_PORT_ENABLE): + SET_RH_PORTSTAT (USBPORTSC_PEC); + OK (0); + case (RH_C_PORT_SUSPEND): +/*** WR_RH_PORTSTAT(RH_PS_PSSC); */ + OK (0); + case (RH_C_PORT_OVER_CURRENT): + OK (0); /* port power over current ** */ + case (RH_C_PORT_RESET): + uhci->rh.c_p_r[wIndex - 1] = 0; + OK (0); + } + break; + + case RH_SET_FEATURE | RH_OTHER | RH_CLASS: + switch (wValue) { + case (RH_PORT_SUSPEND): + SET_RH_PORTSTAT (USBPORTSC_SUSP); + OK (0); + case (RH_PORT_RESET): + SET_RH_PORTSTAT (USBPORTSC_PR); + wait_ms (10); + uhci->rh.c_p_r[wIndex - 1] = 1; + CLR_RH_PORTSTAT (USBPORTSC_PR); + udelay (10); + SET_RH_PORTSTAT (USBPORTSC_PE); + wait_ms (10); + SET_RH_PORTSTAT (0xa); + OK (0); + case (RH_PORT_POWER): + OK (0); /* port power ** */ + case (RH_PORT_ENABLE): + SET_RH_PORTSTAT (USBPORTSC_PE); + OK (0); + } + break; + + case RH_SET_ADDRESS: + uhci->rh.devnum = wValue; + OK (0); + + case RH_GET_DESCRIPTOR: + switch ((wValue & 0xff00) >> 8) { + case (0x01): /* device descriptor */ + len = min (leni, min (sizeof (root_hub_dev_des), wLength)); + memcpy (data, root_hub_dev_des, len); + OK (len); + case (0x02): /* configuration descriptor */ + len = min (leni, min (sizeof (root_hub_config_des), wLength)); + memcpy (data, root_hub_config_des, len); + OK (len); + case (0x03): /*string descriptors */ + stat = -EPIPE; + } + break; + + case RH_GET_DESCRIPTOR | RH_CLASS: + root_hub_hub_des[2] = uhci->rh.numports; + len = min (leni, min (sizeof (root_hub_hub_des), wLength)); + memcpy (data, root_hub_hub_des, len); + OK (len); + + case RH_GET_CONFIGURATION: + *(__u8 *) data = 0x01; + OK (1); + + case RH_SET_CONFIGURATION: + OK (0); + default: + stat = -EPIPE; + } + + + dbg("Root-Hub stat port1: %x port2: %x", + inw (io_addr + USBPORTSC1), inw (io_addr + USBPORTSC2)); + + purb->actual_length = len; + purb->status = stat; + if (purb->complete) + purb->complete (purb); + return USB_ST_NOERROR; +} +/*-------------------------------------------------------------------------*/ + +_static int rh_unlink_urb (purb_t purb) +{ + puhci_t uhci = purb->dev->bus->hcpriv; + + dbg("Root-Hub unlink IRQ"); + uhci->rh.send = 0; + del_timer (&uhci->rh.rh_int_timer); + return 0; +} +/*-------------------------------------------------------------------*/ + +/* + * Map status to standard result codes + * + * is (td->status & 0xFE0000) [a.k.a. uhci_status_bits(td->status) + * is True for output TDs and False for input TDs. + */ +_static int uhci_map_status (int status, int dir_out) +{ + if (!status) + return USB_ST_NOERROR; + if (status & TD_CTRL_BITSTUFF) /* Bitstuff error */ + return -EPROTO; + if (status & TD_CTRL_CRCTIMEO) { /* CRC/Timeout */ + if (dir_out) + return -ETIMEDOUT; + else + return -EILSEQ; + } + if (status & TD_CTRL_NAK) /* NAK */ + return -ETIMEDOUT; + if (status & TD_CTRL_BABBLE) /* Babble */ + return -EPIPE; + if (status & TD_CTRL_DBUFERR) /* Buffer error */ + return -ENOSR; + if (status & TD_CTRL_STALLED) /* Stalled */ + return -EPIPE; + if (status & TD_CTRL_ACTIVE) /* Active */ + return USB_ST_NOERROR; + + return -EPROTO; +} + +/* + * Only the USB core should call uhci_alloc_dev and uhci_free_dev + */ +_static int uhci_alloc_dev (struct usb_device *usb_dev) +{ + return 0; +} + +_static int uhci_free_dev (struct usb_device *usb_dev) +{ + return 0; +} + +/* + * uhci_get_current_frame_number() + * + * returns the current frame number for a USB bus/controller. + */ +_static int uhci_get_current_frame_number (struct usb_device *usb_dev) +{ + return UHCI_GET_CURRENT_FRAME ((puhci_t) usb_dev->bus->hcpriv); +} + +struct usb_operations uhci_device_operations = +{ + uhci_alloc_dev, + uhci_free_dev, + uhci_get_current_frame_number, + uhci_submit_urb, + uhci_unlink_urb +}; + +/* + * For IN-control transfers, process_transfer gets a bit more complicated, + * since there are devices that return less data (eg. strings) than they + * have announced. This leads to a queue abort due to the short packet, + * the status stage is not executed. If this happens, the status stage + * is manually re-executed. + * FIXME: Stall-condition may override 'nearly' successful CTRL-IN-transfer + * when the transfered length fits exactly in maxsze-packets. A bit + * more intelligence is needed to detect this and finish without error. + */ +_static int process_transfer (puhci_t s, purb_t purb) +{ + int ret = USB_ST_NOERROR; + purb_priv_t purb_priv = purb->hcpriv; + struct list_head *qhl = purb_priv->desc_list.next; + puhci_desc_t qh = list_entry (qhl, uhci_desc_t, desc_list); + struct list_head *p = qh->vertical.next; + puhci_desc_t desc= list_entry (purb_priv->desc_list.prev, uhci_desc_t, desc_list); + puhci_desc_t last_desc = list_entry (desc->vertical.prev, uhci_desc_t, vertical); + int data_toggle = usb_gettoggle (purb->dev, usb_pipeendpoint (purb->pipe), usb_pipeout (purb->pipe)); // save initial data_toggle + + + // extracted and remapped info from TD + int maxlength; + int actual_length; + int status = USB_ST_NOERROR; + + dbg("process_transfer: urb contains bulk/control request"); + + + /* if the status phase has been retriggered and the + queue is empty or the last status-TD is inactive, the retriggered + status stage is completed + */ +#if 1 + if (purb_priv->short_control_packet && + ((qh->hw.qh.element == UHCI_PTR_TERM) ||(!(last_desc->hw.td.status & TD_CTRL_ACTIVE)))) + goto transfer_finished; +#endif + purb->actual_length=0; + + for (; p != &qh->vertical; p = p->next) { + desc = list_entry (p, uhci_desc_t, vertical); + + if (desc->hw.td.status & TD_CTRL_ACTIVE) // do not process active TDs + return ret; + + // extract transfer parameters from TD + actual_length = (desc->hw.td.status + 1) & 0x7ff; + maxlength = (((desc->hw.td.info >> 21) & 0x7ff) + 1) & 0x7ff; + status = uhci_map_status (uhci_status_bits (desc->hw.td.status), usb_pipeout (purb->pipe)); + + // see if EP is stalled + if (status == -EPIPE) { + // set up stalled condition + usb_endpoint_halt (purb->dev, usb_pipeendpoint (purb->pipe), usb_pipeout (purb->pipe)); + } + + // if any error occured stop processing of further TDs + if (status != USB_ST_NOERROR) { + // only set ret if status returned an error + uhci_show_td (desc); + ret = status; + purb->error_count++; + break; + } + else if ((desc->hw.td.info & 0xff) != USB_PID_SETUP) + purb->actual_length += actual_length; + +#if 0 + // if (i++==0) + uhci_show_td (desc); // show first TD of each transfer +#endif + + // got less data than requested + if ( (actual_length < maxlength)) { + if (purb->transfer_flags & USB_DISABLE_SPD) { + ret = USB_ST_SHORT_PACKET; // treat as real error + dbg("process_transfer: SPD!!"); + break; // exit after this TD because SP was detected + } + + // short read during control-IN: re-start status stage + if ((usb_pipetype (purb->pipe) == PIPE_CONTROL)) { + if (uhci_packetid(last_desc->hw.td.info) == USB_PID_OUT) { + + qh->hw.qh.element = virt_to_bus (last_desc); // re-trigger status stage + dbg("short packet during control transfer, retrigger status stage @ %p",last_desc); + uhci_show_td (desc); + uhci_show_td (last_desc); + purb_priv->short_control_packet=1; + return 0; + } + } + // all other cases: short read is OK + data_toggle = uhci_toggle (desc->hw.td.info); + break; + } + + data_toggle = uhci_toggle (desc->hw.td.info); + //dbg("process_transfer: len:%d status:%x mapped:%x toggle:%d", actual_length, desc->hw.td.status,status, data_toggle); + + } + usb_settoggle (purb->dev, usb_pipeendpoint (purb->pipe), usb_pipeout (purb->pipe), !data_toggle); + transfer_finished: + + /* APC BackUPS Pro kludge */ + /* It tries to send all of the descriptor instead of */ + /* the amount we requested */ + if (desc->hw.td.status & TD_CTRL_IOC && + status & TD_CTRL_ACTIVE && + status & TD_CTRL_NAK ) + { + dbg("APS WORKAROUND"); + ret=0; + status=0; + } + + unlink_qh (s, qh); + delete_qh (s, qh); + + purb->status = status; + + dbg("process_transfer: urb %p, wanted len %d, len %d status %x err %d", + purb,purb->transfer_buffer_length,purb->actual_length, purb->status, purb->error_count); + //dbg("process_transfer: exit"); +#if 0 + if (purb->actual_length){ + char *uu; + uu=purb->transfer_buffer; + dbg("%x %x %x %x %x %x %x %x", + *uu,*(uu+1),*(uu+2),*(uu+3),*(uu+4),*(uu+5),*(uu+6),*(uu+7)); + } +#endif + return ret; +} + +_static int process_interrupt (puhci_t s, purb_t purb) +{ + int i, ret = USB_ST_URB_PENDING; + purb_priv_t purb_priv = purb->hcpriv; + struct list_head *p = purb_priv->desc_list.next; + puhci_desc_t desc = list_entry (purb_priv->desc_list.prev, uhci_desc_t, desc_list); + + int actual_length; + int status = USB_ST_NOERROR; + + //dbg("urb contains interrupt request"); + + for (i = 0; p != &purb_priv->desc_list; p = p->next, i++) // Maybe we allow more than one TD later ;-) + { + desc = list_entry (p, uhci_desc_t, desc_list); + + if (desc->hw.td.status & TD_CTRL_ACTIVE) { + // do not process active TDs + //dbg("TD ACT Status @%p %08x",desc,desc->hw.td.status); + break; + } + + if (!desc->hw.td.status & TD_CTRL_IOC) { + // do not process one-shot TDs, no recycling + break; + } + // extract transfer parameters from TD + + actual_length = (desc->hw.td.status + 1) & 0x7ff; + status = uhci_map_status (uhci_status_bits (desc->hw.td.status), usb_pipeout (purb->pipe)); + + // see if EP is stalled + if (status == -EPIPE) { + // set up stalled condition + usb_endpoint_halt (purb->dev, usb_pipeendpoint (purb->pipe), usb_pipeout (purb->pipe)); + } + + // if any error occured: ignore this td, and continue + if (status != USB_ST_NOERROR) { + uhci_show_td (desc); + purb->error_count++; + goto recycle; + } + else + purb->actual_length = actual_length; + + // FIXME: SPD? + + recycle: + if (purb->complete) { + //dbg("process_interrupt: calling completion, status %i",status); + purb->status = status; + purb->complete ((struct urb *) purb); + purb->status = USB_ST_URB_PENDING; + } + + // Recycle INT-TD if interval!=0, else mark TD as one-shot + if (purb->interval) { + desc->hw.td.info &= ~(1 << TD_TOKEN_TOGGLE); + if (status==0) { + desc->hw.td.info |= (usb_gettoggle (purb->dev, usb_pipeendpoint (purb->pipe), + usb_pipeout (purb->pipe)) << TD_TOKEN_TOGGLE); + usb_dotoggle (purb->dev, usb_pipeendpoint (purb->pipe), usb_pipeout (purb->pipe)); + } else { + desc->hw.td.info |= (!usb_gettoggle (purb->dev, usb_pipeendpoint (purb->pipe), + usb_pipeout (purb->pipe)) << TD_TOKEN_TOGGLE); + } + desc->hw.td.status= (purb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC | + (purb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27); + wmb(); + } + else { + desc->hw.td.status &= ~TD_CTRL_IOC; // inactivate TD + } + } + + return ret; +} + + +_static int process_iso (puhci_t s, purb_t purb) +{ + int i; + int ret = USB_ST_NOERROR; + purb_priv_t purb_priv = purb->hcpriv; + struct list_head *p = purb_priv->desc_list.next; + puhci_desc_t desc = list_entry (purb_priv->desc_list.prev, uhci_desc_t, desc_list); + + dbg("urb contains iso request"); + if (desc->hw.td.status & TD_CTRL_ACTIVE) + return USB_ST_PARTIAL_ERROR; // last TD not finished + + purb->error_count = 0; + purb->actual_length = 0; + purb->status = USB_ST_NOERROR; + + for (i = 0; p != &purb_priv->desc_list; p = p->next, i++) { + desc = list_entry (p, uhci_desc_t, desc_list); + + //uhci_show_td(desc); + if (desc->hw.td.status & TD_CTRL_ACTIVE) { + // means we have completed the last TD, but not the TDs before + desc->hw.td.status &= ~TD_CTRL_ACTIVE; + dbg("TD still active (%x)- grrr. paranoia!", desc->hw.td.status); + ret = USB_ST_PARTIAL_ERROR; + purb->iso_frame_desc[i].status = ret; + unlink_td (s, desc); + // FIXME: immediate deletion may be dangerous + goto err; + } + + unlink_td (s, desc); + + if (purb->number_of_packets <= i) { + dbg("purb->number_of_packets (%d)<=(%d)", purb->number_of_packets, i); + ret = USB_ST_URB_INVALID_ERROR; + goto err; + } + + if (purb->iso_frame_desc[i].offset + purb->transfer_buffer != bus_to_virt (desc->hw.td.buffer)) { + // Hm, something really weird is going on + dbg("Pointer Paranoia: %p!=%p", purb->iso_frame_desc[i].offset + purb->transfer_buffer, bus_to_virt (desc->hw.td.buffer)); + ret = USB_ST_URB_INVALID_ERROR; + purb->iso_frame_desc[i].status = ret; + goto err; + } + purb->iso_frame_desc[i].actual_length = (desc->hw.td.status + 1) & 0x7ff; + purb->iso_frame_desc[i].status = uhci_map_status (uhci_status_bits (desc->hw.td.status), usb_pipeout (purb->pipe)); + purb->actual_length += purb->iso_frame_desc[i].actual_length; + + err: + + if (purb->iso_frame_desc[i].status != USB_ST_NOERROR) { + purb->error_count++; + purb->status = purb->iso_frame_desc[i].status; + } + dbg("process_iso: len:%d status:%x", + purb->iso_frame_desc[i].length, purb->iso_frame_desc[i].status); + + delete_desc (desc); + list_del (p); + } + dbg("process_iso: exit %i (%d)", i, ret); + return ret; +} + + +_static int process_urb (puhci_t s, struct list_head *p) +{ + int ret = USB_ST_NOERROR; + purb_t purb; + + spin_lock(&s->urb_list_lock); + purb=list_entry (p, urb_t, urb_list); + dbg("found queued urb: %p", purb); + + switch (usb_pipetype (purb->pipe)) { + case PIPE_CONTROL: + case PIPE_BULK: + ret = process_transfer (s, purb); + break; + case PIPE_ISOCHRONOUS: + ret = process_iso (s, purb); + break; + case PIPE_INTERRUPT: + ret = process_interrupt (s, purb); + break; + } + + spin_unlock(&s->urb_list_lock); + + if (purb->status != USB_ST_URB_PENDING) { + int proceed = 0; + dbg("dequeued urb: %p", purb); + dequeue_urb (s, p, 1); + +#ifdef DEBUG_SLAB + kmem_cache_free(urb_priv_kmem, purb->hcpriv); +#else + kfree (purb->hcpriv); +#endif + + if ((usb_pipetype (purb->pipe) != PIPE_INTERRUPT)) { + purb_t tmp = purb->next; // pointer to first urb + int is_ring = 0; + + if (purb->next) { + do { + if (tmp->status != USB_ST_URB_PENDING) { + proceed = 1; + break; + } + tmp = tmp->next; + } + while (tmp != NULL && tmp != purb->next); + if (tmp == purb->next) + is_ring = 1; + } + + // In case you need the current URB status for your completion handler + if (purb->complete && (!proceed || (purb->transfer_flags & USB_URB_EARLY_COMPLETE))) { + dbg("process_transfer: calling early completion"); + purb->complete ((struct urb *) purb); + if (!proceed && is_ring && (purb->status != USB_ST_URB_KILLED)) + uhci_submit_urb (purb); + } + + if (proceed && purb->next) { + // if there are linked urbs - handle submitting of them right now. + tmp = purb->next; // pointer to first urb + + do { + if ((tmp->status != USB_ST_URB_PENDING) && (tmp->status != USB_ST_URB_KILLED) && uhci_submit_urb (tmp) != USB_ST_NOERROR) + break; + tmp = tmp->next; + } + while (tmp != NULL && tmp != purb->next); // submit until we reach NULL or our own pointer or submit fails + + if (purb->complete && !(purb->transfer_flags & USB_URB_EARLY_COMPLETE)) { + dbg("process_transfer: calling completion"); + purb->complete ((struct urb *) purb); + } + } + usb_dec_dev_use (purb->dev); + } + } + + return ret; +} + +_static void uhci_interrupt (int irq, void *__uhci, struct pt_regs *regs) +{ + puhci_t s = __uhci; + unsigned int io_addr = s->io_addr; + unsigned short status; + struct list_head *p, *p2; + + /* + * Read the interrupt status, and write it back to clear the + * interrupt cause + */ + + status = inw (io_addr + USBSTS); + + if (!status) /* shared interrupt, not mine */ + return; + + dbg("interrupt"); + + if (status != 1) { + warn("interrupt, status %x", status); + + // remove host controller halted state + if ((status&0x20) && (s->running)) { + // more to be done - check TDs for invalid entries + // but TDs are only invalid if somewhere else is a (memory ?) problem + outw (USBCMD_RS | inw(io_addr + USBCMD), io_addr + USBCMD); + } + //uhci_show_status (s); + } + //beep(1000); + /* + * the following is very subtle and was blatantly wrong before + * traverse the list in *reverse* direction, because new entries + * may be added at the end. + * also, because process_urb may unlink the current urb, + * we need to advance the list before + * - Thomas Sailer + */ + + spin_lock(&s->unlink_urb_lock); + spin_lock (&s->urb_list_lock); + p = s->urb_list.prev; + spin_unlock (&s->urb_list_lock); + + while (p != &s->urb_list) { + p2 = p; + p = p->prev; + process_urb (s, p2); + } + + spin_unlock(&s->unlink_urb_lock); + + outw (status, io_addr + USBSTS); +#ifdef __alpha + mb (); // ? +#endif + dbg("done\n\n"); +} + +_static void reset_hc (puhci_t s) +{ + unsigned int io_addr = s->io_addr; + + s->apm_state = 0; + /* Global reset for 50ms */ + outw (USBCMD_GRESET, io_addr + USBCMD); + wait_ms (50); + outw (0, io_addr + USBCMD); + wait_ms (10); +} + +_static void start_hc (puhci_t s) +{ + unsigned int io_addr = s->io_addr; + int timeout = 1000; + + /* + * Reset the HC - this will force us to get a + * new notification of any already connected + * ports due to the virtual disconnect that it + * implies. + */ + outw (USBCMD_HCRESET, io_addr + USBCMD); + + while (inw (io_addr + USBCMD) & USBCMD_HCRESET) { + if (!--timeout) { + err("USBCMD_HCRESET timed out!"); + break; + } + } + + /* Turn on all interrupts */ + outw (USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP, io_addr + USBINTR); + + /* Start at frame 0 */ + outw (0, io_addr + USBFRNUM); + outl (virt_to_bus (s->framelist), io_addr + USBFLBASEADD); + + /* Run and mark it configured with a 64-byte max packet */ + outw (USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD); + s->apm_state = 1; + s->running = 1; +} + +_static void __exit uhci_cleanup_dev(puhci_t s) +{ + struct usb_device *root_hub = s->bus->root_hub; + if (root_hub) + usb_disconnect (&root_hub); + + usb_deregister_bus (s->bus); + s->running = 0; + reset_hc (s); + release_region (s->io_addr, s->io_size); + free_irq (s->irq, s); + usb_free_bus (s->bus); + cleanup_skel (s); + kfree (s); + +} + +_static int __init uhci_start_usb (puhci_t s) +{ /* start it up */ + /* connect the virtual root hub */ + struct usb_device *usb_dev; + + usb_dev = usb_alloc_dev (NULL, s->bus); + if (!usb_dev) + return -1; + + s->bus->root_hub = usb_dev; + usb_connect (usb_dev); + + if (usb_new_device (usb_dev) != 0) { + usb_free_dev (usb_dev); + return -1; + } + + return 0; +} + +_static int __init alloc_uhci (int irq, unsigned int io_addr, unsigned int io_size) +{ + puhci_t s; + struct usb_bus *bus; + + s = kmalloc (sizeof (uhci_t), GFP_KERNEL); + if (!s) + return -1; + + memset (s, 0, sizeof (uhci_t)); + INIT_LIST_HEAD (&s->urb_list); + spin_lock_init (&s->urb_list_lock); + spin_lock_init (&s->qh_lock); + spin_lock_init (&s->td_lock); + spin_lock_init (&s->unlink_urb_lock); + s->irq = -1; + s->io_addr = io_addr; + s->io_size = io_size; + s->next = devs; //chain new uhci device into global list + + bus = usb_alloc_bus (&uhci_device_operations); + if (!bus) { + kfree (s); + return -1; + } + + s->bus = bus; + bus->hcpriv = s; + + /* UHCI specs says devices must have 2 ports, but goes on to say */ + /* they may have more but give no way to determine how many they */ + /* have, so default to 2 */ + /* According to the UHCI spec, Bit 7 is always set to 1. So we try */ + /* to use this to our advantage */ + + for (s->maxports = 0; s->maxports < (io_size - 0x10) / 2; s->maxports++) { + unsigned int portstatus; + + portstatus = inw (io_addr + 0x10 + (s->maxports * 2)); + dbg("port %i, adr %x status %x", s->maxports, + io_addr + 0x10 + (s->maxports * 2), portstatus); + if (!(portstatus & 0x0080)) + break; + } + dbg("Detected %d ports", s->maxports); + + /* This is experimental so anything less than 2 or greater than 8 is */ + /* something weird and we'll ignore it */ + if (s->maxports < 2 || s->maxports > 8) { + dbg("Port count misdetected, forcing to 2 ports"); + s->maxports = 2; + } + + s->rh.numports = s->maxports; + + if (init_skel (s)) { + usb_free_bus (bus); + kfree(s); + return -1; + } + + request_region (s->io_addr, io_size, MODNAME); + reset_hc (s); + usb_register_bus (s->bus); + + start_hc (s); + + if (request_irq (irq, uhci_interrupt, SA_SHIRQ, MODNAME, s)) { + err("request_irq %d failed!",irq); + usb_free_bus (bus); + reset_hc (s); + release_region (s->io_addr, s->io_size); + cleanup_skel(s); + kfree(s); + return -1; + } + + s->irq = irq; + + if(uhci_start_usb (s) < 0) { + uhci_cleanup_dev(s); + return -1; + } + + //chain new uhci device into global list + devs = s; + + return 0; +} + +_static int __init start_uhci (struct pci_dev *dev) +{ + int i; + + /* Search for the IO base address.. */ + for (i = 0; i < 6; i++) { +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,8) + unsigned int io_addr = dev->resource[i].start; + unsigned int io_size = + dev->resource[i].end - dev->resource[i].start + 1; + if (!(dev->resource[i].flags & 1)) + continue; +#else + unsigned int io_addr = dev->base_address[i]; + unsigned int io_size = 0x14; + if (!(io_addr & 1)) + continue; + io_addr &= ~1; +#endif + + /* Is it already in use? */ + if (check_region (io_addr, io_size)) + break; + /* disable legacy emulation */ + pci_write_config_word (dev, USBLEGSUP, USBLEGSUP_DEFAULT); + + return alloc_uhci(dev->irq, io_addr, io_size); + } + return -1; +} + +#ifdef CONFIG_APM +_static int handle_apm_event (apm_event_t event) +{ + static int down = 0; + puhci_t s = devs; + dbg("handle_apm_event(%d)", event); + switch (event) { + case APM_SYS_SUSPEND: + case APM_USER_SUSPEND: + if (down) { + dbg("received extra suspend event"); + break; + } + while (s) { + reset_hc (s); + s = s->next; + } + down = 1; + break; + case APM_NORMAL_RESUME: + case APM_CRITICAL_RESUME: + if (!down) { + dbg("received bogus resume event"); + break; + } + down = 0; + while (s) { + start_hc (s); + s = s->next; + } + break; + } + return 0; +} +#endif + +int __init uhci_init (void) +{ + int retval = -ENODEV; + struct pci_dev *dev = NULL; + u8 type; + int i=0; + +#ifdef DEBUG_SLAB + char *slabname=kmalloc(16, GFP_KERNEL); + + if(!slabname) + return -ENOMEM; + + strcpy(slabname, "uhci_desc"); + uhci_desc_kmem = kmem_cache_create(slabname, sizeof(uhci_desc_t), 0, SLAB_HWCACHE_ALIGN, NULL, NULL); + + if(!uhci_desc_kmem) { + err("kmem_cache_create for uhci_desc failed (out of memory)"); + return -ENOMEM; + } + + slabname=kmalloc(16, GFP_KERNEL); + + if(!slabname) + return -ENOMEM; + + strcpy(slabname, "urb_priv"); + urb_priv_kmem = kmem_cache_create(slabname, sizeof(urb_priv_t), 0, SLAB_HWCACHE_ALIGN, NULL, NULL); + + if(!urb_priv_kmem) { + err("kmem_cache_create for urb_priv_t failed (out of memory)"); + return -ENOMEM; + } +#endif + info(VERSTR); + + for (;;) { + dev = pci_find_class (PCI_CLASS_SERIAL_USB << 8, dev); + if (!dev) + break; + + /* Is it UHCI */ + pci_read_config_byte (dev, PCI_CLASS_PROG, &type); + if (type != 0) + continue; + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,8) + pci_enable_device (dev); +#endif + if(!dev->irq) + { + err("Found UHCI device with no IRQ assigned. Check BIOS settings!"); + continue; + } + + /* Ok set it up */ + retval = start_uhci (dev); + + if (!retval) + i++; + + } + +#ifdef CONFIG_APM + if(i) + apm_register_callback (&handle_apm_event); +#endif + return retval; +} + +void __exit uhci_cleanup (void) +{ + puhci_t s; + while ((s = devs)) { + devs = devs->next; + uhci_cleanup_dev(s); + } +#ifdef DEBUG_SLAB + kmem_cache_shrink(uhci_desc_kmem); + kmem_cache_shrink(urb_priv_kmem); +#endif +} + +#ifdef MODULE +int init_module (void) +{ + return uhci_init (); +} + +void cleanup_module (void) +{ +#ifdef CONFIG_APM + apm_unregister_callback (&handle_apm_event); +#endif + uhci_cleanup (); +} + +#endif //MODULE diff --git a/drivers/usb/usb-uhci.h b/drivers/usb/usb-uhci.h new file mode 100644 index 000000000..2afef1cf1 --- /dev/null +++ b/drivers/usb/usb-uhci.h @@ -0,0 +1,252 @@ +#ifndef __LINUX_UHCI_H +#define __LINUX_UHCI_H + +/* + $Id: usb-uhci.h,v 1.31 2000/01/15 22:02:30 acher Exp $ + */ +#define MODNAME "usb-uhci" +#define VERSTR "version v1.169 time " __TIME__ " " __DATE__ + +/* Command register */ +#define USBCMD 0 +#define USBCMD_RS 0x0001 /* Run/Stop */ +#define USBCMD_HCRESET 0x0002 /* Host reset */ +#define USBCMD_GRESET 0x0004 /* Global reset */ +#define USBCMD_EGSM 0x0008 /* Global Suspend Mode */ +#define USBCMD_FGR 0x0010 /* Force Global Resume */ +#define USBCMD_SWDBG 0x0020 /* SW Debug mode */ +#define USBCMD_CF 0x0040 /* Config Flag (sw only) */ +#define USBCMD_MAXP 0x0080 /* Max Packet (0 = 32, 1 = 64) */ + +/* Status register */ +#define USBSTS 2 +#define USBSTS_USBINT 0x0001 /* Interrupt due to IOC */ +#define USBSTS_ERROR 0x0002 /* Interrupt due to error */ +#define USBSTS_RD 0x0004 /* Resume Detect */ +#define USBSTS_HSE 0x0008 /* Host System Error - basically PCI problems */ +#define USBSTS_HCPE 0x0010 /* Host Controller Process Error - the scripts were buggy */ +#define USBSTS_HCH 0x0020 /* HC Halted */ + +/* Interrupt enable register */ +#define USBINTR 4 +#define USBINTR_TIMEOUT 0x0001 /* Timeout/CRC error enable */ +#define USBINTR_RESUME 0x0002 /* Resume interrupt enable */ +#define USBINTR_IOC 0x0004 /* Interrupt On Complete enable */ +#define USBINTR_SP 0x0008 /* Short packet interrupt enable */ + +#define USBFRNUM 6 +#define USBFLBASEADD 8 +#define USBSOF 12 + +/* USB port status and control registers */ +#define USBPORTSC1 16 +#define USBPORTSC2 18 +#define USBPORTSC_CCS 0x0001 /* Current Connect Status ("device present") */ +#define USBPORTSC_CSC 0x0002 /* Connect Status Change */ +#define USBPORTSC_PE 0x0004 /* Port Enable */ +#define USBPORTSC_PEC 0x0008 /* Port Enable Change */ +#define USBPORTSC_LS 0x0030 /* Line Status */ +#define USBPORTSC_RD 0x0040 /* Resume Detect */ +#define USBPORTSC_LSDA 0x0100 /* Low Speed Device Attached */ +#define USBPORTSC_PR 0x0200 /* Port Reset */ +#define USBPORTSC_SUSP 0x1000 /* Suspend */ + +/* Legacy support register */ +#define USBLEGSUP 0xc0 +#define USBLEGSUP_DEFAULT 0x2000 /* only PIRQ enable set */ + +#define UHCI_NULL_DATA_SIZE 0x7ff /* for UHCI controller TD */ + +#define UHCI_PTR_BITS 0x000F +#define UHCI_PTR_TERM 0x0001 +#define UHCI_PTR_QH 0x0002 +#define UHCI_PTR_DEPTH 0x0004 + +#define UHCI_NUMFRAMES 1024 /* in the frame list [array] */ +#define UHCI_MAX_SOF_NUMBER 2047 /* in an SOF packet */ +#define CAN_SCHEDULE_FRAMES 1000 /* how far future frames can be scheduled */ + +/* + * for TD : + */ +#define TD_CTRL_SPD (1 << 29) /* Short Packet Detect */ +#define TD_CTRL_C_ERR_MASK (3 << 27) /* Error Counter bits */ +#define TD_CTRL_LS (1 << 26) /* Low Speed Device */ +#define TD_CTRL_IOS (1 << 25) /* Isochronous Select */ +#define TD_CTRL_IOC (1 << 24) /* Interrupt on Complete */ +#define TD_CTRL_ACTIVE (1 << 23) /* TD Active */ +#define TD_CTRL_STALLED (1 << 22) /* TD Stalled */ +#define TD_CTRL_DBUFERR (1 << 21) /* Data Buffer Error */ +#define TD_CTRL_BABBLE (1 << 20) /* Babble Detected */ +#define TD_CTRL_NAK (1 << 19) /* NAK Received */ +#define TD_CTRL_CRCTIMEO (1 << 18) /* CRC/Time Out Error */ +#define TD_CTRL_BITSTUFF (1 << 17) /* Bit Stuff Error */ +#define TD_CTRL_ACTLEN_MASK 0x7ff /* actual length, encoded as n - 1 */ + +#define TD_CTRL_ANY_ERROR (TD_CTRL_STALLED | TD_CTRL_DBUFERR | \ + TD_CTRL_BABBLE | TD_CTRL_CRCTIME | TD_CTRL_BITSTUFF) + +#define uhci_status_bits(ctrl_sts) (ctrl_sts & 0xFE0000) +#define uhci_actual_length(ctrl_sts) ((ctrl_sts + 1) & TD_CTRL_ACTLEN_MASK) /* 1-based */ +#define uhci_ptr_to_virt(x) bus_to_virt(x & ~UHCI_PTR_BITS) + +/* + * for TD : + */ +#define UHCI_TD_REMOVE 0x0001 /* Remove when done */ + +/* + * for TD : (a.k.a. Token) + */ +#define TD_TOKEN_TOGGLE 19 + +#define uhci_maxlen(token) ((token) >> 21) +#define uhci_toggle(token) (((token) >> TD_TOKEN_TOGGLE) & 1) +#define uhci_endpoint(token) (((token) >> 15) & 0xf) +#define uhci_devaddr(token) (((token) >> 8) & 0x7f) +#define uhci_devep(token) (((token) >> 8) & 0x7ff) +#define uhci_packetid(token) ((token) & 0xff) +#define uhci_packetout(token) (uhci_packetid(token) != USB_PID_IN) +#define uhci_packetin(token) (uhci_packetid(token) == USB_PID_IN) + +/* ------------------------------------------------------------------------------------ + New TD/QH-structures + ------------------------------------------------------------------------------------ */ +typedef enum { + TD_TYPE, QH_TYPE +} uhci_desc_type_t; + +typedef struct { + __u32 link; + __u32 status; + __u32 info; + __u32 buffer; +} uhci_td_t, *puhci_td_t; + +typedef struct { + __u32 head; + __u32 element; /* Queue element pointer */ +} uhci_qh_t, *puhci_qh_t; + +typedef struct { + union { + uhci_td_t td; + uhci_qh_t qh; + } hw; + uhci_desc_type_t type; + struct list_head horizontal; + struct list_head vertical; + struct list_head desc_list; +} uhci_desc_t, *puhci_desc_t; + +typedef struct { + struct list_head desc_list; // list pointer to all corresponding TDs/QHs associated with this request + int short_control_packet; +} urb_priv_t, *purb_priv_t; + +struct virt_root_hub { + int devnum; /* Address of Root Hub endpoint */ + void *urb; + void *int_addr; + int send; + int interval; + int numports; + int c_p_r[8]; + struct timer_list rh_int_timer; +}; + +typedef struct uhci { + int irq; + unsigned int io_addr; + unsigned int io_size; + unsigned int maxports; + int running; + + int apm_state; + + struct uhci *next; // chain of uhci device contexts + + struct list_head urb_list; // list of all pending urbs + + spinlock_t urb_list_lock; // lock to keep consistency + + struct usb_bus *bus; // our bus + + spinlock_t unlink_urb_lock; // lock for unlink_urb + + __u32 *framelist; + uhci_desc_t **iso_td; + uhci_desc_t *int_chain[8]; + uhci_desc_t *control_chain; + uhci_desc_t *bulk_chain; + uhci_desc_t *chain_end; + spinlock_t qh_lock; + spinlock_t td_lock; + struct virt_root_hub rh; //private data of the virtual root hub +} uhci_t, *puhci_t; + + +#define MAKE_TD_ADDR(a) (virt_to_bus(a)&~UHCI_PTR_QH) +#define MAKE_QH_ADDR(a) (virt_to_bus(a)|UHCI_PTR_QH) +#define UHCI_GET_CURRENT_FRAME(uhci) (inw ((uhci)->io_addr + USBFRNUM)) + +/* ------------------------------------------------------------------------------------ + Virtual Root HUB + ------------------------------------------------------------------------------------ */ +/* destination of request */ +#define RH_INTERFACE 0x01 +#define RH_ENDPOINT 0x02 +#define RH_OTHER 0x03 + +#define RH_CLASS 0x20 +#define RH_VENDOR 0x40 + +/* Requests: bRequest << 8 | bmRequestType */ +#define RH_GET_STATUS 0x0080 +#define RH_CLEAR_FEATURE 0x0100 +#define RH_SET_FEATURE 0x0300 +#define RH_SET_ADDRESS 0x0500 +#define RH_GET_DESCRIPTOR 0x0680 +#define RH_SET_DESCRIPTOR 0x0700 +#define RH_GET_CONFIGURATION 0x0880 +#define RH_SET_CONFIGURATION 0x0900 +#define RH_GET_STATE 0x0280 +#define RH_GET_INTERFACE 0x0A80 +#define RH_SET_INTERFACE 0x0B00 +#define RH_SYNC_FRAME 0x0C80 +/* Our Vendor Specific Request */ +#define RH_SET_EP 0x2000 + + +/* Hub port features */ +#define RH_PORT_CONNECTION 0x00 +#define RH_PORT_ENABLE 0x01 +#define RH_PORT_SUSPEND 0x02 +#define RH_PORT_OVER_CURRENT 0x03 +#define RH_PORT_RESET 0x04 +#define RH_PORT_POWER 0x08 +#define RH_PORT_LOW_SPEED 0x09 +#define RH_C_PORT_CONNECTION 0x10 +#define RH_C_PORT_ENABLE 0x11 +#define RH_C_PORT_SUSPEND 0x12 +#define RH_C_PORT_OVER_CURRENT 0x13 +#define RH_C_PORT_RESET 0x14 + +/* Hub features */ +#define RH_C_HUB_LOCAL_POWER 0x00 +#define RH_C_HUB_OVER_CURRENT 0x01 + +#define RH_DEVICE_REMOTE_WAKEUP 0x00 +#define RH_ENDPOINT_STALL 0x01 + +/* Our Vendor Specific feature */ +#define RH_REMOVE_EP 0x00 + + +#define RH_ACK 0x01 +#define RH_REQ_ERR -1 +#define RH_NACK 0x00 + +#define min(a,b) (((a)<(b))?(a):(b)) + +#endif diff --git a/drivers/usb/usb.c b/drivers/usb/usb.c index 6b02641a9..213f69036 100644 --- a/drivers/usb/usb.c +++ b/drivers/usb/usb.c @@ -15,7 +15,7 @@ * It should be considered a slave, with no callbacks. Callbacks * are evil. * - * $Id: usb.c,v 1.39 1999/12/27 15:17:47 acher Exp $ + * $Id: usb.c,v 1.53 2000/01/14 16:19:09 acher Exp $ */ #include @@ -486,7 +486,8 @@ urb_t* usb_alloc_urb(int iso_packets) /*-------------------------------------------------------------------*/ void usb_free_urb(urb_t* urb) { - kfree(urb); + if(urb) + kfree(urb); } /*-------------------------------------------------------------------*/ int usb_submit_urb(urb_t *urb) @@ -515,7 +516,7 @@ int usb_unlink_urb(urb_t *urb) static void usb_api_blocking_completion(urb_t *urb) { api_wrapper_data *awd = (api_wrapper_data *)urb->context; - + if (waitqueue_active(awd->wakeup)) wake_up(awd->wakeup); #if 0 @@ -541,7 +542,7 @@ static void usb_api_async_completion(urb_t *urb) *-------------------------------------------------------------------*/ // Starts urb and waits for completion or timeout -static int usb_start_wait_urb(urb_t *urb, int timeout, unsigned long* rval) +static int usb_start_wait_urb(urb_t *urb, int timeout, int* actual_length) { DECLARE_WAITQUEUE(wait, current); DECLARE_WAIT_QUEUE_HEAD(wqh); @@ -551,7 +552,7 @@ static int usb_start_wait_urb(urb_t *urb, int timeout, unsigned long* rval) awd.wakeup=&wqh; awd.handler=0; init_waitqueue_head(&wqh); - current->state = TASK_UNINTERRUPTIBLE; + current->state = TASK_INTERRUPTIBLE; add_wait_queue(&wqh, &wait); urb->context=&awd; status=usb_submit_urb(urb); @@ -572,15 +573,15 @@ static int usb_start_wait_urb(urb_t *urb, int timeout, unsigned long* rval) if (!status) { // timeout - dbg("usb_control/bulk_msg: timeout"); + printk("usb_control/bulk_msg: timeout\n"); usb_unlink_urb(urb); // remove urb safely status=-ETIMEDOUT; } else status=urb->status; - if (rval) - *rval=urb->actual_length; + if (actual_length) + *actual_length=urb->actual_length; usb_free_urb(urb); return status; @@ -593,7 +594,7 @@ int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe, { urb_t *urb; int retv; - unsigned long length; + int length; urb=usb_alloc_urb(0); if (!urb) @@ -601,7 +602,7 @@ int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe, FILL_CONTROL_URB(urb, usb_dev, pipe, (unsigned char*)cmd, data, len, /* build urb */ (usb_complete_t)usb_api_blocking_completion,0); - + retv=usb_start_wait_urb(urb,timeout, &length); if (retv < 0) return retv; @@ -613,15 +614,25 @@ int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe, int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size, int timeout) { - devrequest dr; - - dr.requesttype = requesttype; - dr.request = request; - dr.value = cpu_to_le16p(&value); - dr.index = cpu_to_le16p(&index); - dr.length = cpu_to_le16p(&size); + devrequest *dr = kmalloc(sizeof(devrequest), GFP_KERNEL); + int ret; + + if(!dr) + return -ENOMEM; + + dr->requesttype = requesttype; + dr->request = request; + dr->value = cpu_to_le16p(&value); + dr->index = cpu_to_le16p(&index); + dr->length = cpu_to_le16p(&size); + //dbg("usb_control_msg"); - return usb_internal_control_msg(dev, pipe, &dr, data, size, timeout); + + ret=usb_internal_control_msg(dev, pipe, dr, data, size, timeout); + + kfree(dr); + + return ret; } /*-------------------------------------------------------------------*/ @@ -629,7 +640,7 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u /* synchronous behavior */ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, - void *data, int len, unsigned long *rval, int timeout) + void *data, int len, int *actual_length, int timeout) { urb_t *urb; @@ -643,7 +654,7 @@ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, FILL_BULK_URB(urb,usb_dev,pipe,(unsigned char*)data,len, /* build urb */ (usb_complete_t)usb_api_blocking_completion,0); - return usb_start_wait_urb(urb,timeout,rval); + return usb_start_wait_urb(urb,timeout,actual_length); } /*-------------------------------------------------------------------*/ @@ -1087,7 +1098,7 @@ int usb_parse_configuration(struct usb_device *dev, struct usb_config_descriptor for (i = 0; i < config->bNumInterfaces; i++) { header = (struct usb_descriptor_header *)buffer; - if (header->bLength > size) { + if ((header->bLength > size) || (header->bLength <= 2)) { err("ran out of descriptors parsing"); return -1; } @@ -1222,7 +1233,8 @@ void usb_disconnect(struct usb_device **pdev) /* Free up all the children.. */ for (i = 0; i < USB_MAXCHILDREN; i++) { struct usb_device **child = dev->children + i; - usb_disconnect(child); + if (*child) + usb_disconnect(child); } /* remove /proc/bus/usb entry */ @@ -1246,6 +1258,9 @@ void usb_connect(struct usb_device *dev) { int devnum; // FIXME needs locking for SMP!! + /* why? this is called only from the hub thread, + * which hopefully doesn't run on multiple CPU's simulatenously 8-) + */ dev->descriptor.bMaxPacketSize0 = 8; /* Start off at 8 bytes */ devnum = find_next_zero_bit(dev->bus->devmap.devicemap, 128, 1); if (devnum < 128) { @@ -1272,6 +1287,8 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char { int i = 5; int result; + + memset(buf,0,size); // Make sure we parse really received data while (i--) { if ((result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), @@ -1283,12 +1300,12 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char return result; } -int usb_get_class_descriptor(struct usb_device *dev, unsigned char type, - unsigned char id, unsigned char index, void *buf, int size) +int usb_get_class_descriptor(struct usb_device *dev, int ifnum, + unsigned char type, unsigned char id, void *buf, int size) { return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN, - (type << 8) + id, index, buf, size, HZ * GET_TIMEOUT); + (type << 8) + id, ifnum, buf, size, HZ * GET_TIMEOUT); } int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char index, void *buf, int size) @@ -1317,31 +1334,31 @@ int usb_get_status(struct usb_device *dev, int type, int target, void *data) USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, data, 2, HZ * GET_TIMEOUT); } -int usb_get_protocol(struct usb_device *dev) +int usb_get_protocol(struct usb_device *dev, int ifnum) { unsigned char type; int ret; if ((ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), USB_REQ_GET_PROTOCOL, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - 0, 1, &type, 1, HZ * GET_TIMEOUT)) < 0) + 0, ifnum, &type, 1, HZ * GET_TIMEOUT)) < 0) return ret; return type; } -int usb_set_protocol(struct usb_device *dev, int protocol) +int usb_set_protocol(struct usb_device *dev, int ifnum, int protocol) { return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_PROTOCOL, USB_TYPE_CLASS | USB_RECIP_INTERFACE, - protocol, 1, NULL, 0, HZ * SET_TIMEOUT); + protocol, ifnum, NULL, 0, HZ * SET_TIMEOUT); } -int usb_set_idle(struct usb_device *dev, int duration, int report_id) +int usb_set_idle(struct usb_device *dev, int ifnum, int duration, int report_id) { 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); + (duration << 8) | report_id, ifnum, NULL, 0, HZ * SET_TIMEOUT); } static void usb_set_maxpacket(struct usb_device *dev) @@ -1373,10 +1390,11 @@ static void usb_set_maxpacket(struct usb_device *dev) * endp: endpoint number in bits 0-3; * direction flag in bit 7 (1 = IN, 0 = OUT) */ -int usb_clear_halt(struct usb_device *dev, int endp) +int usb_clear_halt(struct usb_device *dev, int pipe) { int result; __u16 status; + int endp=usb_pipeendpoint(pipe)|(usb_pipein(pipe)<<7); /* if (!usb_endpoint_halted(dev, endp & 0x0f, usb_endpoint_out(endp))) @@ -1399,11 +1417,11 @@ int usb_clear_halt(struct usb_device *dev, int endp) if (status & 1) return -EPIPE; /* still halted */ - usb_endpoint_running(dev, endp & 0x0f, usb_endpoint_out(endp)); + usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); /* toggle is reset on clear */ - usb_settoggle(dev, endp & 0x0f, usb_endpoint_out(endp), 0); + usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0); return 0; } @@ -1462,18 +1480,18 @@ int usb_set_configuration(struct usb_device *dev, int configuration) return 0; } -int usb_get_report(struct usb_device *dev, unsigned char type, unsigned char id, unsigned char index, void *buf, int size) +int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type, unsigned char id, void *buf, int size) { return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), USB_REQ_GET_REPORT, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - (type << 8) + id, index, buf, size, HZ * GET_TIMEOUT); + (type << 8) + id, ifnum, 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) +int usb_set_report(struct usb_device *dev, int ifnum, unsigned char type, unsigned char id, void *buf, int size) { return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE, - (type << 8) + id, index, buf, size, HZ); + (type << 8) + id, ifnum, buf, size, HZ); } int usb_get_configuration(struct usb_device *dev) @@ -1482,6 +1500,7 @@ int usb_get_configuration(struct usb_device *dev) unsigned int cfgno; unsigned char buffer[8]; unsigned char *bigbuffer; + unsigned int tmp; struct usb_config_descriptor *desc = (struct usb_config_descriptor *)buffer; @@ -1511,8 +1530,11 @@ int usb_get_configuration(struct usb_device *dev) /* We grab the first 8 bytes so we know how long the whole */ /* configuration is */ result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 8); - if (result < 0) { - err("unable to get descriptor"); + if (result < 8) { + if (result < 0) + err("unable to get descriptor"); + else + err("config descriptor too short (expected %i, got %i)",8,result); goto err; } @@ -1525,13 +1547,19 @@ int usb_get_configuration(struct usb_device *dev) result=-ENOMEM; goto err; } - + tmp=desc->wTotalLength; /* Now that we know the length, get the whole thing */ result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bigbuffer, desc->wTotalLength); if (result < 0) { err("couldn't get all of config descriptors"); kfree(bigbuffer); goto err; + } + + if (result < tmp) { + err("config descriptor too short (expected %i, got %i)",tmp,result); + kfree(bigbuffer); + goto err; } result = usb_parse_configuration(dev, &dev->config[cfgno], bigbuffer); kfree(bigbuffer); @@ -1551,13 +1579,17 @@ int usb_get_configuration(struct usb_device *dev) return result; } +/* + * usb_string: + * returns string length (> 0) or error (< 0) + */ int usb_string(struct usb_device *dev, int index, char *buf, size_t size) { unsigned char *tbuf; int err; unsigned int u, idx; - if (size <= 0 || !buf) + if (size <= 0 || !buf || !index) return -EINVAL; buf[0] = 0; tbuf = kmalloc(256, GFP_KERNEL); @@ -1574,15 +1606,15 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size) 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) { + + size--; /* leave room for trailing NULL char in output buffer */ + for (idx = 0, u = 2; u < err; u += 2) { if (idx >= size) break; - if (tbuf[u+1]) { - buf[idx++] = '?'; /* non ASCII character */ - continue; - } - buf[idx++] = tbuf[u]; + if (tbuf[u+1]) /* high byte */ + buf[idx++] = '?'; /* non-ASCII character */ + else + buf[idx++] = tbuf[u]; } buf[idx] = 0; err = idx; @@ -1603,6 +1635,7 @@ int usb_new_device(struct usb_device *dev) { unsigned char *buf; int addr, err; + int tmp; info("USB new device connect, assigned device number %d", dev->devnum); @@ -1615,13 +1648,15 @@ int usb_new_device(struct usb_device *dev) dev->devnum = 0; err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8); - if (err < 0) { - err("USB device not responding, giving up (error=%d)", err); + if (err < 8) { + if (err < 0) + err("USB device not responding, giving up (error=%d)", err); + else + err("USB device descriptor short read (expected %i, got %i)",8,err); clear_bit(addr, &dev->bus->devmap.devicemap); dev->devnum = -1; return 1; } - dev->epmaxpacketin [0] = dev->descriptor.bMaxPacketSize0; dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0; switch (dev->descriptor.bMaxPacketSize0) { @@ -1644,9 +1679,15 @@ int usb_new_device(struct usb_device *dev) wait_ms(10); /* Let the SET_ADDRESS settle */ + tmp = sizeof(dev->descriptor); + err = usb_get_device_descriptor(dev); - if (err < 0) { - err("unable to get device descriptor (error=%d)",err); + if (err < tmp) { + if (err < 0) + err("unable to get device descriptor (error=%d)",err); + else + err("USB device descriptor short read (expected %i, got %i)",tmp,err); + clear_bit(dev->devnum, &dev->bus->devmap.devicemap); dev->devnum = -1; return 1; @@ -1684,9 +1725,12 @@ int usb_new_device(struct usb_device *dev) 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); + if (dev->descriptor.iManufacturer) + usb_show_string(dev, "Manufacturer", dev->descriptor.iManufacturer); + if (dev->descriptor.iProduct) + usb_show_string(dev, "Product", dev->descriptor.iProduct); + if (dev->descriptor.iSerialNumber) + usb_show_string(dev, "SerialNumber", dev->descriptor.iSerialNumber); /* now that the basic setup is over, add a /proc/bus/usb entry */ usbdevfs_add_device(dev); diff --git a/drivers/usb/usb.h b/drivers/usb/usb.h index c6f52047b..ec2754b1f 100644 --- a/drivers/usb/usb.h +++ b/drivers/usb/usb.h @@ -4,6 +4,9 @@ #include #include #include +#include +#include +#include /* for in_interrupt() */ /* USB constants */ @@ -116,7 +119,6 @@ #include #include -#include #define USB_MAJOR 180 @@ -159,8 +161,12 @@ typedef struct wait_queue *wait_queue_head_t; static __inline__ void wait_ms(unsigned int ms) { - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(1 + ms * HZ / 1000); + if(!in_interrupt()) { + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout(1 + ms * HZ / 1000); + } + else + mdelay(ms); } typedef struct { @@ -428,7 +434,7 @@ void usb_free_urb (purb_t purb); int usb_submit_urb(purb_t purb); int usb_unlink_urb(purb_t purb); int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe, devrequest *cmd, void *data, int len, int timeout); -int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, unsigned long *rval, int timeout); +int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int *actual_length, int timeout); /*-------------------------------------------------------------------* * COMPATIBILITY STUFF * @@ -661,22 +667,22 @@ int usb_new_device(struct usb_device *dev); int usb_set_address(struct usb_device *dev); int usb_get_descriptor(struct usb_device *dev, unsigned char desctype, unsigned char descindex, void *buf, int size); -int usb_get_class_descriptor(struct usb_device *dev, unsigned char desctype, - unsigned char descindex, unsigned char ifnum, void *buf, int size); +int usb_get_class_descriptor(struct usb_device *dev, int ifnum, unsigned char desctype, + unsigned char descindex, void *buf, int size); int usb_get_device_descriptor(struct usb_device *dev); int __usb_get_extra_descriptor(char *buffer, unsigned size, unsigned char type, void **ptr); -int usb_get_status (struct usb_device *dev, int type, int target, void *data); -int usb_get_protocol(struct usb_device *dev); -int usb_set_protocol(struct usb_device *dev, int protocol); -int usb_set_interface(struct usb_device *dev, int interface, int alternate); -int usb_set_idle(struct usb_device *dev, int duration, int report_id); +int usb_get_status(struct usb_device *dev, int type, int target, void *data); +int usb_get_protocol(struct usb_device *dev, int ifnum); +int usb_set_protocol(struct usb_device *dev, int ifnum, int protocol); +int usb_set_interface(struct usb_device *dev, int ifnum, int alternate); +int usb_set_idle(struct usb_device *dev, int ifnum, int duration, int report_id); 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); -int usb_set_report(struct usb_device *dev, unsigned char type, - unsigned char id, unsigned char index, void *buf, int size); +int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type, + unsigned char id, void *buf, int size); +int usb_set_report(struct usb_device *dev, int ifnum, unsigned char type, + unsigned char id, void *buf, int size); int usb_string(struct usb_device *dev, int index, char *buf, size_t size); -int usb_clear_halt(struct usb_device *dev, int endp); +int usb_clear_halt(struct usb_device *dev, int pipe); #define usb_get_extra_descriptor(ifpoint,type,ptr)\ __usb_get_extra_descriptor((ifpoint)->extra,(ifpoint)->extralen,type,(void**)ptr) diff --git a/drivers/usb/usb_scsi.c b/drivers/usb/usb_scsi.c deleted file mode 100644 index 885cdac77..000000000 --- a/drivers/usb/usb_scsi.c +++ /dev/null @@ -1,1539 +0,0 @@ -/* Driver for USB Mass Storage compliant devices - * - * (c) 1999 Michael Gee (michael@linuxspecific.com) - * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) - * - * Further reference: - * This driver is based on the 'USB Mass Storage Class' document. This - * describes in detail the protocol used to communicate with such - * devices. Clearly, the designers had SCSI commands in mind when they - * created this document. The commands are all similar to commands - * in the SCSI-II specification. - * - * It is important to note that in a number of cases this class exhibits - * class-specific exemptions from the USB specification. Notably the - * usage of NAK, STALL and ACK differs from the norm, in that they are - * used to communicate wait, failed and OK on commands. - * Also, for certain devices, the interrupt endpoint is used to convey - * status of a command. - * - * Basically, this stuff is WEIRD!! - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "../scsi/scsi.h" -#include "../scsi/hosts.h" -#include "../scsi/sd.h" - -#include "usb.h" -#include "usb_scsi.h" - -/* direction table -- this indicates the direction of the data - * transfer for each command code -- a 1 indicates input - */ -unsigned char us_direction[256/8] = { - 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77, - 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -/* - * Per device data - */ - -static int my_host_number; - -int usb_stor_debug = 1; - -struct us_data { - struct us_data *next; /* next device */ - struct usb_device *pusb_dev; - unsigned int flags; /* from filter initially */ - __u8 ifnum; /* interface number */ - __u8 ep_in; /* in endpoint */ - __u8 ep_out; /* out ....... */ - __u8 ep_int; /* interrupt . */ - __u8 subclass; /* as in overview */ - __u8 protocol; /* .............. */ - __u8 attention_done; /* force attn on first cmd */ - int (*pop)(Scsi_Cmnd *); /* protocol specific do cmd */ - int (*pop_reset)(struct us_data *); /* ........... device reset */ - GUID(guid); /* unique dev id */ - struct Scsi_Host *host; /* our dummy host data */ - Scsi_Host_Template *htmplt; /* own host template */ - int host_number; /* to find us */ - int host_no; /* allocated by scsi */ - int fixedlength; /* expand commands */ - Scsi_Cmnd *srb; /* current srb */ - int action; /* what to do */ - wait_queue_head_t waitq; /* thread waits */ - wait_queue_head_t ip_waitq; /* for CBI interrupts */ - __u16 ip_data; /* interrupt data */ - int ip_wanted; /* needed */ - int pid; /* control thread */ - struct semaphore *notify; /* wait for thread to begin */ - void *irq_handle; /* for USB int requests */ - unsigned int irqpipe; /* pipe for release_irq */ - int mode_xlate; /* trans MODE_6 to _10? */ -}; - -/* - * kernel thread actions - */ - -#define US_ACT_COMMAND 1 -#define US_ACT_ABORT 2 -#define US_ACT_DEVICE_RESET 3 -#define US_ACT_BUS_RESET 4 -#define US_ACT_HOST_RESET 5 - -static struct us_data *us_list; - -static void * storage_probe(struct usb_device *dev, unsigned int ifnum); -static void storage_disconnect(struct usb_device *dev, void *ptr); -static struct usb_driver storage_driver = { - "usb-storage", - storage_probe, - storage_disconnect, - { NULL, NULL } -}; - -/*********************************************************************** - * Data transfer routines - ***********************************************************************/ - -/* transfer one buffer (breaking into packets if necessary) */ -static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length) -{ - int max_size = usb_maxpacket(us->pusb_dev, pipe, usb_pipeout(pipe)) * 16; - int this_xfer; - int result; - unsigned long partial; - int maxtry = 100; - - /* while we have data to transfer */ - while (length) { - - /* calculate how long this will be -- maximum or a remainder */ - this_xfer = length > max_size ? max_size : length; - length -= this_xfer; - - do { - /* transfer the data */ - US_DEBUGP("Bulk xfer %x(%d)\n", (unsigned int)buf, this_xfer); - result = usb_bulk_msg(us->pusb_dev, pipe, buf, - this_xfer, &partial, HZ*5); - US_DEBUGP("bulk_msg returned %d xferred %lu/%d\n", - result, partial, this_xfer); - - /* if we stall, we need to clear it before we go on */ - if (result == USB_ST_STALL) { - US_DEBUGP("clearing endpoint halt for pipe %x\n", pipe); - usb_clear_halt(us->pusb_dev, - usb_pipeendpoint(pipe) | (pipe & USB_DIR_IN)); - } - - /* we want to retry if the device reported NAK */ - if (result == USB_ST_TIMEOUT) { - - /* if our try counter reaches 0, bail out */ - if (!maxtry--) - break; - - /* otherwise, we did transmit some data, and we update pointers */ - this_xfer -= partial; - buf += partial; - - } else if (!result && partial != this_xfer) { - /* result is an error, not a NAK, and short data - assume end */ - result = USB_ST_DATAUNDERRUN; - break; - - } else if (result == USB_ST_STALL && us->protocol == US_PR_CB) { - /* for CB devices, a stall isn't fatal? */ - - /* if our try counter reaches 0, bail out */ - if (!maxtry--) - break; - - this_xfer -= partial; - buf += partial; - } - - /* continue until this transfer is done */ - } while ( this_xfer ); - - /* if we have some nonzero result, we return it here */ - if (result) - return result; - - /* otherwise, we advance the buf pointer - * note that the code above doesn't advance the pointer if all - * goes well - */ - buf += this_xfer; - } - - /* if we get here, we're done and successful */ - return 0; -} - -/* transfer one SCSI command, using scatter-gather if requested */ -static int us_transfer(Scsi_Cmnd *srb, int dir_in) -{ - struct us_data *us = (struct us_data *)srb->host_scribble; - int i; - int result = -1; - unsigned int pipe = dir_in ? usb_rcvbulkpipe(us->pusb_dev, us->ep_in) : - usb_sndbulkpipe(us->pusb_dev, us->ep_out); - - if (srb->use_sg) { - struct scatterlist *sg = (struct scatterlist *) srb->request_buffer; - - for (i = 0; i < srb->use_sg; i++) { - result = us_one_transfer(us, pipe, sg[i].address, sg[i].length); - if (result) - break; - } - } - else - result = us_one_transfer(us, pipe, - srb->request_buffer, srb->request_bufflen); - - if (result) - US_DEBUGP("us_transfer returning error %d\n", result); - return result; -} - -/* calculate the length of the data transfer (not the command) for any - * given SCSI command - */ -static unsigned int us_transfer_length(Scsi_Cmnd *srb) -{ - int i; - unsigned int total = 0; - - /* always zero for some commands */ - switch (srb->cmnd[0]) { - case SEEK_6: - case SEEK_10: - case REZERO_UNIT: - case ALLOW_MEDIUM_REMOVAL: - case START_STOP: - case TEST_UNIT_READY: - return 0; - - default: - break; - } - - if (srb->use_sg) { - struct scatterlist *sg = (struct scatterlist *) srb->request_buffer; - - for (i = 0; i < srb->use_sg; i++) { - total += sg[i].length; - } - return total; - } - else - return srb->request_bufflen; -} - -/*********************************************************************** - * Transport routines - ***********************************************************************/ - -static int CBI_irq(int state, void *buffer, int len, void *dev_id) -{ - struct us_data *us = (struct us_data *)dev_id; - - US_DEBUGP("CBI_irq() called!!\n"); - - if (state != USB_ST_REMOVED) { - us->ip_data = le16_to_cpup((__u16 *)buffer); - US_DEBUGP("Interrupt Status %x\n", us->ip_data); - } - - if (us->ip_wanted) { - us->ip_wanted = 0; - wake_up(&us->ip_waitq); - } - - /* this return code is truly meaningless */ - return 0; -} - -static int pop_CB_reset(struct us_data *us) -{ - unsigned char cmd[12]; - int result; - - US_DEBUGP("pop_CB_reset\n"); - - memset(cmd, -1, sizeof(cmd)); - 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_RECIP_INTERFACE, - 0, us->ifnum, cmd, sizeof(cmd), HZ*5); - - /* long wait for reset */ - - schedule_timeout(HZ*6); - - US_DEBUGP("pop_CB_reset: clearing endpoint halt\n"); - usb_clear_halt(us->pusb_dev, us->ep_in | USB_DIR_IN); - usb_clear_halt(us->pusb_dev, us->ep_out | USB_DIR_OUT); - - US_DEBUGP("pop_CB_reset done\n"); - return 0; -} - -static int pop_CB_command(Scsi_Cmnd *srb) -{ - struct us_data *us = (struct us_data *)srb->host_scribble; - unsigned char cmd[16]; - int result; - int retry = 5; - int done_start = 0; - - /* we'll try this up to 5 times? */ - while (retry--) { - if (us->flags & US_FL_FIXED_COMMAND) { - memset(cmd, 0, us->fixedlength); - - /* fix some commands */ - - switch (srb->cmnd[0]) { - case WRITE_6: - case READ_6: - cmd[0] = srb->cmnd[0] | 0x20; - cmd[1] = srb->cmnd[1] & 0xE0; - cmd[2] = 0; - cmd[3] = srb->cmnd[1] & 0x1F; - cmd[4] = srb->cmnd[2]; - cmd[5] = srb->cmnd[3]; - cmd[8] = srb->cmnd[4]; - break; - - case MODE_SENSE: - case MODE_SELECT: - us->mode_xlate = (srb->cmnd[0] == MODE_SENSE); - cmd[0] = srb->cmnd[0] | 0x40; - cmd[1] = srb->cmnd[1]; - cmd[2] = srb->cmnd[2]; - cmd[8] = srb->cmnd[4]; - break; - - default: - us->mode_xlate = 0; - memcpy(cmd, srb->cmnd, srb->cmd_len); - break; - } /* switch */ - - result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0), - 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); - - /* For UFI, if this is the first time we've sent this TEST_UNIT_READY - * command, we can try again - */ - if (!done_start && (us->subclass == US_SC_UFI) - && (cmd[0] == TEST_UNIT_READY) && (result < 0)) { - - /* as per spec try a start command, wait and retry */ - wait_ms(100); - - done_start++; - memset(cmd, 0, sizeof(cmd)); - cmd[0] = START_STOP; - cmd[4] = 1; /* start */ - - result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0), - US_CBI_ADSC, - USB_TYPE_CLASS | USB_RECIP_INTERFACE, - 0, us->ifnum, - cmd, us->fixedlength, HZ*5); - US_DEBUGP("Next usb_control_msg returns %d\n", result); - - /* allow another retry */ - retry++; - continue; - } - } 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_RECIP_INTERFACE, - 0, us->ifnum, - srb->cmnd, srb->cmd_len, HZ*5); - } - - /* return an answer if we've got one */ - if (/*result != USB_ST_STALL &&*/ result != USB_ST_TIMEOUT) - return result; - } - - /* all done -- return our status */ - return result; -} - -/* - * Control/Bulk status handler - */ - -static int pop_CB_status(Scsi_Cmnd *srb) -{ - struct us_data *us = (struct us_data *)srb->host_scribble; - int result; - __u8 status[2]; - int retry = 5; - - US_DEBUGP("pop_CB_status, proto=%x\n", us->protocol); - switch (us->protocol) { - case US_PR_CB: - /* get from control */ - - 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_RECIP_DEVICE, - 0, us->ifnum, status, sizeof(status), HZ*5); - if (result != USB_ST_TIMEOUT) - break; - } - if (result) { - US_DEBUGP("Bad AP status request %d\n", result); - return DID_ABORT << 16; - } - US_DEBUGP("Got AP status %x %x\n", status[0], status[1]); - if (srb->cmnd[0] != REQUEST_SENSE && srb->cmnd[0] != INQUIRY && - ( (status[0] & ~3) || status[1])) - return (DID_OK << 16) | 2; - else - return DID_OK << 16; - break; - - case US_PR_CBI: - /* get from interrupt pipe */ - - /* add interrupt transfer, marked for removal */ - us->ip_wanted = 1; - - /* go to sleep until we get this interrup */ - sleep_on(&us->ip_waitq); - - /* NO! We don't release this IRQ. We just re-use the handler - usb_release_irq(us->pusb_dev, us->irq_handle, us->irqpipe); - us->irq_handle = NULL; - */ - - if (us->ip_wanted) { - US_DEBUGP("Did not get interrupt on CBI\n"); - us->ip_wanted = 0; - return DID_ABORT << 16; - } - - US_DEBUGP("Got interrupt data %x\n", us->ip_data); - - /* sort out what it means */ - - if (us->subclass == US_SC_UFI) { - /* gives us asc and ascq, as per request sense */ - - if (srb->cmnd[0] == REQUEST_SENSE || - srb->cmnd[0] == INQUIRY) - return DID_OK << 16; - else - return (DID_OK << 16) + ((us->ip_data & 0xff) ? 2 : 0); - } - if (us->ip_data & 0xff) { - US_DEBUGP("Bad CBI interrupt data %x\n", us->ip_data); - return DID_ABORT << 16; - } - return (DID_OK << 16) + ((us->ip_data & 0x300) ? 2 : 0); - } - return DID_ERROR << 16; -} - -/* Protocol command handlers */ - -static int pop_CBI(Scsi_Cmnd *srb) -{ - int result; - - US_DEBUGP("CBI gets a command:\n"); - US_DEBUG(us_show_command(srb)); - - /* run the command */ - if ((result = pop_CB_command(srb)) < 0) { - US_DEBUGP("Call to pop_CB_command returned %d\n", result); - if (result == USB_ST_STALL || result == USB_ST_TIMEOUT) { - return (DID_OK << 16) | 2; - } - return DID_ERROR << 16; - } - - /* transfer the data */ - if (us_transfer_length(srb)) { - result = us_transfer(srb, US_DIRECTION(srb->cmnd[0])); - if ((result < 0) && - (result != USB_ST_DATAUNDERRUN) && - (result != USB_ST_STALL)) { - US_DEBUGP("CBI attempted to transfer data, result is %x\n", result); - return DID_ERROR << 16; - } -#if 0 - else if (result == USB_ST_DATAUNDERRUN) { - return DID_OK << 16; - } - } else { - if (!result) { - return DID_OK << 16; - } -#endif - } - - /* get status */ - return pop_CB_status(srb); -} - -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_RECIP_INTERFACE, - US_BULK_RESET_HARD, us->ifnum, - NULL, 0, HZ*5); - if (result) - US_DEBUGP("Bulk hard reset failed %d\n", result); - usb_clear_halt(us->pusb_dev, us->ep_in | USB_DIR_IN); - usb_clear_halt(us->pusb_dev, us->ep_out | USB_DIR_OUT); - - /* long wait for reset */ - - schedule_timeout(HZ*6); - - return result; -} - -/* - * The bulk only protocol handler. - * Uses the in and out endpoints to transfer commands and data (nasty) - */ -static int pop_Bulk(Scsi_Cmnd *srb) -{ - struct us_data *us = (struct us_data *)srb->host_scribble; - struct bulk_cb_wrap bcb; - struct bulk_cs_wrap bcs; - int result; - unsigned long partial; - int stall; - - /* set up the command wrapper */ - - bcb.Signature = US_BULK_CB_SIGN; - bcb.DataTransferLength = us_transfer_length(srb);; - bcb.Flags = US_DIRECTION(srb->cmnd[0]) << 7; - bcb.Tag = srb->serial_number; - bcb.Lun = 0; - memset(bcb.CDB, 0, sizeof(bcb.CDB)); - memcpy(bcb.CDB, srb->cmnd, srb->cmd_len); - if (us->flags & US_FL_FIXED_COMMAND) { - bcb.Length = us->fixedlength; - } else { - bcb.Length = srb->cmd_len; - } - - /* send it to out endpoint */ - - US_DEBUGP("Bulk command S %x T %x L %d F %d CL %d\n", - bcb.Signature, bcb.Tag, bcb.DataTransferLength, - bcb.Flags, bcb.Length); - result = usb_bulk_msg(us->pusb_dev, - usb_sndbulkpipe(us->pusb_dev, us->ep_out), &bcb, - US_BULK_CB_WRAP_LEN, &partial, HZ*5); - if (result) { - US_DEBUGP("Bulk command result %x\n", result); - return DID_ABORT << 16; - } - - //return DID_BAD_TARGET << 16; - /* send/receive data */ - - if (bcb.DataTransferLength) { - result = us_transfer(srb, bcb.Flags); - if (result && result != USB_ST_DATAUNDERRUN && result != USB_ST_STALL) { - US_DEBUGP("Bulk transfer result %x\n", result); - return DID_ABORT << 16; - } - } - - /* get status */ - - stall = 0; - do { - result = usb_bulk_msg(us->pusb_dev, - usb_rcvbulkpipe(us->pusb_dev, us->ep_in), &bcs, - US_BULK_CS_WRAP_LEN, &partial, HZ*5); - if (result == USB_ST_STALL || result == USB_ST_TIMEOUT) - stall++; - else - break; - } while ( stall < 3); - if (result && result != USB_ST_DATAUNDERRUN) { - US_DEBUGP("Bulk status result = %x\n", result); - return DID_ABORT << 16; - } - - /* check bulk status */ - - US_DEBUGP("Bulk status S %x T %x R %d V %x\n", - bcs.Signature, bcs.Tag, bcs.Residue, bcs.Status); - if (bcs.Signature != US_BULK_CS_SIGN || bcs.Tag != bcb.Tag || - bcs.Status > US_BULK_STAT_PHASE) { - US_DEBUGP("Bulk logical error\n"); - return DID_ABORT << 16; - } - - /* We need to fix some of this status handling. */ - switch (bcs.Status) { - case US_BULK_STAT_OK: - return DID_OK << 16; - - case US_BULK_STAT_FAIL: - /* check for underrun - dont report */ - if (bcs.Residue) - return DID_OK << 16; - //pop_Bulk_reset(us); - break; - - case US_BULK_STAT_PHASE: - return DID_ERROR << 16; - } - - return (DID_OK << 16) | 2; /* check sense required */ -} - -/* Host functions */ - -/* detect adapter (always true ) */ -static int us_detect(struct SHT *sht) -{ - /* FIXME - not nice at all, but how else ? */ - struct us_data *us = (struct us_data *)sht->proc_dir; - char name[32]; - - /* set up our name */ - sprintf(name, "usbscsi%d", us->host_number); - sht->name = sht->proc_name = kmalloc(strlen(name)+1, GFP_KERNEL); - if (!sht->proc_name) - return 0; - strcpy(sht->proc_name, name); - - /* we start with no /proc directory entry */ - sht->proc_dir = NULL; - - /* register the host */ - us->host = scsi_register(sht, sizeof(us)); - if (us->host) { - us->host->hostdata[0] = (unsigned long)us; - us->host_no = us->host->host_no; - return 1; - } - - /* odd... didn't register properly. Abort and free pointers */ - kfree(sht->proc_name); - sht->proc_name = NULL; - sht->name = NULL; - return 0; -} - -/* release - must be here to stop scsi - * from trying to release IRQ etc. - * Kill off our data - */ -static int us_release(struct Scsi_Host *psh) -{ - struct us_data *us = (struct us_data *)psh->hostdata[0]; - struct us_data *prev = (struct us_data *)&us_list; - - if (us->irq_handle) { - usb_release_irq(us->pusb_dev, us->irq_handle, us->irqpipe); - us->irq_handle = NULL; - } - if (us->pusb_dev) - usb_deregister(&storage_driver); - - /* FIXME - leaves hanging host template copy */ - /* (because scsi layer uses it after removal !!!) */ - while (prev->next != us) - prev = prev->next; - prev->next = us->next; - return 0; -} - -/* run command */ -static int us_command( Scsi_Cmnd *srb ) -{ - US_DEBUGP("Bad use of us_command\n"); - - return DID_BAD_TARGET << 16; -} - -/* run command */ -static int us_queuecommand( Scsi_Cmnd *srb , void (*done)(Scsi_Cmnd *)) -{ - struct us_data *us = (struct us_data *)srb->host->hostdata[0]; - - US_DEBUGP("Command wakeup\n"); - if (us->srb) { - /* busy */ - } - srb->host_scribble = (unsigned char *)us; - us->srb = srb; - srb->scsi_done = done; - us->action = US_ACT_COMMAND; - - /* wake up the process task */ - - wake_up_interruptible(&us->waitq); - - return 0; -} - -static int us_abort( Scsi_Cmnd *srb ) -{ - return 0; -} - -static int us_bus_reset( Scsi_Cmnd *srb ) -{ - struct us_data *us = (struct us_data *)srb->host->hostdata[0]; - - US_DEBUGP("Bus reset requested\n"); - us->pop_reset(us); - return SUCCESS; -} - -static int us_host_reset( Scsi_Cmnd *srb ) -{ - return 0; -} - -/*********************************************************************** - * /proc/scsi/ functions - ***********************************************************************/ - -/* we use this macro to help us write into the buffer */ -#undef SPRINTF -#define SPRINTF(args...) do { if (pos < (buffer + length)) pos += sprintf (pos, ## args); } while (0) - -int usb_stor_proc_info (char *buffer, char **start, off_t offset, - int length, int hostno, int inout) -{ - struct us_data *us = us_list; - char *pos = buffer; - char *tmp_ptr; - - /* find our data from hostno */ - while (us) { - if (us->host_no == hostno) - break; - us = us->next; - } - - /* if we couldn't find it, we return an error */ - if (!us) - return -ESRCH; - - /* if someone is sending us data, just throw it away */ - if (inout) - return length; - - /* print the controler name */ - SPRINTF ("Host scsi%d: usb-scsi\n", hostno); - - /* print product and vendor strings */ - 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: "); - 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: "); - 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) { - case US_PR_CB: - SPRINTF("Control/Bulk\n"); - break; - - case US_PR_CBI: - SPRINTF("Control/Bulk/Interrupt\n"); - break; - - case US_PR_BULK: - SPRINTF("Bulk only\n"); - break; - - default: - SPRINTF("Unknown Protocol\n"); - break; - } - - /* show the GUID of the device */ - SPRINTF("GUID: " GUID_FORMAT "\n", GUID_ARGS(us->guid)); - - /* - * Calculate start of next buffer, and return value. - */ - *start = buffer + offset; - - if ((pos - buffer) < offset) - return (0); - else if ((pos - buffer - offset) < length) - return (pos - buffer - offset); - else - return (length); -} - -/* - * this defines our 'host' - */ - -static Scsi_Host_Template my_host_template = { - NULL, /* next */ - NULL, /* module */ - NULL, /* proc_dir */ - usb_stor_proc_info, - NULL, /* name - points to unique */ - us_detect, - us_release, - NULL, /* info */ - NULL, /* ioctl */ - us_command, - us_queuecommand, - NULL, /* eh_strategy */ - us_abort, - us_bus_reset, - us_bus_reset, - us_host_reset, - NULL, /* abort */ - NULL, /* reset */ - NULL, /* slave_attach */ - NULL, /* bios_param */ - 1, /* can_queue */ - -1, /* this_id */ - SG_ALL, /* sg_tablesize */ - 1, /* cmd_per_lun */ - 0, /* present */ - FALSE, /* unchecked_isa_dma */ - FALSE, /* use_clustering */ - TRUE, /* use_new_eh_code */ - TRUE /* emulated */ -}; - -static unsigned char sense_notready[] = { - 0x70, /* current error */ - 0x00, - 0x02, /* not ready */ - 0x00, - 0x00, - 10, /* additional length */ - 0x00, - 0x00, - 0x00, - 0x00, - 0x04, /* not ready */ - 0x03, /* manual intervention */ - 0x00, - 0x00, - 0x00, - 0x00 -}; - -static int usb_stor_control_thread(void * __us) -{ - struct us_data *us = (struct us_data *)__us; - int action; - - lock_kernel(); - - /* - * This thread doesn't need any user-level access, - * so get rid of all our resources.. - */ - daemonize(); - - sprintf(current->comm, "usbscsi%d", us->host_number); - - unlock_kernel(); - - up(us->notify); - - for(;;) { - siginfo_t info; - int unsigned long signr; - - interruptible_sleep_on(&us->waitq); - - action = us->action; - us->action = 0; - - switch (action) { - case US_ACT_COMMAND: - if (us->srb->target || us->srb->lun) { - /* bad device */ - US_DEBUGP( "Bad device number (%d/%d) or dev %x\n", - us->srb->target, us->srb->lun, (unsigned int)us->pusb_dev); - us->srb->result = DID_BAD_TARGET << 16; - } else if (!us->pusb_dev) { - - /* our device has gone - pretend not ready */ - - if (us->srb->cmnd[0] == REQUEST_SENSE) { - memcpy(us->srb->request_buffer, sense_notready, sizeof(sense_notready)); - us->srb->result = DID_OK << 16; - } else { - us->srb->result = (DID_OK << 16) | 2; - } - } else { - US_DEBUG(us_show_command(us->srb)); - - if (us->srb->cmnd[0] == START_STOP && - us->pusb_dev->descriptor.idProduct == 0x0001 && - us->pusb_dev->descriptor.idVendor == 0x04e6) - us->srb->result = DID_OK << 16; - else { - unsigned int savelen = us->srb->request_bufflen; - unsigned int saveallocation = 0; - - /* check for variable length - do properly if so */ - switch (us->srb->cmnd[0]) { - case REQUEST_SENSE: - if (us->srb->request_bufflen > 18) - us->srb->request_bufflen = 18; - else - break; - saveallocation = us->srb->cmnd[4]; - us->srb->cmnd[4] = 18; - break; - - case INQUIRY: - if (us->srb->request_bufflen > 36) - us->srb->request_bufflen = 36; - else - break; - saveallocation = us->srb->cmnd[4]; - us->srb->cmnd[4] = 36; - break; - - case MODE_SENSE: - if (us->srb->request_bufflen > 4) - us->srb->request_bufflen = 4; - else - break; - saveallocation = us->srb->cmnd[4]; - us->srb->cmnd[4] = 4; - break; - - case LOG_SENSE: - case MODE_SENSE_10: - if (us->srb->request_bufflen > 8) - us->srb->request_bufflen = 8; - else - break; - saveallocation = (us->srb->cmnd[7] << 8) | us->srb->cmnd[8]; - us->srb->cmnd[7] = 0; - us->srb->cmnd[8] = 8; - break; - - default: - break; - } /* end switch on cmnd[0] */ - -#if 0 - /* translate READ_6 to READ_10 */ - if (us->srb->cmnd[0] == 0x08) { - - /* get the control */ - us->srb->cmnd[9] = us->srb->cmnd[5]; - - /* get the length */ - us->srb->cmnd[8] = us->srb->cmnd[6]; - us->srb->cmnd[7] = 0; - - /* set the reserved area to 0 */ - us->srb->cmnd[6] = 0; - - /* get LBA */ - us->srb->cmnd[5] = us->srb->cmnd[3]; - us->srb->cmnd[4] = us->srb->cmnd[2]; - us->srb->cmnd[3] = 0; - us->srb->cmnd[2] = 0; - - /* LUN and other info in cmnd[1] can stay */ - - /* fix command code */ - us->srb->cmnd[0] = 0x28; - - US_DEBUGP("Changing READ_6 to READ_10\n"); - US_DEBUG(us_show_command(us->srb)); - } - - /* translate WRITE_6 to WRITE_10 */ - if (us->srb->cmnd[0] == 0x0A) { - - /* get the control */ - us->srb->cmnd[9] = us->srb->cmnd[5]; - - /* get the length */ - us->srb->cmnd[8] = us->srb->cmnd[4]; - us->srb->cmnd[7] = 0; - - /* set the reserved area to 0 */ - us->srb->cmnd[6] = 0; - - /* get LBA */ - us->srb->cmnd[5] = us->srb->cmnd[3]; - us->srb->cmnd[4] = us->srb->cmnd[2]; - us->srb->cmnd[3] = 0; - us->srb->cmnd[2] = 0; - - /* LUN and other info in cmnd[1] can stay */ - - /* fix command code */ - us->srb->cmnd[0] = 0x2A; - - US_DEBUGP("Changing WRITE_6 to WRITE_10\n"); - US_DEBUG(us_show_command(us->srb)); - } -#endif - - /* let's do the command */ - us->srb->result = us->pop(us->srb); - - if (savelen != us->srb->request_bufflen && - us->srb->result == (DID_OK << 16)) { - unsigned char *p = (unsigned char *)us->srb->request_buffer; - unsigned int length = 0; - - /* set correct length and retry */ - switch (us->srb->cmnd[0]) { - case REQUEST_SENSE: - /* simply return 18 bytes */ - p[7] = 10; - length = us->srb->request_bufflen; - break; - - case INQUIRY: - length = p[4] + 5 > savelen ? savelen : p[4] + 5; - us->srb->cmnd[4] = length; - break; - - case MODE_SENSE: - US_DEBUGP("MODE_SENSE Mode data length is %d\n", p[0]); - length = p[0] + 1 > savelen ? savelen : p[0] + 1; - us->srb->cmnd[4] = length; - break; - - case LOG_SENSE: - length = ((p[2] << 8) + p[3]) + 4 > savelen ? savelen : ((p[2] << 8) + p[3]) + 4; - us->srb->cmnd[7] = length >> 8; - us->srb->cmnd[8] = length; - break; - - case MODE_SENSE_10: - US_DEBUGP("MODE_SENSE_10 Mode data length is %d\n", - (p[0] << 8) + p[1]); - length = ((p[0] << 8) + p[1]) + 6 > savelen ? savelen : ((p[0] << 8) + p[1]) + 6; - us->srb->cmnd[7] = length >> 8; - us->srb->cmnd[8] = length; - break; - } /* end switch on cmnd[0] */ - - US_DEBUGP("Old/New length = %d/%d\n", - savelen, length); - - if (us->srb->request_bufflen != length) { - US_DEBUGP("redoing cmd with len=%d\n", length); - us->srb->request_bufflen = length; - us->srb->result = us->pop(us->srb); - } - /* reset back to original values */ - - us->srb->request_bufflen = savelen; - switch (us->srb->cmnd[0]) { - case INQUIRY: - if ((((unsigned char*)us->srb->request_buffer)[2] & 0x7) == 0) { - US_DEBUGP("Fixing INQUIRY data, setting SCSI rev to 2\n"); - ((unsigned char*)us->srb->request_buffer)[2] |= 2; - } - /* FALL THROUGH */ - case REQUEST_SENSE: - case MODE_SENSE: - if (us->srb->use_sg == 0 && length > 0) { - int i; - printk(KERN_DEBUG "Data is"); - for (i = 0; i < 32 && i < length; ++i) - printk(" %.2x", ((unsigned char *)us->srb->request_buffer)[i]); - if (i < length) - printk(" ..."); - printk("\n"); - } - us->srb->cmnd[4] = saveallocation; - if (us->mode_xlate) { - /* convert MODE_SENSE_10 return data - * format to MODE_SENSE_6 format */ - unsigned char *dta = (unsigned char *)us->srb->request_buffer; - dta[0] = dta[1]; /* data len */ - dta[1] = dta[2]; /* med type */ - dta[2] = dta[3]; /* dev-spec prm */ - dta[3] = dta[7]; /* block desc len */ - printk (KERN_DEBUG USB_SCSI "new MODE_SENSE_6 data = %.2X %.2X %.2X %.2X\n", - dta[0], dta[1], dta[2], dta[3]); - } - break; - - case LOG_SENSE: - case MODE_SENSE_10: - us->srb->cmnd[7] = saveallocation >> 8; - us->srb->cmnd[8] = saveallocation; - break; - } /* end switch on cmnd[0] */ - } - /* force attention on first command */ - if (!us->attention_done) { - US_DEBUGP("forcing unit attention\n"); - if (us->srb->cmnd[0] == REQUEST_SENSE) { - if (us->srb->result == (DID_OK << 16)) { - unsigned char *p = (unsigned char *)us->srb->request_buffer; - - us->attention_done = 1; - if ((p[2] & 0x0f) != UNIT_ATTENTION) { - p[2] = UNIT_ATTENTION; - p[12] = 0x29; /* power on, reset or bus-reset */ - p[13] = 0; - } - } - } else if (us->srb->cmnd[0] != INQUIRY && - us->srb->result == (DID_OK << 16)) { - us->srb->result |= 2; /* force check condition */ - } - } - } - } - US_DEBUGP("scsi cmd done, result=%x\n", us->srb->result); - us->srb->scsi_done(us->srb); - us->srb = NULL; - break; - - case US_ACT_ABORT: - break; - - case US_ACT_DEVICE_RESET: - break; - - case US_ACT_BUS_RESET: - break; - - case US_ACT_HOST_RESET: - break; - - } /* end switch on action */ - - if (signal_pending(current)) { - /* sending SIGUSR1 makes us print out some info */ - spin_lock_irq(¤t->sigmask_lock); - signr = dequeue_signal(¤t->blocked, &info); - spin_unlock_irq(¤t->sigmask_lock); - - if (signr == SIGUSR2) { - usb_stor_debug = !usb_stor_debug; - printk(USB_SCSI "debug toggle = %d\n", usb_stor_debug); - } else { - break; /* exit the loop on any other signal */ - } - } - } - - // MOD_DEC_USE_COUNT; - - printk("usb_stor_control_thread exiting\n"); - - return 0; -} - -/* Probe to see if a new device is actually a SCSI device */ -static void * storage_probe(struct usb_device *dev, unsigned int ifnum) -{ - struct usb_interface_descriptor *interface; - int i; - 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 */ - struct us_data *prev; - Scsi_Host_Template *htmplt; - int protocol = 0; - int subclass = 0; - struct usb_interface_descriptor *altsetting = - &(dev->actconfig->interface[ifnum].altsetting[0]); - - /* clear the GUID and fetch the strings */ - GUID_CLEAR(guid); - 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 */ - - /* We make an exception for the shuttle E-USB */ - if (dev->descriptor.idVendor == 0x04e6 && - dev->descriptor.idProduct == 0x0001) { - protocol = US_PR_CB; - subclass = US_SC_8070; /* an assumption */ - } else if (dev->descriptor.bDeviceClass != 0 || - altsetting->bInterfaceClass != USB_CLASS_MASS_STORAGE || - altsetting->bInterfaceSubClass < US_SC_MIN || - altsetting->bInterfaceSubClass > US_SC_MAX) { - /* if it's not a mass storage, we go no further */ - return NULL; - } - - /* At this point, we know we've got a live one */ - US_DEBUGP("USB Mass Storage device detected\n"); - - /* Create a GUID for this device */ - 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, - serial); - } else { - /* We don't have a serial number, so we use 0 */ - make_guid(guid, dev->descriptor.idVendor, - dev->descriptor.idProduct, "0"); - } - - /* Now check if we have seen this GUID before, and restore - * the flags if we find it - */ - for (ss = us_list; ss != NULL; ss = ss->next) { - if (!ss->pusb_dev && GUID_EQUAL(guid, ss->guid)) { - US_DEBUGP("Found existing GUID " GUID_FORMAT "\n", - GUID_ARGS(guid)); - flags = ss->flags; - break; - } - } - - /* If ss == NULL, then this is a new device. Allocate memory for it */ - if (!ss) { - if ((ss = (struct us_data *)kmalloc(sizeof(*ss), - GFP_KERNEL)) == NULL) { - printk(KERN_WARNING USB_SCSI "Out of memory\n"); - return NULL; - } - memset(ss, 0, sizeof(struct us_data)); - } - - /* Initialize the us_data structure with some useful info */ - interface = altsetting; - ss->flags = flags; - ss->ifnum = ifnum; - ss->pusb_dev = dev; - ss->attention_done = 0; - - /* If the device has subclass and protocol, then use that. Otherwise, - * take data from the specific interface. - */ - if (subclass) { - ss->subclass = subclass; - ss->protocol = protocol; - } else { - ss->subclass = interface->bInterfaceSubClass; - ss->protocol = interface->bInterfaceProtocol; - } - - /* set the handler pointers based on the protocol */ - US_DEBUGP("Protocol: "); - switch (ss->protocol) { - case US_PR_CB: - US_DEBUGPX("Control/Bulk\n"); - ss->pop = pop_CBI; - ss->pop_reset = pop_CB_reset; - break; - - case US_PR_CBI: - US_DEBUGPX("Control/Bulk/Interrupt\n"); - ss->pop = pop_CBI; - ss->pop_reset = pop_CB_reset; - break; - - case US_PR_BULK: - US_DEBUGPX("Bulk\n"); - ss->pop = pop_Bulk; - ss->pop_reset = pop_Bulk_reset; - break; - - default: - US_DEBUGPX("Unknown\n"); - kfree(ss); - return NULL; - break; - } - - /* - * We are expecting a minimum of 2 endpoints - in and out (bulk). - * An optional interrupt is OK (necessary for CBI protocol). - * We will ignore any others. - */ - for (i = 0; i < interface->bNumEndpoints; i++) { - /* is it an BULK endpoint? */ - if ((interface->endpoint[i].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) - == USB_ENDPOINT_XFER_BULK) { - if (interface->endpoint[i].bEndpointAddress & USB_DIR_IN) - ss->ep_in = interface->endpoint[i].bEndpointAddress & - USB_ENDPOINT_NUMBER_MASK; - else - ss->ep_out = interface->endpoint[i].bEndpointAddress & - USB_ENDPOINT_NUMBER_MASK; - } - - /* is it an interrupt endpoint? */ - if ((interface->endpoint[i].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) - == USB_ENDPOINT_XFER_INT) { - ss->ep_int = interface->endpoint[i].bEndpointAddress & - USB_ENDPOINT_NUMBER_MASK; - } - } - US_DEBUGP("Endpoints In %d Out %d Int %d\n", - ss->ep_in, ss->ep_out, ss->ep_int); - - /* Do some basic sanity checks, and bail if we find a problem */ - if (usb_set_interface(dev, interface->bInterfaceNumber, 0) || - !ss->ep_in || !ss->ep_out || - (ss->protocol == US_PR_CBI && ss->ep_int == 0)) { - US_DEBUGP("Problems with device\n"); - if (ss->host) { - scsi_unregister_module(MODULE_SCSI_HA, ss->htmplt); - kfree(ss->htmplt->name); - kfree(ss->htmplt); - } - - kfree(ss); - return NULL; - } - - /* If this is a new device (i.e. we haven't seen it before), we need to - * generate a scsi host definition, and register with scsi above us - */ - if (!ss->host) { - /* copy the GUID we created before */ - US_DEBUGP("New GUID " GUID_FORMAT "\n", GUID_ARGS(guid)); - memcpy(ss->guid, guid, sizeof(guid)); - - /* set class specific stuff */ - US_DEBUGP("SubClass: "); - switch (ss->subclass) { - case US_SC_RBC: - US_DEBUGPX("Reduced Block Commands\n"); - break; - - case US_SC_8020: - US_DEBUGPX("8020\n"); - break; - - case US_SC_QIC: - US_DEBUGPX("QIC157\n"); - break; - - case US_SC_8070: - US_DEBUGPX("8070\n"); - ss->flags |= US_FL_FIXED_COMMAND; - ss->fixedlength = 12; - break; - - case US_SC_SCSI: - US_DEBUGPX("Transparent SCSI\n"); - break; - - case US_SC_UFI: - US_DEBUGPX("UFI\n"); - ss->flags |= US_FL_FIXED_COMMAND; - ss->fixedlength = 12; - break; - - default: - US_DEBUGPX("Unknown\n"); - break; - } - - /* Allocate memory for the SCSI Host Template */ - if ((htmplt = (Scsi_Host_Template *) - kmalloc(sizeof(*ss->htmplt), GFP_KERNEL)) == NULL ) { - - printk(KERN_WARNING USB_SCSI "Out of memory\n"); - - kfree(ss); - return NULL; - } - - /* Initialize the host template based on the default one */ - memcpy(htmplt, &my_host_template, sizeof(my_host_template)); - - /* Grab the next host number */ - ss->host_number = my_host_number++; - - /* MDD: FIXME: this is bad. We abuse this pointer so we - * can pass the ss pointer to the host controler thread - * in us_detect - */ - (struct us_data *)htmplt->proc_dir = ss; - - /* shuttle E-USB */ - if (dev->descriptor.idVendor == 0x04e6 && - dev->descriptor.idProduct == 0x0001) { - __u8 qstat[2]; - int result; - - result = usb_control_msg(ss->pusb_dev, usb_rcvctrlpipe(dev,0), - 1, 0xC0, - 0, ss->ifnum, - qstat, 2, HZ*5); - US_DEBUGP("C0 status %x %x\n", qstat[0], qstat[1]); - init_waitqueue_head(&ss->ip_waitq); - ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int); - result = usb_request_irq(ss->pusb_dev, ss->irqpipe, CBI_irq, - 255, (void *)ss, &ss->irq_handle); - if (result) - return NULL; - - interruptible_sleep_on_timeout(&ss->ip_waitq, HZ*6); - } else if (ss->protocol == US_PR_CBI) - { - int result; - - init_waitqueue_head(&ss->ip_waitq); - - /* set up the IRQ pipe and handler */ - /* FIXME: This needs to get the period from the device */ - ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int); - result = usb_request_irq(ss->pusb_dev, ss->irqpipe, CBI_irq, - 255, (void *)ss, &ss->irq_handle); - if (result) { - US_DEBUGP("usb_request_irq failed (0x%x), No interrupt for CBI\n", - result); - } - } - - - /* start up our thread */ - { - DECLARE_MUTEX_LOCKED(sem); - - init_waitqueue_head(&ss->waitq); - - ss->notify = &sem; - ss->pid = kernel_thread(usb_stor_control_thread, ss, - CLONE_FS | CLONE_FILES | CLONE_SIGHAND); - if (ss->pid < 0) { - printk(KERN_WARNING USB_SCSI "Unable to start control thread\n"); - kfree(htmplt); - - kfree(ss); - return NULL; - } - - /* wait for it to start */ - down(&sem); - } - - /* now register - our detect function will be called */ - - scsi_register_module(MODULE_SCSI_HA, htmplt); - - /* put us in the list */ - - prev = (struct us_data *)&us_list; - while (prev->next) - prev = prev->next; - prev->next = ss; - } - - printk(KERN_WARNING "WARNING: USB SCSI data integrity not assured\n"); - printk(KERN_INFO "USB SCSI device found at address %d\n", dev->devnum); - - return ss; -} - -/* Handle a disconnect event from the USB core */ -static void storage_disconnect(struct usb_device *dev, void *ptr) -{ - struct us_data *ss = ptr; - - if (!ss) - return; - - ss->pusb_dev = NULL; - // MOD_DEC_USE_COUNT; -} - - -/*********************************************************************** - * Initialization and registration - ***********************************************************************/ - -int usb_stor_init(void) -{ - // MOD_INC_USE_COUNT; - - if (usb_register(&storage_driver) < 0) - return -1; - - printk(KERN_INFO "USB SCSI support registered.\n"); - return 0; -} - -#ifdef MODULE -int init_module(void) -{ - /* MDD: Perhaps we should register the host here */ - return usb_stor_init(); -} - -void cleanup_module(void) -{ - usb_deregister(&storage_driver); -} -#endif diff --git a/drivers/usb/usb_scsi.h b/drivers/usb/usb_scsi.h deleted file mode 100644 index 3e1feb783..000000000 --- a/drivers/usb/usb_scsi.h +++ /dev/null @@ -1,146 +0,0 @@ -/* Driver for USB SCSI - include file - * - * (C) Michael Gee (michael@linuxspecific.com) 1999 - * - * This driver is schizoid - it makes a USB scanner appear as both a SCSI device - * and a character device. The latter is only available if the device has an - * interrupt endpoint, and is used specifically to receive interrupt events. - * - * In order to support various 'strange' scanners, this module supports plug-in - * device-specific filter modules, which can do their own thing when required. - * - */ - -#include - -#define USB_SCSI "usbscsi: " - -extern int usb_stor_debug; - -#ifdef CONFIG_USB_SCSI_DEBUG -void us_show_command(Scsi_Cmnd *srb); -#define US_DEBUGP(x...) { if(usb_stor_debug) printk( KERN_DEBUG USB_SCSI ## x ); } -#define US_DEBUGPX(x...) { if(usb_stor_debug) printk( ## x ); } -#define US_DEBUG(x) { if(usb_stor_debug) x; } -#else -#define US_DEBUGP(x...) -#define US_DEBUGPX(x...) -#define US_DEBUG(x) -#endif - -/* bit set if input */ -extern unsigned char us_direction[256/8]; -#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1) - -/* Sub Classes */ - -#define US_SC_RBC 1 /* Typically, flash devices */ -#define US_SC_8020 2 /* CD-ROM */ -#define US_SC_QIC 3 /* QIC-157 Tapes */ -#define US_SC_UFI 4 /* Floppy */ -#define US_SC_8070 5 /* Removable media */ -#define US_SC_SCSI 6 /* Transparent */ -#define US_SC_MIN US_SC_RBC -#define US_SC_MAX US_SC_SCSI - -/* Protocols */ - -#define US_PR_CB 1 /* Control/Bulk w/o interrupt */ -#define US_PR_CBI 0 /* Control/Bulk/Interrupt */ -#define US_PR_BULK 0x50 /* bulk only */ - -/* - * Bulk only data structures (Zip 100, for example) - */ - -struct bulk_cb_wrap { - __u32 Signature; /* contains 'USBC' */ - __u32 Tag; /* unique per command id */ - __u32 DataTransferLength; /* size of data */ - __u8 Flags; /* direction in bit 0 */ - __u8 Lun; /* LUN normally 0 */ - __u8 Length; /* of of the CDB */ - __u8 CDB[16]; /* max command */ -}; - -#define US_BULK_CB_WRAP_LEN 31 -#define US_BULK_CB_SIGN 0x43425355 -#define US_BULK_FLAG_IN 1 -#define US_BULK_FLAG_OUT 0 - -struct bulk_cs_wrap { - __u32 Signature; /* should = 'USBS' */ - __u32 Tag; /* same as original command */ - __u32 Residue; /* amount not transferred */ - __u8 Status; /* see below */ - __u8 Filler[18]; -}; - -#define US_BULK_CS_WRAP_LEN 31 -#define US_BULK_CS_SIGN 0x53425355 -#define US_BULK_STAT_OK 0 -#define US_BULK_STAT_FAIL 1 -#define US_BULK_STAT_PHASE 2 - -#define US_BULK_RESET 0xff -#define US_BULK_RESET_SOFT 1 -#define US_BULK_RESET_HARD 0 - -/* - * CBI style - */ - -#define US_CBI_ADSC 0 - -/* - * Filter device definitions - */ -struct usb_scsi_filter { - - struct usb_scsi_filter * next; /* usb_scsi driver only */ - char *name; /* not really required */ - - unsigned int flags; /* Filter flags */ - void * (* probe) (struct usb_device *, char *, char *, char *); /* probe device */ - void (* release)(void *); /* device gone */ - int (* command)(void *, Scsi_Cmnd *); /* all commands */ -}; - -#define GUID(x) __u32 x[3] -#define GUID_EQUAL(x, y) (x[0] == y[0] && x[1] == y[1] && x[2] == y[2]) -#define GUID_CLEAR(x) x[0] = x[1] = x[2] = 0; -#define GUID_NONE(x) (!x[0] && !x[1] && !x[2]) -#define GUID_FORMAT "%08x%08x%08x" -#define GUID_ARGS(x) x[0], x[1], x[2] - -static inline void make_guid( __u32 *pg, __u16 vendor, __u16 product, char *serial) -{ - pg[0] = (vendor << 16) | product; - pg[1] = pg[2] = 0; - while (*serial) { - pg[1] <<= 4; - pg[1] |= pg[2] >> 28; - pg[2] <<= 4; - if (*serial >= 'a') - *serial -= 'a' - 'A'; - pg[2] |= (*serial <= '9' && *serial >= '0') ? *serial - '0' - : *serial - 'A' + 10; - serial++; - } -} - -/* Flag definitions */ -#define US_FL_IP_STATUS 0x00000001 /* status uses interrupt */ -#define US_FL_FIXED_COMMAND 0x00000002 /* expand commands to fixed size */ - -/* - * Called by filters to register/unregister the mini driver - * - * WARNING - the supplied probe function may be called before exiting this fn - */ -int usb_scsi_register(struct usb_scsi_filter *); -void usb_scsi_deregister(struct usb_scsi_filter *); - -#ifdef CONFIG_USB_HP4100 -int hp4100_init(void); -#endif diff --git a/drivers/usb/usb_scsi_debug.c b/drivers/usb/usb_scsi_debug.c deleted file mode 100644 index d29622cad..000000000 --- a/drivers/usb/usb_scsi_debug.c +++ /dev/null @@ -1,102 +0,0 @@ - -/* Driver for USB scsi like devices - * - * (C) Michael Gee (michael@linuxspecific.com) 1999 - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "../scsi/scsi.h" -#include "../scsi/hosts.h" -#include "../scsi/sd.h" - -#include "usb.h" -#include "usb_scsi.h" - -void us_show_command(Scsi_Cmnd *srb) -{ - char *what = NULL; - - switch (srb->cmnd[0]) { - case TEST_UNIT_READY: what = "TEST_UNIT_READY"; break; - case REZERO_UNIT: what = "REZERO_UNIT"; break; - case REQUEST_SENSE: what = "REQUEST_SENSE"; break; - case FORMAT_UNIT: what = "FORMAT_UNIT"; break; - case READ_BLOCK_LIMITS: what = "READ_BLOCK_LIMITS"; break; - case REASSIGN_BLOCKS: what = "REASSIGN_BLOCKS"; break; - case READ_6: what = "READ_6"; break; - case WRITE_6: what = "WRITE_6"; break; - case SEEK_6: what = "SEEK_6"; break; - case READ_REVERSE: what = "READ_REVERSE"; break; - case WRITE_FILEMARKS: what = "WRITE_FILEMARKS"; break; - case SPACE: what = "SPACE"; break; - case INQUIRY: what = "INQUIRY"; break; - case RECOVER_BUFFERED_DATA: what = "RECOVER_BUFFERED_DATA"; break; - case MODE_SELECT: what = "MODE_SELECT"; break; - case RESERVE: what = "RESERVE"; break; - case RELEASE: what = "RELEASE"; break; - case COPY: what = "COPY"; break; - case ERASE: what = "ERASE"; break; - case MODE_SENSE: what = "MODE_SENSE"; break; - case START_STOP: what = "START_STOP"; break; - case RECEIVE_DIAGNOSTIC: what = "RECEIVE_DIAGNOSTIC"; break; - case SEND_DIAGNOSTIC: what = "SEND_DIAGNOSTIC"; break; - case ALLOW_MEDIUM_REMOVAL: what = "ALLOW_MEDIUM_REMOVAL"; break; - case SET_WINDOW: what = "SET_WINDOW"; break; - case READ_CAPACITY: what = "READ_CAPACITY"; break; - case READ_10: what = "READ_10"; break; - case WRITE_10: what = "WRITE_10"; break; - case SEEK_10: what = "SEEK_10"; break; - case WRITE_VERIFY: what = "WRITE_VERIFY"; break; - case VERIFY: what = "VERIFY"; break; - case SEARCH_HIGH: what = "SEARCH_HIGH"; break; - case SEARCH_EQUAL: what = "SEARCH_EQUAL"; break; - case SEARCH_LOW: what = "SEARCH_LOW"; break; - case SET_LIMITS: what = "SET_LIMITS"; break; - case READ_POSITION: what = "READ_POSITION"; break; - case SYNCHRONIZE_CACHE: what = "SYNCHRONIZE_CACHE"; break; - case LOCK_UNLOCK_CACHE: what = "LOCK_UNLOCK_CACHE"; break; - case READ_DEFECT_DATA: what = "READ_DEFECT_DATA"; break; - case MEDIUM_SCAN: what = "MEDIUM_SCAN"; break; - case COMPARE: what = "COMPARE"; break; - case COPY_VERIFY: what = "COPY_VERIFY"; break; - case WRITE_BUFFER: what = "WRITE_BUFFER"; break; - case READ_BUFFER: what = "READ_BUFFER"; break; - case UPDATE_BLOCK: what = "UPDATE_BLOCK"; break; - case READ_LONG: what = "READ_LONG"; break; - case WRITE_LONG: what = "WRITE_LONG"; break; - case CHANGE_DEFINITION: what = "CHANGE_DEFINITION"; break; - case WRITE_SAME: what = "WRITE_SAME"; break; - case READ_TOC: what = "READ_TOC"; break; - case LOG_SELECT: what = "LOG_SELECT"; break; - case LOG_SENSE: what = "LOG_SENSE"; break; - case MODE_SELECT_10: what = "MODE_SELECT_10"; break; - case MODE_SENSE_10: what = "MODE_SENSE_10"; break; - case MOVE_MEDIUM: what = "MOVE_MEDIUM"; break; - case READ_12: what = "READ_12"; break; - case WRITE_12: what = "WRITE_12"; break; - case WRITE_VERIFY_12: what = "WRITE_VERIFY_12"; break; - case SEARCH_HIGH_12: what = "SEARCH_HIGH_12"; break; - case SEARCH_EQUAL_12: what = "SEARCH_EQUAL_12"; break; - case SEARCH_LOW_12: what = "SEARCH_LOW_12"; break; - case READ_ELEMENT_STATUS: what = "READ_ELEMENT_STATUS"; break; - case SEND_VOLUME_TAG: what = "SEND_VOLUME_TAG"; break; - case WRITE_LONG_2: what = "WRITE_LONG_2"; break; - default: break; - } - printk(KERN_DEBUG USB_SCSI "Command %s (%d bytes)\n", what, srb->cmd_len); - printk(KERN_DEBUG USB_SCSI " %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - srb->cmnd[0], srb->cmnd[1], srb->cmnd[2], srb->cmnd[3], srb->cmnd[4], srb->cmnd[5], - srb->cmnd[6], srb->cmnd[7], srb->cmnd[8], srb->cmnd[9]); -} diff --git a/drivers/usb/usb_storage.c b/drivers/usb/usb_storage.c new file mode 100644 index 000000000..0ebb1e413 --- /dev/null +++ b/drivers/usb/usb_storage.c @@ -0,0 +1,1837 @@ +/* Driver for USB Mass Storage compliant devices + * + * (c) 1999 Michael Gee (michael@linuxspecific.com) + * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) + * + * Further reference: + * This driver is based on the 'USB Mass Storage Class' document. This + * describes in detail the protocol used to communicate with such + * devices. Clearly, the designers had SCSI commands in mind when they + * created this document. The commands are all similar to commands + * in the SCSI-II specification. + * + * It is important to note that in a number of cases this class exhibits + * class-specific exemptions from the USB specification. Notably the + * usage of NAK, STALL and ACK differs from the norm, in that they are + * used to communicate wait, failed and OK on commands. + * Also, for certain devices, the interrupt endpoint is used to convey + * status of a command. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "../scsi/scsi.h" +#include "../scsi/hosts.h" +#include "../scsi/sd.h" + +#include "usb.h" +#include "usb_storage.h" + +/* direction table -- this indicates the direction of the data + * transfer for each command code -- a 1 indicates input + */ +unsigned char us_direction[256/8] = { + 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77, + 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/* + * Per device data + */ + +static int my_host_number; + +int usb_stor_debug = 1; + +struct us_data; + +typedef int (*trans_cmnd)(Scsi_Cmnd*, struct us_data*); +typedef int (*trans_reset)(struct us_data*); +typedef void (*proto_cmnd)(Scsi_Cmnd*, struct us_data*); + +struct us_data { + struct us_data *next; /* next device */ + struct usb_device *pusb_dev; /* this usb_device */ + unsigned int flags; /* from filter initially */ + __u8 ifnum; /* interface number */ + __u8 ep_in; /* in endpoint */ + __u8 ep_out; /* out ....... */ + __u8 ep_int; /* interrupt . */ + __u8 subclass; /* as in overview */ + __u8 protocol; /* .............. */ + __u8 attention_done; /* force attn on first cmd */ + trans_cmnd transport; /* protocol specific do cmd */ + trans_reset transport_reset; /* .......... device reset */ + proto_cmnd proto_handler; /* protocol handler */ + GUID(guid); /* unique dev id */ + struct Scsi_Host *host; /* our dummy host data */ + Scsi_Host_Template *htmplt; /* own host template */ + int host_number; /* to find us */ + int host_no; /* allocated by scsi */ + Scsi_Cmnd *srb; /* current srb */ + int action; /* what to do */ + wait_queue_head_t waitq; /* thread waits */ + wait_queue_head_t ip_waitq; /* for CBI interrupts */ + __u16 ip_data; /* interrupt data */ + int ip_wanted; /* needed */ + int pid; /* control thread */ + struct semaphore *notify; /* wait for thread to begin */ + void *irq_handle; /* for USB int requests */ + unsigned int irqpipe; /* pipe for release_irq */ +}; + +/* + * kernel thread actions + */ + +#define US_ACT_COMMAND 1 +#define US_ACT_ABORT 2 +#define US_ACT_DEVICE_RESET 3 +#define US_ACT_BUS_RESET 4 +#define US_ACT_HOST_RESET 5 + +static struct us_data *us_list; + +static void * storage_probe(struct usb_device *dev, unsigned int ifnum); +static void storage_disconnect(struct usb_device *dev, void *ptr); +static struct usb_driver storage_driver = { + "usb-storage", + storage_probe, + storage_disconnect, + { NULL, NULL } +}; + +/*********************************************************************** + * Data transfer routines + ***********************************************************************/ + +/* Transfer one buffer (breaking into packets if necessary) + * Note that this function is necessary because if the device NAKs, we + * need to know that information directly + * + * FIXME: is the above true? Or will the URB status show ETIMEDOUT after + * retrying several times allready? Perhaps this is the way we should + * be going anyway? + */ +static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length) +{ + int max_size; + int this_xfer; + int result; + int partial; + int maxtry; + + /* determine the maximum packet size for these transfers */ + max_size = usb_maxpacket(us->pusb_dev, + pipe, usb_pipeout(pipe)) * 16; + + /* while we have data left to transfer */ + while (length) { + + /* calculate how long this will be -- maximum or a remainder */ + this_xfer = length > max_size ? max_size : length; + length -= this_xfer; + + /* FIXME: this number is totally outrageous. We need to pick + * a better (smaller) number). + */ + + /* setup the retry counter */ + maxtry = 100; + + /* set up the transfer loop */ + do { + /* transfer the data */ + US_DEBUGP("Bulk xfer 0x%x(%d) try #%d\n", + (unsigned int)buf, this_xfer, 101 - maxtry); + result = usb_bulk_msg(us->pusb_dev, pipe, buf, + this_xfer, &partial, HZ*5); + US_DEBUGP("bulk_msg returned %d xferred %d/%d\n", + result, partial, this_xfer); + + /* if we stall, we need to clear it before we go on */ + if (result == -EPIPE) { + US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); + usb_clear_halt(us->pusb_dev, pipe); + } + + /* update to show what data was transferred */ + this_xfer -= partial; + buf += partial; + + /* NAK - we retry a few times */ + if (result == -ETIMEDOUT) { + + US_DEBUGP("us_one_transfer: device NAKed\n"); + + /* if our try counter reaches 0, bail out */ + if (!maxtry--) + return -ETIMEDOUT; + + /* just continue the while loop */ + continue; + } + + /* other errors (besides NAK) -- we just bail out*/ + if (result != 0) { + US_DEBUGP("us_one_transfer: device returned error %d\n", result); + return result; + } + + /* continue until this transfer is done */ + } while ( this_xfer ); + } + + /* if we get here, we're done and successful */ + return 0; +} + +static unsigned int us_transfer_length(Scsi_Cmnd *srb); + +/* transfer one SCSI command, using scatter-gather if requested */ +/* FIXME: what do the return codes here mean? */ +static int us_transfer(Scsi_Cmnd *srb, int dir_in) +{ + struct us_data *us = (struct us_data *)srb->host_scribble; + int i; + int result = -1; + unsigned int pipe = dir_in ? usb_rcvbulkpipe(us->pusb_dev, us->ep_in) : + usb_sndbulkpipe(us->pusb_dev, us->ep_out); + + /* FIXME: stop transferring data at us_transfer_length(), not + * bufflen */ + if (srb->use_sg) { + struct scatterlist *sg = (struct scatterlist *) srb->request_buffer; + + for (i = 0; i < srb->use_sg; i++) { + result = us_one_transfer(us, pipe, sg[i].address, sg[i].length); + if (result) + break; + } + } + else + result = us_one_transfer(us, pipe, srb->request_buffer, + us_transfer_length(srb)); + + if (result < 0) + US_DEBUGP("us_transfer returning error %d\n", result); + return result; +} + +/* calculate the length of the data transfer (not the command) for any + * given SCSI command + */ +static unsigned int us_transfer_length(Scsi_Cmnd *srb) +{ + int i; + unsigned int total = 0; + + /* always zero for some commands */ + switch (srb->cmnd[0]) { + case SEEK_6: + case SEEK_10: + case REZERO_UNIT: + case ALLOW_MEDIUM_REMOVAL: + case START_STOP: + case TEST_UNIT_READY: + return 0; + + case REQUEST_SENSE: + case INQUIRY: + case MODE_SENSE: + return srb->cmnd[4]; + + case LOG_SENSE: + case MODE_SENSE_10: + return (srb->cmnd[7] << 8) + srb->cmnd[8]; + + default: + break; + } + + if (srb->use_sg) { + struct scatterlist *sg = (struct scatterlist *) srb->request_buffer; + + for (i = 0; i < srb->use_sg; i++) { + total += sg[i].length; + } + return total; + } + else + return srb->request_bufflen; +} + +/*********************************************************************** + * Protocol routines + ***********************************************************************/ + +static int CB_transport(Scsi_Cmnd *srb, struct us_data *us); +static int Bulk_transport(Scsi_Cmnd *srb, struct us_data *us); + +static void ufi_command(Scsi_Cmnd *srb, struct us_data *us) +{ + int old_cmnd = 0; + + /* fix some commands -- this is a form of mode translation + * UFI devices only accept 12 byte long commands + * + * NOTE: This only works because a Scsi_Cmnd struct field contains + * a unsigned char cmnd[12], so we know we have storage available + */ + + /* set command length to 12 bytes (this affects the transport layer) */ + srb->cmd_len = 12; + + /* determine the correct (or minimum) data length for these commands */ + switch (us->srb->cmnd[0]) { + + /* for INQUIRY, UFI devices only ever return 36 bytes */ + case INQUIRY: + us->srb->cmnd[4] = 36; + break; + + /* change MODE_SENSE/MODE_SELECT from 6 to 10 byte commands */ + case MODE_SENSE: + case MODE_SELECT: + /* save the command so we can tell what it was */ + old_cmnd = srb->cmnd[0]; + + srb->cmnd[11] = 0; + srb->cmnd[10] = 0; + srb->cmnd[9] = 0; + + /* if we're sending data, we send all. If getting data, + * get the minimum */ + if (srb->cmnd[0] == MODE_SELECT) + srb->cmnd[8] = srb->cmnd[4]; + else + srb->cmnd[8] = 8; + + srb->cmnd[7] = 0; + srb->cmnd[6] = 0; + srb->cmnd[5] = 0; + srb->cmnd[4] = 0; + srb->cmnd[3] = 0; + srb->cmnd[2] = srb->cmnd[2]; + srb->cmnd[1] = srb->cmnd[1]; + srb->cmnd[0] = srb->cmnd[0] | 0x40; + break; + + /* again, for MODE_SENSE_10, we get the minimum (8) */ + case MODE_SENSE_10: + us->srb->cmnd[7] = 0; + us->srb->cmnd[8] = 8; + break; + + /* for REQUEST_SENSE, UFI devices only ever return 18 bytes */ + case REQUEST_SENSE: + us->srb->cmnd[4] = 18; + break; + + /* change READ_6/WRITE_6 to READ_10/WRITE_10, which + * are UFI commands */ + case WRITE_6: + case READ_6: + srb->cmnd[11] = 0; + srb->cmnd[10] = 0; + srb->cmnd[9] = 0; + srb->cmnd[8] = srb->cmnd[4]; + srb->cmnd[7] = 0; + srb->cmnd[6] = 0; + srb->cmnd[5] = srb->cmnd[3]; + srb->cmnd[4] = srb->cmnd[2]; + srb->cmnd[3] = srb->cmnd[1] & 0x1F; + srb->cmnd[2] = 0; + srb->cmnd[1] = srb->cmnd[1] & 0xE0; + srb->cmnd[0] = srb->cmnd[0] | 0x20; + break; + } /* end switch on cmnd[0] */ + + /* send the command to the transport layer */ + us->srb->result = us->transport(srb, us); + + /* if we have an error, we're going to do a + * REQUEST_SENSE automatically */ + + /* FIXME: we should only do this for device + * errors, not system errors */ + if (us->srb->result) { + int temp_result; + int count; + void* old_request_buffer; + + US_DEBUGP("Command FAILED: Issuing auto-REQUEST_SENSE\n"); + + /* set the result so the higher layers expect this data */ + us->srb->result = CHECK_CONDITION; + + us->srb->cmnd[0] = REQUEST_SENSE; + us->srb->cmnd[1] = 0; + us->srb->cmnd[2] = 0; + us->srb->cmnd[3] = 0; + us->srb->cmnd[4] = 18; + us->srb->cmnd[5] = 0; + + /* set the buffer length for transfer */ + old_request_buffer = us->srb->request_buffer; + us->srb->request_bufflen = 18; + us->srb->request_buffer = kmalloc(18, GFP_KERNEL); + + /* FIXME: what if this command fails? */ + temp_result = us->transport(us->srb, us); + US_DEBUGP("-- Result from auto-sense is %d\n", temp_result); + + /* copy the data from the request buffer to the sense buffer */ + for(count = 0; count < 18; count++) + us->srb->sense_buffer[count] = + ((unsigned char *)(us->srb->request_buffer))[count]; + + US_DEBUGP("-- sense key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n", + us->srb->sense_buffer[2] & 0xf, + us->srb->sense_buffer[12], us->srb->sense_buffer[13]); + + /* we're done here */ + kfree(us->srb->request_buffer); + us->srb->request_buffer = old_request_buffer; + return; + } + + /* FIXME: if we need to send more data, or recieve data, we should + * do it here. Then, we can do status handling here also. + * + * This includes MODE_SENSE from above + */ + if (old_cmnd == MODE_SENSE) { + unsigned char *dta = (unsigned char *)us->srb->request_buffer; + + /* calculate the new length */ + int length = (dta[0] << 8) + dta[1] + 2; + + /* copy the available data length into the structure */ + us->srb->cmnd[7] = length >> 8; + us->srb->cmnd[8] = length & 0xFF; + + /* send the command to the transport layer */ + us->srb->result = us->transport(srb, us); + + /* FIXME: this assumes that the 2nd attempt is always + * successful convert MODE_SENSE_10 return data format + * to MODE_SENSE_6 format */ + dta[0] = dta[1]; /* data len */ + dta[1] = dta[2]; /* med type */ + dta[2] = dta[3]; /* dev-spec prm */ + dta[3] = dta[7]; /* block desc len */ + printk (KERN_DEBUG USB_STORAGE + "new MODE_SENSE_6 data = %.2X %.2X %.2X %.2X\n", + dta[0], dta[1], dta[2], dta[3]); + } + + /* FIXME: if this was a TEST_UNIT_READY, and we get a NOT READY/ + * LOGICAL DRIVE NOT READY then we do a START_STOP, and retry + */ + + /* FIXME: here is where we need to fix-up the return data from + * an INQUIRY command to show ANSI SCSI rev 2 + */ + + /* FIXME: The rest of this is bogus. usb_control_msg() will only + * return an error if we've really honked things up. If it just + * needs a START_STOP, then we'll get some data back via + * REQUEST_SENSE -- either way, this belongs at a higher level + */ + +#if 0 + /* For UFI, if this is the first time we've sent this TEST_UNIT_READY + * command, we can try again + */ + if (!done_start && (us->subclass == US_SC_UFI) + && (cmd[0] == TEST_UNIT_READY) && (result < 0)) { + + /* as per spec try a start command, wait and retry */ + wait_ms(100); + + done_start++; + memset(cmd, 0, sizeof(cmd)); + cmd[0] = START_STOP; + cmd[4] = 1; /* start */ + + result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0), + US_CBI_ADSC, + USB_TYPE_CLASS | USB_RECIP_INTERFACE, + 0, us->ifnum, + cmd, 12, HZ*5); + US_DEBUGP("Next usb_control_msg returns %d\n", result); + + /* allow another retry */ + retry++; + continue; + } +#endif +} + +static void transparent_scsi_command(Scsi_Cmnd *srb, struct us_data *us) +{ + unsigned int savelen = us->srb->request_bufflen; + unsigned int saveallocation = 0; + +#if 0 + /* force attention on first command */ + if (!us->attention_done) { + if (us->srb->cmnd[0] == REQUEST_SENSE) { + US_DEBUGP("forcing unit attention\n"); + us->attention_done = 1; + + if (us->srb->result == USB_STOR_TRANSPORT_GOOD) { + unsigned char *p = (unsigned char *)us->srb->request_buffer; + + if ((p[2] & 0x0f) != UNIT_ATTENTION) { + p[2] = UNIT_ATTENTION; + p[12] = 0x29; /* power on, reset or bus-reset */ + p[13] = 0; + } /* if ((p[2] & 0x0f) != UNIT_ATTENTION) */ + } /* if (us->srb->result == USB_STORE_TRANSPORT_GOOD) */ + } + } /* if (!us->attention_done) */ +#endif + + /* If the command has a variable-length payload, then we do them + * in two steps -- first we do the minimum, then we recalculate + * then length, and re-issue the command + * + * we use savelen to remember how much buffer we really have + * we use savealloction to remember how much was really requested + */ + + /* FIXME: remove savelen based on mods to us_transfer_length() */ + switch (us->srb->cmnd[0]) { + case REQUEST_SENSE: + if (us->srb->request_bufflen > 18) + us->srb->request_bufflen = 18; + else + break; + saveallocation = us->srb->cmnd[4]; + us->srb->cmnd[4] = 18; + break; + + case INQUIRY: + if (us->srb->request_bufflen > 36) + us->srb->request_bufflen = 36; + else + break; + saveallocation = us->srb->cmnd[4]; + us->srb->cmnd[4] = 36; + break; + + case MODE_SENSE: + if (us->srb->request_bufflen > 4) + us->srb->request_bufflen = 4; + else + break; + saveallocation = us->srb->cmnd[4]; + us->srb->cmnd[4] = 4; + break; + + case LOG_SENSE: + case MODE_SENSE_10: + if (us->srb->request_bufflen > 8) + us->srb->request_bufflen = 8; + else + break; + saveallocation = (us->srb->cmnd[7] << 8) | us->srb->cmnd[8]; + us->srb->cmnd[7] = 0; + us->srb->cmnd[8] = 8; + break; + + default: + break; + } /* end switch on cmnd[0] */ + + /* This code supports devices which do not support {READ|WRITE}_6 + * Apparently, neither Windows or MacOS will use these commands, + * so some devices do not support them + */ + if (us->flags & US_FL_MODE_XLATE) { + + /* translate READ_6 to READ_10 */ + if (us->srb->cmnd[0] == 0x08) { + + /* get the control */ + us->srb->cmnd[9] = us->srb->cmnd[5]; + + /* get the length */ + us->srb->cmnd[8] = us->srb->cmnd[6]; + us->srb->cmnd[7] = 0; + + /* set the reserved area to 0 */ + us->srb->cmnd[6] = 0; + + /* get LBA */ + us->srb->cmnd[5] = us->srb->cmnd[3]; + us->srb->cmnd[4] = us->srb->cmnd[2]; + us->srb->cmnd[3] = 0; + us->srb->cmnd[2] = 0; + + /* LUN and other info in cmnd[1] can stay */ + + /* fix command code */ + us->srb->cmnd[0] = 0x28; + + US_DEBUGP("Changing READ_6 to READ_10\n"); + US_DEBUG(us_show_command(us->srb)); + } + + /* translate WRITE_6 to WRITE_10 */ + if (us->srb->cmnd[0] == 0x0A) { + + /* get the control */ + us->srb->cmnd[9] = us->srb->cmnd[5]; + + /* get the length */ + us->srb->cmnd[8] = us->srb->cmnd[4]; + us->srb->cmnd[7] = 0; + + /* set the reserved area to 0 */ + us->srb->cmnd[6] = 0; + + /* get LBA */ + us->srb->cmnd[5] = us->srb->cmnd[3]; + us->srb->cmnd[4] = us->srb->cmnd[2]; + us->srb->cmnd[3] = 0; + us->srb->cmnd[2] = 0; + + /* LUN and other info in cmnd[1] can stay */ + + /* fix command code */ + us->srb->cmnd[0] = 0x2A; + + US_DEBUGP("Changing WRITE_6 to WRITE_10\n"); + US_DEBUG(us_show_command(us->srb)); + } + } /* end if (us->flags & US_FL_MODE_XLATE) */ + + /* send the command to the transport layer */ + us->srb->result = us->transport(us->srb, us); + + /* if we have an error, we're going to do a REQUEST_SENSE + * automatically */ + /* FIXME: we should only do this for device errors, not + * system errors */ + if (us->srb->result) { + int temp_result; + int count; + void* old_request_buffer; + + US_DEBUGP("Command FAILED: Issuing auto-REQUEST_SENSE\n"); + + /* set the result so the higher layers expect this data */ + us->srb->result = CHECK_CONDITION; + + us->srb->cmnd[0] = REQUEST_SENSE; + us->srb->cmnd[1] = 0; + us->srb->cmnd[2] = 0; + us->srb->cmnd[3] = 0; + us->srb->cmnd[4] = 18; + us->srb->cmnd[5] = 0; + + /* set the buffer length for transfer */ + old_request_buffer = us->srb->request_buffer; + us->srb->request_bufflen = 18; + us->srb->request_buffer = kmalloc(18, GFP_KERNEL); + + /* FIXME: what if this command fails? */ + temp_result = us->transport(us->srb, us); + US_DEBUGP("-- Result from auto-sense is %d\n", temp_result); + + /* copy the data from the request buffer to the sense buffer */ + for(count = 0; count < 18; count++) + us->srb->sense_buffer[count] = + ((unsigned char *)(us->srb->request_buffer))[count]; + + US_DEBUGP("-- sense key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n", + us->srb->sense_buffer[2] & 0xf, + us->srb->sense_buffer[12], us->srb->sense_buffer[13]); + + /* we're done here */ + kfree(us->srb->request_buffer); + us->srb->request_buffer = old_request_buffer; + return; + } + + if (savelen != us->srb->request_bufflen) { + unsigned char *p = (unsigned char *)us->srb->request_buffer; + unsigned int length = 0; + + /* set correct length and retry */ + switch (us->srb->cmnd[0]) { + + /* FIXME: we should try to get all the sense data */ + case REQUEST_SENSE: + /* simply return 18 bytes */ + p[7] = 10; + length = us->srb->request_bufflen; + break; + + case INQUIRY: + length = p[4] + 5 > savelen ? savelen : p[4] + 5; + us->srb->cmnd[4] = length; + break; + + case MODE_SENSE: + US_DEBUGP("MODE_SENSE Mode data length is %d\n", p[0]); + length = p[0] + 1 > savelen ? savelen : p[0] + 1; + us->srb->cmnd[4] = length; + break; + + case LOG_SENSE: + length = ((p[2] << 8) + p[3]) + 4 > savelen ? savelen : ((p[2] << 8) + p[3]) + 4; + us->srb->cmnd[7] = length >> 8; + us->srb->cmnd[8] = length; + break; + + case MODE_SENSE_10: + US_DEBUGP("MODE_SENSE_10 Mode data length is %d\n", + (p[0] << 8) + p[1]); + length = ((p[0] << 8) + p[1]) + 6 > savelen ? savelen : ((p[0] << 8) + p[1]) + 6; + us->srb->cmnd[7] = length >> 8; + us->srb->cmnd[8] = length; + break; + } /* end switch on cmnd[0] */ + + US_DEBUGP("Old/New length = %d/%d\n", + savelen, length); + + /* issue the new command */ + /* FIXME: this assumes that the second attempt is + * always successful */ + if (us->srb->request_bufflen != length) { + US_DEBUGP("redoing cmd with len=%d\n", length); + us->srb->request_bufflen = length; + us->srb->result = us->transport(us->srb, us); + } + + /* reset back to original values */ + us->srb->request_bufflen = savelen; + + /* fix data as necessary */ + switch (us->srb->cmnd[0]) { + case INQUIRY: + if ((((unsigned char*)us->srb->request_buffer)[2] & 0x7) == 0) { + US_DEBUGP("Fixing INQUIRY data, setting SCSI rev to 2\n"); + ((unsigned char*)us->srb->request_buffer)[2] |= 2; + } + /* FALL THROUGH */ + case REQUEST_SENSE: + case MODE_SENSE: + if (us->srb->use_sg == 0 && length > 0) { + int i; + printk(KERN_DEBUG "Data is"); + for (i = 0; i < 32 && i < length; ++i) + printk(" %.2x", ((unsigned char *)us->srb->request_buffer)[i]); + if (i < length) + printk(" ..."); + printk("\n"); + } + + /* FIXME: is this really necessary? */ + us->srb->cmnd[4] = saveallocation; + break; + + case LOG_SENSE: + case MODE_SENSE_10: + /* FIXME: is this really necessary? */ + us->srb->cmnd[7] = saveallocation >> 8; + us->srb->cmnd[8] = saveallocation; + break; + } /* end switch on cmnd[0] */ + } /* if good command */ +} + +/*********************************************************************** + * Transport routines + ***********************************************************************/ + +static int CBI_irq(int state, void *buffer, int len, void *dev_id) +{ + struct us_data *us = (struct us_data *)dev_id; + + US_DEBUGP("USB IRQ recieved for device on host %d\n", us->host_no); + + /* save the data for interpretation later */ + if (state != USB_ST_REMOVED) { + us->ip_data = le16_to_cpup((__u16 *)buffer); + US_DEBUGP("Interrupt Status 0x%x\n", us->ip_data); + } + + /* was this a wanted interrupt? */ + if (us->ip_wanted) { + us->ip_wanted = 0; + wake_up(&us->ip_waitq); + } else { + US_DEBUGP("ERROR: Unwanted interrupt received!\n"); + } + + /* This return code is truly meaningless -- and I mean truly. It gets + * ignored by other layers. It used to indicate if we wanted to get + * another interrupt or disable the interrupt callback + */ + return 0; +} + +/* FIXME: this reset function doesn't really reset the port, and it + * should. Actually it should probably do what it's doing here, and + * reset the port physically + */ +static int CB_reset(struct us_data *us) +{ + unsigned char cmd[12]; + int result; + + US_DEBUGP("CB_reset\n"); + + memset(cmd, 0xFF, sizeof(cmd)); + 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_RECIP_INTERFACE, + 0, us->ifnum, cmd, sizeof(cmd), HZ*5); + + /* long wait for reset */ + schedule_timeout(HZ*6); + + US_DEBUGP("CB_reset: clearing endpoint halt\n"); + usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in)); + usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out)); + + US_DEBUGP("CB_reset done\n"); + return 0; +} + +static int pop_CB_status(Scsi_Cmnd *srb); + +/* FIXME: we also need a CBI_command which sets up the completion + * interrupt, and waits for it + */ +static int CB_transport(Scsi_Cmnd *srb, struct us_data *us) +{ + int result; + + US_DEBUGP("CBI gets a command:\n"); + US_DEBUG(us_show_command(srb)); + + /* FIXME: we aren't setting the ip_wanted indicator early enough, which + * causes some commands to never complete. This hangs the driver. + */ + + /* let's send the command via the control pipe */ + result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0), + US_CBI_ADSC, USB_TYPE_CLASS | USB_RECIP_INTERFACE, + 0, us->ifnum, + srb->cmnd, srb->cmd_len, HZ*5); + + /* check the return code for the command */ + if (result < 0) { + US_DEBUGP("Call to usb_control_msg() returned %d\n", result); + + /* a stall is a fatal condition from the device */ + if (result == -EPIPE) { + US_DEBUGP("-- Stall on control pipe detected. Clearing\n"); + + US_DEBUGP("-- Return from usb_clear_halt() is %d\n", + usb_clear_halt(us->pusb_dev, + usb_sndctrlpipe(us->pusb_dev, 0))); + return USB_STOR_TRANSPORT_ERROR; + } + + /* FIXME: we need to handle NAKs here */ + return USB_STOR_TRANSPORT_ERROR; + } + + /* transfer the data payload for this command, if one exists*/ + if (us_transfer_length(srb)) { + result = us_transfer(srb, US_DIRECTION(srb->cmnd[0])); + US_DEBUGP("CBI attempted to transfer data, result is 0x%x\n", result); + + /* FIXME: what do the return codes from us_transfer mean? */ + if ((result < 0) && + (result != USB_ST_DATAUNDERRUN) && + (result != USB_ST_STALL)) { + return DID_ERROR << 16; + } + } /* if (us_transfer_length(srb)) */ + + /* get status and return it */ + return pop_CB_status(srb); +} + +/* + * Control/Bulk status handler + */ + +static int pop_CB_status(Scsi_Cmnd *srb) +{ + struct us_data *us = (struct us_data *)srb->host_scribble; + int result; + __u8 status[2]; + int retry = 5; + + US_DEBUGP("pop_CB_status, proto=0x%x\n", us->protocol); + switch (us->protocol) { + case US_PR_CB: + /* get from control */ + + 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_RECIP_DEVICE, + 0, us->ifnum, status, sizeof(status), HZ*5); + if (result != USB_ST_TIMEOUT) + break; + } + if (result) { + US_DEBUGP("Bad AP status request %d\n", result); + return DID_ABORT << 16; + } + US_DEBUGP("Got AP status 0x%x 0x%x\n", status[0], status[1]); + if (srb->cmnd[0] != REQUEST_SENSE && srb->cmnd[0] != INQUIRY && + ( (status[0] & ~3) || status[1])) + return (DID_OK << 16) | 2; + else + return USB_STOR_TRANSPORT_GOOD; + break; + + /* FIXME: this should be in a separate function */ + case US_PR_CBI: + /* get from interrupt pipe */ + + /* add interrupt transfer, marked for removal */ + us->ip_wanted = 1; + + /* go to sleep until we get this interrup */ + /* FIXME: this should be changed to use a timeout */ + sleep_on(&us->ip_waitq); + + if (us->ip_wanted) { + US_DEBUGP("Did not get interrupt on CBI\n"); + us->ip_wanted = 0; + return USB_STOR_TRANSPORT_ERROR; + } + + US_DEBUGP("Got interrupt data 0x%x\n", us->ip_data); + + /* UFI gives us ASC and ASCQ, like a request sense */ + /* FIXME: is this right? do REQUEST_SENSE and INQUIRY need special + * case handling? + */ + if (us->subclass == US_SC_UFI) { + if (srb->cmnd[0] == REQUEST_SENSE || + srb->cmnd[0] == INQUIRY) + return USB_STOR_TRANSPORT_GOOD; + else + if (us->ip_data) + return USB_STOR_TRANSPORT_FAILED; + else + return USB_STOR_TRANSPORT_GOOD; + } + + /* otherwise, we interpret the data normally */ + switch (us->ip_data) { + case 0x0001: + return USB_STOR_TRANSPORT_GOOD; + case 0x0002: + return USB_STOR_TRANSPORT_FAILED; + default: + return USB_STOR_TRANSPORT_ERROR; + } + } + US_DEBUGP("pop_CB_status, reached end of function\n"); + return USB_STOR_TRANSPORT_ERROR; +} + +static int 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_RECIP_INTERFACE, + US_BULK_RESET_HARD, us->ifnum, + NULL, 0, HZ*5); + if (result) + US_DEBUGP("Bulk hard reset failed %d\n", result); + usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in)); + usb_clear_halt(us->pusb_dev, usb_sndbulkpipe(us->pusb_dev, us->ep_out)); + + /* long wait for reset */ + schedule_timeout(HZ*6); + + return result; +} + +/* + * The bulk only protocol handler. + * Uses the in and out endpoints to transfer commands and data + */ +static int Bulk_transport(Scsi_Cmnd *srb, struct us_data *us) +{ + struct bulk_cb_wrap bcb; + struct bulk_cs_wrap bcs; + int result; + int pipe; + int partial; + + /* set up the command wrapper */ + bcb.Signature = US_BULK_CB_SIGN; + bcb.DataTransferLength = us_transfer_length(srb); + bcb.Flags = US_DIRECTION(srb->cmnd[0]) << 7; + bcb.Tag = srb->serial_number; + bcb.Lun = 0; + bcb.Length = srb->cmd_len; + + /* construct the pipe handle */ + pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out); + + /* copy the command payload */ + memset(bcb.CDB, 0, sizeof(bcb.CDB)); + memcpy(bcb.CDB, srb->cmnd, bcb.Length); + + /* send it to out endpoint */ + US_DEBUGP("Bulk command S 0x%x T 0x%x L %d F %d CL %d\n", + bcb.Signature, bcb.Tag, bcb.DataTransferLength, + bcb.Flags, bcb.Length); + result = usb_bulk_msg(us->pusb_dev, pipe, &bcb, + US_BULK_CB_WRAP_LEN, &partial, HZ*5); + US_DEBUGP("Bulk command transfer result 0x%x\n", result); + + /* if we stall, we need to clear it before we go on */ + if (result == -EPIPE) { + US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); + usb_clear_halt(us->pusb_dev, pipe); + } + + /* if the command transfered well, then we go to the data stage */ + /* FIXME: Regardless of the status of the data stage, we go on to the + * status stage. Note that this implies that if a command is + * partially successful, we rely on the device reporting an error + * the CSW. The spec says that the device may just decide to short us. + */ + if (result == 0) { + /* send/receive data payload, if there is any */ + if (bcb.DataTransferLength) { + result = us_transfer(srb, bcb.Flags); + US_DEBUGP("Bulk data transfer result 0x%x\n", result); +#if 0 + if ((result < 0) && (result != USB_ST_DATAUNDERRUN) + && (result != USB_ST_STALL)) { + US_DEBUGP("Bulk data transfer result 0x%x\n", result); + return DID_ABORT << 16; + } +#endif + } + } + + /* See flow chart on pg 15 of the Bulk Only Transport spec for + * an explanation of how this code works. + */ + + /* construct the pipe handle */ + pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in); + + /* get CSW for device status */ + result = usb_bulk_msg(us->pusb_dev, pipe, &bcs, + US_BULK_CS_WRAP_LEN, &partial, HZ*5); + + /* did the attempt to read the CSW fail? */ + if (result == -EPIPE) { + US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); + usb_clear_halt(us->pusb_dev, pipe); + + /* get the status again */ + result = usb_bulk_msg(us->pusb_dev, pipe, &bcs, + US_BULK_CS_WRAP_LEN, &partial, HZ*5); + + /* if it fails again, we need a reset and return an error*/ + if (result == -EPIPE) { + Bulk_reset(us); + return (DID_ABORT << 16); + } + } + + /* if we still have a failure at this point, we're in trouble */ + if (result) { + US_DEBUGP("Bulk status result = 0x%x\n", result); + return DID_ABORT << 16; + } + + /* check bulk status */ + US_DEBUGP("Bulk status S 0x%x T 0x%x R %d V 0x%x\n", + bcs.Signature, bcs.Tag, bcs.Residue, bcs.Status); + if (bcs.Signature != US_BULK_CS_SIGN || bcs.Tag != bcb.Tag || + bcs.Status > US_BULK_STAT_PHASE || partial != 13) { + US_DEBUGP("Bulk logical error\n"); + return DID_ABORT << 16; + } + + /* based on the status code, we report good or bad */ + switch (bcs.Status) { + case US_BULK_STAT_OK: + /* if there is residue, we really didn't finish the command */ + if (bcs.Residue) + return DID_ERROR << 16; + else + return DID_OK << 16; + + case US_BULK_STAT_FAIL: + return DID_ERROR << 16; + + case US_BULK_STAT_PHASE: + Bulk_reset(us); + return DID_ERROR << 16; + } + + return DID_OK << 16; /* check sense required */ +} + +/*********************************************************************** + * Host functions + ***********************************************************************/ + +/* detect adapter (always true ) */ +static int us_detect(struct SHT *sht) +{ + /* FIXME - not nice at all, but how else ? */ + struct us_data *us = (struct us_data *)sht->proc_dir; + char name[32]; + + /* set up our name */ + sprintf(name, "usbscsi%d", us->host_number); + sht->name = sht->proc_name = kmalloc(strlen(name)+1, GFP_KERNEL); + if (!sht->proc_name) + return 0; + strcpy(sht->proc_name, name); + + /* we start with no /proc directory entry */ + sht->proc_dir = NULL; + + /* register the host */ + us->host = scsi_register(sht, sizeof(us)); + if (us->host) { + us->host->hostdata[0] = (unsigned long)us; + us->host_no = us->host->host_no; + return 1; + } + + /* odd... didn't register properly. Abort and free pointers */ + kfree(sht->proc_name); + sht->proc_name = NULL; + sht->name = NULL; + return 0; +} + +/* release - must be here to stop scsi + * from trying to release IRQ etc. + * Kill off our data + */ +static int us_release(struct Scsi_Host *psh) +{ + struct us_data *us = (struct us_data *)psh->hostdata[0]; + struct us_data *prev = (struct us_data *)&us_list; + + if (us->irq_handle) { + usb_release_irq(us->pusb_dev, us->irq_handle, us->irqpipe); + us->irq_handle = NULL; + } + if (us->pusb_dev) + usb_deregister(&storage_driver); + + /* FIXME - leaves hanging host template copy */ + /* (because scsi layer uses it after removal !!!) */ + while (prev->next != us) + prev = prev->next; + prev->next = us->next; + return 0; +} + +/* run command */ +static int us_command( Scsi_Cmnd *srb ) +{ + US_DEBUGP("Bad use of us_command\n"); + + return DID_BAD_TARGET << 16; +} + +/* run command */ +static int us_queuecommand( Scsi_Cmnd *srb , void (*done)(Scsi_Cmnd *)) +{ + struct us_data *us = (struct us_data *)srb->host->hostdata[0]; + + US_DEBUGP("Command wakeup\n"); + if (us->srb) { + /* busy */ + } + srb->host_scribble = (unsigned char *)us; + us->srb = srb; + srb->scsi_done = done; + us->action = US_ACT_COMMAND; + + /* wake up the process task */ + + wake_up_interruptible(&us->waitq); + + return 0; +} + +/* FIXME: This doesn't actually abort anything */ +static int us_abort( Scsi_Cmnd *srb ) +{ + return 0; +} + +static int us_bus_reset( Scsi_Cmnd *srb ) +{ + // struct us_data *us = (struct us_data *)srb->host->hostdata[0]; + + US_DEBUGP("Bus reset requested\n"); + // us->transport_reset(us); + return SUCCESS; +} + +/* FIXME: This doesn't actually reset anything */ +static int us_host_reset( Scsi_Cmnd *srb ) +{ + return 0; +} + +/*********************************************************************** + * /proc/scsi/ functions + ***********************************************************************/ + +/* we use this macro to help us write into the buffer */ +#undef SPRINTF +#define SPRINTF(args...) do { if (pos < (buffer + length)) pos += sprintf (pos, ## args); } while (0) + +int usb_stor_proc_info (char *buffer, char **start, off_t offset, + int length, int hostno, int inout) +{ + struct us_data *us = us_list; + char *pos = buffer; + char *tmp_ptr; + + /* find our data from hostno */ + while (us) { + if (us->host_no == hostno) + break; + us = us->next; + } + + /* if we couldn't find it, we return an error */ + if (!us) + return -ESRCH; + + /* if someone is sending us data, just throw it away */ + if (inout) + return length; + + /* print the controler name */ + SPRINTF ("Host scsi%d: usb-storage\n", hostno); + + /* print product and vendor strings */ + 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: "); + 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: "); + if (usb_string(us->pusb_dev, us->pusb_dev->descriptor.iProduct, tmp_ptr, 256) > 0) + SPRINTF("%s\n", tmp_ptr); + else + SPRINTF("Unknown Product\n"); + kfree(tmp_ptr); + } + + SPRINTF(" Protocol: "); + switch (us->protocol) { + case US_PR_CB: + SPRINTF("Control/Bulk\n"); + break; + + case US_PR_CBI: + SPRINTF("Control/Bulk/Interrupt\n"); + break; + + case US_PR_BULK: + SPRINTF("Bulk only\n"); + break; + + default: + SPRINTF("Unknown Protocol\n"); + break; + } + + /* show the GUID of the device */ + SPRINTF(" GUID: " GUID_FORMAT "\n", GUID_ARGS(us->guid)); + + /* + * Calculate start of next buffer, and return value. + */ + *start = buffer + offset; + + if ((pos - buffer) < offset) + return (0); + else if ((pos - buffer - offset) < length) + return (pos - buffer - offset); + else + return (length); +} + +/* + * this defines our 'host' + */ + +static Scsi_Host_Template my_host_template = { + NULL, /* next */ + NULL, /* module */ + NULL, /* proc_dir */ + usb_stor_proc_info, + NULL, /* name - points to unique */ + us_detect, + us_release, + NULL, /* info */ + NULL, /* ioctl */ + us_command, + us_queuecommand, + NULL, /* eh_strategy */ + us_abort, + us_bus_reset, + us_bus_reset, + us_host_reset, + NULL, /* abort */ + NULL, /* reset */ + NULL, /* slave_attach */ + NULL, /* bios_param */ + 1, /* can_queue */ + -1, /* this_id */ + SG_ALL, /* sg_tablesize */ + 1, /* cmd_per_lun */ + 0, /* present */ + FALSE, /* unchecked_isa_dma */ + FALSE, /* use_clustering */ + TRUE, /* use_new_eh_code */ + TRUE /* emulated */ +}; + +static unsigned char sense_notready[] = { + 0x70, /* current error */ + 0x00, + 0x02, /* not ready */ + 0x00, + 0x00, + 0x0a, /* additional length */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x04, /* not ready */ + 0x03, /* manual intervention */ + 0x00, + 0x00, + 0x00, + 0x00 +}; + +static int usb_stor_control_thread(void * __us) +{ + struct us_data *us = (struct us_data *)__us; + int action; + + lock_kernel(); + + /* + * This thread doesn't need any user-level access, + * so get rid of all our resources.. + */ + daemonize(); + + sprintf(current->comm, "usbscsi%d", us->host_number); + + unlock_kernel(); + + up(us->notify); + + for(;;) { + siginfo_t info; + int unsigned long signr; + + interruptible_sleep_on(&us->waitq); + + action = us->action; + us->action = 0; + + /* FIXME: we need to examine placment of break; and + * scsi_done() calls */ + + switch (action) { + case US_ACT_COMMAND: + /* bad device */ + if (us->srb->target || us->srb->lun) { + US_DEBUGP( "Bad device number (%d/%d) or dev 0x%x\n", + us->srb->target, us->srb->lun, (unsigned int)us->pusb_dev); + us->srb->result = DID_BAD_TARGET << 16; + + us->srb->scsi_done(us->srb); + us->srb = NULL; + break; + } + + /* our device has gone - pretend not ready */ + /* FIXME: we also need to handle INQUIRY here, + * probably */ + if (!us->pusb_dev) { + if (us->srb->cmnd[0] == REQUEST_SENSE) { + memcpy(us->srb->request_buffer, sense_notready, + sizeof(sense_notready)); + us->srb->result = DID_OK << 16; + } else { + us->srb->result = (DID_OK << 16) | 2; + } + + us->srb->scsi_done(us->srb); + us->srb = NULL; + break; + } + + /* we've got a command, let's do it! */ + US_DEBUG(us_show_command(us->srb)); + + /* FIXME: this is to support Shuttle E-USB bridges, it + * appears */ + if (us->srb->cmnd[0] == START_STOP && + us->pusb_dev->descriptor.idProduct == 0x0001 && + us->pusb_dev->descriptor.idVendor == 0x04e6) + us->srb->result = DID_OK << 16; + else { + us->proto_handler(us->srb, us); + } + + US_DEBUGP("scsi cmd done, result=0x%x\n", us->srb->result); + us->srb->scsi_done(us->srb); + us->srb = NULL; + break; + + case US_ACT_ABORT: + break; + + case US_ACT_DEVICE_RESET: + break; + + case US_ACT_BUS_RESET: + break; + + case US_ACT_HOST_RESET: + break; + + } /* end switch on action */ + + if (signal_pending(current)) { + /* sending SIGUSR1 makes us print out some info */ + spin_lock_irq(¤t->sigmask_lock); + signr = dequeue_signal(¤t->blocked, &info); + spin_unlock_irq(¤t->sigmask_lock); + + if (signr == SIGUSR2) { + usb_stor_debug = !usb_stor_debug; + printk(USB_STORAGE "debug toggle = %d\n", usb_stor_debug); + } else { + break; /* exit the loop on any other signal */ + } + } + } + + // MOD_DEC_USE_COUNT; + + printk("usb_stor_control_thread exiting\n"); + + /* FIXME: this is a hack to allow for debugging */ + // scsi_unregister_module(MODULE_SCSI_HA, us->htmplt); + + return 0; +} + +/* Probe to see if a new device is actually a SCSI device */ +static void * storage_probe(struct usb_device *dev, unsigned int ifnum) +{ + struct usb_interface_descriptor *interface; + int i; + 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 */ + struct us_data *prev; + Scsi_Host_Template *htmplt; + int protocol = 0; + int subclass = 0; + struct usb_interface_descriptor *altsetting = + &(dev->actconfig->interface[ifnum].altsetting[0]); + + /* clear the GUID and fetch the strings */ + GUID_CLEAR(guid); + memset(mf, 0, sizeof(mf)); + memset(prod, 0, sizeof(prod)); + memset(serial, 0, sizeof(serial)); + if (dev->descriptor.iManufacturer) + usb_string(dev, dev->descriptor.iManufacturer, mf, sizeof(mf)); + if (dev->descriptor.iProduct) + usb_string(dev, dev->descriptor.iProduct, prod, sizeof(prod)); + if (dev->descriptor.iSerialNumber) + usb_string(dev, dev->descriptor.iSerialNumber, serial, sizeof(serial)); + + /* let's examine the device now */ + + /* We make an exception for the shuttle E-USB */ + if (dev->descriptor.idVendor == 0x04e6 && + dev->descriptor.idProduct == 0x0001) { + protocol = US_PR_CB; + subclass = US_SC_8070; /* an assumption */ + } else if (dev->descriptor.bDeviceClass != 0 || + altsetting->bInterfaceClass != USB_CLASS_MASS_STORAGE || + altsetting->bInterfaceSubClass < US_SC_MIN || + altsetting->bInterfaceSubClass > US_SC_MAX) { + /* if it's not a mass storage, we go no further */ + return NULL; + } + + /* At this point, we know we've got a live one */ + US_DEBUGP("USB Mass Storage device detected\n"); + + /* Create a GUID for this device */ + 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, serial); + } else { + /* We don't have a serial number, so we use 0 */ + make_guid(guid, dev->descriptor.idVendor, + dev->descriptor.idProduct, "0"); + } + + /* Now check if we have seen this GUID before, and restore + * the flags if we find it + */ + for (ss = us_list; ss != NULL; ss = ss->next) { + if (!ss->pusb_dev && GUID_EQUAL(guid, ss->guid)) { + US_DEBUGP("Found existing GUID " GUID_FORMAT "\n", + GUID_ARGS(guid)); + flags = ss->flags; + break; + } + } + + /* If ss == NULL, then this is a new device. Allocate memory for it */ + if (!ss) { + if ((ss = (struct us_data *)kmalloc(sizeof(*ss), + GFP_KERNEL)) == NULL) { + printk(KERN_WARNING USB_STORAGE "Out of memory\n"); + return NULL; + } + memset(ss, 0, sizeof(struct us_data)); + } + + /* Initialize the us_data structure with some useful info */ + interface = altsetting; + ss->flags = flags; + ss->ifnum = ifnum; + ss->pusb_dev = dev; + ss->attention_done = 0; + + /* If the device has subclass and protocol, then use that. Otherwise, + * take data from the specific interface. + */ + if (subclass) { + ss->subclass = subclass; + ss->protocol = protocol; + } else { + ss->subclass = interface->bInterfaceSubClass; + ss->protocol = interface->bInterfaceProtocol; + } + + /* set the handler pointers based on the protocol */ + US_DEBUGP("Transport: "); + switch (ss->protocol) { + case US_PR_CB: + US_DEBUGPX("Control/Bulk\n"); + ss->transport = CB_transport; + ss->transport_reset = CB_reset; + break; + + case US_PR_CBI: + US_DEBUGPX("Control/Bulk/Interrupt\n"); + ss->transport = CB_transport; + ss->transport_reset = CB_reset; + break; + + case US_PR_BULK: + US_DEBUGPX("Bulk\n"); + ss->transport = Bulk_transport; + ss->transport_reset = Bulk_reset; + break; + + default: + US_DEBUGPX("Unknown\n"); + kfree(ss); + return NULL; + break; + } + + /* + * We are expecting a minimum of 2 endpoints - in and out (bulk). + * An optional interrupt is OK (necessary for CBI protocol). + * We will ignore any others. + */ + for (i = 0; i < interface->bNumEndpoints; i++) { + /* is it an BULK endpoint? */ + if ((interface->endpoint[i].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + == USB_ENDPOINT_XFER_BULK) { + if (interface->endpoint[i].bEndpointAddress & USB_DIR_IN) + ss->ep_in = interface->endpoint[i].bEndpointAddress & + USB_ENDPOINT_NUMBER_MASK; + else + ss->ep_out = interface->endpoint[i].bEndpointAddress & + USB_ENDPOINT_NUMBER_MASK; + } + + /* is it an interrupt endpoint? */ + if ((interface->endpoint[i].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + == USB_ENDPOINT_XFER_INT) { + ss->ep_int = interface->endpoint[i].bEndpointAddress & + USB_ENDPOINT_NUMBER_MASK; + } + } + US_DEBUGP("Endpoints In %d Out %d Int %d\n", + ss->ep_in, ss->ep_out, ss->ep_int); + + /* Do some basic sanity checks, and bail if we find a problem */ + if (usb_set_interface(dev, interface->bInterfaceNumber, 0) || + !ss->ep_in || !ss->ep_out || + (ss->protocol == US_PR_CBI && ss->ep_int == 0)) { + US_DEBUGP("Problems with device\n"); + if (ss->host) { + scsi_unregister_module(MODULE_SCSI_HA, ss->htmplt); + kfree(ss->htmplt->name); + kfree(ss->htmplt); + } + + kfree(ss); + return NULL; + } + + /* If this is a new device (i.e. we haven't seen it before), we need to + * generate a scsi host definition, and register with scsi above us + */ + if (!ss->host) { + /* copy the GUID we created before */ + US_DEBUGP("New GUID " GUID_FORMAT "\n", GUID_ARGS(guid)); + memcpy(ss->guid, guid, sizeof(guid)); + + /* set class specific stuff */ + US_DEBUGP("Protocol: "); + switch (ss->subclass) { + case US_SC_RBC: + US_DEBUGPX("Reduced Block Commands\n"); + break; + + case US_SC_8020: + US_DEBUGPX("8020\n"); + break; + + case US_SC_QIC: + US_DEBUGPX("QIC157\n"); + break; + + case US_SC_8070: + US_DEBUGPX("8070\n"); + break; + + case US_SC_SCSI: + US_DEBUGPX("Transparent SCSI\n"); + ss->proto_handler = transparent_scsi_command; + break; + + case US_SC_UFI: + US_DEBUGPX("UFI\n"); + ss->proto_handler = ufi_command; + break; + + default: + US_DEBUGPX("Unknown\n"); + break; + } + + /* We only handle certain protocols. Currently, these are + *the only ones that devices use. + */ + if ((ss->subclass != US_SC_SCSI) && (ss->subclass != US_SC_UFI)) { + US_DEBUGP("Sorry, we do not support that protocol yet.\n"); + US_DEBUGP("If you have a device which uses one of the unsupported\n"); + US_DEBUGP("protocols, please contact mdharm-usb@one-eyed-alien.net\n"); + + kfree(ss); + return NULL; + } + + /* Allocate memory for the SCSI Host Template */ + if ((htmplt = (Scsi_Host_Template *) + kmalloc(sizeof(*ss->htmplt), GFP_KERNEL)) == NULL ) { + + printk(KERN_WARNING USB_STORAGE "Out of memory\n"); + + kfree(ss); + return NULL; + } + + /* Initialize the host template based on the default one */ + memcpy(htmplt, &my_host_template, sizeof(my_host_template)); + + /* Grab the next host number */ + ss->host_number = my_host_number++; + + /* MDD: FIXME: this is bad. We abuse this pointer so we + * can pass the ss pointer to the host controler thread + * in us_detect + */ + (struct us_data *)htmplt->proc_dir = ss; + + /* shuttle E-USB */ + if (dev->descriptor.idVendor == 0x04e6 && + dev->descriptor.idProduct == 0x0001) { + __u8 qstat[2]; + int result; + + result = usb_control_msg(ss->pusb_dev, usb_rcvctrlpipe(dev,0), + 1, 0xC0, + 0, ss->ifnum, + qstat, 2, HZ*5); + US_DEBUGP("C0 status 0x%x 0x%x\n", qstat[0], qstat[1]); + init_waitqueue_head(&ss->ip_waitq); + ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int); + result = usb_request_irq(ss->pusb_dev, ss->irqpipe, CBI_irq, + 255, (void *)ss, &ss->irq_handle); + if (result) + return NULL; + + interruptible_sleep_on_timeout(&ss->ip_waitq, HZ*6); + } else if (ss->protocol == US_PR_CBI) + { + int result; + + init_waitqueue_head(&ss->ip_waitq); + + /* set up the IRQ pipe and handler */ + /* FIXME: This needs to get the period from the device */ + ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int); + result = usb_request_irq(ss->pusb_dev, ss->irqpipe, CBI_irq, + 255, (void *)ss, &ss->irq_handle); + if (result) { + US_DEBUGP("usb_request_irq failed (0x%x), No interrupt for CBI\n", + result); + } + } + + + /* start up our thread */ + { + DECLARE_MUTEX_LOCKED(sem); + + init_waitqueue_head(&ss->waitq); + + ss->notify = &sem; + ss->pid = kernel_thread(usb_stor_control_thread, ss, + CLONE_FS | CLONE_FILES | CLONE_SIGHAND); + if (ss->pid < 0) { + printk(KERN_WARNING USB_STORAGE "Unable to start control thread\n"); + kfree(htmplt); + + kfree(ss); + return NULL; + } + + /* wait for it to start */ + down(&sem); + } + + /* now register - our detect function will be called */ + scsi_register_module(MODULE_SCSI_HA, htmplt); + + /* put us in the list */ + prev = (struct us_data *)&us_list; + while (prev->next) + prev = prev->next; + prev->next = ss; + } + + printk(KERN_INFO "WARNING: USB Mass Storage data integrity not assured\n"); + printk(KERN_INFO "USB Mass Storage device found at %d\n", dev->devnum); + + return ss; +} + +/* Handle a disconnect event from the USB core */ +static void storage_disconnect(struct usb_device *dev, void *ptr) +{ + struct us_data *ss = ptr; + + if (!ss) + return; + + ss->pusb_dev = NULL; + // MOD_DEC_USE_COUNT; +} + + +/*********************************************************************** + * Initialization and registration + ***********************************************************************/ + +int usb_stor_init(void) +{ + // MOD_INC_USE_COUNT; + + /* register the driver, return -1 if error */ + if (usb_register(&storage_driver) < 0) + return -1; + + printk(KERN_INFO "USB Mass Storage support registered.\n"); + return 0; +} + +#ifdef MODULE +int init_module(void) +{ + /* MDD: Perhaps we should register the host here */ + return usb_stor_init(); +} + +void cleanup_module(void) +{ + usb_deregister(&storage_driver); +} +#endif diff --git a/drivers/usb/usb_storage.h b/drivers/usb/usb_storage.h new file mode 100644 index 000000000..114a2c12a --- /dev/null +++ b/drivers/usb/usb_storage.h @@ -0,0 +1,130 @@ +/* Driver for USB mass storage - include file + * + * (c) 1999 Michael Gee (michael@linuxspecific.com) + * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) + * + */ + +#include + +#define USB_STORAGE "usb-storage: " + +extern int usb_stor_debug; + +#ifdef CONFIG_USB_STORAGE_DEBUG +void us_show_command(Scsi_Cmnd *srb); +#define US_DEBUGP(x...) { if(usb_stor_debug) printk( KERN_DEBUG USB_STORAGE ## x ); } +#define US_DEBUGPX(x...) { if(usb_stor_debug) printk( ## x ); } +#define US_DEBUG(x) { if(usb_stor_debug) x; } +#else +#define US_DEBUGP(x...) +#define US_DEBUGPX(x...) +#define US_DEBUG(x) +#endif + +/* bit set if input */ +extern unsigned char us_direction[256/8]; +#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1) + +/* Sub Classes */ + +#define US_SC_RBC 1 /* Typically, flash devices */ +#define US_SC_8020 2 /* CD-ROM */ +#define US_SC_QIC 3 /* QIC-157 Tapes */ +#define US_SC_UFI 4 /* Floppy */ +#define US_SC_8070 5 /* Removable media */ +#define US_SC_SCSI 6 /* Transparent */ +#define US_SC_MIN US_SC_RBC +#define US_SC_MAX US_SC_SCSI + +/* Protocols */ + +#define US_PR_CB 1 /* Control/Bulk w/o interrupt */ +#define US_PR_CBI 0 /* Control/Bulk/Interrupt */ +#define US_PR_BULK 0x50 /* bulk only */ + +/* + * Bulk only data structures (Zip 100, for example) + */ + +/* command block wrapper */ +struct bulk_cb_wrap { + __u32 Signature; /* contains 'USBC' */ + __u32 Tag; /* unique per command id */ + __u32 DataTransferLength; /* size of data */ + __u8 Flags; /* direction in bit 0 */ + __u8 Lun; /* LUN normally 0 */ + __u8 Length; /* of of the CDB */ + __u8 CDB[16]; /* max command */ +}; + +#define US_BULK_CB_WRAP_LEN 31 +#define US_BULK_CB_SIGN 0x43425355 +#define US_BULK_FLAG_IN 1 +#define US_BULK_FLAG_OUT 0 + +/* command status wrapper */ +struct bulk_cs_wrap { + __u32 Signature; /* should = 'USBS' */ + __u32 Tag; /* same as original command */ + __u32 Residue; /* amount not transferred */ + __u8 Status; /* see below */ + __u8 Filler[18]; +}; + +#define US_BULK_CS_WRAP_LEN 31 +#define US_BULK_CS_SIGN 0x53425355 +#define US_BULK_STAT_OK 0 +#define US_BULK_STAT_FAIL 1 +#define US_BULK_STAT_PHASE 2 + +#define US_BULK_RESET 0xff +#define US_BULK_RESET_SOFT 1 +#define US_BULK_RESET_HARD 0 + +/* + * Transport return codes + */ + +#define USB_STOR_TRANSPORT_GOOD 0 /* Transport good, command good */ +#define USB_STOR_TRANSPORT_FAILED 1 /* Transport good, command failed */ +#define USB_STOR_TRANSPORT_ERROR 2 /* Transport bad (i.e. device dead */ + +/* + * CBI style + */ + +#define US_CBI_ADSC 0 + +/* + * GUID definitions + */ + +#define GUID(x) __u32 x[3] +#define GUID_EQUAL(x, y) (x[0] == y[0] && x[1] == y[1] && x[2] == y[2]) +#define GUID_CLEAR(x) x[0] = x[1] = x[2] = 0; +#define GUID_NONE(x) (!x[0] && !x[1] && !x[2]) +#define GUID_FORMAT "%08x%08x%08x" +#define GUID_ARGS(x) x[0], x[1], x[2] + +static inline void make_guid( __u32 *pg, __u16 vendor, __u16 product, char *serial) +{ + pg[0] = (vendor << 16) | product; + pg[1] = pg[2] = 0; + while (*serial) { + pg[1] <<= 4; + pg[1] |= pg[2] >> 28; + pg[2] <<= 4; + if (*serial >= 'a') + *serial -= 'a' - 'A'; + pg[2] |= (*serial <= '9' && *serial >= '0') ? *serial - '0' + : *serial - 'A' + 10; + serial++; + } +} + +/* Flag definitions */ +#define US_FL_IP_STATUS 0x00000001 /* status uses interrupt */ +#define US_FL_FIXED_COMMAND 0x00000002 /* expand commands to fixed size */ +#define US_FL_MODE_XLATE 0x00000004 /* translate _6 to _10 comands for + Win/MacOS compatibility */ diff --git a/drivers/usb/usb_storage_debug.c b/drivers/usb/usb_storage_debug.c new file mode 100644 index 000000000..cff8f9a61 --- /dev/null +++ b/drivers/usb/usb_storage_debug.c @@ -0,0 +1,104 @@ + +/* Driver for USB mass storage (scsi-like) devices + * + * (C) Michael Gee (michael@linuxspecific.com) 1999 + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "../scsi/scsi.h" +#include "../scsi/hosts.h" +#include "../scsi/sd.h" + +#include "usb.h" +#include "usb_storage.h" + +void us_show_command(Scsi_Cmnd *srb) +{ + char *what = NULL; + + switch (srb->cmnd[0]) { + case TEST_UNIT_READY: what = "TEST_UNIT_READY"; break; + case REZERO_UNIT: what = "REZERO_UNIT"; break; + case REQUEST_SENSE: what = "REQUEST_SENSE"; break; + case FORMAT_UNIT: what = "FORMAT_UNIT"; break; + case READ_BLOCK_LIMITS: what = "READ_BLOCK_LIMITS"; break; + case REASSIGN_BLOCKS: what = "REASSIGN_BLOCKS"; break; + case READ_6: what = "READ_6"; break; + case WRITE_6: what = "WRITE_6"; break; + case SEEK_6: what = "SEEK_6"; break; + case READ_REVERSE: what = "READ_REVERSE"; break; + case WRITE_FILEMARKS: what = "WRITE_FILEMARKS"; break; + case SPACE: what = "SPACE"; break; + case INQUIRY: what = "INQUIRY"; break; + case RECOVER_BUFFERED_DATA: what = "RECOVER_BUFFERED_DATA"; break; + case MODE_SELECT: what = "MODE_SELECT"; break; + case RESERVE: what = "RESERVE"; break; + case RELEASE: what = "RELEASE"; break; + case COPY: what = "COPY"; break; + case ERASE: what = "ERASE"; break; + case MODE_SENSE: what = "MODE_SENSE"; break; + case START_STOP: what = "START_STOP"; break; + case RECEIVE_DIAGNOSTIC: what = "RECEIVE_DIAGNOSTIC"; break; + case SEND_DIAGNOSTIC: what = "SEND_DIAGNOSTIC"; break; + case ALLOW_MEDIUM_REMOVAL: what = "ALLOW_MEDIUM_REMOVAL"; break; + case SET_WINDOW: what = "SET_WINDOW"; break; + case READ_CAPACITY: what = "READ_CAPACITY"; break; + case READ_10: what = "READ_10"; break; + case WRITE_10: what = "WRITE_10"; break; + case SEEK_10: what = "SEEK_10"; break; + case WRITE_VERIFY: what = "WRITE_VERIFY"; break; + case VERIFY: what = "VERIFY"; break; + case SEARCH_HIGH: what = "SEARCH_HIGH"; break; + case SEARCH_EQUAL: what = "SEARCH_EQUAL"; break; + case SEARCH_LOW: what = "SEARCH_LOW"; break; + case SET_LIMITS: what = "SET_LIMITS"; break; + case READ_POSITION: what = "READ_POSITION"; break; + case SYNCHRONIZE_CACHE: what = "SYNCHRONIZE_CACHE"; break; + case LOCK_UNLOCK_CACHE: what = "LOCK_UNLOCK_CACHE"; break; + case READ_DEFECT_DATA: what = "READ_DEFECT_DATA"; break; + case MEDIUM_SCAN: what = "MEDIUM_SCAN"; break; + case COMPARE: what = "COMPARE"; break; + case COPY_VERIFY: what = "COPY_VERIFY"; break; + case WRITE_BUFFER: what = "WRITE_BUFFER"; break; + case READ_BUFFER: what = "READ_BUFFER"; break; + case UPDATE_BLOCK: what = "UPDATE_BLOCK"; break; + case READ_LONG: what = "READ_LONG"; break; + case WRITE_LONG: what = "WRITE_LONG"; break; + case CHANGE_DEFINITION: what = "CHANGE_DEFINITION"; break; + case WRITE_SAME: what = "WRITE_SAME"; break; + case READ_TOC: what = "READ_TOC"; break; + case LOG_SELECT: what = "LOG_SELECT"; break; + case LOG_SENSE: what = "LOG_SENSE"; break; + case MODE_SELECT_10: what = "MODE_SELECT_10"; break; + case MODE_SENSE_10: what = "MODE_SENSE_10"; break; + case MOVE_MEDIUM: what = "MOVE_MEDIUM"; break; + case READ_12: what = "READ_12"; break; + case WRITE_12: what = "WRITE_12"; break; + case WRITE_VERIFY_12: what = "WRITE_VERIFY_12"; break; + case SEARCH_HIGH_12: what = "SEARCH_HIGH_12"; break; + case SEARCH_EQUAL_12: what = "SEARCH_EQUAL_12"; break; + case SEARCH_LOW_12: what = "SEARCH_LOW_12"; break; + case READ_ELEMENT_STATUS: what = "READ_ELEMENT_STATUS"; break; + case SEND_VOLUME_TAG: what = "SEND_VOLUME_TAG"; break; + case WRITE_LONG_2: what = "WRITE_LONG_2"; break; + default: break; + } + printk(KERN_DEBUG USB_STORAGE + "Command %s (%d bytes)\n", what, srb->cmd_len); + printk(KERN_DEBUG USB_STORAGE + " %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + srb->cmnd[0], srb->cmnd[1], srb->cmnd[2], srb->cmnd[3], srb->cmnd[4], srb->cmnd[5], + srb->cmnd[6], srb->cmnd[7], srb->cmnd[8], srb->cmnd[9]); +} diff --git a/drivers/usb/usbdevice_fs.h b/drivers/usb/usbdevice_fs.h index a4bd5d154..be3424a88 100644 --- a/drivers/usb/usbdevice_fs.h +++ b/drivers/usb/usbdevice_fs.h @@ -111,7 +111,6 @@ struct usbdevfs_urb { #ifdef __KERNEL__ -#include #include #include diff --git a/drivers/usb/usbkbd.c b/drivers/usb/usbkbd.c index 26de45a38..c6803f943 100644 --- a/drivers/usb/usbkbd.c +++ b/drivers/usb/usbkbd.c @@ -142,7 +142,8 @@ static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum) if (!(endpoint->bEndpointAddress & 0x80)) return NULL; if ((endpoint->bmAttributes & 3) != 3) return NULL; - usb_set_protocol(dev, 0); + usb_set_protocol(dev, interface->bInterfaceNumber, 0); + usb_set_idle(dev, interface->bInterfaceNumber, 0, 0); if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL; memset(kbd, 0, sizeof(struct usb_kbd)); diff --git a/drivers/usb/usbmouse.c b/drivers/usb/usbmouse.c index e4145d095..7276ca670 100644 --- a/drivers/usb/usbmouse.c +++ b/drivers/usb/usbmouse.c @@ -83,8 +83,9 @@ static void *usb_mouse_probe(struct usb_device *dev, unsigned int ifnum) if ((endpoint->bmAttributes & 3) != 3) return NULL; #ifndef USBMOUSE_EXTRA - usb_set_protocol(dev, 0); + usb_set_protocol(dev, interface->bInterfaceNumber, 0); #endif + usb_set_idle(dev, interface->bInterfaceNumber, 0, 0); if (!(mouse = kmalloc(sizeof(struct usb_mouse), GFP_KERNEL))) return NULL; memset(mouse, 0, sizeof(struct usb_mouse)); diff --git a/drivers/usb/uss720.c b/drivers/usb/uss720.c index 1328af1e8..d4db8546e 100644 --- a/drivers/usb/uss720.c +++ b/drivers/usb/uss720.c @@ -177,7 +177,7 @@ static int clear_epp_timeout(struct parport *pp) /* * Access functions. */ - +#if 0 static int uss720_irq(int usbstatus, void *buffer, int len, void *dev_id) { struct parport *pp = (struct parport *)dev_id; @@ -191,6 +191,7 @@ static int uss720_irq(int usbstatus, void *buffer, int len, void *dev_id) parport_generic_irq(0, pp, NULL); return 1; } +#endif static void parport_uss720_write_data(struct parport *pp, unsigned char d) { @@ -356,7 +357,7 @@ static size_t parport_uss720_epp_write_data(struct parport *pp, const void *buf, #else struct parport_uss720_private *priv = pp->private_data; struct usb_device *usbdev = priv->usbdev; - unsigned long rlen; + int rlen; int i; if (!usbdev) @@ -365,7 +366,7 @@ static size_t parport_uss720_epp_write_data(struct parport *pp, const void *buf, return 0; i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buf, length, &rlen, HZ*20); if (i) - printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %u rlen %lu\n", buf, length, rlen); + printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %u rlen %u\n", buf, length, rlen); change_mode(pp, ECR_PS2); return rlen; #endif @@ -417,7 +418,7 @@ static size_t parport_uss720_ecp_write_data(struct parport *pp, const void *buff { struct parport_uss720_private *priv = pp->private_data; struct usb_device *usbdev = priv->usbdev; - unsigned long rlen; + int rlen; int i; if (!usbdev) @@ -426,7 +427,7 @@ static size_t parport_uss720_ecp_write_data(struct parport *pp, const void *buff return 0; i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buffer, len, &rlen, HZ*20); if (i) - printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %u rlen %lu\n", buffer, len, rlen); + printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %u rlen %u\n", buffer, len, rlen); change_mode(pp, ECR_PS2); return rlen; } @@ -435,7 +436,7 @@ static size_t parport_uss720_ecp_read_data(struct parport *pp, void *buffer, siz { struct parport_uss720_private *priv = pp->private_data; struct usb_device *usbdev = priv->usbdev; - unsigned long rlen; + int rlen; int i; if (!usbdev) @@ -444,7 +445,7 @@ static size_t parport_uss720_ecp_read_data(struct parport *pp, void *buffer, siz return 0; i = usb_bulk_msg(usbdev, usb_rcvbulkpipe(usbdev, 2), buffer, len, &rlen, HZ*20); if (i) - printk(KERN_ERR "uss720: recvbulk ep 2 buf %p len %u rlen %lu\n", buffer, len, rlen); + printk(KERN_ERR "uss720: recvbulk ep 2 buf %p len %u rlen %u\n", buffer, len, rlen); change_mode(pp, ECR_PS2); return rlen; } @@ -468,7 +469,7 @@ static size_t parport_uss720_write_compat(struct parport *pp, const void *buffer { struct parport_uss720_private *priv = pp->private_data; struct usb_device *usbdev = priv->usbdev; - unsigned long rlen; + int rlen; int i; if (!usbdev) @@ -477,7 +478,7 @@ static size_t parport_uss720_write_compat(struct parport *pp, const void *buffer return 0; i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buffer, len, &rlen, HZ*20); if (i) - printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %u rlen %lu\n", buffer, len, rlen); + printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %u rlen %u\n", buffer, len, rlen); change_mode(pp, ECR_PS2); return rlen; } @@ -606,8 +607,10 @@ static void * uss720_probe(struct usb_device *usbdev, unsigned int ifnum) MOD_INC_USE_COUNT; return pp; +#if 0 probe_abort_port: parport_unregister_port(pp); +#endif probe_abort: kfree(priv); return NULL; diff --git a/drivers/usb/wmforce.c b/drivers/usb/wmforce.c index b8fef7891..fa2d1b465 100644 --- a/drivers/usb/wmforce.c +++ b/drivers/usb/wmforce.c @@ -1,9 +1,9 @@ /* * wmforce.c Version 0.1 * - * Copyright (c) 1999 Vojtech Pavlik + * Copyright (c) 2000 Vojtech Pavlik * - * USB Logitech WingMan Force tablet support + * USB Logitech WingMan Force joystick support * * Sponsored by SuSE */ -- cgit v1.2.3