diff -Naur linux.225/Documentation/Configure.help linux.225.visws/Documentation/Configure.help --- linux.225/Documentation/Configure.help Fri Mar 26 13:23:20 1999 +++ linux.225.visws/Documentation/Configure.help Thu Apr 15 17:51:21 1999 @@ -9066,6 +9066,170 @@ UART chip. This interface is rarely found on sound cards. It's safe to answer N to this question. +Universal Serial Bus +CONFIG_USB + The Universal Serial Bus (USB) is a new kind of bus which allows + true Plug'n'Play, hot plug and dynamic configuration, following a + tiered star topology. Devices such as keyboards, mice, joysticks, + video cameras, speakers, game-pads ... etc may use this bus, as long + as they are prepared for it. Note you can ONLY compile this as a + MODULE [this will change in a future]. + + In case of doubt, is safe to say Y/M. + +Modular drivers load on demand +CONFIG_USB_LOD + The USB driver stack supports dynamic configuration, and to achieve + it, there's a register of supported drivers. When it is not possible + to configure a device with any of the drivers in that register, the + kernel can request to load modules which could do it. + + Modular drivers register themselves the first time they are loaded, + so if you disable this option, you need to manually insert the + driver modules (eg: at boot) and then unload them if you will not + use them. This is needed for the stack to know which drivers are + available. IN A FUTURE, the stack will automagically load the + drivers it knows that should be there [due to configuration + settings], but it is not implemented yet. + + Note that when saying Y, you will find many messages on device + attachment in your daemon log [from modprobe] indicating it cannot + find module 'usb-VVVV.IIII.CC.SS.PP'. Those are the driver + combinations, and normally are harmless and can be ignored. + + It is safe [and recommended] to say Y. + +Universal Host Controller Interface (UHCI) support +CONFIG_USB_UHCI + The USB host controllers come in two flavors. This is the UHCI, + which is the standard HCI (Host Controller Interface) used by + Intel. In overall performance, OHCI (Open Host Controller Interface) + is better then UHCI, UHCI is cheaper. Note you can ONLY compile this + as a module. + + In case of doubt, is safe to say Y/M. + + +Open Host Controller Interface (OHCI) support +CONFIG_USB_OHCI + The USB host controllers come in two flavors. This is the OHCI, + which is the standard HCI (Host Controller Interface) used by + anyone who is not Intel. Note you can ONLY compile this as a module. + + In case of doubt, is safe to say Y/M. + + +Hub Devices Class (AUD) 1.0 support +CONFIG_USB_HUBD + Hubs are one of the basic elements of the USB bus topology. They are + the `nodes' which allow you to connect as much as 127 devices to the + same host card. Note you'll always have a root hub embedded in your + USB host adapter card (which exposes normally two ports); this + driver is for non-root hubs. Only if you don't plan to use non-root + hubs, should you say N here. + + In case of doubt, is safe to say Y/M. + + +Audio Devices Class (AUD) 1.0 support +CONFIG_USB_AUDD + The USB defines classes of devices. Enable this option to have + generic driver for devices which follow the Audio Class. These + devices may be all kind of speakers, microphones, recorders, mixing + banks, sequencers, etc ... + + In case of doubt, is safe to say Y/M. + + +Human Interface Devices (HID) 1.0 support +CONFIG_USB_HIDD + The USB defines classes of devices. Enable this option to have a + generic driver for HID Class devices. These devices are the ones we + humans use to communicate (interface) data to the computer, such as + keyboards, mice, tablets, game-pad, joysticks, VR globes, etc ... + + In case of doubt, is safe to say Y/M. + + +Human Interface Devices Boot Protocol (HIDBP) 1.0 support +CONFIG_USB_HIDBP + The HID Class defines a boot protocol for keyboards and mice. This + makes an smaller driver for those who only need minimal support + (mainly for boot time). Enable this option to have the driver + compiled. + + Note this driver *requires* the Miscellaneous User Drivers option, + CONFIG_UMISC, which will be activated auto-magically if you select + it. You may need to rebuild your kernel if it wasn't previously + selected. + + In case of doubt, is safe to say Y/M. + + +Boot Protocol keyboard support +CONFIG_USB_HIDBP_KBD + Enable this option for compiling in support for keyboards in the + HIDBP driver. YOU NEED THE MULTIPLE KEYBOARDS PATCH FOR THIS TO + COMPILE; please don't report as a bug if the driver doesn't compile + for not having applied the patch; that's normal; you can find the + patch at the UUSBD web page or at + ftp://samba.anu.edu.au/pub/linux-pmac/imac/kbd-2.2.0-final.patch.gz. + + It is recommended to say Y here [if you patched the kernel]. + + +Boot Protocol mouse +CONFIG_USB_HIDBP_MSE + Enable this option for compiling in support for mice in the HIDBP + driver. + + It is recommended to say Y here. + + +Boot Protocol Genius EasyPen Tablet +CONFIG_USB_HIDBP_GENIUS_EASYPEN + Enable this option for compiling in support for Genius EasyPen in + Boot Protocol mode. + + It is recommended to say Y here only if you have it. It is not + dangerous if you say Y and don't have it. + + +Communication Devices Class (CDC) 1.0 Support +CONFIG_USB_CDCD + The USB defines classes of devices. Enable this option to have a + generic driver for communication devices. This definition englobes + modems, ISDN adapters, network interfaces (Ethernet, ATM, remote + NDIS) and telephony devices. + + In case of doubt is safe to say Y/M. + + +CDC ISDN support +CONFIG_USB_CDCD_ISDN + The CDC supports many sub-models. This options enables the creation + of a generic driver for USB ISDN (Integrated Services Digital + Network) adapters. + + In case of doubt, it is safe to say Y/M. + + +CDC ISDN support for CAPI 2.0 compliant adapters +CONFIG_USB_CDCD_ISDN_CAPI + Enable this option support CAPI 2.0 compliant ISDN adapters. CAPI is + the `Common ISDN API', which enables adapters of many different + brands to be operated with the same drivers. + + In case of doubt, it is safe to say Y/M. + + +Raw Driver Support +CONFIG_USB_RAWD + Use this driver to be able to read/write directly to device + endpoints from userland, using normal file operations. NOTE THIS + DRIVER IS NOT FINISHED YET!!!!! + + In case of doubt is safe to say Y/M. VIDC Sound CONFIG_VIDC_SOUND Say Y here for ARM systems with the VIDC video controller and 16-bit @@ -11267,3 +11431,6 @@ # LocalWords: alphalinux GOBIOS csn chemnitz nat ACARD AMI MegaRAID megaraid # LocalWords: QNXFS ISI isicom xterms Apollos VPN RCPCI rcpci sgi visws pcmcia # LocalWords: IrLPT UIRCC Tecra +# LocalWords: USB HCI UHCI OHCI AUD HID KBD MSE CDC +# LocalWords: MSDD AUDD HIDD HIDBP CDCD RAWD GENIUS TABLET +# LocalWords: LOD diff -Naur linux.225/arch/alpha/config.in linux.225.visws/arch/alpha/config.in --- linux.225/arch/alpha/config.in Mon Feb 1 12:03:20 1999 +++ linux.225.visws/arch/alpha/config.in Thu Apr 15 17:51:21 1999 @@ -276,6 +276,20 @@ fi endmenu +# USB Support +# +# FIXME: the USB support should be at General Setup on _all_ archs, +# and the drivers scattered on their directories. + +mainmenu_option next_comment +comment 'Universal Serial Bus (USB)' +tristate 'USB Support' CONFIG_USB +if [ "$CONFIG_USB" != "n" ] +then + source drivers/uusbd/Config.in +fi +endmenu + mainmenu_option next_comment comment 'Kernel hacking' diff -Naur linux.225/arch/arm/config.in linux.225.visws/arch/arm/config.in --- linux.225/arch/arm/config.in Thu Jan 14 10:29:28 1999 +++ linux.225.visws/arch/arm/config.in Thu Apr 15 17:51:21 1999 @@ -211,6 +211,20 @@ source fs/Config.in +# USB Support +# +# FIXME: the USB support should be at General Setup on _all_ archs, +# and the drivers scattered on their directories. + +mainmenu_option next_comment +comment 'Universal Serial Bus (USB)' +tristate 'USB Support' CONFIG_USB +if [ "$CONFIG_USB" != "n" ] +then + source drivers/uusbd/Config.in +fi +endmenu + mainmenu_option next_comment comment 'Kernel hacking' diff -Naur linux.225/arch/i386/config.in linux.225.visws/arch/i386/config.in --- linux.225/arch/i386/config.in Fri Mar 12 17:39:50 1999 +++ linux.225.visws/arch/i386/config.in Thu Apr 15 17:51:21 1999 @@ -192,6 +192,20 @@ fi endmenu +# USB Support +# +# FIXME: the USB support should be at General Setup on _all_ archs, +# and the drivers scattered on their directories. + +mainmenu_option next_comment +comment 'Universal Serial Bus (USB)' +tristate 'USB Support' CONFIG_USB +if [ "$CONFIG_USB" != "n" ] +then + source drivers/uusbd/Config.in +fi +endmenu + mainmenu_option next_comment comment 'Kernel hacking' diff -Naur linux.225/arch/m68k/config.in linux.225.visws/arch/m68k/config.in --- linux.225/arch/m68k/config.in Mon Feb 1 12:03:20 1999 +++ linux.225.visws/arch/m68k/config.in Thu Apr 15 17:51:21 1999 @@ -357,6 +357,20 @@ endmenu fi +# USB Support +# +# FIXME: the USB support should be at General Setup on _all_ archs, +# and the drivers scattered on their directories. + +mainmenu_option next_comment +comment 'Universal Serial Bus (USB)' +tristate 'USB Support' CONFIG_USB +if [ "$CONFIG_USB" != "n" ] +then + source drivers/uusbd/Config.in +fi +endmenu + mainmenu_option next_comment comment 'Kernel hacking' diff -Naur linux.225/arch/mips/config.in linux.225.visws/arch/mips/config.in --- linux.225/arch/mips/config.in Mon Feb 1 12:03:20 1999 +++ linux.225.visws/arch/mips/config.in Thu Apr 15 17:51:21 1999 @@ -208,6 +208,20 @@ source drivers/sgi/char/Config.in fi +# USB Support +# +# FIXME: the USB support should be at General Setup on _all_ archs, +# and the drivers scattered on their directories. + +mainmenu_option next_comment +comment 'Universal Serial Bus (USB)' +tristate 'USB Support' CONFIG_USB +if [ "$CONFIG_USB" != "n" ] +then + source drivers/uusbd/Config.in +fi +endmenu + mainmenu_option next_comment comment 'Kernel hacking' diff -Naur linux.225/arch/ppc/config.in linux.225.visws/arch/ppc/config.in --- linux.225/arch/ppc/config.in Wed Mar 10 21:30:31 1999 +++ linux.225.visws/arch/ppc/config.in Thu Apr 15 17:51:21 1999 @@ -168,6 +168,20 @@ source drivers/char/Config.in source fs/Config.in +# USB Support +# +# FIXME: the USB support should be at General Setup on _all_ archs, +# and the drivers scattered on their directories. + +mainmenu_option next_comment +comment 'Universal Serial Bus (USB)' +tristate 'USB Support' CONFIG_USB +if [ "$CONFIG_USB" != "n" ] +then + source drivers/uusbd/Config.in +fi +endmenu + mainmenu_option next_comment comment 'Sound' tristate 'Sound card support' CONFIG_SOUND diff -Naur linux.225/arch/sparc/config.in linux.225.visws/arch/sparc/config.in --- linux.225/arch/sparc/config.in Mon Mar 15 16:10:43 1999 +++ linux.225.visws/arch/sparc/config.in Thu Apr 15 17:51:21 1999 @@ -194,6 +194,20 @@ tristate 'Software watchdog' CONFIG_SOFT_WATCHDOG endmenu +# USB Support +# +# FIXME: the USB support should be at General Setup on _all_ archs, +# and the drivers scattered on their directories. + +mainmenu_option next_comment +comment 'Universal Serial Bus (USB)' +tristate 'USB Support' CONFIG_USB +if [ "$CONFIG_USB" != "n" ] +then + source drivers/uusbd/Config.in +fi +endmenu + mainmenu_option next_comment comment 'Kernel hacking' diff -Naur linux.225/arch/sparc64/config.in linux.225.visws/arch/sparc64/config.in --- linux.225/arch/sparc64/config.in Mon Mar 15 16:10:43 1999 +++ linux.225.visws/arch/sparc64/config.in Thu Apr 15 17:51:21 1999 @@ -245,6 +245,20 @@ tristate 'Software watchdog' CONFIG_SOFT_WATCHDOG endmenu +# USB Support +# +# FIXME: the USB support should be at General Setup on _all_ archs, +# and the drivers scattered on their directories. + +mainmenu_option next_comment +comment 'Universal Serial Bus (USB)' +tristate 'USB Support' CONFIG_USB +if [ "$CONFIG_USB" != "n" ] +then + source drivers/uusbd/Config.in +fi +endmenu + mainmenu_option next_comment comment 'Kernel hacking' diff -Naur linux.225/drivers/Makefile linux.225.visws/drivers/Makefile --- linux.225/drivers/Makefile Fri Nov 20 08:59:01 1998 +++ linux.225.visws/drivers/Makefile Thu Apr 15 17:51:21 1999 @@ -10,7 +10,7 @@ SUB_DIRS := block char net misc sound MOD_SUB_DIRS := $(SUB_DIRS) ALL_SUB_DIRS := $(SUB_DIRS) pci scsi sbus cdrom isdn pnp \ - macintosh video dio zorro fc4 + macintosh video dio zorro fc4 uusbd ifdef CONFIG_DIO SUB_DIRS += dio @@ -100,5 +100,16 @@ SUB_DIRS += net/hamradio MOD_SUB_DIRS += net/hamradio endif +# If CONFIG_USB is set, core USB support is compiled in, but we want +# to allow having stuff as modules. +ifeq ($(CONFIG_USB),y) +SUB_DIRS += uusbd +MOD_SUB_DIRS += uusbd +else + ifeq ($(CONFIG_USB),m) + MOD_SUB_DIRS += uusbd + endif +endif + include $(TOPDIR)/Rules.make diff -Naur linux.225/drivers/char/Makefile linux.225.visws/drivers/char/Makefile --- linux.225/drivers/char/Makefile Wed Mar 24 11:46:00 1999 +++ linux.225.visws/drivers/char/Makefile Fri Apr 16 10:12:03 1999 @@ -42,7 +42,7 @@ ifndef CONFIG_SUN_KEYBOARD ifdef CONFIG_VT -L_OBJS += keyboard.o +LX_OBJS += keyboard.o endif ifneq ($(ARCH),m68k) L_OBJS += pc_keyb.o defkeymap.o diff -Naur linux.225/drivers/char/keyboard.c linux.225.visws/drivers/char/keyboard.c --- linux.225/drivers/char/keyboard.c Fri Jan 8 11:11:45 1999 +++ linux.225.visws/drivers/char/keyboard.c Thu Apr 15 17:43:19 1999 @@ -24,6 +24,7 @@ */ #include +#include #include #include #include @@ -31,6 +32,7 @@ #include #include #include +#include #include #include @@ -71,35 +73,55 @@ } /* - * global state includes the following, and various static variables - * in this module: prev_scancode, shift_state, diacr, npadch, dead_key_next. - * (last_console is now a global variable) + * Per-keyboard state. + * At present all keyboards are connected to the current fg_console - + * this needs to be generalized a bit. */ +struct keyboard_state { + struct keyboard_state *next; + struct kbd_ll_operations *k_op; + void *devid; + ushort **key_maps; + struct kbd_struct *kbd; + struct tty_struct *tty; + int last_scancode; + struct timer_list repeat_timer; + int dead_key_next; + int shift_state; + int npadch; /* -1 or number assembled on pad */ +#ifdef CONFIG_MAGIC_SYSRQ + int sysrq_pressed; +#endif + char rep; /* flag telling character repeat */ + unsigned char diacr; + unsigned char k_down[NR_SHIFT]; /* shift state counters.. */ + unsigned long key_down[256/BITS_PER_LONG]; /* keyboard key bitmap */ +}; -/* shift state counters.. */ -static unsigned char k_down[NR_SHIFT] = {0, }; -/* keyboard key bitmap */ -static unsigned long key_down[256/BITS_PER_LONG] = { 0, }; +/* + * List of all keyboards (and a spinlock for it). + */ +static struct keyboard_state *all_kbds; +static spinlock_t all_kbds_lock = SPIN_LOCK_UNLOCKED; -static int dead_key_next = 0; /* * In order to retrieve the shift_state (for the mouse server), either * the variable must be global, or a new procedure must be created to * return the value. I chose the former way. + * This now reflects the shift_state of the last keyboard + * whose shift_state changed - paulus. */ int shift_state = 0; -static int npadch = -1; /* -1 or number assembled on pad */ -static unsigned char diacr = 0; -static char rep = 0; /* flag telling character repeat */ + struct kbd_struct kbd_table[MAX_NR_CONSOLES]; static struct tty_struct **ttytab; -static struct kbd_struct * kbd = kbd_table; -static struct tty_struct * tty = NULL; -void compute_shiftstate(void); +void kbd_compute_shiftstate(struct keyboard_state *); -typedef void (*k_hand)(unsigned char value, char up_flag); -typedef void (k_handfn)(unsigned char value, char up_flag); +typedef void (*k_hand)(struct keyboard_state *, unsigned char value, + char up_flag); +typedef void (k_handfn)(struct keyboard_state *, unsigned char value, + char up_flag); static k_handfn do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift, @@ -116,16 +138,17 @@ #define TYPES_ALLOWED_IN_RAW_MODE ((1 << KT_SPEC) | (1 << KT_SHIFT)) -typedef void (*void_fnp)(void); -typedef void (void_fn)(void); +typedef void (*void_fnp)(struct keyboard_state *); +typedef void (void_fn)(struct keyboard_state *); static void_fn do_null, enter, show_ptregs, send_intr, lastcons, caps_toggle, num, hold, scroll_forw, scroll_back, boot_it, caps_on, compose, - SAK, decr_console, incr_console, spawn_console, bare_num; + SAK, decr_console, incr_console, spawn_console, bare_num, + do_show_mem, do_show_state; static void_fnp spec_fn_table[] = { - do_null, enter, show_ptregs, show_mem, - show_state, send_intr, lastcons, caps_toggle, + do_null, enter, show_ptregs, do_show_mem, + do_show_state, send_intr, lastcons, caps_toggle, num, hold, scroll_forw, scroll_back, boot_it, caps_on, compose, SAK, decr_console, incr_console, spawn_console, bare_num @@ -143,33 +166,28 @@ const int NR_TYPES = SIZE(max_vals); -/* N.B. drivers/macintosh/mac_keyb.c needs to call put_queue */ -void put_queue(int); -static unsigned char handle_diacr(unsigned char); +static void put_queue(struct tty_struct *, int); +static unsigned char handle_diacr(struct keyboard_state *, unsigned char); /* kbd_pt_regs - set by keyboard_interrupt(), used by show_ptregs() */ struct pt_regs * kbd_pt_regs; -#ifdef CONFIG_MAGIC_SYSRQ -static int sysrq_pressed; -#endif - /* * Many other routines do put_queue, but I think either * they produce ASCII, or they produce some user-assigned * string, and in both cases we might assume that it is * in utf-8 already. */ -void to_utf8(ushort c) { +void to_utf8(struct tty_struct *tty, ushort c) { if (c < 0x80) - put_queue(c); /* 0******* */ + put_queue(tty, c); /* 0******* */ else if (c < 0x800) { - put_queue(0xc0 | (c >> 6)); /* 110***** 10****** */ - put_queue(0x80 | (c & 0x3f)); + put_queue(tty, 0xc0 | (c >> 6)); /* 110***** 10****** */ + put_queue(tty, 0x80 | (c & 0x3f)); } else { - put_queue(0xe0 | (c >> 12)); /* 1110**** 10****** 10****** */ - put_queue(0x80 | ((c >> 6) & 0x3f)); - put_queue(0x80 | (c & 0x3f)); + put_queue(tty, 0xe0 | (c >> 12)); /* 1110**** 10****** 10****** */ + put_queue(tty, 0x80 | ((c >> 6) & 0x3f)); + put_queue(tty, 0x80 | (c & 0x3f)); } /* UTF-8 is defined for words of up to 31 bits, but we need only 16 bits here */ @@ -178,29 +196,60 @@ /* * Translation of escaped scancodes to keycodes. * This is now user-settable (for machines were it makes sense). + * (XXX It doesn't make much sense with multiple keyboards :-() */ int setkeycode(unsigned int scancode, unsigned int keycode) { - return kbd_setkeycode(scancode, keycode); + struct keyboard_state *ks; + int err = 0; + + spin_lock(&all_kbds_lock); + for (ks = all_kbds; ks != NULL && err == 0; ks = ks->next) + if (ks->key_maps == key_maps) + err = ks->k_op->setkeycode(ks->devid, scancode, keycode); + spin_unlock(&all_kbds_lock); + return err; } +/* XXX and this makes even less sense... :-* */ int getkeycode(unsigned int scancode) { - return kbd_getkeycode(scancode); + struct keyboard_state *ks = all_kbds; + + if (ks == NULL) + return -ENODEV; + return ks->k_op->getkeycode(ks->devid, scancode); +} + +static void kbd_repeat(unsigned long devid) +{ + struct keyboard_state *ks = (struct keyboard_state *) devid; + unsigned long flags; + + save_flags(flags); + cli(); + kbd_handle_scancode((void *)ks, ks->last_scancode); + restore_flags(flags); } -void handle_scancode(unsigned char scancode) +void kbd_handle_scancode(void *kbdid, int scancode) { + struct keyboard_state *ks = (struct keyboard_state *) kbdid; unsigned char keycode; char up_flag; /* 0 or 0200 */ - char raw_mode; + char raw_mode, rep; + struct kbd_struct *kbd; + struct tty_struct *tty; do_poke_blanked_console = 1; mark_bh(CONSOLE_BH); add_keyboard_randomness(scancode); - tty = ttytab? ttytab[fg_console]: NULL; + del_timer(&ks->repeat_timer); + + ks->tty = tty = ttytab? ttytab[fg_console]: NULL; + ks->kbd = kbd = kbd_table + fg_console; if (tty && (!tty->driver_data)) { /* * We touch the tty structure via the the ttytab array @@ -211,53 +260,65 @@ */ tty = NULL; } - kbd = kbd_table + fg_console; + if ((raw_mode = (kbd->kbdmode == VC_RAW))) { - put_queue(scancode); + put_queue(tty, scancode); /* we do not return yet, because we want to maintain the key_down array, so that we have the correct values when finishing RAW mode or when changing VT's */ } - if (!kbd_pretranslate(scancode, raw_mode)) - return; + if (!ks->k_op->pretranslate(ks->devid, scancode, raw_mode)) + return; + /* * Convert scancode to keycode */ up_flag = (scancode & 0200); scancode &= 0x7f; - if (!kbd_translate(scancode, &keycode, raw_mode)) - return; + if (!ks->k_op->translate(ks->devid, scancode, &keycode, raw_mode)) + return; /* * At this point the variable `keycode' contains the keycode. - * Note: the keycode must not be 0 (++Geert: on m68k 0 is valid). * We keep track of the up/down status of the key, and * return the keycode if in MEDIUMRAW mode. */ if (up_flag) { rep = 0; - if(!test_and_clear_bit(keycode, key_down)) - up_flag = kbd_unexpected_up(keycode); + if (!test_and_clear_bit(keycode, ks->key_down)) + up_flag = ks->k_op->unexpected_up(ks->devid, keycode); } else - rep = test_and_set_bit(keycode, key_down); + rep = test_and_set_bit(keycode, ks->key_down); + ks->rep = rep; + + if (!raw_mode && !up_flag + && ks->k_op->dont_repeat && !ks->k_op->dont_repeat[keycode]) { + ks->last_scancode = scancode; + ks->repeat_timer.function = kbd_repeat; + ks->repeat_timer.data = (unsigned long) ks; + ks->repeat_timer.expires = jiffies + + (rep? ks->k_op->repeat_delay: ks->k_op->repeat_initial); + add_timer(&ks->repeat_timer); + } #ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */ - if (keycode == SYSRQ_KEY) { - sysrq_pressed = !up_flag; + if (keycode == ks->k_op->sysrq_key) { + ks->sysrq_pressed = !up_flag; return; - } else if (sysrq_pressed) { + } else if (ks->sysrq_pressed) { if (!up_flag) - handle_sysrq(kbd_sysrq_xlate[keycode], kbd_pt_regs, kbd, tty); + handle_sysrq(ks->k_op->sysrq_xlate[keycode], + kbd_pt_regs, kbd, tty); return; } #endif if (kbd->kbdmode == VC_MEDIUMRAW) { /* soon keycodes will require more than one byte */ - put_queue(keycode + up_flag); + put_queue(tty, keycode + up_flag); raw_mode = 1; /* Most key classes will be ignored */ } @@ -281,8 +342,8 @@ u_char type; /* the XOR below used to be an OR */ - int shift_final = shift_state ^ kbd->lockstate ^ kbd->slockstate; - ushort *key_map = key_maps[shift_final]; + int shift_final = ks->shift_state ^ kbd->lockstate ^ kbd->slockstate; + ushort *key_map = ks->key_maps[shift_final]; if (key_map != NULL) { keysym = key_map[keycode]; @@ -295,36 +356,36 @@ if (type == KT_LETTER) { type = KT_LATIN; if (vc_kbd_led(kbd, VC_CAPSLOCK)) { - key_map = key_maps[shift_final ^ (1<key_maps[shift_final ^ (1<slockstate = 0; } else { /* maybe only if (kbd->kbdmode == VC_UNICODE) ? */ if (!up_flag && !raw_mode) - to_utf8(keysym); + to_utf8(tty, keysym); } } else { /* maybe beep? */ /* we have at least to update shift_state */ #if 1 /* how? two almost equivalent choices follow */ - compute_shiftstate(); + kbd_compute_shiftstate(ks); #else - keysym = U(plain_map[keycode]); + keysym = U(ks->key_maps[0][keycode]); type = KTYP(keysym); if (type == KT_SHIFT) - (*key_handler[type])(keysym & 0xff, up_flag); + (*key_handler[type])(ks, keysym & 0xff, up_flag); #endif } } } -void put_queue(int ch) +static void put_queue(struct tty_struct *tty, int ch) { wake_up(&keypress_wait); if (tty) { @@ -333,7 +394,7 @@ } } -static void puts_queue(char *cp) +static void puts_queue(struct tty_struct *tty, char *cp) { wake_up(&keypress_wait); if (!tty) @@ -346,49 +407,61 @@ con_schedule_flip(tty); } -static void applkey(int key, char mode) +static void applkey(struct tty_struct *tty, int key, char mode) { static char buf[] = { 0x1b, 'O', 0x00, 0x00 }; buf[1] = (mode ? 'O' : '['); buf[2] = key; - puts_queue(buf); + puts_queue(tty, buf); } -static void enter(void) +static void enter(struct keyboard_state *ks) { - if (diacr) { - put_queue(diacr); - diacr = 0; + if (ks->diacr) { + put_queue(ks->tty, ks->diacr); + ks->diacr = 0; } - put_queue(13); - if (vc_kbd_mode(kbd,VC_CRLF)) - put_queue(10); + put_queue(ks->tty, 13); + if (vc_kbd_mode(ks->kbd, VC_CRLF)) + put_queue(ks->tty, 10); } -static void caps_toggle(void) +static void caps_toggle(struct keyboard_state *ks) { - if (rep) + if (ks->rep) return; - chg_vc_kbd_led(kbd, VC_CAPSLOCK); + chg_vc_kbd_led(ks->kbd, VC_CAPSLOCK); } -static void caps_on(void) +static void caps_on(struct keyboard_state *ks) { - if (rep) + if (ks->rep) return; - set_vc_kbd_led(kbd, VC_CAPSLOCK); + set_vc_kbd_led(ks->kbd, VC_CAPSLOCK); } -static void show_ptregs(void) +static void show_ptregs(struct keyboard_state *ks) { if (kbd_pt_regs) show_regs(kbd_pt_regs); } -static void hold(void) +static void do_show_mem(struct keyboard_state *ks) +{ + show_mem(); +} + +static void do_show_state(struct keyboard_state *ks) { - if (rep || !tty) + show_state(); +} + +static void hold(struct keyboard_state *ks) +{ + struct tty_struct *tty = ks->tty; + + if (ks->rep || !tty) return; /* @@ -402,12 +475,12 @@ stop_tty(tty); } -static void num(void) +static void num(struct keyboard_state *ks) { - if (vc_kbd_mode(kbd,VC_APPLIC)) - applkey('P', 1); + if (vc_kbd_mode(ks->kbd, VC_APPLIC)) + applkey(ks->tty, 'P', 1); else - bare_num(); + bare_num(ks); } /* @@ -416,19 +489,19 @@ * Bind this to NumLock if you prefer that the NumLock key always * changes the NumLock flag. */ -static void bare_num(void) +static void bare_num(struct keyboard_state *ks) { - if (!rep) - chg_vc_kbd_led(kbd,VC_NUMLOCK); + if (!ks->rep) + chg_vc_kbd_led(ks->kbd, VC_NUMLOCK); } -static void lastcons(void) +static void lastcons(struct keyboard_state *ks) { /* switch to the last used console, ChN */ set_console(last_console); } -static void decr_console(void) +static void decr_console(struct keyboard_state *ks) { int i; @@ -441,7 +514,7 @@ set_console(i); } -static void incr_console(void) +static void incr_console(struct keyboard_state *ks) { int i; @@ -454,45 +527,49 @@ set_console(i); } -static void send_intr(void) +static void send_intr(struct keyboard_state *ks) { + struct tty_struct *tty = ks->tty; + if (!tty) return; tty_insert_flip_char(tty, 0, TTY_BREAK); con_schedule_flip(tty); } -static void scroll_forw(void) +static void scroll_forw(struct keyboard_state *ks) { scrollfront(0); } -static void scroll_back(void) +static void scroll_back(struct keyboard_state *ks) { scrollback(0); } -static void boot_it(void) +static void boot_it(struct keyboard_state *ks) { ctrl_alt_del(); } -static void compose(void) +static void compose(struct keyboard_state *ks) { - dead_key_next = 1; + ks->dead_key_next = 1; } int spawnpid, spawnsig; -static void spawn_console(void) +static void spawn_console(struct keyboard_state *ks) { if (spawnpid) if(kill_proc(spawnpid, spawnsig, 1)) spawnpid = 0; } -static void SAK(void) +static void SAK(struct keyboard_state *ks) { + struct tty_struct *tty = ks->tty; + /* * SAK should also work in all raw modes and reset * them properly. @@ -505,17 +582,19 @@ #endif } -static void do_ignore(unsigned char value, char up_flag) +static void do_ignore(struct keyboard_state *ks, unsigned char value, char up_flag) { } -static void do_null() +static void do_null(struct keyboard_state *ks) { - compute_shiftstate(); + kbd_compute_shiftstate(ks); } -static void do_spec(unsigned char value, char up_flag) +static void do_spec(struct keyboard_state *ks, unsigned char value, char up_flag) { + struct kbd_struct *kbd = ks->kbd; + if (up_flag) return; if (value >= SIZE(spec_fn_table)) @@ -523,29 +602,29 @@ if ((kbd->kbdmode == VC_RAW || kbd->kbdmode == VC_MEDIUMRAW) && !(SPECIALS_ALLOWED_IN_RAW_MODE & (1 << value))) return; - spec_fn_table[value](); + spec_fn_table[value](ks); } -static void do_lowercase(unsigned char value, char up_flag) +static void do_lowercase(struct keyboard_state *ks, unsigned char value, char up_flag) { printk(KERN_ERR "keyboard.c: do_lowercase was called - impossible\n"); } -static void do_self(unsigned char value, char up_flag) +static void do_self(struct keyboard_state *ks, unsigned char value, char up_flag) { if (up_flag) return; /* no action, if this is a key release */ - if (diacr) - value = handle_diacr(value); + if (ks->diacr) + value = handle_diacr(ks, value); - if (dead_key_next) { - dead_key_next = 0; - diacr = value; + if (ks->dead_key_next) { + ks->dead_key_next = 0; + ks->diacr = value; return; } - put_queue(value); + put_queue(ks->tty, value); } #define A_GRAVE '`' @@ -558,10 +637,10 @@ {A_GRAVE, A_ACUTE, A_CFLEX, A_TILDE, A_DIAER, A_CEDIL }; /* Obsolete - for backwards compatibility only */ -static void do_dead(unsigned char value, char up_flag) +static void do_dead(struct keyboard_state *ks, unsigned char value, char up_flag) { value = ret_diacr[value]; - do_dead2(value,up_flag); + do_dead2(ks, value, up_flag); } /* @@ -569,12 +648,12 @@ * dead keys modifying the same character. Very useful * for Vietnamese. */ -static void do_dead2(unsigned char value, char up_flag) +static void do_dead2(struct keyboard_state *ks, unsigned char value, char up_flag) { if (up_flag) return; - diacr = (diacr ? handle_diacr(value) : value); + ks->diacr = (ks->diacr ? handle_diacr(ks, value) : value); } @@ -585,12 +664,12 @@ * Otherwise, conclude that DIACR was not combining after all, * queue it and return CH. */ -unsigned char handle_diacr(unsigned char ch) +unsigned char handle_diacr(struct keyboard_state *ks, unsigned char ch) { - int d = diacr; + int d = ks->diacr; int i; - diacr = 0; + ks->diacr = 0; for (i = 0; i < accent_table_size; i++) { if (accent_table[i].diacr == d && accent_table[i].base == ch) @@ -600,30 +679,31 @@ if (ch == ' ' || ch == d) return d; - put_queue(d); + put_queue(ks->tty, d); return ch; } -static void do_cons(unsigned char value, char up_flag) +static void do_cons(struct keyboard_state *ks, unsigned char value, char up_flag) { if (up_flag) return; set_console(value); } -static void do_fn(unsigned char value, char up_flag) +static void do_fn(struct keyboard_state *ks, unsigned char value, char up_flag) { if (up_flag) return; if (value < SIZE(func_table)) { if (func_table[value]) - puts_queue(func_table[value]); + puts_queue(ks->tty, func_table[value]); } else printk(KERN_ERR "do_fn called with value=%d\n", value); } -static void do_pad(unsigned char value, char up_flag) +static void do_pad(struct keyboard_state *ks, unsigned char value, char up_flag) { + struct kbd_struct *kbd = ks->kbd; static const char *pad_chars = "0123456789+-*/\015,.?()"; static const char *app_map = "pqrstuvwxylSRQMnnmPQ"; @@ -631,8 +711,8 @@ return; /* no action, if this is a key release */ /* kludge... shift forces cursor/number keys */ - if (vc_kbd_mode(kbd,VC_APPLIC) && !k_down[KG_SHIFT]) { - applkey(app_map[value], 1); + if (vc_kbd_mode(kbd,VC_APPLIC) && !ks->k_down[KG_SHIFT]) { + applkey(ks->tty, app_map[value], 1); return; } @@ -640,59 +720,60 @@ switch (value) { case KVAL(K_PCOMMA): case KVAL(K_PDOT): - do_fn(KVAL(K_REMOVE), 0); + do_fn(ks, KVAL(K_REMOVE), 0); return; case KVAL(K_P0): - do_fn(KVAL(K_INSERT), 0); + do_fn(ks, KVAL(K_INSERT), 0); return; case KVAL(K_P1): - do_fn(KVAL(K_SELECT), 0); + do_fn(ks, KVAL(K_SELECT), 0); return; case KVAL(K_P2): - do_cur(KVAL(K_DOWN), 0); + do_cur(ks, KVAL(K_DOWN), 0); return; case KVAL(K_P3): - do_fn(KVAL(K_PGDN), 0); + do_fn(ks, KVAL(K_PGDN), 0); return; case KVAL(K_P4): - do_cur(KVAL(K_LEFT), 0); + do_cur(ks, KVAL(K_LEFT), 0); return; case KVAL(K_P6): - do_cur(KVAL(K_RIGHT), 0); + do_cur(ks, KVAL(K_RIGHT), 0); return; case KVAL(K_P7): - do_fn(KVAL(K_FIND), 0); + do_fn(ks, KVAL(K_FIND), 0); return; case KVAL(K_P8): - do_cur(KVAL(K_UP), 0); + do_cur(ks, KVAL(K_UP), 0); return; case KVAL(K_P9): - do_fn(KVAL(K_PGUP), 0); + do_fn(ks, KVAL(K_PGUP), 0); return; case KVAL(K_P5): - applkey('G', vc_kbd_mode(kbd, VC_APPLIC)); + applkey(ks->tty, 'G', vc_kbd_mode(kbd, VC_APPLIC)); return; } - put_queue(pad_chars[value]); + put_queue(ks->tty, pad_chars[value]); if (value == KVAL(K_PENTER) && vc_kbd_mode(kbd, VC_CRLF)) - put_queue(10); + put_queue(ks->tty, 10); } -static void do_cur(unsigned char value, char up_flag) +static void do_cur(struct keyboard_state *ks, unsigned char value, char up_flag) { static const char *cur_chars = "BDCA"; if (up_flag) return; - applkey(cur_chars[value], vc_kbd_mode(kbd,VC_CKMODE)); + applkey(ks->tty, cur_chars[value], vc_kbd_mode(ks->kbd,VC_CKMODE)); } -static void do_shift(unsigned char value, char up_flag) +static void do_shift(struct keyboard_state *ks, unsigned char value, char up_flag) { - int old_state = shift_state; + struct kbd_struct *kbd = ks->kbd; + int old_state = ks->shift_state; - if (rep) + if (ks->rep) return; /* Mimic typewriter: @@ -706,23 +787,23 @@ if (up_flag) { /* handle the case that two shift or control keys are depressed simultaneously */ - if (k_down[value]) - k_down[value]--; + if (ks->k_down[value]) + ks->k_down[value]--; } else - k_down[value]++; + ks->k_down[value]++; - if (k_down[value]) - shift_state |= (1 << value); + if (ks->k_down[value]) + ks->shift_state |= (1 << value); else - shift_state &= ~ (1 << value); + ks->shift_state &= ~ (1 << value); /* kludge */ - if (up_flag && shift_state != old_state && npadch != -1) { + if (up_flag && ks->shift_state != old_state && ks->npadch != -1) { if (kbd->kbdmode == VC_UNICODE) - to_utf8(npadch & 0xffff); + to_utf8(ks->tty, ks->npadch & 0xffff); else - put_queue(npadch & 0xff); - npadch = -1; + put_queue(ks->tty, ks->npadch & 0xff); + ks->npadch = -1; } } @@ -731,42 +812,55 @@ /* maybe called when keymap is undefined, so that shiftkey release is seen */ void compute_shiftstate(void) { + struct keyboard_state *ks; + + spin_lock(&all_kbds_lock); + for (ks = all_kbds; ks != NULL; ks = ks->next) + kbd_compute_shiftstate(ks); + spin_unlock(&all_kbds_lock); +} + +void kbd_compute_shiftstate(struct keyboard_state *ks) +{ int i, j, k, sym, val; - shift_state = 0; - for(i=0; i < SIZE(k_down); i++) - k_down[i] = 0; - - for(i=0; i < SIZE(key_down); i++) - if(key_down[i]) { /* skip this word if not a single bit on */ - k = i*BITS_PER_LONG; - for(j=0; jshift_state = 0; + for (i = 0; i < SIZE(ks->k_down); i++) + ks->k_down[i] = 0; + + for (i = 0; i < SIZE(ks->key_down); i++) { + if (ks->key_down[i] == 0) + continue; /* skip this word if not a single bit on */ + k = i * BITS_PER_LONG; + for (j = 0; j < BITS_PER_LONG; j++, k++) { + if (test_bit(k, ks->key_down) == 0) + continue; + sym = U(ks->key_maps[0][k]); + if (KTYP(sym) == KT_SHIFT) { + val = KVAL(sym); + if (val == KVAL(K_CAPSSHIFT)) + val = KVAL(K_SHIFT); + ks->k_down[val]++; + ks->shift_state |= (1<shift_state; /* XXX */ } -static void do_meta(unsigned char value, char up_flag) +static void do_meta(struct keyboard_state *ks, unsigned char value, char up_flag) { if (up_flag) return; - if (vc_kbd_mode(kbd, VC_META)) { - put_queue('\033'); - put_queue(value); + if (vc_kbd_mode(ks->kbd, VC_META)) { + put_queue(ks->tty, '\033'); + put_queue(ks->tty, value); } else - put_queue(value | 0x80); + put_queue(ks->tty, value | 0x80); } -static void do_ascii(unsigned char value, char up_flag) +static void do_ascii(struct keyboard_state *ks, unsigned char value, char up_flag) { int base; @@ -774,30 +868,30 @@ return; if (value < 10) /* decimal input of code, while Alt depressed */ - base = 10; + base = 10; else { /* hexadecimal input of code, while AltGr depressed */ - value -= 10; - base = 16; + value -= 10; + base = 16; } - if (npadch == -1) - npadch = value; + if (ks->npadch == -1) + ks->npadch = value; else - npadch = npadch * base + value; + ks->npadch = ks->npadch * base + value; } -static void do_lock(unsigned char value, char up_flag) +static void do_lock(struct keyboard_state *ks, unsigned char value, char up_flag) { - if (up_flag || rep) + if (up_flag || ks->rep) return; - chg_vc_kbd_lock(kbd, value); + chg_vc_kbd_lock(ks->kbd, value); } -static void do_slock(unsigned char value, char up_flag) +static void do_slock(struct keyboard_state *ks, unsigned char value, char up_flag) { - if (up_flag || rep) + if (up_flag || ks->rep) return; - chg_vc_kbd_slock(kbd, value); + chg_vc_kbd_slock(ks->kbd, value); } /* @@ -886,13 +980,74 @@ static void kbd_bh(void) { unsigned char leds = getleds(); + struct keyboard_state *ks; if (leds != ledstate) { ledstate = leds; - kbd_leds(leds); + spin_lock(&all_kbds_lock); + for (ks = all_kbds; ks != NULL; ks = ks->next) + ks->k_op->leds(ks, leds); + spin_unlock(&all_kbds_lock); } } +#ifndef NEW_STYLE_KEYBOARD +int oldkbd_setkeycode(void *devid, unsigned int scancode, unsigned int keycode) +{ + return kbd_setkeycode(scancode, keycode); +} + +int oldkbd_getkeycode(void *devid, unsigned int scancode) +{ + return kbd_getkeycode(scancode); +} + +int oldkbd_pretranslate(void *devid, unsigned char scancode, char raw_mode) +{ + return kbd_pretranslate(scancode, raw_mode); +} + +int oldkbd_translate(void *devid, unsigned char scancode, + unsigned char *keycode, char raw_mode) +{ + return kbd_translate(scancode, keycode, raw_mode); +} + +int oldkbd_unexpected_up(void *devid, unsigned char keycode) +{ + return kbd_unexpected_up(keycode); +} + +void oldkbd_leds(void *devid, unsigned char leds) +{ + return kbd_leds(leds); +} + +struct kbd_ll_operations oldkbd_operations = { + oldkbd_setkeycode, + oldkbd_getkeycode, + oldkbd_pretranslate, + oldkbd_translate, + oldkbd_unexpected_up, + oldkbd_leds, +#ifdef CONFIG_MAGIC_SYSRQ + SYSRQ_KEY, + kbd_sysrq_xlate, +#else + -1, NULL, +#endif + 0, 0, NULL +}; + +void *old_kbdid; + +void handle_scancode(unsigned char scancode) +{ + if (old_kbdid) + kbd_handle_scancode(old_kbdid, scancode); +} +#endif /* NEW_STYLE_KEYBOARD */ + __initfunc(int kbd_init(void)) { int i; @@ -912,7 +1067,58 @@ ttytab = console_driver.table; kbd_init_hw(); + +#ifndef NEW_STYLE_KEYBOARD + old_kbdid = register_keyboard(oldkbd_operations, NULL, key_maps); +#endif /* NEW_STYLE_KEYBOARD */ + init_bh(KEYBOARD_BH, kbd_bh); mark_bh(KEYBOARD_BH); return 0; } + +void *register_keyboard(struct kbd_ll_operations *ops, void *devid, + ushort **kmaps) +{ + struct keyboard_state *ks, **ksp; + + ks = (struct keyboard_state *) kmalloc(sizeof(*ks), GFP_KERNEL); + if (ks == 0) + return NULL; + memset(ks, 0, sizeof(*ks)); + + ks->next = NULL; + ks->k_op = ops; + ks->devid = devid; + ks->key_maps = kmaps; + ks->npadch = -1; + + if (all_kbds == NULL && kmaps != key_maps) + memcpy(key_maps, kmaps, sizeof(key_maps)); + + spin_lock(&all_kbds_lock); + for (ksp = &all_kbds; *ksp != NULL; ksp = &(*ksp)->next) + ; + *ksp = ks; + spin_unlock(&all_kbds_lock); + + return (void *) ks; +} + +void unregister_keyboard(void *kbdid) +{ + struct keyboard_state **ksp; + + spin_lock(&all_kbds_lock); + for (ksp = &all_kbds; *ksp != NULL; ksp = &(*ksp)->next) { + if (*ksp == kbdid) { + *ksp = (*ksp)->next; + kfree(kbdid); + break; + } + } +} + +EXPORT_SYMBOL(register_keyboard); +EXPORT_SYMBOL(unregister_keyboard); +EXPORT_SYMBOL(kbd_handle_scancode); diff -Naur linux.225/drivers/char/pc_keyb.c linux.225.visws/drivers/char/pc_keyb.c --- linux.225/drivers/char/pc_keyb.c Sun Feb 7 00:23:04 1999 +++ linux.225.visws/drivers/char/pc_keyb.c Thu Apr 15 17:43:19 1999 @@ -15,6 +15,10 @@ * */ +/* Uncomment this if you have keyboard in ps/2 port, not mouse */ + +/*#define KEYBOARD_IN_PSAUX*/ + #include #include @@ -27,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -55,6 +60,8 @@ "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */ "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */ "\r\000/"; /* 0x60 - 0x6f */ +#else +#define pckbd_sysrq_xlate NULL #endif static void kbd_write(int address, int data); @@ -91,6 +98,30 @@ #endif /* CONFIG_PSMOUSE */ +extern int pckbd_setkeycode(void *, unsigned int scancode, + unsigned int keycode); +extern int pckbd_getkeycode(void *, unsigned int scancode); +extern int pckbd_pretranslate(void *, unsigned char scancode, char raw_mode); +extern int pckbd_translate(void *, unsigned char scancode, + unsigned char *keycode, char raw_mode); +extern char pckbd_unexpected_up(void *, unsigned char keycode); +extern void pckbd_leds(void *, unsigned char leds); +#define SYSRQ_KEY 0x54 + +struct kbd_ll_operations pckbd_operations = { + pckbd_setkeycode, + pckbd_getkeycode, + pckbd_pretranslate, + pckbd_translate, + pckbd_unexpected_up, + pckbd_leds, + SYSRQ_KEY, + pckbd_sysrq_xlate, + 0, 0, NULL +}; + +static void *pckbd_id; + /* * Wait for keyboard controller input buffer to drain. * @@ -242,7 +273,7 @@ static unsigned int prev_scancode = 0; /* remember E0, E1 */ -int pckbd_setkeycode(unsigned int scancode, unsigned int keycode) +int pckbd_setkeycode(void *devid, unsigned int scancode, unsigned int keycode) { if (scancode < SC_LIM || scancode > 255 || keycode > 127) return -EINVAL; @@ -253,7 +284,7 @@ return 0; } -int pckbd_getkeycode(unsigned int scancode) +int pckbd_getkeycode(void *devid, unsigned int scancode) { return (scancode < SC_LIM || scancode > 255) ? -EINVAL : @@ -294,7 +325,7 @@ return 1; } -int pckbd_pretranslate(unsigned char scancode, char raw_mode) +int pckbd_pretranslate(void *devid, unsigned char scancode, char raw_mode) { if (scancode == 0xff) { /* in scancode mode 1, my ESC key generates 0xff */ @@ -316,8 +347,8 @@ return 1; } -int pckbd_translate(unsigned char scancode, unsigned char *keycode, - char raw_mode) +int pckbd_translate(void *devid, unsigned char scancode, + unsigned char *keycode, char raw_mode) { if (prev_scancode) { /* @@ -395,7 +426,7 @@ return 1; } -char pckbd_unexpected_up(unsigned char keycode) +char pckbd_unexpected_up(void *devid, unsigned char keycode) { /* unexpected, but this can happen: maybe this was a key release for a FOCUS 9000 PF key; if we want to see it, we have to clear up_flag */ @@ -416,6 +447,9 @@ mouse_reply_expected = 0; } +#ifdef KEYBOARD_IN_PSAUX + handle_strangecode (scancode); +#else add_mouse_randomness(scancode); if (aux_count) { int head = queue->head; @@ -430,7 +464,54 @@ } } #endif +#endif +} + +#ifdef KEYBOARD_IN_PSAUX +static void *psaux_id; + +static char strange_xlat[ 256 ] = { +/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ +/* 0 */ 0x00,0x43,0x00,0x3f,0x3d,0x3b,0x3c,0x58,0x00,0x44,0x42,0x40,0x3e,0x0f,0x29,0x00, +/* 1 */ 0x00, 56,0x2a,0x00, 29,0x10,0x02,0x00,0x00,0x00,0x2c,0x1f,0x1e,0x11,0x03,0x00, +/* 2 */ 0x00,0x2e,0x2d,0x20,0x12,0x05,0x04,0x00,0x00, 57,0x2f,0x21,0x14,0x13,0x06,0x00, +/* 3 */ 0x00,0x31,0x30,0x23,0x22,0x15,0x07,0x00,0x00,0x00,0x32,0x24,0x16,0x08,0x09,0x00, +/* 4 */ 0x00,0x33,0x25,0x17,0x18,0x0b,0x0a,0x00,0x00,0x34,0x35,0x26,0x27,0x19,0x0c,0x00, +/* 5 */ 0x00,0x00,0x28,0x00,0x1a,0x0d,0x00,0x00,0x3a,0x36,0x1c,0x1b,0x00,0x2b,0x00,0x00, +/* 6 */ 0x00,0x00,0x00,0x00,0x00,0x00, 14,0x00,0x00,0x4f,0x00,0x4b,0x47,0x00,0x00,0x00, +/* 7 */ 0x52,0x53,0x50,0x00,0x4d,0x48,0x01,0x00,0x57,0x00,0x51,0x00,0x37,0x49,0x46,0x00, +/* 8 */ 0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* 9 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* a */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* b */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* c */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* d */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* e */ 0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* f */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +}; + +static void handle_strangecode(int c) +{ + static int or = 0, i; + + switch (c) { + case 0xf0: + or = 0x80; + return; + } + + i = strange_xlat[c]; + if (!i) + printk( "Unknown strangecode %x\n", c ); +#if 0 + else + printk( "Known strangecode %x = %x\n", c, i ); +#endif + kbd_handle_scancode( psaux_id, i|or ); + or = 0; } +#endif + /* * This reads the keyboard status port, and does the @@ -452,7 +533,7 @@ handle_mouse_event(scancode); } else { if (do_acknowledge(scancode)) - handle_scancode(scancode); + kbd_handle_scancode(pckbd_id, scancode); mark_bh(KEYBOARD_BH); } @@ -512,7 +593,7 @@ return 0; } -void pckbd_leds(unsigned char leds) +void pckbd_leds(void *devid, unsigned char leds) { if (!send_data(KBD_CMD_SET_LEDS) || !send_data(leds)) send_data(KBD_CMD_ENABLE); /* re-enable kbd if any errors */ @@ -724,6 +805,10 @@ /* Ok, finally allocate the IRQ, and off we go.. */ request_irq(KEYBOARD_IRQ, keyboard_interrupt, 0, "keyboard", NULL); + + pckbd_id = register_keyboard(&pckbd_operations, NULL, key_maps); + if (pckbd_id == NULL) + printk(KERN_ERR "Couldn't register PC keyboard!\n"); } #if defined CONFIG_PSMOUSE @@ -859,7 +944,7 @@ return 0; } queue->head = queue->tail = 0; /* Flush input queue */ - if (request_irq(AUX_IRQ, keyboard_interrupt, SA_SHIRQ, "PS/2 Mouse", AUX_DEV)) { + if (request_irq(AUX_IRQ, keyboard_interrupt, SA_SHIRQ, "PS/2 Auxiliary", AUX_DEV)) { aux_count--; return -EBUSY; } @@ -992,6 +1077,12 @@ kbd_write(KBD_CNTL_REG, KBD_CCMD_MOUSE_DISABLE); /* Disable aux device. */ kbd_write_cmd(AUX_INTS_OFF); /* Disable controller ints. */ +#ifdef KEYBOARD_IN_PSAUX + open_aux(NULL, NULL); + psaux_id = register_keyboard(&pckbd_operations, NULL, key_maps); + if (psaux_id == NULL) + printk(KERN_ERR "Couldn't register keyboard in PS/2 mouse port!\n"); +#endif return 0; } diff -Naur linux.225/drivers/uusbd/ANNOUNCE linux.225.visws/drivers/uusbd/ANNOUNCE --- linux.225/drivers/uusbd/ANNOUNCE Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/ANNOUNCE Sun Apr 4 18:46:26 1999 @@ -0,0 +1,131 @@ + + Hi! + + This is the 19990405 release of the UUSBD. + + Long time to have it, but this brings a lot of changes and +enhancements, and more are to come. + + I wanted to comment on the messages we've been seeing on the +mailing list lately about difficulty and how slow is development and +etc, etc, etc ... as I don't know enough english as to express it, +I'll do it in Spanish: + + Estoy hasta la puntal ciruelo de que la peña que más + se queja sea la que menos se moja el culo a la hora de + colaborar, así que me empezaré a pasar por el arco del triunfo + a todo capullei que siga dando la vara sin contribuir, porque + es que me raya mazo; al menos que se lean la puta + documentación. Al que no le mole, que curre para que mejore, + que de esto al final chupamos todos. + + Having said this, I'm more relaxed and can think more +carefully :). I've added a sort note at the README on how to start +reading the USB source. Not too much, but it's a readme file, right? + + And on the complex code, well, as I commented someone, once +you understand destructors (easy if you've done 'serious' C++/OO +sometime) and that when a usecount of zero is reached it is +automatically fired, or that you can use it to destroy a used +structure, it's easy to follow. + + Anyway, I plan some simplifications, one of them as suggested +by Linus. I thought of it but didn't want to change it as it was +working; now that the general feeling prefers things more simple, I'll +do it. I also plan to (someday) modify the UHCI driver to follow +Linus' design. It's much simpler ... I don't know why I rejected that +idea last summer. + + I've been working all the time on UHCI, so I had no time to +keep on with HID. When? I dunno, I really want it. The parser is +complicated and it's challenging me more as time goes by. + + So, let's go with a change summary: + + - Added ability to disable dynamic load on demand of drivers + (at config time); instead you have to load all drivers at + the very beginning and then unload them. This way they are + registered, and uusbd won't try to find any other + different. + + This is only really useful if you want to get rid of those + 'modprobe: can't locate module usb-VVVV.IIII.CC.SS.PP' + messages. + + - Added hacky support for the Genius EasyPen tablet, in boot + protocol mode. + + - Trimmed logs in source files, trying to reduce overall + package size. + + - Modified the ts_usb_pipe structure. The transaction list has + gone to the endpoint structure, and the host pointer is away + for ever. The endpoint now keeps a list of the transactions + queued for it and the descriptors open to it. + + Note that now the ts_usb_pipe, as member of a list, has a + ts_snode and a destructor (which is automagically set at + usb_pipe_endp_set()), so, when using it in another structure + (statically, not as a pointer) ts_snode_ref() it, to evitate + it's destruction (see it at ts_usb_device and + ts_usb_device_nozero()). + + The descriptors list at the endpoint could seem complicate, + and perhaps it may go away in the future; Linus' suggestion + was just to mark the device as 'unreachable', unregister it + from everywhere and keep going until all references are + gone. This way there's not much need for the list. + + Anyway, there is the foundation for shared endpoints. Now + you can open multiple pipes to the same endpoint. I have to + add code to be able to open one exclusively. + + - The usb_pipe_*() functions have been simplified and it's + semantics changed, so that the stupid step of going trough + addresses lookup is gone, as we almost always had the + pointer available directly before calling. + + - The transaction list has been reworked to make sense, using + a linear order which is much easier to track and maintain. + + - khubdd has been renamed to kusbdd, because it was doing more + then hub managing ... esthetical. + + - Now you can unload a module even if there are devices + plugged in. You have to start by the drivers, but it + works. Only when some file is opened by a process into a + driver (eg. gpm), as normal, the module is not unloadable. + + - Solved some clashes between the UHCI and OHCI modules + (static symbols are good :), but they still clash and cannot + be loaded at the same time [or the box freezes]. Even two + OHCI controllers clash when using the same module as driver. + + - Fixed to allow compilation with CONFIG_PCI undefined + ... though quite useles now ... + + - Catched why UHCI was loosing packets [and thus mice and kbd + where flaky]. It's related to incorrect synchronization of + the data toggle. Solved using a fast hack, but have to + rework part of the scheduling code to have that finely + tuned. + + Still I cannot plug devices trough hubs to UHCI controllers, + they don't work [CRC/Timeout error]. Should verify the + cables ... and the sw. + + Also modified the UHCI code so that cou can remove a + transaction from the transaction list from its callback + function. Thanks! + + So, that's all folks. Tomorrow I have full day with PSpice +simulating little stupid digital circuits, and perhaps this week I'll +have to fly again to the little Mountain View at the SV, so I don't +know how much will advance, and where, but I'd like to push HID a wee +bit. + + BTW, for those who still didn't notice, when I said 'boycott +him [to Linus]' I was kidding, ironizing, etc ... is fun :), and what +the fuck? Ain't I free enough as to ask it if I wished? + + Have a nice night ... I'll try to :) diff -Naur linux.225/drivers/uusbd/BUG-REPORTING linux.225.visws/drivers/uusbd/BUG-REPORTING --- linux.225/drivers/uusbd/BUG-REPORTING Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/BUG-REPORTING Mon Dec 7 06:20:50 1998 @@ -0,0 +1,63 @@ + + Bugs? any? are you sure? really, really, _really_ sure? Ok, I +believe you :). Did you brush your teeth? HAVE YOU CHECKED THE KERNEL +VERSION IS OK? [visit the INSTALL file to see which kversion I'm using +to develop]; modutils version is also ok to the kernel? + + REMEMBER: NON-SMP KERNELS. SMP WILL FAIL. + + Fine, so you've found a bug [no, you ain't the only one :)], +please follow these guidelines and do a bug report [e-mail is +recommended, but if you wan't to do the report via post-card, you're +free]. + + Sooo ... when reporting bugs or whatever [I welcome every +class of report, if it worked or not], please send me: + + - version of the UUSBD driver you are using + + - kernel version (`uname -a') + + - kernel configuration (linux/.config) + + - compiler you're using [gcc | egcs + versions] + + - the kernel logs + + The best way to get'em is to redirect kernel (all levels) + logs to a single file inserting the line: + + kern.* /var/log/kernel.log + + at /etc/syslog.conf (remember to do `killall -HUP syslogd' + to restart syslogd after changing it). On Debian systems, + `/etc/init.d/sysklogd restart' will do. + + IT IS _VERY_ IMPORTANT TO HAVE _ALL_ THE LOG LEVELS. IF YOU + ONLY MAIL ME THE NON-DEBUG LEVELS [I.E. ONLY ERRORS], I + WON'T BE ABLE TO DIAGNOSE THE PROBLEM AS FAST AS OTHERWISE. + + It uses to also help if you force the symbol `GDLF_FNTRACE' + to be defined for all source code files, what will generate + bulks of trace information [to do that, on file + include/uusbd/gdlf.h, section `/* 1 to override global + settings */', change `#undef GDLF_FNTRACE' to `#define + GDLF_FNTRACE'. + + - your `lspci -vv' [if you don't have `lspci', `cat /proc/pci' + is ok]. + + - if there are crashes, the `System.map' file generated by + executing `make sysmap' in the UUSBD directory _after_ + loading the modules. + + NOTE I WONT BE ABLE TO DEBUG ANYTHING IF I DONT HAVE ALL THIS +INFO [specially System.map for crashes]. And yes, I'm shouting :) + + PLEASE, COMPRESS _ALL_ FILES, with `gzip -9' or best, `bzip2 +-9'. I get my mail trough a modem link and it's a pain to pay to the +phone co. every coin :) + + Just in case, my e-mail is inaky@peloncho.fis.ucm.es. + + Thanks diff -Naur linux.225/drivers/uusbd/COPYING linux.225.visws/drivers/uusbd/COPYING --- linux.225/drivers/uusbd/COPYING Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/COPYING Fri Dec 26 18:06:59 1997 @@ -0,0 +1,340 @@ + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff -Naur linux.225/drivers/uusbd/COPYRIGHT linux.225.visws/drivers/uusbd/COPYRIGHT --- linux.225/drivers/uusbd/COPYRIGHT Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/COPYRIGHT Sat Feb 20 14:53:55 1999 @@ -0,0 +1,15 @@ + + The work under this package is copyrighted 1996, 1997 and 1998 +by Iñaky Pérez González and others where +noted so; however, it is distributed and released under the GNU Public +License (visit the file COPYING) in hope it will be useful for anybody +who may need it and to encourage public contributions to these efforts +we call Linux and Free Software/Open Source Software. + + All trademarks are copyrighted (or registered, or owned, or +whatever right they've got over it) by their respective owners. + + Other persons who have contributed significant parts of code: + +- Paul MacKerras [hidbp stuff + ohci fixes and code] +- Rasca Gmelch [raw driver] diff -Naur linux.225/drivers/uusbd/Config.in linux.225.visws/drivers/uusbd/Config.in --- linux.225/drivers/uusbd/Config.in Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/Config.in Sun Apr 4 17:31:30 1999 @@ -0,0 +1,97 @@ +# +# UUSBD Configuration +# + +#if [ "$CONFIG_PROCFS" = "y" ] +#then +# bool 'Support procfs status reports' CONFIG_USB_PROCFS +#fi +bool 'Enable modular drivers load on demand?' CONFIG_USB_LOD + +# HCis +dep_tristate 'Universal Host Controller Interface (UHCI) support' CONFIG_USB_UHCI $CONFIG_USB +dep_tristate 'Open Host Controller Interface (OHCI) support' CONFIG_USB_OHCI $CONFIG_USB + + +# +# Class drivers +# ------------- + +# Hub +dep_tristate 'Hub Devices Class (HUBD) 1.0 support' CONFIG_USB_HUBD $CONFIG_USB +# Audio +dep_tristate 'Audio Devices Class (AUDD) 1.0 support' CONFIG_USB_AUDD $CONFIG_USB +# HID +dep_tristate 'Human Interface Devices (HID) 1.0 support' CONFIG_USB_HIDD $CONFIG_USB +dep_tristate 'Human Interface Devices Boot Protocol (HIDBP) 1.0 support' CONFIG_USB_HIDBP $CONFIG_USB +if [ "$CONFIG_USB_HIDBP" != "n" ] +then + if [ "$CONFIG_UMISC" = "n" -a "$CONFIG_USB_HIDBP" = "m" ]; then + define_bool CONFIG_UMISC m + fi + if [ "$CONFIG_UMISC" != "y" -a "$CONFIG_USB_HIDBP" = "y" ]; then + define_bool CONFIG_UMISC y + fi +# if [ "$CONFIG_UMISC" == "n" ]; then +# if [ "$CONFIG_USB_HIDBP" = "m" ]; then +# define_bool CONFIG_UMISC m +# else +# define_bool CONFIG_UMISC y +# fi +# fi + bool ' Boot Protocol Keyboard support' CONFIG_USB_HIDBP_KBD + bool ' Boot Protocol Mouse support' CONFIG_USB_HIDBP_MSE + bool ' Boot Protocol Genius EasyPen support' CONFIG_USB_HIDBP_GENIUS_EASYPEN + if [ "$CONFIG_USB_HIDBP_GENIUS_EASYPEN" = "y" -a "$CONFIG_USB_HIDBP_MSE" = "n" ]; then + define_bool CONFIG_USB_HIDBP_MSE y + fi +fi + +# Communications +# +# FIXME: add checks for CONFIG_SERIAL, CONFIG_ISDN_CAPI, .. etc + +dep_tristate 'Communication Devices Class 1.0 support' CONFIG_USB_CDCD $CONFIG_USB + +if [ "$CONFIG_USB_CDCD" != "n" ] +then + +# dep_tristate ' POTS Model' CONFIG_USB_CDCD_POTS $CONFIG_USB_CDCD +# if [ "$CONFIG_USB_CDCD_POTS" != "n" ] +# then +# dep_tristate ' Direct Line Model' CONFIG_USB_CDCD_POTS_DL $CONFIG_USB_CDCD +# dep_tristate ' Datapump Model' CONFIG_USB_CDCD_POTS_DP $CONFIG_USB_CDCD +# dep_tristate ' Abstract Control Model' CONFIG_USB_CDCD_POTS_AC $CONFIG_USB_CDCD +# if [ "$CONFIG_USB_CDCD_POTS_AC" != "n" ] +# then +# dep_tristate ' Abstract Control Model Serial Emulation' CONFIG_USB_CDCD_AC_POTS_SE $CONFIG_USB_CDCD +# fi +# dep_tristate ' Telephone Model' CONFIG_USB_CDCD_POTS_TM $CONFIG_USB_CDCD +# fi + + dep_tristate ' ISDN Model' CONFIG_USB_CDCD_ISDN $CONFIG_USB_CDCD + if [ "$CONFIG_USB_CDCD_ISDN" != "n" ] + then +# dep_tristate ' Multi Channel Model' CONFIG_USB_CDCD_ISDN_MC $CONFIG_USB_CDCD + dep_tristate ' CAPI 2.0 Model' CONFIG_USB_CDCD_ISDN_CAPI $CONFIG_USB_CDCD + fi + +# dep_tristate ' Networking Model' CONFIG_USB_CDCD_NET $CONFIG_USB_CDCD +# if [ "$CONFIG_USB_CDCD_NET" != "n" ] +# then +# dep_tristate ' Ethernet' CONFIG_USB_CDCD_NET_ETH $CONFIG_USB_CDCD +# dep_tristate ' ATM' CONFIG_USB_CDCD_NET_ATM $CONFIG_USB_CDCD +# dep_tristate ' Remote NDIS' CONFIG_USB_CDCD_NET_RNDIS $CONFIG_USB_CDCD +# fi + +fi + +# Mass +dep_tristate 'Mass Storage Devices (MSD) 1.0 support' CONFIG_USB_MSDD $CONFIG_USB + +# Raw device access +dep_tristate 'Raw Device Access (experimental)' CONFIG_USB_RAWD $CONFIG_USB + +# Local variables: +# mode: shell-script +# End: diff -Naur linux.225/drivers/uusbd/INSTALL linux.225.visws/drivers/uusbd/INSTALL --- linux.225/drivers/uusbd/INSTALL Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/INSTALL Sun Feb 28 12:16:35 1999 @@ -0,0 +1,228 @@ + + You require: + + - kernel version: 2.2.0 [ok, -pre9] + + - latest modutils for the kernel + + - NON SMP kernel LOCK CODE IS BROKEN!!! Don't use + CONFIG_SMP!!! (btw, Martin Schaller + an adventurous user tried and + found trouble, related to the re-routing of IRQ's by the + IO-APIC; he's already contacted Ingo Molnar in order to + handle it) + + You may install in two different ways; I'll prepend A or B to +each shell command line (i.e. "A$ " or "B$ ") to denote each method; +if nothing prepended (just "$ "), that's a common step. + + One [method A] is extracting the uusbd-VERSION.tar.gz package +at the Linux kernel subdirectory linux/drivers, for linking into the +kernel: + +$ export LINUXDIR=/usr/src/linux +A$ export UUSBDDIR=$LINUXDIR/drivers/uusbd +A$ tar xzf uusbd-VERSION.tar.gz -C $LINUXDIR/drivers + + Other is [method B] extracting on a directory by itself: + +B$ export UUSBDDIR=~yogurcito/uusbd +B$ tar xzf uusbd-VERSION.tar.gz -C $UUSBDDIR/.. + + Note all scripts look at the LINUXDIR environment for a +placement of Linux Kernel sources. If not found, they assume they are +at `/usr/src/linux'. + + Now we generate a patch to modify the kernel source tree, in +order to enable using the Linux configuration system to configure the +UUSBD. You require it always, never care if you compile into the +kernel or outside it: + +B$ cd $LINUXDIR/drivers +B$ rm -f uusbd +B$ ln -s $UUSBDDIR uusbd +B$ cd $LINUXDIR/include +B$ rm -f uusbd +B$ ln -s $UUSBDDIR/include/uusbd uusbd +$ cd $UUSBDDIR/patches +A$ ./install-headers +$ ./mkcfgpatch > /tmp/usb-patch +$ cd $LINUXDIR/.. +$ patch -p0 < /tmp/usb-patch +$ rm /tmp/usb-patch +$ cd $LINUXDIR +$ make menuconfig + +[or `make xconfig' or `make oldconfig', up to you]. + + If you plan to use the keyboard support, you MUST install the +multiple keyboard patch. See the comment for ./hidbp/usb-hidbp.o +below. + + Before starting to compile, take a look at +$UUSBDDIR/Makefile.inc and fix anything you could need to [normally +everything should be setup ok already]. Then, for method A [standard +kernel build method]: + +A$ cd $LINUXDIR +A$ make dep # generate dependencies +A$ make clean # do cleanings +A$ make modules # compile modules +A$ make modules_install # install modules + + for method B: + +B$ cd $UUSBDDIR +B$ make dep +B$ make modules +B$ make modules_install + + What you should have now [at the $UUSBDDIR directory or at +/lib/modules/KVERSION/uusbd]: + +./usb.o The core USB driver and hub manager + +./uhci/usb-uhci.o The HCD (Host Controller Driver) for UHCI + controllers (on most motherboards with Intel + chipset). UHCI generally sucks, but it is a + cheap solution, and in some cases, it is + worth the effort. However, I recommend OHCI + controllers [read next]. + + You can tell if your controller is UHCI or + OHCI by looking at the output of 'lspci' or + 'cat /proc/pci'. If the USB controller it + shows there has I/O range assigned, then + that's UHCI. If it has memory, then it is + OHCI. + +./ohci/usb-ohci.o The HCD for OHCI controllers. Found on other + platforms [i.e., Compaqs, non-Intel ...] and + starting to be seen on a lot of PC + motherboards. Fine controllers. + +./audd/usb-audd.o The USB Audio Devices Driver [SKELETON + IMPLEMENTED ONLY]; a driver for audio + devices. Note this is just an skeleton, it + does nothing useful yet. + +./audd/usb-msdd.o The USB Mass Storage Devices Driver [SKELETON + IMPLEMENTED ONLY]; a driver for mass storage + devices. Note this is just an skeleton, it + does nothing useful yet. + +./audd/usb-cdcd.o The USB Communication Devices Class Driver + [SKELETON IMPLEMENTED ONLY]; a driver for + communication devices. Note this is just an + skeleton, it does nothing useful yet. + +./hidd/usb-hidd.o The USB Human Interface Devices Driver, not + implemented fully yet. + +./hidbp/usb-hidbp.o The USB Human Interface Devices Driver Boot + Protocol. This is a simplified, smaller driver + for use of HID keyboards and mice which + support the Boot Protocol. + + This driver uses the misc character devices, + with minors 16 up to 48. So: + + $ mknod /dev/hidbp-kbd-0 c 10 16 + $ mknod /dev/hidbp-kbd-1 c 10 17 + $ ... + $ mknod /dev/hidbp-kbd-15 c 10 31 + + $ mknod /dev/hidbp-mse-0 c 10 32 + $ mknod /dev/hidbp-mse-1 c 10 33 + $ ... + $ mknod /dev/hidbp-mse-15 c 10 47 + + Where the hidbp-?-0 is the first detected kbd or + mouse, hidbp-?-1 the second ... + + You can use the little programs + hidbp/b(kbd|mse)-test to see some output [in + form of hex codes]. You can also use the + mouse, by using the corresponding device file + and using protocol type 'busmouse'. IANF we'll + develop a new protocol exchanging method to + allow high resollution and more enhancements. + + MULTIPLE!! --> Keyboard is being integrated into the kernel + KEYBOARDS!! --> ... stay tuned. In the mean time, you require + the keyboard integration patch you can get + from the web page. If you don't use it, + HIDBP_kbd won't compile. + +./hubd/usb-hubd.o The USB Hub Driver; driver for USB hubs, + backbone of the USB topology. Half tested, but + works. + +./rawd/usb-rawd.o Foundations for a raw access driver, to access + the USB devices from userland directly to the + endpoints. Not finished yet. Thanks to Rasca + Gmelch for working on this. + +./skeld/usb-skeld.o Skeleton driver. You should be able of + creating a very basic driver starting out of + this one. + + To ease module loading, you can use the file +$UUSBDDIR/patches/uusbd-conf.modules. If using Debian +modutils-2.1.121 or higher, just do: + +$ cp $UUSBDDIR/patches/uusbd-conf.modules /etc/modutils/uusbd +$ update-modules + + if you ain't using Debian, you can get by with: + +$ cat $UUSBDDIR/patches/uusbd-conf.modules >> /etc/conf.modules + + After any of them, do: + +$ depmod -av + +to regenerate the module dependencies for the UUSBD modules. Make sure +you see uusbd stuff on the output. + + If you look at that file, you'll see something like: + +alias usb-0000.0000.08.00.00 usb-msdd.o +alias usb-0000.0000.09.00.00 usb-hubd.o + +These little numbers are codes. First four hex digits are vendor code, +next is product ID, then USB class, subclass and protocol. The UUSBD +core uses these names to load the modules needed to configure a +device. 0x9 is the HUB class and 0x8 the Mass Storage class. + + Now you just can + +$ modprobe usb + +this will automatically load the host controller drivers you compiled +in (if so requested), for UHCI and OHCI controllers and start +enumerating. + + Most people just have one controller, so you only have to +compile UHCI or OHCI support. To guess which one you should compile, +use '/sbin/lspci -v | grep USB'. This shows your controllers. If they +have the text '(prog-if 10)' appended, that's an OHCI controller; else +it is an UHCI controller. + + WARNING!! I'm still trying to hunt why it _freezes_ when you +load and run, at the same time, the usb-uhci and usb-ohci drivers, so +_never_ load them both [unless you plan to debug it]. + + Be sure to have USB enabled on your motherboard, as on `old' +ones it comes disabled. Go to the BIOS and enable everything that's +USB related. I dunno if with new kernel's PCI code that's necessary, +but just in case (there has been some traffic on the mailing list +about this issue lately; there're some BIOSes which doesn't permit +enabling the USB support). + + Iñaky + + inaky@peloncho.fis.ucm.es + http://peloncho.fis.ucm.es/~inaky + http://peloncho.fis.ucm.es/~inaky/USB + diff -Naur linux.225/drivers/uusbd/MIRRORS linux.225.visws/drivers/uusbd/MIRRORS --- linux.225/drivers/uusbd/MIRRORS Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/MIRRORS Sat Feb 27 10:45:20 1999 @@ -0,0 +1,47 @@ + + The project's web is located at these URLs: + +[U = URL, M = maintainer, P = mirroring period, L = location] + +U: http://peloncho.fis.ucm.es/~inaky/uusbd-www +M: inaky@peloncho.fis.ucm.es +P: master +L: Spain/RUNET + +U: http://club.idecnet.com/~pegon/uusbd-www +M: pegon@idecnet.com +P: daily, at 02:00 CET +L: Spain/IdecNet + +U: http://wwwhome.cs.utwente.nl/~ia_ric/USB +M: Ric Klaren +P: unknown +L: The Netherlands + +U: http://www.bcinternet.com/~inaky/USB +M: Mike Wood +P: daily, at 03:00 EST +L: Canada + +U: http://darwin.igeofcu.unam.mx/USB +M: esteban@igeofcu.unam.mx +P: daily +L: Mexico + +U: http://nv.org/linux/USB +M: Steven Byrnes +P: unknown +L: Houston and Maryland, USA + +U: http://electricrain.com/Linux/USB +M: Gregory P. Smith +P: daily, at 01:42 PST +L: Mountain View, California USA + +U: http://josefine.ben.tuwien.ac.at/~mfischer/mirrors/peloncho.fis.ucm.es/~inaky/uusbd-www +M: Markus Fischer +P: daily, at 00:00 CET +L: Vienna, Austria + + Thanks to all the people who provided mirror space! + diff -Naur linux.225/drivers/uusbd/Makefile linux.225.visws/drivers/uusbd/Makefile --- linux.225/drivers/uusbd/Makefile Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/Makefile Sun Feb 7 05:11:19 1999 @@ -0,0 +1,211 @@ +# +# Makefile for the Universal USB Driver, Linux flavour +# ---------------------------------------------------- +# +# Distributed under the terms of the GNU Public License Version 2 +# See files COPYRIGHT and COPYING at the root distribution directory +# +# all_targets: Makes O_TARGET and L_TARGET +# fastdep: To remake quickly and recursively the dependencies +# sub_dirs: Creates the sub directories SUB_DIRS +# modules: Makes M_OBJS, MX_OBJS, MI_OBJS and MIX_OBJS, +# recursively in MOD_SUB_DIRS and MOD_IN_SUB_DIRS. Also +# makes the module's list name and links'em to +# $(TOPDIR)/modules. + +# Subdirs to run into +# ------------------- + +CLEANSTUFF += System.map .modules-list TAGS +SUBDIRS := audd cdcd hidd hidbp hubd msdd ohci quirks rawd \ + skeld uhci +SUB_DIRS = quirks +MOD_IN_SUB_DIRS := quirks +ALL_SUB_DIRS := $(SUBDIRS) +MOD_LIST_NAME := UUSBD_MODULES + +MOD_TO_LIST = $(shell test -r $(MODULES_FILE) && \ + sed -e 's/^.*\///g' -e 's/dummy_module//' \ + $(MODULES_FILE)) +export UUSBDDIR := $(shell pwd) + +# This line must be here for it to interpretate the *DIR and also to +# define all the CONFIG_* and stuff needed below. +include Makefile.inc +ifdef NOT_IN_LINUX_KERNEL +export EXTRA_CFLAGS += -I./include/ +endif + +# Object and module specification + +USB_OBJS := generic.o \ + hcd.o \ + hubm-stch.o \ + hubm-hkeep.o \ + hubm-generic.o \ + kernel-interface.o \ + khubdd.o \ + misc.o \ + slist.o \ + mm.o \ + usbd-3slist.o \ + usbd-cfg.o \ + usbd-descr.o \ + usbd-endp.o \ + usbd-iface.o \ + usbd-ops.o \ + usbd-device.o \ + usbd-drv.o \ + usbd-host.o \ + usbd-tr.o \ + usbd.o + +ifeq ($(CONFIG_PCI),y) + USB_OBJS += pci.o +endif + +ifeq ($(CONFIG_USB_PROCFS),y) + USB_OBJS += procfs.o +endif + +O_OBJS := $(USB_OBJS) +OX_OBJS := usb-symtab.o +O_TARGET := usb.o + +M_OBJS := dummy_module + +# Playing with the values of the configuration statements, [n, m, y], +# set up what to compile. + +ifeq ($(CONFIG_USB),y) + L_TARGET := usb.a + L_OBJS := usb.o +endif + +ifeq ($(CONFIG_USB),m) + M_OBJS += usb.o +endif + + +ifeq ($(CONFIG_USB_UHCI),y) + SUB_DIRS += uhci + L_OBJS += uhci/usb-uhci.o +endif + +ifeq ($(CONFIG_USB_UHCI),m) + MOD_IN_SUB_DIRS += uhci +endif + + +ifeq ($(CONFIG_USB_OHCI),y) + SUB_DIRS += ohci + L_OBJS += ohci/usb-ohci.o +endif + +ifeq ($(CONFIG_USB_OHCI),m) + MOD_IN_SUB_DIRS += ohci +endif + + +ifeq ($(CONFIG_USB_HUBD),y) + SUB_DIRS += hubd + L_OBJS += hubd/usb-hubd.o +endif + +ifeq ($(CONFIG_USB_HUBD),m) + MOD_IN_SUB_DIRS += hubd +endif + + +ifeq ($(CONFIG_USB_SKELD),y) + SUB_DIRS += skeld + L_OBJS += skeld/usb-skeld.o +endif + +ifeq ($(CONFIG_USB_SKELD),m) + MOD_IN_SUB_DIRS += skeld +endif + + +ifeq ($(CONFIG_USB_HIDD),y) + SUB_DIRS += hidd + L_OBJS += hidd/usb-hidd.o +endif + +ifeq ($(CONFIG_USB_HIDD),m) + MOD_IN_SUB_DIRS += hidd +endif + + +ifeq ($(CONFIG_USB_HIDBP),y) + SUB_DIRS += hidbp + L_OBJS += hidbp/usb-hidbp.o +endif + +ifeq ($(CONFIG_USB_HIDBP),m) + MOD_IN_SUB_DIRS += hidbp +endif + + +ifeq ($(CONFIG_USB_AUDD),y) + SUB_DIRS += audd + L_OBJS += audd/usb-audd.o +endif + +ifeq ($(CONFIG_USB_AUDD),m) + MOD_IN_SUB_DIRS += audd +endif + + +ifeq ($(CONFIG_USB_CDCD),y) + SUB_DIRS += cdcd + L_OBJS += cdcd/usb-cdcd.o +endif + +ifeq ($(CONFIG_USB_CDCD),m) + MOD_IN_SUB_DIRS += cdcd +endif + + +ifeq ($(CONFIG_USB_MSDD),y) + SUB_DIRS += msdd + L_OBJS += msdd/usb-msdd.o +endif + +ifeq ($(CONFIG_USB_MSDD),m) + MOD_IN_SUB_DIRS += msdd +endif + + +ifeq ($(CONFIG_USB_RAWD),y) + SUB_DIRS += rawd + L_OBJS += rawd/usb-rawd.o +endif +ifeq ($(CONFIG_USB_RAWD),m) + MOD_IN_SUB_DIRS += rawd +endif + + +include $(TOPDIR)/Rules.make +include Makefile-rules.inc + +.PHONY: dummy_module +dummy_module: +ifeq ($(CONFIG_USB),m) + rm -f $(MODULES_FILE) + for v in $(M_OBJS); do echo `pwd`/$$v; done >> $(MODULES_FILE) +endif + +ifndef IN_LINUX_KERNEL +modules_install: + @( set -e; \ + MODLIB=$(INSTALL_MOD_PATH)/lib/modules/$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION); \ + inst_mod() { These="`cat $$1`"; \ + mkdir -p $$MODLIB/$$2; cp $$These $$MODLIB/$$2; \ + echo Installing modules under $$MODLIB/$$2; \ + }; \ + grep -v dummy_module .modules-list > .modules-list.$$$$; \ + mv .modules-list.$$$$ .modules-list; \ + if [ -f .modules-list ]; then inst_mod .modules-list uusbd; fi; \ + ) +endif diff -Naur linux.225/drivers/uusbd/Makefile-rules.inc linux.225.visws/drivers/uusbd/Makefile-rules.inc --- linux.225/drivers/uusbd/Makefile-rules.inc Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/Makefile-rules.inc Fri Dec 11 17:56:22 1998 @@ -0,0 +1,117 @@ +# +# Universal USB Driver +# -------------------- +# +# Distributed under the terms of the GNU Public License Version 2 +# See files COPYRIGHT and COPYING at the root distribution directory +# +# PPC Stuff for iMac by Paul Mackerras +# +# Common make rules for stand-alone compilation + + +# no user-serviceable parts below this line + +ifndef IN_LINUX_KERNEL +.PHONY: TAGS tags dep clean distclean realclean doc docs tar cvstar love + +%.i: %.c + $(CPP) $(CPPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -c $^ -o $@ + +.PRECIOUS: %.i +%.ci: %.i + -grep -v -e "^#" -e "^ *$$" $^ | indent > $@ + mv -f $@ $^ + +%.s: %.c + $(CC) -S $(CFLAGS) $(EXTRA_CFLAGS) -c $^ -o $@ + +%.io: %.i + $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c $^ -o $@ + +dep: +ifneq "$(strip $(SUBDIRS))" "" + set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i $@; done +endif +ifneq "$(strip $(SUB_DIRS))" "" + set -e; for i in $(SUB_DIRS); do $(MAKE) -C $$i $@; done +endif +ifneq "$(strip $(MOD_SUB_DIRS))" "" + set -e; for i in $(MOD_SUB_DIRS); do $(MAKE) -C $$i $@; done +endif + -$(CPP) -M $(CPPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) *.c > .depend + +CLEANSTUFF += *~ *.[aios] *.bak *.ci *.io +DISTCLEANSTUFF += .depend \\\#*\\\# .*.flags +REALCLEANSTUFF += TAGS + +clean: + rm -f $(CLEANSTUFF) +ifneq "$(strip $(SUBDIRS))" "" + set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i $@; done +endif + +distclean: + rm -f $(DISTCLEANSTUFF) $(CLEANSTUFF) +ifneq "$(strip $(SUBDIRS))" "" + set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i $@; done +endif + +realclean: + rm -f $(REALCLEANSTUFF) $(DISTCLEANSTUFF) $(CLEANSTUFF) +ifneq "$(strip $(SUBDIRS))" "" + set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i $@; done +endif + +doc docs: +ifneq "$(strip $(SUBDIRS))" "" + set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i $@; done +endif + +TAGS: *.c *.h +TAGS tags: + find . -name "*.[ch]" | etags - + +# archive + +ifeq "$(TARNAME)" "" +TARNAME=uusbd +TARDIR=uusbd +endif + +tar: + tar c -C .. \ + --exclude '*~' --exclude '*.bak' \ + --exclude '*.[aios]' --exclude '*.ci' --exclude '*.io' \ + --exclude '*/System.map' --exclude '.*flags' \ + --exclude '*./TAGS' --exclude '*/.depend' \ + --exclude '#*#' \ + -f - $(TARDIR) \ + | bzip2 -9f \ + > ../$(TARNAME)-$$(date +%Y%m%d%H%M).tar.bz2 + +cvstar: + tar c -C $$CVSROOT \ + --exclude '*~' --exclude '*.bak' \ + --exclude '*.[aios]' --exclude '*.ci' --exclude '*.io' \ + --exclude '*/System.map' --exclude '.*flags' \ + --exclude '*./TAGS' --exclude '*/.depend' \ + --exclude '#*#' \ + -f - $(TARDIR) \ + | bzip2 -9f \ + > ../$(TARNAME)-$$(date +%Y%m%d%H%M).CVS.tar.bz2 + +# Flower Power :) + +love: + @echo "not war!" + +# Symbols +KVER=$(shell uname -r) +sysmap System.map: /boot/System.map-$(KVER) + patches/make_sysmap \ + /boot/System.map-$(KVER) /proc/ksyms \ + /lib/modules/$(KVER)/*/*.o \ + > System.map + +endif # !IN_LINUX_KERNEL diff -Naur linux.225/drivers/uusbd/Makefile.inc linux.225.visws/drivers/uusbd/Makefile.inc --- linux.225/drivers/uusbd/Makefile.inc Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/Makefile.inc Sun Apr 4 18:04:26 1999 @@ -0,0 +1,67 @@ +# +# Universal USB Driver +# -------------------- +# +# Distributed under the terms of the GNU Public License Version 2 +# See files COPYRIGHT and COPYING at the root distribution directory +# +# PPC Stuff for iMac by Paul Mackerras +# +# Common make stuff for compiling stand-alone modules + +ifndef TOPDIR +export NOT_IN_LINUX_KERNEL := 1 +else +# Check this when recursive making ... +ifndef NOT_IN_LINUX_KERNEL +export IN_LINUX_KERNEL := 1 +endif +endif + + +ifdef NOT_IN_LINUX_KERNEL + +ifdef LINUXDIR +export TOPDIR := $(LINUXDIR) +else +export TOPDIR := /usr/src/linux +endif + +VERSION = $(shell $(CONFIG_SHELL) grep ^VERSION $(TOPDIR)/Makefile | sed -e 's/ //g' | cut -d'=' -f2) +PATCHLEVEL = $(shell $(CONFIG_SHELL) grep ^PATCHLEVEL $(TOPDIR)/Makefile | sed -e 's/ //g' | cut -d'=' -f2) +SUBLEVEL = $(shell $(CONFIG_SHELL) grep ^SUBLEVEL $(TOPDIR)/Makefile | sed -e 's/ //g' | cut -d'=' -f2) +EXTRAVERSION = $(shell $(CONFIG_SHELL) grep ^EXTRAVERSION $(TOPDIR)/Makefile | sed -e 's/ //g' | cut -d'=' -f2) + +export KERNEL_OPT = -D__KERNEL__ -I$(TOPDIR)/include +export KERNEL_OPT += -DEXPORT_SYMTAB -DMODULE -DMODVERSIONS -include $(TOPDIR)/include/linux/modversions.h +export WARNINGS = -Wall -Wstrict-prototypes +ifdef CONFIG_PPC +export COMPILE = -O2 -fomit-frame-pointer -D__powerpc__ -fsigned-char +export COMPILE += -msoft-float -pipe -fno-builtin -ffixed-r2 +export COMPILE += -mmultiple -mstring +else +export COMPILE = -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -m486 +export COMPILE += -malign-loops=2 -malign-jumps=2 -malign-functions=2 -DCPU=586 +endif +export LD = ld +export LD_RFLAG = -r +export LD_OPT = -r +export CFLAGS = $(KERNEL_OPT) $(WARNINGS) $(COMPILE) +# for genksyms to work +export CFLAGS += -I. +export HOSTCC = gcc +export HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer +export GENKSYMS=/sbin/genksyms +ifeq ($(TOPDIR)/.config,$(wildcard $(TOPDIR)/.config)) +include $(TOPDIR)/.config +endif + +endif # NOT_IN_LINUX_KERNEL + + +# USB Options +# ----------- + +export EXTRA_CFLAGS += -g -D__UUSBD__ #-DUSB_HWDB +export MODULES_FILE := $(TOPDIR)/drivers/uusbd/.modules-list + diff -Naur linux.225/drivers/uusbd/README linux.225.visws/drivers/uusbd/README --- linux.225/drivers/uusbd/README Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/README Sun Apr 4 18:10:51 1999 @@ -0,0 +1,112 @@ + + Hi :) + + [PLEASE READ FULLY, OR AT LEAST UNTIL 5th PARAGRAPH :)] + + FOR INFO ON BUG REPORTING, SEE FILE `BUG-REPORTING' + + FOR INFO ON BUREOCRATIC STUFF, SEE FILE `COPYRIGHT' + + FOR INFO ON INSTALLING, SEE FILE `INSTALL' + + This is an snapshot of the work we are doing on Linux-USB. + + Note that this project has involved the creation of a new +whole subsystem, like SCSI. I don't know if as complicated, but it's +been for me :), a little kernel nerd. It may also be optimized in a +lot of places, but I'm mainly concerned to first make it +work. Optimization will come later. + + Currently there are drivers for UHCI and OHCI host controllers +(without isochronous support, but we'll code that soon). Mice works in +Boot Protocol mode; so do keyboards [need an special patch to have the +kernel using it]; we are working at the same time in drivers for HID, +audio, ISDN CAPI interface and the FDU (floppy) drivers. + + Also the hub driver is done, and tested to some extent; it +works :). + + Note that everything gives *bulks* of debug info. This is +intentionated; however, you may loose messages if you have all of them +activated. To solve this, you can increase the klog buffer length +[#define LOG_BUF_LEN ...] in linux/kernel/printk.c. I've set it up to +131072 [way too big, isn't it? :)]. Also, if you're using Debian, +chances are `emerg' messages are sent to everyone logged in. You may +want to turn this off, as function traces use the `emerg' level and it +would clutter your console/terminals [on /etc/syslog.conf comment out +`*.emerg *' and exec '/etc/init.d/sysklogd reload']. + + I must recognize I spend too much time documenting and making +things look somehow fancy, instead of 'wasting' that time coding. This +may sound as bad, but it's been what has made Linux-USB more compact, +as I've been always to track down what is each thing (believe it or +not, there are functions I wrote a month ago I'd won't know what do +they do if it weren't for the docs). + + I'm using 2.2.x to run this; 2.0.x won't work, nor I intend +to. + + Note that all the known craps are marked with a FIXME tag, and +all the things which should be taken in consideration with a NOTE +tag. Warnings, (you guessed!) marked with WARNING tags. Also at the +TODO file there's a list of things to do (that's the name for). There +are some more sticked to the wall behind my monitor. + + Also take into account that the code is getting fairly +complex. I come from C++ fanatism :), and that's what made me develop +the ideas on destructors and use counts for the linked lists. They +need a *lot* of hard-core debugging and stress testing (and +optimization in some places). Thus, take it easy when messing with +them. Also needs optimization the trillion checks done all around the +code as some will be unnecessary when assertions are disabled (this is +marked at the TODO file). + + IF YOU INTEND to understand the code, start at the kernel usb +driver daemon (kusbdd) at khubdd.c. It's an asynch kernel process +which does almost all the interesting stuff. It is started from +usb_init() at kernel-interface.c, which makes kusbdd start enumerating +by calling function usb_hub_host_enum() [which is at khubdd.c]. The +enumerating function finally calls (via pointers) the +[ou]hci_enumerate() functions at uusbd/[ou]hci. NOTE THAT, ANYHOW, YOU +NEED TO HAVE AT LEAST USB BASICS UNDERSTOOD. + + I also need feedback on the documentation. I'd like to have a +lot more of docs and not as disconnected as actual, but it's quite +difficult for me to keep everything on the bleeding edge. I try it, +anyway. Someday I should bundle all the docs in a big, boring document +:) + + Please, send me (or to the list) any ideas, suggestions, +patches, flames (> /dev/null :), and remember I'm a poor rookie kernel +coder! + + I'm trying to keep the code fairly architecture-independent, +(ok, there are some craps here and there, but I think they're all +marked as FIXME tags). If anybody would like to get this thing ported +to BSD/Mach/Hurd/"any FREE os" when it is done, I'd love it, but I +have no idea of those systems, and so I could only help to the guy +doing the porting. However, please send me any sugerences to keep the +code more or less OS independent (in fact, this is why I renamed the +package to uusbd, trying to mean Universal USB Driver). Always remind +the only license method will be GPL, at least for the code I own. + + The SCRATCH file is where my disconnected ideas finally sink, +as well as all the suggestions and stuff. It is a black board to write +everything down so it is not forgotten. Please, take a look at it, but +don't take everything serious :) + + BTW, the USBDI standard has shut off their doors to us (we +cannot pay to certify our intellectual openness ...). We stay tuned +for a sollution suitable for Free Software. + + Iñaky + + inaky@peloncho.fis.ucm.es + http://peloncho.fis.ucm.es/~inaky + http://peloncho.fis.ucm.es/~inaky/USB + +P.D.: the mailing list is at linux-usb@peloncho.fis.ucm.es, subscribe + with: + + $ echo subscribe linux-usb | mail majordomo@peloncho.fis.ucm.es + diff -Naur linux.225/drivers/uusbd/SCRATCH linux.225.visws/drivers/uusbd/SCRATCH --- linux.225/drivers/uusbd/SCRATCH Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/SCRATCH Sat Feb 27 10:45:42 1999 @@ -0,0 +1,391 @@ + + + All the stuff in this file are ideas, scratches and things I +write down as a poor and anarchical TO-DO list ... somethings are +useful, some not, some are bad, some outdated ... anarchy in action! + + ---- + + When scheduling iso pipes on UHCI, add a table which maps the +expected frame count when it should be finishing, so is easier to keep +track of it. + + Also add BWR based on how many hi-speed ctl or bulk xfers are +queued. + + + ---- + + Remove dev_set(up|dn), as UHCI won't use and add +endp_set(up|dn), as OHCI will use. Add an 'ts_dtor* hci' field to +ts_usb_endp with a #if defined (CONFIG_USB_OHCI) || defined +(CONFIG_USB_OHCI_MODULE) so it won't be compiled in for UHCI +systems. + +typedef struct s_ohci_endp ts_ohci_endp; /* 16 byte aligned */ +struct s_ohci_endp +{ + ts_ohci_ed ed; /* must be first, 16 byte aligned */ + /* Info? Statistics ... */ +}; + + ---- + + Statistics + + So, I want to gather statistics. They make you look cool, +nice, good-looking and suits like them. However, first of all, they +waste resources, but they can also be useful to allow the software to +auto tune (ie: UHCI) or to help you doing it better. + + Per endpoint: + + - Transactions done (not packets sent, but whole +transactions). + + - Transacion Period (mean period in which a transaction is +executed [usb_tr_run()]) - [1/s]. + + - Byte Speed [bytes/second] + + - Errors + + - Error density [errors/bytes] + + We just have to store an initial timestamp each time we open +the endpoint, a transaction count and a byte count (cleared also when +opening). Counts may overflow, perhaps will have to add to the means +directly [guess how :)] + + These statistics should be taken from the transaction +statistics, and it should be a cooperative effort between HCD and +USBD. + + Device wide statistics should be these ones too, adding all +endpoint wide statistics. Perhaps they should be cleared when a +configuration is changed and reinitialized with endpoint 0 values +... think more about this. + + BTW, statistics could be optionally left out at compilation +time [if performance is an issue and statistics not]. However, some +functionality could be lost [like auto-tuning and the like]. + + ---- + + Scanning configuration descriptor blocks. + + First pass: + + We scan number the of real interfaces storing it in +cfg->bNumInterfaces or returning it [I prefer this one]. + + We also scan for each interface the number of alternate +settings and store it into iface->bAlternateSetting [as we know, by +USB 1.0 Spec 9.6.3, that first alternate setting is always number +zero, we can recover later from this modification]. + + There's no need for a second pass. The code which uses the +cooked interfaces must be aware of this and act in consequence. + + On storing the vendor/class specific info found on the +descriptor block, I'd bet for letting it up to the driver to search +for it. It can even use the [yet to be coded] persistence system to +keep track of where is it on identical devices, and thus save time +when locating it. + + ---- + + More on persistence (for loadable modules) + + The device is connected, a driver searched, driver loads, ok? +then it configure cfels [and the goodies should be that every +non-active cfel auto-unconfigures, so we have less resource +waste]. Then we have this module loaded who's configured some cfels, +attaching structures to them. But it is not used [it's use count is +zero], so it's candidate for unload. When it unloads, it could leave +the data structures plugged to the cfel structs. Then, if the user +uses it again [i.e., open(2)], it reloads and using a list of devices +and cfels provided by it's driver structure [which was kept on +memory], he can relocate the devices he had configured, ACTUALIZE THE +DESTRUCTOR FUNCTION POINTERS [very important! they may have changed +address] and use it, skeeping the reconfiguration process. + + When the device is to be unconfigured, the driver is reloaded, +it does all it's stuff and it'll be auto-unloaded again ... + + Even more, the linked list that each device should have +linking all it's structures linked to cfels data structures +[ts_usb_cfel->d_*] could be kept in the driver structure, so that no +other list has to be kept to configured elements to faslty access +them. + + This has an obvious disadvantage: the structures are kept +memory. It's ugly enough we have this big structs [device, cfgs, +ifaces, asets] and then we add, per driver, an struct, and a list of +other structs, perhaps one per device [suppossing the inactive cfels +ain't configured]; we have a very respectable amount of data structs +on memory. + + Ok, there're advantages too: FAST. Little bus transactions on +reload. + + ---- + + Another approach: the KGDBM, a generic persistence system in +the form of a completely independent module which implements the GNU +DBM interface in the kernel. + + It would consist of a GDBM compatible API in the kernel which +would redirect all requests to a user land daemon who would do the +hard work. Thus we have independent databases, etc ... available under +/var/lib/kgdbm/`uname -r`/. + + Would be nice to have it working also without user land +daemon, but it'd be quite too hard, so first try would require the +user land daemon. + + This should be completely modular, and not interfere the +kernel _for_ anything. The kgdbm_open() function should be able to +detect if the user-land daemon is not working and start it [as kmod +does with modprobe]. Similarly, the kgdbm_close() function should kill +the daemon if it is not being used by anybody else. + + I don't know how the fuck to do the interfacing with the +daemon. Will have to lurk around ... + + + Advantages: + + - We spend less memory, as we store short keys and data + + - It is reboot-proof, so we keep the data over reboots + + - Helps to keep track of topology changes + + + Disadvantages: + + - Slower + + - Races [database stored on a USB disk and module wants to + access the database to know the disk's data: deadlock]. + Sollution for this case could be use one or other sollution + [even mixed and controlled via proc/sysctl] based on the + device. For storage media, it'd be advisable to use previous + method. + + - Reentrancy problems on kernel. + + ---- + + + ---- + + From the comments to USBDI v0.7 3.3.1, on device +configuration. Complete it: + + The way I propose is: when a device is plugged into the USB + system, the matching driver(s) is(are) loaded and configure the + device. However, they must keep themselves in a zero-reference + count state, so they can be auto unloaded by the OS for not being + used. Note the device keeps in the same configured state. + + Later, when the device is going to be used [some program opens + it], the OS automagically loads the device driver again, which + knows [via a persistence system] which devices he was managing and + then may access them [also note it knows the device's state]. + + When a device is unplugged, all currently open + handles/descriptors to it are invalidated, and the unconfiguration + procedures for each involved driver called. This may cause again a + re-load of the driver if unloaded to make it update it's device + information. + + This way we guarantee minimal resource waste for modular + drivers, as well as direct support for hadly-linked in drivers. + + On Linux USB, I'm using a quite simple system for driver + registration. On system boot time [or whenever new drivers are + available], all usb drivers are loaded. They register within the + USBD system [and try to configure unconfigured matching devices] + and then go to zero-reference count state. Then Linux unloads them + if unused. Thus, the USBD always knows in a fast lookup list which + driver's are available to load. As a fallback method there's [not + yet finished] a generic module loading system. There's also a hooks + system which uses this logic to call functions/load modules when + any device is attached/detached to the bus. + + Note this interface is not yet completed. + + ---- + +Add: + +#MODULE_PARM(usb,"xxx"); +MODULE_AUTHOR(USB_AUTHOR/MAINTAINER); +MODULE_SUPPORTED_DEVICE("usb"); + + ---- + + Using the module persistency system, we could make the hosts +keep their address number, as well as devices keep their +configurations and alternate settings between module +load/unloads. Also device's could keep their 'virtual address' in the +UUSBD system (being the 'virtual address' a way to locate'em +independently of the host/hub where they're connected). + + ---- + + Got to make volatile all the fields on structs which are +modified by the [OU]HCI controllers + + ---- DEPRECATED/IMPLEMENTED + + The read/write functions interface + + Each time somebody tries to read from a USB device, it has got +to provide and ts_usb_open structure describing the endpoint to read +from (we'll consider the read operation from now), a buffer to read to +and a number of bytes to read. + + The sequence then is to allocate a kernel buffer to hold the +data read from the endpoint and start to schedule USB reads. As soon +as the read is complete, the read function should return. This seems +troublefree, but ... what'd happen if the user requests to read 1.6 +GB? Trouble, we can't allocate a kernel buffer of 1.6 GB (ok, we could +if we had the pysical memory, but it'd be quite an stupid sollution +with today's computers ... ). + + So the sollution should be to allocate an smaller buffer of a +predefined {sysctl,/proc}-tunable (on a per-device and endpoint +basis?) size -- multiple of the endpoint's transfer size and optimized +to consume as little kmemory as possible --. Thus, we'd schedule reads +to that buffer and when the buffer is full, copy it to the one +provided by the function. + + However this may imply latencies (when copying the buffer we +can't schedule more transfers) that aren't allowable for isochronous +and interrupt transfers (though interrupt transfers are less likely to +suffer this problem). So it should be made to copy the already +transfered data when a percentage of the buffer is full and after +schedule more transfers to that part of the buffer we've just copied +while the rest of the buffer is being filled. What's the correct +percentage of the buffer to trigger the copy? I guess it'll depend on +the time we take to schedule the new xfers and copy the data (in this +order). I'd vote to set it in the middle and allow it to be +tunable. Ahead on time I'll try to write an optimizing function (based +in something like increase the percentage until a timeout failure is +found, then lower it a bit ... some auto-adapting stuff). + + ---- + + Little endian GCC aligns structs & bitfields with first +element being the lowest significant. + +aka: struct { char x, y, z, k;} would yield the 32 bits integer + k << 24 + z << 16 + y << 8 + x + + ---- + + Endpoints should be shareable between two or more people +wishing to write/read. Quite something like the dup() syscall. + + ---- + + /* Sample IRQ handler */ + +static void lp_interrupt (int irq, void *dev_id, struct pt_regs *regs) +{ + struct lp_struct *lp = &lp_table[0]; + + while (irq != lp->irq) + if (++lp >= &lp_table[LP_NO]) + return; + + wake_up(&lp->lp_wait_q); +} + + + ---- + + How to (raw) read/write from a USB device (we suppose it's configured): + + We can only set the destination host && device once. When set, +if we want to write to another host/device, have to open another +descriptor. However, destination interfaces/endpoints may be set, as +they may coexist. + +fd = open ("/dev/usb1", O_RDONLY | O_WRONLY); this creates an struct at the kernel for keeping track of the + open file (problem: dup() really duplicates or reopens? fix + this). +ioctl (fd, USB_IOCTL_SET_IFACE, ts_usb_addr, t_usb_aset); Set an interface's alternate setting +ioctl (fd, USB_IOCTL_SET_DEST, ts_usb_addr); Set the address/iface/endpoint device we want to write to (reset dest + enpoint to 0; FIXME: really should?) Return error if + unexistant addr. +ioctl (fd, USB_IOCTL_SET_DEST, This could be kind of a "logical" way to open a device, + VendorId-ProductId-Cookie); hiding the topology of the bus(es) from the client +ioctl (fd, USB_IOCTL_SET_DEST, The same, but more abstract even, using classes. + ClassId-SubClassId-ProtocolID-Cookie); Should the Cookie be the same as the one for the VendorId-ProductId? +read/write (fd, buffer, size); Read/write to the addressed device, numbered endpoint with + the defined transfer method. Error if writing in interrupt + transfer type ... etc. On overrun, return -ENOSPC. +close (fd); + + --- + + +* IDEA: virtual mappings for persistence of bus/device topology + +* IDEA (Oren Tirosh): chroot of USB for consoles + +* IDEA (Oren Tirosh): use a daemon (usbd :) for detecting change of + state, do enumeration .. etc + +* TODO: Contact Thrustmaster again. Also applies for Fujitsu (the guy + at the HQ at Japan) an the ICL local representative here at Madrid. + The ICL local representative has said nay ... thanks, Fujitsu Spain :-P + +* TODO: OHCI should be implemented one of these days + + --- + + Virtual addresses. + +How to uniquely identify devices (and keep them with the same ID from +boot to boot): + + The background on this is quite simple; imagine the following scenario: +you've got four video cards, four work-station kits (composed of monitors +-which are compounded of a monitor and a pair of stereo speakers-, keyboards, +video camera and mice (all tied up to a single hub, and thus, you have each +work-station kit connected by a single USB line). You install everything, and +now, you move one of the kits three meters left, and it's a lot better to use +another hub located over there. How'd we tell the software that though they've +change locations, the device's are the same we meant to be, let's say, +/dev/monitor2, /dev/camera2, /dev/kbd2, /dev/mouse2, /dev/audio2? + + + Sollutions? Ideas? + + - Serial number in device descriptor (iSerialNumber) may be not +implemented (it is an string descriptor). It could be used for devices which DO +implement it + + - Analize (somehow) the structure from which the device is hanging. This +would be only ok for compounds. If the whole compound is the same, it's +ok. However, this loops back to the same problem, but with bigger devices :) + + - Store a kind of "virtual" or "logical" structure on disk and load it +on boot, such that it maps the actual physical topology to the constant one ... + + - Related to this, Oren Tirosh suggests that something could be +implemented for each process having something like it's own root hub (analog to +the root directory). + + - Using the vendor id/device id pair sounds cool. Then problem +now comes as soon as you got two identical devices connected. This is +the big problem. Also using class/subclass/protocol. Grrr. + + - Would be cool to use the persistent stuff of the new +modutils. Could be useful for this. + diff -Naur linux.225/drivers/uusbd/THANKS linux.225.visws/drivers/uusbd/THANKS --- linux.225/drivers/uusbd/THANKS Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/THANKS Wed Dec 30 10:43:37 1998 @@ -0,0 +1,144 @@ + + The following corporations have helped us in the development +of Linux USB / UUSBD: + + - USAR Systems provided us with one of their excellent USB + Evaluation Kits. It allows us to test the Linux-USB driver + for compilance with the latest USB specification. USAR + Systems recognized the importance of an up-to-date open + Operating System and supports this project with + Hardware. Thanks!. + + - Thanks to Intel Corporation for their precious help. + + - We teamed up with Cherry to make Linux the first OS with + built-in USB support. Cherry is one of the biggest keyboard + makers in the world. + + - CMD Technology, Inc. sponsored us kindly donating a CSA-6700 + PCI-to-USB Controller Board to test the OHCI implementation. + + - Due to their support to us, Keytronic can be sure that they + will sell keyboards to some of the 3 million (at least) + Linux users. + + - Many thanks to ing büro h doran [http://www.ibhdoran.com]! + It was almost imposible to get a PC backplate USB connector + for the motherboard here at Europe (mine, home-made, was + quite lowsy :). Now I know where to adquire nice USB stuff! + + - Genius Germany donated a USB mouse to test the mouse boot + protocol. They've also donated a F-23 digital joystick and a + NetMouse Pro. Thanks! + + - AVM GmbH Berlin is supporting the development of the Linux + USB driver for the AVM ISDN Controller B1 USB. AVM is a + leading manufacturer for active and passive ISDN Controllers + and CAPI 2.0-based software. The active design of the AVM B1 + is open for all OS platforms, including Linux. + + - Thanks to Y-E Data, Inc. for donating their FlashBuster-U + USB Floppy Disk Drive, so we could test the bulk transfer + code. + + - Many thanks to Logitech for contributing a three axis USB + mouse. + + Logitech designs, manufactures and markets + Human Interface Devices, having a long history and + experience in making devices such as keyboards, mice, + trackballs, cameras, loudspeakers and control devices for + gaming and professional use. + + Being a recognized vendor and seller for all these devices, + they have donated USB mice, a joystick and a scanner, as a + way to acknowledge the importance of Linux and to allow + Logitech customers to enjoy support in their favorite + operating systems and all Linux users to use Logitech and + other USB hardware. + + Logitech is official sponsor of the Linux Conference on + Feb. 11th 1999 in Vienna, where we'll will present the + current state of the Linux USB effort. + + - CATC has provided means to uncover dark corners of the UHCI + inner workings with a USB Inspector. + + - Thanks to Entrega for providing PCI to USB cards, hubs and + converter products for development. + + + And thanks go to (hey! in no particular order :) + + - Oren Tirosh , for standing so patiently + all my doubts'bout USB and giving lots of cool ideas. + + - Jochen Karrer , for + pointing out mortal bugs and giving advice. + + - Edmund Humemberger , for it's great work on + public relationships and general management stuff for the + Linux-USB effort. + + - Alberto Menegazzi is starting the + documentation for the UUSBD. Go for it! + + - Ric Klaren for doing nice + introductory documents (compiting with Alberto's :). + + - Christian Groessler , for it's help on those + itchy bits ... :) + + - Paul MacKerras for polishing OHCI and pushing me harder for + the iMac support, giving improvements and enhancements. + + - Fernando Herrera has taken + charge of composing, maintaining and feeding the + long-awaited, unique and marvelous UUSBD FAQ! Tadaaaa!!! + + - All the Free Software and Linux community, the FSF & the GNU + project, the MIT X consortium, the TeX people ... everyone! + You know who you are! + + - Big thanks to Richard Stallman for creating Emacs! + + - The people at the linux-usb mailing list, for reading so + many messages :) Ok, no more kidding; for all your advices! + + - All the people at the USB Implementors Forum for their + help and assistance. + + - Nathan Myers , for his advice! (hope you + liked Cibeles' party). + + - Linus Torvalds, for starting, developing and managing Linux. + + - Mike Smith, Craig Keithley, Thierry Giron and Janet Schank + for convincing me USB Standard hubs are not that standard + and that's good to allow for vendor specific quirks on the + standard hub driver. + + I should invite all of you to have some beers (or whatever), +so if sometime you come around Madrid and I've money, gimme a call and +I'll invite you :) + + + Special thanks & hellos go to my cool friends: + + María (lot's of kisses 2 U), Mon (no puidorl), Mon, Las Jakas, +Potxokin, Noemi, l'Amico, Alberto, Alfonso, Eviki, Edu (¡qué fea +era!), El Primo, la penya de Benicàssim (salut y força al canut!), +Mayche (com estem, xiqueta?), the people at AFU and CDEP/CCFF, Josete, +la parejita felís, Teknoland, Kernel Panic, Enrique Melero & Santiago +Vila ... bfff, lot's, could fill megabytes with a name list +... they're too many! Don't feel missed if you ain't here :) and you +think you should, just tell me [whep!]. + + Yeah, my family too ... + + Thousand kisses to Gretchen Garmendia, wherever you are. + + + + The War isn't over ... many battles to go yet + diff -Naur linux.225/drivers/uusbd/TODO linux.225.visws/drivers/uusbd/TODO --- linux.225/drivers/uusbd/TODO Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/TODO Sat Feb 20 14:54:10 1999 @@ -0,0 +1,544 @@ + +Legend: - [->] + + * To do + + Almost done + ! Gotta check it + - Done + YYYYMMDDHHMM + + +- ------------ ------------ --------- +* 199902201818 - Alpha rocks ... and cracks + UUSBD/OHCI. See message by Christian + Groessler and fix as much as possible. + +* 199901242026 - After setting SOF, make sure it's ok, by + reading back _from_the_host_ it's value + and comparing it. + +* 199901031957 - Make HCIs register for APM events and + send a global suspend on bus when a + suspend is going to be entered into. + +* 199812110010 - Implement warnings? Perhaps we could + remove them, thouhg I like having'em. + +* 199812110009 - Implement full data buffer + refilling/cicling in ts_usb_tr. + + +* 199812110008 - Remove looping in ts_usb_tr, it will be + useless. + +* 199811282020 - Make a direct step to SETUP state from + error, done or aborted to evitate the + overhead of resetting to move to + inserted state. + +* 199811182359 - In usbd.c, rename all of those to + usb_pipe_(open|close)(), + usb_pipe_host_(open|close)(), + usb_pipe_dev_(open|close)(), + usb_pipe_endp_(open|close)(). + + 199811292333 -> Done + +* 199811182118 - Rename ts_usb_open to ts_usb_pipe + + 199811292333 -> done + +* 199811181220 - The _a_init() functions are suboptimal + on cleaning the allocated + structures. Move it to zero all the + allocated array and then call _clean() + on first structure and then copy that to + the rest of the structures. + +* 199811171047 - Add a per-device semaphore to evitate + collisions between a process making + transactions to a device and the khubdd + detaching it at the same + time. Transaction code should use and + ack that semaphore, as well as the + khubdd code. usb_device_detach() should + not need to worry about it. + +* 199808240218 - Add device version code + (device->release) to the device matching + logic. + +* 199807231448 - The proper name for the structure house + keeping methods should be: + + Old name Correct name + TYPE_clean TYPE_clean + TYPE_init TYPE_alloc + TYPE_free TYPE_release + TYPE_destroy TYPE_destroy + + _clean() should just clean, without + checking anything else; _alloc() should + just alloc, not cleaning, and should be + inlined; __release() should release, + checking, without cleaning; _destroy() + should release everything, unregistering + from external stuff which registers to + the structure. + + 199808272359 -> DONE. + + Now have to split the _clean() methods + in a composition. One is the _zero(), + which would clean to zero an structure + and the other _nozero(), which would + assign the non-zero needed initial + values. + + This way, a _clean() on a composite + structure would do a _zero() on it and + then call _nozero() on it's composite + parts. Now we are repeating a lot of + memset's. + + 199811292333 -> done + +* 199807231440 - Rename usb_request_dataless() to + usb_request(). + +* 199807212245 - Many functions could perfectly live + without returning anything, as errors + will only be checked with assertions on + ... and when the code is perfect (year + 4345e+4, day up, day down), they won't + be needed. + +* 199807211832 - Move all the methods in the host struct + to a ts_usb_hci_methods structure and + keep it into ts_usb_hci, as they all are + passed [or can infere from passed data] + which host they're using. Thus, it + doesn't make sense to replicate all that + data. + + 199808280001 -> Deprecated. It'd add another + indirection and it is not worth the + waste. + +* 199807130057 - Probably the uhci root hub init code and + the hubd_config code can be somehow + merged, there's a lot in common. + +* 199807110237 - ts_*_clean() are generally setting all + to zero, so they should be moved to do + memset() to zero of the full struct, + then call ts_*_clean() on each composite + member and set any other field to it's + clean state (if not zero). + + 199808280002 -> DONE. Now should split in _zero() and + _nozero(). + +* 199806211720 - The ts_*_init() functions can be inlined + most of all. Do it. + +* 199806211405 - the ts_*_free() functions should _not_ + call ts_*_clean() at the very end. This + should be left to the caller's + discretion, as normally we do a free() + on it later and makes no sense to clear + it. + +* 199806121910 - See the devfs + http://www.atnf.csiro.au/~rgooch/linux/devfs.txt, + it may be interesting for USB. + +* 199805161112 - on usb_close(), should I abort or flush? + currently it aborts, but I'd prefer it + to flush xfers, as that's the normal + Unix way. + +* 199805052319 - Check within the PCI cfg address at + offset 0x60 the USB release number. + +* 199804262135 - Add parameters for: + + - Default langID to get + + - Default code to translate UNICODE + charset to [UNICODE->ISO?] + +* 199804081649 - Port numbers for the hubs range from 1 + to n, not from 0 to n-1; check this. + +- 199804081627 - All operations which make requests are + using almost the same structure, which + is being repeated all over the + code. It should be tried to collapse it + in a single function, which given the + parameters [the request, the trbuf?, + error msgs et al] did it. + + 199807211834 -> Done with the + usb_request_data[less]() functions. + +* 199804071954 - All drivers *must* acknowledge APM + events, by registering with + apm_register_callback(). This should be + a must for distributing them. + + Many drivers will even need an ioctl() to + mark when may reject or always accept a + suspend [cameras, ie]. Some other + drivers always must accept a suspend + [kbd, mice]. See 'USB-APM Interactions', + Intel Corporation. + + Even more, I'd vote for making a fixed + IOCTL, of obligatory inclusion, which + would make it selectable if we want to + accept or deny APM suspends based on + used criteria (but shipped with the most + common/acceptable default). This should + allow us, for example, to let a module + player going on and be able to have the + system suspend if we don't do any other + stuff, by telling the audio driver to + accept suspends. + + The nice way for doing this could be to + have a global per-driver flag who would + be set and unset by different driver + operations. When it is set, no suspends + would be acknowledged, when unset they + would. Perhaps a finer bitmask matching + APM's events could be made. + +* 199803041640 - All operations which operate on + endpoints/xfers should actualize the + stat member of the endpoint structure. + +* 199802121632 - All the functions at USBD should honour + read/write locks (except the read/write + methods in usbd-rw.c and + usbd-crw.c). Check that. + + However, this is troubly. We got to take + into account that if a device is + suddenly unplugged, the khubdd will + simply destroy it ... geeze! + +* 199802101621 - Find a better way for the declaration + and implementation of the ts_Nslists. + +* 199802091243 - The ts_*_init*() and ts_*_free*() should + be optimized out by inlining them. + +- 199801111639 - Crap. The driver code is not working + properly when re-registrating a previous + registered and then unloaded driver, + causing a memory leak somewhere. + + 199802112036 -> Fixed. Has involved a check of all + the destructors system, as it was + caused by a faulty sequence of + resources liberation. + +* 199801111639 - We should fix the case of drivers + having same attributes/codes, as they'd + overwrite themselves. Should add a + signature generation function and add + that signature to the driver structure + (the signature could be generated from + the driver's attributes/codes and + strings in the *names, but it should be + constant from invocation to invocation). + +* 199801091219 - As an aid to enhance portability, should + add wrappers for most kernel-related + interface functions, such as + verify_area(), *_lock(), request_*(), + wake_up(), sleep_on(), wait_queues ... + +* 199801090015 - All functions should convert to little + endian when needed, hiding this from the + API user, except for non USB defined + descriptors (class descriptors ... etc), + for which we don't know anything. + +* 199801082059 - Change the term 'attributes' in docs to + 'codes'. + +* 199712312010 - Move the file interface + (file-operations.c) stuff to a driver, + the Raw Driver (rawd), which will + implement all these, with a vicsp of + 0000.0000.00.00.00. It will have + assigned a single major and minor + numbers, and the selection of bus, + device and endpoint will be done via + ioctl. + + Control xfers may be done by forcing + the first part of the data buffer to be + the request data (even for reading from + the devices; it'll just be not + overwritten). + + Control xfers should to default endpoint + that have to be done via the USB API + should be filtered out and interdicted + or rerouted to the API, to keep in sync + device's state with the in-kernel data + structures. + +* 199712311759 - Do a compilation with SMP enabled to + check locks. Also check and fix in many + places, as there maybe some + deadlocks. Need to add read locks + upgradeable to write locks. + +* 199712311744 - A deep look is neccessary all around + the code to optimize the checks. Checks + are done everywhere, but most are + 'useless' as many functions will only + fail when assertions are enabled. Thus, + an optimization analysis has to be done, + tracking every posible call trace to + check which checks should be assertions + and which assertions should be checks. + +- 199712310517 - I seem stupid. Check all the code where + anything is added to any list, as the + list operations ALREADY WRITE LOCK THE + LIST. Just got to lock the added item if + applies. + + 199712311932 -> Done. + ++ 199712302349 - Revise all the destructor/registration + system. I'm afraid will have to add an + special function for each case as + destructor, as I'll find plenty of + memory leaks. + + 199712311742 -> Almost done, at least for devices, + hosts, drivers and HCIs. The + registration system for devices is + based upon the usb_device_attach() + and _detach() functions. For the rest + is based on usb_xxx_[un]register(). + +- 199712301734 - In the slists, move all the macros to + inline functions. + + 199712311741 -> Done. + +- 199712281652 - Separate usb-dtor.h into usb-dtor.h and + usb-dtor-impl.h, separating the + declaration code from the implementation + code, as this will imply we don't have + to make gdlf.h available to all the + includes. + + 199712300432 -> Fixed with the environments stuff, as + in usb-slist.h + +- 199712270048 - Unify all the use counts names, using + `usecnt' as variable name (and use the + atomicity stuff below). + + 199712311741 -> Done; most usecounts are hold now in + the nodes of lists. + +- 199712261704 - Move all the use count stuff to use the + macros at asm/atomic.h (atomic_*()) to + guarantee atomicity. + + 19980209 -> Done. + +* 199712072137 - As an open descriptor can be aborted and + unset at any moment by external causes, + or whatever reason, ALL the functions + accepting a ts_usb_open* must check for + it's validity before using, except in + the case it is going to be directly + passed to a lower-level function. Open + descriptors will probably require locks + and use counts. + +- 199712052140 - The list of unconfigured devices using + the unnext member of the ts_usb_device + struct is a dirty damn quick + hack. Should reimplement it in an non so + expensive way (we're wasting a pointer + on each structure). However, I'm not + that sure. Opinions? + + 199712311741 -> Now it is implemented inside a triple + single-list for the devices, thus, it + is already solved. + +- 199710112055 - Asked by the Berlin group: make a hook + on usb_register_device() to get notices + of when a device is registered. Could + also extend to unregistering. + + 199712????? -> Done with the driver stuff. You can + create a pseudo-driver for getting + the notifications, as as soon as a + device is plugged in, it tries to + configure it. Register a driver of + the proper type and you've got your + hook. Later, each driver should + implement it's own internal hooks. + +- 199710012146 - Move *.h which will have to go to linux/ + to usb-*.h. + + 199712????? -> Done + +* 199709042312 - Should make a paper introducing to USB + and it's concepts + + 19971222??? -> Done ... in spanish. Is an article for + the Linux Focus Magazine. However, + should translate to english. + +* 199706211706 - Reimplement using spinlocks, atomics or + cli/sti the parts which need to be + atomic, and also decide which ones need + which types of lock. Also check that + there are no printk()s on protected + sections. + Take a look at asm/spinlock.h. + + 199713050048 -> The locks stuff doesn't look very + well. Should fully check it, put'em + at every needed place and check if + gotta use _irq or _irqsave ??? Take a + look at the spinlocks doc. + +* 199705111400 - Should write a paper describing the + over-all architecture of the driver; + something like a road-map. + ++ 199704041603 - All the data structures house-keeping + methods should be cleaned to be posible + to use them from user-land (thus + removing all kernel code usage, which is + done in some of them when freeing). + + 199706222222 -> Partially done. Got to check it + +* 199704231959 - When we're done with the transfer + scheduler, we should note that on + section 5.9.3 of the USB Spec 1.0, + there's a way to use the bit-stuffing to + force bandwitdh reclamation. That's + already "done" on UHCI, however, there + should be a way to auto-tune it based on + statistics of failed control/bulk + transactions caused by babble errors. + + This should be an HCI issue, but there + should be a common tuning method. + +- 199704231901 - On all the _free() functions, + when clearing, we're using the + corresponding _init() function, which + seems to be a little performance hit, as + GCC isn't able of optimizing the first + comparison when inlining (even on -O3), + so perhaps it would be a nice idea to 1) + put the cleaning/initializing code into + a macro and put that macro on the + _init() and _free() functions, or 2) + duplicate it by hand (with the risk of + forgetting something). + + 199705041552 -> Re-implemented in some modules, + mostly UHCI's and some others, using + a macro named *_clean(). I should + export those macros in the .h to make + them available. + + 199706222222 -> Done. + +- 199704231844 - VERY IMPORTANT! This is a damn + performance impact I've been too silly to + notice. All the functions in uhci.c (and + probably more) spend a lot of damn time + dereferencing arrays looking for the + right iobase or what the fuck. Modify it + all to accept only iobase numbers, + ts_uhci_host structs ... etc ... + + 199706222222 -> Almost reimplemented in every + place. Should check to be sure. + + 199712?????? -> Done + +- 199704202048 - Move all the hardware specific stuff + from ts_usb_host to ts_usb_host->hci + + 199706222222 -> Done. Got to test it. + +* 199703112031 - Add an usb_strerror() function to + translate all the `usb_errno' codes to + something quite readable. + +- 199703022330 - Got to start thinking how to make the + kernel interface to transmit/receive to + devices. My idea is to allow a set of + functions (open/configure, read, write, + ioctl/suspend/resume, close), being the + device identified by it's controller + number and device's address. + + 199705041456 -> Seems to be more or less + defined. However, it's sure I'll have + to change it, as more ideas come out ... + + 199712?????? -> Finished. Had to add methods for + control read/write, but it looks ok + now. Also had to add a method to set + the SOF. + + 199712311749 -> Done. + +- 199703022332 - What'about the hierarchical structure + in which each host has an array of + pointers to its devices, and later a + hierarchical tree starting with the root + hub, which will have an array of ports, + describing this one the port (status et + al) and a link to the connected device + if any. If the device is a hub, repeat + the tale. If it is a device, just a + device you'll have :). + + 199712????? -> Each host has a list of devices + connected to it, linked via the + "hostnext" member of each device + structure. There's a global list of + devices, linked via the "next" + member. Later, each host has a root + hub pointer to the hub structure + which holds an array of ports. On + each port structure there's a pointer + to the connected device [unless none + is connected]. + + 199712311746 -> The devices are members of three + lists implemented via a triple-node + list (ts_3slist). First one is for + the general list of devices, to which + every device in the UUSBD + belongs. Second is for list of + devices connected to each host, and + third is for the list of unconfigured + devices, holding devices who still + are in need of configuration. + +* 199703022336 - What'bout having some sleep? diff -Naur linux.225/drivers/uusbd/audd/Makefile linux.225.visws/drivers/uusbd/audd/Makefile --- linux.225/drivers/uusbd/audd/Makefile Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/audd/Makefile Sat Nov 14 09:16:54 1998 @@ -0,0 +1,48 @@ +# +# Makefile for the Universal USB Audio Devices Driver, Linux flavour +# ------------------------------------------------------------------ +# +# Distributed under the terms of the GNU Public License Version 2 +# See files COPYRIGHT and COPYING at the root distribution directory + +SUB_DIRS := +MOD_IN_SUB_DIRS := $(SUB_DIRS) +ALL_SUB_DIRS := $(SUB_DIRS) + +AUDD_OBJS := cfg.o generic.o hkeep.o driver.o +AUDD_XOBJS := #audd-symtab.o +AUDD_TARGET := usb-audd.o + +# Libraries +L_OBJS := +LX_OBJS := +# L_TARGET (just one) will be the archive of all the L_OBJS and LX_OBJS +L_TARGET := + +# Modules +MIX_OBJS := +MI_OBJS := +# Made by modules. These ones get symlinked at $(TOPDIR)/modules and +# added to the list of modules +M_OBJS := $(AUDD_TARGET) dummy_module + +# Objects +OX_OBJS := $(AUDD_XOBJS) +O_OBJS := $(AUDD_OBJS) +# O_TARGET (just one) will be made by compiling+linking OX_OBJS and O_OBJS +O_TARGET := $(AUDD_TARGET) + +include ../Makefile.inc +ifdef NOT_IN_LINUX_KERNEL +export EXTRA_CFLAGS += -I../include +endif + +include $(TOPDIR)/Rules.make +include ../Makefile-rules.inc + +.PHONY: dummy_module +dummy_module: +ifeq ($(CONFIG_USB_AUDD),m) + for v in $(M_OBJS); do echo `pwd`/$$v; done >> $(MODULES_FILE) +endif + diff -Naur linux.225/drivers/uusbd/audd/README linux.225.visws/drivers/uusbd/audd/README --- linux.225/drivers/uusbd/audd/README Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/audd/README Fri Aug 28 16:58:15 1998 @@ -0,0 +1,7 @@ + + The UUSBD Audio Devices Driver (audd/usb-audd.o) + + This is the driver for the USB devices which comply with the +USB Audio Devices Class. It's currently embrionary and non-operative. + + Iñaky diff -Naur linux.225/drivers/uusbd/audd/cfg.c linux.225.visws/drivers/uusbd/audd/cfg.c --- linux.225/drivers/uusbd/audd/cfg.c Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/audd/cfg.c Sun Apr 4 17:32:48 1999 @@ -0,0 +1,305 @@ + +/* USB Audio Devices Driver v$Revision: 1.9 $ + * + * (C) 1997-99 by Iñaky Pérez González + * + * Distributed under the terms of the GNU Public License Version 2 + * See files COPYRIGHT and COPYING at the root distribution directory + * + * $Id: cfg.c,v 1.9 1999/04/05 00:32:48 inaky Exp $ + * + * Changelog at the bottom + * + * USB Audio Devices - Configuration + * --------------------------------- + * + * This is the embrion of the USB AUDD. + * + */ + +#include + +#define GDLF_IDENT "USB-AUDD" +#define GDLF_LOCAL /* Define if want local settings */ +#define GDLF_DEF_LOGLEVEL 9 +#define GDLF_ASSERTIONS /* want assertions (#undef if not) */ +#define GDLF_FNTRACE /* want function traces */ +#define GDLF_LOCATIONS /* want locations in log messages */ +#include + +#include + + + /* FIXME: Detailed desc + * + * First time we are called (*paudd == NULL), we just create an + * audd structure, fill it's dtor, register it, fill in the data + * from the descriptors and assign it to cfel's data, + * referencing. Then we finish by setting the cfel's configured + * flag to 1. + * + * Compliance: USB Spec 1.0 xxxx + * + * Parameters: + * + * type descr + * + * Global: + * + * type name descr + * + * Returns: + * + * int Number of cfels configured, errno code < 0 on + * error. + * + * Global: + * + * type name descr + */ + +int audd_config_iface (ts_audd** paudd, ts_usb_cfel* cfel, + ts_usb_device* device, ts_usb_cfg* cfg, + ts_usb_iface* iface) +{ + int errcode; + ts_audd *audd; + + gdlf_fntrace ("audd_config_iface (0x%p, 0x%p, 0x%p, 0x%p, 0x%p)", + paudd, cfel, device, cfg, iface); + gdlf_aassert (paudd != NULL, return -EINVAL); + gdlf_aassert (device != NULL, return -EINVAL); + gdlf_aassert (cfel != NULL, return -EINVAL); + gdlf_aassert (cfg != NULL, return -EINVAL); + gdlf_aassert (iface != NULL, return -EINVAL); + gdlf_aassert (iface->active != NULL, return -EINVAL); + gdlf_aassert (&iface->active->cfel == cfel, return -EINVAL); + gdlf_aassert (cfel->class == AUDD_CLASS, return -EINVAL); + + /* Create new audio structure? */ + + if (*paudd == NULL) /* got to create a new one */ + { + audd = ts_audd_init(); + if (audd == NULL) + { + gdlf_err ("No memory to configure interface %d " + "of device (%d %d)\n", + iface->addr, + usb_host_addr (device), usb_dev_addr (device)); + audd_errno = -USBE_NO_MEMORY; + usb_errno = -USBE_NO_MEMORY; + return -ENOMEM; + } + ts_3snode_ref (&device->msnode); + audd->device = device; + *paudd = audd; + cfel->data = &audd->snode; /* reference later */ + errcode = audd_register (audd); /* register ... */ + if (errcode < 0) /* ok? ... */ + return errcode; /* ... no, audd_register() complained */ + } + else + audd = *paudd; + ts_snode_ref (&audd->snode); + cfel->configured = (unsigned long)audd; + + /* + * Ok, initialize the interface data accordingly to it's + * subclass. + */ + +#if 0 + switch (iface->active->cfel.subclass) + { + } +#endif + + return 1; +} + + /* Configure a device class interface + * + * This function may be used to be called from audd_config() to + * configure the class part of a configurable element. + * + * Audio devices have many interfaces which are independent, but + * for the audio purposes, we need them all, so the first time we + * are called on a device, we search for all the interfaces we + * could be interested in (from the active USB configuration) and + * configure them. + * + * Returns: + * + * int Number of cfels configured, errno code < 0 on + * error. + * + * Global: + * + * int audd_errno On error, error code. + * int usb_errno On error, error code. + */ + + +int audd_config (ts_usb_cfel* cfel, ts_usb_device* device, + ts_usb_cfg* cfg, t_usb_cfg cfg_idx, + ts_usb_iface* iface, t_usb_iface iface_idx, + ts_usb_aset* aset, t_usb_aset aset_idx, __u32 flags) +{ + int errcode, cfels = 0; + ts_audd *audd = NULL; + ts_usb_iface *ifaceitr, *iface_top; + + gdlf_fntrace ("audd_config (0x%p, 0x%p, 0x%p, " + "0x%p, 0x%p, %u)", cfel, device, cfg, + iface, aset, flags); + gdlf_aassert (cfel != NULL, return -EINVAL); + gdlf_aassert (device != NULL, return -EINVAL); + + if (cfel->class != AUDD_CLASS) + { + gdlf_err ("Pretended to configure as audio non-audio " + "class interface %d of device (%d %d)\n", + iface->addr, + usb_host_addr (device), usb_dev_addr (device)); + return 0; + } + + /* Ok, configure this cfel */ + + errcode = audd_config_iface (&audd, cfel, device, cfg, iface); + if (errcode <= 0) + { + gdlf_err ("Couldn't configure interface %d of device (%d %d)\n", + iface->addr, + usb_host_addr (device), usb_dev_addr (device)); + return errcode; + } + else if (errcode > 0) + cfels++; + + /* + * Walk all the device iface's, searching for more audd ifaces + */ + + for (ifaceitr = cfg->iface, iface_top = ifaceitr + cfg->ifaces; + ifaceitr < iface_top; ifaceitr++) + { + gdlf_aassert (ifaceitr->active != NULL, continue); + + if (ifaceitr->active->cfel.class == AUDD_CLASS) + { + gdlf_debug ("Found interface %d of device (%d %d)\n", + ifaceitr->addr, + usb_host_addr (device), usb_dev_addr (device)); + errcode = audd_config_iface (&audd, &ifaceitr->active->cfel, + device, cfg, ifaceitr); + if (errcode <= 0) + gdlf_debug ("Couldn't configure interface???\n"); + else if (errcode > 0) + cfels++; + } + } + return cfels; +} + + + /* Unconfigure all cfels configured by this driver + * + * This function may be used to unconfigure a driver's + * class-configured configurable elements. + * + * Parameters: + * + * ts_usb_device* Pointer to the device structure to + * unconfigure. + * + * unsigned USB_CFG_* flags indicating why is this + * function called. + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + * + * Global: + * + * int audd_errno On error, error code. + * int usb_errno On error, error code. + */ + +int audd_unconfig (ts_usb_device* device, unsigned flags) +{ + t_usb_cfg cfg_cnt; + ts_usb_cfg *cfg; + ts_usb_iface *iface, *iface_top; + ts_usb_aset *aset, *aset_top; + + gdlf_fntrace ("audd_unconfig (0x%p, %u)", device, flags); + gdlf_aassert (device != NULL, return -EINVAL); + + for (cfg_cnt = 0; cfg_cnt < device->pcfgs; cfg_cnt++) + { + cfg = device->pcfg[cfg_cnt]; + if (cfg == NULL) /* unloaded? skip */ + continue; + + /* Walk cfg's interfaces */ + + for (iface = cfg->iface, iface_top = iface + cfg->ifaces; + iface < iface_top; iface++) + { + /* Walk the iface's asets */ + + for (aset = iface->aset, aset_top = aset + iface->asets; + aset < aset_top; aset++) + + /* cfged by us? */ + + if (aset->cfel.configured + && aset->cfel.data + && aset->cfel.data->dtor.fn + == (tf_dtor)audd_destroy) + { + ts_snode_unref (aset->cfel.data, NULL); + aset->cfel.data = NULL; + aset->cfel.configured = 0; /* uncfged */ + } + } + } + return 0; +} + +/* Log: + * + * $Log: cfg.c,v $ + * Revision 1.9 1999/04/05 00:32:48 inaky + * Updated dates + * + * Revision 1.8 1998/12/16 00:19:44 inaky + * Added patch by Thomas Reiner to make it compile. + * + * Revision 1.7 1998/11/14 17:17:10 inaky + * Moved the include files to uusbd/include/uusbd, to ease integration + * into the Linux kernel. + * + * Revision 1.6 1998/10/31 02:15:06 inaky + * Removed all the d_* pointers from ts_usb_cfel and collapsed them into + * a single pointer; only one was really used. + * + * Revision 1.5 1998/08/30 13:53:15 inaky + * Comment fixes. + * + * Revision 1.4 1998/08/28 23:57:53 inaky + * Unscrewed down .. + * + * Revision 1.2 1998/08/25 04:05:50 inaky + * Added the basic configuration code. + * + * Revision 1.1 1998/08/24 22:16:57 inaky + * Added first revision of embrionic audio driver + * + * + */ + + + diff -Naur linux.225/drivers/uusbd/audd/driver.c linux.225.visws/drivers/uusbd/audd/driver.c --- linux.225/drivers/uusbd/audd/driver.c Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/audd/driver.c Sun Apr 4 17:32:49 1999 @@ -0,0 +1,290 @@ + +/* USB Audio Devices Driver v$Revision: 1.8 $ + * + * (C) 1997-99 by Iñaky Pérez González + * + * Distributed under the terms of the GNU Public License Version 2 + * See files COPYRIGHT and COPYING at the root distribution directory + * + * $Id: driver.c,v 1.8 1999/04/05 00:32:49 inaky Exp $ + * + * Changelog at the bottom + * + * USB Audio Devices - Driver management + * ------------------------------------- + * + * This is the embrion of the USB AUDD. + * + */ + + +#include /* __init */ +#define __NO_VERSION__ +#include /* MOD_*_USE_COUNT */ +#include /* locks */ + +#include + +#define GDLF_IDENT "USB-AUDD" +#define GDLF_LOCAL /* Define if want local settings */ +#define GDLF_DEF_LOGLEVEL 9 +#define GDLF_ASSERTIONS /* want assertions (#undef if not) */ +#define GDLF_FNTRACE /* want function traces */ +#define GDLF_LOCATIONS /* want locations in log messages */ +#include + +#include + + +extern atomic_t usecnt; +volatile int audd_errno = 0; + +#define NAME /* short!! */ \ + "USB Audio Devices Driver v$Revision: 1.8 $" + +#define COPYRIGHT \ + "(c) 1998 Inaky Perez Gonzalez " \ + "" + +#define VENDOR 0 +#define VENDORNAME \ + NULL + +#define PRODUCT 0 +#define DEVICENAME \ + NULL + +#define CLASS AUDD_CLASS +#define CLASSNAME \ + "USB Audio Devices" + +#define SUBCLASS 0 +#define SUBCLASSNAME \ + NULL + +#define PROTOCOL 0 +#define PROTOCOLNAME \ + NULL + +#define SNODE_NULL { {NULL}, NULL, 0} + +ts_usb_driver* audd_driver = NULL; + + + /* + * Linux module support + */ + +#ifdef MODULE + +int init_module (void) +{ + return audd_init(); +} + +void cleanup_module (void) +{ + audd_release(); + audd_shutdown(); + return; +} + +#endif + + + /* Initialize the audd driver + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + * + * Global: + * + * int audd_errno On error, error code. + * int usb_errno On error, error code. + */ + +int __init audd_init (void) +{ + int errcode; + + gdlf_fntrace ("audd_init()"); + gdlf_info (NAME "\n"); +#ifdef MODULE + gdlf_info (COPYRIGHT "\n"); +#endif + + audd_driver = ts_usb_driver_init(); + if (audd_driver == NULL) + { + usb_errno = audd_errno = -USBE_NO_MEMORY; + return -ENOMEM; + } + + /* Set driver's attributes */ + + audd_driver->vendor = VENDOR; + audd_driver->product = PRODUCT; + audd_driver->class = CLASS; + audd_driver->subclass = SUBCLASS; + audd_driver->protocol = PROTOCOL; + + /* Set info */ + + audd_driver->name = NAME; /* driver name */ + audd_driver->copyright = COPYRIGHT; /* driver copyright */ + audd_driver->vendorname = VENDORNAME; /* device's vendor name */ + audd_driver->productname = DEVICENAME; /* device's name */ + audd_driver->classname = CLASSNAME; /* class' name */ + audd_driver->subclassname = SUBCLASSNAME; /* subclass' name */ + audd_driver->protocolname = PROTOCOLNAME; /* protocol name */ + + audd_driver->config = audd_config; /* config method */ + audd_driver->unconfig = audd_unconfig; /* unconfig method */ + audd_driver->reference = audd_reference; /* reference method */ + ts_snode_ref (&audd_driver->snode); /* we hold a reference to it */ + + ts_slist_clean (&audd_list); /* initialize the list */ + errcode = usb_drv_register (audd_driver); /* register driver */ + if (errcode) + { + gdlf_err ("Cannot register driver: " + "errno/usb %d/%d\n", + errcode, usb_errno); + if (audd_driver->snode.next == NULL) + { + ts_usb_driver_clean (audd_driver); + usb_kfree (audd_driver); + } + audd_errno = -USBE_DRIVER_CANT_REG; + return errcode; + } + + /* FIXME: do you class' stuf */ +#warning FIXME: do class stuff! + + return 0; +} + + + /* Release the audd driver + * + * Do what is needed to ensure the use count of the driver is + * zero and can be unloaded from the kernel. + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + * + * Global: + * + * int audd_errno On error, error code. + * int usb_errno On error, error code. + */ + +int audd_release (void) +{ + gdlf_fntrace ("audd_release()"); + +#warning FIXME: audd_release() not implemented! + + return -ENOSYS; +} + + + /* Shutdown the skel driver + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + * + * Global: + * + * int audd_errno On error, error code. + * int usb_errno On error, error code. + */ + +int audd_shutdown (void) +{ + gdlf_fntrace ("audd_shutdown()"); + + /* FIXME: do you class' stuf */ + + ts_snode_unref (&audd_driver->snode, NULL); + return usb_drv_unregister (audd_driver); +} + + + /* Driver reference + * + * The 'reference' method is used when we take any of the driver's + * code or data structures to use it. If so, we call it with a + * positive argument (one reference, regardless the value of the + * _positive_ number). When we are done, we release the reference + * calling it with a negative number. It always returns the number + * of references or < 0 on error. Calling it with an argument of + * zero will just return the number of references. + * Compliance: USB Spec 1.0 xxxx + * + * Parameters: + * + * type descr + * + * Global: + * + * type name descr + * + * Returns: + * + * type descr + * + * Global: + * + * type name descr + */ + +int audd_reference (ts_usb_device* device, int n) +{ + gdlf_fntrace ("audd_reference (0x%p, %d)", device, n); + gdlf_aassert (device != NULL, return -EINVAL); + + if (n > 0) + { + atomic_inc (&usecnt); + MOD_INC_USE_COUNT; + } + else if (n < 0) + { + atomic_dec (&usecnt); + MOD_DEC_USE_COUNT; + } + return atomic_read (&usecnt); +} + +/* Log: + * + * $Log: driver.c,v $ + * Revision 1.8 1999/04/05 00:32:49 inaky + * Updated dates + * + * Revision 1.7 1998/12/16 00:19:45 inaky + * Added patch by Thomas Reiner to make it compile. + * + * Revision 1.6 1998/11/14 17:17:11 inaky + * Moved the include files to uusbd/include/uusbd, to ease integration + * into the Linux kernel. + * + * Revision 1.5 1998/08/30 13:53:27 inaky + * Comment fixes. + * + * Revision 1.4 1998/08/28 23:58:23 inaky + * Unscrewed off. + * + * Revision 1.2 1998/08/25 04:06:02 inaky + * Removed module stuff. + * + * Revision 1.1 1998/08/24 22:16:58 inaky + * Added first revision of embrionic audio driver + * + */ + diff -Naur linux.225/drivers/uusbd/audd/generic.c linux.225.visws/drivers/uusbd/audd/generic.c --- linux.225/drivers/uusbd/audd/generic.c Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/audd/generic.c Sun Apr 4 17:32:50 1999 @@ -0,0 +1,125 @@ + +/* USB Audio Devices Driver v$Revision: 1.8 $ + * + * (C) 1997-99 by Iñaky Pérez González + * + * Distributed under the terms of the GNU Public License Version 2 + * See files COPYRIGHT and COPYING at the root distribution directory + * + * $Id: generic.c,v 1.8 1999/04/05 00:32:50 inaky Exp $ + * + * Changelog at the bottom + * + * USB Audio Devices - Generic stuff + * --------------------------------- + * + * This is the embrion of the USB AUDD. + * + */ + +#include + +#define GDLF_IDENT "USB-AUDD" +#define GDLF_LOCAL /* Define if want local settings */ +#define GDLF_DEF_LOGLEVEL 9 +#define GDLF_ASSERTIONS /* want assertions (#undef if not) */ +#define GDLF_FNTRACE /* want function traces */ +#define GDLF_LOCATIONS /* want locations in log messages */ +#include + +#include + + + /* Allocates and initializes to a known state a ts_audd* + * structure. + * + * Returns: + * ts_audd* Pointer to newly allocated hub structure. Must + * be freed with usb_kfree(). + */ + +ts_audd* ts_audd_init (void) +{ + ts_audd* audd; + + gdlf_fntrace ("ts_audd_init()"); + audd = usb_kmalloc (sizeof (ts_audd), GFP_KERNEL); + if (audd == NULL) + { + gdlf_err ("Cannot allocate space for a " + "ts_audd structure\n"); + return NULL; + } +#warning FIXME +/* ts_audd_clean (audd); */ + return audd; +} + + + /* Free a ts_audd structure's contents. + * + * Checks for the magic number being ok. Remember that the + * structure iself is not freed, just it's contents. + * + * Parameters: + * + * ts_hubd* Pointer to the hub structure to free. + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + * + * Global: + * + * int usb_errno Modified on error with an USB error code. + */ + +void ts_audd_release (ts_audd* audd) +{ + gdlf_fntrace ("ts_audd_free (0x%p)", audd); + gdlf_aassert (audd != NULL, return); + gdlf_assert (audd->snode.dtor.fn == (tf_dtor)audd_destroy); + gdlf_assert (ts_slist_next (&audd->snode) == NULL); + + if (audd->device) + ts_3snode_unref (&audd->device->msnode, NULL); + + if (audd->aic) + { +#warning FIXME: finish this!!! +#if 0 + ts_audd_aic_a_release (audd->aic, audd->aics); +#endif + usb_kfree (audd->aic); + } + return; +} + + +/* Log: + * + * $Log: generic.c,v $ + * Revision 1.8 1999/04/05 00:32:50 inaky + * Updated dates + * + * Revision 1.7 1998/12/16 00:19:46 inaky + * Added patch by Thomas Reiner to make it compile. + * + * Revision 1.6 1998/11/14 17:17:12 inaky + * Moved the include files to uusbd/include/uusbd, to ease integration + * into the Linux kernel. + * + * Revision 1.5 1998/08/30 13:53:35 inaky + * Comment fixes. + * + * Revision 1.4 1998/08/29 00:02:25 inaky + * unscrewed off + * + * Revision 1.2 1998/08/25 04:06:24 inaky + * Added warning comments on unfinished stuff. + * + * Revision 1.1 1998/08/24 22:16:58 inaky + * Added first revision of embrionic audio driver + * + */ + diff -Naur linux.225/drivers/uusbd/audd/header linux.225.visws/drivers/uusbd/audd/header --- linux.225/drivers/uusbd/audd/header Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/audd/header Sun Apr 4 17:32:51 1999 @@ -0,0 +1,19 @@ + +/* USB Audio Devices Driver v$Revision: 1.4 $ + * + * (C) 1997-99 by Iñaky Pérez González + * + * Distributed under the terms of the GNU Public License Version 2 + * See files COPYRIGHT and COPYING at the root distribution directory + * + * $Id: header,v 1.4 1999/04/05 00:32:51 inaky Exp $ + * + * Changelog at the bottom + * + * USB Audio Devices - + * --------------------------------- + * + * This is the embrion of the USB AUDD. + * + */ + diff -Naur linux.225/drivers/uusbd/audd/hkeep.c linux.225.visws/drivers/uusbd/audd/hkeep.c --- linux.225/drivers/uusbd/audd/hkeep.c Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/audd/hkeep.c Sun Apr 4 17:32:52 1999 @@ -0,0 +1,207 @@ + +/* USB Audio Devices Driver v$Revision: 1.7 $ + * + * (C) 1997-99 by Iñaky Pérez González + * + * Distributed under the terms of the GNU Public License Version 2 + * See files COPYRIGHT and COPYING at the root distribution directory + * + * $Id: hkeep.c,v 1.7 1999/04/05 00:32:52 inaky Exp $ + * + * Changelog at the bottom + * + * USB Audio Devices - + * --------------------------------- + * + * This is the embrion of the USB AUDD. + * + */ + +#include /* locks */ +#include /* MOD_*_USE_COUNT */ + +#include + +#define GDLF_IDENT "USB-AUDD" +#define GDLF_LOCAL /* Define if want local settings */ +#define GDLF_DEF_LOGLEVEL 9 +#define GDLF_ASSERTIONS /* want assertions (#undef if not) */ +#define GDLF_FNTRACE /* want function traces */ +#define GDLF_LOCATIONS /* want locations in log messages */ +#include + +#include + + +ts_slist audd_list; /* list of registered class structures */ + + + /* Unregister an audd element + * + * This is the destructor function. + * + * Parameters: + * + * ts_audd* Class element to unregister + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + * + * Global: + * + * int usb_errno On error, error code. + * int audd_errno On error, error code. + */ + +int audd_unregister (ts_audd* audd) +{ + gdlf_fntrace ("audd_unregister (0x%p)", audd); + gdlf_aassert (audd != NULL, return -EINVAL); + gdlf_assert (audd->snode.dtor.fn == (tf_dtor)audd_destroy); + + /* Let's get it removed from the list */ + + ts_slist_del (&audd_list, &audd->snode); +#warning FIXME: remove this, it makes modules stay for ever + MOD_DEC_USE_COUNT; + return 0; /* bye */ +} + + + /* FIXME: Detailed desc + * + * Compliance: USB Spec 1.0 xxxx + * + * Parameters: + * + * type descr + * + * Global: + * + * type name descr + * + * Returns: + * + * type descr + * + * Global: + * + * type name descr + */ + +int audd_destroy (ts_audd* audd) +{ + t_usb_cfg cfg_cnt; + ts_usb_cfg *cfg; + ts_usb_iface *iface, *iface_top; + ts_usb_aset *aset, *aset_top; + + gdlf_fntrace ("audd_destroy (0x%p)", audd); + gdlf_aassert (audd != NULL, return -EINVAL); + gdlf_assert (audd->snode.dtor.fn == (tf_dtor)audd_destroy); + gdlf_aassert (audd->device, return -EINVAL); + gdlf_aassert (audd->device->pcfg, return -EINVAL); + + ts_snode_ref (&audd->snode); + + /* + * Ok, walk the cfgs, ifaces and aset, searching for an + * element configured for this audd. If found, unref audd and + * keep on. + */ + + for (cfg_cnt = 0; cfg_cnt < audd->device->pcfgs; cfg_cnt++) + { + cfg = audd->device->pcfg[cfg_cnt]; + if (cfg == NULL) /* unloaded? skip */ + continue; + + /* Walk cfg's interfaces */ + + for (iface = cfg->iface, iface_top = iface + cfg->ifaces; + iface < iface_top; iface++) + { + /* Walk the iface's asets */ + + for (aset = iface->aset, aset_top = aset + iface->asets; + aset < aset_top; aset++) + + /* cfged by us? */ + + if (aset->cfel.configured == (unsigned long)&audd->snode) + { + ts_snode_unref (&audd->snode, NULL); + aset->cfel.configured = 0; /* uncfged */ + } + } + } + + audd_unregister (audd); /* unregister */ + ts_snode_unref_nd (&audd->snode); + ts_audd_release (audd); /* clean the struct */ + return 0; /* bye */ +} + + + /* Register an audd element + * + * Parameters: + * + * ts_audd* Class element to register + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + * + * Global: + * + * int usb_errno On error, error code. + * int audd_errno On error, error code. + */ + +int audd_register (ts_audd* audd) +{ + int errcode; + + gdlf_fntrace ("audd_register (0x%p)", audd); + gdlf_aassert (audd != NULL, return -EINVAL); + + ts_dtor_fill (&audd->snode.dtor, (tf_dtor)audd_destroy); + + /* get into the list */ + + errcode = ts_slist_prep (&audd_list, &audd->snode); + + if (errcode) + return errcode; +#warning FIXME: remove this, it makes modules stay for ever + MOD_INC_USE_COUNT; + return 0; /* bye */ +} + +/* Log: + * + * $Log: hkeep.c,v $ + * Revision 1.7 1999/04/05 00:32:52 inaky + * Updated dates + * + * Revision 1.6 1998/12/16 00:19:47 inaky + * Added patch by Thomas Reiner to make it compile. + * + * Revision 1.5 1998/11/14 17:17:13 inaky + * Moved the include files to uusbd/include/uusbd, to ease integration + * into the Linux kernel. + * + * Revision 1.4 1998/08/29 00:05:30 inaky + * Unscrewed off. + * + * Revision 1.2 1998/08/25 04:06:57 inaky + * Added destructor. + * + * Revision 1.1 1998/08/24 22:16:58 inaky + * Added first revision of embrionic audio driver + * + */ + + diff -Naur linux.225/drivers/uusbd/cdcd/Makefile linux.225.visws/drivers/uusbd/cdcd/Makefile --- linux.225/drivers/uusbd/cdcd/Makefile Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/cdcd/Makefile Sat Nov 14 09:17:37 1998 @@ -0,0 +1,43 @@ +# +# Makefile for the Universal USB Driver, Linux flavour +# ---------------------------------------------------- +# +# Distributed under the terms of the GNU Public License Version 2 +# See files COPYRIGHT and COPYING at the root distribution directory + +SUB_DIRS := +MOD_IN_SUB_DIRS := $(SUB_DIRS) +ALL_SUB_DIRS := $(SUB_DIRS) + +CDCD_TARGET := usb-cdcd.o +CDCD_OBJS := class-cfg.o class-generic.o class-hkeep.o driver.o +CDCD_XOBJS := #cdcd-symtab.o + +# Libraries +L_OBJS := +LX_OBJS := +# L_TARGET (just one) will be the archive of all the L_OBJS and LX_OBJS +L_TARGET := + +M_OBJS := $(CDCD_TARGET) dummy_module + +# Objects +OX_OBJS := $(CDCD_XOBJS) +O_OBJS := $(CDCD_OBJS) +# O_TARGET (just one) will be made by compiling+linking OX_OBJS and O_OBJS +O_TARGET := $(CDCD_TARGET) + +include ../Makefile.inc +ifdef NOT_IN_LINUX_KERNEL +export EXTRA_CFLAGS += -I../include +endif + +include $(TOPDIR)/Rules.make +include ../Makefile-rules.inc + +.PHONY: dummy_module +dummy_module: +ifeq ($(CONFIG_USB_CDCD),m) + for v in $(M_OBJS); do echo `pwd`/$$v; done >> $(MODULES_FILE) +endif + diff -Naur linux.225/drivers/uusbd/cdcd/README linux.225.visws/drivers/uusbd/cdcd/README --- linux.225/drivers/uusbd/cdcd/README Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/cdcd/README Tue Oct 13 15:58:38 1998 @@ -0,0 +1,8 @@ + + The UUSBD Communication Devices Class Driver (cdcd/usb-cdcd.o) + + This driver will try to implement all of the CDC class, using +submodules for each Class model. Currently I'm going to implement only +the CAPI ISDN model, as it is the only device I have to test. + + Iñaky diff -Naur linux.225/drivers/uusbd/cdcd/class-cfg.c linux.225.visws/drivers/uusbd/cdcd/class-cfg.c --- linux.225/drivers/uusbd/cdcd/class-cfg.c Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/cdcd/class-cfg.c Sun Apr 4 17:33:43 1999 @@ -0,0 +1,146 @@ + +/* USB Communications Class Devices Driver v$Revision: 1.6 $ + * + * (C) 1998-99 by Iñaky Pérez González + * + * Distributed under the terms of the GNU Public License Version 2 + * See files COPYRIGHT and COPYING at the root distribution directory + * + * $Id: class-cfg.c,v 1.6 1999/04/05 00:33:43 inaky Exp $ + * + * Changelog at the bottom + * + * + * Communications Class Driver - Class inteface to configuration API + * ----------------------------------------------------------------- + */ + +#define __NO_VERSION__ /* We just want MOD_*_USE_COUNT() */ +#include /* MOD_*_USE_COUNT() */ + +#include + +#define GDLF_IDENT "USB-CDCD" +#define GDLF_LOCAL /* Define if want local settings */ +#define GDLF_DEF_LOGLEVEL 9 +#define GDLF_ASSERTIONS /* want assertions (#undef if not) */ +#define GDLF_FNTRACE /* want function traces */ +#define GDLF_LOCATIONS /* want locations in log messages */ +#include + +#include + + + /* Configure a device class interface + * + * This function may be used to be called from cdcd_config() to + * configure the class part of a configurable element. + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + */ + +int cdcd_config (ts_usb_cfel* cfel, ts_usb_device* device, + ts_usb_cfg* cfg, t_usb_cfg cfg_idx, + ts_usb_iface* iface, t_usb_iface iface_idx, + ts_usb_aset* aset, t_usb_aset aset_idx, __u32 flags) +{ + gdlf_fntrace ("cdcd_config (0x%p, 0x%p, 0x%p, " + "0x%p, 0x%p, %u)", cfel, device, cfg, + iface, aset, flags); + gdlf_aassert (cfel != NULL, return -EINVAL); + gdlf_aassert (device != NULL, return -EINVAL); +#warning FIXME: cdcd_config() not implemented! + return -ENOSYS; +} + + + /* Unconfigure a class configured configurable element + * + * This function may be used to unconfigure a driver's + * class-configured configurable elements. + * + * Parameters: + * + * ts_usb_device* Pointer to the device structure to + * unconfigure. + * + * unsigned USB_CFG_* flags indicating why is this + * function called. + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + */ + +int cdcd_unconfig (ts_usb_device* device, unsigned flags) +{ + t_usb_cfg cfg_cnt; + ts_usb_cfg *cfg; + ts_usb_iface *iface, *iface_top; + ts_usb_aset *aset, *aset_top; + + gdlf_fntrace ("cdcd_unconfig (0x%p, %u)", device, flags); + gdlf_aassert (device != NULL, return -EINVAL); + + for (cfg_cnt = 0; cfg_cnt < device->pcfgs; cfg_cnt++) + { + cfg = device->pcfg[cfg_cnt]; + if (cfg == NULL) /* unloaded? skip */ + continue; + + /* Walk cfg's interfaces */ + + for (iface = cfg->iface, iface_top = iface + cfg->ifaces; + iface < iface_top; iface++) + { + /* Walk the iface's asets */ + + for (aset = iface->aset, aset_top = aset + iface->asets; + aset < aset_top; aset++) + + /* cfged by us? */ + + if (aset->cfel.configured + && aset->cfel.data + && aset->cfel.data->dtor.fn + == (tf_dtor)cdcd_destroy) + { + +#warning FIXME: do class stuff here!! + + ts_snode_unref (aset->cfel.data, NULL); + aset->cfel.data = NULL; + aset->cfel.configured = 0; /* uncfged */ + } + } + } + return 0; +} + +/* Log: + * + * $Log: class-cfg.c,v $ + * Revision 1.6 1999/04/05 00:33:43 inaky + * Updated dates + * + * Revision 1.5 1998/11/14 17:18:03 inaky + * Linkage into the kernel made possible. Moved the include files to + * uusbd/include/uusbd, to ease integration into the Linux kernel. + * + * Revision 1.4 1998/11/09 21:32:58 inaky + * Changed the name of the configuration pointer array to pcfg. + * + * Revision 1.3 1998/10/31 02:15:19 inaky + * Removed all the d_* pointers from ts_usb_cfel and collapsed them into + * a single pointer; only one was really used. + * + * Revision 1.2 1998/10/14 21:44:28 inaky + * Moved _class -> ''. + * + * Revision 1.1 1998/10/13 22:58:38 inaky + * First embrionical CDCD driver + * + */ + diff -Naur linux.225/drivers/uusbd/cdcd/class-generic.c linux.225.visws/drivers/uusbd/cdcd/class-generic.c --- linux.225/drivers/uusbd/cdcd/class-generic.c Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/cdcd/class-generic.c Sun Apr 4 17:33:45 1999 @@ -0,0 +1,94 @@ + +/* USB Communications Class Devices Driver v$Revision: 1.4 $ + * + * (C) 1998-99 by Iñaky Pérez González + * + * Distributed under the terms of the GNU Public License Version 2 + * See files COPYRIGHT and COPYING at the root distribution directory + * + * $Id: class-generic.c,v 1.4 1999/04/05 00:33:45 inaky Exp $ + * + * Changelog at the bottom + * + * + * Communications Class Driver - Generic stuff + * ------------------------------------------- + */ + +#include + +#define GDLF_IDENT "USB-CDCD" +#define GDLF_LOCAL /* Define if want local settings */ +#define GDLF_DEF_LOGLEVEL 9 +#define GDLF_ASSERTIONS /* want assertions (#undef if not) */ +#define GDLF_FNTRACE /* want function traces */ +#define GDLF_LOCATIONS /* want locations in log messages */ +#include + +#include + + +ts_cdcd* ts_cdcd_init (void) +{ + ts_cdcd* cdcd; + + gdlf_fntrace ("ts_cdcd_init (void)"); + cdcd = usb_kmalloc (sizeof (ts_cdcd), GFP_KERNEL); + if (cdcd == NULL) + { + gdlf_err ("Cannot allocate space for a " + "ts_cdcd structure\n"); + return NULL; + } + ts_cdcd_clean (cdcd); + return cdcd; +} + + +void ts_cdcd_release (ts_cdcd* cdcd) +{ + gdlf_fntrace ("ts_cdcd_release (0x%p)", cdcd); + gdlf_aassert (cdcd != NULL, return); + gdlf_assert (cdcd->snode.dtor.fn == (tf_dtor)cdcd_destroy); +#warning FIXME: release class stuff + return; +} + + +/* Log: + * + * $Log: class-generic.c,v $ + * Revision 1.4 1999/04/05 00:33:45 inaky + * Updated dates + * + * Revision 1.3 1998/11/14 17:18:04 inaky + * Linkage into the kernel made possible. Moved the include files to + * uusbd/include/uusbd, to ease integration into the Linux kernel. + * + * Revision 1.2 1998/10/14 21:44:48 inaky + * Moved the management code here from the header file. + * + * Revision 1.1 1998/10/13 22:58:38 inaky + * First embrionical CDCD driver + * + * Revision 1.6 1998/08/29 00:07:21 inaky + * Actualized. + * + * Revision 1.5 1998/01/08 12:19:20 inaky + * Added copyright strings to all important files + * + * Revision 1.4 1998/01/01 16:11:41 inaky + * Fixed bug, a couple _init routines where returning NULL instead of the + * pointer :) + * + * Revision 1.3 1997/12/31 05:37:46 inaky + * Fixed some craps. + * + * Revision 1.2 1997/12/30 22:30:35 inaky + * Fixed some bugs. + * + * Revision 1.1 1997/12/30 20:18:04 inaky + * Generic class structure handlings. + * + */ + diff -Naur linux.225/drivers/uusbd/cdcd/class-hkeep.c linux.225.visws/drivers/uusbd/cdcd/class-hkeep.c --- linux.225/drivers/uusbd/cdcd/class-hkeep.c Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/cdcd/class-hkeep.c Sun Apr 4 17:33:46 1999 @@ -0,0 +1,203 @@ + +/* USB Communications Class Devices Driver v$Revision: 1.6 $ + * + * (C) 1998-99 by Iñaky Pérez González + * + * Distributed under the terms of the GNU Public License Version 2 + * See files COPYRIGHT and COPYING at the root distribution directory + * + * $Id: class-hkeep.c,v 1.6 1999/04/05 00:33:46 inaky Exp $ + * + * Changelog at the bottom + * + * + * Communications Class Driver - Class structures housekeeping + * ----------------------------------------------------------- + */ + +#include /* MOD_*_USE_COUNT */ +#include /* locks */ + +#include + +#define GDLF_IDENT "USB-CDCD" +#define GDLF_LOCAL /* Define if want local settings */ +#define GDLF_DEF_LOGLEVEL 9 +#define GDLF_ASSERTIONS /* want assertions (#undef if not) */ +#define GDLF_FNTRACE /* want function traces */ +#define GDLF_LOCATIONS /* want locations in log messages */ +#include +#include + + +ts_slist cdcd_list; /* list of registered class structures */ + + + /* Unregister an cdcd element + * + * This is the destructor function. + * + * Parameters: + * + * ts_cdcd* Class element to unregister + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + */ + +int cdcd_unregister (ts_cdcd* class) +{ + gdlf_fntrace ("cdcd_unregister (0x%p)", class); + gdlf_aassert (class != NULL, return -EINVAL); + gdlf_assert (class->snode.dtor.fn == (tf_dtor)cdcd_destroy); + + /* FIXME: do your class' unregistration stuff */ +#warning FIXME: class stuff not implemented! + + /* Let's get it removed from the list */ + + ts_slist_del (&cdcd_list, &class->snode); + ts_cdcd_release (class); /* clean the struct */ +#warning FIXME: remove this, it makes modules stay for ever + MOD_DEC_USE_COUNT; /* we ain't using the module */ + return 0; /* bye */ +} + + + /* FIXME: Detailed desc + * + * Compliance: USB Spec 1.0 xxxx + * + * Parameters: + * + * type descr + * + * Global: + * + * type name descr + * + * Returns: + * + * type descr + * + * Global: + * + * type name descr + */ + +int cdcd_destroy (ts_cdcd* class) +{ + t_usb_cfg cfg_cnt; + ts_usb_cfg *cfg; + ts_usb_iface *iface, *iface_top; + ts_usb_aset *aset, *aset_top; + + gdlf_fntrace ("cdcd_destroy (0x%p)", class); + gdlf_aassert (class != NULL, return -EINVAL); + gdlf_assert (class->snode.dtor.fn == (tf_dtor)cdcd_destroy); + gdlf_aassert (class->device, return -EINVAL); + gdlf_aassert (class->device->pcfg, return -EINVAL); + + ts_snode_ref (&class->snode); + +#warning FIXME: do your class destruction stuff + + /* + * Ok, walk the cfgs, ifaces and aset, searching for an + * element configured for this class. If found, unref class and + * keep on. + */ + + for (cfg_cnt = 0; cfg_cnt < class->device->pcfgs; cfg_cnt++) + { + cfg = class->device->pcfg[cfg_cnt]; + if (cfg == NULL) /* unloaded? skip */ + continue; + + /* Walk cfg's interfaces */ + + for (iface = cfg->iface, iface_top = iface + cfg->ifaces; + iface < iface_top; iface++) + { + /* Walk the iface's asets */ + + for (aset = iface->aset, aset_top = aset + iface->asets; + aset < aset_top; aset++) + + /* cfged by us? */ + +#warning WARNING: as a sample, we ID the struct with the configured field + + if (aset->cfel.configured == (unsigned long)&class->snode) + { + ts_snode_unref (&class->snode, NULL); + aset->cfel.configured = 0; /* uncfged */ + } + } + } + + cdcd_unregister (class); /* unregister */ + ts_snode_unref_nd (&class->snode); + ts_cdcd_release (class); /* clean the struct */ + return 0; /* bye */ +} + + + /* Register an cdcd element + * + * Parameters: + * + * ts_cdcd* Class element to register + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + */ + +int cdcd_register (ts_cdcd* class) +{ + int errcode; + + gdlf_fntrace ("cdcd_register (0x%p)", class); + gdlf_aassert (class != NULL, return -EINVAL); + + /* FIXME: do your class' stuff */ +#warning FIXME: class stuff not implemented! + + ts_dtor_fill (&class->snode.dtor, (tf_dtor)cdcd_destroy); + + /* get into the list */ + + errcode = ts_slist_prep (&cdcd_list, &class->snode); + if (errcode) + return errcode; +#warning FIXME: remove this, it makes modules stay for ever + MOD_INC_USE_COUNT; /* request we're using the module */ + return 0; /* bye */ +} + +/* Log: + * + * $Log: class-hkeep.c,v $ + * Revision 1.6 1999/04/05 00:33:46 inaky + * Updated dates + * + * Revision 1.5 1998/11/14 17:18:05 inaky + * Linkage into the kernel made possible. Moved the include files to + * uusbd/include/uusbd, to ease integration into the Linux kernel. + * + * Revision 1.4 1998/11/09 21:33:13 inaky + * Changed the name of the configuration pointer array to pcfg. + * + * Revision 1.3 1998/10/31 02:15:36 inaky + * Fixed a tag name ... + * + * Revision 1.2 1998/10/14 21:46:21 inaky + * Moved _class to ''. + * + * Revision 1.1 1998/10/13 22:58:38 inaky + * First embrionical CDCD driver + * + */ + diff -Naur linux.225/drivers/uusbd/cdcd/driver.c linux.225.visws/drivers/uusbd/cdcd/driver.c --- linux.225/drivers/uusbd/cdcd/driver.c Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/cdcd/driver.c Sun Apr 4 17:33:47 1999 @@ -0,0 +1,260 @@ + +/* USB Communications Class Devices Driver v$Revision: 1.4 $ + * + * (C) 1998-99 by Iñaky Pérez González + * + * Distributed under the terms of the GNU Public License Version 2 + * See files COPYRIGHT and COPYING at the root distribution directory + * + * $Id: driver.c,v 1.4 1999/04/05 00:33:47 inaky Exp $ + * + * Changelog at the bottom + * + * + * Communications Class Driver - Driver housekeeping + * ------------------------------------------------- + */ + +#include /* __init */ +#define __NO_VERSION__ +#include /* MOD_*_USE_COUNT */ +#include /* locks */ + +#include + +#define GDLF_IDENT "USB-CDCD" +#define GDLF_LOCAL /* Define if want local settings */ +#define GDLF_DEF_LOGLEVEL 9 +#define GDLF_ASSERTIONS /* want assertions (#undef if not) */ +#define GDLF_FNTRACE /* want function traces */ +#define GDLF_LOCATIONS /* want locations in log messages */ +#include + +#include + + +atomic_t usecnt; + +#define NAME /* short!! */ \ + "Communication Devices Class Driver v$Revision: 1.4 $ " + +#define COPYRIGHT \ + "(c) 1998 Inaky Perez Gonzalez " \ + "" + +#define VENDOR 0 +#define VENDORNAME NULL + +#define PRODUCT 0 +#define DEVICENAME NULL + +#define CLASS 0x2 +#define CLASSNAME \ + "Communication Class Devices" + +#define SUBCLASS 0 +#define SUBCLASSNAME NULL + +#define PROTOCOL 0 +#define PROTOCOLNAME NULL + +#define SNODE_NULL { {NULL}, NULL, 0} + +ts_usb_driver* cdcd_driver = NULL; + + + /* + * Linux module support + */ + +#ifdef MODULE + +int init_module (void) +{ + return cdcd_init(); +} + +void cleanup_module (void) +{ + cdcd_release(); + cdcd_shutdown(); + return; +} + +#endif + + + /* Initialize the cdcd driver + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + */ + +int __init cdcd_init (void) +{ + int errcode; + + gdlf_fntrace ("cdcd_init()"); + gdlf_info (NAME "\n"); +#ifdef MODULE + gdlf_info (COPYRIGHT "\n"); +#endif + + cdcd_driver = ts_usb_driver_init(); + if (cdcd_driver == NULL) + { + usb_errno = -USBE_NO_MEMORY; + return -ENOMEM; + } + + /* Set driver's attributes */ + + cdcd_driver->vendor = VENDOR; + cdcd_driver->product = PRODUCT; + cdcd_driver->class = CLASS; + cdcd_driver->subclass = SUBCLASS; + cdcd_driver->protocol = PROTOCOL; + + /* Set info */ + + cdcd_driver->name = NAME; /* driver name */ + cdcd_driver->copyright = COPYRIGHT; /* driver copyright */ + cdcd_driver->vendorname = VENDORNAME; /* device's vendor name */ + cdcd_driver->productname = DEVICENAME; /* device's name */ + cdcd_driver->classname = CLASSNAME; /* class' name */ + cdcd_driver->subclassname = SUBCLASSNAME; /* subclass' name */ + cdcd_driver->protocolname = PROTOCOLNAME; /* protocol name */ + + cdcd_driver->config = cdcd_config; /* config method */ + cdcd_driver->unconfig = cdcd_unconfig; /* unconfig method */ + cdcd_driver->reference = cdcd_reference; /* unconfig method */ + ts_snode_ref (&cdcd_driver->snode); /* we hold a reference to it */ + + ts_slist_clean (&cdcd_list); /* initialize the list */ + errcode = usb_drv_register (cdcd_driver); /* register driver */ + if (errcode) + { + gdlf_err ("Cannot register driver " + "(errno/usb = %d/%d)\n", + errcode, usb_errno); + if (cdcd_driver->snode.next == NULL) + { + ts_usb_driver_clean (cdcd_driver); + usb_kfree (cdcd_driver); + } + return errcode; + } + + /* FIXME: do you class' stuf */ +#warning FIXME: do class stuff! + + return 0; +} + + + /* Release the cdcd driver + * + * Do what is needed to ensure the use count of the driver is + * zero and can be unloaded from the kernel. + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + */ + +int cdcd_release (void) +{ + gdlf_fntrace ("cdcd_release()"); + +#warning FIXME: cdcd_release() not implemented! + + return -ENOSYS; +} + + + /* Shutdown the skel driver + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + */ + +int cdcd_shutdown (void) +{ + gdlf_fntrace ("cdcd_shutdown()"); + + /* FIXME: do you class' stuf */ + + ts_snode_unref (&cdcd_driver->snode, NULL); + return usb_drv_unregister (cdcd_driver); +} + + + /* FIXME: Detailed desc + * + * The 'reference' method is used when we take any of the driver's + * code or data structures to use it. If so, we call it with a + * positive argument (one reference, regardless the value of the + * _positive_ number). When we are done, we release the reference + * calling it with a negative number. It always returns the number + * of references or < 0 on error. Calling it with an argument of + * zero will just return the number of references. + * Compliance: USB Spec 1.0 xxxx + * + * Parameters: + * + * type descr + * + * Global: + * + * type name descr + * + * Returns: + * + * type descr + * + * Global: + * + * type name descr + */ + +int cdcd_reference (ts_usb_device* device, int n) +{ + gdlf_fntrace ("cdcd_reference (0x%p, %d)", device, n); + gdlf_aassert (device != NULL, return -EINVAL); + +#warning FIXME: add more stuff, keep the device ptr ... + + if (n > 0) + { + atomic_inc (&usecnt); + MOD_INC_USE_COUNT; + } + else if (n < 0) + { + atomic_dec (&usecnt); + MOD_DEC_USE_COUNT; + } + return atomic_read (&usecnt); +} + + +/* Log: + * + * $Log: driver.c,v $ + * Revision 1.4 1999/04/05 00:33:47 inaky + * Updated dates + * + * Revision 1.3 1998/11/14 17:18:06 inaky + * Linkage into the kernel made possible. Moved the include files to + * uusbd/include/uusbd, to ease integration into the Linux kernel. + * + * Revision 1.2 1998/10/14 21:46:51 inaky + * Removed errno and _class stuff. + * + * Revision 1.1 1998/10/13 22:58:38 inaky + * First embrionical CDCD driver + * + */ + diff -Naur linux.225/drivers/uusbd/cdcd/header linux.225.visws/drivers/uusbd/cdcd/header --- linux.225/drivers/uusbd/cdcd/header Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/cdcd/header Sun Apr 4 17:33:48 1999 @@ -0,0 +1,17 @@ + +/* USB Communications Class Devices Driver v$Revision: 1.2 $ + * + * (C) 1998-99 by Iñaky Pérez González + * + * Distributed under the terms of the GNU Public License Version 2 + * See files COPYRIGHT and COPYING at the root distribution directory + * + * $Id: header,v 1.2 1999/04/05 00:33:48 inaky Exp $ + * + * Changelog at the bottom + * + * + * Communications Class Driver - Class inteface to configuration API + * ----------------------------------------------------------------- + */ + diff -Naur linux.225/drivers/uusbd/generic.c linux.225.visws/drivers/uusbd/generic.c --- linux.225/drivers/uusbd/generic.c Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/generic.c Sun Apr 4 17:31:32 1999 @@ -0,0 +1,1216 @@ + +/* USB Driver Stack v$Revision: 1.72 $ + * + * (C) 1997-99 by Iñaky Pérez González + * + * Distributed under the terms of the GNU Public License Version 2 + * See files COPYRIGHT and COPYING at the root distribution directory + * + * $Id: generic.c,v 1.72 1999/04/05 00:31:32 inaky Exp $ + * + * Changelog at the bottom + * + * USB generic stuff + * + */ + +#include +#include +#include +#include + +#define GDLF_IDENT "USB" +#define GDLF_LOCAL /* Define if want local settings */ +#define GDLF_DEF_LOGLEVEL 9 +#define GDLF_ASSERTIONS /* want assertions (#undef if not) */ +#undef GDLF_FNTRACE /* want function traces */ +#define GDLF_LOCATIONS /* want locations in log messages */ +#include + + /* Methods to initialize/clear ts_usb_* structures, arrays of + * these structures and arrays of pointers to these structures */ + + /* ts_usb_xx_init(), ts_usb_xx_a_init() + * + * All these functions share a common behaviour (change xx with + * the data type). ts_usb_xx_init() initializes a single + * structure, ts_usb_xx_a_init() initializes an array of these + * structures, ts_usb_xx_pa_init() initializes an array of + * pointers to these structures. + * + * They are suppossed to leave the structure in a known, fully + * resetter and resource free state, will all the items (where + * posible) set to the invalid value. + * + * Parameters: + * ts_usb_xx* [ts_usb_xx_[a_]init()] Address of the structure to + * initialize. It will *overwrite* everything in the + * struct, without previously releasing anything. If + * NULL, space will be allocated with kmalloc() for + * it. + * ts_usb_xx** [ts_usb_xx_pa_init()] The same as ts_usb_xx* in + * the other set of functions, but in the form of an + * array of pointers :) + * unsigned [ts_usb_xx_a_init()] size of the array of + * structures to initialize. + * + * Returns: + * ts_usb_xx* Pointer to the initialized (and/or allocated) + * structure/array of structures. NULL on error + * (normally memory allocation error). + */ + + + /* ts_usb_xx_release(), ts_usb_xx_a_release(), ts_usb_xx_pa_release() + * + * All these functions share a common behaviour (change xx with + * the data type). ts_usb_xx_release() releases THE CONTENTS of a + * single structure, ts_usb_xx_a_release() releases an array of these + * structures. Beware that the space allocated for this structures + * is not released, JUST THE CONTENTS are released. + * + * Parameters: + * ts_usb_xx* [ts_usb_xx_[a_]free()] Address of the + * structure/array to release. It will release + * everything in the struct and clear it to + * known-reset state values. If NULL, nothing will be + * done. + * ts_usb_xx** [ts_usb_xx_pa_release()] pointer to the array of + * pointers to release. Same behaviour as ts_usb_xx* + * above. + * unsigned [ts_usb_xx_[p]a_release()] size of the array of + * structures/pointers to release. + * + * Returns: + * void + */ + + +#define FREE_PTR(p) \ + if ((p) != NULL) \ + { \ + usb_kfree ((p)); \ + (p) = NULL; \ + } + + /* ts_usb_addr */ + +ts_usb_addr* ts_usb_addr_init (ts_usb_addr* addr) +{ + gdlf_fntrace ("ts_usb_addr_init (0x%p)", addr); + + if (addr == NULL) + addr = usb_kmalloc (sizeof (ts_usb_addr), GFP_KERNEL); + if (addr == NULL) + return NULL; + + ts_usb_addr_clean (addr); + return addr; +} + +void ts_usb_addr_release (ts_usb_addr* addr) +{ + gdlf_fntrace ("ts_usb_addr_release (0x%p)", addr); + gdlf_assert (addr); + return; +} + + /* ts_usb_tr */ + +ts_usb_tr* ts_usb_tr_init (void) +{ + ts_usb_tr *addr; + + gdlf_fntrace ("ts_usb_tr_init()"); + + addr = usb_kmalloc (sizeof (ts_usb_tr), GFP_KERNEL); + if (addr == NULL) + return NULL; + + ts_usb_tr_clean (addr); + return addr; +} + +void ts_usb_tr_release (ts_usb_tr* tr) +{ + gdlf_fntrace ("ts_usb_tr_release (0x%p)", tr); + gdlf_aassert (tr, return); + gdlf_assert (atomic_read (&tr->snode.usecnt) == 0); + gdlf_assert (tr->hci == NULL); + return; +} + + /* ts_usb_endp */ + +ts_usb_endp* ts_usb_endp_init (ts_usb_endp* endp) +{ + gdlf_fntrace ("ts_usb_endp_init (0x%p)", endp); + + if (endp == NULL) /* Alloc memory if so requested */ + endp = usb_kmalloc (sizeof (ts_usb_endp), GFP_KERNEL); + if (endp == NULL) + return NULL; + + ts_usb_endp_clean (endp); + return endp; +} + +ts_usb_endp* ts_usb_endp_a_init (size_t size) +{ + ts_usb_endp *endps; + ts_usb_endp *itr; + + gdlf_fntrace ("ts_usb_endp_a_init (%u)", size); + + endps = usb_kmalloc (sizeof (ts_usb_endp) * size, GFP_KERNEL); + if (endps == NULL) + return NULL; + + for (itr = endps + size - 1; itr >= endps; itr--) + { + /* Need braces, this is a macro! */ + ts_usb_endp_clean (itr); + } + + return endps; +} + +ts_usb_endp** ts_usb_endp_pa_init (ts_usb_endp** pendps, size_t size) +{ + ts_usb_endp **itr; + + gdlf_fntrace ("ts_usb_endp_pa_init (0x%p, %u)", pendps, size); + + if (pendps == NULL) /* Alloc memory if so requested */ + pendps = usb_kmalloc (sizeof (ts_usb_endp*) * size, GFP_KERNEL); + if (pendps == NULL) + return NULL; + + for (itr = pendps + size - 1; itr >= pendps; itr--) + *itr = NULL; + + return pendps; +} + +void ts_usb_endp_release (ts_usb_endp* endp) +{ + gdlf_fntrace ("ts_usb_endp_release (0x%p)", endp); + + gdlf_assert (endp); + + /* ts_usb_endp->desc is not kfree()'ed, as it is only a + * reference, we do not own it */ + + return; +} + +void ts_usb_endp_a_release (ts_usb_endp* endps, size_t size) +{ + ts_usb_endp *itr; + + gdlf_fntrace ("ts_usb_endp_a_release (0x%p, %u)", endps, size); + + gdlf_aassert (endps != NULL, return); + gdlf_aassert (size != 0, return); + + for (itr = endps + size - 1; itr >= endps; itr--) + ts_usb_endp_release (itr); + + return; +} + +void ts_usb_endp_pa_release (ts_usb_endp** pendps, size_t size) +{ + gdlf_fntrace ("ts_usb_endp_pa_release (0x%p, %u)", pendps, size); + + gdlf_aassert (pendps != NULL, return); + gdlf_aassert (size != 0, return); + + /* + * This is only an array of references to endpoints, we do not + * own them, so we don't free'em + */ + + FREE_PTR (pendps); + return; +} + +void ts_usb_endp_printk (const ts_usb_endp* endp) +{ + gdlf_fntrace ("ts_usb_endp_printk (0x%p)", endp); + gdlf_aassert (endp != NULL, return); + + gdlf_debug ("ts_usb_endp 0x%p\n", endp); + gdlf_debug (" addr: %d\n", endp->addr); + gdlf_debug (" type: %d\n", endp->type); + gdlf_debug (" interval: %d\n", endp->interval); + gdlf_debug (" maxpktsize: %d\n", endp->maxpktsize); + gdlf_debug (" shared: %d\n", endp->shared); + gdlf_debug (" descrs: 0x%p\n", &endp->descrs); + ts_slist_printk (&endp->descrs); + gdlf_debug (" trs: 0x%p\n", &endp->trs); + ts_slist_printk (&endp->trs); + gdlf_debug (" last: 0x%p\n", endp->last); + gdlf_debug (" qlast: 0x%p\n", endp->qlast); + gdlf_debug (" running: 0x%p\n", endp->running); +#if defined (CONFIG_USB_OHCI) || defined (CONFIG_USB_OHCI_MODULE) + gdlf_debug (" hci: 0x%p\n", endp->hci); +#endif + return; +} + + + /* ts_usb_cfel */ + +ts_usb_cfel* ts_usb_cfel_init (void) +{ + ts_usb_cfel* cfel; + + gdlf_fntrace ("ts_usb_cfel_init()"); + cfel = usb_kmalloc (sizeof (ts_usb_cfel), GFP_KERNEL); + if (cfel == NULL) + { + gdlf_err ("Cannot allocate space for a " + "ts_usb_cfel structure\n"); + return NULL; + } + ts_usb_cfel_clean (cfel); + return cfel; +} + +void ts_usb_cfel_release (ts_usb_cfel* cfel) +{ + gdlf_fntrace ("ts_usb_cfel_release (0x%p)", cfel); + gdlf_aassert (cfel != NULL, return); + + /* Device should be already unconfigured. See khubdd.c */ + + gdlf_assert (cfel->data == NULL); + return; +} + +void ts_usb_cfel_printk (const ts_usb_cfel* cfel) +{ + gdlf_fntrace ("ts_usb_cfel_printk (0x%p)", cfel); + gdlf_aassert (cfel != NULL, return); + + gdlf_debug ("ts_usb_cfel 0x%p\n", cfel); + gdlf_debug (" class: 0x%02x\n", cfel->class); + gdlf_debug (" subclass: 0x%02x\n", cfel->subclass); + gdlf_debug (" protocol: 0x%02x\n", cfel->protocol); + gdlf_debug (" configured: 0x%lx\n", cfel->configured); + + gdlf_debug (" data: 0x%p\n", cfel->data); + return; +} + + + /* ts_usb_aset */ + +ts_usb_aset* ts_usb_aset_init (ts_usb_aset* aset) +{ + gdlf_fntrace ("ts_usb_aset_init (0x%p)", aset); + + if (aset == NULL) /* Alloc memory if so requested */ + aset = usb_kmalloc (sizeof (ts_usb_aset), GFP_KERNEL); + if (aset == NULL) + return NULL; + + ts_usb_aset_clean (aset); + return aset; +} + +ts_usb_aset* ts_usb_aset_a_init (size_t size) +{ + ts_usb_aset *asets; + ts_usb_aset *itr; + + gdlf_fntrace ("ts_usb_aset_a_init (%u)", size); + + asets = usb_kmalloc (sizeof (ts_usb_aset) * size, GFP_KERNEL); + if (asets == NULL) + return NULL; + + for (itr = asets + size - 1; itr >= asets; itr--) + { + /* Need braces, this is a macro! */ + ts_usb_aset_clean (itr); + } + + return asets; +} + +void ts_usb_aset_release (ts_usb_aset* aset) +{ + gdlf_fntrace ("ts_usb_aset_release (0x%p)", aset); + + gdlf_aassert (aset != NULL, return); + + /* + * Alternate setting should be already unconfigured. See + * khubdd.c. + */ + + ts_usb_cfel_release (&aset->cfel); + + FREE_PTR (aset->descr); + if (aset->endp) + { + ts_usb_endp_a_release (aset->endp, aset->endps); + FREE_PTR (aset->endp); + } + + return; +} + +void ts_usb_aset_a_release (ts_usb_aset* asets, size_t size) +{ + ts_usb_aset *itr; + + gdlf_fntrace ("ts_usb_aset_a_release (0x%p, %u)", asets, size); + + gdlf_aassert (asets != NULL, return); + gdlf_aassert (size != 0, return); + + for (itr = asets + size - 1; itr >= asets; itr--) + ts_usb_aset_release (itr); + + return; +} + +void ts_usb_aset_printk (const ts_usb_aset* aset) +{ + int cnt; + gdlf_fntrace ("ts_usb_aset_printk (0x%p)", aset); + gdlf_aassert (aset, return); + + gdlf_debug ("ts_usb_aset 0x%p\n", aset); + gdlf_debug (" addr: %u\n", aset->addr); + ts_usb_cfel_printk (&aset->cfel); + gdlf_debug (" endp: 0x%p\n", aset->endp); + gdlf_debug (" endps: %u\n", aset->endps); + + gdlf_debug (" descr: %s\n", aset->descr? aset->descr : "(null)"); + + if (aset->endps) + { + gdlf_debug ("Endpoints dump for aset 0x%p\n", aset); + for (cnt = 0; cnt < aset->endps; cnt++) + ts_usb_endp_printk (&aset->endp[cnt]); + } + return; +} + + + /* ts_usb_iface */ + +ts_usb_iface* ts_usb_iface_init (ts_usb_iface* iface) +{ + gdlf_fntrace ("ts_usb_iface_init (0x%p)", iface); + + if (iface == NULL) /* Alloc memory if so requested */ + iface = usb_kmalloc (sizeof (ts_usb_iface), GFP_KERNEL); + if (iface == NULL) + return NULL; + + ts_usb_iface_clean (iface); + return iface; +} + +ts_usb_iface* ts_usb_iface_a_init (size_t size) +{ + ts_usb_iface* ifaces; + ts_usb_iface *itr; + + gdlf_fntrace ("ts_usb_iface_a_init (%u)", size); + + ifaces = usb_kmalloc (sizeof (ts_usb_iface) * size, GFP_KERNEL); + if (ifaces == NULL) + return NULL; + + for (itr = ifaces + size - 1; itr >= ifaces; itr--) + { + /* Need braces, this is a macro! */ + ts_usb_iface_clean (itr); + } + + return ifaces; +} + +void ts_usb_iface_release (ts_usb_iface* iface) +{ + gdlf_fntrace ("ts_usb_iface_release (0x%p)", iface); + gdlf_aassert (iface, return); + + if (iface->aset) + { + ts_usb_aset_a_release (iface->aset, iface->asets); + FREE_PTR (iface->aset); + } + + return; +} + +void ts_usb_iface_a_release (ts_usb_iface* ifaces, size_t size) +{ + ts_usb_iface *itr; + + gdlf_fntrace ("ts_usb_iface_a_release (0x%p, %u)", ifaces, size); + + gdlf_aassert (ifaces != NULL, return); + gdlf_aassert (size != 0, return); + + for (itr = ifaces + size - 1; itr >= ifaces; itr--) + ts_usb_iface_release (itr); + + return; +} + +void ts_usb_iface_printk (const ts_usb_iface* iface) +{ + int cnt; + gdlf_fntrace ("ts_usb_iface_printk (0x%p)", iface); + gdlf_aassert (iface, return); + + gdlf_debug ("ts_usb_iface 0x%p\n", iface); + gdlf_debug (" addr: %u\n", iface->addr); + + gdlf_debug (" aset: 0x%p\n", iface->aset); + gdlf_debug (" asets: %u\n", iface->asets); + gdlf_debug (" active: 0x%p\n", iface->active); + + gdlf_debug ("Alternate settings dump for iface 0x%p\n", iface); + for (cnt = 0; cnt < iface->asets; cnt++) + ts_usb_aset_printk (&iface->aset[cnt]); + return; +} + + /* ts_usb_cfg */ + +ts_usb_cfg* ts_usb_cfg_init (void) +{ + ts_usb_cfg *cfg; + + gdlf_fntrace ("ts_usb_cfg_init (void)"); + + cfg = usb_kmalloc (sizeof (ts_usb_cfg), GFP_KERNEL); + if (cfg == NULL) + return NULL; + + ts_usb_cfg_clean (cfg); + return cfg; +} + +#if 0 +ts_usb_cfg* ts_usb_cfg_a_init (ts_usb_cfg* cfgs, size_t size) +{ + ts_usb_cfg *itr; + + gdlf_fntrace ("ts_usb_cfg_a_init (0x%p, %u)", cfgs, size); + + if (cfgs == NULL) /* Alloc memory if so requested */ + cfgs = usb_kmalloc (sizeof (ts_usb_cfg) * size, GFP_KERNEL); + if (cfgs == NULL) + return NULL; + + for (itr = cfgs + size - 1; itr >= cfgs; itr--) + { + /* Need braces, this is a macro! */ + ts_usb_cfg_clean (itr); + } + + return cfgs; +} +#endif + +void ts_usb_cfg_release (ts_usb_cfg* cfg) +{ + gdlf_fntrace ("ts_usb_cfg_release (0x%p)", cfg); + + gdlf_aassert (cfg, return); + gdlf_assert (atomic_read (&cfg->usecnt) == 0); + + FREE_PTR (cfg->descr); + FREE_PTR (cfg->pendp); + ts_usb_iface_a_release (cfg->iface, cfg->ifaces); + FREE_PTR (cfg->iface); + return; +} + +void ts_usb_cfg_printk (const ts_usb_cfg* cfg) +{ + int cnt; + + gdlf_fntrace ("ts_usb_cfg_printk (0x%p)", cfg); + gdlf_aassert (cfg != NULL, return); + + gdlf_debug ("ts_usb_cfg 0x%p\n", cfg); + gdlf_debug (" addr: %u\n", cfg->addr); + + gdlf_debug (" failed: %u\n", cfg->failed); + gdlf_debug (" buspower: %u\n", cfg->buspower); + gdlf_debug (" selfpower: %u\n", cfg->selfpower); + gdlf_debug (" remwakeup: %u\n", cfg->remwakeup); + gdlf_debug (" maxpower: %u\n", cfg->maxpower); + + gdlf_debug (" iface: 0x%p\n", cfg->iface); + gdlf_debug (" ifaces: %u\n", cfg->ifaces); + + gdlf_debug (" pendps: %u\n", cfg->pendps); + for (cnt = 0; cnt < cfg->pendps; cnt++) + gdlf_debug (" pendp[%02d]: 0x%p\n", cnt, cfg->pendp[cnt]); + gdlf_debug (" descr: %s\n", cfg->descr? cfg->descr : "(null)"); + gdlf_debug (" usecnt: %d\n", atomic_read (&cfg->usecnt)); + + gdlf_debug ("Interfaces dump for configuration 0x%p:\n", cfg); + for (cnt = 0; cnt < cfg->ifaces; cnt++) + ts_usb_iface_printk (&cfg->iface[cnt]); + return; +} + +#if 0 +void ts_usb_cfg_a_release (ts_usb_cfg* cfgs, size_t size) +{ + ts_usb_cfg *itr; + + gdlf_fntrace ("ts_usb_cfg_a_release (0x%p, %u)", cfgs, size); + + gdlf_aassert (cfgs != NULL, return); + gdlf_aassert (size != 0, return); + + for (itr = cfgs + size - 1; itr >= cfgs; itr--) + ts_usb_cfg_release (itr); + + return; +} +#endif + + /* ts_usb_device */ + +ts_usb_device* ts_usb_device_init (void) +{ + ts_usb_device* device; + + gdlf_fntrace ("ts_usb_device_init ()"); + + device = usb_kmalloc (sizeof (ts_usb_device), GFP_KERNEL); + if (device == NULL) + { + gdlf_err ("Cannot allocate a ts_usb_device\n"); + return NULL; + } + + ts_usb_device_clean (device); + return device; +} + +#if 0 +ts_usb_device* ts_usb_device_a_init (size_t size) +{ + ts_usb_device *devices; + ts_usb_device *itr; + + gdlf_fntrace ("ts_usb_device_a_init (%u)", size); + + devices = usb_kmalloc (sizeof (ts_usb_device) * size, GFP_KERNEL); + if (devices == NULL) + return NULL; + + for (itr = devices + size - 1; itr >= devices; itr--) + { + /* Need braces, this is a macro! */ + ts_usb_device_clean (itr); + } + + return devices; +} +#endif + +void ts_usb_device_release (ts_usb_device* device) +{ + t_usb_cfg cnt; + + gdlf_fntrace ("ts_usb_device_release (0x%p)", device); + + gdlf_assert (device); + gdlf_passert (atomic_read (&device->msnode.usecnt) == 0, + "use count for device 0x%p is %u\n", + device, atomic_read (&device->msnode.usecnt)); + gdlf_assert (device->msnode.next[0] == NULL); + gdlf_assert (device->msnode.next[1] == NULL); + gdlf_assert (device->msnode.next[2] == NULL); + + /* + * Device should be already unconfigured. See khubdd.c. + */ + + ts_usb_cfel_release (&device->cfel); + + + /* + * Device should be already removed from the hub + */ + + gdlf_passert (device->hub == NULL, + "The hub is still 0x%p\n", device->hub); + + /* Remove the configurations and strings */ + + for (cnt = 0; cnt < device->pcfgs; cnt++) + if (device->pcfg[cnt]) + { + ts_usb_cfg_release (device->pcfg[cnt]); + FREE_PTR (device->pcfg[cnt]); + } + FREE_PTR (device->pcfg); + + FREE_PTR (device->serial); + FREE_PTR (device->descr); + FREE_PTR (device->mfrer); + + return; +} + +#if 0 +void ts_usb_device_a_release (ts_usb_device* devices, size_t size) +{ + ts_usb_device *itr; + + gdlf_fntrace ("ts_usb_device_a_release (0x%p, %u)", devices, size); + + gdlf_aassert (size != 0, return); + gdlf_aassert (devics != NULL, return); + + for (itr = devices + size - 1; itr >= devices; itr--) + ts_usb_device_release (itr); + + return; +} +#endif + +void ts_usb_device_printk (const ts_usb_device* device) +{ + int cnt; + + gdlf_fntrace ("ts_usb_device_printk (0x%p)", device); + gdlf_aassert (device != NULL, return); + + gdlf_debug ("ts_usb_device 0x%p\n", device); + ts_3snode_printk (&device->msnode); + gdlf_debug (" addr: %d\n", device->addr); + gdlf_debug (" hub: 0x%p\n", device->hub); + gdlf_debug (" port: %u\n", device->port); + + gdlf_debug (" remwakeup: %d\n", device->remwakeup); + gdlf_debug (" selfpwrd: %d\n", device->selfpwrd); + gdlf_debug (" cfgzero: %d\n", device->cfgzero); + + ts_usb_endp_printk (&device->endp0); + ts_usb_pipe_printk (&device->endp0d); + + gdlf_debug (" pcfg: 0x%p\n", device->pcfg); + gdlf_debug (" pcfgs: %d\n", device->pcfgs); + gdlf_debug (" active: 0x%p\n", device->active); + + gdlf_debug (" cfels: %d\n", device->cfels); + gdlf_debug (" cfelu: %d\n", device->cfelu); + gdlf_debug (" acfels: %d\n", device->acfels); + gdlf_debug (" acfelu: %d\n", device->acfelu); + + ts_usb_cfel_printk (&device->cfel); + + gdlf_debug (" usb_version: %04x\n", device->usb_version); + gdlf_debug (" vendor: %04x\n", device->vendor); + gdlf_debug (" product: %04x\n", device->product); + gdlf_debug (" version: %04x\n", device->version); + + gdlf_debug (" mfrer: %s\n", + device->mfrer? device->mfrer : "(null)"); + gdlf_debug (" descr: %s\n", + device->descr? device->descr : "(null)"); + gdlf_debug (" serial: %s\n", + device->serial? device->serial : "(null)"); + + gdlf_debug ("Configuration tree dump for device 0x%p\n", device); + for (cnt = 0; cnt < device->pcfgs; cnt++) + if (device->pcfg[cnt]) + ts_usb_cfg_printk (device->pcfg[cnt]); + return; +} + + + /* ts_usb_host */ + +ts_usb_host* ts_usb_host_init (void) +{ + ts_usb_host* host; + + gdlf_fntrace ("ts_usb_host_init (void)"); + + host = usb_kmalloc (sizeof (ts_usb_host), GFP_KERNEL); + if (host == NULL) + return NULL; + + ts_usb_host_clean (host); + return host; +} + +void ts_usb_host_release (ts_usb_host* host) +{ + gdlf_fntrace ("ts_usb_host_release (0x%p)", host); + + gdlf_assert (host); + gdlf_assert (atomic_read (&host->snode.usecnt) == 0); + gdlf_assert (host->snode.next == NULL); + + if (host->master) /* ??? It should be clean */ + { + gdlf_err ("Master device field of host 0x%p is 0x%p " + "instead of NULL\n", host, host->master); + usb_device_unref (host->master, NULL); + host->master = NULL; + } + + /* No checks on HCI, as it must have been destroyed already */ + + return; +} + + + /* ts_usb_pipe */ + +void ts_usb_pipe_printk (const ts_usb_pipe* pipe) +{ + gdlf_fntrace ("ts_usb_pipe_printk (0x%p)", pipe); + gdlf_aassert (pipe != NULL, return); + + gdlf_debug ("ts_usb_pipe 0x%p\n", pipe); + gdlf_debug (" device: 0x%p\n", pipe->device); + gdlf_debug (" endp: 0x%p\n", pipe->endp); + return; +} + + + /* ts_usb_driver */ + +ts_usb_driver* ts_usb_driver_init (void) +{ + ts_usb_driver* driver; + + gdlf_fntrace ("ts_usb_driver_init()"); + + driver = + usb_kmalloc (sizeof (ts_usb_driver), GFP_KERNEL); + + if (driver == NULL) + return NULL; + ts_usb_driver_clean (driver); + return driver; +} + + +void ts_usb_driver_release (ts_usb_driver* driver) +{ + gdlf_fntrace ("ts_usb_driver_release (0x%p)", driver); + gdlf_aassert (driver != NULL, return); + gdlf_passert (atomic_read (&driver->snode.usecnt) == 0, + "aiee!! cleaning used ts_usb_driver %p " + "(usecount = %d)\n", + driver, atomic_read (&driver->snode.usecnt)); + return; +} + +void ts_usb_driver_printk (const ts_usb_driver* driver) +{ + gdlf_fntrace ("ts_usb_driver_printk (0x%p)", driver); + gdlf_aassert (driver != NULL, return); + + gdlf_debug ("ts_usb_driver 0x%p\n", driver); + ts_snode_printk (&driver->snode); + gdlf_debug (" vendor: 0x%04x\n", driver->vendor); + gdlf_debug (" product: 0x%04x\n", driver->product); + gdlf_debug (" class: 0x%02x\n", driver->class); + gdlf_debug (" subclass: 0x%02x\n", driver->subclass); + gdlf_debug (" protocol: 0x%02x\n", driver->protocol); + + gdlf_debug (" id: 0x%x\n", driver->id); + + gdlf_debug (" name: %s\n", + driver->name? driver->name : "(null)"); + gdlf_debug (" copyright: %s\n", + driver->copyright? driver->copyright : "(null)"); + gdlf_debug (" vendorname: %s\n", + driver->vendorname? driver->vendorname : "(null)"); + gdlf_debug (" productname: %s\n", + driver->productname? driver->productname : "(null)"); + gdlf_debug (" classname: %s\n", + driver->classname? driver->classname : "(null)"); + gdlf_debug (" subclassname: %s\n", + driver->subclassname? driver->subclassname : "(null)"); + gdlf_debug (" protocolname: %s\n", + driver->protocolname? driver->protocolname : "(null)"); + + gdlf_debug (" config: 0x%p\n", driver->config); + gdlf_debug (" unconfig: 0x%p\n", driver->unconfig); + gdlf_debug (" reference: 0x%p\n", driver->reference); + + ts_slist_printk (&driver->uselist); + + return; +} + + /* ts_usb_hci */ + +ts_usb_hci* ts_usb_hci_init (void) +{ + ts_usb_hci* hci; + + gdlf_fntrace ("ts_usb_hci_init()"); + hci = usb_kmalloc (sizeof (ts_usb_hci), GFP_KERNEL); + if (hci == NULL) + { + gdlf_err ("Cannot allocate space for a " + "ts_usb_hci structure\n"); + return NULL; + } + ts_usb_hci_clean (hci); + return hci; +} + + +void ts_usb_hci_release (ts_usb_hci* hci) +{ + gdlf_fntrace ("ts_usb_hci_release (0x%p)", hci); + gdlf_aassert (hci != NULL, return); + gdlf_assert (hci->snode.dtor.fn == (tf_dtor)usb_hci_destroy); + return; +} + + +int ts_usb_drv_use_destroy (ts_usb_drv_use* use) +{ + gdlf_fntrace ("ts_usb_drv_use_destroy (0x%p)", use); + gdlf_aassert (use != NULL, return -EINVAL); + + ts_usb_drv_use_release (use); + return 0; +} + +/* Log: + * + * $Log: generic.c,v $ + * Revision 1.72 1999/04/05 00:31:32 inaky + * Trimmed logs in files where it was too big. Moved the transaction list + * to the endpoints and made these have a list of open descriptors to it, + * not just one [making the foundations for endpoint sharing]. Removed + * the host pointer from the pipe structure, needless. + * + * Renamed khubdd to kusbdd, as it was doing more stuff then hub's + * managing, so it made sense. Added the compile time configuration + * option to disable load on demand of drivers [having to manually load + * all of them at startup to register, then they can be unloaded and will + * be loaded when needed]. + * + * Changed the semantics and simplified usb_pipe_*(). Now the functions + * are pointer (or handle) based, instead of using addresses, what added + * a useless step. + * + * Finally reworked the transaction list to make sense. Now it's divided + * in a linear sequence of states which is more logical and easy to + * keep. It has made much simpler to deal with it. + * + * Revision 1.71 1999/02/09 02:41:00 inaky + * You pigheaded, ts_usb_pipe_release() returns VOID. + * + * Revision 1.70 1999/02/08 16:51:48 inaky + * Fixed typo, thx to Rasca Gmelch. + * + * Revision 1.69 1999/02/07 13:12:11 inaky + * Moved ts_usb_pipe_init() to usb.h. + * + * Revision 1.68 1998/12/23 23:14:36 inaky + * Removed the >> 1 in ts_usb_endp_printk, as it confused when reading + * them. + * + * Revision 1.67 1998/12/19 17:06:43 inaky + * Fixed printing 4 digit hex codes to always put trailing zeroes and + * always 4 digits wide. + * + * Revision 1.66 1998/11/26 21:58:01 inaky + * Renamed all the ts_usb_open stuff and friends to use _pipe_. + * + * Revision 1.65 1998/11/14 17:12:14 inaky + * Moved the include files to uusbd/include/uusbd, to ease integration + * into the Linux kernel. Linkage into the kernel made possible. + * + * Revision 1.64 1998/11/09 21:20:33 inaky + * Fixed prototypes for array generation/deletion, using size_t as size + * type. + * + * Revision 1.63 1998/10/31 02:07:35 inaky + * Removed all the d_* pointers from ts_usb_cfel and collapsed them into + * a single pointer; only one was really used. + * + * Added the fix for devices using index 0 as first configuration + * descriptor, with a bit which indicates it. + * + * Revision 1.62 1998/09/14 02:27:42 inaky + * Added a comment on being only able to compile as module. Added the new + * dynamic cfg->pendp scheme. + * + * Revision 1.61 1998/08/30 14:03:40 inaky + * Fixed endpoint addres reporting. + * + * Revision 1.60 1998/08/30 12:38:55 inaky + * Fixed reports of the endpoint pointer array numbers. + * + * Revision 1.59 1998/08/28 23:43:33 inaky + * Added missing closing parentheses. + * + * Revision 1.58 1998/08/27 22:13:12 inaky + * Removed traces. + * + * Revision 1.57 1998/08/27 10:52:16 inaky + * Moved ts_*_free() to ts_*_release(), made them return void and severed + * assertions. + * + * Revision 1.56 1998/08/25 03:58:45 inaky + * Fixed the printing style for class, subclass and protocols, added a + * driver printk function. + * + * Revision 1.55 1998/08/24 02:13:01 inaky + * Added braces to `for' loops which call ts_*_clean()! it was only + * executing the first command of the macro. Proper sollution would be to + * define'em with do { } while (0). + * + * Fixed assertions. + * + * Added a set of functions to dump the state of devices, configurations, + * ifaces and asets, printing the whole trees. Fixed some ts_*_free() + * calls to return void. Fixed others to call ts_*_a_free() only if + * there's array to free. + * + * Revision 1.54 1998/08/03 13:21:46 inaky + * Fixed assertions to give clearer error messages on device's free + * method. + * + * Revision 1.53 1998/07/30 22:57:15 inaky + * Fixed all the for loops, as some could be broken. + * + * Revision 1.52 1998/07/23 14:18:20 inaky + * Renamed the ts_usb_trbuf struct to ts_usb_tr + * + * Removed the host printk function, it wasn't used. + * + * Revision 1.51 1998/07/16 15:59:35 inaky + * Fixed the mess with transactions on device-less hubs. + * + * Revision 1.50 1998/07/16 14:03:49 inaky + * Fixed the ts_usb_host_free() function, as it was destroying the HCI + * part, which it shouldn't, as it should be already destroyed and freed + * when calling this function. + * + * Revision 1.49 1998/07/16 12:43:15 inaky + * Added the transaction (ts_usb_trbuf) housekeeping functions. + * + * Moved from the old read/write interface to the new, request-based + * interface. + * + * Revision 1.48 1998/07/12 22:38:30 inaky + * Fixed the array cleaning code, as it was wroken. + * Removed the old root hub code from host house-keeping; added the + * reference method in hosts. + * + * Revision 1.47 1998/06/21 20:09:12 inaky + * Removed the structure clean call from all ts_*_free() methods. + * + * Revision 1.46 1998/06/20 21:54:48 inaky + * Massive changes to split the old monolithic hubd driver into a hub + * manager (hub wrappers and daemon) and a dynamic driver, which can be + * replaced and its different parts reused. + * + * Revision 1.45 1998/04/26 03:24:05 inaky + * Fixed ts_usb_(iface|endp|aset)_a_init() routines not to need a + * pointer. It should only allocate and clean. Disabled the + * ts_usb_(cfg|device)_a_(init|free)() fn, which isn't used. Added the + * fix to make the cfg's array on a device be a pointers array. + * + * Revision 1.44 1998/04/13 21:48:56 inaky + * On ts_usb_device_init() and ts_usb_device_a_init() removed the + * allocation stuff. + * + * Revision 1.43 1998/03/28 19:24:22 inaky + * Removed inclusion of usb-methods.h + * + * Revision 1.42 1998/02/10 17:14:29 inaky + * Moved to use ts_snode_[un]ref() to ref/unref snodes, fixed some + * mistakes usint atomic_read(); Also changed the error handling when + * any of the root, master or hci field of a host are set when freeing + * it. + * + * Revision 1.41 1998/02/09 13:09:43 inaky + * Moved all the use counts to atomic, using atomic_t and atomic_*() + * + * Revision 1.40 1998/01/11 15:44:15 inaky + * Finished functions from the descriptor, inteface and endpoint modules, + * fixed docs, pretty printed and removed craps. + * + * Revision 1.39 1998/01/08 12:19:06 inaky + * Added copyright strings to all important files + * + * Revision 1.38 1998/01/02 19:39:36 inaky + * Added the definition for endpoint zero to the device structure and + * removed it from the list of endpoints kept at each configuration. Also + * updated it on places where needed and removed the concept of basic + * configuration, as is no longer needed. + * + * Revision 1.37 1998/01/02 00:12:15 inaky + * Finished the new driver scheme. Documented at usbd-drv.c + * + * Revision 1.36 1998/01/01 16:11:03 inaky + * Fixed bug, a couple _init routines where returning NULL instead of the + * pointer :) + * + * Revision 1.35 1997/12/31 16:37:10 inaky + * Finished the HCI interface + * + * Revision 1.34 1997/12/31 05:29:45 inaky + * Added the handling functions for ts_usb_cfel + * + * Revision 1.33 1997/12/30 20:15:42 inaky + * Moved everything to the new lists scheme. Untested yet. + * + * Revision 1.32 1997/12/30 00:02:46 inaky + * Stupid change to fix code alignment pretty printing + * + * Revision 1.31 1997/12/29 00:25:35 inaky + * Fixed unimplemented functions to return -ENOSYS and moving the khubdd + * to use signals as commands. + * Also added function traces on most files that had them disabled (donkey!) + * + * Revision 1.30 1997/12/27 03:00:13 inaky + * Moved to GDLF and fixed some docs + * + * Revision 1.29 1997/12/27 02:24:03 inaky + * Moving everything to use the GDLF for logging and debug checkings. + * Removed the global array of USB hosts and moved it to a linked + * list. Added an address field to each USB host controller. + * Removed lots of cruft that were accumulated and useless. Still some + * missing, but may be useful someday. + * + * Revision 1.28 1997/12/22 02:44:28 inaky + * Trying to move all the documentation to the source files from the + * header files, as it was duplicated. + * + * Revision 1.27 1997/12/08 02:40:57 inaky + * Fixed some stuff of the #includes, modified the makefile targets to be + * more flexible, tried to finish the device configuration section. + * + * Revision 1.26 1997/12/06 01:55:47 inaky + * Now finishing the configuration system + * + * Revision 1.25 1997/12/06 00:19:39 inaky + * Almost finished the usbd/host, usbd/cfg and a lot of meat from + * usbd/device. Also added the driver definition. Got to polish it yet + * ... + * + * Revision 1.24 1997/11/29 20:21:47 inaky + * Documented and almost fixes the read/write/abort API, documented a + * damn lot and implemented some stuff + * + * Revision 1.23 1997/11/29 00:46:29 inaky + * Documented almost all the hub basic API, added spin locks to + * usb_host_register() and some more stuff. Going for more. + * + * Revision 1.22 1997/10/31 05:44:29 inaky + * *** empty log message *** + * + * Revision 1.21 1997/10/24 04:20:18 inaky + * Security backup + * + * Revision 1.20 1997/10/02 22:29:36 inaky + * Finally managed to understand the workings of the MODVERSIONS (ok, not + * exactly the working, but how to make it work). + * + * Now I can go to sleep happy :) -- I know, I'm really sick -- + * + * Revision 1.19 1997/10/02 21:28:59 inaky + * Remade all the directory structure to make it cleaner when the USB + * class drivers come. + * + * Revision 1.18 1997/09/30 13:04:42 inaky + * Moved the name of the package to uusbd: Universal USB Driver + * + * Revision 1.17 1997/09/25 00:12:29 inaky + * At the very least I hunted down the bug which was causing all that + * damned exceptions, all memory related. Well, I'm a cock-fingered. Ix + * don't know how to code; I'm stupid; I'm dreadful; I'm .... + * + * Revision 1.16 1997/09/08 10:54:48 inaky + * Modified the generic functions to gain some performance, also some other checks + * + * Revision 1.15 1997/07/03 20:00:02 inaky + * Moved all the hw dependencies to the HCD module, modified the + * controller detections stuff to use just PCI means (okay, other buses + * to come, but when they come). General fixes, but no really new deep + * enhancements. + * + * Revision 1.14 1997/06/22 19:54:30 inaky + * Seems that the moving of all the hw dependants stuff to the HCI + * modules is done. Got to test it yet, but at least it compiles cleanly. + * + * Revision 1.13 1997/06/19 20:38:17 inaky + * Moving al hardware dependant stuff to the HCD modules + * + * Revision 1.12 1997/05/04 14:38:34 inaky + * Some fixes ... + * + * Revision 1.11 1997/05/03 21:22:48 inaky + * Adding a lot of code, with the only objetive of adding the first + * transfer type: control :) Still there's a lot of stuff to do, mostly + * concerning data structures handling. + * + * Revision 1.10 1997/04/20 21:25:56 inaky + * Finished the spec for the Hub Class (now gotta implement it) + * :). Started coding the Frame Lists code, hope UHCI support will be + * finished in some sessions. + * This code is breaking, I'm doing something bad with kmallocs. kFree()ing + * something not kmalloc()ed. + * + * Revision 1.9 1997/04/14 16:56:01 inaky + * *** empty log message *** + * + * Revision 1.8 1997/04/12 16:47:49 inaky + * Added the code for buffering reads/writes to/from userland + * + * Revision 1.7 1997/04/10 21:30:48 inaky + * Fixed the file code, so it opens/closes ok; also reads/writes ok ... ok, just theory + * + * Revision 1.6 1997/04/06 22:56:44 inaky + * Added the functions to set destinations of an USB open descriptor + * (ts_usb_open); however, I haven't tested it yet ... bugs flowing! + * + * Revision 1.5 1997/04/06 21:14:31 inaky + * Still with the definition of the access interface. More or less it is + * taking an stable form. + * + * Revision 1.4 1997/04/02 20:02:03 inaky + * Added init/free code for some struct more. Some still missing. + * + * Revision 1.3 1997/03/31 20:24:46 inaky + * Pfff ... a lot. Mostly added descriptors stuff (HUB class still is + * missing a lot) and I think I've got a definitive idea of how to + * implement the storing of configurations and interfaces. + * + * Revision 1.2 1997/03/09 23:10:31 inaky + * *** empty log message *** + * + * Revision 1.1 1997/03/02 22:11:02 inaky + * *** empty log message *** + * + * Revision 1.1 1997/02/22 22:25:44 inaky + * *** empty log message *** + * + * + */ + diff -Naur linux.225/drivers/uusbd/hardware linux.225.visws/drivers/uusbd/hardware --- linux.225/drivers/uusbd/hardware Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/hardware Tue Mar 9 14:53:50 1999 @@ -0,0 +1,37 @@ +# +# USB Ids +# ------- + +# Bus Description +# +# BUS: (pci|usb) + +# USB Vendor Description +# +# vendor CODE { "NAME" "URL" "COMMENTS" } +# +# CODE: 16 bit hex USB device code +# NAME: Vendor name +# URL: That ... + +# USB Host Controller Description +# +# host BUS-VENDOR.BUS-CODE { "NAME" TYPE PORTS "URL" "COMMENTS" } +# +# VENDOR: vendor code +# CODE: device code for the vendor +# TYPE: (o|u) OHCI/UHCI +# PORTS: Interger, number of ports +# URL: +# COMMENTS: + +# USB Device Description +# +# device VENDOR.CODE { "NAME" FLAGS "COMMENTS" } +# +# VENDOR: 16 bit hex USB vendor code +# CODE: 16 bit hex USB device code +# +# FLAGS: # has a serial number +# M has manufacturer string +# D has device string diff -Naur linux.225/drivers/uusbd/hcd.c linux.225.visws/drivers/uusbd/hcd.c --- linux.225/drivers/uusbd/hcd.c Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/hcd.c Sun Apr 4 17:31:33 1999 @@ -0,0 +1,373 @@ + +/* USB Driver Stack v$Revision: 1.19 $ + * + * (C) 1997-99 by Iñaky Pérez González + * + * Distributed under the terms of the GNU Public License Version 2 + * See files COPYRIGHT and COPYING at the root distribution directory + * + * $Id: hcd.c,v 1.19 1999/04/05 00:31:33 inaky Exp $ + * + * Changelog at the bottom + * + * + * Host Controller Driver implementation + * ------------------------------------- + */ + + +#include +#include +#include /* usb_host_destroy() */ + +#define GDLF_IDENT "USB-HCD" +#define GDLF_LOCAL /* Define if want local settings */ +#define GDLF_DEF_LOGLEVEL 9 +#define GDLF_ASSERTIONS /* want assertions (#undef if not) */ +#undef GDLF_FNTRACE /* want function traces */ +#define GDLF_LOCATIONS /* want locations in log messages */ +#include + + +ts_slist hcis; /* list of registered HCIs */ +extern ts_slist hosts; /* list of registered hosts */ + + + /* Register an HCI into the UUSBD's HCD + * + * This function will add a new HCD into the UUSBD + * system. However, we can only expect IANF to see two, UHCI and + * OHCI, but ... + * + * The HCI structure (ts_usb_hci) must be properly initialized + * with (ts_usb_hci_init()) and must have a name set (the 'name' + * member). Note this member is a 'const char*', what means the + * structure doesn't hold a local copy of the name, so do not + * modify it :) nor free it while the name is in use. + * + * Parameters: + * + * ts_usb_hci* Pointer to the host controller interface to + * registrate. + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + * + * Global: + * + * int usb_errno On error, error code. + */ + +int usb_hci_register (ts_usb_hci* hci) +{ + gdlf_fntrace ("usb_hci_register (0x%p)", hci); + gdlf_aassert (hci != NULL, return -EINVAL); + gdlf_aassert (hci->name != NULL, return -EINVAL); + gdlf_aassert (hci->type != 0, return -EINVAL); + gdlf_aassert (hci->enumerate != NULL, return -EINVAL); + + /* Fill the destructor and add to list */ + + ts_dtor_fill (&hci->snode.dtor, (tf_dtor)usb_hci_destroy); + return ts_slist_prep (&hcis, &hci->snode); +} + + + /* Unregister an HCI from the UUSBD's HCD + * + * Parameters: + * + * ts_usb_hci* Pointer to the HCI structure. + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + * + * Global: + * + * int usb_errno On error, error code. + */ + +int usb_hci_unregister (ts_usb_hci* hci) +{ + gdlf_fntrace ("usb_hci_unregister (0x%p)", hci); + gdlf_aassert (hci != NULL, return -EINVAL); + + usb_hci_release (hci); + ts_slist_del (&hcis, &hci->snode); + return 0; +} + + + /* Release an HCI + * + * To accomplish it, we request the destruction of all the + * ts_usb_hosts who use an hci registered within this HCI's list. + * + * Parameters: + * + * ts_usb_hci* Pointer to HCI structure we want released + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + * + * Global: + * + * int usb_errno On error, error code. + */ + +int usb_hci_release (ts_usb_hci* hci) +{ + int errcode; + ts_usb_host *host, *next; + + gdlf_fntrace ("usb_hci_release (0x%p)", hci); + gdlf_aassert (hci != NULL, return -EINVAL); + + /* + * we must unregister every ts_usb_host which uses a + * controller from this HCI. + */ + + read_lock (&hosts->lock); + host = (ts_usb_host*)ts_slist_head (&hosts); + while (host != NULL) + { + next = (ts_usb_host*)ts_snode_next (&host->snode); + if (host->hcitype == hci->type) /* HCI is this kind's? */ + { + errcode = usb_host_destroy (host); /* kill it */ + gdlf_passert (errcode == 0, + "Couldn't destroy host 0x%p: " + "errno/usb %d/%d. " + "Killing it anyway.\n", + host, errcode, usb_errno); + usb_kfree (host); + } + host = next; + } + read_unlock (&hosts->lock); + return 0; +} + + + /* Destructor for ts_usb_hci + * + * Parameters: + * + * ts_usb_hci* Pointer to the HCI structure. + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + * + * Global: + * + * int usb_errno On error, error code. + */ + +int usb_hci_destroy (ts_usb_hci* hci) +{ + gdlf_fntrace ("usb_hci_destroy (0x%p)", hci); + gdlf_aassert (hci != NULL, return -EINVAL); + + ts_snode_ref (&hci->snode); + usb_hci_unregister (hci); + ts_snode_unref_nd (&hci->snode); + ts_usb_hci_release (hci); + return 0; +} + + + /* Register a host controller into an HCI + * + * This function is used to register a host controller data + * structure (ts_*hci_host) into it's correspoing HCI list + * (ts_usb_hci). + * + * Parameters: + * + * ts_usb_hci* Pointer to the HCI structure where to register + * the host controller. + * + * ts_snode* Pointer to the host controller interface's + * snode. + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + * + * Global: + * + * int usb_errno On error, error code. + */ + +int usb_hci_register_host (ts_usb_hci* hci, ts_snode* snode) +{ + int errcode; + gdlf_fntrace ("usb_hci_register_host (0x%p, 0x%p)", + hci, snode); + gdlf_aassert (hci != NULL, return -EINVAL); + gdlf_aassert (snode != NULL, return -EINVAL); + + errcode = ts_slist_prep (&hci->hosts, snode); + gdlf_passert (errcode == 0, + "Cannot add host controller 0x%p to " + "HCI 0x%p: errno/usb %d/%d\n", + hci, snode, errcode, usb_errno); + + return errcode; +} + + + /* Unregister a host controller from an HCI + * + * This function is used to unregister a host controller data + * structure (ts_*hci_host) from it's correspoing HCI list + * (ts_usb_hci). + * + * Parameters: + * + * ts_usb_hci* Pointer to the HCI structure from where to + * unregister the host controller. + * + * ts_snode* Pointer to the host controller interface's + * snode. + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + * + * Global: + * + * int usb_errno On error, error code. + */ + +int usb_hci_unregister_host (ts_usb_hci* hci, ts_snode* snode) +{ + gdlf_fntrace ("usb_hci_unregister_host (0x%p, 0x%p)", + hci, snode); + gdlf_aassert (hci != NULL, return -EINVAL); + gdlf_aassert (snode != NULL, return -EINVAL); + + ts_slist_del (&hci->hosts, snode); + return 0; +} + + +/* Log: + * + * $Log: hcd.c,v $ + * Revision 1.19 1999/04/05 00:31:33 inaky + * Trimmed logs in files where it was too big. Moved the transaction list + * to the endpoints and made these have a list of open descriptors to it, + * not just one [making the foundations for endpoint sharing]. Removed + * the host pointer from the pipe structure, needless. + * + * Renamed khubdd to kusbdd, as it was doing more stuff then hub's + * managing, so it made sense. Added the compile time configuration + * option to disable load on demand of drivers [having to manually load + * all of them at startup to register, then they can be unloaded and will + * be loaded when needed]. + * + * Changed the semantics and simplified usb_pipe_*(). Now the functions + * are pointer (or handle) based, instead of using addresses, what added + * a useless step. + * + * Finally reworked the transaction list to make sense. Now it's divided + * in a linear sequence of states which is more logical and easy to + * keep. It has made much simpler to deal with it. + * + * Revision 1.18 1999/01/23 18:36:16 inaky + * Added a fix to have the enumerate method. + * + * Revision 1.17 1998/11/14 17:12:28 inaky + * Moved the include files to uusbd/include/uusbd, to ease integration + * into the Linux kernel. + * + * Revision 1.16 1998/09/14 19:44:07 inaky + * Severed assertions. + * + * Revision 1.15 1998/08/28 23:44:03 inaky + * Severed assertions and the function, in general. + * + * Revision 1.14 1998/08/27 11:14:57 inaky + * Moved ts_*_free() to ts_*_release(), made them return void and severed + * assertions. + * + * Revision 1.13 1998/08/24 02:13:14 inaky + * Removed function traces + * + * Revision 1.12 1998/07/16 12:43:44 inaky + * Removed lockings when adding to lists, the list code already does it. + * + * Revision 1.11 1998/07/12 22:39:12 inaky + * Fixed destructor to use reference and non-destructive unreference to + * keep the object alive during destruction. + * + * Revision 1.10 1998/06/20 21:54:48 inaky + * Massive changes to split the old monolithic hubd driver into a hub + * manager (hub wrappers and daemon) and a dynamic driver, which can be + * replaced and its different parts reused. + * + * Revision 1.9 1998/02/12 14:28:51 inaky + * Replaced the old check-and-delete code with the new one, simpler and + * more effective. + * + * Revision 1.8 1998/02/10 19:39:56 inaky + * Fixed the destructor and unregistration methods, to do a check on + * presence before deleting from their respective lists. + * + * Revision 1.7 1998/01/08 12:19:06 inaky + * Added copyright strings to all important files + * + * Revision 1.6 1998/01/02 00:12:15 inaky + * Finished the new driver scheme. Documented at usbd-drv.c + * + * Revision 1.5 1997/12/31 18:30:01 inaky + * Finished adapting the UHCI module to the new HCD driver + * + * Revision 1.4 1997/12/31 17:06:35 inaky + * Removed some unneeded locks and fixed some others. + * + * Revision 1.3 1997/12/31 16:25:10 inaky + * Added the functions to register host controllers into their HCIs + * + * Revision 1.2 1997/12/31 05:37:00 inaky + * Almost finished all the lists and life cycle for hosts, drivers and + * devices. Some craps to be fixed yet. + * + * Revision 1.1 1997/12/30 22:30:17 inaky + * Added the foundations of the HCD and fixed some bugs. + * + * Revision 1.2 1997/12/27 19:54:46 inaky + * Removed .txt file who got in by mistake and added some stuff to the + * templates. + * + * Revision 1.1 1997/10/02 21:29:17 inaky + * Remade all the directory structure to make it cleaner when the USB + * class drivers come. + * + * Revision 1.1 1997/02/22 22:25:44 inaky + * *** empty log message *** + * + * + */ + + + + + + + + + + + + + + + + diff -Naur linux.225/drivers/uusbd/hidbp/Makefile linux.225.visws/drivers/uusbd/hidbp/Makefile --- linux.225/drivers/uusbd/hidbp/Makefile Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/hidbp/Makefile Tue Dec 15 16:20:24 1998 @@ -0,0 +1,69 @@ +# +# Makefile for the Universal USB Human Interface Devices Driver, Linux flavour +# ---------------------------------------------------------------------------- +# +# Distributed under the terms of the GNU Public License Version 2 +# See files COPYRIGHT and COPYING at the root distribution directory + +CLEANSTUFF += bmse-test bkbd-test keymap.c +SUB_DIRS := +MOD_IN_SUB_DIRS := $(SUB_DIRS) +ALL_SUB_DIRS := $(SUB_DIRS) + +HIDBP_OBJS := cfg.o driver.o hkeep.o hidbp.o +HIDBP_XOBJS := #symtab.o +HIDBP_TARGET := usb-hidbp.o + +include ../Makefile.inc +ifdef NOT_IN_LINUX_KERNEL +export EXTRA_CFLAGS += -I../include +endif + +ifeq ($(CONFIG_USB_HIDBP_KBD),y) + HIDBP_OBJS += keyboard.o keymap.o +endif + +ifeq ($(CONFIG_USB_HIDBP_MSE),y) + HIDBP_OBJS += mouse.o +endif + +# Libraries +L_OBJS := +LX_OBJS := +# L_TARGET (just one) will be the archive of all the L_OBJS and LX_OBJS +L_TARGET := + +# Modules +MIX_OBJS := +MI_OBJS := +# Made by modules. These ones get symlinked at $(TOPDIR)/modules and +# added to the list of modules +M_OBJS := $(HIDBP_TARGET) dummy_module + +# Objects +OX_OBJS := $(HIDBP_XOBJS) +O_OBJS := $(HIDBP_OBJS) +# O_TARGET (just one) will be made by compiling+linking OX_OBJS and O_OBJS +O_TARGET := $(HIDBP_TARGET) + +include $(TOPDIR)/Rules.make +include ../Makefile-rules.inc + +.PHONY: dummy_module +dummy_module: +ifeq ($(CONFIG_USB_HIDBP),m) + for v in $(M_OBJS); do echo `pwd`/$$v; done >> $(MODULES_FILE) +endif + +bkbd-test: bkbd-test.c + $(HOSTCC) $(HOSTCFLAGS) -o bkbd-test bkbd-test.c + +bmse-test: bmse-test.c + $(HOSTCC) $(HOSTCFLAGS) -o bmse-test bmse-test.c + +keymap.c: keymap.map + loadkeys --mktable $^ | \ + sed -e '/plain_map\[/s/^/static /' \ + -e '/key_maps/s//usb_key_maps/' \ + -e '/keymap_count/,$$d' > $@ + diff -Naur linux.225/drivers/uusbd/hidbp/README linux.225.visws/drivers/uusbd/hidbp/README --- linux.225/drivers/uusbd/hidbp/README Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/hidbp/README Tue Nov 17 02:06:50 1998 @@ -0,0 +1,20 @@ + + The UUSBD HID Boot Protocol Driver (hidbp/usb-hidbp.o) + + This is the driver for the USB devices which comply with the +USB HID Boot Protocol. You will need the misc character devices driver +turned on (CONFIG_UMISC enabled). It will register keyboards and mice +(up to 16) at minor device numbers HIDBP_BKBD_MINOR and +HIDBP_BMSE_MINOR respectively (both defined at ../hidd/usb-hidd.h). + + Mice imitate busmouse protocol with three buttons. I've seen +some strange problems when using X, as the server slows down a +lot. I've thought of my code being to slow, but perhaps is because +I've made the call to bmse_read blocking [I've seen ~47 calls/second +by X]. Doing the reading with bmse-test at continuous rate with no +waiting nor printing doesn't slow the machine down, so I guess it'll +be that. Will have to fix it. + + Guess gpm will need some fixing in that direction too + + Iñaky diff -Naur linux.225/drivers/uusbd/hidbp/TODO linux.225.visws/drivers/uusbd/hidbp/TODO --- linux.225/drivers/uusbd/hidbp/TODO Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/hidbp/TODO Fri Dec 11 17:55:03 1998 @@ -0,0 +1,6 @@ + +- Rename functions to the usual naming scheme + +- Why does Paul make all the insertion stuff into hidbp_config()? it + is wasted resources, as until open(), we don't use it. Perhaps for + static kernel use. \ No newline at end of file diff -Naur linux.225/drivers/uusbd/hidbp/bkbd-test.c linux.225.visws/drivers/uusbd/hidbp/bkbd-test.c --- linux.225/drivers/uusbd/hidbp/bkbd-test.c Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/hidbp/bkbd-test.c Sun Apr 4 17:38:38 1999 @@ -0,0 +1,164 @@ + +/* + * Keyboard Boot Protocol Test + * --------------------------- + * + * The HID Boot Protocol for keyboards specifies the keyboard will + * return, when polled, eight bytes of data. The disposition and + * meaning of the data is specified on struct ts_bkbd_report in + * ../hidd/usb-hidd.h. + * + * What we do is just open the first registered keyboard and read + * from it. Note what happens if you suddenly unplug the keyboard + * [wait some time for kusbdd to notice]. + */ + +#include +#include +#include +#include +#include + +#define DEFAULT_POLL_INTERVAL 100000 + +void version (FILE* file) +{ + fprintf (file, + "UUSBD Utils - USB HID Boot Protocol Keyboard Test v$Version$\n"); + return; +} + +void help (FILE* file) +{ + fprintf (file, +"(C) 1998 Inaky Perez Gonzalez \n" +"\n" +"bkbd-test [OPTIONS] DEVICE\n" +"\n" +"Options:\n" +"\n" +" -V, --version Show version info\n" +" -h, --help Show this help\n" +" -i, --interval MICROSECONDS Set delay between reads (polls) to \n" +" MICROSECONDS (default is %d us). 0\n" +" don't wait\n" +" -p, --dont-print Don't print any data, just read\n" +"\n", + DEFAULT_POLL_INTERVAL); + return; +} + + +int main (int argc, char **argv) +{ + int print = 1; + int option; + int idxptr; + ssize_t res; + int fd; + char* dev; + char data[8]; + + unsigned long interval = DEFAULT_POLL_INTERVAL; + + struct option longopts[] = + { + { "interval", required_argument, NULL, 'i' }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'V' }, + { "dont-print", no_argument, NULL, 'p' }, + { NULL, 0, NULL, 0 } + }; + const char shortopts[] = "i:phV"; + + while ((option = getopt_long (argc, argv, shortopts, + longopts, &idxptr)) + >= 0) + { + switch (option) + { + case 'i': + if (sscanf (optarg, "%lu", &interval) == 0) + perror ("rate"); + break; + + case 'h': + version (stdout); + help (stdout); + exit (0); + break; + + case 'V': + version (stdout); + exit (0); + break; + + case 'p': + print = 0; + break; + + default: + version (stderr); + help (stderr); + exit (1); + break; + } + } + + if (optind >= argc) + { + version (stderr); + help (stderr); + exit (1); + } + else + dev = argv[optind]; + + fd = open (dev, O_RDONLY); + if (fd == -1) + { + perror ("open"); + exit (1); + } + + do + { + res = read (fd, &data, 8); + if (res == 0) + break; + if (res < 0) + { + if (errno == EBADFD) + fprintf (stderr, "Device %s unplugged/turned off!!\n", dev); + else + perror ("read"); + break; + } + else if (print) + printf ("Modifiers: 0x%02x " + "cte 0x%02x " + "key1 0x%02x " + "key2 0x%02x " + "key3 0x%02x " + "key4 0x%02x " + "key5 0x%02x " + "key6 0x%02x\n", + (unsigned)data[0], + (unsigned)data[1], + (unsigned)data[2], + (unsigned)data[3], + (unsigned)data[4], + (unsigned)data[5], + (unsigned)data[6], + (unsigned)data[7]); + usleep (interval); + } while (1); + close (fd); + return 0; +} + +/* + * Local Variables: + * compile-command: "make bkbd-test" + * End: + */ diff -Naur linux.225/drivers/uusbd/hidbp/bmse-test.c linux.225.visws/drivers/uusbd/hidbp/bmse-test.c --- linux.225/drivers/uusbd/hidbp/bmse-test.c Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/hidbp/bmse-test.c Sun Apr 4 17:38:39 1999 @@ -0,0 +1,154 @@ + +/* + * Mouse Boot Protocol Test + * ------------------------ + * + * The HID Boot Protocol for mice specifies the mouse will + * return, when polled, a minimum of three bytes of data. The + * disposition and meaning of the data is specified on struct + * ts_bmse_report in ../hidd/usb-hidd.h. + * + * What we do is just open the given mouse device and read + * from it. Note what happens if you suddenly unplug the mouse + * [wait some time for kusbdd to notice]. + */ + +#include +#include +#include +#include +#include + +#define DEFAULT_POLL_INTERVAL 100000 + +void version (FILE* file) +{ + fprintf (file, + "UUSBD Utils - USB HID Boot Protocol Mouse Test v$Version$\n"); + return; +} + +void help (FILE* file) +{ + fprintf (file, +"(C) 1998 Inaky Perez Gonzalez \n" +"\n" +"bmse-test [OPTIONS] DEVICE\n" +"\n" +"Options:\n" +"\n" +" -V, --version Show version info\n" +" -h, --help Show this help\n" +" -i, --interval MICROSECONDS Set delay between reads (polls) to \n" +" MICROSECONDS (default is %d us). 0\n" +" don't wait\n" +" -p, --dont-print Don't print any data, just read\n" +"\n", + DEFAULT_POLL_INTERVAL); + return; +} + +int main (int argc, char **argv) +{ + int print = 1; + int option; + int idxptr; + ssize_t res; + int fd; + char* dev; + char data[8]; + unsigned long interval = DEFAULT_POLL_INTERVAL; + + struct option longopts[] = + { + { "interval", required_argument, NULL, 'i' }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'V' }, + { "dont-print", no_argument, NULL, 'p' }, + { NULL, 0, NULL, 0 } + }; + const char shortopts[] = "i:phV"; + + while ((option = getopt_long (argc, argv, shortopts, + longopts, &idxptr)) + >= 0) + { + switch (option) + { + case 'i': + if (sscanf (optarg, "%lu", &interval) == 0) + perror ("rate"); + break; + + case 'h': + version (stdout); + help (stdout); + exit (0); + break; + + case 'V': + version (stdout); + exit (0); + break; + + case 'p': + print = 0; + break; + + default: + version (stderr); + help (stderr); + exit (1); + break; + } + } + + if (optind >= argc) + { + version (stderr); + help (stderr); + exit (1); + } + else + dev = argv[optind]; + + fd = open (dev, O_RDONLY); + if (fd == -1) + { + perror ("open"); + exit (1); + } + + do + { + res = read (fd, &data, 8); + if (res == 0) + break; + if (res < 0) + { + if (errno == EBADFD) + { + fprintf (stderr, "Device %s unplugged/turned off!!\n", dev); + break; + } + perror ("read"); + } + else if (print) + printf ("buttons: 0x%02x " + "xdelta: %d " + "ydelta: %d\n", + (unsigned)data[0], + (int)data[1], + (int)data[2]); + if (interval) + usleep (interval); + } while (1); + close (fd); + return 0; +} + +/* + * Local Variables: + * compile-command: "make bmse-test" + * End: + */ diff -Naur linux.225/drivers/uusbd/hidbp/cfg.c linux.225.visws/drivers/uusbd/hidbp/cfg.c --- linux.225/drivers/uusbd/hidbp/cfg.c Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/hidbp/cfg.c Sun Apr 4 17:38:41 1999 @@ -0,0 +1,437 @@ + +/* USB Human Interface Devices Driver v$Revision: 1.18 $ + * + * (C) 1997-99 by Iñaky Pérez González + * (C) 1998-99 by Paul Mackerras + * + * Distributed under the terms of the GNU Public License Version 2 + * See files COPYRIGHT and COPYING at the root distribution directory + * + * $Id: cfg.c,v 1.18 1999/04/05 00:38:41 inaky Exp $ + * + * Changelog at the bottom + * + * USB HID Boot Protocol + * --------------------- + * + * This is an smaller driver then HID, but is capable of reading from + * keyboards and mice which understand the boot protocol. This makes + * it nice to have it compiled for boot disks and that stuff with size + * constraints. + */ + +#define __NO_VERSION__ +#include +#include +#include /* locks */ +#include + +#include + +#define GDLF_IDENT "USB-HIDBP" +#define GDLF_LOCAL /* Define if want local settings */ +#define GDLF_DEF_LOGLEVEL 9 +#define GDLF_ASSERTIONS /* want assertions (#undef if not) */ +#undef GDLF_FNTRACE /* want function traces */ +#define GDLF_LOCATIONS /* want locations in log messages */ +#include + +#include + + + + /* Configure a HID BP interface + * + * This function may be used to be called from hidd_config() to + * configure the class part of a configurable element. + * + * Returns: + * + * int Number of cfels configured, errno code < 0 on + * error. + */ + +int hidbp_config (ts_usb_cfel* cfel, ts_usb_device* device, + ts_usb_cfg* cfg, t_usb_cfg cfg_idx, + ts_usb_iface* iface, t_usb_iface iface_idx, + ts_usb_aset* aset, t_usb_aset aset_idx, __u32 flags) +{ + int errcode; + int base; + const char *name; + ts_hidbp *hidbp; + struct file_operations *fops; + ts_usb_request req; + size_t data_size, alloc_data_size; + size_t extra_size; + void (*callback)(ts_usb_tr*,int); + void (*init)(ts_hidbp*); + + gdlf_fntrace ("hidbp_config (0x%p, 0x%p, 0x%p, " + "0x%p, 0x%p, %u)", cfel, device, cfg, + iface, aset, flags); + gdlf_aassert (cfel != NULL, return -EINVAL); + gdlf_aassert (cfel->class == HIDD_CLASS, return -EBADFD); + gdlf_aassert (device != NULL, return -EINVAL); + gdlf_aassert (iface != NULL, return -EINVAL); + gdlf_aassert (aset != NULL, return -EINVAL); + + if (cfel->class != HIDD_CLASS) + { + gdlf_err ("Pretended to configure as HID non-HID " + "class interface %d of device (%d %d)\n", + iface->addr, + usb_host_addr (device), usb_dev_addr (device)); + return 0; + } + + if (cfel->subclass != HIDD_SUBCLASS_BOOT) + { + gdlf_err ("Pretended to configure as HID Boot Protocol " + "non-HIDBP class interface %d of device (%d %d)\n", + iface->addr, + usb_host_addr (device), usb_dev_addr (device)); + return 0; + } + + /* make sure some theorical facts */ + + gdlf_assert (aset->endps == 1); + gdlf_assert (aset->endp[0].type == e_usb_tr_type_intr); + + /* Ok, configure this cfel */ + + init = NULL; + switch (cfel->protocol) + { + case HIDBP_PROTOCOL_KBD: +#ifdef CONFIG_USB_HIDBP_KBD + gdlf_info ("HID Boot Protocol Keyboard at interface %d " + "of device (%d %d)\n", iface->addr, + usb_host_addr (device), usb_dev_addr (device)); + base = HIDBP_BKBD_MINOR; + name = "keyboard"; + fops = &bkbd_fops; + data_size = sizeof (ts_bkbd_report); + alloc_data_size = data_size; + extra_size = sizeof (ts_hidbp_kbd); + callback = bkbd_callback; + init = bkbd_init; +#else + gdlf_err ("HID Boot Protocol Keyboard at interface %d " + "of device (%d %d), support not enabled\n", + iface->addr, usb_host_addr (device), + usb_dev_addr (device)); + return -ENOSYS; +#endif + break; + + /* + * We get more space then needed for data [data_size], + * because some mice may return more data then 3 bytes, + * for vendor specific data. In this case, we just read + * and discard it, in order to evitate bus errors. + */ + + case HIDBP_PROTOCOL_MSE: +#ifdef CONFIG_USB_HIDBP_MSE + gdlf_info ("HID Boot Protocol Mouse at interface %d " + "of device (%d %d)\n", iface->addr, + usb_host_addr (device), usb_dev_addr (device)); + base = HIDBP_BMSE_MINOR; + name = "mouse"; + fops = &bmse_fops; + data_size = sizeof (ts_bmse_report); + alloc_data_size = HIDBP_BMSE_ALLOC_DATA_SIZE; + extra_size = sizeof (ts_hidbp_mouse); + callback = bmse_callback; + init = bmse_init; +#else + gdlf_err ("HID Boot Protocol Mouse at interface %d " + "of device (%d %d), support not enabled\n", + iface->addr, usb_host_addr (device), + usb_dev_addr (device)); + return -ENOSYS; +#endif + break; + + default: + gdlf_err ("Interface %d of device (%d %d) supports " + "unknown HID Boot Protocol %d\n", iface->addr, + usb_host_addr (device), usb_dev_addr (device), + cfel->protocol); + return -ENOSYS; + break; + } + + /* + * Ok, we can get on with this guy. + * + * set protocol to boot protocol + */ + + req.bmreqtype = 0x21; + req.request = e_hidd_req_set_protocol; + req.value = 0; + req.index = iface->addr; + req.length = 0; + + errcode = usb_request_dataless (device, &req, "set protocol"); + if (errcode < 0) + { + gdlf_err ("Cannot set interface %d of device (%d %d) " + "to HID Boot Protocol: errno/usb %d/%d\n", + iface->addr, usb_host_addr (device), + usb_dev_addr (device), errcode, usb_errno); + return errcode; + } + + /* set report mode to idle until change */ + + req.bmreqtype = 0x21; + req.request = e_hidd_req_set_idle; + req.value = 0; /* report only if change detected */ + req.index = iface->addr; + req.length = 0; + + errcode = usb_request_dataless (device, &req, "set idle"); + if (errcode < 0) + gdlf_err ("Cannot set idle mode on HID Boot %s, " + "interface %d of device (%d %d) errno/usb %d/%d\n", + name, iface->addr, usb_host_addr (device), + usb_dev_addr (device), errcode, usb_errno); + + /* allocate a ts_hidbp structure and register it */ + + hidbp = ts_hidbp_init(); + if (hidbp == NULL) + { + gdlf_err ("Cannot allocate memory for using interface " + "%d of device (%d %d) as HID Boot Protocol %s\n", + iface->addr, usb_host_addr (device), + usb_dev_addr (device), name); + return -ENOMEM; + } + + /* data allocated on hidbp_open() */ + + hidbp->errcode = data_size; + + ts_dtor_fill (&hidbp->snode.dtor, (tf_dtor)hidbp_destroy); + errcode = hidbp_register (hidbp); + gdlf_aassert (errcode >= 0, return errcode); + + usb_pipe_dev_set (&hidbp->pipe, device); + cfel->configured = (unsigned long)hidbp; + cfel->data = ts_snode_ref (&hidbp->snode); + + hidbp->aset = aset; + hidbp->tr.pipe = &hidbp->pipe; + hidbp->tr.data_size = hidbp->tr.size = data_size; + hidbp->tr.status = e_usb_tr_status_filled; + hidbp->tr.warn.callback = callback; + hidbp->tr.done_warn = 1; + hidbp->tr.method = 1; + hidbp->tr.private = hidbp; + hidbp->tr.timeout = 0; /* let it block */ + + /* alloc a misc char device */ + + hidbp->miscdev.minor = -1; /* paranoia */ + hidbp->miscdev.minor = hidbp_free_address (base); + if (hidbp->miscdev.minor < 0) + { + gdlf_err ("No minor number space to allocate HIDBP %s at " + "device (%d %d): errno %d\n", + name, usb_host_addr (device), usb_dev_addr (device), + hidbp->miscdev.minor); + hidbp_destroy (hidbp); + usb_kfree (hidbp); + } + hidbp->miscdev.fops = fops; + + /* + * basic name is 64 chars at most, also we add lengths for + * manufacturer, device name and serial. +3 is for the + * separators. + */ + + hidbp->miscdev.name = + usb_kmalloc ( + (64 + (device->mfrer? strlen (device->mfrer) : 0) + + (device->descr? strlen (device->descr) : 0) + + (device->serial? strlen (device->serial) : 0) + + 3) * sizeof (char), GFP_KERNEL); + if (hidbp->miscdev.name == NULL) + { + gdlf_err ("No memory for device 0x%p (%d %d)'s name! " + "Aborting!!\n", device, usb_host_addr (device), + usb_dev_addr (device)); + hidbp_destroy (hidbp); + usb_kfree (hidbp); + return -ENOMEM; + } + sprintf ((char*)hidbp->miscdev.name, + "HIDBP %s/USB dev (%d %d)%s %s %s %s", + name, usb_host_addr (device), usb_dev_addr (device), + (device->mfrer || device->descr || device->serial)? ":" : "", + device->mfrer? device->mfrer : "", + device->descr? device->descr : "", + device->serial? device->serial : ""); + errcode = misc_register (&hidbp->miscdev); + if (errcode < 0) + { + gdlf_err ("Unable to register misc device with minor " + "%d! Aborting!!\n", hidbp->miscdev.minor); + hidbp_destroy (hidbp); + usb_kfree (hidbp); + } + + /* Start the first transaction */ + + errcode = usb_pipe_endp_set (&hidbp->pipe, &hidbp->aset->endp[0]); + if (errcode < 0) + { + gdlf_err ("Cannot open endpoint %d, interface %d of " + "device (%d %d) to read %s input: " + "errno/usb %d/%d\n", + hidbp->aset->endp[0].addr, hidbp->aset->addr, + usb_host_addr (hidbp->pipe.device), + usb_dev_addr (hidbp->pipe.device), + name, errcode, usb_errno); + usb_pipe_endp_unset (&hidbp->pipe); + return -ENXIO; + } + + /* Insert the tr */ + + hidbp->data = usb_kmalloc (alloc_data_size + extra_size, GFP_KERNEL); + if (hidbp->data == NULL) + { + gdlf_err ("No memory to set up a buffer for input on " + "%s\n", hidbp->miscdev.name); + usb_pipe_endp_unset (&hidbp->pipe); + return -ENOMEM; + } + hidbp->tr.data = (__u8 *) hidbp->data + extra_size; + memset (hidbp->data, 0, extra_size); + + errcode = usb_tr_setup (&hidbp->tr); + if (errcode < 0) + { + usb_kfree (hidbp->tr.data); + hidbp->tr.data = NULL; + usb_tr_setdn (&hidbp->tr); + usb_pipe_endp_unset (&hidbp->pipe); + return errcode; + } + + errcode = usb_tr_insert (&hidbp->tr); + if (errcode < 0) + { + usb_kfree (hidbp->tr.data); + hidbp->tr.data = NULL; + usb_tr_setdn (&hidbp->tr); + usb_pipe_endp_unset (&hidbp->pipe); + return errcode; + } + + /* call device-specific init function */ + + if (init) + (*init) (hidbp); + + /* schedule first read */ + + hidbp->jiffies0 = jiffies; + errcode = usb_tr_run (&hidbp->tr); + if (errcode < 0) + gdlf_err ("Error scheduling read for %s at device (%d %d): " + "errno/usb %d/%d\n", name, + usb_host_addr (hidbp->pipe.device), + usb_dev_addr (hidbp->pipe.device), + hidbp->tr.errno, hidbp->tr.usb_errno); + + return errcode; +} + + + /* Unconfigure all cfels configured by this driver + * + * This function may be used to unconfigure a driver's + * class-configured configurable elements. + * + * Parameters: + * + * ts_usb_device* Pointer to the device structure to + * unconfigure. + * + * unsigned USB_CFG_* flags indicating why is this + * function called. + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + */ + +int hidbp_unconfig (ts_usb_device* device, unsigned flags) +{ + t_usb_cfg cfg_cnt; + ts_usb_cfg *cfg; + ts_usb_iface *iface, *iface_top; + ts_usb_aset *aset, *aset_top; + + gdlf_fntrace ("hidbp_unconfig (0x%p, %u)", device, flags); + gdlf_aassert (device != NULL, return -EINVAL); + + for (cfg_cnt = 0; cfg_cnt < device->pcfgs; cfg_cnt++) + { + cfg = device->pcfg[cfg_cnt]; + if (cfg == NULL) /* unloaded? skip */ + continue; + + /* Walk cfg's interfaces */ + + for (iface = cfg->iface, iface_top = iface + cfg->ifaces; + iface < iface_top; iface++) + { + /* Walk the iface's asets */ + + for (aset = iface->aset, aset_top = aset + iface->asets; + aset < aset_top; aset++) + + /* cfged by us? */ + + if (aset->cfel.configured + && aset->cfel.data + && (aset->cfel.data->dtor.fn + == (tf_dtor)hidbp_destroy) + ) + { + ts_dtor_exec (&aset->cfel.data->dtor); + usb_kfree (aset->cfel.data); + aset->cfel.data = NULL; + aset->cfel.configured = 0; /* uncfged */ + } + } + } + return 0; +} + + +/* Log: + * + * $Log: cfg.c,v $ + * Revision 1.18 1999/04/05 00:38:41 inaky + * Renamed khubdd to kusbdd, moved to new usb_pipe_*() semantics, trimmed + * logs. + * + * Revision 1.17 1999/03/14 23:12:19 inaky + * Fixed a TYPO (with capitals). When calling usb_kfree(), it was calling + * it so that finally what got called was usb_kfree (NULL), and thus, the + * hidbp was never freed -> leak. + * + * Revision 1.16 1999/02/28 19:50:01 inaky + * Made the mice/kbd detection message be more clear to understand [I + * hope :)]. + */ diff -Naur linux.225/drivers/uusbd/hidbp/driver.c linux.225.visws/drivers/uusbd/hidbp/driver.c --- linux.225/drivers/uusbd/hidbp/driver.c Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/hidbp/driver.c Sun Apr 4 17:38:42 1999 @@ -0,0 +1,326 @@ + +/* USB Human Interface Devices Driver v$Revision: 1.9 $ + * + * (C) 1997-99 by Iñaky Pérez González + * (C) 1998-99 by Paul Mackerras + * + * Distributed under the terms of the GNU Public License Version 2 + * See files COPYRIGHT and COPYING at the root distribution directory + * + * $Id: driver.c,v 1.9 1999/04/05 00:38:42 inaky Exp $ + * + * Changelog at the bottom + * + * USB HID Boot Protocol + * --------------------- + * + * This is an smaller driver then HID, but is capable of reading from + * keyboards and mice which understand the boot protocol. This makes + * it nice to have it compiled for boot disks and that stuff with size + * constraints. + */ + +#include +#include /* __init */ +#include +#include /* locks */ +#include + +#include + +#define GDLF_IDENT "USB-HIDBP" +#define GDLF_LOCAL /* Define if want local settings */ +#define GDLF_DEF_LOGLEVEL 9 +#define GDLF_ASSERTIONS /* want assertions (#undef if not) */ +#undef GDLF_FNTRACE /* want function traces */ +#define GDLF_LOCATIONS /* want locations in log messages */ +#include + +#include + + + +#define NAME /* short!! */ \ + "USB HID Boot Protocol Driver v$Revision: 1.9 $" + +#define COPYRIGHT \ + "(c) 1998 Inaky Perez Gonzalez " \ + "" + +#define VENDOR 0 +#define VENDORNAME \ + NULL + +#define PRODUCT 0 +#define DEVICENAME \ + NULL + +#define CLASS HIDD_CLASS +#define CLASSNAME \ + "USB Human Interface Devices" + +#define SUBCLASS 1 +#define SUBCLASSNAME \ + "Boot Protocol" + +#define PROTOCOL 0 +#define PROTOCOLNAME \ + NULL + +#define SNODE_NULL { {NULL}, NULL, 0} + + /* Driver stuff */ + +atomic_t usecnt; +ts_usb_driver* hidbp_driver = NULL; +ts_slist hidbp_list; + + + /* Initialize the hidbp driver + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + */ + +int __init hidbp_init (void) +{ + int errcode; + + gdlf_fntrace ("hidbp_init()"); + gdlf_info (NAME "\n"); +#ifdef MODULE + gdlf_info (COPYRIGHT "\n"); +#endif + + hidbp_driver = ts_usb_driver_init(); + if (hidbp_driver == NULL) + { + usb_errno = -USBE_NO_MEMORY; + return -ENOMEM; + } + + /* Set driver's attributes */ + + hidbp_driver->vendor = VENDOR; + hidbp_driver->product = PRODUCT; + hidbp_driver->class = CLASS; + hidbp_driver->subclass = SUBCLASS; + hidbp_driver->protocol = PROTOCOL; + + /* Set info */ + + hidbp_driver->name = NAME; /* driver name */ + hidbp_driver->copyright = COPYRIGHT; /* driver copyright */ + hidbp_driver->vendorname = VENDORNAME; /* device's vendor name */ + hidbp_driver->productname = DEVICENAME; /* device's name */ + hidbp_driver->classname = CLASSNAME; /* class' name */ + hidbp_driver->subclassname = SUBCLASSNAME; /* subclass' name */ + hidbp_driver->protocolname = PROTOCOLNAME; /* protocol name */ + + hidbp_driver->config = hidbp_config; /* config method */ + hidbp_driver->unconfig = hidbp_unconfig; /* unconfig method */ + hidbp_driver->reference = hidbp_reference; /* reference method */ + ts_snode_ref (&hidbp_driver->snode); /* we hold a reference to it */ + + ts_slist_clean (&hidbp_list); /* initialize the list */ + errcode = usb_drv_register (hidbp_driver); /* register driver */ + if (errcode) + { + gdlf_err ("Cannot register driver: " + "errno/usb %d/%d\n", + errcode, usb_errno); + usb_drv_destroy (hidbp_driver); + usb_kfree (hidbp_driver); + return errcode; + } + return 0; +} + + + /* Release the hidbp driver + * + * Do what is needed to ensure the use count of the driver is + * zero and can be unloaded from the kernel. + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + */ + +int hidbp_release (void) +{ + ts_snode *itr, *next; + + gdlf_fntrace ("hidbp_release()"); + + usb_drv_release (hidbp_driver); /* release devices using us */ + gdlf_assert (ts_slist_head (&hidbp_driver->uselist) == NULL); + +#warning FIXME: remove me +#if 0 + itr = ts_slist_head (&hidbp_driver->uselist); + while (itr) + { + next = ts_slist_next (itr); + ts_dtor_exec (&itr->dtor); + usb_kfree (itr); + itr = next; + } +#endif + + /* + * Ok, if there still are people on the list, it means some + * failed, so we'll do it in the rude way. + */ + + itr = ts_slist_head (&hidbp_driver->uselist); + if (itr) + gdlf_warning ("Some devices neglected to release their " + "use of the HID/BP driver. Will have to use " + "the rude way. Expect inconsistencies\n"); + while (itr) + { + next = ts_slist_next (itr); + usb_drv_release_use (hidbp_driver, (ts_usb_drv_use*)itr, NULL); + itr = next; + } + + return 0; +} + + + /* Shutdown the skel driver + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + */ + +int hidbp_shutdown (void) +{ + gdlf_fntrace ("hidbp_shutdown()"); + hidbp_release(); + ts_snode_unref (&hidbp_driver->snode, NULL); + return usb_drv_unregister (hidbp_driver); +} + + + /* Driver reference + * + * The 'reference' method is used when we take any of the driver's + * code or data structures to use it. If so, we call it with a + * positive argument (one reference, regardless the value of the + * _positive_ number). When we are done, we release the reference + * calling it with a negative number. It always returns the number + * of references or < 0 on error. Calling it with an argument of + * zero will just return the number of references. + * + * Parameters: + * + * ts_usb_device* Pointer to device making the reference. + * + * int What kind: < 0 unreference, 0 report reference + * count, > 0 reference. Everytime just ONE + * [un]reference is made. + * + * Global: + * + * atomic_t usecnt Use count for the driver. + * + * Returns: + * + * int Number of references or < 0 errno code. + * + * Global: + * + * atomic_t usecnt Use count for the driver. + */ + +int hidbp_reference (ts_usb_device* device, int n) +{ + gdlf_fntrace ("hidbp_reference (0x%p, %d)", device, n); + gdlf_aassert (device != NULL, return -EINVAL); + + if (n > 0) + { + atomic_inc (&usecnt); + MOD_INC_USE_COUNT; + } + else if (n < 0) + { + atomic_dec (&usecnt); + MOD_DEC_USE_COUNT; + } + return atomic_read (&usecnt); +} + + + /* Linux module support */ + +#ifdef MODULE + +int init_module (void) +{ + return hidbp_init(); +} + +void cleanup_module (void) +{ + hidbp_release(); + hidbp_shutdown(); + return; +} + +#endif + + +/* Log: + * + * $Log: driver.c,v $ + * Revision 1.9 1999/04/05 00:38:42 inaky + * Renamed khubdd to kusbdd, moved to new usb_pipe_*() semantics, trimmed + * logs. + * + * Revision 1.8 1999/03/14 23:12:55 inaky + * Now it should wot be needed that loop to look for unreleased hidbps, + * keep the assertion just in case. + * + * Revision 1.7 1999/03/09 22:54:26 inaky + * Finished hidb_release(), so when the driver is unloaded, all devices + * by it configured get also released. + * + * Revision 1.6 1999/02/03 22:35:04 inaky + * *** empty log message *** + * + * Revision 1.5 1999/01/31 11:44:38 inaky + * Added some docs. + * + * Revision 1.4 1998/12/12 15:17:04 inaky + * Removed tracing. + * + * Revision 1.3 1998/11/14 17:18:55 inaky + * Moved the include files to uusbd/include/uusbd, to ease integration + * into the Linux kernel. + * + * Revision 1.2 1998/09/14 02:03:58 inaky + * Reworked the driver and config system to register the misc device only + * on device configuration time. + * + * Revision 1.1 1998/09/11 00:50:57 inaky + * Moved the HID Boot Protocol to a single driver, so it can be isolated + * more easily. It supports keyboards and mice, settable at compile time. + * + * Revision 1.1 1998/08/30 13:55:46 inaky + * Added boot protocol support and a simple test program. + * + * Revision 1.1 1998/08/28 23:53:14 inaky + * New driver + * + * Revision 1.3 1998/08/28 00:14:22 inaky + * New driver ... + * + */ + + + diff -Naur linux.225/drivers/uusbd/hidbp/hidbp.c linux.225.visws/drivers/uusbd/hidbp/hidbp.c --- linux.225/drivers/uusbd/hidbp/hidbp.c Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/hidbp/hidbp.c Sun Apr 4 17:38:43 1999 @@ -0,0 +1,243 @@ + +/* USB Human Interface Devices Driver v$Revision: 1.13 $ + * + * (C) 1997-99 by Iñaky Pérez González + * + * Distributed under the terms of the GNU Public License Version 2 + * See files COPYRIGHT and COPYING at the root distribution directory + * + * $Id: hidbp.c,v 1.13 1999/04/05 00:38:43 inaky Exp $ + * + * Changelog at the bottom + * + * USB HID Boot Protocol + * --------------------- + * + * Stuff common to both mice and kbds. + */ + +#define __NO_VERSION__ +#include +#include +#include /* locks */ +#include + +#include + +#define GDLF_IDENT "USB-HIDBP" +#define GDLF_LOCAL /* Define if want local settings */ +#define GDLF_DEF_LOGLEVEL 9 +#define GDLF_ASSERTIONS /* want assertions (#undef if not) */ +#undef GDLF_FNTRACE /* want function traces */ +#define GDLF_LOCATIONS /* want locations in log messages */ +#include + +#include + + + /* Seek a free minor address and return it. + * + * NOTE: The method for doing this search could be enhanced, as it + * is no secret I haven't squeezed my brains finding one :) + * + * We'll just start with address number 'base' and count up. With + * each one, we'll test all the elements in the list and see if + * someone owns it. If it does, we'll use the next one, and so + * on. + * + * Returns: + * + * int Free address if ok, errno code < 0 on + * error. Address is guaranteed to be between + * 'base' and 'base + HIDBP_DEVICES_MAX'. If no + * address is available, -ENOSPC (no space left + * on device) will be returned. + */ + +#define HIDBP_DEVICES_MAX 16 + +int hidbp_free_address (unsigned base) +{ + ts_hidbp* itr; + int addr = base; /* default initial address */ + int top = addr + HIDBP_DEVICES_MAX; + + gdlf_fntrace ("hidbp_free_address (%u)", base); + + for (addr = base; addr < top; addr++) /* cycle all addresses */ + { + itr = (ts_hidbp*) /* get last registered device */ + ts_slist_head (&hidbp_list); + while (itr) /* on each cycle hidbps */ + { + if (itr->miscdev.minor == addr) /* Used? */ + break; /* ok, skip */ + itr = (ts_hidbp*) ts_slist_next (&itr->snode); + } + if (itr == NULL) /* unused addr */ + return addr; + } + + /* Bad, none found */ + + return -ENOSPC; +} + + + /* Open a boot protocol device + * + * Major number is HIDBP_MAJOR, minor number is at the ts_hidbp. They + * are numbered after the configuration order. devfs will rock + * here. + * + * Parameters: + * + * struct inode* i-node description structure. + * + * struct file* file description structure. + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + */ + +int hidbp_open (struct inode *inode, struct file *file) +{ + unsigned minor; /* hidbp struct index number */ + ts_hidbp *hidbp; + + gdlf_fntrace ("hidbp_open (0x%p, 0x%p)", inode, file); + gdlf_aassert (inode != NULL, return -EINVAL); + gdlf_aassert (file != NULL, return -EINVAL); + + /* Find which _hidbp_ are we referring to */ + + minor = MINOR (inode->i_rdev); /* get the minor number */ + hidbp = (ts_hidbp*)ts_slist_head (&hidbp_list); + while (hidbp) + { + if (gdlf_c1assert (hidbp->aset) + && gdlf_c1assert (hidbp->aset->cfel.class == HIDD_CLASS) + && gdlf_c1assert (hidbp->aset->cfel.subclass == HIDD_SUBCLASS_BOOT) + && hidbp->miscdev.minor == minor) + break; + hidbp = (ts_hidbp*)ts_slist_next (&hidbp->snode); + } + + if (hidbp == NULL) /* not found */ + return -ENODEV; + + /* set the private data, increment the reference count */ + + file->private_data = ts_snode_ref (&hidbp->snode); + hidbp->file = file; + MOD_INC_USE_COUNT; + + return 0; +} + + + /* Close a boot protocol device + * + * Note we always do the MOD_DEC_USE_COUNT. Why? Easy, on device + * plugout, hidbp_destroy() shouldn't do it, as it could mean the + * module will be unloaded, and when this function called, it + * won't be there ... error. + * + * However, on device plugout [and hidbp_destroy() called], + * file->private_data is NULL, so we must accept the case. A file + * will always be opened with a NON NULL file->private_data, so we + * can count this will be always the same case. + * + * Parameters: + * + * struct inode* i-node description structure. + * + * struct file* file description structure. + * + * Returns: + * + * int 0 no error detected, != errno error code. + */ + +int hidbp_close (struct inode *inode, struct file *file) +{ + ts_hidbp *hidbp; + + gdlf_fntrace ("hidbp_close (0x%p, 0x%p)", inode, file); + gdlf_aassert (inode != NULL, return -EINVAL); + gdlf_aassert (file != NULL, return -EINVAL); + + MOD_DEC_USE_COUNT; + hidbp = file->private_data; /* get the private data */ + if (hidbp == NULL) /* device removed? */ + return 0; + gdlf_aassert (hidbp->snode.dtor.fn == (tf_dtor)hidbp_destroy, + return -EINVAL); + file->private_data = NULL; + hidbp->file = NULL; + ts_snode_unref (&hidbp->snode, NULL); + return 0; +} + + + +/* Log: + * + * $Log: hidbp.c,v $ + * Revision 1.13 1999/04/05 00:38:43 inaky + * Renamed khubdd to kusbdd, moved to new usb_pipe_*() semantics, trimmed + * logs. + * + * Revision 1.12 1999/02/08 15:34:53 inaky + * Removed tracing. + * + * Revision 1.11 1999/01/31 11:44:58 inaky + * Added again the setting of file descriptor, in a temporary way. We + * should fix this RSN. + * + * Revision 1.10 1998/12/19 17:09:58 inaky + * Fixed the assignation of addresses. It was broken. + * + * Revision 1.9 1998/12/16 00:21:29 inaky + * Fixed the behaviour on closing or destroying, to keep modules until + * all devices are closed. + * + * Revision 1.8 1998/12/12 02:41:55 inaky + * Reorganized the code. + * + * Revision 1.7 1998/11/26 21:58:22 inaky + * Renamed all the ts_usb_open stuff and friends to use _pipe_. + * + * Revision 1.6 1998/11/17 13:36:56 inaky + * Made the mouse reading doyuble buffered, to evitate X slowing down. + * + * Revision 1.5 1998/11/14 17:18:56 inaky + * Moved the include files to uusbd/include/uusbd, to ease integration + * into the Linux kernel. + * + * Revision 1.4 1998/11/09 21:33:54 inaky + * You should get an error code before checking it ... + * + * Revision 1.3 1998/10/22 00:06:45 inaky + * Moved to hidbp_config() the selection of the size to use for the + * data. Also fixed bits when freeing. + * + * Revision 1.2 1998/09/14 02:04:23 inaky + * Added all the common routines, such as config, open, close and search + * for a free address. + * + * Revision 1.1 1998/09/11 00:50:57 inaky + * Moved the HID Boot Protocol to a single driver, so it can be isolated + * more easily. It supports keyboards and mice, settable at compile time. + * + * Revision 1.1 1998/08/30 13:55:46 inaky + * Added boot protocol support and a simple test program. + * + * Revision 1.1 1998/08/28 23:53:14 inaky + * New driver + * + * Revision 1.3 1998/08/28 00:14:22 inaky + * New driver ... + * + */ diff -Naur linux.225/drivers/uusbd/hidbp/hkeep.c linux.225.visws/drivers/uusbd/hidbp/hkeep.c --- linux.225/drivers/uusbd/hidbp/hkeep.c Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/hidbp/hkeep.c Sun Apr 4 17:38:44 1999 @@ -0,0 +1,236 @@ + +/* USB Human Interface Devices Driver v$Revision: 1.13 $ + * + * (C) 1997-99 by Iñaky Pérez González + * + * Distributed under the terms of the GNU Public License Version 2 + * See files COPYRIGHT and COPYING at the root distribution directory + * + * $Id: hkeep.c,v 1.13 1999/04/05 00:38:44 inaky Exp $ + * + * Changelog at the bottom + * + * USB HID Boot Protocol + * --------------------- + * + * This is an smaller driver then HID, but is capable of reading from + * keyboards and mice which understand the boot protocol. This makes + * it nice to have it compiled for boot disks and that stuff with size + * constraints. + */ + +#define __NO_VERSION__ +#include +#include +#include /* locks */ +#include + +#include + +#define GDLF_IDENT "USB-HIDBP" +#define GDLF_LOCAL /* Define if want local settings */ +#define GDLF_DEF_LOGLEVEL 9 +#define GDLF_ASSERTIONS /* want assertions (#undef if not) */ +#undef GDLF_FNTRACE /* want function traces */ +#define GDLF_LOCATIONS /* want locations in log messages */ +#include + +#include + + + /* Unregister an hidbp element + * + * This is the destructor function. + * + * Parameters: + * + * ts_hidbp* Class element to unregister + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + */ + +int hidbp_unregister (ts_hidbp* hidbp) +{ + gdlf_fntrace ("hidbp_unregister (0x%p)", hidbp); + gdlf_aassert (hidbp != NULL, return -EINVAL); + gdlf_aassert (hidbp->snode.dtor.fn == (tf_dtor)hidbp_destroy, + return -EINVAL); + + /* Let's get it removed from the list */ + + ts_slist_del (&hidbp_list, &hidbp->snode); + return 0; /* bye */ +} + + + /* Destroy a hidbp structure. + * + * Parameters: + * + * ts_hidbp* HIDBP struct to kill. + * + * Returns: + * + * int 0 if ok, < 0 errno code on error. + */ + +extern void bkbd_shutdown (ts_hidbp*); + +int hidbp_destroy (ts_hidbp* hidbp) +{ + gdlf_fntrace ("hidbp_destroy (0x%p)", hidbp); + gdlf_aassert (hidbp != NULL, return -EINVAL); + gdlf_assert (hidbp->aset != NULL); + gdlf_assert (hidbp->pipe.device != NULL); + + ts_snode_ref (&hidbp->snode); + + /* hidbp->file may be null, if no file is opened */ + + if (hidbp->aset) + switch (hidbp->aset->cfel.protocol) + { + case HIDBP_PROTOCOL_KBD: +#ifdef CONFIG_USB_HIDBP_KBD + bkbd_shutdown (hidbp); +#endif + break; + + case HIDBP_PROTOCOL_MSE: +#ifdef CONFIG_USB_HIDBP_MSE + bmse_destroy (hidbp); +#endif + break; + + default: + gdlf_err ("Device (%d %d) supports " + "unknown HID Boot Protocol %d\n", + usb_host_addr (hidbp->pipe.device), + usb_dev_addr (hidbp->pipe.device), + hidbp->aset->cfel.protocol); + break; + } + + /* + * Temporarily enabled. If not, we don't unref the hidbp and + * the module stays there. Also when hidbp_close() is called, + * we have trouble, as there's nothing to refer to. + */ + +#warning FIXME: remove me? agree with paul, multi file opens: how? +#if 1 + if (hidbp->file && hidbp->file->private_data) /* tell file to go away */ + { + gdlf_assert (hidbp->file->private_data == hidbp); + hidbp->file->private_data = NULL; + ts_snode_unref (&hidbp->snode, NULL); + } +#endif + if (hidbp->data) + usb_kfree (hidbp->data); + usb_pipe_close (&hidbp->pipe); + hidbp_unregister (hidbp); /* unregister */ + /* remove the reference for cfel.data */ + ts_snode_unref (&hidbp->snode, NULL); + ts_snode_unref_nd (&hidbp->snode); + ts_hidbp_release (hidbp); + return 0; +} + + + /* Register an hidbp element + * + * Parameters: + * + * ts_hidbp* Class element to register + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + */ + +int hidbp_register (ts_hidbp* hidbp) +{ + int errcode; + + gdlf_fntrace ("hidbp_register (0x%p)", hidbp); + gdlf_aassert (hidbp != NULL, return -EINVAL); + gdlf_aassert (hidbp->snode.dtor.fn == (tf_dtor)hidbp_destroy, + return -EINVAL); + + /* get into the list */ + + errcode = ts_slist_prep (&hidbp_list, &hidbp->snode); + if (errcode) + return errcode; + return 0; /* bye */ +} + + +/* Log: + * + * $Log: hkeep.c,v $ + * Revision 1.13 1999/04/05 00:38:44 inaky + * Renamed khubdd to kusbdd, moved to new usb_pipe_*() semantics, trimmed + * logs. + * + * Revision 1.12 1999/03/09 22:55:04 inaky + * Add a destructor to hidbp_destroy() for mice, as the poll table + * entries are still active and we need to tell them to stop, as well as + * the asynchornous tasks. + * + * Revision 1.11 1999/02/03 22:35:12 inaky + * *** empty log message *** + * + * Revision 1.10 1999/01/31 11:45:26 inaky + * Added some docs and again, temporarily, info on file descriptors. + * + * Revision 1.9 1999/01/23 18:48:15 inaky + * Added a fix by Paul MacKerras. We were allocating hidbp->data and + * setting hidbp->tr.data to hidbp->data + extra_size; thus, freeing + * hidbp->tr.data caused an error. As far as I remember, I am the one to + * blame for doing that ... :) + * + * Revision 1.8 1998/12/16 00:21:54 inaky + * Added suhutdown functions [mainly to unregister keyboards]. + * + * Revision 1.7 1998/12/12 15:17:05 inaky + * Removed tracing. + * + * Revision 1.6 1998/11/26 21:58:23 inaky + * Renamed all the ts_usb_open stuff and friends to use _pipe_. + * + * Revision 1.5 1998/11/14 17:18:57 inaky + * Moved the include files to uusbd/include/uusbd, to ease integration + * into the Linux kernel. + * + * Revision 1.4 1998/10/31 02:16:43 inaky + * Removed all the d_* pointers from ts_usb_cfel and collapsed them into + * a single pointer; only one was really used. + * + * Revision 1.3 1998/10/22 00:07:22 inaky + * Made it free the buffer space used by the tr to get data from the kbd + * or mouse. + * + * Revision 1.2 1998/09/14 02:04:37 inaky + * Removed global variables comment. + * + * Revision 1.1 1998/09/11 00:50:58 inaky + * Moved the HID Boot Protocol to a single driver, so it can be isolated + * more easily. It supports keyboards and mice, settable at compile time. + * + * Revision 1.1 1998/08/30 13:55:46 inaky + * Added boot protocol support and a simple test program. + * + * Revision 1.1 1998/08/28 23:53:14 inaky + * New driver + * + * Revision 1.3 1998/08/28 00:14:22 inaky + * New driver ... + * + */ + + + diff -Naur linux.225/drivers/uusbd/hidbp/keyboard.c linux.225.visws/drivers/uusbd/hidbp/keyboard.c --- linux.225/drivers/uusbd/hidbp/keyboard.c Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/hidbp/keyboard.c Thu Apr 15 17:55:00 1999 @@ -0,0 +1,771 @@ + +/* USB Human Interface Devices Driver Boot Protocol v$Revision: 1.13 $ + * + * (C) 1997-99 by Iñaky Pérez González + * (C) 1998-99 by Paul Mackerras + * + * Distributed under the terms of the GNU Public License Version 2 + * See files COPYRIGHT and COPYING at the root distribution directory + * + * $Id: keyboard.c,v 1.13 1999/04/05 00:38:45 inaky Exp $ + * + * Changelog at the bottom + * + * USB HID Boot Protocol + * --------------------- + * + * This is an smaller driver then HID, but is capable of reading from + * keyboards and mice which understand the boot protocol. This makes + * it nice to have it compiled for boot disks and that stuff with size + * constraints. + */ + +#define __NO_VERSION__ +#include +#include +#include /* locks */ +#include + +#include /* kbd stuff */ +#include + +#include + +#define GDLF_IDENT "USB-HIDBP" +#define GDLF_LOCAL /* Define if want local settings */ +#define GDLF_DEF_LOGLEVEL 9 +#define GDLF_ASSERTIONS /* want assertions (#undef if not) */ +#undef GDLF_FNTRACE /* want function traces */ +#define GDLF_LOCATIONS /* want locations in log messages */ +#include + +#include +#include + +#if defined (CONFIG_PMAC) && defined (CONFIG_USB_HIDBP_MSE) +#define EMULATE_BUTTONS +#endif + +extern int bkbd_setkeycode (void *devid, unsigned int scancode, + unsigned keycode); +extern int bkbd_getkeycode (void *devid, unsigned int scancode); +extern int bkbd_pretranslate (void *devid, unsigned char scancode, + char raw_mode); +extern int bkbd_translate (void *devid, unsigned char scancode, + unsigned char *keycode, char raw_mode); +extern char bkbd_unexpected_up (void *devid, unsigned char keycode); +extern void bkbd_leds (void *devid, unsigned char leds); + + /* Hack for emulating buttons 2 and 3 using the keyboard */ + +#ifdef EMULATE_BUTTONS +int bkbd_emulate_b2_code = e_hidd_kpd_num_lock_clear; +int bkbd_emulate_b3_code = e_hidd_kpd_equal; +extern void bmse_emulate_button (int button, int down); +#endif + + + /* this map indicates which keys shouldn't autorepeat. */ + +static unsigned char dont_repeat[128] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, /* esc */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* modifiers */ +}; + +extern ushort *usb_key_maps[]; + + + /* FIXME: Detailed desc + * + * Compliance: USB Spec 1.0 xxxx + * + * Parameters: + * + * type descr + * + * Global: + * + * type name descr + * + * Returns: + * + * type descr + * + * Global: + * + * type name descr + */ + +int bkbd_setkeycode (void *devid, unsigned int scancode, + unsigned int keycode) +{ + gdlf_fntrace ("bkbd_setkeycode (0x%p, %u, %u)", + devid, scancode, keycode); + gdlf_aassert (devid != NULL, return -EINVAL); + + return -EINVAL; +} + + + /* FIXME: Detailed desc + * + * Compliance: USB Spec 1.0 xxxx + * + * Parameters: + * + * type descr + * + * Global: + * + * type name descr + * + * Returns: + * + * type descr + * + * Global: + * + * type name descr + */ + +int bkbd_getkeycode (void *devid, unsigned int scancode) +{ + gdlf_fntrace ("bkbd_getkeycode (0x%p, %u)", devid, scancode); + gdlf_aassert (devid != NULL, return -EINVAL); + + return -EINVAL; +} + + + /* FIXME: Detailed desc + * + * Compliance: USB Spec 1.0 xxxx + * + * Parameters: + * + * type descr + * + * Global: + * + * type name descr + * + * Returns: + * + * type descr + * + * Global: + * + * type name descr + */ + +int bkbd_pretranslate (void *devid, unsigned char scancode, + char raw_mode) +{ + gdlf_fntrace ("bkbd_pretranslate (0x%p, %u, %u)", + devid, (unsigned)scancode, (unsigned)raw_mode); + gdlf_aassert (devid != NULL, return -EINVAL); + + return 1; +} + + + /* FIXME: Detailed desc + * + * Compliance: USB Spec 1.0 xxxx + * + * Parameters: + * + * type descr + * + * Global: + * + * type name descr + * + * Returns: + * + * type descr + * + * Global: + * + * type name descr + */ + +int bkbd_translate (void *devid, unsigned char keycode, + unsigned char *keycodep, char raw_mode) +{ + gdlf_fntrace ("bkbd_translate (0x%p, %u, 0x%p, %u)", + devid, (unsigned)keycode, keycodep, + (unsigned)raw_mode); + gdlf_aassert (devid != NULL, return -EINVAL); + gdlf_aassert (keycodep != NULL, return -EINVAL); + + if (!raw_mode) + { + /* Convert R-shift/control/option/cmd to L version. */ + if (keycode >= 0x7b && keycode <= 0x7e) + keycode -= 4; + } + *keycodep = keycode; + return 1; +} + + + /* FIXME: Detailed desc + * + * Compliance: USB Spec 1.0 xxxx + * + * Parameters: + * + * type descr + * + * Global: + * + * type name descr + * + * Returns: + * + * type descr + * + * Global: + * + * type name descr + */ + +char bkbd_unexpected_up (void *devid, unsigned char keycode) +{ + gdlf_fntrace ("bkbd_translate (0x%p, %u)", + devid, (unsigned)keycode); + gdlf_aassert (devid != NULL, return 0); + + return 0x80; +} + + + /* FIXME: Detailed desc + * + * Compliance: USB Spec 1.0 xxxx + * + * Parameters: + * + * type descr + * + * Global: + * + * type name descr + * + * Returns: + * + * type descr + * + * Global: + * + * type name descr + */ + +void bkbd_leds (void *devid, unsigned char leds) +{ + gdlf_fntrace ("bkbd_translate (0x%p, %u)", + devid, (unsigned)leds); + gdlf_aassert (devid != NULL, return); + +#warning FIXME: bkbd_leds not implemented! +} + + /* + * HIDBP Keyboard Operations + * + * Some ops are still unimplemented. + */ + +struct kbd_ll_operations bkbd_operations = +{ + bkbd_setkeycode, + bkbd_getkeycode, + bkbd_pretranslate, + bkbd_translate, + bkbd_unexpected_up, + bkbd_leds, + -1, /* no SysRq key */ + NULL, + HZ/2, HZ/15, + dont_repeat +}; + + + + /* Initialize a keyboard for use by the kernel. + * + * The device is configured and the interrupt transaction is + * ready to run, but not running yet. + * + * We use hidbp->data as a bitmap of the keys which are down. + * + * Parameters: + * + * type descr + * + * Global: + * + * type name descr + * + * Returns: + * + * type descr + * + * Global: + * + * type name descr + */ + +void bkbd_init (ts_hidbp *hidbp) +{ + ts_hidbp_kbd *kb; + + gdlf_fntrace ("bkbd_init (0x%p)", hidbp); + gdlf_aassert (hidbp != NULL, return); + + kb = (ts_hidbp_kbd*) hidbp->data; + + kb->kbd_id = register_keyboard (&bkbd_operations, hidbp, + usb_key_maps); + if (kb->kbd_id == NULL) + gdlf_err ("Couldn't register USB HIDBP keyboard at " + "device (%d %d)\n", + usb_host_addr (hidbp->pipe.device), + usb_dev_addr (hidbp->pipe.device)); +} + + + /* Make kernel forget a keyboard + * + * Parameters: + * + * type descr + * + * Returns: + * + * type descr + */ + +void bkbd_shutdown (ts_hidbp *hidbp) +{ + ts_hidbp_kbd *kb; + + gdlf_fntrace ("bkbd_shutdown (0x%p)", hidbp); + gdlf_aassert (hidbp != NULL, return); + + kb = (ts_hidbp_kbd*) hidbp->data; + + if (kb != NULL && kb->kbd_id != NULL) + { + unregister_keyboard (kb->kbd_id); + kb->kbd_id = NULL; + } +} + + + /* FIXME: Detailed desc + * + * Compliance: USB Spec 1.0 xxxx + * + * Parameters: + * + * type descr + * + * Global: + * + * type name descr + * + * Returns: + * + * type descr + * + * Global: + * + * type name descr + */ + +static void input_keycode (ts_hidbp *bkbd, int code, int down) +{ + ts_hidbp_kbd *kb; + + gdlf_fntrace ("input_keycode (0x%p, %d, %d)", bkbd, code, down); + gdlf_aassert (bkbd != NULL, return); + + kb = (ts_hidbp_kbd*) bkbd->data; + + /* + * Unfortunately we have to compress the 8-bit keycode range + * that USB gives to a 7-bit range. + */ + + if (code >= 0x77) + { + if (code >= e_hidd_kbd_left_control + && code <= e_hidd_kbd_right_gui) + code -= e_hidd_kbd_left_control - 0x77; + else + return; + } + /* + * For the iMac, we emulate mouse buttons 2 and 3 using keyboard + * buttons. + */ + +#ifdef EMULATE_BUTTONS + if (code == bkbd_emulate_b2_code) + { + bmse_emulate_button (2, down); + return; + } + if (code == bkbd_emulate_b3_code) + { + bmse_emulate_button (3, down); + return; + } +#endif /* EMULATE_BUTTONS */ + + kbd_handle_scancode (kb->kbd_id, code + (down? 0: 0x80)); +} + + + /* FIXME: Detailed desc + * + * Compliance: USB Spec 1.0 xxxx + * + * Parameters: + * + * type descr + * + * Global: + * + * type name descr + * + * Returns: + * + * type descr + * + * Global: + * + * type name descr + */ + +void bkbd_callback (ts_usb_tr* tr, int flags) +{ + ts_hidbp *bkbd; + ts_hidbp_kbd *kb; + int errcode; + + gdlf_fntrace ("bkbd_callback (0x%p, 0x%x)", tr, flags); + gdlf_aassert (tr != NULL, return); + + if (flags & USB_CB_ABORTED) + return; + + /* copy the data */ + + bkbd = tr->private; + gdlf_aassert (bkbd != NULL, return); + kb = (ts_hidbp_kbd*) bkbd->data; + gdlf_aassert (kb != NULL, return); + + bkbd->errcode = errcode = + tr->errno < 0? tr->errno : tr->xfered; + + if (errcode >= 0) + { + /* + * We have received some data from the keyboard. We make + * a bitmap of the keys that are currently down and + * compare it with the bitmap of keys that were down + * before in order to detect key down/up transitions. + */ + int i, k; + unsigned char *trdata = (unsigned char *) tr->data; + unsigned char newmap[HIDBP_KBD_KDN_BITMAP_SIZE]; /* keys down now */ + + memset (newmap, 0, sizeof (newmap)); + + /* + * The first byte of the boot keyboard report contains the + * modifier keys (left and right control, shift, option, + * command) as a bitmap, so we copy that byte to the + * appropriate byte of our bitmap. + */ + newmap[e_hidd_kbd_left_control/8] = trdata[0]; + + /* + * Bytes 2 - 7 contain codes of other keys that are down. + * If they are e_hidd_kbd_rollover_error, there are too + * many keys down to report. + */ + + for (i = 2; i < errcode; ++i) + { + int k = trdata[i]; + if (k == e_hidd_kbd_rollover_error) + goto ignore; + if (k <= e_hidd_kbd_undefined_error) + continue; + newmap[k >> 3] |= 1 << (k & 7); + } + + /* + * Now compare the old and new bitmaps and call the + * input_keycode() procedure for any codes whose bit + * differs. We also update the stored bitmap here. + */ + + for (i = 0; i < HIDBP_KBD_KDN_BITMAP_SIZE; ++i) + { + if (newmap[i] != kb->keymap[i]) + { + int diff = newmap[i] ^ kb->keymap[i]; + for (k = 0; k < 8; ++k) + { + if ((diff & (1 << k)) != 0) + input_keycode (bkbd, (i << 3) + k, + newmap[i] & (1<keymap[i] = newmap[i]; + } + } + ignore: + memset (tr->data, 0, tr->size); + bkbd->errcode = tr->xfered; + } + else + { + bkbd->errcode = errcode; + bkbd->errors++; + + /* Check if we are having more errors then allowed + * + * We check each HZ/3 the quantity of errors, then reset + * the counts. If it goes over the stablished quota + * ... reset. + */ + + if ((jiffies - bkbd->jiffies0) > HZ / 3) + { + if ((bkbd->errors * HZ / (jiffies - bkbd->jiffies0) / 3) + > HIDBP_MAX_ERRS_SEC / 3) + { + gdlf_err ("Too many errors (%lu in %lu jiffies) reading " + "keyboard at device (%d %d): errno/usb %d/%d; " + "resetting\n", + bkbd->errors, jiffies - bkbd->jiffies0, + bkbd->pipe.device? usb_host_addr (bkbd->pipe.device) : -1, + bkbd->pipe.device? usb_dev_addr (bkbd->pipe.device) : -1, + tr->errno, tr->usb_errno); + usb_device_reset_safe (bkbd->pipe.device); + return; + } + bkbd->jiffies0 = jiffies; + bkbd->errors = 0; + } + } + + /* reschedule */ + + usb_tr_reset (tr); + errcode = usb_tr_run (tr); + if (errcode < 0) + { +#if what_is_pipe_host + gdlf_err ("Error scheduling read for kbd at device (%d %d): " + "errno/usb %d/%d\n", + bkbd->pipe.host? usb_host_addr (bkbd->pipe.device) : -1, + bkbd->pipe.device? usb_dev_addr (bkbd->pipe.device) : -1, + tr->errno, tr->usb_errno); +#endif + if (errcode == -EREMOTEIO) + usb_endp_stall_clear (tr->pipe); + bkbd->errcode = errcode; + } + return; +} + + + /* FIXME: Detailed desc + * + * Compliance: USB Spec 1.0 xxxx + * + * Parameters: + * + * type descr + * + * Global: + * + * type name descr + * + * Returns: + * + * type descr + * + * Global: + * + * type name descr + */ + +ssize_t bkbd_read (struct file* file, char* data, size_t size, + loff_t* offset) +{ + ts_hidbp *bkbd; + ssize_t errcode; + + gdlf_fntrace ("bkbd_read (0x%p, 0x%p, %u, 0x%p)", + file, data, size, offset); + gdlf_aassert (file != NULL, return -EINVAL); + gdlf_aassert (data != NULL, return -EINVAL); + gdlf_aassert (file != NULL, return -EINVAL); + + if (size < sizeof (ts_bkbd_report)) + return -EINVAL; + + errcode = verify_area (VERIFY_WRITE, data, size); + if (errcode) + return errcode; + + bkbd = file->private_data; /* get the private data */ + if (bkbd == NULL) /* device removed? */ + return -EBADFD; + gdlf_aassert (bkbd->snode.dtor.fn == (tf_dtor)hidbp_destroy, + return -EBADFD); + + errcode = bkbd->errcode; + if (errcode >= 0) + { + copy_to_user (data, bkbd->data, errcode); + if (size > errcode) + clear_user (data + errcode, size - errcode); + } + return errcode; +} + + + /* FIXME: Detailed desc + * + * Compliance: USB Spec 1.0 xxxx + * + * Parameters: + * + * type descr + * + * Global: + * + * type name descr + * + * Returns: + * + * type descr + * + * Global: + * + * type name descr + */ + +int bkbd_ioctl (struct inode* inode, struct file* file, + unsigned int cmd, unsigned long arg) +{ + ts_hidbp* bkbd; + + gdlf_fntrace ("bkbd_ioctl (0x%p, 0x%p, %u, %lu)", + inode, file, cmd, arg); + gdlf_aassert (inode != NULL, return -EINVAL); + gdlf_aassert (file != NULL, return -EINVAL); + + bkbd = file->private_data; /* get the private data */ + if (bkbd == NULL) /* device removed? */ + return -EBADFD; + +#warning FIXME: ioctls? + return 0; +} + +struct file_operations bkbd_fops = +{ + NULL, /* llseek */ + bkbd_read, /* read */ + NULL, /* write */ + NULL, /* readdir */ + NULL, /* select */ + bkbd_ioctl, /* ioctl */ + NULL, /* mmap */ + hidbp_open, /* open */ + NULL, /* flush */ + hidbp_close, /* release */ + NULL, /* fsync */ + NULL, /* fasync */ + NULL, /* check_media_change */ + NULL /* revalidate */ +}; + + +/* Log: + * + * $Log: keyboard.c,v $ + * Revision 1.13 1999/04/05 00:38:45 inaky + * Renamed khubdd to kusbdd, moved to new usb_pipe_*() semantics, trimmed + * logs. + * + * Revision 1.12 1999/02/08 15:36:30 inaky + * Don't do anything at the callback when aborted. + * + * Revision 1.11 1999/02/07 01:37:23 inaky + * Small cosmetic changes, reset device on error. + * + * Revision 1.10 1998/12/25 22:53:04 inaky + * Merged changes by Paul MacKerras, mostly documentation and + * unregistration of keyboard on shutdown. + * + * Revision 1.9 1998/12/16 00:22:31 inaky + * Many changes [all by Paul, I guess], mostly to add 3 button emulation + * to mice. + * + * Revision 1.8 1998/12/12 02:42:30 inaky + * Added the kernel integration stuff [by Paul]. Some pretty printing by + * Iñaky. + * + * Revision 1.7 1998/11/26 21:58:24 inaky + * Renamed all the ts_usb_open stuff and friends to use _pipe_. + * + * Revision 1.6 1998/11/14 17:18:58 inaky + * Moved the include files to uusbd/include/uusbd, to ease integration + * into the Linux kernel. + * + * Revision 1.5 1998/10/14 21:47:16 inaky + * Fixed _blatant_ mistake! + * + * Revision 1.4 1998/09/24 16:06:15 inaky + * Fixed all the writing code, just to be sure and make it cleaner. + * + * Revision 1.3 1998/09/24 16:00:50 inaky + * Added area verification before write and clearing stalled endpoints on + * error. + * + * Revision 1.2 1998/09/14 02:05:11 inaky + * Removed unneeded specific routines. Made the tr be inserted at open + * time and only ran at read time. + * + * Revision 1.1 1998/09/11 00:50:58 inaky + * Moved the HID Boot Protocol to a single driver, so it can be isolated + * more easily. It supports keyboards and mice, settable at compile time. + * + * Revision 1.1 1998/08/30 13:55:46 inaky + * Added boot protocol support and a simple test program. + * + * Revision 1.1 1998/08/28 23:53:14 inaky + * New driver + * + * Revision 1.3 1998/08/28 00:14:22 inaky + * New driver ... + * + */ diff -Naur linux.225/drivers/uusbd/hidbp/keymap.c linux.225.visws/drivers/uusbd/hidbp/keymap.c --- linux.225/drivers/uusbd/hidbp/keymap.c Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/hidbp/keymap.c Thu Apr 15 17:55:14 1999 @@ -0,0 +1,166 @@ +/* Do not edit this file! It was automatically generated by */ +/* loadkeys --mktable defkeymap.map > defkeymap.c */ + +#include +#include +#include + +static u_short plain_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf200, 0xf200, 0xfb61, 0xfb62, 0xfb63, 0xfb64, + 0xfb65, 0xfb66, 0xfb67, 0xfb68, 0xfb69, 0xfb6a, 0xfb6b, 0xfb6c, + 0xfb6d, 0xfb6e, 0xfb6f, 0xfb70, 0xfb71, 0xfb72, 0xfb73, 0xfb74, + 0xfb75, 0xfb76, 0xfb77, 0xfb78, 0xfb79, 0xfb7a, 0xf031, 0xf032, + 0xf033, 0xf034, 0xf035, 0xf036, 0xf037, 0xf038, 0xf039, 0xf030, + 0xf201, 0xf01b, 0xf07f, 0xf009, 0xf020, 0xf02d, 0xf03d, 0xf05b, + 0xf05d, 0xf05c, 0xf200, 0xf03b, 0xf027, 0xf060, 0xf02c, 0xf02e, + 0xf02f, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104, 0xf105, + 0xf106, 0xf107, 0xf108, 0xf109, 0xf10a, 0xf10b, 0xf200, 0xf209, + 0xf11d, 0xf115, 0xf114, 0xf118, 0xf116, 0xf117, 0xf119, 0xf602, + 0xf601, 0xf600, 0xf603, 0xf208, 0xf30d, 0xf30c, 0xf30b, 0xf30a, + 0xf30e, 0xf301, 0xf302, 0xf303, 0xf304, 0xf305, 0xf306, 0xf307, + 0xf308, 0xf309, 0xf300, 0xf310, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf702, + 0xf700, 0xf701, 0xf703, 0xf707, 0xf705, 0xf701, 0xf701, 0xf200, +}; + +static u_short shift_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf200, 0xf200, 0xfb41, 0xfb42, 0xfb43, 0xfb44, + 0xfb45, 0xfb46, 0xfb47, 0xfb48, 0xfb49, 0xfb4a, 0xfb4b, 0xfb4c, + 0xfb4d, 0xfb4e, 0xfb4f, 0xfb50, 0xfb51, 0xfb52, 0xfb53, 0xfb54, + 0xfb55, 0xfb56, 0xfb57, 0xfb58, 0xfb59, 0xfb5a, 0xf021, 0xf040, + 0xf023, 0xf024, 0xf025, 0xf05e, 0xf026, 0xf02a, 0xf028, 0xf029, + 0xf201, 0xf01b, 0xf07f, 0xf009, 0xf020, 0xf05f, 0xf02b, 0xf07b, + 0xf07d, 0xf07c, 0xf200, 0xf03a, 0xf022, 0xf07e, 0xf03c, 0xf03e, + 0xf03f, 0xf207, 0xf10a, 0xf10b, 0xf10c, 0xf10d, 0xf10e, 0xf10f, + 0xf110, 0xf111, 0xf112, 0xf113, 0xf10a, 0xf10b, 0xf200, 0xf203, + 0xf11d, 0xf115, 0xf114, 0xf20b, 0xf116, 0xf117, 0xf20a, 0xf602, + 0xf601, 0xf600, 0xf603, 0xf208, 0xf30d, 0xf30c, 0xf30b, 0xf30a, + 0xf30e, 0xf301, 0xf302, 0xf303, 0xf304, 0xf305, 0xf306, 0xf307, + 0xf308, 0xf309, 0xf300, 0xf310, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf702, + 0xf700, 0xf701, 0xf703, 0xf707, 0xf705, 0xf701, 0xf701, 0xf200, +}; + +static u_short altgr_map[NR_KEYS] = { + 0xf914, 0xf200, 0xf917, 0xf919, 0xfb61, 0xfb62, 0xfb63, 0xfb64, + 0xfb65, 0xfb66, 0xfb67, 0xfb68, 0xfb69, 0xfb6a, 0xfb6b, 0xfb6c, + 0xfb6d, 0xfb6e, 0xfb6f, 0xfb70, 0xfb71, 0xfb72, 0xfb73, 0xfb74, + 0xfb75, 0xfb76, 0xfb77, 0xfb78, 0xfb79, 0xfb7a, 0xf200, 0xf040, + 0xf200, 0xf024, 0xf200, 0xf200, 0xf07b, 0xf05b, 0xf05d, 0xf07d, + 0xf201, 0xf200, 0xf200, 0xf200, 0xf200, 0xf05c, 0xf200, 0xf200, + 0xf07e, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf207, 0xf50c, 0xf50d, 0xf50e, 0xf50f, 0xf510, 0xf511, + 0xf512, 0xf513, 0xf514, 0xf515, 0xf516, 0xf517, 0xf200, 0xf202, + 0xf11d, 0xf115, 0xf114, 0xf118, 0xf116, 0xf117, 0xf119, 0xf602, + 0xf601, 0xf600, 0xf603, 0xf208, 0xf30d, 0xf30c, 0xf30b, 0xf30a, + 0xf30e, 0xf90b, 0xf90c, 0xf90d, 0xf90e, 0xf90f, 0xf910, 0xf911, + 0xf912, 0xf913, 0xf90a, 0xf310, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf702, + 0xf700, 0xf701, 0xf703, 0xf707, 0xf705, 0xf701, 0xf701, 0xf200, +}; + +static u_short ctrl_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf200, 0xf200, 0xf001, 0xf002, 0xf003, 0xf004, + 0xf005, 0xf006, 0xf007, 0xf008, 0xf009, 0xf00a, 0xf00b, 0xf00c, + 0xf00d, 0xf00e, 0xf00f, 0xf010, 0xf011, 0xf012, 0xf013, 0xf014, + 0xf015, 0xf016, 0xf017, 0xf018, 0xf019, 0xf01a, 0xf200, 0xf000, + 0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f, 0xf07f, 0xf200, 0xf200, + 0xf201, 0xf200, 0xf008, 0xf200, 0xf000, 0xf01f, 0xf200, 0xf01b, + 0xf01d, 0xf01c, 0xf200, 0xf200, 0xf007, 0xf000, 0xf200, 0xf20e, + 0xf07f, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104, 0xf105, + 0xf106, 0xf107, 0xf108, 0xf109, 0xf10a, 0xf10b, 0xf200, 0xf204, + 0xf11d, 0xf115, 0xf114, 0xf118, 0xf116, 0xf117, 0xf119, 0xf602, + 0xf601, 0xf600, 0xf603, 0xf208, 0xf30d, 0xf30c, 0xf30b, 0xf30a, + 0xf30e, 0xf301, 0xf302, 0xf303, 0xf304, 0xf305, 0xf306, 0xf307, + 0xf308, 0xf309, 0xf300, 0xf310, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf702, + 0xf700, 0xf701, 0xf703, 0xf707, 0xf705, 0xf701, 0xf701, 0xf200, +}; + +static u_short shift_ctrl_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf200, 0xf200, 0xf001, 0xf002, 0xf003, 0xf004, + 0xf005, 0xf006, 0xf007, 0xf008, 0xf009, 0xf00a, 0xf00b, 0xf00c, + 0xf00d, 0xf00e, 0xf00f, 0xf010, 0xf011, 0xf012, 0xf013, 0xf014, + 0xf015, 0xf016, 0xf017, 0xf018, 0xf019, 0xf01a, 0xf200, 0xf000, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf201, 0xf200, 0xf200, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf207, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf11d, 0xf115, 0xf114, 0xf118, 0xf116, 0xf117, 0xf119, 0xf602, + 0xf601, 0xf600, 0xf603, 0xf208, 0xf30d, 0xf30c, 0xf30b, 0xf30a, + 0xf30e, 0xf301, 0xf302, 0xf303, 0xf304, 0xf305, 0xf306, 0xf307, + 0xf308, 0xf309, 0xf300, 0xf310, 0xf200, 0xf200, 0xf20c, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf702, + 0xf700, 0xf701, 0xf703, 0xf707, 0xf705, 0xf701, 0xf701, 0xf200, +}; + +static u_short alt_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf200, 0xf200, 0xf861, 0xf862, 0xf863, 0xf864, + 0xf865, 0xf866, 0xf867, 0xf868, 0xf869, 0xf86a, 0xf86b, 0xf86c, + 0xf86d, 0xf86e, 0xf86f, 0xf870, 0xf871, 0xf872, 0xf873, 0xf874, + 0xf875, 0xf876, 0xf877, 0xf878, 0xf879, 0xf87a, 0xf831, 0xf832, + 0xf833, 0xf834, 0xf835, 0xf836, 0xf837, 0xf838, 0xf839, 0xf830, + 0xf80d, 0xf81b, 0xf87f, 0xf809, 0xf820, 0xf82d, 0xf83d, 0xf85b, + 0xf85d, 0xf85c, 0xf200, 0xf83b, 0xf827, 0xf860, 0xf82c, 0xf82e, + 0xf82f, 0xf207, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504, 0xf505, + 0xf506, 0xf507, 0xf508, 0xf509, 0xf50a, 0xf50b, 0xf200, 0xf209, + 0xf11d, 0xf115, 0xf114, 0xf118, 0xf116, 0xf117, 0xf119, 0xf211, + 0xf210, 0xf600, 0xf603, 0xf208, 0xf30d, 0xf30c, 0xf30b, 0xf30a, + 0xf30e, 0xf901, 0xf902, 0xf903, 0xf904, 0xf905, 0xf906, 0xf907, + 0xf908, 0xf909, 0xf900, 0xf310, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf702, + 0xf700, 0xf701, 0xf703, 0xf707, 0xf705, 0xf701, 0xf701, 0xf200, +}; + +static u_short shift_alt_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf200, 0xf200, 0xf841, 0xf842, 0xf843, 0xf844, + 0xf845, 0xf846, 0xf847, 0xf848, 0xf849, 0xf84a, 0xf84b, 0xf84c, + 0xf84d, 0xf84e, 0xf84f, 0xf850, 0xf851, 0xf852, 0xf853, 0xf854, + 0xf855, 0xf856, 0xf857, 0xf858, 0xf859, 0xf85a, 0xf821, 0xf840, + 0xf823, 0xf824, 0xf825, 0xf85e, 0xf826, 0xf82a, 0xf828, 0xf829, + 0xf201, 0xf200, 0xf200, 0xf200, 0xf200, 0xf85f, 0xf200, 0xf87b, + 0xf87d, 0xf87c, 0xf200, 0xf200, 0xf200, 0xf200, 0xf83c, 0xf83e, + 0xf200, 0xf207, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf11d, 0xf115, 0xf114, 0xf118, 0xf116, 0xf117, 0xf119, 0xf602, + 0xf601, 0xf600, 0xf603, 0xf208, 0xf30d, 0xf30c, 0xf30b, 0xf30a, + 0xf30e, 0xf301, 0xf302, 0xf303, 0xf304, 0xf305, 0xf306, 0xf307, + 0xf308, 0xf309, 0xf300, 0xf310, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf702, + 0xf700, 0xf701, 0xf703, 0xf707, 0xf705, 0xf701, 0xf701, 0xf200, +}; + +static u_short ctrl_alt_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf200, 0xf200, 0xf801, 0xf802, 0xf803, 0xf804, + 0xf805, 0xf806, 0xf807, 0xf808, 0xf809, 0xf80a, 0xf80b, 0xf80c, + 0xf80d, 0xf80e, 0xf80f, 0xf810, 0xf811, 0xf812, 0xf813, 0xf814, + 0xf815, 0xf816, 0xf817, 0xf818, 0xf819, 0xf81a, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf201, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf207, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504, 0xf505, + 0xf506, 0xf507, 0xf508, 0xf509, 0xf50a, 0xf50b, 0xf200, 0xf200, + 0xf11d, 0xf115, 0xf114, 0xf118, 0xf116, 0xf117, 0xf119, 0xf602, + 0xf601, 0xf600, 0xf603, 0xf208, 0xf30d, 0xf30c, 0xf30b, 0xf30a, + 0xf30e, 0xf301, 0xf302, 0xf303, 0xf304, 0xf305, 0xf306, 0xf307, + 0xf308, 0xf309, 0xf300, 0xf310, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf702, + 0xf700, 0xf701, 0xf703, 0xf707, 0xf705, 0xf701, 0xf701, 0xf200, +}; + +ushort *usb_key_maps[MAX_NR_KEYMAPS] = { + plain_map, shift_map, altgr_map, 0, + ctrl_map, shift_ctrl_map, 0, 0, + alt_map, shift_alt_map, 0, 0, + ctrl_alt_map, 0 +}; + diff -Naur linux.225/drivers/uusbd/hidbp/keymap.map linux.225.visws/drivers/uusbd/hidbp/keymap.map --- linux.225/drivers/uusbd/hidbp/keymap.map Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/hidbp/keymap.map Tue Dec 15 16:22:45 1998 @@ -0,0 +1,243 @@ +# Kernel keymap for keyboards. This uses 7 modifier combinations. +keymaps 0-2,4-5,8,9,12 +# We use the Command (pretzel) key as Alt, and the Option key as AltGr. +# +keycode 0x04 = a + altgr keycode 0x00 = Hex_A +keycode 0x05 = b + altgr keycode 0x0b = Hex_B +keycode 0x06 = c + altgr keycode 0x08 = Hex_C +keycode 0x07 = d + altgr keycode 0x02 = Hex_D +keycode 0x08 = e + altgr keycode 0x0e = Hex_E +keycode 0x09 = f + altgr keycode 0x03 = Hex_F +keycode 0x0a = g +keycode 0x0b = h +keycode 0x0c = i +keycode 0x0d = j +keycode 0x0e = k +keycode 0x0f = l +keycode 0x10 = m +keycode 0x11 = n +keycode 0x12 = o +keycode 0x13 = p +keycode 0x14 = q +keycode 0x15 = r +keycode 0x16 = s +keycode 0x17 = t +keycode 0x18 = u +keycode 0x19 = v +keycode 0x1a = w +keycode 0x1b = x +keycode 0x1c = y +keycode 0x1d = z +keycode 0x1e = one exclam + alt keycode 0x1e = Meta_one + alt shift keycode 0x1e = Meta_exclam +keycode 0x1f = two at at + control keycode 0x1f = nul + shift control keycode 0x1f = nul + alt keycode 0x1f = Meta_two + alt shift keycode 0x1f = Meta_at +keycode 0x20 = three numbersign + control keycode 0x20 = Escape + alt keycode 0x20 = Meta_three + alt shift keycode 0x20 = Meta_numbersign +keycode 0x21 = four dollar dollar + control keycode 0x21 = Control_backslash + alt keycode 0x21 = Meta_four + alt shift keycode 0x21 = Meta_dollar +keycode 0x22 = five percent + control keycode 0x22 = Control_bracketright + alt keycode 0x22 = Meta_five + alt shift keycode 0x22 = Meta_percent +keycode 0x23 = six asciicircum + control keycode 0x23 = Control_asciicircum + alt keycode 0x23 = Meta_six + alt shift keycode 0x23 = Meta_asciicircum +keycode 0x24 = seven ampersand braceleft + control keycode 0x24 = Control_underscore + alt keycode 0x24 = Meta_seven + alt shift keycode 0x24 = Meta_ampersand +keycode 0x25 = eight asterisk bracketleft + control keycode 0x25 = Delete + alt keycode 0x25 = Meta_eight + alt shift keycode 0x25 = Meta_asterisk +keycode 0x26 = nine parenleft bracketright + alt keycode 0x26 = Meta_nine + alt shift keycode 0x26 = Meta_parenleft +keycode 0x27 = zero parenright braceright + alt keycode 0x27 = Meta_zero + alt shift keycode 0x27 = Meta_parenright +keycode 0x28 = Return + alt keycode 0x28 = Meta_Control_m +keycode 0x29 = Escape Escape + alt keycode 0x29 = Meta_Escape +keycode 0x2a = Delete Delete + control keycode 0x2a = BackSpace + alt keycode 0x2a = Meta_Delete +keycode 0x2b = Tab Tab + alt keycode 0x2b = Meta_Tab +keycode 0x2c = space space + control keycode 0x2c = nul + alt keycode 0x2c = Meta_space +keycode 0x2d = minus underscore backslash + control keycode 0x2d = Control_underscore + shift control keycode 0x2d = Control_underscore + alt keycode 0x2d = Meta_minus + alt shift keycode 0x2d = Meta_underscore +keycode 0x2e = equal plus + alt keycode 0x2e = Meta_equal +keycode 0x2f = bracketleft braceleft + control keycode 0x2f = Escape + alt keycode 0x2f = Meta_bracketleft + alt shift keycode 0x2f = Meta_braceleft +keycode 0x30 = bracketright braceright asciitilde + control keycode 0x30 = Control_bracketright + alt keycode 0x30 = Meta_bracketright + alt shift keycode 0x30 = Meta_braceright +keycode 0x31 = backslash bar + control keycode 0x31 = Control_backslash + alt keycode 0x31 = Meta_backslash + alt shift keycode 0x31 = Meta_bar +keycode 0x32 = +keycode 0x33 = semicolon colon + alt keycode 0x33 = Meta_semicolon +keycode 0x34 = apostrophe quotedbl + control keycode 0x34 = Control_g + alt keycode 0x34 = Meta_apostrophe +keycode 0x35 = grave asciitilde + control keycode 0x35 = nul + alt keycode 0x35 = Meta_grave +keycode 0x36 = comma less + alt keycode 0x36 = Meta_comma + alt shift keycode 0x36 = Meta_less +keycode 0x37 = period greater + control keycode 0x37 = Compose + alt keycode 0x37 = Meta_period + alt shift keycode 0x37 = Meta_greater +keycode 0x38 = slash question + control keycode 0x38 = Delete + alt keycode 0x38 = Meta_slash +keycode 0x39 = Caps_Lock +keycode 0x3a = F1 F11 Console_13 + control keycode 0x3a = F1 + alt keycode 0x3a = Console_1 + control alt keycode 0x3a = Console_1 +keycode 0x3b = F2 F12 Console_14 + control keycode 0x3b = F2 + alt keycode 0x3b = Console_2 + control alt keycode 0x3b = Console_2 +keycode 0x3c = F3 F13 Console_15 + control keycode 0x3c = F3 + alt keycode 0x3c = Console_3 + control alt keycode 0x3c = Console_3 +keycode 0x3d = F4 F14 Console_16 + control keycode 0x3d = F4 + alt keycode 0x3d = Console_4 + control alt keycode 0x3d = Console_4 +keycode 0x3e = F5 F15 Console_17 + control keycode 0x3e = F5 + alt keycode 0x3e = Console_5 + control alt keycode 0x3e = Console_5 +keycode 0x3f = F6 F16 Console_18 + control keycode 0x3f = F6 + alt keycode 0x3f = Console_6 + control alt keycode 0x3f = Console_6 +keycode 0x40 = F7 F17 Console_19 + control keycode 0x40 = F7 + alt keycode 0x40 = Console_7 + control alt keycode 0x40 = Console_7 +keycode 0x41 = F8 F18 Console_20 + control keycode 0x41 = F8 + alt keycode 0x41 = Console_8 + control alt keycode 0x41 = Console_8 +keycode 0x42 = F9 F19 Console_21 + control keycode 0x42 = F9 + alt keycode 0x42 = Console_9 + control alt keycode 0x42 = Console_9 +keycode 0x43 = F10 F20 Console_22 + control keycode 0x43 = F10 + alt keycode 0x43 = Console_10 + control alt keycode 0x43 = Console_10 +keycode 0x44 = F11 F11 Console_23 + control keycode 0x44 = F11 + alt keycode 0x44 = Console_11 + control alt keycode 0x44 = Console_11 +keycode 0x45 = F12 F12 Console_24 + control keycode 0x45 = F12 + alt keycode 0x45 = Console_12 + control alt keycode 0x45 = Console_12 +keycode 0x46 = +keycode 0x47 = Scroll_Lock Show_Memory Show_Registers + control keycode 0x47 = Show_State + alt keycode 0x47 = Scroll_Lock +keycode 0x48 = Pause +keycode 0x49 = Insert +keycode 0x4a = Home +keycode 0x4b = Prior + shift keycode 0x4b = Scroll_Backward +keycode 0x4c = Remove +keycode 0x4d = End +keycode 0x4e = Next + shift keycode 0x4e = Scroll_Forward +keycode 0x4f = Right + alt keycode 0x4f = Incr_Console +keycode 0x50 = Left + alt keycode 0x50 = Decr_Console +keycode 0x51 = Down +keycode 0x52 = Up +keycode 0x53 = Num_Lock +# shift keycode 0x53 = Bare_Num_Lock +keycode 0x54 = KP_Divide +keycode 0x55 = KP_Multiply +keycode 0x56 = KP_Subtract +keycode 0x57 = KP_Add +keycode 0x58 = KP_Enter +keycode 0x59 = KP_1 + alt keycode 0x59 = Ascii_1 + altgr keycode 0x59 = Hex_1 +keycode 0x5a = KP_2 + alt keycode 0x5a = Ascii_2 + altgr keycode 0x5a = Hex_2 +keycode 0x5b = KP_3 + alt keycode 0x5b = Ascii_3 + altgr keycode 0x5b = Hex_3 +keycode 0x5c = KP_4 + alt keycode 0x5c = Ascii_4 + altgr keycode 0x5c = Hex_4 +keycode 0x5d = KP_5 + alt keycode 0x5d = Ascii_5 + altgr keycode 0x5d = Hex_5 +keycode 0x5e = KP_6 + alt keycode 0x5e = Ascii_6 + altgr keycode 0x5e = Hex_6 +keycode 0x5f = KP_7 + alt keycode 0x5f = Ascii_7 + altgr keycode 0x5f = Hex_7 +keycode 0x60 = KP_8 + alt keycode 0x60 = Ascii_8 + altgr keycode 0x60 = Hex_8 +keycode 0x61 = KP_9 + alt keycode 0x61 = Ascii_9 + altgr keycode 0x61 = Hex_9 +keycode 0x62 = KP_0 + alt keycode 0x62 = Ascii_0 + altgr keycode 0x62 = Hex_0 +keycode 0x63 = KP_Period +keycode 0x64 = +keycode 0x65 = +# keycode 0x66 = Power + control shift keycode 0x66 = Boot +# keycode 0x67 = KP_Equals +keycode 0x77 = Control +keycode 0x78 = Shift +keycode 0x79 = AltGr +keycode 0x7a = Alt +keycode 0x7b = Control_R +keycode 0x7c = Shift_R +keycode 0x7d = AltGr_R +keycode 0x7e = Alt_R diff -Naur linux.225/drivers/uusbd/hidbp/mouse.c linux.225.visws/drivers/uusbd/hidbp/mouse.c --- linux.225/drivers/uusbd/hidbp/mouse.c Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/hidbp/mouse.c Sun Apr 4 17:38:46 1999 @@ -0,0 +1,713 @@ + +/* USB Human Interface Devices Driver v$Revision: 1.21 $ + * + * (C) 1997-99 by Iñaky Pérez González + * (C) 1998-99 by Paul Mackerras + * + * Distributed under the terms of the GNU Public License Version 2 + * See files COPYRIGHT and COPYING at the root distribution directory + * + * $Id: mouse.c,v 1.21 1999/04/05 00:38:46 inaky Exp $ + * + * Changelog at the bottom + * + * USB HID Boot Protocol + * --------------------- + * + * This is an smaller driver then HID, but is capable of reading from + * keyboards and mice which understand the boot protocol. This makes + * it nice to have it compiled for boot disks and that stuff with size + * constraints. + */ + +#define __NO_VERSION__ +#include +#include +#include /* locks */ +#include + +#include +#include + +#define GDLF_IDENT "USB-HIDBP" +#define GDLF_LOCAL /* Define if want local settings */ +#define GDLF_DEF_LOGLEVEL 9 +#define GDLF_ASSERTIONS /* want assertions (#undef if not) */ +#undef GDLF_FNTRACE /* want function traces */ +#define GDLF_LOCATIONS /* want locations in log messages */ +#include + +#include + +#if defined (CONFIG_PMAC) && defined (CONFIG_USB_HIDBP_MSE) +#define EMULATE_BUTTONS +#endif + +struct file_operations bmse_fops = +{ + NULL, /* llseek */ + bmse_read, /* read */ + NULL, /* write */ + NULL, /* readdir */ + bmse_poll, /* select */ + bmse_ioctl, /* ioctl */ + NULL, /* mmap */ + hidbp_open, /* open */ + NULL, /* flush */ + hidbp_close, /* release */ + NULL, /* fsync */ + bmse_fasync, /* fasync */ + NULL, /* check_media_change */ + NULL /* revalidate */ +}; + + /* + * Initialize the private data for a USB mouse. + * The area has already been zeroed. + */ + +void bmse_init (ts_hidbp *bmse) +{ + ts_hidbp_mouse *bm = (ts_hidbp_mouse*)bmse->data; + + bm->data.buttons = 0x87; /* all buttons up */ + bm->wait = NULL; + bm->fasyncp = NULL; +} + + + /* Emulate second and third button on iMac + * + * Hack for iMac: a keyboard key which is used for an emulated + * mouse button has been pressed or released. Generate a button + * up/down event on the most recent mouse detected. + * + * Parameters: + * + * type descr + * + * Returns: + * + * type descr + */ + +#ifdef EMULATE_BUTTONS +void bmse_emulate_button (int button, int down) +{ + ts_hidbp *hidbp; + ts_hidbp_mouse *bm; + int mask; + + /* + * Search through the list of HID-BP devices looking for a + * mouse. FIXME: it would be nice to have a better way to + * match up keyboards and mice together. + */ + + for (hidbp = (ts_hidbp*) ts_slist_head (&hidbp_list); + hidbp != NULL; + hidbp = (ts_hidbp*) ts_slist_next (&hidbp->snode)) + { + if (hidbp->aset->cfel.protocol == HIDBP_PROTOCOL_MSE) + break; + } + + if (hidbp == NULL) + { + gdlf_debug ("no mouse found"); + return; + } + + /* Set or reset the bit corresponding to the emulated button. */ + + bm = (ts_hidbp_mouse *) hidbp->data; + mask = (8 >> button) & 7; + spin_lock (&bm->lock); + if (down) + { + bm->emul_buttons |= mask; + bm->data.buttons &= ~mask; + } + else + { + bm->emul_buttons &= ~mask; + bm->data.buttons |= mask; + } + bm->ready = 1; + spin_unlock (&bm->lock); + + /* Wake up any process waiting for mouse data. */ + + wake_up_interruptible (&bm->wait); + if (bm->fasyncp) + kill_fasync (bm->fasyncp, SIGIO); +} +#endif /* EMULATE_BUTTONS */ + + + /* Function called when a transaction to the mouse is finished + * + * Note this function is in charge to adapt the tr->data_size to + * match the incoming data size. HID Boot Protocol doesn't provide + * a way to know in advance which is the damn size of the data + * being sent. This is ugly, as we'll see some errors until we + * adapt the rate. What we do is to increase from 3 until doubling + * it [the max size we have] and if keeps failing, reset. + * + * I've seen this needed mostly on some Genius Kye Mice, which + * reported four bytes in BP mode. + * + * Parameters: + * + * ts_usb_tr* Transaction which finished + * + * int Flags indicating what happened + */ + +void bmse_callback (ts_usb_tr* tr, int flags) +{ + ts_hidbp *bmse; + + int errcode; + gdlf_fntrace ("bmse_callback (0x%p, 0x%x)", tr, flags); + + /* copy the data */ + + bmse = tr->private; + gdlf_aassert (bmse != NULL, return); + gdlf_aassert (&bmse->tr == tr, return); + + if (flags & USB_CB_ABORTED) /* no need to keep on */ + return; + + /* If no error, get the data and translate it */ + + bmse->errcode = errcode = + tr->errno < 0? tr->errno : tr->xfered; + if (errcode >= 0) + { + __u8 buttons; + int x, y; + __s8 *trdata = (__s8*) tr->data; + ts_hidbp_mouse *bm = (ts_hidbp_mouse*) bmse->data; + + /* + * From tr->data, generate data at bmse->data which can + * be interpreted as busmouse protocol. + * + * FIXME: should support multiple emulations. + */ + + + /* Quick hack + * + * For some reason, the Genius EasyPen reports as HID BP, + * when it doesn't follow, at all, the Boot + * Protocol. Instead of using the first three bytes to + * report as BP and the following ones to add more or even + * extended information, they just seem to use bytes: + * + * 01 X0 X1 Y0 Y1 BUTTONS 80 C3 + * + * BUTTONS:5 tip pressed + * BUTTONS:6 button pressed + * BUTTONS:7 light pen in range with tablet + * + * So we try to make it look like the original serial + * genitizer protocol and let the user land code deal with + * it. + */ + +#ifdef CONFIG_USB_HIDBP_GENIUS_EASYPEN + +#define HIDBP_GEASYPEN_X_TOP 0x0fa0 /* limits guessed pushing the pen */ +#define HIDBP_GEASYPEN_Y_TOP 0x0bc0 + + if (tr->pipe->dev->vendor == USB_VENDOR_KYE + && tr->pipe->dev->product == USB_DEVICE_KYE_EASYPEN) + { + __u8 *utrdata = (__u8*) tr->data; + + if (tr->size <= 6) + gdlf_err ("Wrong report size (%d) for Genius " + "EasyPen at device id " + "0x%08x (%d %d)\n", + tr->size, bmse->pipe.dev->id, + bmse->pipe.dev? + usb_host_addr (bmse->pipe.dev) : -1, + bmse->pipe.dev? + usb_dev_addr (bmse->pipe.dev) : -1); + + buttons = bm->data.buttons = + (utrdata[5] & 0x20? 4 : 0) + | (utrdata[5] & 0x40? 2 : 0); + bm->data.buttons = (~buttons & 0x07) | 0x80; + + x = utrdata[2] << 8 | utrdata[1]; /* X = [0:0x0fa0] */ + y = utrdata[4] << 8 | utrdata[3]; /* Y = [0:0x0bc0] */ + +#warning DEBUG: remove me (disabled) +#if 0 + usb_dump_bytes (tr->data, tr->size); + gdlf_debug ("%+03d %+03d 0x%02x\n", x, y, bm->data.buttons); +#endif + spin_lock (&bm->lock); /* absolute positioning */ + bm->data.xd = (x - bm->x0) / 3; + bm->data.yd = (y - bm->y0) / 3; + bm->x0 = x; + bm->y0 = y; + } + else +#endif /* !CONFIG_USB_HIDBP_GENIUS_EASYPEN */ + { + buttons = trdata[0]; + buttons = ((buttons & 1)? 4 : 0) /* left? */ + | ((buttons & 2)? 1 : 0) /* right? */ + | ((buttons & 4)? 2 : 0); /* middle? */ + x = trdata[1]; + y = - trdata[2]; + + spin_lock (&bm->lock); /* relative positioning */ + x += bm->data.xd; + y += bm->data.yd; + bm->data.xd = x <= -128? -128 : x >= 127? 127 : x; + bm->data.yd = y <= -128? -128 : y >= 127? 127 : y; +#ifdef EMULATE_BUTTONS + bm->data.buttons = (~buttons & ~bm->emul_buttons & 0x07) | 0x80; +#else + bm->data.buttons = (~buttons & 0x07) | 0x80; +#endif + } + + bm->ready = 1; + spin_unlock (&bm->lock); + + wake_up_interruptible (&bm->wait); + if (bm->fasyncp) + kill_fasync (bm->fasyncp, SIGIO); + + memset (tr->data, 0, tr->data_size); + bmse->errcode = tr->xfered; + usb_tr_reset (tr); + } + else while (1) /* Sheesh ... error! */ + { + /* Perhaps we are reading less bytes then coming? */ + + if (errcode == -EIO + && tr->data_size < HIDBP_BMSE_ALLOC_DATA_SIZE) + { + errcode = usb_tr_setdn (tr); + if (errcode < 0) + { + gdlf_err ("Cannot set down transaction to re-adapt " + "data buffer size on HID Boot Protocol " + "mouse at device id 0x%x " + "(%d %d): errno/usb %d %d\n", + bmse->pipe.device->id, + usb_host_addr (bmse->pipe.device), + usb_dev_addr (bmse->pipe.device), + errcode, usb_errno); + usb_device_reset_safe (bmse->pipe.device); + return; + } + + tr->data_size++; /* try one byte more */ + gdlf_debug ("Huh ... adapting data buffer size to %d\n", + tr->data_size); + tr->size = tr->data_size; + errcode = usb_tr_setup (tr); + if (errcode < 0) + { + gdlf_err ("Cannot re-set up transaction to re-adapt " + "data buffer size on HID Boot Protocol " + "mouse at device id 0x%x " + "(%d %d): errno/usb %d %d\n", + bmse->pipe.device->id, + usb_host_addr (bmse->pipe.device), + usb_dev_addr (bmse->pipe.device), + errcode, usb_errno); + usb_device_reset_safe (bmse->pipe.device); + return; + } + errcode = usb_tr_insert (tr); + if (errcode < 0) + { + gdlf_err ("Cannot re-insert transaction to re-adapt " + "data buffer size on HID Boot Protocol " + "mouse at device id 0x%x " + "(%d %d): errno/usb %d %d\n", + bmse->pipe.device->id, + usb_host_addr (bmse->pipe.device), + usb_dev_addr (bmse->pipe.device), + errcode, usb_errno); + usb_device_reset_safe (bmse->pipe.device); + return; + } + break; + } + + bmse->errcode = errcode; + bmse->errors++; + + /* Check if we are having more errors then allowed + * + * We check each HZ/3 the quantity of errors, then reset + * the counts. If it goes over the stablished quota + * ... reset. + */ + + if ((jiffies - bmse->jiffies0) > HZ / 3) + { + if ((bmse->errors * HZ / (jiffies - bmse->jiffies0) / 3) + > HIDBP_MAX_ERRS_SEC / 3) + { + gdlf_err ("Too many errors (%lu in %lu jiffies) reading " + "mouse at device (%d %d): errno/usb %d/%d; " + "resetting\n", + bmse->errors, jiffies - bmse->jiffies0, + usb_host_addr (bmse->pipe.device), + usb_dev_addr (bmse->pipe.device), + tr->errno, tr->usb_errno); + usb_device_reset_safe (bmse->pipe.device); + return; + } + bmse->jiffies0 = jiffies; + bmse->errors = 0; + } + usb_tr_reset (tr); + break; + } + + /* reschedule */ + + errcode = usb_tr_run (tr); + if (errcode < 0) + { + gdlf_err ("Error scheduling read for mouse at device (%d %d): " + "errno/usb %d/%d\n", + usb_host_addr (bmse->pipe.device), + usb_dev_addr (bmse->pipe.device), + tr->errno, tr->usb_errno); + if (errcode == -EREMOTEIO) + usb_endp_stall_clear (tr->pipe); + bmse->errcode = errcode; + } + return; +} + + + /* Read from the mouse, using the VFS interface + * + * This function is called when read() is called to a hidbp mouse + * device. + * + * Parameters: + * + * struct file* File structure + * + * char* Where to write data to. + * + * size_t Number of bytes to read. + * + * loff_t* Offset; unsupported. + * + * Returns: + * + * ssize_t Number of bytes readen. + */ + +ssize_t bmse_read (struct file* file, char* data, size_t size, + loff_t* offset) +{ + ts_hidbp *bmse; + ts_hidbp_mouse *bm; + ssize_t errcode; + ts_bus_mouse bmdata; + unsigned long flags; + int ready; + + gdlf_fntrace ("bmse_read (0x%p, 0x%p, %u, 0x%p)", + file, data, size, offset); + gdlf_aassert (file != NULL, return -EINVAL); + gdlf_aassert (data != NULL, return -EINVAL); + + if (size < sizeof (bmdata)) + return -EINVAL; + + errcode = verify_area (VERIFY_WRITE, data, size); + if (errcode) /* Check we can write */ + return errcode; + + bmse = file->private_data; /* get the private data */ + if (bmse == NULL) /* device removed? */ + return -EBADFD; + + gdlf_aassert (bmse->snode.dtor.fn == (tf_dtor)hidbp_destroy, + return -EBADFD); + + bm = (ts_hidbp_mouse *) bmse->data; + + /* Get the data from the mouse */ + + spin_lock_irqsave (&bm->lock, flags); + bmdata = bm->data; + ready = bm->ready; + if (ready) + { + bm->data.xd = bm->data.yd = 0; /* clear movement data */ + bm->ready = 0; + } + spin_unlock_irqrestore (&bm->lock, flags); + + if (!ready) + return -EAGAIN; + + /* Write it */ + + copy_to_user (data, &bmdata, sizeof (bmdata)); + if (size > sizeof (bmdata)) + clear_user (data + sizeof (bmdata), size - sizeof (bmdata)); + return size; +} + + + /* + * This procedure implements the poll (and select) call + * for a USB mouse device. + * + * Parameters: + * + * struct file* File structure + * + * poll_table* Poll table structure + * + * Returns: + * + * unsigned int ???? + */ + +unsigned int bmse_poll (struct file* file, poll_table* wait) +{ + ts_hidbp *bmse; + ts_hidbp_mouse *bm; + + gdlf_fntrace ("bmse_poll (0x%p, 0x%p)", file, wait); + + bmse = file->private_data; /* get the private data */ + if (bmse == NULL) /* device removed? */ + return -EBADFD; + gdlf_aassert (bmse->snode.dtor.fn == (tf_dtor)hidbp_destroy, + return -EBADFD); + + /* Get the mouse structure and wait until ready */ + + bm = (ts_hidbp_mouse*) bmse->data; + poll_wait (file, &bm->wait, wait); + if (bm->ready) + return POLLIN | POLLRDNORM; + return 0; +} + + + /* FIXME: Detailed desc + * + * Compliance: USB Spec 1.0 xxxx + * + * Parameters: + * + * type descr + * + * Global: + * + * type name descr + * + * Returns: + * + * type descr + * + * Global: + * + * type name descr + */ + +int bmse_fasync (int fd, struct file *filp, int on) +{ + ts_hidbp *bmse; + ts_hidbp_mouse *bm; + + gdlf_fntrace ("bmse_fasync (%d, 0x%p, %d)\n", fd, filp, on); + + bmse = filp->private_data; /* get the private data */ + if (bmse == NULL) /* device removed? */ + return -EBADFD; + gdlf_aassert (bmse->snode.dtor.fn == (tf_dtor)hidbp_destroy, + return -EBADFD); + + bm = (ts_hidbp_mouse*) bmse->data; + return fasync_helper (fd, filp, on, &bm->fasyncp); +} + + + /* FIXME: Detailed desc + * + * Compliance: USB Spec 1.0 xxxx + * + * Parameters: + * + * type descr + * + * Global: + * + * type name descr + * + * Returns: + * + * type descr + * + * Global: + * + * type name descr + */ + +int bmse_ioctl (struct inode* inode, struct file* file, + unsigned int cmd, unsigned long arg) +{ + ts_hidbp* bmse; + + gdlf_fntrace ("bmse_ioctl (0x%p, 0x%p, %u, %lu)", + inode, file, cmd, arg); + gdlf_aassert (inode != NULL, return -EINVAL); + gdlf_aassert (file != NULL, return -EINVAL); + + bmse = file->private_data; /* get the private data */ + if (bmse == NULL) /* device removed? */ + return -EBADFD; + +#warning FIXME: bmse ioctls? + return 0; +} + + + /* Make kernel forget a mouse + * + * This means telling everybody waiting for mouse input. + * + * Parameters: + * + * type descr + * + * Returns: + * + * type descr + */ + +void bmse_destroy (ts_hidbp *hidbp) +{ + ts_hidbp_mouse *bm; + + gdlf_fntrace ("bmse_shutdown (0x%p)", hidbp); + gdlf_aassert (hidbp != NULL, return); + + + bm = (ts_hidbp_mouse*) hidbp->data; + gdlf_aassert (bm != NULL, return); + + wake_up_interruptible (&bm->wait); + if (bm->fasyncp) + kill_fasync (bm->fasyncp, SIGIO); +} + +/* Log: + * + * $Log: mouse.c,v $ + * Revision 1.21 1999/04/05 00:38:46 inaky + * Renamed khubdd to kusbdd, moved to new usb_pipe_*() semantics, trimmed + * logs. + * + * Revision 1.20 1999/04/01 16:44:51 inaky + * Changed Genius Tablet to Genius EasyPen ... + * + * Revision 1.19 1999/04/01 00:16:20 inaky + * Added Genius Tablet hacky support + * + * Revision 1.18 1999/03/31 23:17:32 inaky + * Primary version with very limited and broken support for the Genius + * Tablet. + * + * Revision 1.17 1999/03/09 22:55:18 inaky + * Add destructor for mice. + * + * Revision 1.16 1999/02/20 22:54:59 inaky + * Fixed a motherfucking brace I don't know why got in there. + * + * Revision 1.15 1999/02/09 02:40:13 inaky + * Fixed to make the callback reset only if error or ok, and not when + * resizing, as the tr is already reset. + * + * Revision 1.14 1999/02/08 15:37:09 inaky + * Don't do anything at the callback when aborted. Otherwise, the + * transaction is again re-scheduled and the cleaning up process gets + * confused. + * + * Revision 1.13 1999/02/03 22:35:22 inaky + * *** empty log message *** + * + * Revision 1.12 1999/01/31 11:46:37 inaky + * Added docs, paranoid assertions, and a way to automatically adapt to + * the number of bytes coming trough the wire. + * + * Revision 1.11 1998/12/25 22:55:10 inaky + * Mixed changes by Paul MacKerras, mostly documentation and a fix for + * buttons. + * + * Revision 1.10 1998/12/16 00:23:18 inaky + * Added poll system call. It still chokes on unplug. Gotta check it. + * All changes by Paul. + * + * Revision 1.9 1998/12/12 02:43:09 inaky + * Added comments and made a primitive system for detecting and resetting + * defective mice. + * + * Revision 1.8 1998/11/26 21:58:25 inaky + * Renamed all the ts_usb_open stuff and friends to use _pipe_. + * + * Revision 1.7 1998/11/17 13:36:57 inaky + * Made the mouse reading doyuble buffered, to evitate X slowing down. + * + * Revision 1.6 1998/11/17 09:51:30 inaky + * Fixed the protocol to imitate bus mouse and added more options to the + * test utilities to be able not to print anything not wait [to do load + * tests]. + * + * Revision 1.5 1998/11/14 17:18:59 inaky + * Moved the include files to uusbd/include/uusbd, to ease integration + * into the Linux kernel. + * + * Revision 1.4 1998/10/14 21:47:34 inaky + * Fixed _blatant_ mistake. + * + * Revision 1.3 1998/09/24 16:05:58 inaky + * Fixed error handling on read, added verifications and checks. + * + * Revision 1.2 1998/09/14 02:05:18 inaky + * Removed unneeded specific routines. Made the tr be inserted at open + * time and only ran at read time. + * + * Revision 1.1 1998/09/11 00:50:59 inaky + * Moved the HID Boot Protocol to a single driver, so it can be isolated + * more easily. It supports keyboards and mice, settable at compile time. + * + * Revision 1.1 1998/08/30 13:55:46 inaky + * Added boot protocol support and a simple test program. + * + * Revision 1.1 1998/08/28 23:53:14 inaky + * New driver + * + * Revision 1.3 1998/08/28 00:14:22 inaky + * New driver ... + * + */ + + + diff -Naur linux.225/drivers/uusbd/hidd/Makefile linux.225.visws/drivers/uusbd/hidd/Makefile --- linux.225/drivers/uusbd/hidd/Makefile Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/hidd/Makefile Sat Nov 14 09:19:29 1998 @@ -0,0 +1,47 @@ +# +# Makefile for the Universal USB Human Interface Devices Driver, Linux flavour +# ---------------------------------------------------------------------------- +# +# Distributed under the terms of the GNU Public License Version 2 +# See files COPYRIGHT and COPYING at the root distribution directory + +SUB_DIRS := +MOD_IN_SUB_DIRS := $(SUB_DIRS) +ALL_SUB_DIRS := $(SUB_DIRS) + +HIDD_OBJS := cfg.o generic.o hkeep.o driver.o +HIDD_XOBJS := #symtab.o +HIDD_TARGET := usb-hidd.o + +# Libraries +L_OBJS := +LX_OBJS := +# L_TARGET (just one) will be the archive of all the L_OBJS and LX_OBJS +L_TARGET := + +# Modules +MIX_OBJS := +MI_OBJS := +# Made by modules. These ones get symlinked at $(TOPDIR)/modules and +# added to the list of modules +M_OBJS := $(HIDD_TARGET) dummy_module + +# Objects +OX_OBJS := $(HIDD_XOBJS) +O_OBJS := $(HIDD_OBJS) +# O_TARGET (just one) will be made by compiling+linking OX_OBJS and O_OBJS +O_TARGET := $(HIDD_TARGET) + +include ../Makefile.inc +ifdef NOT_IN_LINUX_KERNEL +export EXTRA_CFLAGS += -I../include +endif + +include $(TOPDIR)/Rules.make +include ../Makefile-rules.inc + +.PHONY: dummy_module +dummy_module: +ifeq ($(CONFIG_USB_HIDD),m) + for v in $(M_OBJS); do echo `pwd`/$$v; done >> $(MODULES_FILE) +endif diff -Naur linux.225/drivers/uusbd/hidd/README linux.225.visws/drivers/uusbd/hidd/README --- linux.225/drivers/uusbd/hidd/README Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/hidd/README Fri Aug 28 16:53:14 1998 @@ -0,0 +1,7 @@ + + The UUSBD Human Interface Devices Driver (hidd/usb-hidd.o) + + This is the driver for the USB devices which comply with the +USB HID. It's currently embrionary and non-operative. + + Iñaky diff -Naur linux.225/drivers/uusbd/hidd/cfg.c linux.225.visws/drivers/uusbd/hidd/cfg.c --- linux.225/drivers/uusbd/hidd/cfg.c Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/hidd/cfg.c Sun Apr 4 17:39:36 1999 @@ -0,0 +1,764 @@ + +/* USB Human Interface Devices Driver v$Revision: 1.9 $ + * + * (C) 1997-99 by Iñaky Pérez González + * + * Distributed under the terms of the GNU Public License Version 2 + * See files COPYRIGHT and COPYING at the root distribution directory + * + * $Id: cfg.c,v 1.9 1999/04/05 00:39:36 inaky Exp $ + * + * Changelog at the bottom + * + * USB Human Interface Devices - Configuration + * ------------------------------------------- + * + * This takes care of initially configuring HID devices. + * + */ + +#include + +#define GDLF_IDENT "USB-HIDD" +#define GDLF_LOCAL /* Define if want local settings */ +#define GDLF_DEF_LOGLEVEL 9 +#define GDLF_ASSERTIONS /* want assertions (#undef if not) */ +#define GDLF_FNTRACE /* want function traces */ +#define GDLF_LOCATIONS /* want locations in log messages */ +#include + +#include + + + /* Fill in all the physical descriptors related information + * + * We start by seeking for physical descriptor set 0. If found, + * we take it's info [how many sets are and how many descriptors + * do they have]. + * + * Then we allocate ts_hidd_phys, it's ts_hidd_phys_set(s) and + * each set's ts_hidd_phys_descr(s). + * + * Fill them in, allocate space to get one full descriptor set; + * get each one and fill it. If anyone fails, keep the data clear + * and continue; free the space used to get the descriptor sets. + * + * Parameters: + * + * type descr + * + * Returns: + * + * type descr + */ + +int hidd_config_physical (ts_hidd* hidd, + ts_hidd_descr_head* phead, + size_t heads) +{ + struct + { + __u8 number; + __u8 length; + } descr_set_0; /* Struct for storing physical descriptor 0 */ + + size_t cnt; + size_t length; /* phys descr set 0 length */ + ssize_t errcode; + ts_usb_request req; + __u8 *set; /* place to store the sets */ + ts_hidd_phys *phys; /* phisycal descriptor structure */ + + gdlf_fntrace ("hidd_config_physical (0x%p, 0x%p, %u)", + hidd, phead, heads); + gdlf_aassert (hidd != NULL, return -EINVAL); + gdlf_aassert (phead != NULL, return -EINVAL); + gdlf_aassert (heads != 0, return -EINVAL); + + /* we walk all ifaces just to be sure, right? */ + + for (length = 0, cnt = 0; cnt < heads; cnt++) + if (phead[cnt].type == e_hidd_descr_physical) + { + if (length != 0) + gdlf_err ("Huh? got more then one physical " + "descriptor set 0 on interface %d of " + "device id 0x%08x (%d %d)\n", + hidd->iface->addr, hidd->pipe.device->id, + usb_host_addr (hidd->pipe.device), + usb_dev_addr (hidd->pipe.device)); + else + { + length = phead[cnt].length; + gdlf_debug ("Found physical descriptor at head index " + "%d; length %u\n", cnt, length); + } + } + if (length == 0) /* no physicals? ... */ + { + gdlf_notice ("No physical descriptors on interface %d of " + "device id 0x%08x (%d %d)\n", + hidd->iface->addr, hidd->pipe.device->id, + usb_host_addr (hidd->pipe.device), + usb_dev_addr (hidd->pipe.device)); + return 0; /* ... so, away with it, let's leave */ + } + + /* let's get descriptor 0 */ + + req.bmreqtype = 0x81; + req.request = e_usb_req_get_descriptor; + req.value = e_hidd_descr_physical << 8; /* & 0xf == 0 => set 0 */ + req.index = hidd->iface->addr; + req.length = length; + + errcode = usb_request_data (hidd->pipe.device, &req, + &descr_set_0, + "get HID physical descriptor set 0"); + if (errcode < 0) + { + gdlf_err ("Error requesting physical descriptor set zero on " + "interface %d of device id 0x%08x (%d %d): " + "errno/usb %d/%d\n", errcode, usb_errno, + hidd->iface->addr, hidd->pipe.device->id, + usb_host_addr (hidd->pipe.device), + usb_dev_addr (hidd->pipe.device)); + return errcode; + } + else if (errcode != sizeof (descr_set_0)) + { + gdlf_err ("Size mismatch (requested %d bytes, read %d) when " + "requesting physical descriptor set zero on " + "interface %d of device id 0x%08x (%d %d)\n", + sizeof (descr_set_0), errcode, + hidd->iface->addr, hidd->pipe.device->id, + usb_host_addr (hidd->pipe.device), + usb_dev_addr (hidd->pipe.device)); + return -EPIPE; + } + + /* got it ... let's allocate everything */ + + phys = usb_kmalloc (sizeof (ts_hidd_phys), GFP_KERNEL); + if (phys == NULL) + { + gdlf_err ("Cannot allocate memory for a physical " + "descriptor structure on " + "interface %d of device id 0x%08x (%d %d)\n", + hidd->iface->addr, hidd->pipe.device->id, + usb_host_addr (hidd->pipe.device), + usb_dev_addr (hidd->pipe.device)); + return -ENOMEM; + } + ts_hidd_phys_clean (phys); + phys->descrs = (descr_set_0.length - 1) + / sizeof (ts_hidd_phys_descr); + phys->sets = descr_set_0.number; + phys->set = usb_kmalloc (phys->sets * sizeof (ts_hidd_phys_set), + GFP_KERNEL); + ts_hidd_phys_set_a_clean (phys->set, phys->sets); + if (phys->set == NULL) + { + gdlf_err ("Cannot allocate memory for the physical " + "descriptor sets array on " + "interface %d of device id 0x%08x (%d %d)\n", + hidd->iface->addr, hidd->pipe.device->id, + usb_host_addr (hidd->pipe.device), + usb_dev_addr (hidd->pipe.device)); + usb_kfree (phys); + return -ENOMEM; + } + + /* place for physical descriptor sets */ + + set = usb_kmalloc (descr_set_0.length, GFP_KERNEL); + if (set == NULL) + { + gdlf_err ("Cannot allocate memory for physical " + "descriptor set data on " + "interface %d of device id 0x%08x (%d %d)\n", + hidd->iface->addr, hidd->pipe.device->id, + usb_host_addr (hidd->pipe.device), + usb_dev_addr (hidd->pipe.device)); + ts_hidd_phys_release (phys); + usb_kfree (phys); + return -ENOMEM; + } + + /* Now let's start getting each descriptor set */ + + req.bmreqtype = 0x81; + req.request = e_usb_req_get_descriptor; + req.index = hidd->iface->addr; + req.length = descr_set_0.length; + + for (cnt = 0; cnt < phys->sets; cnt++) + { + req.value = (e_hidd_descr_physical << 8) | (cnt + 1); + errcode = usb_request_data (hidd->pipe.device, &req, + set, + "get HID physical descriptor set"); + if (errcode < 0) + { + gdlf_err ("Error getting physical descriptor set %d " + "from HID interface %d of device id 0x%08x " + "(%d %d): errno/usb %d/%d\n", cnt + 1, + hidd->iface->addr, hidd->pipe.device->id, + usb_host_addr (hidd->pipe.device), + usb_dev_addr (hidd->pipe.device), + errcode, usb_errno); + ts_hidd_phys_release (phys); + usb_kfree (phys); + usb_kfree (set); + return errcode; + } + else if (errcode != descr_set_0.length) + { + gdlf_err ("Wrong size (%d bytes requested, %d readen) " + "while getting physical descriptor set %d " + "from HID interface %d of device id 0x%08x " + "(%d %d)\n", + descr_set_0.length, errcode, cnt + 1, + hidd->iface->addr, hidd->pipe.device->id, + usb_host_addr (hidd->pipe.device), + usb_dev_addr (hidd->pipe.device)); + ts_hidd_phys_release (phys); + usb_kfree (phys); + usb_kfree (set); + return errcode; + } + + /* descriptor readen, let's put it into the structure */ + + phys->set[cnt].info.v = *set; + + /* allocate space for descriptors */ + + phys->set[cnt].descr = + usb_kmalloc (phys->descrs * sizeof (ts_hidd_phys_descr), + GFP_KERNEL); + if (phys->set[cnt].descr == NULL) + { + gdlf_err ("Cannot allocate memory for physical " + "descriptor set %d on " + "interface %d of device id 0x%08x (%d %d)\n", + cnt + 1, + hidd->iface->addr, hidd->pipe.device->id, + usb_host_addr (hidd->pipe.device), + usb_dev_addr (hidd->pipe.device)); + ts_hidd_phys_release (phys); + usb_kfree (phys); + usb_kfree (set); + return -ENOMEM; + } + + /* fill in descriptors info */ + + memmove (phys->set[cnt].descr, set+1, + phys->descrs * sizeof (ts_hidd_phys_descr)); + } + usb_kfree (set); + hidd->phys = phys; + gdlf_debug ("Got physical descriptors for HID " + "interface %d of device id 0x%08x (%d %d)\n", + hidd->iface->addr, hidd->pipe.device->id, + usb_host_addr (hidd->pipe.device), + usb_dev_addr (hidd->pipe.device)); + return 0; +} + + + /* Fill in all the report descriptors related information + * + * Calculate how many space is required to get all the report + * descriptors, allocate a buffer of that size and read all the + * report descriptors to the buffer. + * + * Load parser module and get parsing function address, use it or + * get it's address directly (if linked in). Call (*hidd_parser) + * (hidd, buffer), release buffer and unuse parser module; if + * parser error, exit with error. + * + * Parameters: + * + * type descr + * + * Returns: + * + * type descr + */ + +int hidd_config_report (ts_hidd* hidd, + ts_hidd_descr_head* pheads, + size_t heads) +{ + gdlf_fntrace ("hidd_config_report (0x%p, 0x%p, %u)", + hidd, pheads, heads); + gdlf_aassert (hidd != NULL, return -EINVAL); + gdlf_aassert (pheads != NULL, return -EINVAL); + gdlf_aassert (heads != 0, return -EINVAL); + +#warning FIXME: hidd_config_report() not implemented! + return -ENOSYS; +} + + + /* Configure a device class interface + * + * This function may be used to be called from hidd_config() to + * configure the class part of a configurable element. + * + * Returns: + * + * int Number of cfels configured, errno code < 0 on + * error. + */ + +int hidd_config (ts_usb_cfel* cfel, ts_usb_device* device, + ts_usb_cfg* cfg, t_usb_cfg cfg_idx, + ts_usb_iface* iface, t_usb_iface iface_idx, + ts_usb_aset* aset, t_usb_aset aset_idx, __u32 flags) +{ + int errcode; + ts_usb_request req; + __u8 heads; /* number of descriptor heads */ + __u8 *itr, *top; + ts_hidd_descr *pdescr; /* pointer to descriptor data */ + ts_hidd_descr_head *pheads; + ts_hidd *hidd; + size_t descr_size; + int cnt; + + gdlf_fntrace ("hidd_config (0x%p, 0x%p, 0x%p, " + "0x%p, 0x%p, %u)", cfel, device, cfg, + iface, aset, flags); + gdlf_aassert (cfel != NULL, return -EINVAL); + gdlf_aassert (device != NULL, return -EINVAL); + + if (cfel->class != HIDD_CLASS) + { + gdlf_err ("Pretended to configure as HID non-HID " + "class interface %d of device (%d %d)\n", + iface->addr, + usb_host_addr (device), usb_dev_addr (device)); + return 0; + } + + /* Ok, configure? this cfel */ + + switch (cfel->subclass) + { + case HIDD_SUBCLASS_BOOT: /* we don't care about this one */ + gdlf_notice ("Interface %d of device (%d %d) supports " + "HID Boot Protocol, will use Report Protocol\n", + iface->addr, usb_host_addr (device), + usb_dev_addr (device)); + + case HIDD_SUBCLASS_REPORT: + gdlf_notice ("Interface %d of device (%d %d) supports " + "HID Report Protocol, configuring\n", iface->addr, + usb_host_addr (device), usb_dev_addr (device)); + break; + + + default: + gdlf_err ("Interface %d of device (%d %d): unknown " + "HID subclass code %d\n", iface->addr, + usb_host_addr (device), usb_dev_addr (device), + cfel->subclass); + return -EINVAL; + break; + } + + /* set protocol to report protocol */ + + req.bmreqtype = 0x21; + req.request = e_hidd_req_set_protocol; + req.value = 1; + req.index = iface->addr; + req.length = 0; + + errcode = usb_request_dataless (device, &req, + "set report protocol"); + if (errcode < 0) + { + gdlf_err ("Cannot set interface %d of device (%d %d) " + "to HID Report Protocol: errno/usb %d/%d\n", + iface->addr, usb_host_addr (device), + usb_dev_addr (device), errcode, usb_errno); + return errcode; + } + + /* Get HID descriptor's first 6 bytes and do sanity checks */ + + { + ts_hidd_descr descr; + + req.bmreqtype = 0x81; + req.request = e_usb_req_get_descriptor; + req.value = e_hidd_descr_hid << 8; + req.index = iface->addr; + req.length = sizeof (descr); + + errcode = usb_request_data (device, &req, &descr, + "HID descriptor get"); + if (errcode < 0) + { + gdlf_err ("Cannot get HID descriptor on interface %d " + "of device id 0x%08x (%d %d): errno/usb %d/%d\n", + iface->addr, device->id, usb_host_addr (device), + usb_dev_addr (device), errcode, usb_errno); + return errcode; + } + else if (errcode != sizeof (descr)) + { + gdlf_err ("Expected %d bytes and readed %d when requesting " + "HID descriptor on interface %d " + "of device id 0x%08x (%d %d): errno/usb %d/%d\n", + sizeof (descr), errcode, iface->addr, + device->id, usb_host_addr (device), + usb_dev_addr (device), errcode, usb_errno); + return errcode; + } + + /* Verify it is a HID descriptor */ + + if (descr.head.bDescriptorType != e_hidd_descr_hid) + { + gdlf_err ("Invalid descriptor type (%d) returned as " + "HID descriptor by interface %d of device " + "id 0x%08x (%d %d)\n", + descr.head.bDescriptorType, iface->addr, + device->id, usb_host_addr (device), + usb_dev_addr (device)); + return -EBADFD; + } + + /* Check HID version, if we support it */ + + descr.release = le16_to_cpu (descr.release); + if (descr.release > 0x0100) + { + gdlf_err ("Unsupported HID version %u.%u on interface %d " + "of device id 0x%08x (%d %d)\n", + descr.release & 0xff00 >> 16, + descr.release & 0x00ff, + iface->addr, device->id, + usb_host_addr (device), + usb_dev_addr (device)); + return -EPROTONOSUPPORT; + } + heads = descr.descrs; + + /* Check there's at least one descriptor [report] */ + + if (heads == 0) + { + gdlf_err ("Buggy HID descriptor, it reports zero additional " + "descriptors on interface %d " + "of device id 0x%08x (%d %d)\n", + iface->addr, device->id, usb_host_addr (device), + usb_dev_addr (device)); + return -EBADFD; + } + + /* + * check total descriptor length agrees with number of + * descriptors + */ + + descr_size = (sizeof (ts_hidd_descr) + + heads * HIDD_DESCR_HEAD_PACKED_SIZE); + if (descr_size != descr.head.bLength) + { + gdlf_err ("Buggy HID descriptor, it reports a number " + "of additional descriptors which doesn't " + "match it's size; on interface %d of device " + "id 0x%08x (%d %d)\n", + iface->addr, device->id, usb_host_addr (device), + usb_dev_addr (device)); + return -EBADFD; + } + } + + /* allocate space for the full descriptor */ + + pdescr = usb_kmalloc (descr_size, GFP_KERNEL); + if (pdescr == NULL) + { + gdlf_err ("Cannot allocate %d bytes to read " + "full HID descriptor on interface %d " + "device id 0x%08x (%d %d)\n", + descr_size, iface->addr, device->id, + usb_host_addr (device), usb_dev_addr (device)); + return -ENOMEM; + } + + /* allocate a temporary array to unpack the descriptors data */ + + pheads = usb_kmalloc (heads * sizeof (ts_hidd_descr_head), GFP_KERNEL); + if (pdescr == NULL) + { + gdlf_err ("Cannot allocate %d bytes to read " + "full HID descriptor on interface %d " + "device id 0x%08x (%d %d)\n", + heads * sizeof (ts_hidd_descr_head), iface->addr, + device->id, + usb_host_addr (device), usb_dev_addr (device)); + usb_kfree (pdescr); + return -ENOMEM; + } + + /* Get full HID descriptor */ + + req.bmreqtype = 0x81; + req.request = e_usb_req_get_descriptor; + req.value = e_hidd_descr_hid << 8; + req.index = iface->addr; + req.length = descr_size; + + errcode = usb_request_data (device, &req, pdescr, + "HID descriptor get"); + if (errcode < 0) + { + gdlf_err ("Cannot get HID descriptor on interface %d " + "of device id 0x%08x (%d %d): errno/usb %d/%d\n", + iface->addr, device->id, usb_host_addr (device), + usb_dev_addr (device), errcode, usb_errno); + usb_kfree (pdescr); + usb_kfree (pheads); + return errcode; + } + else if (errcode != descr_size) + { + gdlf_err ("Expected %d bytes and only read %d when requesting " + "HID descriptor on interface %d " + "of device id 0x%08x (%d %d): errno/usb %d/%d\n", + descr_size, errcode, iface->addr, + device->id, usb_host_addr (device), + usb_dev_addr (device), errcode, usb_errno); + usb_kfree (pdescr); + usb_kfree (pheads); + return errcode; + } + + /* Unpack descriptor heads + * + * This should be endian-proof [the LOW + 256 * HIGH] should + * be optimized out by the compiler. + */ + + itr = (__u8*)(pdescr + 1); /* looking at bDescriptorType */ + top = itr + heads * HIDD_DESCR_HEAD_PACKED_SIZE; + for (cnt = 0; itr < top; cnt++, itr += 3) + { + gdlf_aassert (cnt < heads, break); + pheads[cnt].type = *itr; + pheads[cnt].length = *(itr + 1) + 256 * (*(itr + 2)); + } + + /* Allocate ts_hidd struct and fill country */ + + hidd = ts_hidd_init(); + if (hidd == NULL) /* isn't this fun? */ + { + gdlf_err ("No memory allocate a HID structure\n"); + usb_kfree (pdescr); + usb_kfree (pheads); + return -ENOMEM; + } + hidd->country = pdescr->country; + hidd->release = le16_to_cpu (pdescr->release); + + /* Set the device info on hidd structure */ + + errcode = usb_pipe_dev_set (&hidd->pipe, device); + if (errcode < 0) + { + gdlf_err ("Cannot open a pipe to the device on HID " + "interface %d of device id 0x%08x (%d %d): " + "errno/usb %d/%d\n", + iface->addr, device->id, usb_host_addr (device), + usb_dev_addr (device), errcode, usb_errno); + usb_pipe_close (&hidd->pipe); + usb_kfree (pdescr); + usb_kfree (pheads); + usb_kfree (hidd); + return errcode; + } + hidd->iface = iface; + hidd->cfg = cfg; + ts_dtor_fill (&hidd->snode.dtor, (tf_dtor) hidd_destroy); + usb_configuration_ref (cfg); + + /* Seek for physical descriptors; if any, and load'em */ + + errcode = hidd_config_physical (hidd, pheads, heads); + if (errcode < 0) + { + hidd_destroy (hidd); + usb_kfree (hidd); + usb_kfree (pdescr); + usb_kfree (pheads); + return errcode; + } + + /* Load and parse HID Report descriptors */ + + errcode = hidd_config_report (hidd, pheads, heads); + usb_kfree (pdescr); + usb_kfree (pheads); + if (errcode < 0) + { + hidd_destroy (hidd); + usb_kfree (hidd); + return errcode; + } + + /* + * Set report mode to idle until change for each reportid + * (following HID 1.0 7.2.4 Remark on 'Report ID'). We set + * report ID zero, as this means _all_ report ids, or at + * least, it should. + */ + + req.bmreqtype = 0x21; + req.request = e_hidd_req_set_idle; + req.value = 0; /* report only if change detected */ + req.index = iface->addr; + req.length = 0; + + errcode = usb_request_dataless (device, &req, "set idle"); + if (errcode < 0) + gdlf_err ("Cannot set idle mode on HID interface " + "%d of device (%d %d) errno/usb %d/%d\n", + iface->addr, usb_host_addr (device), + usb_dev_addr (device), errcode, usb_errno); + + /* + * based on the usage pages shown by the reports/application + * collections, seek for registered (if not registered, + * request them to be loaded; if unexistant, skip) HID + * submodules which could deal with it and make them register + * within this hidd. This will allow them to listen to the + * event pipe this device will generate + */ + +#warning FIXME: load subdrivers + + /* + * If any reader opens the event reading pipe, start reading + * the interrupt endpoint and filling events as + * they are made available; the callback function will get an + * event, pipe it and re-schedule a read . + */ + +#warning FIXME: pipe events + + return 0; +} + + + /* Unconfigure all cfels configured by this driver + * + * This function may be used to unconfigure a driver's + * class-configured configurable elements. + * + * Parameters: + * + * ts_usb_device* Pointer to the device structure to + * unconfigure. + * + * unsigned USB_CFG_* flags indicating why is this + * function called. + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. */ + +int hidd_unconfig (ts_usb_device* device, unsigned flags) +{ + t_usb_cfg cfg_cnt; + ts_usb_cfg *cfg; + ts_usb_iface *iface, *iface_top; + ts_usb_aset *aset, *aset_top; + + gdlf_fntrace ("hidd_unconfig (0x%p, %u)", device, flags); + gdlf_aassert (device != NULL, return -EINVAL); + + for (cfg_cnt = 0; cfg_cnt < device->pcfgs; cfg_cnt++) + { + cfg = device->pcfg[cfg_cnt]; + if (cfg == NULL) /* unloaded? skip */ + continue; + + /* Walk cfg's interfaces */ + + for (iface = cfg->iface, iface_top = iface + cfg->ifaces; + iface < iface_top; iface++) + { + /* Walk the iface's asets */ + + for (aset = iface->aset, aset_top = aset + iface->asets; + aset < aset_top; aset++) + + /* cfged by us? */ + + if (aset->cfel.configured + && aset->cfel.data + && (aset->cfel.data->dtor.fn + == (tf_dtor)hidd_destroy) + ) + { + ts_dtor_exec (&aset->cfel.data->dtor); + usb_kfree (aset->cfel.data = NULL); + aset->cfel.data = NULL; + aset->cfel.configured = 0; /* uncfged */ + } + } + } + return 0; +} + +/* Log: + * + * $Log: cfg.c,v $ + * Revision 1.9 1999/04/05 00:39:36 inaky + * Updated dates and moved to new usb_pipe_*() semantics + * + * Revision 1.8 1999/01/23 18:49:18 inaky + * Added all the code to get physical descriptors [untested], as well as + * initial configuration. Will I someday finish the parsing side? + * + * Revision 1.7 1999/01/01 22:54:54 inaky + * Added skeletons for filling the phys and report descr struct, will + * finish later. The basic configuration code is done, just missing the + * before mentioned functions and the pipe structure. + * + * Revision 1.6 1998/12/23 23:10:20 inaky + * Added some stuff copied from hidbp, to not forget it :). + * + * Revision 1.5 1998/11/14 17:19:46 inaky + * Moved the include files to uusbd/include/uusbd, to ease integration + * into the Linux kernel. + * + * Revision 1.4 1998/10/31 02:16:55 inaky + * Removed all the d_* pointers from ts_usb_cfel and collapsed them into + * a single pointer; only one was really used. + * + * Revision 1.3 1998/09/11 00:51:50 inaky + * Moved the boot protocol to a single driver, to isolate it more easily. + * + * Revision 1.2 1998/08/30 13:56:11 inaky + * Fixed comments. Added support to multiplex to boot protocols. + * + * Revision 1.1 1998/08/28 23:53:14 inaky + * New driver + * + * Revision 1.3 1998/08/28 00:14:22 inaky + * New driver ... + * + */ + + + diff -Naur linux.225/drivers/uusbd/hidd/driver.c linux.225.visws/drivers/uusbd/hidd/driver.c --- linux.225/drivers/uusbd/hidd/driver.c Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/hidd/driver.c Sun Apr 4 17:39:37 1999 @@ -0,0 +1,280 @@ + +/* USB Human Interface Devices Driver v$Revision: 1.5 $ + * + * (C) 1997-99 by Iñaky Pérez González + * + * Distributed under the terms of the GNU Public License Version 2 + * See files COPYRIGHT and COPYING at the root distribution directory + * + * $Id: driver.c,v 1.5 1999/04/05 00:39:37 inaky Exp $ + * + * Changelog at the bottom + * + * USB Human Interface Devices - Configuration + * ------------------------------------------- + * + * This is the embrion of the USB HID Driver. + * + */ + +#include /* __init */ +#define __NO_VERSION__ +#include /* MOD_*_USE_COUNT */ +#include /* locks */ + +#include + +#define GDLF_IDENT "USB-HIDD" +#define GDLF_LOCAL /* Define if want local settings */ +#define GDLF_DEF_LOGLEVEL 9 +#define GDLF_ASSERTIONS /* want assertions (#undef if not) */ +#define GDLF_FNTRACE /* want function traces */ +#define GDLF_LOCATIONS /* want locations in log messages */ +#include + +#include + + +atomic_t usecnt; +volatile int hidd_errno = 0; + +#define NAME /* short!! */ \ + "USB Human Interface Devices Driver v$Revision: 1.5 $" + +#define COPYRIGHT \ + "(c) 1998 Inaky Perez Gonzalez " \ + "" + +#define VENDOR 0 +#define VENDORNAME \ + NULL + +#define PRODUCT 0 +#define DEVICENAME \ + NULL + +#define CLASS HIDD_CLASS +#define CLASSNAME \ + "USB Human Inteface Devices" + +#define SUBCLASS 0 +#define SUBCLASSNAME \ + NULL + +#define PROTOCOL 0 +#define PROTOCOLNAME \ + NULL + +#define SNODE_NULL { {NULL}, NULL, 0} + +ts_usb_driver* hidd_driver = NULL; + + /* + * Linux module support + */ + +#ifdef MODULE + +int init_module (void) +{ + return hidd_init(); +} + +void cleanup_module (void) +{ + hidd_release(); + hidd_shutdown(); + return; +} + +#endif + + + /* Initialize the hidd driver + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + * + * Global: + * + * int hidd_errno On error, error code. + * int usb_errno On error, error code. + */ + +int __init hidd_init (void) +{ + int errcode; + + gdlf_fntrace ("hidd_init()"); + gdlf_info (NAME "\n"); +#ifdef MODULE + gdlf_info (COPYRIGHT "\n"); +#endif + + hidd_driver = ts_usb_driver_init(); + if (hidd_driver == NULL) + { + usb_errno = hidd_errno = -USBE_NO_MEMORY; + return -ENOMEM; + } + + /* Set driver's attributes */ + + hidd_driver->vendor = VENDOR; + hidd_driver->product = PRODUCT; + hidd_driver->class = CLASS; + hidd_driver->subclass = SUBCLASS; + hidd_driver->protocol = PROTOCOL; + + /* Set info */ + + hidd_driver->name = NAME; /* driver name */ + hidd_driver->copyright = COPYRIGHT; /* driver copyright */ + hidd_driver->vendorname = VENDORNAME; /* device's vendor name */ + hidd_driver->productname = DEVICENAME; /* device's name */ + hidd_driver->classname = CLASSNAME; /* class' name */ + hidd_driver->subclassname = SUBCLASSNAME; /* subclass' name */ + hidd_driver->protocolname = PROTOCOLNAME; /* protocol name */ + + hidd_driver->config = hidd_config; /* config method */ + hidd_driver->unconfig = hidd_unconfig; /* unconfig method */ + hidd_driver->reference = hidd_reference; /* reference method */ + ts_snode_ref (&hidd_driver->snode); /* we hold a reference to it */ + + ts_slist_clean (&hidd_list); /* initialize the list */ + errcode = usb_drv_register (hidd_driver); /* register driver */ + if (errcode) + { + gdlf_err ("Cannot register driver: " + "errno/usb %d/%d\n", + errcode, usb_errno); + usb_drv_destroy (hidd_driver); + usb_kfree (hidd_driver); + hidd_errno = -USBE_DRIVER_CANT_REG; + return errcode; + } + + /* FIXME: do you class' stuf */ +#warning FIXME: do class stuff! + + return 0; +} + + + /* Release the hidd driver + * + * Do what is needed to ensure the use count of the driver is + * zero and can be unloaded from the kernel. + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + * + * Global: + * + * int hidd_errno On error, error code. + * int usb_errno On error, error code. + */ + +int hidd_release (void) +{ + gdlf_fntrace ("hidd_release()"); + +#warning FIXME: hidd_release() not implemented! + + return -ENOSYS; +} + + + /* Shutdown the skel driver + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + * + * Global: + * + * int hidd_errno On error, error code. + * int usb_errno On error, error code. + */ + +int hidd_shutdown (void) +{ + gdlf_fntrace ("hidd_shutdown()"); + ts_snode_unref (&hidd_driver->snode, NULL); + return usb_drv_unregister (hidd_driver); +} + + + /* Driver reference + * + * The 'reference' method is used when we take any of the driver's + * code or data structures to use it. If so, we call it with a + * positive argument (one reference, regardless the value of the + * _positive_ number). When we are done, we release the reference + * calling it with a negative number. It always returns the number + * of references or < 0 on error. Calling it with an argument of + * zero will just return the number of references. + * Compliance: USB Spec 1.0 xxxx + * + * Parameters: + * + * type descr + * + * Global: + * + * type name descr + * + * Returns: + * + * type descr + * + * Global: + * + * type name descr + */ + +int hidd_reference (ts_usb_device* device, int n) +{ + gdlf_fntrace ("hidd_reference (0x%p, %d)", device, n); + gdlf_aassert (device != NULL, return -EINVAL); + + if (n > 0) + { + atomic_inc (&usecnt); + MOD_INC_USE_COUNT; + } + else if (n < 0) + { + atomic_dec (&usecnt); + MOD_DEC_USE_COUNT; + } + return atomic_read (&usecnt); +} + +/* Log: + * + * $Log: driver.c,v $ + * Revision 1.5 1999/04/05 00:39:37 inaky + * Updated dates and moved to new usb_pipe_*() semantics + * + * Revision 1.4 1998/11/14 17:19:47 inaky + * Moved the include files to uusbd/include/uusbd, to ease integration + * into the Linux kernel. + * + * Revision 1.3 1998/09/11 00:51:51 inaky + * Moved the boot protocol to a single driver, to isolate it more easily. + * + * Revision 1.2 1998/08/30 13:56:54 inaky + * Fixed destroying driver stryctures on error, added char device + * registration. + * + * Revision 1.1 1998/08/28 23:53:14 inaky + * New driver + * + * Revision 1.3 1998/08/28 00:14:23 inaky + * New driver ... + * + */ + diff -Naur linux.225/drivers/uusbd/hidd/generic.c linux.225.visws/drivers/uusbd/hidd/generic.c --- linux.225/drivers/uusbd/hidd/generic.c Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/hidd/generic.c Sun Apr 4 17:39:38 1999 @@ -0,0 +1,53 @@ + +/* USB Human Interface Devices Driver v$Revision: 1.4 $ + * + * (C) 1997-99 by Iñaky Pérez González + * + * Distributed under the terms of the GNU Public License Version 2 + * See files COPYRIGHT and COPYING at the root distribution directory + * + * $Id: generic.c,v 1.4 1999/04/05 00:39:38 inaky Exp $ + * + * Changelog at the bottom + * + * USB Human Interface Devices - Configuration + * ------------------------------------------- + * + * This is the embrion of the USB HID Driver. + * + */ + +#include + +#define GDLF_IDENT "USB-HIDD" +#define GDLF_LOCAL /* Define if want local settings */ +#define GDLF_DEF_LOGLEVEL 9 +#define GDLF_ASSERTIONS /* want assertions (#undef if not) */ +#define GDLF_FNTRACE /* want function traces */ +#define GDLF_LOCATIONS /* want locations in log messages */ +#include + +#include + + +/* Log: + * + * $Log: generic.c,v $ + * Revision 1.4 1999/04/05 00:39:38 inaky + * Updated dates and moved to new usb_pipe_*() semantics + * + * Revision 1.3 1998/11/14 17:19:49 inaky + * Moved the include files to uusbd/include/uusbd, to ease integration + * into the Linux kernel. + * + * Revision 1.2 1998/08/30 13:57:07 inaky + * Moved all this to be inlined in the header file. + * + * Revision 1.1 1998/08/28 23:53:15 inaky + * New driver + * + * Revision 1.3 1998/08/28 00:14:23 inaky + * New driver ... + * + */ + diff -Naur linux.225/drivers/uusbd/hidd/header linux.225.visws/drivers/uusbd/hidd/header --- linux.225/drivers/uusbd/hidd/header Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/hidd/header Sun Apr 4 17:39:39 1999 @@ -0,0 +1,18 @@ + +/* USB Human Interface Devices Driver v$Revision: 1.2 $ + * + * (C) 1997-99 by Iñaky Pérez González + * + * Distributed under the terms of the GNU Public License Version 2 + * See files COPYRIGHT and COPYING at the root distribution directory + * + * $Id: header,v 1.2 1999/04/05 00:39:39 inaky Exp $ + * + * Changelog at the bottom + * + * USB Human Interface Devices - Configuration + * ------------------------------------------- + * + * This is the embrion of the USB HID Driver. + * + */ diff -Naur linux.225/drivers/uusbd/hidd/hkeep.c linux.225.visws/drivers/uusbd/hidd/hkeep.c --- linux.225/drivers/uusbd/hidd/hkeep.c Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/hidd/hkeep.c Sun Apr 4 17:39:40 1999 @@ -0,0 +1,179 @@ + +/* USB Human Interface Devices Driver v$Revision: 1.6 $ + * + * (C) 1997-99 by Iñaky Pérez González + * + * Distributed under the terms of the GNU Public License Version 2 + * See files COPYRIGHT and COPYING at the root distribution directory + * + * $Id: hkeep.c,v 1.6 1999/04/05 00:39:40 inaky Exp $ + * + * Changelog at the bottom + * + * USB Human Interface Devices - Configuration + * ------------------------------------------- + * + * This is the embrion of the USB HID Driver. + * + */ + +#include /* locks */ +#include /* MOD_*_USE_COUNT */ + +#include + +#define GDLF_IDENT "USB-HIDD" +#define GDLF_LOCAL /* Define if want local settings */ +#define GDLF_DEF_LOGLEVEL 9 +#define GDLF_ASSERTIONS /* want assertions (#undef if not) */ +#define GDLF_FNTRACE /* want function traces */ +#define GDLF_LOCATIONS /* want locations in log messages */ +#include + +#include + + +ts_slist hidd_list; /* list of registered class structures */ + + + /* Unregister an hidd element + * + * This is the destructor function. + * + * Parameters: + * + * ts_hidd* Class element to unregister + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + * + * Global: + * + * int usb_errno On error, error code. + * int hidd_errno On error, error code. + */ + +int hidd_unregister (ts_hidd* hidd) +{ + gdlf_fntrace ("hidd_unregister (0x%p)", hidd); + gdlf_aassert (hidd != NULL, return -EINVAL); + gdlf_aassert (hidd->snode.dtor.fn == (tf_dtor)hidd_destroy, + return -EINVAL); + + /* Let's get it removed from the list */ + + ts_slist_del (&hidd_list, &hidd->snode); +#warning FIXME: remove this, it makes modules stay for ever + MOD_DEC_USE_COUNT; + return 0; /* bye */ +} + + + /* FIXME: Detailed desc + * + * Compliance: USB Spec 1.0 xxxx + * + * Parameters: + * + * type descr + * + * Global: + * + * type name descr + * + * Returns: + * + * type descr + * + * Global: + * + * type name descr + */ + +int hidd_destroy (ts_hidd* hidd) +{ + gdlf_fntrace ("hidd_destroy (0x%p)", hidd); + gdlf_aassert (hidd != NULL, return -EINVAL); + gdlf_aassert (hidd->snode.dtor.fn == (tf_dtor)hidd_destroy, + return -EINVAL); + + ts_snode_ref (&hidd->snode); + + usb_pipe_close (&hidd->pipe); + if (hidd->cfg) + usb_configuration_unref (hidd->cfg); +#if 0 + hidd_unregister (hidd); /* unregister */ +#endif + + ts_snode_unref_nd (&hidd->snode); + ts_hidd_release (hidd); /* clean the struct */ + return 0; /* bye */ +} + + + /* Register an hidd element + * + * Parameters: + * + * ts_hidd* Class element to register + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + * + * Global: + * + * int usb_errno On error, error code. + * int hidd_errno On error, error code. + */ + +int hidd_register (ts_hidd* hidd) +{ + int errcode; + + gdlf_fntrace ("hidd_register (0x%p)", hidd); + gdlf_aassert (hidd != NULL, return -EINVAL); + gdlf_aassert (hidd->snode.dtor.fn == (tf_dtor)hidd_destroy, + return -EINVAL); + + /* get into the list */ + + errcode = ts_slist_prep (&hidd_list, &hidd->snode); + if (errcode) + return errcode; +#warning FIXME: remove this, it makes modules stay for ever + MOD_INC_USE_COUNT; + return 0; /* bye */ +} + +/* Log: + * + * $Log: hkeep.c,v $ + * Revision 1.6 1999/04/05 00:39:40 inaky + * Updated dates and moved to new usb_pipe_*() semantics + * + * Revision 1.5 1999/01/23 18:49:58 inaky + * Added destruction stuff to hidd, such as closing the pipe and + * unreferencing the configuration. + * + * Revision 1.4 1998/11/14 17:19:50 inaky + * Moved the include files to uusbd/include/uusbd, to ease integration + * into the Linux kernel. + * + * Revision 1.3 1998/09/11 00:51:52 inaky + * Moved the boot protocol to a single driver, to isolate it more easily. + * + * Revision 1.2 1998/08/30 13:58:02 inaky + * Added checks and fixed the destructor. + * + * Revision 1.1 1998/08/28 23:53:15 inaky + * New driver + * + * Revision 1.3 1998/08/28 00:14:23 inaky + * New driver ... + * + */ + + diff -Naur linux.225/drivers/uusbd/hidd/parser.c linux.225.visws/drivers/uusbd/hidd/parser.c --- linux.225/drivers/uusbd/hidd/parser.c Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/hidd/parser.c Sun Apr 4 17:39:41 1999 @@ -0,0 +1,64 @@ + +/* USB Human Interface Devices Driver v$Revision: 1.2 $ + * + * (C) 1997-99 by Iñaky Pérez González + * + * Distributed under the terms of the GNU Public License Version 2 + * See files COPYRIGHT and COPYING at the root distribution directory + * + * $Id: parser.c,v 1.2 1999/04/05 00:39:41 inaky Exp $ + * + * Changelog at the bottom + * + * USB Human Interface Devices - Parser + * ------------------------------------ + * + * This is the report descriptor parser + * + */ + +#include + +#define GDLF_IDENT "USB-HIDD" +#define GDLF_LOCAL /* Define if want local settings */ +#define GDLF_DEF_LOGLEVEL 9 +#define GDLF_ASSERTIONS /* want assertions (#undef if not) */ +#define GDLF_FNTRACE /* want function traces */ +#define GDLF_LOCATIONS /* want locations in log messages */ +#include + + /* + * Allocate a new ts_hidd_report + * + * When item-main, allocate new ts_hidd_report + * Remove local items + * Keep global items [defaults] + * + * item-collection, start new collection + * + * item-push, item state table pushed onto stack + * + * item-pop, replace item state with stack's top. + * + * + * + * + * + * + * + */ + + +/* Log: + * + * $Log: parser.c,v $ + * Revision 1.2 1999/04/05 00:39:41 inaky + * Updated dates and moved to new usb_pipe_*() semantics + * + * Revision 1.1 1998/12/23 23:09:54 inaky + * Added try to being parser ... just nothing. + * + */ + + + diff -Naur linux.225/drivers/uusbd/hubd/Makefile linux.225.visws/drivers/uusbd/hubd/Makefile --- linux.225/drivers/uusbd/hubd/Makefile Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/hubd/Makefile Sat Nov 14 09:20:20 1998 @@ -0,0 +1,43 @@ +# +# Makefile for the Universal USB Driver, Linux flavour +# ---------------------------------------------------- +# +# Distributed under the terms of the GNU Public License Version 2 +# See files COPYRIGHT and COPYING at the root distribution directory + +SUB_DIRS := +MOD_IN_SUB_DIRS := $(SUB_DIRS) +ALL_SUB_DIRS := $(SUB_DIRS) + +# Objects +OX_OBJS := hubd-symtab.o +O_OBJS := hkeep.o driver.o ports.o requests.o cfg.o +# O_TARGET (just one) will be made by compiling+linking OX_OBJS and O_OBJS +O_TARGET := usb-hubd.o + +# Modules +MIX_OBJS := +MI_OBJS := +# Made by modules. These ones get symlinked at $(TOPDIR)/modules and +# added to the list of modules +M_OBJS := usb-hubd.o dummy_module + +# This module is always hard-linked to usb.o, as it has to work always. + +ifeq ($(CONFIG_USB_PROCFS),y) + O_OBJS += procfs.o +endif + +include ../Makefile.inc +ifdef NOT_IN_LINUX_KERNEL +export EXTRA_CFLAGS += -I../include +endif + +include $(TOPDIR)/Rules.make +include ../Makefile-rules.inc + +.PHONY: dummy_module +dummy_module: +ifeq ($(CONFIG_USB_HUBD),m) + for v in $(M_OBJS); do echo `pwd`/$$v; done >> $(MODULES_FILE) +endif diff -Naur linux.225/drivers/uusbd/hubd/README linux.225.visws/drivers/uusbd/hubd/README --- linux.225/drivers/uusbd/hubd/README Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/hubd/README Sat Jun 20 14:55:16 1998 @@ -0,0 +1,12 @@ + + The UUSBD Hub Driver (hubd.o) + + Note this driver is a loadable module, as the UUSBD Hub +Manager abstracts the calls to it. + + This driver is meant to be a generic hub driver. Quirky, +braindamaged and the like hubs can get their own driver, which may be +re-implemented completely or do some stuff and then pass control to +this driver's code (thus, complementing it). + + Iñaky diff -Naur linux.225/drivers/uusbd/hubd/cfg.c linux.225.visws/drivers/uusbd/hubd/cfg.c --- linux.225/drivers/uusbd/hubd/cfg.c Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/hubd/cfg.c Sun Apr 4 17:40:21 1999 @@ -0,0 +1,466 @@ + +/* USB Driver Stack v$Revision: 1.7 $ + * + * (C) 1997-99 by Iñaky Pérez González + * + * Distributed under the terms of the GNU Public License Version 2 + * See files COPYRIGHT and COPYING at the root distribution directory + * + * $Id: cfg.c,v 1.7 1999/04/05 00:40:21 inaky Exp $ + * + * Changelog at the bottom + * + * + * Hub Driver - Configuration and friends + * -------------------------------------- + * + */ + +#include /* spinlock_init() */ +#define __NO_VERSION__ +#include /* MOD_*_USE_COUNT */ + +#include +#include + +#define GDLF_IDENT "USB-HUBD" +#define GDLF_LOCAL /* Define if want local settings */ +#define GDLF_DEF_LOGLEVEL gdlf_level_top +#define GDLF_ASSERTIONS /* want assertions (#undef if not) */ +#undef GDLF_FNTRACE /* want function traces */ +#define GDLF_LOCATIONS /* want locations in log messages */ +#include + + + /* Configure a hub + * + * This function is called by the UUSBD when it needs to + * configure a hub. + * + * It sets up all the data structures and registrations on all + * needed places. Also initializes the 'tr' member to do the + * status change transactions with the default callback. Use your + * callback there if needed, but follow the working guidelines + * (see the source code for it). + * + * This stuff: + * + * usb_configuration_ref (cfg); + * usb_device_ref (&device->msnode); + * usb_host_ref (&hub->host->snode); + * + * is needed for the counts to be ok. The hub destructor, + * usb_hub_destroy() will unreference on hub structure + * destruction. + * + * Parameters: + * + * ts_usb_cfel* Configurable element to configure. + * + * ts_usb_device* Pointer to the device structure to configure. + * + * ts_usb_cfg* USB configuration where the configurable + * element is (NULL if it is the Device + * Configurable Element). + * + * ts_usb_iface* Interface where the configurable element is + * (NULL if it is the Device Configurable + * Element). + * + * ts_usb_aset* Alternate setting where the configurable + * element is (NULL if it is the Device + * Configurable Element). + * + * __u32 USB_CFG_* flags indicating why is this + * function called. + * + * Returns: + * + * int Number of cfels configured, errno code < 0 on + * error. + */ + +int hubd_config (ts_usb_cfel* cfel, ts_usb_device* device, + ts_usb_cfg* cfg, t_usb_cfg cfg_idx, + ts_usb_iface* iface, t_usb_iface iface_idx, + ts_usb_aset* aset, t_usb_aset aset_idx, __u32 flags) +{ + int errcode, cnt; + ts_usb_hub *hub; + + gdlf_fntrace ("hubd_config (0x%p, 0x%p, 0x%p, %u, " + "0x%p, %u, 0x%p, %u, %u)", cfel, device, + cfg, cfg_idx, iface, iface_idx, + aset, aset_idx, flags); + + /* Check class */ + + if (cfel->class != HUBD_CLASS) + { + gdlf_err ("Tried to configure non-hub device " + "0x%p (%d %d) as hub\n", + device, usb_host_addr (device), + usb_dev_addr (device)); + return 0; /* nothing configured */ + } + + /* check this is the device cfel */ + + if (cfel != &device->cfel) + { + gdlf_err ("Hub configuration not called on device " + "wide basis for device 0x%p (%d %d)\n", + device, usb_host_addr (device), + usb_dev_addr (device)); + return -EBADFD; + } + + /* + * Set the active configuration to the self powered one if + * possible + */ + + if (device->pcfg == NULL) + { + gdlf_err ("Device id 0x%08x (%d %d) configuration tree not " + "filled in, aborting\n", + device->id, usb_host_addr (device), + usb_dev_addr (device)); + return -EINVAL; + } + +#warning FIXME: get the configuration from the persistence system, choose the best one [self powered] + + cnt = 0; + + if (device->pcfg[cnt] == NULL) + { + gdlf_err ("Device id 0x%08x (%d %d) configuration index %d not " + "filled in, aborting\n", + cnt, device->id, usb_host_addr (device), + usb_dev_addr (device)); + return -EINVAL; + } + + errcode = usb_configuration_set (device, device->pcfg[cnt]->addr, 0); + if (errcode < 0) + { + gdlf_err ("Cannot switch to configuration index " + "%d, address %d (%s) of device 0x%p (%d %d): " + "errno/usb %d/%d\n", + cnt, device->pcfg[cnt]->addr, + device->pcfg[cnt]->descr? + device->pcfg[cnt]->descr : "name n/a", + device, usb_host_addr (device), + usb_dev_addr (device), + errcode, usb_errno); + return errcode; + } + + /* + * Hub spec (USB 1.0 Spec, Chapter 11th) mandates just an + * interface and one endpoint. + */ + + gdlf_aassert (device->active != NULL, return -EINVAL); + gdlf_assert (device->active->ifaces == 1); + gdlf_assert (device->active->iface[0].active->endps == 1); + + /* + * Now set all given pointers to what we need + * + * This is left so in order to prepare it to the time when a + * device can have a hub in a single interface. This may + * happen in a future. Now it looks like extra work? yep, but + * it should be optimized out. If not, we can #ifdef it. + */ + + cfg = device->active; + iface = &cfg->iface[0]; + aset = iface->active; + cfel = &aset->cfel; + + gdlf_aassert ((cfg->iface - iface) / sizeof (ts_usb_iface) + < cfg->ifaces, + return -EINVAL); + gdlf_aassert ((iface->aset - aset) / sizeof (ts_usb_aset) + < iface->asets, + return -EINVAL); + + /* Create a hub structure and fill basics */ + + hub = ts_usb_hub_init(); /* alloc */ + if (hub == NULL) /* on error ... */ + return -ENOMEM; /* ... ts_usb_hub_init() complains itself */ + + /* (hub destructor set when registering) */ + + hub->configuring = 1; /* we are configuring it */ + hub->host = device->hub->host; /* set hub's host */ + usb_host_ref (hub->host); + hub->device = device; /* set hub's device */ + usb_device_ref (device); + hub->cfg = cnt; + usb_configuration_ref (cfg); + hub->iface = (cfg->iface - iface) / sizeof (ts_usb_iface); + hub->aset = (iface->aset - aset) / sizeof (ts_usb_aset); + hub->operations = &hubd_operations; + + /* Fill in data from descriptor */ + + errcode = hubd_descriptor_fill (hub); + if (errcode < 0) + { + gdlf_err ("Couldn't fill hub 0x%p (%d %d) " + "descriptor data: " + "errno/usb %d/%d\n", + hub, hub->host->addr, hub->device->addr, + errcode, usb_errno); + usb_configuration_unref (cfg); + usb_device_unref (device, NULL); + usb_host_unref (hub->host, NULL); + ts_usb_hub_release (hub); + usb_kfree (hub); + return errcode; + } + + /* Set up the status change descriptor */ + +#warning FIXME: open a new desciptor for endpoint zero? + errcode = usb_pipe_open (&hub->pipe, hub->device, + &aset->endp[USB_HUB_ENDP_STAT_CH]); + if (errcode < 0) + { + gdlf_err ("Couldn't open hub 0x%p (%d %d)'s " + "status change endpoint: " + "errno/usb %d/%d\n", + hub, hub->host->addr, hub->device->addr, + errcode, usb_errno); + usb_configuration_unref (cfg); + usb_device_unref (device, NULL); + usb_host_unref (hub->host, NULL); + ts_usb_hub_release (hub); + usb_kfree (hub); + return errcode; + } + + /* set the transfers data */ + + hub->tr.size = (1 + hub->ports)/8 + + ((1 + hub->ports) % 8? 1 : 0); + hub->tr.data = + usb_kmalloc (hub->tr.size, GFP_KERNEL); + if (hub->tr.data == NULL) + { + gdlf_err ("No memory to set up a %u bytes data " + "buffer for hub 0x%p (%d %d)'s status " + "change endpoint\n", + hub->tr.size, hub, hub->host->addr, + hub->device->addr); + hub->tr.size = 0; + usb_configuration_unref (cfg); + usb_device_unref (device, NULL); + usb_host_unref (hub->host, NULL); + usb_kfree (hub); + return errcode; + } + hub->tr.timeout = 0; /* don't want it to timeout */ + hub->tr.warn.callback = usb_hub_status_callback; + hub->tr.method = 1; + hub->tr.done_warn = 1; /* warn on end */ +#if 0 + hub->tr.user = 0; +#endif + hub->tr.status = e_usb_tr_status_filled; + hub->tr.pipe = &hub->pipe; + + errcode = usb_tr_setup (&hub->tr); + if (errcode < 0) + { + gdlf_err ("Cannot setup a read from hub 0x%p " + "(%d %d)'s status change endpoint: " + "errno/usb %d/%d\n", + hub, hub->host->addr, hub->device->addr, + errcode, usb_errno); + usb_tr_destroy (&hub->tr); + usb_configuration_unref (cfg); + usb_device_unref (device, NULL); + usb_host_unref (hub->host, NULL); + ts_usb_hub_release (hub); + usb_kfree (hub); + return errcode; + } + + errcode = usb_tr_insert (&hub->tr); + if (errcode < 0) + { + gdlf_err ("Cannot insert a read from hub 0x%p " + "(%d %d)'s status change endpoint: " + "errno/usb %d/%d\n", + hub, hub->host->addr, hub->device->addr, + errcode, usb_errno); + usb_tr_destroy (&hub->tr); + usb_configuration_unref (cfg); + usb_device_unref (device, NULL); + usb_host_unref (hub->host, NULL); + ts_usb_hub_release (hub); + usb_kfree (hub); + return errcode; + } + + /* + * FIXME: We should be using just cfel->data. We could store + * the 'hubd' pointer at 'tr->private', thus + * usb_hub_status_callback() can get it. In the mean + * time, we use this one + * + * However, only set device->cfel.data, because + * otherway, it'll see the device cfel and an interface + * cfel being active/configured, and will try to + * destroy both [aka: crash]. + */ + + cfel->data = NULL; + device->cfel.data = + ts_snode_ref (&hub->snode); /* attach to device */ + + device->cfel.configured = + cfel->configured = (__u32)hub; /* it's configured! */ + hub->configuring = 0; /* done configuring the hub */ +#warning FIXME: Make unreferenced drivers work + /* FIXME: problem is when releasing the driver, hubs ain't unregistered */ +#ifndef HUBD_UNREF_WORKS + hubd_reference (hub, 1); /* we use the driver */ +#endif + + /* Register the hub structure (it starts scheduling) */ + + errcode = usb_hub_register (hub); + if (errcode < 0) + { + gdlf_err ("Couldn't register hub 0x%p (%d %d): " + "errno/usb %d/%d\n", + hub, hub->host->addr, hub->device->addr, + errcode, usb_errno); +#ifndef HUBD_UNREF_WORKS + hubd_reference (hub, -1); +#endif + device->cfel.data = NULL; + device->cfel.configured = 0; + cfel->data = NULL; + cfel->configured = 0; /* it's configured! */ + usb_configuration_unref (cfg); + usb_device_unref (device, NULL); + usb_host_unref (hub->host, NULL); + ts_snode_unref (&hub->snode, NULL); /* this will kfree() */ + ts_usb_hub_release (hub); + return errcode; + } + + /* Power on all the ports */ + + if (hub->power <= 2) /* can we turn ports' power on? */ + { + for (cnt = 0; cnt < hub->ports; cnt++) + { + errcode = usb_port_feature_set (hub, cnt, e_usb_port_fes_power); + if (errcode < 0) + gdlf_err ("Error powering on port %u " + "of hub 0x%p, device (%d %d): " + "errno/usb %d/%d\n", + cnt, hub, hub->host->addr, + hub->device->addr, + errcode, usb_errno); + } + usb_waitms (2 * hub->pwrontime); + } + return 1; /* we've configured one cfel */ +} + + + /* Unconfigure a device if hub + * + * This routine is called by when it is required to unconfigure + * all devices which use a particular driver. It has to make sure + * that any device which have any cfel configured by this driver + * is unconfigured. + * + * So, the easiest way is to find this device into the driver use + * list. The use list keeps pointers to hub structures. If we find + * the pointer to this device's hub structure at our use list, + * then we must unconfigure the device. + * + * To accomplish that task, instead of calling directly the + * usb_hub_destroy() destructor, we call the structure's + * destructor and then free the data. + * + * Parameters: + * + * ts_usb_device* Pointer to the device structure to + * unconfigure. + * + * __u32 USB_CFG_* flags indicating why is this + * function called. + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + */ + +int hubd_unconfig (ts_usb_device* device, __u32 flags) +{ + int count; /* unconfigured cfels */ + ts_snode *itr, *next, *this; + + gdlf_fntrace ("hubd_unconfig (0x%p, 0x%x)", device, flags); + + this = device->cfel.data; /* hub drivers hook there */ + count = 0; + itr = ts_slist_head (&hubd_driver->uselist); + while (itr) + { + next = ts_slist_next (itr); + if (((ts_usb_drv_use*)itr)->user == this) + { + ts_dtor_exec (&itr->dtor); /* destroy ~ unconfigure */ + count++; + } + itr = next; + } + return count; +} + +/* Log: + * + * $Log: cfg.c,v $ + * Revision 1.7 1999/04/05 00:40:21 inaky + * Trimmed logs, updated dates and moved to new usb_pipe_*() semantics + * + * Revision 1.6 1999/03/09 22:56:26 inaky + * Make driver stay with zero reference count. Useful? I dunno + * ... perhaps will be dropped. Hubs and hosts are the only stuff + * _really_ needed on USB. Rest may be unloaded. + * + * Revision 1.5 1999/02/28 19:50:30 inaky + * Check before trying configurations that the configuration tree is + * loaded. + * + * Revision 1.4 1998/12/12 02:44:27 inaky + * Misc fixes, as not having timeout on hubs [by Paul]. Also made + * ts_usb_hub data be only at one cfel, as it was being duplicated, and + * thus the unconfiguration crashed. + * + * Revision 1.3 1998/11/26 21:58:33 inaky + * Renamed all the ts_usb_open stuff and friends to use _pipe_. + * + * Revision 1.2 1998/11/14 17:20:29 inaky + * Moved the include files to uusbd/include/uusbd, to ease integration + * into the Linux kernel. + * + * Revision 1.1 1998/11/09 21:34:47 inaky + * Split the driver.c file into driver-only and configuration issues + * stuff. + * + * + */ + diff -Naur linux.225/drivers/uusbd/hubd/driver.c linux.225.visws/drivers/uusbd/hubd/driver.c --- linux.225/drivers/uusbd/hubd/driver.c Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/hubd/driver.c Tue Mar 9 14:56:42 1999 @@ -0,0 +1,303 @@ + +/* USB Driver Stack v$Revision: 1.35 $ + * + * (C) 1997-99 by Iñaky Pérez González + * + * Distributed under the terms of the GNU Public License Version 2 + * See files COPYRIGHT and COPYING at the root distribution directory + * + * $Id: driver.c,v 1.35 1999/03/09 22:56:42 inaky Exp $ + * + * Changelog at the bottom + * + * + * Hub Driver - Driver housekeeping + * -------------------------------- + * + * Driver definition and basic code for the Hubs + * + */ + +#include /* spinlock_init() */ +#include /* MOD_*_USE_COUNT */ +#include /* MOD_*_USE_COUNT */ + +#include +#include + +#if defined (CONFIG_USB_HUBD_MODULE) +#include +#endif + +#define GDLF_IDENT "USB-HUBD" +#define GDLF_LOCAL /* Define if want local settings */ +#define GDLF_DEF_LOGLEVEL gdlf_level_top +#define GDLF_ASSERTIONS /* want assertions (#undef if not) */ +#undef GDLF_FNTRACE /* want function traces */ +#define GDLF_LOCATIONS /* want locations in log messages */ +#include + + + /* Driver information */ + +#define NAME /* short!! */ \ + "UUSBD Hub Driver v$Revision: 1.35 $" + +#define COPYRIGHT \ + "(c) 1997-98 Inaky Perez Gonzalez " \ + "" + +#define VENDOR 0 +#define VENDORNAME \ + NULL + +#define PRODUCT 0 +#define DEVICENAME \ + NULL + +#define CLASS HUBD_CLASS +#define CLASSNAME \ + "Hub" + +#define SUBCLASS 0 +#define SUBCLASSNAME \ + NULL + +#define PROTOCOL 0 +#define PROTOCOLNAME \ + NULL + + +ts_usb_driver *hubd_driver = NULL; /* Driver structure */ + +const ts_usb_hub_ops hubd_operations = /* Operations this driver does */ +{ + hubd_schedule_status_change, + hubd_descriptor_get, + hubd_descriptor_set, + hubd_descriptor_fill, + hubd_status_get, + hubd_bus_status_get, + hubd_feature, + hubd_port_feature, + hubd_port_status_get, + hubd_port_reset, + hubd_free +}; + + + /* Initialize the hubd driver + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + * + * Global: + * + * int usb_errno On error, error code. + */ + +int __init hubd_init (void) +{ + int errcode; + + gdlf_fntrace ("hubd_init (void)"); + gdlf_info (NAME "\n"); +#ifdef MODULE + gdlf_info (COPYRIGHT "\n"); +#endif + + hubd_driver = ts_usb_driver_init(); + if (hubd_driver == NULL) + { + usb_errno = -USBE_NO_MEMORY; + return -ENOMEM; + } + + /* Set driver's attributes */ + + hubd_driver->vendor = VENDOR; + hubd_driver->product = PRODUCT; + hubd_driver->class = CLASS; + hubd_driver->subclass = SUBCLASS; + hubd_driver->protocol = PROTOCOL; + + /* Set info */ + + hubd_driver->name = NAME; /* driver name */ + hubd_driver->copyright = COPYRIGHT; /* driver copyright */ + hubd_driver->vendorname = VENDORNAME; /* device's vendor name */ + hubd_driver->productname = DEVICENAME; /* device's name */ + hubd_driver->classname = CLASSNAME; /* class' name */ + hubd_driver->subclassname = SUBCLASSNAME; /* subclass' name */ + hubd_driver->protocolname = PROTOCOLNAME; /* protocol name */ + + hubd_driver->config = hubd_config; /* config method */ + hubd_driver->unconfig = hubd_unconfig; /* unconfig method */ + ts_snode_ref (&hubd_driver->snode); /* we hold a reference to it */ + + /* Register the driver */ + + errcode = usb_drv_register (hubd_driver); /* register driver */ + if (errcode) + { + gdlf_err ("Cannot register UUSBD Hub Driver: " + "errno/usb %d/%d\n", + errcode, usb_errno); + if (hubd_driver->snode.next == NULL) + { + ts_usb_driver_clean (hubd_driver); + usb_kfree (hubd_driver); + } + return errcode; + } + + return 0; +} + + + /* Release the hubd driver + * + * Do what is needed to ensure the use count of the driver is + * zero so it can be unloaded from the kernel. What we got to do + * is to call the driver use release function and then unconfigure + * all hubs which still use this driver. + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + */ + + +int hubd_release (void) +{ + ts_snode *itr, *next; + + gdlf_fntrace ("hubd_release (void)"); + + usb_drv_release (hubd_driver); /* release devices using us */ + + /* + * Now try to release all devices which might be using us + * indirectly by unreferencing them + */ + + itr = ts_slist_head (&hubd_driver->uselist); + while (itr) + { + next = ts_slist_next (itr); + ts_snode_unref (itr, NULL); + itr = next; + } + + /* + * Ok, if there still are people on the list, it means some + * failed, so we'll do it in the rude way. + */ + + itr = ts_slist_head (&hubd_driver->uselist); + if (itr) + gdlf_warning ("Some devices neglected to release their " + "use of the hub driver. Will have to use " + "the rude way. Expect inconsistencies\n"); + while (itr) + { + next = ts_slist_next (itr); + usb_drv_release_use (hubd_driver, (ts_usb_drv_use*)itr, NULL); + itr = next; + } + + return 0; +} + + + /* Shutdown the hub driver + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + */ + +int hubd_shutdown (void) +{ + gdlf_fntrace ("hubd_shutdown()"); + + hubd_release(); + ts_snode_unref (&hubd_driver->snode, NULL); + + /* + * We'll ignore the error if it cannot be found on the list, + * as it may happend that when the initialization fails, the + * hub driver is not registered, and thus there's no need to + * unregister it :) + */ + + return usb_drv_unregister (hubd_driver); +} + + + /* Add/remove a reference to the driver + * + * This function is used to tell the hub driver if we are or not + * using any of it's data structures or functions. When we take a + * pointer to any of the driver's function in the operations + * structure, we must reference (use) it, so we call this with a + * positive argument. When we are done using them, we call it with + * a negative argument. + * + * Parameters: + * + * ts_usb_hub* Pointer to the hub with which we are using + * the driver. + * + * __u8 Positive for ONE reference, negative for ONE + * unreference. If zero, return use count. + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + */ + +int hubd_reference (ts_usb_hub* hub, int no) +{ + gdlf_fntrace ("hubd_reference (0x%p, %d)", hub, no); + + if (no > 0) /* reference */ + MOD_INC_USE_COUNT; /* module's too */ + else if (no < 0) /* unreference */ + MOD_DEC_USE_COUNT; /* module's too */ + + return usb_drv_reference (hubd_driver, &hub->snode, no); +} + + + /* Modular stuff */ + +#ifdef MODULE + +int init_module (void) +{ + return hubd_init(); +} + +void cleanup_module (void) +{ + hubd_shutdown(); + return; +} + +#endif + +/* Log: + * + * $Log: driver.c,v $ + * Revision 1.35 1999/03/09 22:56:42 inaky + * Trimmed logs. + * + * Revision 1.34 1999/02/07 01:37:39 inaky + * Remove some useless messages and make it shorter :) + * + * Revision 1.33 1998/12/12 02:44:44 inaky + * Removed traces. + */ + diff -Naur linux.225/drivers/uusbd/hubd/hkeep.c linux.225.visws/drivers/uusbd/hubd/hkeep.c --- linux.225/drivers/uusbd/hubd/hkeep.c Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/hubd/hkeep.c Tue Mar 9 14:57:17 1999 @@ -0,0 +1,71 @@ + +/* USB Driver Stack v$Revision: 1.21 $ + * + * (C) 1997-99 by Iñaky Pérez González + * + * Distributed under the terms of the GNU Public License Version 2 + * See files COPYRIGHT and COPYING at the root distribution directory + * + * $Id: hkeep.c,v 1.21 1999/03/09 22:57:17 inaky Exp $ + * + * Changelog at the bottom + * + * Hub driver - Class structures housekeeping + * ------------------------------------------ + */ + +#define __NO_VERSION__ /* We just want MOD_*_USE_COUNT() */ +#include /* MOD_*_USE_COUNT() */ +#include /* locks */ + +#include +#include + +#define GDLF_IDENT "USB-HUBD" +#define GDLF_LOCAL /* Define if want local settings */ +#define GDLF_DEF_LOGLEVEL 9 +#define GDLF_ASSERTIONS /* want assertions (#undef if not) */ +#undef GDLF_FNTRACE /* want function traces */ +#define GDLF_LOCATIONS /* want locations in log messages */ +#include + + + /* Release a devices's usage of the hub driver + * + * Parameters: + * + * ts_usb_hub* Pointer to the hub struct to free. + * + * Returns: + * + * int 0 if ok, < 0 errno code on error. + * + * Global: + * + * int usb_errno on error, set to -USBE_*, else unmodified. + * + * int usb_hub_errno on error, set to -USBE_*, else unmodified. + */ + +int hubd_free (ts_usb_hub* hub) +{ + gdlf_fntrace ("hubd_free (0x%p)", hub); + gdlf_aassert (hub != NULL, return -EINVAL); +#ifndef HUBD_UNREF_WORKS + hubd_reference (hub, -1); +#endif + return 0; +} + + +/* Log: + * + * $Log: hkeep.c,v $ + * Revision 1.21 1999/03/09 22:57:17 inaky + * Trimmed logs, added capability to have the driver staying in + * zero-reference count. + * + * Revision 1.20 1998/12/12 02:44:53 inaky + * Removed traces. + */ + diff -Naur linux.225/drivers/uusbd/hubd/hubd-symtab.c linux.225.visws/drivers/uusbd/hubd/hubd-symtab.c --- linux.225/drivers/uusbd/hubd/hubd-symtab.c Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/hubd/hubd-symtab.c Sun Apr 4 17:40:23 1999 @@ -0,0 +1,79 @@ + +/* USB Driver Stack v$Revision: 1.7 $ + * + * (C) 1997-99 by Iñaky Pérez González + * + * Distributed under the terms of the GNU Public License Version 2 + * See files COPYRIGHT and COPYING at the root distribution directory + * + * $Id: hubd-symtab.c,v 1.7 1999/04/05 00:40:23 inaky Exp $ + * + * Changelog at the bottom + * + * + * Hub driver symbol table export + * ------------------------------ + * + * Here we export all the symbols which will be needed by the rest of + * the modules to use us. + */ + + +#include +#define __NO_VERSION__ +#include +#include + + /* driver.c */ + +EXPORT_SYMBOL(hubd_driver); +EXPORT_SYMBOL(hubd_operations); +EXPORT_SYMBOL(hubd_init); +EXPORT_SYMBOL(hubd_release); +EXPORT_SYMBOL(hubd_shutdown); +EXPORT_SYMBOL(hubd_config); +EXPORT_SYMBOL(hubd_unconfig); +EXPORT_SYMBOL(hubd_reference); + + + /* hkeep.c */ + +EXPORT_SYMBOL(hubd_free); + + /* requests.c */ + +EXPORT_SYMBOL(hubd_descriptor_get); +EXPORT_SYMBOL(hubd_descriptor_set); +EXPORT_SYMBOL(hubd_descriptor_fill); +EXPORT_SYMBOL(hubd_status_get); +EXPORT_SYMBOL(hubd_bus_status_get); +EXPORT_SYMBOL(hubd_feature); + + + /* ports.c */ + +EXPORT_SYMBOL(hubd_port_feature); +EXPORT_SYMBOL(hubd_port_status_get); +EXPORT_SYMBOL(hubd_port_reset); + + +/* Log: + * + * $Log: hubd-symtab.c,v $ + * Revision 1.7 1999/04/05 00:40:23 inaky + * Trimmed logs, updated dates and moved to new usb_pipe_*() semantics + * + * Revision 1.6 1998/11/14 17:20:34 inaky + * Moved the include files to uusbd/include/uusbd, to ease integration + * into the Linux kernel. + * + * Revision 1.5 1998/06/21 20:08:21 inaky + * Added missing symbols and rm'd unused ones. + * + * Revision 1.4 1998/06/20 21:55:18 inaky + * Massive changes to split the old monolithic hubd driver into a hub + * manager (hub wrappers and daemon) and a dynamic driver, which can be + * replaced and its different parts reused. + */ + + diff -Naur linux.225/drivers/uusbd/hubd/ports.c linux.225.visws/drivers/uusbd/hubd/ports.c --- linux.225/drivers/uusbd/hubd/ports.c Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/hubd/ports.c Sun Apr 4 17:40:24 1999 @@ -0,0 +1,228 @@ + +/* USB Driver Stack v$Revision: 1.18 $ + * + * (C) 1997-99 by Iñaky Pérez González + * + * Distributed under the terms of the GNU Public License Version 2 + * See files COPYRIGHT and COPYING at the root distribution directory + * + * $Id: ports.c,v 1.18 1999/04/05 00:40:24 inaky Exp $ + * + * Changelog at the bottom + * + * + * HUB Driver + * ---------- + * + * Code for making standard requests to the hubs' ports + */ + +#include +#include + +#define GDLF_IDENT "USB-HUBD" +#define GDLF_LOCAL /* Define if want local settings */ +#define GDLF_DEF_LOGLEVEL 9 +#define GDLF_ASSERTIONS /* want assertions (#undef if not) */ +#undef GDLF_FNTRACE /* want function traces */ +#define GDLF_LOCATIONS /* want locations in log messages */ +#include + + + /* Dirty-work function for hubd_port_feature_*() + * + * THIS FUNCTION IS FOR INTERNAL USE, DO NOT CALL IT DIRECTLY + * + * Parameters: + * + * ts_usb_hub* Pointer to hub structure + * + * __u8 Port number + * + * e_usb_featsel Feature + * + * e_usb_req USB request code + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + */ + +int hubd_port_feature (ts_usb_hub* hub, __u8 port, + e_usb_featsel feature, e_usb_req request) +{ + ssize_t errcode; + ts_usb_request req; + + gdlf_fntrace ("hubd_port_feature (0x%p, %u, %u, %u)", + hub, port, feature, request); + gdlf_aassert (hub != NULL, return -EINVAL); + gdlf_aassert (port < hub->ports, return -EINVAL); + + req.bmreqtype = 0x23; + req.request = request; + req.value = feature; + req.index = port + 1; + + read_lock (&hub->device->msnode.lock); + errcode = usb_request_dataless (hub->device, &req, + "hub port feature change"); + if (errcode < 0) + gdlf_err ("Cannot change hub port feature; request failed: " + "errno/usb %d/%d\n", errcode, usb_errno); + read_unlock (&hub->device->msnode.lock); + return errcode; +} + + + /* Get the port status, as well as the status bits which have + * experienced a change. On the lower word are stored the status + * bits and in the higher word the status change bits. You can use + * the #defined masks USB_PORT_STAT_* for the status bits and + * USB_PORT_STAT_C_* for the status change bits. + * + * To acknowledge the changes reported with this function [most + * of them], use the usb_port_feature_clear() function. + * + * NOTE: all the values are in host order, though USB uses little + * endian. + * + * Compliance: USB Spec 1.0 - 11.12.2.6 + * + * Parameters: + * + * ts_usb_hub* Pointer to the hub structure. If NULL, -EINVAL + * will be returned. + * + * __u8 Port number. + * + * Returns: + * + * __s32 If > 0, status code (and with HUBD_PORT_STAT_* to + * get the bits) [FIXME: things may get hairy if + * sometime someone decides to use bit 31 for + * status ...]. On error, <0 errno code. + */ + +__s32 hubd_port_status_get (ts_usb_hub* hub, __u8 port) +{ + int errcode; + ts_usb_request req; + __u32 status; + + gdlf_fntrace ("hubd_port_status_get (0x%p, %u)", hub, port); + gdlf_aassert (hub != NULL, return -EINVAL); + gdlf_aassert (port < hub->ports, return -EINVAL); + + req.bmreqtype = 0xa3; + req.request = e_usb_hub_req_get_status; + req.value = 0; + req.index = port + 1; + req.length = sizeof (status); + + read_lock (&hub->device->msnode.lock); + errcode = usb_request_data (hub->device, &req, &status, + "get port status"); + if (errcode < 0) + gdlf_err ("Cannot get port status; request failed: " + "errno/usb %d/%d\n", errcode, usb_errno); + read_unlock (&hub->device->msnode.lock); + + /* The hub manager updates the port structure */ + + return errcode < 0? errcode : le32_to_cpu (status); +} + + + /* Reset a hub's port. + * + * This function will reset a USB port, blocking [interruptibly] + * until the reset is over. FIXME: Must use some sort of wait + * queuing here; adding a pointer field to the port structure to + * the wait queue. + * + * Parameters: + * + * ts_usb_hub* Pointer to the hub structure. If NULL, -EINVAL + * will be returned. + * + * __u8 Number of the port to reset. -ENODEV if the + * port doesn't exist. + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + */ + +#define USB_RESET_WAIT_RETRIES 10 + +int hubd_port_reset (ts_usb_hub* hub, __u8 port) +{ + int errcode, cnt; + ts_usb_port *pport; + + gdlf_fntrace ("hubd_port_reset (0x%p, %u)", hub, port); + + pport = &hub->port[port]; + + /* Request the reset */ + + pport->reset = 1; + errcode = usb_port_feature_set (hub, port, e_usb_port_fes_reset); + if (errcode < 0) + { + gdlf_err ("Error resetting port %u of hub 0x%p, " + "device (%d %d): " + "errno/usb %d/%d\n", + port, hub, hub->host->addr, + hub->device->addr, + errcode, usb_errno); + return errcode; + } + + /* Wait 10ms, as stated by USB 1.0 Spec 11.6.2 */ + + cnt = 0; + while (cnt < USB_RESET_WAIT_RETRIES) + { + usb_waitms (USB_PORT_RESET_TIME); + if (usb_port_status_get (hub, port) + & USB_PORT_STAT_C_RESET) + break; + cnt++; + } + + /* FIXME: don't check return code? should be clear, shouldn't it? */ + usb_port_feature_clear (hub, port, e_usb_port_fes_c_reset); + + if (cnt >= USB_RESET_WAIT_RETRIES) /* not resetted? */ + { + gdlf_err ("Error resetting port %u of hub 0x%p (%d -1): " + "reset process was interrupted or not completed\n", + port, hub, hub->host->addr); + usb_errno = -USBE_PORT_RESET_INT; + write_unlock (&hci->snode.lock); + return -ENOMEDIUM; + } + + return 0; +} + + +/* Log: + * + * $Log: ports.c,v $ + * Revision 1.18 1999/04/05 00:40:24 inaky + * Trimmed logs, updated dates and moved to new usb_pipe_*() semantics + * + * Revision 1.17 1999/04/01 00:16:36 inaky + * *** empty log message *** + * + * Revision 1.16 1998/12/12 02:45:22 inaky + * Fixed itchy bits [thx Paul]. + * + * Revision 1.15 1998/11/14 17:20:35 inaky + * Moved the include files to uusbd/include/uusbd, to ease integration + * into the Linux kernel. + */ + diff -Naur linux.225/drivers/uusbd/hubd/requests.c linux.225.visws/drivers/uusbd/hubd/requests.c --- linux.225/drivers/uusbd/hubd/requests.c Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/hubd/requests.c Sun Apr 4 17:40:25 1999 @@ -0,0 +1,503 @@ + +/* USB Driver Stack v$Revision: 1.18 $ + * + * (C) 1997-99 by Iñaky Pérez González + * + * Distributed under the terms of the GNU Public License Version 2 + * See files COPYRIGHT and COPYING at the root distribution directory + * + * $Id: requests.c,v 1.18 1999/04/05 00:40:25 inaky Exp $ + * + * Changelog at the bottom + * + * + * HUB Driver + * ---------- + * + * Code for making standard requests to the hubs + */ + +#include +#include + +#define GDLF_IDENT "USB-HUBD" +#define GDLF_LOCAL /* Define if want local settings */ +#define GDLF_DEF_LOGLEVEL 9 +#define GDLF_ASSERTIONS /* want assertions (#undef if not) */ +#undef GDLF_FNTRACE /* want function traces */ +#define GDLF_LOCATIONS /* want locations in log messages */ +#include + + + /* Get the hub descriptor. + * + * Compliance: USB Spec 1.0 11.12.2.4 + * + * Parameters: + * + * ts_usb_hub* Pointer to hub structure. + * + * __u8 Descriptor index. Normally zero. + * + * void* Pointer to the buffer. + * + * size_t Size of the buffer for the descriptor + * + * Returns: + * + * ssize_t Bytes readen if ok [excluding request + * phase's], errno code < 0 on error. Note that + * no more than size_t bytes will be readen. Is + * up to the caller to determine if the + * descriptor has been fully read. + * + * Global: + * + * int usb_errno On error, error code. + */ + +ssize_t hubd_descriptor_get (ts_usb_hub* hub, __u8 index, + void* data, size_t size) +{ + int errcode; + ts_usb_request req; + + gdlf_fntrace ("hubd_descriptor_get (0x%p, %u, 0x%p, %u)", + hub, index, data, size); + + req.bmreqtype = 0xa0; + req.request = e_usb_req_get_descriptor; + req.value = ((e_usb_desc_hub & 0xff) << 8) | index; + req.index = 0; + req.length = size; + + read_lock (&hub->device->msnode.lock); + errcode = usb_request_data (hub->device, &req, data, + "get hub descriptor"); + if (errcode < 0) + gdlf_err ("Cannot get hub descriptor; request failed: " + "errno/usb %d/%d\n", errcode, usb_errno); + read_unlock (&hub->device->msnode.lock); + return errcode; +} + + + /* Set a hub's descriptor + * + * Overwrites the previous upon succesful reception of the new + * one. Any of the hub's available descriptors may be overwritten, + * specifying it's type and it's index number. However, not all + * hubs support this operation, as this request is optional and + * writes data to a class-specific descriptor. + * + * Compliance: USB Spec 1.0 11.12.2.7 + * + * Parameters: + * + * ts_usb_hub* Pointer to the hub structure. If NULL, -EINVAL + * will be returned. + * + * __u8 Descriptor index. + * + * const void* Pointer to the descriptor data in little + * endian format. If NULL, -EINVAL will be + * returned. + * + * size_t Length of the descriptor data. If 0, -EINVAL + * will be returned. + * + * Returns: + * + * ssize_t Bytes transmited [excluding request phase's] + * or errno code < 0 on error. + * + * Global: + * + * int usb_errno On error, error code. + */ + +ssize_t hubd_descriptor_set (ts_usb_hub* hub, __u8 index, + const void* data, size_t size) +{ + int errcode; + ts_usb_request req; + + gdlf_fntrace ("hubd_descriptor_set (0x%p, %u, 0x%p, %u)", + hub, index, data, size); + + req.bmreqtype = 0x20; + req.request = e_usb_req_set_descriptor; + req.value = ((e_usb_desc_hub & 0xff) << 8) | index; + req.index = 0; + req.length = size; + + write_lock (&hub->device->msnode.lock); + errcode = usb_request_data (hub->device, &req, (void*)data, + "set hub descriptor"); + if (errcode < 0) + gdlf_err ("Cannot set hub descriptor; request failed: " + "errno/usb %d/%d\n", errcode, usb_errno); + write_unlock (&hub->device->msnode.lock); + return errcode; +} + + + /* Dirty-work function for hubd_feature_*() + * + * THIS FUNCTION IS FOR INTERNAL USE, DO NOT CALL IT DIRECTLY + * + * Parameters: + * + * ts_usb_hub* Pointer to hub structure + * + * e_usb_featsel Feature + * + * e_usb_req USB request code + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + * + * Global: + * + * int usb_errno On error, error code. + */ + +int hubd_feature (ts_usb_hub* hub, e_usb_featsel feature, e_usb_req request) +{ + ssize_t errcode; + ts_usb_request req; + + gdlf_fntrace ("hubd_feature (0x%p, %u, %u)", + hub, feature, request); + gdlf_aassert (hub != NULL, return -EINVAL); + + req.bmreqtype = 0x20; + req.request = request; + req.value = feature; + req.index = 0; + + write_lock (&hub->device->msnode.lock); + errcode = usb_request_dataless (hub->device, &req, + "hub feature change"); + if (errcode < 0) + gdlf_err ("Cannot change hub feature; request failed: " + "errno/usb %d/%d\n", errcode, usb_errno); + write_unlock (&hub->device->msnode.lock); + return errcode; +} + + + /* Get hub status and change bits + * + * The data is returned in 32 bits, being testable with the + * #defined masks HUBD_STATUS_* for the status bits and + * HUBD_STATUS_C_* for the status change bits. + * + * Compliance: USB Spec 1.0 11.12.2.5 + * + * Parameters: + * + * ts_usb_hub* Pointer to the hub structure. If NULL, -EINVAL + * will be returned. + * + * Returns: + * + * __s32 If > 0, status code (and with HUBD_STAT_* to + * get the bits) [FIXME: things may get hairy if + * sometime someone decides to use bit 31 for + * status ...]. On error, <0 errno code. + */ + +__s32 hubd_status_get (ts_usb_hub* hub) +{ + int errcode; + ts_usb_request req; + __u32 status; + + gdlf_fntrace ("hubd_status_get (0x%p)", hub); + gdlf_aassert (hub != NULL, return -EINVAL); + + req.bmreqtype = 0xa0; + req.request = e_usb_hub_req_get_status; + req.value = 0; + req.index = 0; + req.length = sizeof (status); + + read_lock (&hub->device->msnode.lock); + errcode = usb_request_data (hub->device, &req, &status, + "get hub status"); + if (errcode < 0) + gdlf_err ("Cannot get hub status; request failed: " + "errno/usb %d/%d\n", errcode, usb_errno); + read_unlock (&hub->device->msnode.lock); + return errcode < 0? errcode : le32_to_cpu (status); +} + + + /* Read the status of the bus + * + * This function will read the bus status on fiven port as + * sampled at the last EOF2 hub state. It will be returned on bits + * 0 and 1 of the return value if > 0. You can then use the mask + * values USB_HUB_BUS_STAT_DP and USB_HUB_BUS_STAT_DN to sample the + * values of the D- and D+ lines. + * + * NOTE: This is a very lowlevel function, intended as a debugging + * aid. + * + * Compliance: USB Spec 1.0 - 11.12.2.3 + * + * Parameters: + * + * ts_usb_hub* Pointer to the hub structure. If NULL, -EINVAL + * will be returned. + * + * __u8 Port number. + * + * Returns: + * + * __s8 > 0 if ok, encoding the bus state (and with + * USB_HUB_BUS_STAT_* to get the bits). <0 errno + * code on error. If the hub doesn't support this + * operation, it will answer with an stall and + * return. The code returned will be -EOPNOTSUPP. + */ + +__s8 hubd_bus_status_get (ts_usb_hub* hub, __u8 port) +{ + int errcode; + ts_usb_request req; + __u8 status; + + gdlf_fntrace ("hubd_bus_status_get (0x%p, %u)", hub, status); + gdlf_aassert (hub != NULL, return -EINVAL); + gdlf_aassert (port < hub->ports, return -EINVAL); + + req.bmreqtype = 0xa3; + req.request = e_usb_req_get_status; + req.value = 0; + req.index = port+1; + req.length = sizeof (status); + + read_lock (&hub->device->msnode.lock); + errcode = usb_request_data (hub->device, &req, &status, + "get bus status"); + if (errcode < 0) + gdlf_err ("Cannot get bus status; request failed: " + "errno/usb %d/%d\n", errcode, usb_errno); + read_unlock (&hub->device->msnode.lock); + return errcode < 0? errcode : status; +} + + + /* Initializes a hub control structure from a Hub Descriptor + * + * It will read in the descriptor, parse it, and fill in the + * structure, allocating space for it as needed. The structure + * will hold data which must be freed with ts_usb_hub_free() before + * usb_kfree()ing the structure. + * + * Parameters: + * + * ts_usb_hub* Pointer to hub structure to fill in. + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + */ + +int hubd_descriptor_fill (ts_usb_hub* hub) +{ + int errcode; + ts_usb_hub_desc *desc; + ts_usb_desc_head head; + + gdlf_fntrace ("ts_usb_hub_init_desc (0x%p)", hub); + gdlf_aassert (hub != NULL, return -EINVAL); + + /* get the header, enough to get the full length */ + + errcode = hubd_descriptor_get (hub, 0, &head, sizeof (head)); + if (errcode < 0) + { + gdlf_err ("Error reading " + "hub 0x%p (%u %u)'s descriptor head: " + "errno/usb %d/%d\n", + hub, hub->host->addr, hub->device->addr, + errcode, usb_errno); + return errcode; + } + + /* check for consistency on descriptor */ + + if (head.bDescriptorType != e_usb_desc_hub) + { + gdlf_err ("Incorrect descriptor passed as hub descriptor\n"); + return -ENODATA; /* FIXME: errno code? */ + } + + /* alloc mem for the descriptor */ + + desc = usb_kmalloc (head.bLength * sizeof (__u8), + GFP_KERNEL); + if (desc == NULL) + { + gdlf_err ("Failed to allocated %d bytes to store " + "hub 0x%p (%u %u)'s descriptor\n", + head.bLength * sizeof (__u8), hub, + hub->host->addr, hub->device->addr); + return -ENOMEM; + } + + /* get the descriptor */ + + errcode = hubd_descriptor_get (hub, 0, desc, + head.bLength * sizeof (__u8)); + if (errcode < 0) + { + gdlf_err ("Error reading " + "hub 0x%p (%u %u)'s descriptor: " + "errno/usb %d/%d\n", + hub, hub->host->addr, hub->device->addr, + errcode, usb_errno); + usb_kfree (desc); + return errcode; + } + + /* Ok, fill in the data */ + + hub->ports = desc->bNbrPorts; + hub->port = ts_usb_port_a_init (hub->ports); + if (hub->port == NULL) + { + ts_usb_hub_release (hub); + usb_kfree (desc); + return -ENOMEM; + } + hub->pwrontime = desc->bPwrOn2PwrGood; + hub->maxcurrent = desc->bHubContrCurrent; + + hub->power = (le16_to_cpu (desc->wHubCharacteristics) + | USB_HUB_CRTS_PWR_CTL_MASK); + hub->compound = (le16_to_cpu (desc->wHubCharacteristics) + | USB_HUB_CRTS_COMPD_MASK)? 1 : 0; + hub->overc_prot = (le16_to_cpu (desc->wHubCharacteristics) + | USB_HUB_CRTS_CURRENT_MASK) + >> USB_HUB_CRTS_CURRENT_MASK_S; + + /* Initialize the ports' data */ + +#warning FIXME: test this block, guess it wont work the first time + + { + int byte; /* byte counter */ + int port, top; /* port counter, top */ + int bit; /* bit counter */ + unsigned char bits1, bits2; /* Data for each byte of the bit arrays */ + + for (port = byte = 0, top = hub->ports; port < top; byte++) + { + bits1 = desc->PortData[byte]; /* Device removable array */ + bits2 = desc->PortData[byte + top]; /* Power Ctl Mask array */ + for (bit = 0; + bit < sizeof (char) && port < top; + port++, bit++, bits1 >>= 1, bits2 >>= 1) + { + if (byte == 0 && port == 0) /* This one is reserved */ + continue; + hub->port[port].removable = bits1 & 0x1; + hub->port[port].pwrctl = bits2 & 0x1; + } + } + } + + usb_kfree (desc); + return 0; +} + + + /* Schedule a read from the hub's status change endpoint + * + * If error re-scheduling, we take the most radical option, to + * reset the hub directly. However, FIXME, this is quite + * radical. Should think of a possible better way. + * + * Note this function _will_ complain itself, so the caller has + * to do nothing in case of error but raise it on the call chain + * [if needed]. + * + * Parameters: + * + * ts_hubd* Pointer to the hub structure we want to + * schedule with. + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + * + * Global: + * + * int usb_errno On error, error code. + * + * int hubd_errno On error, error code. + */ + +int hubd_schedule_status_change (ts_usb_hub* hub) +{ + int errcode; + + gdlf_fntrace ("hubd_schedule_status_change (0x%p)", hub); + + if (hub->tr.status >= e_usb_tr_status_ok) + usb_tr_reset (&hub->tr); + + errcode = usb_tr_run (&hub->tr); + if (errcode < 0) + { + gdlf_err ("Error runing status change read for " + "hub 0x%p (%d %d): errno/usb_errno %d/%d\n", + hub, hub->host->addr, hub->device->addr, + hub->tr.errno, hub->tr.usb_errno); + +#warning FIXME: do some more retries, there may be some timing issues related to hubs + + /* + * FIXME: see msg ... for the timing issues stuff + * + * From: Reid Augustin + * To: inaky@peloncho.fis.ucm.es + * Subject: Re: [linux-usb] Self powered hub behaviours on local power loose? + * Date: Tue, 07 Apr 1998 12:32:37 -0700 (PDT) + * + * We can only reset if we aren't configuring the hub, as + * we would start a reentrancy. If configuring [aka, + * called from hubd_config()] and fails, the configuration + * process will fail, and will be more or less the same. + */ + + if (!hub->configuring) + usb_device_reset (hub->device); + return errcode; + } + return 0; +} + + +/* Log: + * + * $Log: requests.c,v $ + * Revision 1.18 1999/04/05 00:40:25 inaky + * Trimmed logs, updated dates and moved to new usb_pipe_*() semantics + * + * Revision 1.17 1998/12/12 02:45:42 inaky + * Fixed itchy bits [thx Paul]. + * + * Revision 1.16 1998/11/26 21:58:35 inaky + * Renamed all the ts_usb_open stuff and friends to use _pipe_. + * + * Revision 1.15 1998/11/14 17:20:36 inaky + * Moved the include files to uusbd/include/uusbd, to ease integration + * into the Linux kernel. + */ + diff -Naur linux.225/drivers/uusbd/hubm-generic.c linux.225.visws/drivers/uusbd/hubm-generic.c --- linux.225/drivers/uusbd/hubm-generic.c Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/hubm-generic.c Sun Apr 4 17:31:34 1999 @@ -0,0 +1,309 @@ + +/* USB Driver Stack v$Revision: 1.15 $ + * + * (C) 1997-99 by Iñaky Pérez González + * + * $Id: hubm-generic.c,v 1.15 1999/04/05 00:31:34 inaky Exp $ + * + * Distributed under the terms of the GNU Public License Version 2 + * See files COPYRIGHT and COPYING at the root distribution directory + * + * Changelog at the bottom + * + * + * Hub manager generic code + * ------------------------ + * + */ + +#include +#include +#include +#include +#include "hubm.h" + +#define GDLF_IDENT "USB-HUBM" +#define GDLF_LOCAL /* Define if want local settings */ +#define GDLF_DEF_LOGLEVEL gdlf_level_top +#define GDLF_ASSERTIONS /* want assertions (#undef if not) */ +#undef GDLF_FNTRACE /* want function traces */ +#define GDLF_LOCATIONS /* want locations in log messages */ +#include + + + /* Allocates and initializes to a known state a ts_usb_hub* + * structure. + * + * Returns: + * ts_usb_hub* Pointer to newly allocated hub structure. Must be + * freed with usb_kfree(). + */ + +ts_usb_hub* ts_usb_hub_init (void) +{ + ts_usb_hub* class; + + gdlf_fntrace ("ts_usb_hub_init()"); + class = usb_kmalloc (sizeof (ts_usb_hub), GFP_KERNEL); + if (class == NULL) + { + gdlf_err ("Cannot allocate space for a " + "ts_usb_hub structure\n"); + return NULL; + } + ts_usb_hub_clean (class); + return class; +} + + + /* Free a ts_usb_hub structure's contents. Checks for the magic + * number being ok. Remember that the structure iself is not + * freed, just it's contents. + * + * Parameters: + * + * ts_usb_hub* Pointer to the hub structure to free. + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + * + */ + +void ts_usb_hub_release (ts_usb_hub* hub) +{ + gdlf_fntrace ("ts_usb_hub_release (0x%p)", hub); + gdlf_aassert (hub != NULL, return); + + if (gdlf_c0assert (hub->snode.dtor.fn == (tf_dtor)usb_hub_destroy)) + { + gdlf_assert (hub->host == NULL); + gdlf_assert (hub->device == NULL); + } + + if (hub->port) + { + ts_usb_port_a_release (hub->port, hub->ports); + usb_kfree (hub->port); + } + + if (hub->tr.data) + usb_kfree (hub->tr.data); + + ts_usb_pipe_release (&hub->pipe); + ts_usb_tr_release (&hub->tr); + + return; +} + + + /* Creates and initializes a port structure. + * + * Returns: + * + * ts_usb_port* Pointer to port structure. + * + * Global: + * + * int usb_errno On error, error code. + */ + +ts_usb_port* ts_usb_port_init (void) +{ + ts_usb_port* port; + + gdlf_fntrace ("ts_usb_port_init()"); + + port = usb_kmalloc (sizeof (ts_usb_port), GFP_KERNEL); + if (port == NULL) + { + usb_errno = -USBE_NO_MEMORY; + gdlf_err ("No memory to create a port" + "structure\n"); + return NULL; + } + + ts_usb_port_clean (port); + return port; +} + +void ts_usb_port_release (ts_usb_port* port) +{ + gdlf_fntrace ("ts_usb_port_release (0x%p)", port); + gdlf_aassert (port != NULL, return); + + if (port->device) + usb_device_unref (port->device, NULL); + + ts_usb_port_clean (port); + return; +} + + +ts_usb_port* ts_usb_port_a_init (size_t size) +{ + ts_usb_port *top, *ports; + + gdlf_fntrace ("ts_usb_port_a_init (%u)", size); + gdlf_aassert (size != 0, return NULL); + + ports = usb_kmalloc (sizeof (ts_usb_port) * size, GFP_KERNEL); + if (ports == NULL) + { + usb_errno = -USBE_NO_MEMORY; + gdlf_err ("No memory to create a ts_usb_port array\n"); + return NULL; + } + + for (top = ports + size - 1; top >= ports; top--) + { + /* Need braces, this is a macro! */ + ts_usb_port_clean (top); + } + return ports; +} + + +void ts_usb_port_a_release (ts_usb_port* ports, size_t size) +{ + ts_usb_port *top; + + gdlf_fntrace ("ts_usb_port_a_release (0x%p, %u)", ports, size); + gdlf_aassert (ports != NULL, return); + + for (top = ports + size; ports < top; ports++) + ts_usb_port_release (ports); + + return; +} + + +/* Log: + * + * $Log: hubm-generic.c,v $ + * Revision 1.15 1999/04/05 00:31:34 inaky + * Trimmed logs in files where it was too big. Moved the transaction list + * to the endpoints and made these have a list of open descriptors to it, + * not just one [making the foundations for endpoint sharing]. Removed + * the host pointer from the pipe structure, needless. + * + * Renamed khubdd to kusbdd, as it was doing more stuff then hub's + * managing, so it made sense. Added the compile time configuration + * option to disable load on demand of drivers [having to manually load + * all of them at startup to register, then they can be unloaded and will + * be loaded when needed]. + * + * Changed the semantics and simplified usb_pipe_*(). Now the functions + * are pointer (or handle) based, instead of using addresses, what added + * a useless step. + * + * Finally reworked the transaction list to make sense. Now it's divided + * in a linear sequence of states which is more logical and easy to + * keep. It has made much simpler to deal with it. + * + * Revision 1.14 1998/11/26 21:58:03 inaky + * Renamed all the ts_usb_open stuff and friends to use _pipe_. + * + * Revision 1.13 1998/11/14 17:12:39 inaky + * Moved the include files to uusbd/include/uusbd, to ease integration + * into the Linux kernel. + * + * Revision 1.12 1998/11/09 21:21:53 inaky + * Added assertions in function of the degree of initialization of an + * structure. Fixed the hub_release function to release the open and tr + * structures. Moved all device ref/unref to usb_device_[un]ref(). Moved + * all array size parameters to size_t. + * + * Revision 1.11 1998/09/24 15:50:05 inaky + * Moved 'hub_port' to 'port'. + * + * Revision 1.10 1998/09/14 02:28:02 inaky + * Removed the usb_hub_errno variable. + * + * Revision 1.9 1998/08/27 22:13:24 inaky + * Removed traces. + * + * Revision 1.8 1998/08/27 10:48:25 inaky + * Moved ts_*_free() to ts_*_release(), made them return void and severed + * assertions. + * + * Revision 1.7 1998/08/24 02:14:08 inaky + * Removed debug messages. + * + * Revision 1.6 1998/08/19 23:33:02 inaky + * Added debug messages to track memory corruption problems. Still here, + * just in case. + * + * Revision 1.5 1998/08/03 13:22:04 inaky + * Removed debug messages at port clean. + * + * Revision 1.4 1998/07/16 15:59:36 inaky + * Fixed the mess with transactions on device-less hubs. + * + * Revision 1.3 1998/07/14 21:43:49 inaky + * Removed spurios debug info + * + * Revision 1.2 1998/07/12 22:39:53 inaky + * When freeing the array of ports, we got to _free_ it :) Some of the + * debug code _should_ go away someday. + * + * Revision 1.1 1998/06/20 21:54:48 inaky + * Massive changes to split the old monolithic hubd driver into a hub + * manager (hub wrappers and daemon) and a dynamic driver, which can be + * replaced and its different parts reused. + * + * Revision 1.15 1998/04/13 22:18:39 inaky + * Finished most of the hub driver; some updates still needed. + * + * Revision 1.14 1998/02/10 17:41:07 inaky + * Fixed to use ts_[S]snode_[un]ref() + * + * Revision 1.13 1998/02/09 13:42:56 inaky + * Moved all use counts to atomic + * + * Revision 1.12 1998/01/08 12:19:18 inaky + * Added copyright strings to all important files + * + * Revision 1.11 1997/12/31 05:37:40 inaky + * Fixed some craps. + * + * Revision 1.10 1997/12/30 22:30:29 inaky + * Fixed some bugs. + * + * Revision 1.9 1997/12/30 20:14:58 inaky + * Moved to the new lists code. Untested yet. + * + * Revision 1.8 1997/12/29 00:26:14 inaky + * Moving the khubdd to use signals as commands. + * + * Revision 1.7 1997/12/27 17:25:42 inaky + * Finished moving to GDLF. Deprecated usb_printk and __LOCATION__ + * + * Revision 1.6 1997/12/27 02:06:13 inaky + * Moving everything to use the GDLF for logging and debug checkings. + * Removed the global array of USB hosts and moved it to a linked + * list. Added an address field to each USB host controller. + * Removed lots of cruft that were accumulated and useless. Still some + * missing, but may be useful someday. + * + * Revision 1.5 1997/12/13 20:56:37 inaky + * Moving all the documentation to the .c files except the ones for data + * structures and inline functions. Helps making the header files cleaner. + * + * Revision 1.4 1997/12/08 02:41:53 inaky + * Moving the hubd to the new driver style + * + * Revision 1.3 1997/12/06 00:19:51 inaky + * Almost finished the usbd/host, usbd/cfg and a lot of meat from + * usbd/device. Also added the driver definition. Got to polish it yet + * ... + * + * Revision 1.2 1997/11/29 20:21:58 inaky + * Documented and almost fixes the read/write/abort API, documented a + * damn lot and implemented some stuff + * + * Revision 1.1 1997/10/31 05:44:31 inaky + * *** empty log message *** + * + */ + diff -Naur linux.225/drivers/uusbd/hubm-hkeep.c linux.225.visws/drivers/uusbd/hubm-hkeep.c --- linux.225/drivers/uusbd/hubm-hkeep.c Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/hubm-hkeep.c Sun Apr 4 17:31:35 1999 @@ -0,0 +1,600 @@ + +/* USB Driver Stack v$Revision: 1.32 $ + * + * (C) 1997-99 by Iñaky Pérez González + * + * Distributed under the terms of the GNU Public License Version 2 + * See files COPYRIGHT and COPYING at the root distribution directory + * + * $Id: hubm-hkeep.c,v 1.32 1999/04/05 00:31:35 inaky Exp $ + * + * Changelog at the bottom + * + * + * Hub Manager - Driver housekeeping + * -------------------------------- + * + * Driver definition and basic code for the Hubs. + */ + +#include /* spinlock_init() */ + +#include +#include +#include +#include "hubm.h" + +#define GDLF_IDENT "USB-HUBM" +#define GDLF_LOCAL /* Define if want local settings */ +#define GDLF_DEF_LOGLEVEL gdlf_level_top +#define GDLF_ASSERTIONS /* want assertions (#undef if not) */ +#undef GDLF_FNTRACE /* want function traces */ +#define GDLF_LOCATIONS /* want locations in log messages */ +#include + +ts_slist usb_hub_list; + + + /* Detach all devices from a hub + * + * Compliance: USB Spec 1.0 xxxx + * + * Parameters: + * + * type descr + * + * Global: + * + * type name descr + * + * Returns: + * + * type descr + * + * Global: + * + * type name descr + */ + +int usb_hub_detach_devices (ts_usb_hub* hub, __u32 flags) +{ + int errcode; + int cnt; + ts_usb_device *device; + + gdlf_fntrace ("usb_hub_detach_devices (0x%p)", hub); + + for (cnt = 0; cnt < hub->ports; cnt++) + { + device = hub->port[cnt].device; + if (device == NULL) + continue; + + errcode = usb_device_detach (device, flags); + if (errcode < 0) + gdlf_err ("Error detaching device 0x%p (%d %d) " + "from port %u of hub 0x%p (%d %d): " + "errno/usb %d/%d; " + "expect inconsistencies\n", + device, + device->hub->host->addr, + device->addr, + cnt, hub, + hub->host->addr, + hub->device? hub->device->addr : -1, + errcode, usb_errno); + usb_kfree (device); + usb_port_reset (hub, cnt); + } + return 0; +} + + + + /* Initialize the hub manager + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + * + * Global: + * + * int usb_errno On error, error code. + */ + +int usb_hub_init (void) +{ + int errcode; + + gdlf_fntrace ("usb_hub_init (void)"); + + /* Initialize */ + + ts_slist_clean (&usb_hub_list); + spin_lock_init (&dqueue_lock); /* lock init'on */ + memset ((void*)dqueue, 0, /* clean the queue */ + sizeof (struct s_dqueue) * USB_HUB_DQUEUE_SLOTS); + + errcode = usb_hub_startd(); /* start daemon */ + if (errcode) + return errcode; + + return 0; +} + + + /* Release the hub manager + * + * Free and clean all data structs managed by the hub manager. + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + */ + +int usb_hub_release (void) +{ + ts_usb_hub *itr, *next; + + gdlf_fntrace ("usb_hub_release (void)"); + + itr = (ts_usb_hub*) ts_slist_head (&usb_hub_list); + while (itr) + { + next = (ts_usb_hub*) ts_slist_next (&itr->snode); + usb_hub_destroy (itr); + itr = next; + } + return 0; +} + + + /* Shutdown the hub manager + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + */ + +int usb_hub_shutdown (void) +{ + gdlf_fntrace ("usb_hub_shutdown()"); + + /* we'll go over errors ... */ + + usb_hub_release(); + return usb_hub_stopd(); +} + + + /* Unregister an hub + * + * This function will unregister a hub structure from the system, + * following the inverse steps than when registering (this means + * remove the hub from the linked list of hubs), previosuly + * detaching all the pending devices. + * + * Parameters: + * + * ts_usb_hub* Class element to unregister + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + */ + +int usb_hub_unregister (ts_usb_hub* hub) +{ + gdlf_fntrace ("usb_hub_unregister (0x%p)", hub); + + gdlf_aassert (hub != NULL, return -EINVAL); + gdlf_passert (atomic_read (&hub->snode.usecnt) != 0, + "ts_usb_hub 0x%p's reference count is zero!\n", + hub); + + /* Stop scheduling reads (if doing it) */ + + if (hub->operations + && hub->operations->schedule_stch != NULL + && hub->tr.pipe != NULL) + usb_pipe_close (&hub->pipe); + + /* Detach everything */ + + usb_hub_detach_devices (hub, USB_CFG_HUB_DESTROY); + + /* Remove the hub from the hub's list */ + + ts_slist_del (&usb_hub_list, &hub->snode); + return 0; /* bye */ +} + + + /* Register a hub + * + * This function expects a ts_usb_hub structure will all the fields + * filled in but `dtor'. This implies having the pipe member + * open correctly, the tr member set up ready for + * transfers (it's up to the specific hub driver in which state + * must the transaction be; normally you'd have it INSERTED and + * the drivers schedule status change function would just EXECUTE + * it and reset it down from ABORTED, DONE or ERROR to INSERTED + * again to repeat the execution). + * + * Note that filling the `device' pointer means to also increment + * the use count `usecount' of the device structure pointed to by + * that pointer. Also note that an structure with any parameter + * unspecified will be considered invalid, and thus -EINVAL + * returned. + * + * If everything is valid, it then will: + * + * 1. Fill in the snode.dtor member with the usb_hub_unregister() + * function. + * + * 2. append the hub structure to the list of hubs (and increment + * the hub use count), + * + * 3. start scheduling polls on the hub by calling + * usb_hub_schedule_status_chage(). If not supported (returns + * -ENOSYS), then the hub is taken to be polling [root hubs], + * and the responsibility for it is left to the HCD. + * + * Parameters: + * + * ts_usb_hub* Class element to register + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + */ + +int usb_hub_register (ts_usb_hub* hub) +{ + int errcode; + int cnt; + ts_usb_hub *root; + ts_usb_hub *itr; + + gdlf_fntrace ("usb_hub_register (0x%p)", hub); + gdlf_aassert (hub != NULL, return -EINVAL); + + /* + * First of all, we check the depth in the USB tree and beep + * if greater then 5 (See USB Spec 1.0, 7.1.16). We must allow + * a maximum of 5 hub levels, counting the root hub. Note we + * start counting on zero, so five must not be reached. + * + * Instead of keeping a depth count on each hub, each time we + * plug a hub in, we walk back the list until we reach the + * root hub, counting each hub. If we count five, then this + * one is not allowed to be plugged, as we'd violate the USB + * topology as described on USB Spec 1.0 7.1.16. + * + * Note we `blindly' assign itr to itr->device->hub. We know + * that at least, UHCI root hubs have device set as NULL. Ok, + * we can do that, as if itr is the root hub, it'll be catched + * before the assignment and it will not happen. + */ + + read_lock (&hub->host->snode.lock); + root = &hub->host->root; /* huuuh ... loooong :) */ + for (itr = hub, cnt = 0; /* Walk the list back to the root */ + itr != root && cnt < 5; + itr = itr->device->hub, cnt++); + read_unlock (&hub->host->snode.lock); + + if (cnt >= 5) /* out of luck, too many hubs */ + { + /* + * No check for hub->device != NULL, as it is suppossed + * to happen _only_ on root hubs, and they cannot raise + * this error [unless mistake in the code :)]. + */ + gdlf_err ("Cannot add new hub to port " + "%u of hub 0x%p (%d %d): " + "no more than four hubs may " + "be chained (five counting root hub)\n", + hub->device->port, hub->device->hub, + hub->host->addr, + hub->device->hub->device->addr); + return -EMLINK; + } + + /* Set the destructor */ + + write_lock (&hub->snode.lock); + ts_dtor_fill (&hub->snode.dtor, (tf_dtor)usb_hub_destroy); + + /* add it to the list */ + + errcode = ts_slist_prep (&usb_hub_list, &hub->snode); + if (errcode) + { + gdlf_err ("Cannot register hub 0x%p: couldn't " + "add it to the hub's list, errno %d\n", + hub, errcode); + write_unlock (&hub->snode.lock); + return errcode; + } + write_unlock (&hub->snode.lock); + + /* set power policy, power on all ports */ + + for (cnt = 0; cnt < hub->ports; cnt++) + usb_port_feature_set (hub, cnt, e_usb_port_fes_power); + + /* Start scheduling */ + + errcode = usb_hub_schedule_status_change (hub); /* start it */ + if (errcode < 0 && errcode != -ENOSYS) /* any error? */ + { + gdlf_err ("Cannot schedule status change read " + "on hub 0x%p (%d %d): errno/usb %d/%d. " + "Registration failed\n", + hub, hub->host->addr, + hub->device? hub->device->addr : -1, + errcode, usb_errno); + write_lock (&hub->snode.lock); + ts_slist_del (&usb_hub_list, &hub->snode); + write_unlock (&hub->snode.lock); + return errcode; + } + + /* Advertise it */ + + if (hub->device) + gdlf_info ("Hub at device id 0x%08x (%d %d), port %d\n", + hub->device->id, usb_host_addr (hub->device), + usb_dev_addr (hub->device), hub->device->port); + else + gdlf_info ("Root hub at host %d\n", hub->host->addr); + + return 0; +} + + + /* Register a device connected to one of this hub's ports to this + * hub's structures. + * + * This function will be called by usb_device_attach(). It will + * get the hub structure to which we want to attach the device, + * the port number and the device structure. + * + * Then it will point the device->hub to the hub, increment the + * hubs usecount and set device->port. It will also set the + * hub->port[port]->device to device and increment the device use + * count. Now the device has a pointer to the hub and port, and + * the hub knows which device is plugged in that port. + * + * Actually, it should not talk to the device, as the control + * endpoint 0 may not initialized yet. + * + * Parameters: + * + * ts_usb_device* Device structure to attach to the hub. Note + * that the hub is taken from the hub field of + * the ts_usb_device structure. + * + * ts_usb_hub* Hub structure into which we are registering. + * + * __u8 Port number. + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + */ + +int usb_hub_register_device (ts_usb_hub* hub, ts_usb_device* device, + __u8 port) +{ + gdlf_fntrace ("usb_hub_register_device (0x%p, 0x%p, %u)", + device, hub, port); + gdlf_aassert (device != NULL, return -EINVAL); + gdlf_aassert (hub != NULL, return -EINVAL); + gdlf_aassert (port < hub->ports, return -EINVAL); + + write_lock (&device->msnode.lock); + write_lock (&hub->snode.lock); + + device->hub = hub; + ts_snode_ref (&hub->snode); + device->port = port; + + hub->port[port].device = device; + usb_device_ref (device); + + write_unlock (&hub->snode.lock); + write_unlock (&device->msnode.lock); + return 0; +} + + + /* Unregisters a device from a hub + * + * This function undoes what usb_hub_register_device() does. It will + * just unset all the data fields the previous one set, taking + * care of resource counts and cleaning fields. Take into account + * it does NO operation on the USB bus. + * + * Parameters: + * + * ts_usb_device* Device structure to attach to the hub. Note + * that the hub is taken from the hub field of + * the ts_usb_device structure. + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + */ + +int usb_hub_unregister_device (ts_usb_device* device) +{ + ts_usb_hub* hub; + + gdlf_fntrace ("usb_hub_unregister_device (0x%p)", device); + gdlf_aassert (device != NULL, return -EINVAL); + + hub = device->hub; + if (hub == NULL) + { + gdlf_warning ("Cannot unregister device 0x%p, " + "it has no hub!\n", + device); + return -EBADF; + } + + write_lock (&device->msnode.lock); + write_lock (&hub->snode.lock); + + usb_device_unref (device, NULL); + hub->port[device->port].device = NULL; + + ts_snode_unref (&hub->snode, NULL); + device->hub = NULL; + device->port = 0; + + write_unlock (&hub->snode.lock); + write_unlock (&device->msnode.lock); + return 0; +} + + + /* Destroy a hub + * + * Parameters: + * + * ts_usb_hub* Class element to unregister + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + */ + +int usb_hub_destroy (ts_usb_hub* hub) +{ + int cnt; + int errcode; + ts_usb_device *device; + ts_usb_cfel *cfel; + + gdlf_fntrace ("usb_hub_destroy (0x%p)", hub); + gdlf_aassert (hub != NULL, return -EINVAL); + +#warning FIXME: remove all queued events in kusbdd:dqueue for this hub + + ts_snode_ref (&hub->snode); /* evitate it's destruction */ + atomic_inc (&hub->in_progress); + if (atomic_read (&hub->in_progress) > 1) + gdlf_info ("A change is still being processed " + "in hub 0x%p (%d %d); destroying anyway\n", + hub, hub->host->addr, + hub->device? hub->device->addr : -1); + + /* Detach everything [we also do this on unregister...] */ + + usb_hub_detach_devices (hub, USB_CFG_HUB_DESTROY); + + /* Power off all ports */ + + if (hub->power <= 2) /* can we turn ports' power off? */ + { + for (cnt = 0; cnt < hub->ports; cnt++) + { + errcode = usb_port_feature_clear (hub, cnt, e_usb_port_fes_power); + if (errcode < 0) + gdlf_err ("Error powering off port %u " + "of hub 0x%p, device (%d %d): " + "errno/usb %d/%d\n", + cnt, hub, hub->host->addr, + hub->device? hub->device->addr : -1, + errcode, usb_errno); + } + } + + /* + * Leave the cfel unconfigured + * + * Note we'll only do it if there's a device and we have + * to search which cfel it is [thus, using only the + * configuration, interface and alternate setting info if + * configured independently, what I'm not sure if it is + * possible]. + * + * Setting cfel->data to NULL and kfree()ing should be + * done by the caller. + */ + + device = hub->device; /* NOTE THIS ONE!! */ + if (device) + { +#if 0 + if (USB_DEVICE_AG_INDEP (device)) + cfel = &device->pcfg[hub->cfg]->iface[hub->iface] + .aset[hub->aset].cfel; + else + cfel = &device->cfel; + cfel->configured = 0; +#endif + device->cfel.configured = 0; + cfel = &device->pcfg[hub->cfg]->iface[hub->iface] + .aset[hub->aset].cfel; + } + + /* Unregister the hub structure */ + + usb_hub_unregister (hub); /* rm from hub's list */ + + if (hub->host) /* when errors at the very initial stages ... */ + { /* ... things ain't set up */ + usb_host_unref (hub->host, NULL); /* no more refs to host */ + hub->host = NULL; + } + if (device) /* no more refs to dev */ + { + usb_configuration_unref (device->pcfg[hub->cfg]); + usb_device_unref (device, NULL);/* (it may be root!) */ + hub->device = NULL; + } + + if (hub->operations) + usb_hub_free (hub); /* release drivers */ + ts_snode_unref_nd (&hub->snode); + atomic_dec (&hub->in_progress); + /* This is safe, we keep a reference from the structure */ + gdlf_assert_act (ts_snode_unref_nd (&hub->tr.snode)); + ts_usb_hub_release (hub); + /* a destructor must not kfree() it's struct! */ + return 0; +} + +/* Log: + * + * $Log: hubm-hkeep.c,v $ + * Revision 1.32 1999/04/05 00:31:35 inaky + * Trimmed logs in files where it was too big. Moved the transaction list + * to the endpoints and made these have a list of open descriptors to it, + * not just one [making the foundations for endpoint sharing]. Removed + * the host pointer from the pipe structure, needless. + * + * Renamed khubdd to kusbdd, as it was doing more stuff then hub's + * managing, so it made sense. Added the compile time configuration + * option to disable load on demand of drivers [having to manually load + * all of them at startup to register, then they can be unloaded and will + * be loaded when needed]. + * + * Changed the semantics and simplified usb_pipe_*(). Now the functions + * are pointer (or handle) based, instead of using addresses, what added + * a useless step. + * + * Finally reworked the transaction list to make sense. Now it's divided + * in a linear sequence of states which is more logical and easy to + * keep. It has made much simpler to deal with it. + * + * Revision 1.31 1999/02/09 06:14:42 inaky + * Fixed locking code, thanks to Masami Kishida. + * + * Revision 1.30 1999/02/08 15:33:44 inaky + * Added advertisements when a hub is attached. + */ + diff -Naur linux.225/drivers/uusbd/hubm-stch.c linux.225.visws/drivers/uusbd/hubm-stch.c --- linux.225/drivers/uusbd/hubm-stch.c Wed Dec 31 16:00:00 1969 +++ linux.225.visws/drivers/uusbd/hubm-stch.c Sun Apr 4 17:31:36 1999 @@ -0,0 +1,1076 @@ + +/* USB Driver Stack v$Revision: 1.21 $ + * + * (C) 1997-99 by Iñaky Pérez González + * + * Distributed under the terms of the GNU Public License Version 2 + * See files COPYRIGHT and COPYING at the root distribution directory + * + * $Id: hubm-stch.c,v 1.21 1999/04/05 00:31:36 inaky Exp $ + * + * Changelog at the bottom + * + * + * Hub Manager - Response to status changes + * ---------------------------------------- + * + * Functions to deal with the response to status changes from + * hubs. Note that per hub driver / per hub function hooks are + * provided in order to fix quirks. + * + */ + +#warning FIXME: add driver hooks + +#include +#include "hubm.h" /* Internal hubm stuff */ + +#define GDLF_IDENT "USB-HUBM" +#define GDLF_LOCAL /* Define if want local settings */ +#define GDLF_DEF_LOGLEVEL 9 +#define GDLF_ASSERTIONS /* want assertions (#undef if not) */ +#undef GDLF_FNTRACE /* want function traces */ +#define GDLF_LOCATIONS /* want locations in log messages */ +#include + + + /* Handle a hub status change + * + * This function will act in consequence of a hub status + * change. It will obtain the new hub status, and based upon the + * changed bits, act. + * + * Parameters: + * + * ts_hubd* Hub to operate on. + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + * + * Global: + * + * int hubd_errno On error, error code. + */ + +int usb_hub_status_change (ts_usb_hub* hub) +{ + int errcode; + __u32 status; + + /* Get new hub status */ + + status = usb_hub_status_get (hub); + if (status < 0) + { + gdlf_err ("There was an error trying to process a hub " + "status change on hub 0x%p, device (%d %d): " + "cannot get status\n", + hub, hub->host->addr, + hub->device? hub->device->addr : -1); + /* hubd_errno set by hubd_status_get() */ + return status; + } + + /* Process the status change [if any] */ + + errcode = 0; + + if (status & USB_HUB_STATUS_C_LOCAL_PWR) + errcode = usb_hub_local_power_change (hub); + + if (status & USB_HUB_STATUS_C_OVER_CURRENT) + errcode = usb_hub_overcurrent_change (hub); + + /* + * yeah, we loose results, but each function is suppossed to + * to complain adequately. + */ + + return errcode; +} + + + /* Process a hub over current status change + * + * An overcurrent condition has raised/gone if the overcurrent + * change bit is set. + * + * If we have an overcurrent here, it means a global overcurrent. + * Power has been shut off to all ports, so according to the port + * state diagram (USB 1.0 Spec, Figure 11-5, Pag 221), it is like + * having the ports powered off (or disconnected if hub doesn't + * allow power switching). We have to detach the devices, warn of + * the fact and then retry to power them on. This will re-start + * the connection sequence for the devices, as well as it's + * configuration. If any device again causes an overcurrent, this + * will keep on failing until the user notices and removes the + * offending device from the hub. Perhaps we should add a delay + * here, but as the condition won't raise again until the device + * is configured and working, it should be enough. + * + * If 0, the overcurrent condition is gone. This should + * happen as soon as the ports are powered off. + * + * NOTE: here we relay on usb_hub_status_get() having actualized the + * hub status fields (`local_power' and `overcurrent'). + * + * Parameters: + * + * ts_usb_hub* Hub we are handling + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + */ + +int usb_hub_overcurrent_change (ts_usb_hub* hub) +{ + int cnt; /* port counter */ + int errcode; + + gdlf_fntrace ("usb_hub_overcurrent_change (0x%p)", hub); + + if (hub->overcurrent) + { + ts_usb_device *device; + + /* Ok, we have a global overcurrent */ + + gdlf_emerg ("Hub 0x%p, device (%d %d) is " + "in overcurrent; it cannot deliver " + "power to all it's attached devices; " + "detaching them\n", + hub, hub->host->addr, + hub->device? hub->device->addr : -1); + + for (cnt = 0; cnt < hub->ports; cnt++) + { + device = hub->port[cnt].device; + + if (device == NULL) + continue; + + errcode = usb_device_detach (device, + USB_CFG_HUB_OVR_CUR); + if (errcode < 0) + gdlf_err ("Error detaching device 0x%p (%d %d) " + "(because of global overcurrent) from " + "port %u of hub 0x%p, device (%d %d): " + "errno/usb %d/%d; " + "expect inconsistencies\n", + device, device->hub->host->addr, + device->addr, cnt, hub, + hub->host->addr, + hub->device? hub->device->addr : -1, + errcode, usb_errno); + usb_kfree (device); + hub->port[cnt].try = 1; + } + } + else + { + /* + * out of overcurrent condition + * + * We should make here sure that all the ports + * are powered on. We do it on all as it is suppossed it + * was a global overcurrent condition, and this, power was + * shut down to all ports (as indicated on USB Spec 1.0 + * Table 11-14, bit 1). + */ + + gdlf_info ("Hub 0x%p, device (%d %d) has gone out of " + "global overcurrent state\n", + hub, hub->host->addr, + hub->device? hub->device->addr : -1); + + if (hub->power <= 2) /* if we can turn power on ... */ + { + for (cnt = 0; cnt < hub->ports; cnt++) + { + errcode = usb_port_feature_set (hub, cnt, + e_usb_port_fes_power); + if (errcode < 0) + gdlf_err ("Error powering on port %u " + "of hub 0x%p, device (%d %d): " + "errno/usb %d/%d\n", + cnt, hub, hub->host->addr, + hub->device? hub->device->addr : -1, + errcode, usb_errno); + } + usb_waitms (2 * hub->pwrontime); + } + } + + /* Acknowledge the status change */ + + errcode = usb_hub_feature_clear (hub, e_usb_hub_fes_c_over_current); + if (errcode < 0) + { + gdlf_err ("Error acknowledging hub's overcurrent status " + "change to hub 0x%p, device (%d %d): " + "errno/usb %d/%d\n", + hub, hub->host->addr, + hub->device? hub->device->addr : -1, + errcode, usb_errno); + return errcode; + } + return 0; +} + + + /* Handle a local power change on a hub + * + * Here we are faced with a problem. When this function is + * invoked is because the local power supply in a hub has + * transitioned from the lost to the ok state [the good news] or + * from the ok to the lost state [the bad news]. + * + * If the hub is not self powered [hub->device->active->selfpower + * != 0], then this will not happen. This comprobation is + * asserted, as it should not happen, though it'd be a hardware + * problem ... perhaps it should be always done. FIXME. + * + * Ok, then we have this self-powered hub, who delivers at least + * 5 unit loads/port. If local power is lost, I supposse it closes + * current to all ports, as I cannot find on the spec what happens + * exactly, but it could depend on the hub, as some ports may be + * drawing a current amount which is supplied by the bus. + * + * Thus, the approach I'm using is all devices are powered off + * until I find something better [FIXME]. + * + * If it's only selfpowered, then we are lost ... to the + * river. It should signal a disconnect on the port and the port + * change functions would detach it. + * + * NOTE: here we relay on usb_hub_status_get() having actualized the + * hub status fields (`local_power' and `overcurrent'). + * + * Parameters: + * + * ts_usb_hub* Hub we are handling + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + */ + +int usb_hub_local_power_change (ts_usb_hub* hub) +{ + int cnt; /* port counter */ + int errcode; + + gdlf_fntrace ("usb_hub_local_power_change (0x%p)", hub); + + gdlf_apassert (hub->device? hub->device->active->selfpower : 1, + return -EBADF, + "Ein?? Local power change on non self-powered " + "hub 0x%p, device (%d %d)\n", + hub, hub->host->addr, + hub->device? hub->device->addr : -1); + +#warning FIXME: brute force method, should refine + + if (hub->local_power) /* Lost local power? */ + { + /* + * All ports to `power off' state if supported, else to + * `disabled' state. Also we detach the device plugged + * into it, giving a reason. + * + * Note than for gang-power swiching mode, for all ports + * to be powered off, it will happen when we have + * requested all ports to be powered off [after the for + * loop] (USB Spec 1.0 11.12.2.2). + */ + + int feature; /* feature to clear */ + ts_usb_device* device; + + gdlf_emerg ("Hub 0x%p, device (%d %d) has " + "lost it's local power supply\n", + hub, hub->host->addr, + hub->device? hub->device->addr : -1); + + if (hub->power <= 2) /* can we turn ports' power off? */ + feature = e_usb_port_fes_power; + else + feature = e_usb_port_fes_enable; + + for (cnt = 0; cnt < hub->ports; cnt++) + { + device = hub->port[cnt].device; + + if (device == NULL) + continue; + + errcode = usb_device_detach (device, + USB_CFG_HUB_PWR_DN); + if (errcode < 0) + gdlf_err ("Error detaching device 0x%p (%d %d) " + "(because of local power down) from " + "port %u of hub 0x%p, device (%d %d): " + "errno/usb %d/%d; " + "expect inconsistencies\n", + device, device->hub->host->addr, + device->addr, cnt, hub, + hub->host->addr, + hub->device? hub->device->addr : -1, + errcode, usb_errno); + usb_kfree (device); + hub->port[cnt].try = 1; + + errcode = usb_port_feature_clear (hub, cnt, feature); + if (errcode < 0) + gdlf_err ("Error %s on port %u " + "of hub 0x%p, device (%d %d): " + "errno/usb %d/%d\n", + hub->power <= 2? "turning power off " : "disabling", + cnt, hub, hub->host->addr, + hub->device? hub->device->addr : -1, + errcode, usb_errno); + } + } + else /* power is ok */ + { + /* + * Power on all the ports if supported, else leave them at + * their current state [should be disconnected]. + */ + + gdlf_alert ("Hub 0x%p, device (%d %d) has " + "recovered it's local power supply\n", + hub, hub->host->addr, + hub->device? hub->device->addr : -1); + + if (hub->power <= 2) /* can we turn ports' power on? */ + { + for (cnt = 0; cnt < hub->ports; cnt++) + { + errcode = usb_port_feature_set (hub, cnt, + e_usb_port_fes_power); + if (errcode < 0) + gdlf_err ("Error powering on port %u " + "of hub 0x%p, device (%d %d): " + "errno/usb %d/%d\n", + cnt, hub, hub->host->addr, + hub->device? hub->device->addr : -1, + errcode, usb_errno); + } + usb_waitms (2 * hub->pwrontime); + } + } + + /* Acknowledge the status change */ + + errcode = usb_hub_feature_clear (hub, e_usb_hub_fes_c_local_pwr); + if (errcode < 0) + { + gdlf_err ("Error acknowledging hub's local power status " + "change to hub 0x%p, device (%d %d): " + "errno/usb %d/%d\n", + hub, hub->host->addr, + hub->device? hub->device->addr : -1, + errcode, usb_errno); + return errcode; + } + return 0; +} + + + + + + /* The overcurrent status has changed on a port + * + * If the overcurrent bit is set, we have an overcurrent on the + * port; it's power has been shut off. We have to detach the + * device and acknowledge. + * + * I don't know if a change from overcurrent to no overcurrent + * will be reported, as once the port is powered off, the + * overcurrent is over. Thus, when acknowledging, it should clear + * the overcurrent condition and warn again (change) that we have + * no overcurrent, then we'd turn the power back on. + * + * If this doesn't work ... we'll have to change the method. + * + * Parameters: + * + * ts_usb_hub* Hub + * + * __u8 Port number + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + */ + +int port_over_current_change (ts_usb_hub* hub, __u8 port) +{ + int errcode; + + gdlf_fntrace ("port_over_current_change (0x%p, %u)", + hub, port); + + if (hub->port[port].overcurrent) /* we've got overcurrent */ + { + /* check there's a device, jic */ + + if (hub->port[port].device == NULL) + gdlf_info ("Ein?? Overcurrent reported at " + "port %u of hub 0x%p (%d %d) " + "and no device attached\n", + port, hub, + hub->host->addr, + hub->device? hub->device->addr : -1); + else + { + ts_usb_device *device = hub->port[port].device; + + gdlf_emerg ("Device (%d %d) at port %u of " + "hub 0x%p (%d %d) is in " + "overcurrent; detaching it\n", + device->hub->host->addr, + device->addr, port, hub, + hub->host->addr, + hub->device? hub->device->addr : -1); + + /* detach it */ + + errcode = usb_device_detach (device, + USB_CFG_HUB_OVR_CUR); + if (errcode < 0) + gdlf_err ("Error detaching device 0x%p (%d %d) " + "(because of global overcurrent) from " + "port %u of hub 0x%p, device (%d %d): " + "errno/usb %d/%d\n", + device, device->hub->host->addr, + device->addr, port, hub, + hub->host->addr, + hub->device? hub->device->addr : -1, + errcode, usb_errno); + usb_kfree (device); + hub->port[port].try = 1; + } + } + else /* out of overcurrent condition, power it on */ + { + gdlf_info ("Port %u of hub 0x%p (%d %d) got out of " + "overcurrent; powering it on\n", + port, hub, hub->host->addr, + hub->device? hub->device->addr : -1); + + if (hub->power <= 2) /* if we can turn power on ... */ + { + errcode = usb_port_feature_set (hub, port, + e_usb_port_fes_power); + if (errcode < 0) + gdlf_err ("Error powering on port %u " + "of hub 0x%p (%d %d): " + "errno/usb %d/%d\n", + port, hub, hub->host->addr, + hub->device? hub->device->addr : -1, + errcode, usb_errno); + usb_waitms (2 * hub->pwrontime); + } + } + + /* Acknowledge the status change */ + + errcode = usb_port_feature_clear (hub, port, + e_usb_port_fes_c_over_current); + if (errcode < 0) + { + gdlf_err ("Error acknowledging port's overcurrent status " + "change to port %u of hub 0x%p (%d %d): " + "errno/usb %d/%d\n", + port, hub, hub->host->addr, + hub->device? hub->device->addr : -1, + errcode, usb_errno); + return errcode; + } + return 0; +} + + + /* There was a hardware caused change in the enable status + * + * A change caused by hardware has put the hub out or into + * enabled state. One of the reasons may be an overcurrent [and + * this is a reason for checking this before overcurrent]. + * + * If we have moved to the disabled state, we detach the device + * and reset it; this will not cause another status change, from + * disabled to enabled, as it'd be software generated and this bit + * only is for hardware detection. Anyhow, we'll keep some code to + * attach it in the case [again, should not happen] it happens. + * + * Now, we should be seeing an enable change when the port + * completes a reset sequence ... + * + * Parameters: + * + * ts_usb_hub* Hub + * + * __u8 Port number + * + * Returns: + * + * int 0 if ok, errno code < 0 on error. + * + * Global: + * + * int usb_errno On error, error code. + */ + +int port_enable_change (ts_usb_hub* hub, __u8 port) +{ + int errcode = 0; + ts_usb_device *device; + + gdlf_fntrace ("port_enable_change (0x%p, %u)", hub, port); + + /* + * NOTE: This code, initially, is almost the same as for the + * port_connection_change(), function, so keep'em + * synchronized, right? + */ + + if (hub->port[port].enable) + { + /* + * enabled port, let's attach the device + * + * I know, this would be quite strange, but just in case. +