summaryrefslogtreecommitdiffstats
path: root/cfe/cfe/usb/usbhid.c
diff options
context:
space:
mode:
Diffstat (limited to 'cfe/cfe/usb/usbhid.c')
-rw-r--r--cfe/cfe/usb/usbhid.c664
1 files changed, 664 insertions, 0 deletions
diff --git a/cfe/cfe/usb/usbhid.c b/cfe/cfe/usb/usbhid.c
new file mode 100644
index 0000000..df84f4e
--- /dev/null
+++ b/cfe/cfe/usb/usbhid.c
@@ -0,0 +1,664 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * USB Human Interface Driver File: usbhid.c
+ *
+ * This module deals with keyboards, mice, etc. It's very simple,
+ * and only the "boot protocol" is supported.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#ifndef _CFE_
+#include <stdio.h>
+#include <time.h>
+#include <memory.h>
+#include <stdint.h>
+#include "usbhack.h"
+#else
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_printf.h"
+#include "cfe_console.h"
+#endif
+
+#include "lib_malloc.h"
+#include "lib_queue.h"
+#include "usbchap9.h"
+#include "usbd.h"
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define HID_BOOT_PROTOCOL 0
+#define HID_REPORT_PROTOCOL 1
+
+#define HID_DEVTYPE_UNKNOWN 0
+#define HID_DEVTYPE_KBD 1
+#define HID_DEVTYPE_MOUSE 2
+#define HID_DEVTYPE_MAX 2
+
+#define UBR_KBD_MODS 0
+#define UBR_KBD_RSVD 1
+#define UBR_KBD_KEYS 2
+#define UBR_KBD_NUMKEYS 6
+#define UBR_KBD_MAX 8
+
+#define KBD_MOD_LCTRL 0x01
+#define KBD_MOD_LSHIFT 0x02
+#define KBD_MOD_LALT 0x04
+#define KBD_MOD_LWIN 0x08
+
+#define KBD_MOD_RCTRL 0x10
+#define KBD_MOD_RSHIFT 0x20
+#define KBD_MOD_RALT 0x40
+#define KBD_MOD_RWIN 0x80
+
+/* *********************************************************************
+ * Macros
+ ********************************************************************* */
+
+#define usbhid_set_protocol(dev,protocol,ifc) \
+ usb_simple_request(dev,0x21,0x0B,0,ifc)
+
+
+/* *********************************************************************
+ * Forward Definitions
+ ********************************************************************* */
+
+static int usbhid_attach(usbdev_t *dev,usb_driver_t *drv);
+static int usbhid_detach(usbdev_t *dev);
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+typedef struct usbhid_softc_s {
+ int uhid_ipipe;
+ int uhid_ipipemps;
+ int uhid_devtype;
+ uint8_t uhid_imsg[UBR_KBD_MAX];
+ uint8_t uhid_lastmsg[UBR_KBD_MAX];
+ uint32_t uhid_shiftflags;
+} usbhid_softc_t;
+
+usb_driver_t usbhid_driver = {
+ "Human-Interface Device",
+ usbhid_attach,
+ usbhid_detach
+};
+
+static char *usbhid_devtypes[3] = {
+ "Unknown",
+ "Keyboard",
+ "Mouse"};
+
+#ifdef CFG_VGACONSOLE
+extern int pcconsole_enqueue(uint8_t ch);
+#endif
+
+
+/* *********************************************************************
+ * Constants for keyboard table
+ ********************************************************************* */
+
+#define FLG_NUM 0x0001 /* Toggles: same as bits for LEDs */
+#define FLG_CAPS 0x0002
+#define FLG_SCROLL 0x0004
+#define FLG_SHIFT 0x0008 /* Shifts */
+#define FLG_CTRL 0x0100
+#define FLG_ALT 0x0200
+#define FLG_FKEY 0x0400 /* function keys */
+#define FLG_NKPD 0x0800 /* numeric keypad */
+#define FLG_ASCII 0x1000 /* regular ASCII character */
+#define FLG_NONE 0x2000
+
+
+/* *********************************************************************
+ * Structures for keyboard table
+ ********************************************************************* */
+
+#define KC_RESPLEN 4
+typedef struct keycode_s {
+ int kc_type;
+ char kc_normal[KC_RESPLEN];
+ char kc_shifted[KC_RESPLEN];
+ char kc_ctrl[KC_RESPLEN];
+} keycode_t;
+
+
+/* *********************************************************************
+ * Scan code conversion table
+ ********************************************************************* */
+
+static keycode_t usbhid_scantable[] = {
+ { FLG_NONE, "", "", "" }, /* 0 */
+ { FLG_NONE, "", "", "" }, /* 1 */
+ { FLG_NONE, "", "", "" }, /* 2 */
+ { FLG_NONE, "", "", "" }, /* 3 */
+ { FLG_ASCII, "a", "A", "\001" }, /* 4 a */
+ { FLG_ASCII, "b", "B", "\002" }, /* 5 b */
+ { FLG_ASCII, "c", "C", "\003" }, /* 6 c */
+ { FLG_ASCII, "d", "D", "\004" }, /* 7 d */
+ { FLG_ASCII, "e", "E", "\005" }, /* 8 e */
+ { FLG_ASCII, "f", "F", "\006" }, /* 9 f */
+ { FLG_ASCII, "g", "G", "\007" }, /* 10 g */
+ { FLG_ASCII, "h", "H", "\010" }, /* 11 h */
+ { FLG_ASCII, "i", "I", "\011" }, /* 12 i */
+ { FLG_ASCII, "j", "J", "\n" }, /* 13 j */
+ { FLG_ASCII, "k", "K", "\013" }, /* 14 k */
+ { FLG_ASCII, "l", "L", "\014" }, /* 15 l */
+ { FLG_ASCII, "m", "M", "\r" }, /* 16 m */
+ { FLG_ASCII, "n", "N", "\016" }, /* 17 n */
+ { FLG_ASCII, "o", "O", "\017" }, /* 18 o */
+ { FLG_ASCII, "p", "P", "\020" }, /* 19 p */
+ { FLG_ASCII, "q", "Q", "\021" }, /* 20 q */
+ { FLG_ASCII, "r", "R", "\022" }, /* 21 r */
+ { FLG_ASCII, "s", "S", "\023" }, /* 22 s */
+ { FLG_ASCII, "t", "T", "\024" }, /* 23 t */
+ { FLG_ASCII, "u", "U", "\025" }, /* 24 u */
+ { FLG_ASCII, "v", "V", "\026" }, /* 25 v */
+ { FLG_ASCII, "w", "W", "\027" }, /* 26 w */
+ { FLG_ASCII, "x", "X", "\030" }, /* 27 x */
+ { FLG_ASCII, "y", "Y", "\031" }, /* 28 y */
+ { FLG_ASCII, "z", "Z", "\032" }, /* 29 z */
+
+ { FLG_ASCII, "1", "!", "!" }, /* 30 1 */
+ { FLG_ASCII, "2", "@", "\000" }, /* 31 2 */
+ { FLG_ASCII, "3", "#", "#" }, /* 32 3 */
+ { FLG_ASCII, "4", "$", "$" }, /* 33 4 */
+ { FLG_ASCII, "5", "%", "%" }, /* 34 5 */
+ { FLG_ASCII, "6", "^", "\036" }, /* 35 6 */
+ { FLG_ASCII, "7", "&", "&" }, /* 36 7 */
+ { FLG_ASCII, "8", "*", "\010" }, /* 37 8 */
+ { FLG_ASCII, "9", "(", "(" }, /* 38 9 */
+ { FLG_ASCII, "0", ")", ")" }, /* 39 0 */
+
+ { FLG_ASCII, "\r", "\r", "\n" }, /* 40 ENT */
+ { FLG_ASCII, "\033", "\033", "\033" }, /* 41 ESC */
+ { FLG_ASCII, "\177", "\177", "\010" }, /* 42 <- */
+ { FLG_ASCII, "\t", "\177\t", "\t" }, /* 43 ->| */
+ { FLG_ASCII, " ", " ", "\000" }, /* 44 SPC */
+
+ { FLG_ASCII, "-", "_", "\037" }, /* 45 - */
+ { FLG_ASCII, "=", "+", "+" }, /* 46 = */
+ { FLG_ASCII, "[", "{", "\033" }, /* 47 [ */
+ { FLG_ASCII, "]", "}", "\035" }, /* 48 ] */
+ { FLG_ASCII, "\\", "|", "\034" }, /* 49 \ */
+
+ { FLG_NONE, "", "", "" }, /* 50 pound */
+
+ { FLG_ASCII, ";", ":", ";" }, /* 51 ; */
+ { FLG_ASCII, "'", "\"", "'" }, /* 52 ' */
+ { FLG_ASCII, "`", "~", "`" }, /* 53 ` */
+ { FLG_ASCII, ",", "<", "<" }, /* 54 , */
+ { FLG_ASCII, ".", ">", ">" }, /* 55 . */
+ { FLG_ASCII, "/", "?", "\037" }, /* 56 / */
+ { FLG_CAPS, "", "", "" }, /* 57 CAPS */
+
+ { FLG_FKEY, "\033[M", "\033[Y", "\033[k" }, /* 58 f1 */
+ { FLG_FKEY, "\033[N", "\033[Z", "\033[l" }, /* 59 f2 */
+ { FLG_FKEY, "\033[O", "\033[a", "\033[m" }, /* 60 f3 */
+ { FLG_FKEY, "\033[P", "\033[b", "\033[n" }, /* 61 f4 */
+ { FLG_FKEY, "\033[Q", "\033[c", "\033[o" }, /* 62 f5 */
+ { FLG_FKEY, "\033[R", "\033[d", "\033[p" }, /* 63 f6 */
+ { FLG_FKEY, "\033[S", "\033[e", "\033[q" }, /* 64 f7 */
+ { FLG_FKEY, "\033[T", "\033[f", "\033[r" }, /* 65 f8 */
+ { FLG_FKEY, "\033[U", "\033[g", "\033[s" }, /* 66 f9 */
+ { FLG_FKEY, "\033[V", "\033[h", "\033[t" }, /* 67 f10 */
+ { FLG_FKEY, "\033[W", "\033[i", "\033[u" }, /* 68 f11 */
+ { FLG_FKEY, "\033[X", "\033[j", "\033[v" }, /* 69 f12 */
+
+ { FLG_NONE, "", "", "" }, /* 70 prtsc */
+ { FLG_SCROLL, "", "", "" }, /* 71 SCRLK */
+ { FLG_NONE, "", "", "" }, /* 72 pause */
+ { FLG_NONE, "", "", "" }, /* 73 KPins */
+ { FLG_NONE, "", "", "" }, /* 74 KPhome */
+ { FLG_NONE, "", "", "" }, /* 75 KPpgup */
+ { FLG_NONE, "", "", "" }, /* 76 KPdel */
+ { FLG_NONE, "", "", "" }, /* 77 KPend */
+ { FLG_NONE, "", "", "" }, /* 78 KPpgdn */
+
+ { FLG_FKEY, "\033[C", "", "" }, /* 79 KPright */
+ { FLG_FKEY, "\033[D", "", "" }, /* 80 KPleft */
+ { FLG_FKEY, "\033[B", "", "" }, /* 81 KPdown */
+ { FLG_FKEY, "\033[A", "", "" }, /* 82 KPup */
+
+ { FLG_NUM, "", "", "" }, /* 83 NUMLK */
+ { FLG_NKPD, "/", "/", "/" }, /* 84 KP/ */
+ { FLG_NKPD, "*", "*", "*" }, /* 85 KP* */
+ { FLG_NKPD, "-", "-", "-" }, /* 86 KP- */
+ { FLG_NKPD, "+", "+", "+" }, /* 87 KP+ */
+ { FLG_NKPD, "\r", "\r", "\n" }, /* 88 KPent */
+
+ { FLG_NKPD, "1", "\033[F", "1" }, /* 89 KP1 */
+ { FLG_NKPD, "2", "\033[B", "2" }, /* 90 KP2 */
+ { FLG_NKPD, "3", "\033[G", "3" }, /* 91 KP3 */
+ { FLG_NKPD, "4", "\033[D", "4" }, /* 92 KP4 */
+ { FLG_NKPD, "5", "\033[E", "5" }, /* 93 KP5 */
+ { FLG_NKPD, "6", "\033[C", "6" }, /* 94 KP6 */
+ { FLG_NKPD, "7", "\033[H", "7" }, /* 95 KP7 */
+ { FLG_NKPD, "8", "\033[A", "8" }, /* 96 KP8 */
+ { FLG_NKPD, "9", "\033[I", "9" }, /* 97 KP9 */
+ { FLG_NKPD, "0", "\033[L", "0" }, /* 98 KP0 */
+
+ { FLG_NKPD, ".", "\177", "." }, /* 99 KP. */
+
+ { FLG_NONE, "", "", "" }, /* 100 non\ */
+
+};
+
+#define usbhid_scantablesize (sizeof(usbhid_scantable)/sizeof(keycode_t))
+
+
+/* *********************************************************************
+ * usbhid_kbd_mod1(uhid)
+ *
+ * Process modifier key changes for the current USB event,
+ * which was stored in uhid_imsg. Basically all this does
+ * is update uhid_shiftflags, converting the bits into the ones
+ * we use in our keyboard table.
+ *
+ * Input parameters:
+ * uhid - the hid softc.
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void usbhid_kbd_mod1(usbhid_softc_t *uhid)
+{
+ uint8_t changed;
+ uint8_t mod;
+
+ /*
+ * See if anything changed.
+ */
+
+ changed = (uhid->uhid_imsg[UBR_KBD_MODS] ^ uhid->uhid_lastmsg[UBR_KBD_MODS]);
+ if (changed == 0) return;
+
+ /*
+ * Something changed. Reflect changes in our local copy of the
+ * shift state.
+ */
+
+ mod = uhid->uhid_imsg[UBR_KBD_MODS];
+
+ uhid->uhid_shiftflags &= ~(FLG_SHIFT|FLG_ALT|FLG_CTRL);
+
+ if (mod & (KBD_MOD_LCTRL|KBD_MOD_RCTRL)) uhid->uhid_shiftflags |= FLG_CTRL;
+ if (mod & (KBD_MOD_LSHIFT|KBD_MOD_RSHIFT)) uhid->uhid_shiftflags |= FLG_SHIFT;
+ if (mod & (KBD_MOD_LALT|KBD_MOD_RALT)) uhid->uhid_shiftflags |= FLG_ALT;
+}
+
+/* *********************************************************************
+ * usbhid_kbd_scan1(uhid,scan,breakflg)
+ *
+ * Handle a single keyboard event. Using the scan code, look up
+ * the key in the table and convert it to one or more characters
+ * for the keyboard event queue.
+ *
+ * Input parameters:
+ * uhid - the hid softc
+ * scan - scan code from keyboard report
+ * breakflg - true if key is being released, false if pressed
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void usbhid_kbd_scan1(usbhid_softc_t *uhid,uint8_t scan,int breakflg)
+{
+ keycode_t *code = 0;
+ char *str;
+
+ /*
+ * Check scan code for reality.
+ */
+
+ if (scan >= usbhid_scantablesize) return;
+ code = &usbhid_scantable[scan];
+
+ /*
+ * If the change is a toggle, handle the toggle. These
+ * keys also deal with the LEDs on the keyboard.
+ */
+
+ if (code->kc_type & (FLG_CAPS|FLG_SCROLL|FLG_NUM)) {
+ if (!breakflg) uhid->uhid_shiftflags ^= code->kc_type;
+// if (ks->ks_setleds) {
+// (*(ks->ks_setleds))(ks,ks->ks_shiftflags & (FLG_CAPS|FLG_SCROLL|FLG_NUM));
+// }
+ }
+
+ /*
+ * Regular keys - just look up in table and
+ * queue the characters to the upper layers.
+ */
+
+ if (code->kc_type & (FLG_ASCII | FLG_FKEY | FLG_NKPD)) {
+ if (uhid->uhid_shiftflags & (FLG_SHIFT|FLG_CAPS)) str = code->kc_shifted;
+ else if (uhid->uhid_shiftflags & FLG_CTRL) str = code->kc_ctrl;
+ else str = code->kc_normal;
+ if (!breakflg) {
+#if CFG_VGACONSOLE
+ while (*str) {
+ pcconsole_enqueue(*str++);
+ }
+#else
+ printf("%s",str);
+#endif
+#ifndef _CFE_
+ fflush(stdout);
+#endif
+ }
+ }
+
+}
+
+
+/* *********************************************************************
+ * usbhid_kbd_scan(uhid)
+ *
+ * Main processing routine for keyboard report messages. Once
+ * we've determined that it is a keyboard mesage, we end up
+ * here. The work involves seeing what new keys have arrived
+ * in the list (presses), and which ones are no longer there
+ * (releases). To do this, we us the current and previous
+ * report structure.
+ *
+ * Input parameters:
+ * uhid - the hid softc
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void usbhid_kbd_scan(usbhid_softc_t *uhid)
+{
+ int n,o;
+
+ /*
+ * Modifier keys (shift, alt, control)
+ */
+
+ if (uhid->uhid_imsg[UBR_KBD_MODS] ^ uhid->uhid_lastmsg[UBR_KBD_MODS]) {
+ usbhid_kbd_mod1(uhid);
+ }
+
+ /*
+ * "Make" codes (keys pressed down)
+ * Look for keys in 'uhid_imsg' that are not in 'uhid_lastmsg'
+ */
+
+ for (n = UBR_KBD_KEYS; n < (UBR_KBD_KEYS + UBR_KBD_NUMKEYS); n++) {
+ if (uhid->uhid_imsg[n] == 0) break; /* no more keys */
+ for (o = UBR_KBD_KEYS; o < (UBR_KBD_KEYS + UBR_KBD_NUMKEYS); o++) {
+ if (uhid->uhid_imsg[n] == uhid->uhid_lastmsg[o]) break;
+ }
+ if (o == (UBR_KBD_KEYS + UBR_KBD_NUMKEYS)) { /* key not found, must be pressed */
+ usbhid_kbd_scan1(uhid,uhid->uhid_imsg[n],0);
+ }
+ }
+
+ /*
+ * "Break" codes (keys released)
+ * Look for keys in 'uhid_lastmsg' that are not in 'uhid_imsg'
+ */
+
+
+ for (n = UBR_KBD_KEYS; n < (UBR_KBD_KEYS + UBR_KBD_NUMKEYS); n++) {
+ if (uhid->uhid_lastmsg[n] == 0) break; /* no more keys */
+ for (o = UBR_KBD_KEYS; o < (UBR_KBD_KEYS + UBR_KBD_NUMKEYS); o++) {
+ if (uhid->uhid_lastmsg[n] == uhid->uhid_imsg[o]) break;
+ }
+ if (o == (UBR_KBD_KEYS + UBR_KBD_NUMKEYS)) { /* key not found, must be released */
+ usbhid_kbd_scan1(uhid,uhid->uhid_lastmsg[n],1);
+ }
+ }
+}
+
+
+/* *********************************************************************
+ * usbhid_ireq_callback(ur)
+ *
+ * This routine is called when our interrupt transfer completes
+ * and there is report data to be processed.
+ *
+ * Input parameters:
+ * ur - usb request
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+
+static int usbhid_ireq_callback(usbreq_t *ur)
+{
+ usbhid_softc_t *uhid = (ur->ur_dev->ud_private);
+
+ /*
+ * If the driver is unloaded, the request will be cancelled.
+ */
+
+ if (ur->ur_status == 0xFF) {
+ usb_free_request(ur);
+ return 0;
+ }
+
+ /*
+ * What we do now depends on the type of device.
+ */
+
+ switch (uhid->uhid_devtype) {
+ case HID_DEVTYPE_KBD:
+ /*
+ * Handle keyboard event
+ */
+ usbhid_kbd_scan(uhid);
+
+ /*
+ * Save old event to compare for next time.
+ */
+ memcpy(uhid->uhid_lastmsg,uhid->uhid_imsg,8);
+ break;
+
+ case HID_DEVTYPE_MOUSE:
+#if 0
+ /*
+ * No need to handle mice, but here's the good stuff.
+ */
+ printf("Mouse: [%s %s %s] X:%d Y:%d Wheel:%d\n",
+ (ur->ur_buffer[0] & 1) ? "left" : "",
+ (ur->ur_buffer[0] & 4) ? "middle" : "",
+ (ur->ur_buffer[0] & 2) ? "right" : "",
+ (int)(signed char)ur->ur_buffer[1],
+ (int)(signed char)ur->ur_buffer[2],
+ (int)(signed char)ur->ur_buffer[3]);
+#endif
+ break;
+ }
+
+ /*
+ * Re-queue request to get next keyboard event.
+ */
+
+ usb_queue_request(ur);
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * usbhid_queue_intreq(dev,softc)
+ *
+ * Queue an interrupt request for this usb device. The
+ * driver will place this request on the queue that corresponds
+ * to the endpoint, and will call the callback routine when
+ * something happens.
+ *
+ * Input parameters:
+ * dev - usb device
+ * softc - the usb hid softc
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void usbhid_queue_intreq(usbdev_t *dev,usbhid_softc_t *softc)
+{
+ usbreq_t *ur;
+
+ ur = usb_make_request(dev,
+ softc->uhid_ipipe,
+ softc->uhid_imsg,softc->uhid_ipipemps,
+ UR_FLAG_IN);
+
+ ur->ur_callback = usbhid_ireq_callback;
+
+ usb_queue_request(ur);
+}
+
+
+/* *********************************************************************
+ * usbhid_attach(dev,drv)
+ *
+ * This routine is called when the bus scan stuff finds a HID
+ * device. We finish up the initialization by configuring the
+ * device and allocating our softc here.
+ *
+ * Input parameters:
+ * dev - usb device, in the "addressed" state.
+ * drv - the driver table entry that matched
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+
+static int usbhid_attach(usbdev_t *dev,usb_driver_t *drv)
+{
+ usb_config_descr_t *cfgdscr = dev->ud_cfgdescr;
+ usb_endpoint_descr_t *epdscr;
+ usb_interface_descr_t *ifdscr;
+ usbhid_softc_t *softc;
+
+ dev->ud_drv = drv;
+
+ softc = KMALLOC(sizeof(usbhid_softc_t),0);
+ memset(softc,0,sizeof(usbhid_softc_t));
+ dev->ud_private = softc;
+
+ epdscr = usb_find_cfg_descr(dev,USB_ENDPOINT_DESCRIPTOR_TYPE,0);
+ ifdscr = usb_find_cfg_descr(dev,USB_INTERFACE_DESCRIPTOR_TYPE,0);
+
+ if (!epdscr || !ifdscr) {
+ /*
+ * Could not get descriptors, something is very wrong.
+ * Leave device addressed but not configured.
+ */
+ return 0;
+ }
+
+ /*
+ * Choose the standard configuration.
+ */
+
+ usb_set_configuration(dev,cfgdscr->bConfigurationValue);
+
+ /*
+ * Set the protocol to the "boot" protocol, so we don't
+ * have to deal with fancy HID stuff.
+ */
+
+ usbhid_set_protocol(dev,HID_BOOT_PROTOCOL,ifdscr->bInterfaceNumber);
+
+ /*
+ * Open the interrupt pipe.
+ */
+
+ softc->uhid_ipipe = usb_open_pipe(dev,epdscr);
+ softc->uhid_ipipemps = GETUSBFIELD(epdscr,wMaxPacketSize);
+
+ /*
+ * Figure out the device type from the protocol. Keyboards,
+ * mice use this field to distinguish themselves.
+ */
+
+ softc->uhid_devtype = ifdscr->bInterfaceProtocol;
+ if (softc->uhid_devtype > HID_DEVTYPE_MAX) {
+ softc->uhid_devtype = HID_DEVTYPE_UNKNOWN;
+ }
+
+ console_log("USBHID: %s Configured.\n",
+ usbhid_devtypes[softc->uhid_devtype]);
+
+ /*
+ * Queue a transfer on the interrupt endpoint to catch
+ * our first characters.
+ */
+
+ usbhid_queue_intreq(dev,softc);
+
+ return 0;
+}
+
+/* *********************************************************************
+ * usbhid_detach(dev)
+ *
+ * This routine is called when the bus scanner notices that
+ * this device has been removed from the system. We should
+ * do any cleanup that is required. The pending requests
+ * will be cancelled automagically.
+ *
+ * Input parameters:
+ * dev - usb device
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+
+static int usbhid_detach(usbdev_t *dev)
+{
+ return 0;
+}
+
+
+