Document usb-hid.c functions.
[seabios.git] / src / usb-hid.c
1 // Code for handling USB Human Interface Devices (HID).
2 //
3 // Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
4 //
5 // This file may be distributed under the terms of the GNU LGPLv3 license.
6
7 #include "util.h" // dprintf
8 #include "usb-hid.h" // usb_keyboard_setup
9 #include "config.h" // CONFIG_*
10 #include "usb.h" // usb_ctrlrequest
11 #include "biosvar.h" // GET_GLOBAL
12
13 struct usb_pipe *keyboard_pipe VAR16VISIBLE;
14
15
16 /****************************************************************
17  * Setup
18  ****************************************************************/
19
20 // Send USB HID protocol message.
21 static int
22 set_protocol(struct usb_pipe *pipe, u16 val)
23 {
24     struct usb_ctrlrequest req;
25     req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
26     req.bRequest = HID_REQ_SET_PROTOCOL;
27     req.wValue = val;
28     req.wIndex = 0;
29     req.wLength = 0;
30     return send_default_control(pipe, &req, NULL);
31 }
32
33 // Send USB HID SetIdle request.
34 static int
35 set_idle(struct usb_pipe *pipe, int ms)
36 {
37     struct usb_ctrlrequest req;
38     req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
39     req.bRequest = HID_REQ_SET_IDLE;
40     req.wValue = (ms/4)<<8;
41     req.wIndex = 0;
42     req.wLength = 0;
43     return send_default_control(pipe, &req, NULL);
44 }
45
46 #define KEYREPEATWAITMS 500
47 #define KEYREPEATMS 33
48
49 int
50 usb_keyboard_init(struct usb_pipe *pipe
51                   , struct usb_interface_descriptor *iface, int imax)
52 {
53     if (! CONFIG_USB_KEYBOARD)
54         return -1;
55     if (keyboard_pipe)
56         // XXX - this enables the first found keyboard (could be random)
57         return -1;
58     dprintf(2, "usb_keyboard_setup %p\n", pipe);
59
60     // Find intr in endpoint.
61     struct usb_endpoint_descriptor *epdesc = findEndPointDesc(
62         iface, imax, USB_ENDPOINT_XFER_INT, USB_DIR_IN);
63     if (!epdesc || epdesc->wMaxPacketSize != 8) {
64         dprintf(1, "No keyboard intr in?\n");
65         return -1;
66     }
67
68     // Enable "boot" protocol.
69     int ret = set_protocol(pipe, 1);
70     if (ret)
71         return -1;
72     // Periodically send reports to enable key repeat.
73     ret = set_idle(pipe, KEYREPEATMS);
74     if (ret)
75         return -1;
76
77     keyboard_pipe = alloc_intr_pipe(pipe, epdesc);
78     if (!keyboard_pipe)
79         return -1;
80
81     dprintf(1, "USB keyboard initialized\n");
82     return 0;
83 }
84
85 void
86 usb_keyboard_setup(void)
87 {
88     if (! CONFIG_USB_KEYBOARD)
89         return;
90     keyboard_pipe = NULL;
91 }
92
93
94 /****************************************************************
95  * Keyboard events
96  ****************************************************************/
97
98 // Mapping from USB key id to ps2 key sequence.
99 static u16 KeyToScanCode[] VAR16 = {
100     0x0000, 0x0000, 0x0000, 0x0000, 0x001e, 0x0030, 0x002e, 0x0020,
101     0x0012, 0x0021, 0x0022, 0x0023, 0x0017, 0x0024, 0x0025, 0x0026,
102     0x0032, 0x0031, 0x0018, 0x0019, 0x0010, 0x0013, 0x001f, 0x0014,
103     0x0016, 0x002f, 0x0011, 0x002d, 0x0015, 0x002c, 0x0002, 0x0003,
104     0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b,
105     0x001c, 0x0001, 0x000e, 0x000f, 0x0039, 0x000c, 0x000d, 0x001a,
106     0x001b, 0x002b, 0x0000, 0x0027, 0x0028, 0x0029, 0x0033, 0x0034,
107     0x0035, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
108     0x0041, 0x0042, 0x0043, 0x0044, 0x0057, 0x0058, 0xe037, 0x0046,
109     0xe11d, 0xe052, 0xe047, 0xe049, 0xe053, 0xe04f, 0xe051, 0xe04d,
110     0xe04b, 0xe050, 0xe048, 0x0045, 0xe035, 0x0037, 0x004a, 0x004e,
111     0xe01c, 0x004f, 0x0050, 0x0051, 0x004b, 0x004c, 0x004d, 0x0047,
112     0x0048, 0x0049, 0x0052, 0x0053
113 };
114
115 // Mapping from USB modifier id to ps2 key sequence.
116 static u16 ModifierToScanCode[] VAR16 = {
117     //lcntl, lshift, lalt, lgui, rcntl, rshift, ralt, rgui
118     0x001d, 0x002a, 0x0038, 0xe05b, 0xe01d, 0x0036, 0xe038, 0xe05c
119 };
120
121 #define RELEASEBIT 0x80
122
123 // Format of USB event data
124 struct keyevent {
125     u8 modifiers;
126     u8 reserved;
127     u8 keys[6];
128 };
129
130 // Translate data from KeyToScanCode[] to calls to process_key().
131 static void
132 prockeys(u16 keys)
133 {
134     if (keys > 0xff) {
135         u8 key = keys>>8;
136         if (key == 0xe1) {
137             // Pause key
138             process_key(0xe1);
139             process_key(0x1d | (keys & RELEASEBIT));
140             process_key(0x45 | (keys & RELEASEBIT));
141             return;
142         }
143         process_key(key);
144     }
145     process_key(keys);
146 }
147
148 // Handle a USB key press/release event.
149 static void
150 procscankey(u8 key, u8 flags)
151 {
152     if (key >= ARRAY_SIZE(KeyToScanCode))
153         return;
154     u16 keys = GET_GLOBAL(KeyToScanCode[key]);
155     if (keys)
156         prockeys(keys | flags);
157 }
158
159 // Handle a USB modifier press/release event.
160 static void
161 procmodkey(u8 mods, u8 flags)
162 {
163     int i;
164     for (i=0; mods; i++)
165         if (mods & (1<<i)) {
166             // Modifier key change.
167             prockeys(GET_GLOBAL(ModifierToScanCode[i]) | flags);
168             mods &= ~(1<<i);
169         }
170 }
171
172 // Process USB keyboard data.
173 static void noinline
174 handle_key(struct keyevent *data)
175 {
176     dprintf(9, "Got key %x %x\n", data->modifiers, data->keys[0]);
177
178     // Load old keys.
179     u16 ebda_seg = get_ebda_seg();
180     struct usbkeyinfo old;
181     old.data = GET_EBDA2(ebda_seg, usbkey_last.data);
182
183     // Check for keys no longer pressed.
184     int addpos = 0;
185     int i;
186     for (i=0; i<ARRAY_SIZE(old.keys); i++) {
187         u8 key = old.keys[i];
188         if (!key)
189             break;
190         int j;
191         for (j=0;; j++) {
192             if (j>=ARRAY_SIZE(data->keys)) {
193                 // Key released.
194                 procscankey(key, RELEASEBIT);
195                 if (i+1 >= ARRAY_SIZE(old.keys) || !old.keys[i+1])
196                     // Last pressed key released - disable repeat.
197                     old.repeatcount = 0xff;
198                 break;
199             }
200             if (data->keys[j] == key) {
201                 // Key still pressed.
202                 data->keys[j] = 0;
203                 old.keys[addpos++] = key;
204                 break;
205             }
206         }
207     }
208     procmodkey(old.modifiers & ~data->modifiers, RELEASEBIT);
209
210     // Process new keys
211     procmodkey(data->modifiers & ~old.modifiers, 0);
212     old.modifiers = data->modifiers;
213     for (i=0; i<ARRAY_SIZE(data->keys); i++) {
214         u8 key = data->keys[i];
215         if (!key)
216             continue;
217         // New key pressed.
218         procscankey(key, 0);
219         old.keys[addpos++] = key;
220         old.repeatcount = KEYREPEATWAITMS / KEYREPEATMS + 1;
221     }
222     if (addpos < ARRAY_SIZE(old.keys))
223         old.keys[addpos] = 0;
224
225     // Check for key repeat event.
226     if (addpos) {
227         if (!old.repeatcount)
228             procscankey(old.keys[addpos-1], 0);
229         else if (old.repeatcount != 0xff)
230             old.repeatcount--;
231     }
232
233     // Update old keys
234     SET_EBDA2(ebda_seg, usbkey_last.data, old.data);
235 }
236
237 // Check for USB events pending - called periodically from timer interrupt.
238 void
239 usb_check_key(void)
240 {
241     if (! CONFIG_USB_KEYBOARD)
242         return;
243     struct usb_pipe *pipe = GET_GLOBAL(keyboard_pipe);
244     if (!pipe)
245         return;
246
247     for (;;) {
248         struct keyevent data;
249         int ret = usb_poll_intr(pipe, &data);
250         if (ret)
251             break;
252         handle_key(&data);
253     }
254 }