1/*  *********************************************************************
2    *  Broadcom Common Firmware Environment (CFE)
3    *
4    *  USB Human Interface Driver		File: usbhid.c
5    *
6    *  This module deals with keyboards, mice, etc.  It's very simple,
7    *  and only the "boot protocol" is supported.
8    *
9    *  Author:  Mitch Lichtenberg (mpl@broadcom.com)
10    *
11    *********************************************************************
12    *
13    *  Copyright 2000,2001,2002,2003
14    *  Broadcom Corporation. All rights reserved.
15    *
16    *  This software is furnished under license and may be used and
17    *  copied only in accordance with the following terms and
18    *  conditions.  Subject to these conditions, you may download,
19    *  copy, install, use, modify and distribute modified or unmodified
20    *  copies of this software in source and/or binary form.  No title
21    *  or ownership is transferred hereby.
22    *
23    *  1) Any source code used, modified or distributed must reproduce
24    *     and retain this copyright notice and list of conditions
25    *     as they appear in the source file.
26    *
27    *  2) No right is granted to use any trade name, trademark, or
28    *     logo of Broadcom Corporation.  The "Broadcom Corporation"
29    *     name may not be used to endorse or promote products derived
30    *     from this software without the prior written permission of
31    *     Broadcom Corporation.
32    *
33    *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
34    *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
35    *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
36    *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
37    *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
38    *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
39    *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
40    *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
41    *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
42    *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
43    *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
44    *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
45    *     THE POSSIBILITY OF SUCH DAMAGE.
46    ********************************************************************* */
47
48
49#ifndef _CFE_
50#include <stdio.h>
51#include <time.h>
52#include <memory.h>
53#include <stdint.h>
54#include "usbhack.h"
55#else
56#include "lib_types.h"
57#include "lib_string.h"
58#include "lib_printf.h"
59#include "cfe_console.h"
60#endif
61
62#include "lib_malloc.h"
63#include "lib_queue.h"
64#include "usbchap9.h"
65#include "usbd.h"
66
67/*  *********************************************************************
68    *  Constants
69    ********************************************************************* */
70
71#define HID_BOOT_PROTOCOL	0
72#define HID_REPORT_PROTOCOL	1
73
74#define HID_DEVTYPE_UNKNOWN	0
75#define HID_DEVTYPE_KBD		1
76#define HID_DEVTYPE_MOUSE	2
77#define HID_DEVTYPE_MAX		2
78
79#define UBR_KBD_MODS	0
80#define UBR_KBD_RSVD	1
81#define UBR_KBD_KEYS	2
82#define UBR_KBD_NUMKEYS	6
83#define UBR_KBD_MAX	8
84
85#define KBD_MOD_LCTRL	0x01
86#define KBD_MOD_LSHIFT	0x02
87#define KBD_MOD_LALT	0x04
88#define KBD_MOD_LWIN	0x08
89
90#define KBD_MOD_RCTRL	0x10
91#define KBD_MOD_RSHIFT	0x20
92#define KBD_MOD_RALT	0x40
93#define KBD_MOD_RWIN	0x80
94
95/*  *********************************************************************
96    *  Macros
97    ********************************************************************* */
98
99#define usbhid_set_protocol(dev,protocol,ifc) \
100        usb_simple_request(dev,0x21,0x0B,0,ifc)
101
102
103/*  *********************************************************************
104    *  Forward Definitions
105    ********************************************************************* */
106
107static int usbhid_attach(usbdev_t *dev,usb_driver_t *drv);
108static int usbhid_detach(usbdev_t *dev);
109
110/*  *********************************************************************
111    *  Structures
112    ********************************************************************* */
113
114typedef struct usbhid_softc_s {
115    int uhid_ipipe;
116    int uhid_ipipemps;
117    int uhid_devtype;
118    uint8_t uhid_imsg[UBR_KBD_MAX];
119    uint8_t uhid_lastmsg[UBR_KBD_MAX];
120    uint32_t uhid_shiftflags;
121} usbhid_softc_t;
122
123usb_driver_t usbhid_driver = {
124    "Human-Interface Device",
125    usbhid_attach,
126    usbhid_detach
127};
128
129static char *usbhid_devtypes[3] = {
130    "Unknown",
131    "Keyboard",
132    "Mouse"};
133
134#ifdef CFG_VGACONSOLE
135extern int pcconsole_enqueue(uint8_t ch);
136#endif
137
138
139/*  *********************************************************************
140    *  Constants for keyboard table
141    ********************************************************************* */
142
143#define FLG_NUM             0x0001  /* Toggles: same as bits for LEDs */
144#define FLG_CAPS            0x0002
145#define FLG_SCROLL          0x0004
146#define FLG_SHIFT           0x0008  /* Shifts */
147#define FLG_CTRL            0x0100
148#define FLG_ALT             0x0200
149#define FLG_FKEY            0x0400  /* function keys */
150#define FLG_NKPD            0x0800  /* numeric keypad */
151#define FLG_ASCII           0x1000  /* regular ASCII character */
152#define FLG_NONE            0x2000
153
154
155/*  *********************************************************************
156    *  Structures for keyboard table
157    ********************************************************************* */
158
159#define KC_RESPLEN 4
160typedef struct keycode_s {
161    int         kc_type;
162    char        kc_normal[KC_RESPLEN];
163    char        kc_shifted[KC_RESPLEN];
164    char        kc_ctrl[KC_RESPLEN];
165} keycode_t;
166
167
168/*  *********************************************************************
169    *  Scan code conversion table
170    ********************************************************************* */
171
172static keycode_t usbhid_scantable[] = {
173    { FLG_NONE,   "",             "",             "" },           /* 0 */
174    { FLG_NONE,   "",             "",             "" },           /* 1 */
175    { FLG_NONE,   "",             "",             "" },           /* 2 */
176    { FLG_NONE,   "",             "",             "" },           /* 3 */
177    { FLG_ASCII,  "a",            "A",            "\001" },       /* 4 a */
178    { FLG_ASCII,  "b",            "B",            "\002" },       /* 5 b */
179    { FLG_ASCII,  "c",            "C",            "\003" },       /* 6 c */
180    { FLG_ASCII,  "d",            "D",            "\004" },       /* 7 d */
181    { FLG_ASCII,  "e",            "E",            "\005" },       /* 8 e */
182    { FLG_ASCII,  "f",            "F",            "\006" },       /* 9 f */
183    { FLG_ASCII,  "g",            "G",            "\007" },       /* 10 g */
184    { FLG_ASCII,  "h",            "H",            "\010" },       /* 11 h */
185    { FLG_ASCII,  "i",            "I",            "\011" },       /* 12 i */
186    { FLG_ASCII,  "j",            "J",            "\n" },         /* 13 j */
187    { FLG_ASCII,  "k",            "K",            "\013" },       /* 14 k */
188    { FLG_ASCII,  "l",            "L",            "\014" },       /* 15 l */
189    { FLG_ASCII,  "m",            "M",            "\r" },         /* 16 m */
190    { FLG_ASCII,  "n",            "N",            "\016" },       /* 17 n */
191    { FLG_ASCII,  "o",            "O",            "\017" },       /* 18 o */
192    { FLG_ASCII,  "p",            "P",            "\020" },       /* 19 p */
193    { FLG_ASCII,  "q",            "Q",            "\021" },       /* 20 q */
194    { FLG_ASCII,  "r",            "R",            "\022" },       /* 21 r */
195    { FLG_ASCII,  "s",            "S",            "\023" },       /* 22 s */
196    { FLG_ASCII,  "t",            "T",            "\024" },       /* 23 t */
197    { FLG_ASCII,  "u",            "U",            "\025" },       /* 24 u */
198    { FLG_ASCII,  "v",            "V",            "\026" },       /* 25 v */
199    { FLG_ASCII,  "w",            "W",            "\027" },       /* 26 w */
200    { FLG_ASCII,  "x",            "X",            "\030" },       /* 27 x */
201    { FLG_ASCII,  "y",            "Y",            "\031" },       /* 28 y */
202    { FLG_ASCII,  "z",            "Z",            "\032" },       /* 29 z */
203
204    { FLG_ASCII,  "1",            "!",            "!" },          /* 30 1 */
205    { FLG_ASCII,  "2",            "@",            "\000" },       /* 31 2 */
206    { FLG_ASCII,  "3",            "#",            "#" },          /* 32 3 */
207    { FLG_ASCII,  "4",            "$",            "$" },          /* 33 4 */
208    { FLG_ASCII,  "5",            "%",            "%" },          /* 34 5 */
209    { FLG_ASCII,  "6",            "^",            "\036" },       /* 35 6 */
210    { FLG_ASCII,  "7",            "&",            "&" },          /* 36 7 */
211    { FLG_ASCII,  "8",            "*",            "\010" },       /* 37 8 */
212    { FLG_ASCII,  "9",            "(",            "(" },          /* 38 9 */
213    { FLG_ASCII,  "0",            ")",            ")" },          /* 39 0 */
214
215    { FLG_ASCII,  "\r",           "\r",           "\n" },         /* 40 ENT */
216    { FLG_ASCII,  "\033",         "\033",         "\033" },       /* 41 ESC */
217    { FLG_ASCII,  "\177",         "\177",         "\010" },       /* 42 <- */
218    { FLG_ASCII,  "\t",           "\177\t",       "\t" },         /* 43 ->| */
219    { FLG_ASCII,  " ",            " ",            "\000" },       /* 44 SPC */
220
221    { FLG_ASCII,  "-",            "_",            "\037" },       /* 45 - */
222    { FLG_ASCII,  "=",            "+",            "+" },          /* 46 = */
223    { FLG_ASCII,  "[",            "{",            "\033" },       /* 47 [ */
224    { FLG_ASCII,  "]",            "}",            "\035" },       /* 48 ] */
225    { FLG_ASCII,  "\\",           "|",            "\034" },       /* 49 \ */
226
227    { FLG_NONE,   "",             "",             "" },           /* 50 pound */
228
229    { FLG_ASCII,  ";",            ":",            ";" },          /* 51 ; */
230    { FLG_ASCII,  "'",            "\"",           "'" },          /* 52 ' */
231    { FLG_ASCII,  "`",            "~",            "`" },          /* 53 ` */
232    { FLG_ASCII,  ",",            "<",            "<" },          /* 54 , */
233    { FLG_ASCII,  ".",            ">",            ">" },          /* 55 . */
234    { FLG_ASCII,  "/",            "?",            "\037" },       /* 56 / */
235    { FLG_CAPS,   "",             "",             "" },           /* 57 CAPS */
236
237    { FLG_FKEY,   "\033[M",       "\033[Y",       "\033[k" },     /* 58 f1 */
238    { FLG_FKEY,   "\033[N",       "\033[Z",       "\033[l" },     /* 59 f2 */
239    { FLG_FKEY,   "\033[O",       "\033[a",       "\033[m" },     /* 60 f3 */
240    { FLG_FKEY,   "\033[P",       "\033[b",       "\033[n" },     /* 61 f4 */
241    { FLG_FKEY,   "\033[Q",       "\033[c",       "\033[o" },     /* 62 f5 */
242    { FLG_FKEY,   "\033[R",       "\033[d",       "\033[p" },     /* 63 f6 */
243    { FLG_FKEY,   "\033[S",       "\033[e",       "\033[q" },     /* 64 f7 */
244    { FLG_FKEY,   "\033[T",       "\033[f",       "\033[r" },     /* 65 f8 */
245    { FLG_FKEY,   "\033[U",       "\033[g",       "\033[s" },     /* 66 f9 */
246    { FLG_FKEY,   "\033[V",       "\033[h",       "\033[t" },     /* 67 f10 */
247    { FLG_FKEY,   "\033[W",       "\033[i",       "\033[u" },     /* 68 f11 */
248    { FLG_FKEY,   "\033[X",       "\033[j",       "\033[v" },     /* 69 f12 */
249
250    { FLG_NONE,   "",             "",             "" },           /* 70 prtsc */
251    { FLG_SCROLL, "",             "",             "" },           /* 71 SCRLK  */
252    { FLG_NONE,   "",             "",             "" },           /* 72 pause */
253    { FLG_NONE,   "",             "",             "" },           /* 73 KPins */
254    { FLG_NONE,   "",             "",             "" },           /* 74 KPhome */
255    { FLG_NONE,   "",             "",             "" },           /* 75 KPpgup */
256    { FLG_NONE,   "",             "",             "" },           /* 76 KPdel */
257    { FLG_NONE,   "",             "",             "" },           /* 77 KPend */
258    { FLG_NONE,   "",             "",             "" },           /* 78 KPpgdn */
259
260    { FLG_FKEY,   "\033[C",       "",             "" },           /* 79 KPright */
261    { FLG_FKEY,   "\033[D",       "",             "" },           /* 80 KPleft */
262    { FLG_FKEY,   "\033[B",       "",             "" },           /* 81 KPdown */
263    { FLG_FKEY,   "\033[A",       "",             "" },           /* 82 KPup */
264
265    { FLG_NUM,    "",             "",             "" },           /* 83 NUMLK */
266    { FLG_NKPD,   "/",            "/",            "/" },          /* 84 KP/ */
267    { FLG_NKPD,   "*",            "*",            "*" },          /* 85 KP* */
268    { FLG_NKPD,   "-",            "-",            "-" },          /* 86 KP- */
269    { FLG_NKPD,   "+",            "+",            "+" },          /* 87 KP+ */
270    { FLG_NKPD,   "\r",           "\r",           "\n" },         /* 88 KPent */
271
272    { FLG_NKPD,   "1",            "\033[F",       "1" },          /* 89 KP1 */
273    { FLG_NKPD,   "2",            "\033[B",       "2" },          /* 90 KP2 */
274    { FLG_NKPD,   "3",            "\033[G",       "3" },          /* 91 KP3 */
275    { FLG_NKPD,   "4",            "\033[D",       "4" },          /* 92 KP4 */
276    { FLG_NKPD,   "5",            "\033[E",       "5" },          /* 93 KP5 */
277    { FLG_NKPD,   "6",            "\033[C",       "6" },          /* 94 KP6 */
278    { FLG_NKPD,   "7",            "\033[H",       "7" },          /* 95 KP7 */
279    { FLG_NKPD,   "8",            "\033[A",       "8" },          /* 96 KP8 */
280    { FLG_NKPD,   "9",            "\033[I",       "9" },          /* 97 KP9 */
281    { FLG_NKPD,   "0",            "\033[L",       "0" },          /* 98 KP0 */
282
283    { FLG_NKPD,   ".",            "\177",         "." },          /* 99 KP. */
284
285    { FLG_NONE,   "",             "",             "" },           /* 100 non\ */
286
287};
288
289#define usbhid_scantablesize (sizeof(usbhid_scantable)/sizeof(keycode_t))
290
291
292/*  *********************************************************************
293    *  usbhid_kbd_mod1(uhid)
294    *
295    *  Process modifier key changes for the current USB event,
296    *  which was stored in uhid_imsg.  Basically all this does
297    *  is update uhid_shiftflags, converting the bits into the ones
298    *  we use in our keyboard table.
299    *
300    *  Input parameters:
301    *  	   uhid - the hid softc.
302    *
303    *  Return value:
304    *  	   nothing
305    ********************************************************************* */
306
307static void usbhid_kbd_mod1(usbhid_softc_t *uhid)
308{
309    uint8_t changed;
310    uint8_t mod;
311
312    /*
313     * See if anything changed.
314     */
315
316    changed = (uhid->uhid_imsg[UBR_KBD_MODS] ^ uhid->uhid_lastmsg[UBR_KBD_MODS]);
317    if (changed == 0) return;
318
319    /*
320     * Something changed.  Reflect changes in our local copy of the
321     * shift state.
322     */
323
324    mod = uhid->uhid_imsg[UBR_KBD_MODS];
325
326    uhid->uhid_shiftflags &= ~(FLG_SHIFT|FLG_ALT|FLG_CTRL);
327
328    if (mod & (KBD_MOD_LCTRL|KBD_MOD_RCTRL))   uhid->uhid_shiftflags |= FLG_CTRL;
329    if (mod & (KBD_MOD_LSHIFT|KBD_MOD_RSHIFT)) uhid->uhid_shiftflags |= FLG_SHIFT;
330    if (mod & (KBD_MOD_LALT|KBD_MOD_RALT)) uhid->uhid_shiftflags |= FLG_ALT;
331}
332
333/*  *********************************************************************
334    *  usbhid_kbd_scan1(uhid,scan,breakflg)
335    *
336    *  Handle a single keyboard event.  Using the scan code, look up
337    *  the key in the table and convert it to one or more characters
338    *  for the keyboard event queue.
339    *
340    *  Input parameters:
341    *  	   uhid - the hid softc
342    *  	   scan - scan code from keyboard report
343    *  	   breakflg - true if key is being released, false if pressed
344    *
345    *  Return value:
346    *  	   nothing
347    ********************************************************************* */
348
349static void usbhid_kbd_scan1(usbhid_softc_t *uhid,uint8_t scan,int breakflg)
350{
351    keycode_t *code = 0;
352    char *str;
353
354    /*
355     * Check scan code for reality.
356     */
357
358    if (scan >= usbhid_scantablesize) return;
359    code = &usbhid_scantable[scan];
360
361    /*
362     * If the change is a toggle, handle the toggle.  These
363     * keys also deal with the LEDs on the keyboard.
364     */
365
366    if (code->kc_type & (FLG_CAPS|FLG_SCROLL|FLG_NUM)) {
367	if (!breakflg) uhid->uhid_shiftflags ^= code->kc_type;
368//	if (ks->ks_setleds) {
369//	    (*(ks->ks_setleds))(ks,ks->ks_shiftflags & (FLG_CAPS|FLG_SCROLL|FLG_NUM));
370//	    }
371	}
372
373    /*
374     * Regular keys - just look up in table and
375     * queue the characters to the upper layers.
376     */
377
378    if (code->kc_type & (FLG_ASCII | FLG_FKEY | FLG_NKPD)) {
379	if (uhid->uhid_shiftflags & (FLG_SHIFT|FLG_CAPS)) str = code->kc_shifted;
380	else if (uhid->uhid_shiftflags & FLG_CTRL) str = code->kc_ctrl;
381	else str = code->kc_normal;
382	if (!breakflg) {
383#if CFG_VGACONSOLE
384	    while (*str) {
385		pcconsole_enqueue(*str++);
386		}
387#else
388	    printf("%s",str);
389#endif
390#ifndef _CFE_
391	    fflush(stdout);
392#endif
393	    }
394	}
395
396}
397
398
399/*  *********************************************************************
400    *  usbhid_kbd_scan(uhid)
401    *
402    *  Main processing routine for keyboard report messages.  Once
403    *  we've determined that it is a keyboard mesage, we end up
404    *  here.  The work involves seeing what new keys have arrived
405    *  in the list (presses), and which ones are no longer there
406    *  (releases).  To do this, we us the current and previous
407    *  report structure.
408    *
409    *  Input parameters:
410    *  	   uhid - the hid softc
411    *
412    *  Return value:
413    *  	   nothing
414    ********************************************************************* */
415
416static void usbhid_kbd_scan(usbhid_softc_t *uhid)
417{
418    int n,o;
419
420    /*
421     * Modifier keys (shift, alt, control)
422     */
423
424    if (uhid->uhid_imsg[UBR_KBD_MODS] ^ uhid->uhid_lastmsg[UBR_KBD_MODS]) {
425	usbhid_kbd_mod1(uhid);
426	}
427
428    /*
429     * "Make" codes (keys pressed down)
430     * Look for keys in 'uhid_imsg' that are not in 'uhid_lastmsg'
431     */
432
433    for (n = UBR_KBD_KEYS; n < (UBR_KBD_KEYS + UBR_KBD_NUMKEYS); n++) {
434	if (uhid->uhid_imsg[n] == 0) break;	/* no more keys */
435	for (o = UBR_KBD_KEYS; o < (UBR_KBD_KEYS + UBR_KBD_NUMKEYS); o++) {
436	    if (uhid->uhid_imsg[n] == uhid->uhid_lastmsg[o]) break;
437	    }
438	if (o == (UBR_KBD_KEYS + UBR_KBD_NUMKEYS)) {	/* key not found, must be pressed */
439	    usbhid_kbd_scan1(uhid,uhid->uhid_imsg[n],0);
440	    }
441	}
442
443    /*
444     * "Break" codes (keys released)
445     * Look for keys in 'uhid_lastmsg' that are not in 'uhid_imsg'
446     */
447
448
449    for (n = UBR_KBD_KEYS; n < (UBR_KBD_KEYS + UBR_KBD_NUMKEYS); n++) {
450	if (uhid->uhid_lastmsg[n] == 0) break;	/* no more keys */
451	for (o = UBR_KBD_KEYS; o < (UBR_KBD_KEYS + UBR_KBD_NUMKEYS); o++) {
452	    if (uhid->uhid_lastmsg[n] == uhid->uhid_imsg[o]) break;
453	    }
454	if (o == (UBR_KBD_KEYS + UBR_KBD_NUMKEYS)) {	/* key not found, must be released */
455	    usbhid_kbd_scan1(uhid,uhid->uhid_lastmsg[n],1);
456	    }
457	}
458}
459
460
461/*  *********************************************************************
462    *  usbhid_ireq_callback(ur)
463    *
464    *  This routine is called when our interrupt transfer completes
465    *  and there is report data to be processed.
466    *
467    *  Input parameters:
468    *  	   ur - usb request
469    *
470    *  Return value:
471    *  	   0
472    ********************************************************************* */
473
474static int usbhid_ireq_callback(usbreq_t *ur)
475{
476    usbhid_softc_t *uhid = (ur->ur_dev->ud_private);
477
478    /*
479     * If the driver is unloaded, the request will be cancelled.
480     */
481
482    if (ur->ur_status == 0xFF) {
483	usb_free_request(ur);
484	return 0;
485	}
486
487    /*
488     * What we do now depends on the type of device.
489     */
490
491    switch (uhid->uhid_devtype) {
492	case HID_DEVTYPE_KBD:
493	    /*
494	     * Handle keyboard event
495	     */
496	    usbhid_kbd_scan(uhid);
497
498	    /*
499	     * Save old event to compare for next time.
500	     */
501	    memcpy(uhid->uhid_lastmsg,uhid->uhid_imsg,8);
502	    break;
503
504	case HID_DEVTYPE_MOUSE:
505	    break;
506	}
507
508    /*
509     * Re-queue request to get next keyboard event.
510     */
511
512    usb_queue_request(ur);
513
514    return 0;
515}
516
517
518/*  *********************************************************************
519    *  usbhid_queue_intreq(dev,softc)
520    *
521    *  Queue an interrupt request for this usb device.  The
522    *  driver will place this request on the queue that corresponds
523    *  to the endpoint, and will call the callback routine when
524    *  something happens.
525    *
526    *  Input parameters:
527    *  	   dev - usb device
528    *  	   softc - the usb hid softc
529    *
530    *  Return value:
531    *  	   nothing
532    ********************************************************************* */
533
534static void usbhid_queue_intreq(usbdev_t *dev,usbhid_softc_t *softc)
535{
536    usbreq_t *ur;
537
538    ur = usb_make_request(dev,
539			  softc->uhid_ipipe,
540			  softc->uhid_imsg,softc->uhid_ipipemps,
541			  UR_FLAG_IN);
542
543    ur->ur_callback = usbhid_ireq_callback;
544
545    usb_queue_request(ur);
546}
547
548
549/*  *********************************************************************
550    *  usbhid_attach(dev,drv)
551    *
552    *  This routine is called when the bus scan stuff finds a HID
553    *  device.  We finish up the initialization by configuring the
554    *  device and allocating our softc here.
555    *
556    *  Input parameters:
557    *  	   dev - usb device, in the "addressed" state.
558    *  	   drv - the driver table entry that matched
559    *
560    *  Return value:
561    *  	   0
562    ********************************************************************* */
563
564static int usbhid_attach(usbdev_t *dev,usb_driver_t *drv)
565{
566    usb_config_descr_t *cfgdscr = dev->ud_cfgdescr;
567    usb_endpoint_descr_t *epdscr;
568    usb_interface_descr_t *ifdscr;
569    usbhid_softc_t *softc;
570
571    dev->ud_drv = drv;
572
573    softc = KMALLOC(sizeof(usbhid_softc_t),0);
574    memset(softc,0,sizeof(usbhid_softc_t));
575    dev->ud_private = softc;
576
577    epdscr = usb_find_cfg_descr(dev,USB_ENDPOINT_DESCRIPTOR_TYPE,0);
578    ifdscr = usb_find_cfg_descr(dev,USB_INTERFACE_DESCRIPTOR_TYPE,0);
579
580    if (!epdscr || !ifdscr) {
581	/*
582	 * Could not get descriptors, something is very wrong.
583	 * Leave device addressed but not configured.
584	 */
585	return 0;
586	}
587
588    /*
589     * Choose the standard configuration.
590     */
591
592    usb_set_configuration(dev,cfgdscr->bConfigurationValue);
593
594    /*
595     * Set the protocol to the "boot" protocol, so we don't
596     * have to deal with fancy HID stuff.
597     */
598
599    usbhid_set_protocol(dev,HID_BOOT_PROTOCOL,ifdscr->bInterfaceNumber);
600
601    /*
602     * Open the interrupt pipe.
603     */
604
605    softc->uhid_ipipe = usb_open_pipe(dev,epdscr);
606    softc->uhid_ipipemps = GETUSBFIELD(epdscr,wMaxPacketSize);
607
608    /*
609     * Figure out the device type from the protocol.  Keyboards,
610     * mice use this field to distinguish themselves.
611     */
612
613    softc->uhid_devtype = ifdscr->bInterfaceProtocol;
614    if (softc->uhid_devtype > HID_DEVTYPE_MAX) {
615	softc->uhid_devtype = HID_DEVTYPE_UNKNOWN;
616	}
617
618    console_log("USBHID: %s Configured.\n",
619	   usbhid_devtypes[softc->uhid_devtype]);
620
621    /*
622     * Queue a transfer on the interrupt endpoint to catch
623     * our first characters.
624     */
625
626    usbhid_queue_intreq(dev,softc);
627
628    return 0;
629}
630
631/*  *********************************************************************
632    *  usbhid_detach(dev)
633    *
634    *  This routine is called when the bus scanner notices that
635    *  this device has been removed from the system.  We should
636    *  do any cleanup that is required.  The pending requests
637    *  will be cancelled automagically.
638    *
639    *  Input parameters:
640    *  	   dev - usb device
641    *
642    *  Return value:
643    *  	   0
644    ********************************************************************* */
645
646static int usbhid_detach(usbdev_t *dev)
647{
648    return 0;
649}
650
651
652
653