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