some routines for removing a device on demand. thist do not work properly
[ppcskel.git] / usb / drivers / class / hid.c
1 /*
2         ppcskel - a Free Software replacement for the Nintendo/BroadOn bootloader.
3         hid driver
4
5 Copyright (C) 2009     Bernhard Urban <lewurm@gmx.net>
6 Copyright (C) 2009     Sebastian Falbesoner <sebastian.falbesoner@gmail.com>
7
8 # This code is licensed to you under the terms of the GNU GPL, version 2;
9 # see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
10 */
11
12 #include "../../core/core.h"
13 #include "../../core/usb.h"
14 #include "../../usbspec/usb11spec.h"
15 #include "../../../malloc.h"
16 #include "../../../string.h"
17
18 #include "hid.h"
19
20 struct usb_driver hidkb = {
21         .name     = "hidkb",
22         .probe  = usb_hidkb_probe,
23         .check  = usb_hidkb_check,
24         .remove = usb_hidkb_remove,
25         .data     = NULL
26 };
27
28 /*
29  * just using two very simple US layout code translation tables that
30  * are sufficient for providing a getc() C standard library call;
31  * the only non-printable character here in this table is ESCAPE which
32  * has index 0x29 and is zero
33  */
34 unsigned char code_translation_table[2][57] = {
35         { /* unshifted */
36          0,   0,   0,   0,  'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
37         'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '1', '2',
38         '3', '4', '5', '6', '7', '8', '9', '0', '\n', 0,  '\r','\t',' ', '-', '=', '[',
39         ']', '\\','\\',';', '\'','`', ',', '.', '/'
40         },
41         { /* shifted */
42          0,   0,   0,   0,  'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
43         'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@',
44         '#', '$', '%', '^', '&', '*', '(', ')', '\n', 0,  '\r','\t',' ', '_', '+', '{',
45         '}', '|', '|', ':', '\"','~', '<', '>', '?'
46         }
47 };
48
49
50 void usb_hidkb_init()
51 {
52         usb_register_driver(&hidkb);
53 }
54
55 void usb_hidkb_probe()
56 {
57         struct usb_device *dev;
58         struct element *iterator = core.devices->head;
59         
60         while(iterator != NULL) {
61                 dev = (struct usb_device*)iterator->data;
62                 if(dev == NULL) {
63                         continue;
64                 }
65
66                 if(dev->conf->intf->bInterfaceClass == HID_CLASSCODE &&
67                                 dev->conf->intf->bInterfaceSubClass == 1 && /* keyboard support boot protocol? */
68                                 dev->conf->intf->bInterfaceProtocol == 1) { /* keyboard? */
69                         hidkb.data = (void*) dev;
70                         usb_hidkb_set_idle(dev, 1);
71                 }
72
73                 iterator=iterator->next;
74         }
75 }
76
77 void usb_hidkb_set_idle(struct usb_device *dev, u8 duration) {
78 #define SET_IDLE 0x0A
79         u8 buf[8];
80         memset(buf, 0, 8);
81         usb_control_msg(dev, 0x21, SET_IDLE, (duration << 8), 0, 0, buf, 0);
82         hexdump((void*) buf, 8);
83 }
84
85 void usb_hidkb_check()
86 {
87 }
88
89 u8 usb_hidkb_inuse()
90 {
91         return hidkb.data ? 1 : 0;
92 }
93
94 void usb_hidkb_remove() {
95         hidkb.data = NULL;
96 }
97
98 struct kbrep *usb_hidkb_getChars() {
99         struct usb_device *dev = (struct usb_device*) hidkb.data;
100         struct kbrep *ret = (struct kbrep*) malloc(sizeof(struct kbrep));
101
102         memset(ret, 0, 8);
103         s8 epnum = dev->conf->intf->endp->bEndpointAddress & 0xf;
104         (void) usb_interrupt_read(dev, epnum, (u8*) ret, 8, 0);
105 #if 0
106         printf("============\nusb_interrupt_read:\n");
107         hexdump((void*)ret, 8);
108 #endif
109         return ret;
110 }
111
112 unsigned char usb_hidkb_get_char_from_keycode(u8 keycode, int shifted)
113 {
114         unsigned char result = 0;
115         if (keycode >= 0x3 && keycode < 57) {
116                 result = code_translation_table[!!shifted][keycode];
117         }
118         return result;
119 }