source: mainline/uspace/drv/usbhid/kbddev.c@ 27270db

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 27270db was 27270db, checked in by Lubos Slovak <lubos.slovak@…>, 14 years ago

Fixed initialization of kbd_dev.

  • Setting console phone to -1.
  • Property mode set to 100644
File size: 19.1 KB
RevLine 
[2391aaf]1/*
2 * Copyright (c) 2011 Lubos Slovak
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup drvusbhid
30 * @{
31 */
32/**
33 * @file
34 * USB HID keyboard device structure and API.
35 */
36
37#include <errno.h>
38#include <str_error.h>
39#include <fibril.h>
40
41#include <io/keycode.h>
42#include <ipc/kbd.h>
43
44#include <usb/usb.h>
45#include <usb/classes/hid.h>
46#include <usb/pipes.h>
47#include <usb/debug.h>
48#include <usb/classes/hidparser.h>
49#include <usb/classes/classes.h>
50
51#include "kbddev.h"
52#include "hiddev.h"
53#include "hidreq.h"
54#include "layout.h"
55#include "conv.h"
56
57/*----------------------------------------------------------------------------*/
58
59static const unsigned DEFAULT_ACTIVE_MODS = KM_NUM_LOCK;
60static const size_t BOOTP_REPORT_SIZE = 6;
61static const size_t BOOTP_BUFFER_SIZE = 8;
62static const size_t BOOTP_BUFFER_OUT_SIZE = 1;
63
64/** Keyboard polling endpoint description for boot protocol class. */
65static usb_endpoint_description_t poll_endpoint_description = {
66 .transfer_type = USB_TRANSFER_INTERRUPT,
67 .direction = USB_DIRECTION_IN,
68 .interface_class = USB_CLASS_HID,
69 .interface_subclass = USB_HID_SUBCLASS_BOOT,
70 .interface_protocol = USB_HID_PROTOCOL_KEYBOARD,
71 .flags = 0
72};
73
74/*----------------------------------------------------------------------------*/
75/* Keyboard layouts */
76/*----------------------------------------------------------------------------*/
77
78#define NUM_LAYOUTS 3
79
80static layout_op_t *layout[NUM_LAYOUTS] = {
81 &us_qwerty_op,
82 &us_dvorak_op,
83 &cz_op
84};
85
86static int active_layout = 0;
87
88/*----------------------------------------------------------------------------*/
89/* Modifier constants */
90/*----------------------------------------------------------------------------*/
91
92static const keycode_t usbhid_modifiers_keycodes[USB_HID_MOD_COUNT] = {
93 KC_LCTRL, /* USB_HID_MOD_LCTRL */
94 KC_LSHIFT, /* USB_HID_MOD_LSHIFT */
95 KC_LALT, /* USB_HID_MOD_LALT */
96 0, /* USB_HID_MOD_LGUI */
97 KC_RCTRL, /* USB_HID_MOD_RCTRL */
98 KC_RSHIFT, /* USB_HID_MOD_RSHIFT */
99 KC_RALT, /* USB_HID_MOD_RALT */
100 0, /* USB_HID_MOD_RGUI */
101};
102
103/*----------------------------------------------------------------------------*/
104/* IPC method handler */
105/*----------------------------------------------------------------------------*/
106
107static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
108static ddf_dev_ops_t keyboard_ops = {
109 .default_handler = default_connection_handler
110};
111
112/** Default handler for IPC methods not handled by DDF.
113 *
114 * @param dev Device handling the call.
115 * @param icallid Call id.
116 * @param icall Call data.
117 */
118void default_connection_handler(ddf_fun_t *fun,
119 ipc_callid_t icallid, ipc_call_t *icall)
120{
121 sysarg_t method = IPC_GET_IMETHOD(*icall);
122
123 usbhid_kbd_t *kbd_dev = (usbhid_kbd_t *)fun->driver_data;
[27270db]124 assert(kbd_dev != NULL);
[2391aaf]125
126 if (method == IPC_M_CONNECT_TO_ME) {
127 int callback = IPC_GET_ARG5(*icall);
128
129 if (kbd_dev->console_phone != -1) {
130 async_answer_0(icallid, ELIMIT);
131 return;
132 }
133
134 kbd_dev->console_phone = callback;
135 async_answer_0(icallid, EOK);
136 return;
137 }
[27270db]138
[2391aaf]139 async_answer_0(icallid, EINVAL);
140}
141
142/*----------------------------------------------------------------------------*/
143/* Key processing functions */
144/*----------------------------------------------------------------------------*/
145
146static void usbhid_kbd_set_led(usbhid_kbd_t *kbd_dev)
147{
148 uint8_t buffer[BOOTP_BUFFER_OUT_SIZE];
149 int rc= 0;
150 unsigned i;
151
152 memset(buffer, 0, BOOTP_BUFFER_OUT_SIZE);
153 uint8_t leds = 0;
154
155 if (kbd_dev->mods & KM_NUM_LOCK) {
156 leds |= USB_HID_LED_NUM_LOCK;
157 }
158
159 if (kbd_dev->mods & KM_CAPS_LOCK) {
160 leds |= USB_HID_LED_CAPS_LOCK;
161 }
162
163 if (kbd_dev->mods & KM_SCROLL_LOCK) {
164 leds |= USB_HID_LED_SCROLL_LOCK;
165 }
166
167 // TODO: COMPOSE and KANA
168
169 usb_log_debug("Creating output report.\n");
170 usb_log_debug("Leds: 0x%x\n", leds);
171 if ((rc = usb_hid_boot_keyboard_output_report(
172 leds, buffer, BOOTP_BUFFER_OUT_SIZE)) != EOK) {
173 usb_log_warning("Error composing output report to the keyboard:"
174 "%s.\n", str_error(rc));
175 return;
176 }
177
178 // TODO: REFACTOR!!!
179
180 usb_log_debug("Output report buffer: ");
181 for (i = 0; i < BOOTP_BUFFER_OUT_SIZE; ++i) {
182 usb_log_debug("0x%x ", buffer[i]);
183 }
184 usb_log_debug("\n");
185
186 uint16_t value = 0;
187 value |= (USB_HID_REPORT_TYPE_OUTPUT << 8);
188
189 assert(kbd_dev->hid_dev != NULL);
190 assert(kbd_dev->hid_dev->initialized);
191 usbhid_req_set_report(kbd_dev->hid_dev, value, buffer,
192 BOOTP_BUFFER_OUT_SIZE);
193}
194
195/*----------------------------------------------------------------------------*/
196
197static void usbhid_kbd_push_ev(usbhid_kbd_t *kbd_dev, int type,
198 unsigned int key)
199{
200 console_event_t ev;
201 unsigned mod_mask;
202
203 // TODO: replace by our own parsing?? or are the key codes identical??
204 switch (key) {
205 case KC_LCTRL: mod_mask = KM_LCTRL; break;
206 case KC_RCTRL: mod_mask = KM_RCTRL; break;
207 case KC_LSHIFT: mod_mask = KM_LSHIFT; break;
208 case KC_RSHIFT: mod_mask = KM_RSHIFT; break;
209 case KC_LALT: mod_mask = KM_LALT; break;
210 case KC_RALT: mod_mask = KM_RALT; break;
211 default: mod_mask = 0; break;
212 }
213
214 if (mod_mask != 0) {
215 if (type == KEY_PRESS)
216 kbd_dev->mods = kbd_dev->mods | mod_mask;
217 else
218 kbd_dev->mods = kbd_dev->mods & ~mod_mask;
219 }
220
221 switch (key) {
222 case KC_CAPS_LOCK: mod_mask = KM_CAPS_LOCK; break;
223 case KC_NUM_LOCK: mod_mask = KM_NUM_LOCK; break;
224 case KC_SCROLL_LOCK: mod_mask = KM_SCROLL_LOCK; break;
225 default: mod_mask = 0; break;
226 }
227
228 if (mod_mask != 0) {
229 usb_log_debug2("\n\nChanging mods and lock keys\n");
230 usb_log_debug2("\nmods before: 0x%x\n", kbd_dev->mods);
231 usb_log_debug2("\nLock keys before:0x%x\n\n",
232 kbd_dev->lock_keys);
233
234 if (type == KEY_PRESS) {
235 usb_log_debug2("\nKey pressed.\n");
236 /*
237 * Only change lock state on transition from released
238 * to pressed. This prevents autorepeat from messing
239 * up the lock state.
240 */
241 kbd_dev->mods =
242 kbd_dev->mods ^ (mod_mask & ~kbd_dev->lock_keys);
243 kbd_dev->lock_keys = kbd_dev->lock_keys | mod_mask;
244
245 /* Update keyboard lock indicator lights. */
246 usbhid_kbd_set_led(kbd_dev);
247 } else {
248 usb_log_debug2("\nKey released.\n");
249 kbd_dev->lock_keys = kbd_dev->lock_keys & ~mod_mask;
250 }
251 }
252
253 usb_log_debug2("\n\nmods after: 0x%x\n", kbd_dev->mods);
254 usb_log_debug2("\nLock keys after: 0x%x\n\n", kbd_dev->lock_keys);
255
256 if (type == KEY_PRESS && (kbd_dev->mods & KM_LCTRL) && key == KC_F1) {
257 active_layout = 0;
258 layout[active_layout]->reset();
259 return;
260 }
261
262 if (type == KEY_PRESS && (kbd_dev->mods & KM_LCTRL) && key == KC_F2) {
263 active_layout = 1;
264 layout[active_layout]->reset();
265 return;
266 }
267
268 if (type == KEY_PRESS && (kbd_dev->mods & KM_LCTRL) && key == KC_F3) {
269 active_layout = 2;
270 layout[active_layout]->reset();
271 return;
272 }
273
274 ev.type = type;
275 ev.key = key;
276 ev.mods = kbd_dev->mods;
277
278 if (ev.mods & KM_NUM_LOCK) {
279 usb_log_debug("\n\nNum Lock turned on.\n\n");
280 }
281
282 ev.c = layout[active_layout]->parse_ev(&ev);
283
284 usb_log_debug2("Sending key %d to the console\n", ev.key);
285 assert(kbd_dev->console_phone != -1);
286
287 async_msg_4(kbd_dev->console_phone, KBD_EVENT, ev.type, ev.key,
288 ev.mods, ev.c);
289}
290
291/*----------------------------------------------------------------------------*/
292
293static void usbhid_kbd_check_modifier_changes(usbhid_kbd_t *kbd_dev,
294 uint8_t modifiers)
295{
296 /*
297 * TODO: why the USB keyboard has NUM_, SCROLL_ and CAPS_LOCK
298 * both as modifiers and as keys with their own scancodes???
299 *
300 * modifiers should be sent as normal keys to usbhid_parse_scancode()!!
301 * so maybe it would be better if I received it from report parser in
302 * that way
303 */
304
305 int i;
306 for (i = 0; i < USB_HID_MOD_COUNT; ++i) {
307 if ((modifiers & usb_hid_modifiers_consts[i]) &&
308 !(kbd_dev->modifiers & usb_hid_modifiers_consts[i])) {
309 // modifier pressed
310 if (usbhid_modifiers_keycodes[i] != 0) {
311 usbhid_kbd_push_ev(kbd_dev, KEY_PRESS,
312 usbhid_modifiers_keycodes[i]);
313 }
314 } else if (!(modifiers & usb_hid_modifiers_consts[i]) &&
315 (kbd_dev->modifiers & usb_hid_modifiers_consts[i])) {
316 // modifier released
317 if (usbhid_modifiers_keycodes[i] != 0) {
318 usbhid_kbd_push_ev(kbd_dev, KEY_RELEASE,
319 usbhid_modifiers_keycodes[i]);
320 }
321 } // no change
322 }
323
324 kbd_dev->modifiers = modifiers;
325}
326
327/*----------------------------------------------------------------------------*/
328
329static void usbhid_kbd_check_key_changes(usbhid_kbd_t *kbd_dev,
330 const uint8_t *key_codes)
331{
332 // TODO: phantom state!!
333
334 unsigned int key;
335 unsigned int i, j;
336
337 // TODO: quite dummy right now, think of better implementation
338
339 /*
340 * 1) Key releases
341 */
342 for (j = 0; j < kbd_dev->keycode_count; ++j) {
343 // try to find the old key in the new key list
344 i = 0;
345 while (i < kbd_dev->keycode_count
346 && key_codes[i] != kbd_dev->keycodes[j]) {
347 ++i;
348 }
349
350 if (i == kbd_dev->keycode_count) {
351 // not found, i.e. the key was released
352 key = usbhid_parse_scancode(kbd_dev->keycodes[j]);
353 usbhid_kbd_push_ev(kbd_dev, KEY_RELEASE, key);
354 usb_log_debug2("\nKey released: %d\n", key);
355 } else {
356 // found, nothing happens
357 }
358 }
359
360 /*
361 * 1) Key presses
362 */
363 for (i = 0; i < kbd_dev->keycode_count; ++i) {
364 // try to find the new key in the old key list
365 j = 0;
366 while (j < kbd_dev->keycode_count
367 && kbd_dev->keycodes[j] != key_codes[i]) {
368 ++j;
369 }
370
371 if (j == kbd_dev->keycode_count) {
372 // not found, i.e. new key pressed
373 key = usbhid_parse_scancode(key_codes[i]);
374 usb_log_debug2("\nKey pressed: %d (keycode: %d)\n", key,
375 key_codes[i]);
376 usbhid_kbd_push_ev(kbd_dev, KEY_PRESS, key);
377 } else {
378 // found, nothing happens
379 }
380 }
381
382 memcpy(kbd_dev->keycodes, key_codes, kbd_dev->keycode_count);
383
384 usb_log_debug2("\nNew stored keycodes: ");
385 for (i = 0; i < kbd_dev->keycode_count; ++i) {
386 usb_log_debug2("%d ", kbd_dev->keycodes[i]);
387 }
388}
389
390/*----------------------------------------------------------------------------*/
391/* Callbacks for parser */
392/*----------------------------------------------------------------------------*/
393
394static void usbhid_kbd_process_keycodes(const uint8_t *key_codes, size_t count,
395 uint8_t modifiers, void *arg)
396{
397 if (arg == NULL) {
398 usb_log_warning("Missing argument in callback "
399 "usbhid_process_keycodes().\n");
400 return;
401 }
402
403 usb_log_debug2("Got keys from parser: ");
404 unsigned i;
405 for (i = 0; i < count; ++i) {
406 usb_log_debug2("%d ", key_codes[i]);
407 }
408 usb_log_debug2("\n");
409
410 usbhid_kbd_t *kbd_dev = (usbhid_kbd_t *)arg;
411 assert(kbd_dev != NULL);
412
413 if (count != kbd_dev->keycode_count) {
414 usb_log_warning("Number of received keycodes (%d) differs from"
415 " expected number (%d).\n", count, kbd_dev->keycode_count);
416 return;
417 }
418
419 usbhid_kbd_check_modifier_changes(kbd_dev, modifiers);
420 usbhid_kbd_check_key_changes(kbd_dev, key_codes);
421}
422
423/*----------------------------------------------------------------------------*/
424/* General kbd functions */
425/*----------------------------------------------------------------------------*/
426
427static void usbhid_kbd_process_data(usbhid_kbd_t *kbd_dev,
428 uint8_t *buffer, size_t actual_size)
429{
430 usb_hid_report_in_callbacks_t *callbacks =
431 (usb_hid_report_in_callbacks_t *)malloc(
432 sizeof(usb_hid_report_in_callbacks_t));
433
434 callbacks->keyboard = usbhid_kbd_process_keycodes;
435
436 //usb_hid_parse_report(kbd_dev->parser, buffer, actual_size, callbacks,
437 // NULL);
438 /*usb_log_debug2("Calling usb_hid_boot_keyboard_input_report() with size"
439 " %zu\n", actual_size);*/
440 //dump_buffer("bufffer: ", buffer, actual_size);
441
442 int rc = usb_hid_boot_keyboard_input_report(buffer, actual_size,
443 callbacks, kbd_dev);
444
445 if (rc != EOK) {
446 usb_log_warning("Error in usb_hid_boot_keyboard_input_report():"
447 "%s\n", str_error(rc));
448 }
449}
450
451/*----------------------------------------------------------------------------*/
452/* HID/KBD structure manipulation */
453/*----------------------------------------------------------------------------*/
454
455static usbhid_kbd_t *usbhid_kbd_new()
456{
457 usbhid_kbd_t *kbd_dev =
458 (usbhid_kbd_t *)malloc(sizeof(usbhid_kbd_t));
459
460 if (kbd_dev == NULL) {
461 usb_log_fatal("No memory!\n");
462 return NULL;
463 }
464
465 memset(kbd_dev, 0, sizeof(usbhid_kbd_t));
466
467 kbd_dev->hid_dev = usbhid_dev_new();
468 if (kbd_dev->hid_dev == NULL) {
469 usb_log_fatal("Could not create HID device structure.\n");
470 return NULL;
471 }
472
[27270db]473 kbd_dev->console_phone = -1;
[2391aaf]474 kbd_dev->initialized = 0;
475
476 return kbd_dev;
477}
478
479/*----------------------------------------------------------------------------*/
480
481static int usbhid_kbd_init(usbhid_kbd_t *kbd_dev, ddf_dev_t *dev)
482{
483 int rc;
484
485 usb_log_info("Initializing HID/KBD structure...\n");
486
487 if (kbd_dev == NULL) {
488 usb_log_error("Failed to init keyboard structure: no structure"
489 " given.\n");
490 return EINVAL;
491 }
492
493 if (dev == NULL) {
494 usb_log_error("Failed to init keyboard structure: no device"
495 " given.\n");
496 return EINVAL;
497 }
498
499 if (kbd_dev->initialized) {
500 usb_log_warning("Keyboard structure already initialized.\n");
501 return EINVAL;
502 }
503
504 rc = usbhid_dev_init(kbd_dev->hid_dev, dev, &poll_endpoint_description);
505
506 if (rc != EOK) {
507 usb_log_error("Failed to initialize HID device structure: %s\n",
508 str_error(rc));
509 return rc;
510 }
511
512 assert(kbd_dev->hid_dev->initialized);
513
514 // save the size of the report (boot protocol report by default)
515 kbd_dev->keycode_count = BOOTP_REPORT_SIZE;
516 kbd_dev->keycodes = (uint8_t *)calloc(
517 kbd_dev->keycode_count, sizeof(uint8_t));
518
519 if (kbd_dev->keycodes == NULL) {
520 usb_log_fatal("No memory!\n");
521 return rc;
522 }
523
524 kbd_dev->modifiers = 0;
525 kbd_dev->mods = DEFAULT_ACTIVE_MODS;
526 kbd_dev->lock_keys = 0;
527
528 /*
529 * Set boot protocol.
530 * Set LEDs according to initial setup.
531 */
532 assert(kbd_dev->hid_dev != NULL);
533 assert(kbd_dev->hid_dev->initialized);
534 usbhid_req_set_protocol(kbd_dev->hid_dev, USB_HID_PROTOCOL_BOOT);
535
536 usbhid_kbd_set_led(kbd_dev);
537
538 kbd_dev->initialized = 1;
539 usb_log_info("HID/KBD device structure initialized.\n");
540
541 return EOK;
542}
543
544/*----------------------------------------------------------------------------*/
545/* HID/KBD polling */
546/*----------------------------------------------------------------------------*/
547
548static void usbhid_kbd_poll(usbhid_kbd_t *kbd_dev)
549{
550 int rc, sess_rc;
551 uint8_t buffer[BOOTP_BUFFER_SIZE];
552 size_t actual_size;
553
554 usb_log_info("Polling keyboard...\n");
555
556 if (!kbd_dev->initialized) {
557 usb_log_error("HID/KBD device not initialized!\n");
558 return;
559 }
560
561 assert(kbd_dev->hid_dev != NULL);
562 assert(kbd_dev->hid_dev->initialized);
563
564 while (true) {
565 async_usleep(1000 * 10);
566
567 sess_rc = usb_endpoint_pipe_start_session(
568 &kbd_dev->hid_dev->poll_pipe);
569 if (sess_rc != EOK) {
570 usb_log_warning("Failed to start a session: %s.\n",
571 str_error(sess_rc));
572 continue;
573 }
574
575 rc = usb_endpoint_pipe_read(&kbd_dev->hid_dev->poll_pipe,
576 buffer, BOOTP_BUFFER_SIZE, &actual_size);
577
578 sess_rc = usb_endpoint_pipe_end_session(
579 &kbd_dev->hid_dev->poll_pipe);
580
581 if (rc != EOK) {
582 usb_log_warning("Error polling the keyboard: %s.\n",
583 str_error(rc));
584 continue;
585 }
586
587 if (sess_rc != EOK) {
588 usb_log_warning("Error closing session: %s.\n",
589 str_error(sess_rc));
590 continue;
591 }
592
593 /*
594 * If the keyboard answered with NAK, it returned no data.
595 * This implies that no change happened since last query.
596 */
597 if (actual_size == 0) {
598 usb_log_debug("Keyboard returned NAK\n");
599 continue;
600 }
601
602 /*
603 * TODO: Process pressed keys.
604 */
605 usb_log_debug("Calling usbhid_kbd_process_data()\n");
606 usbhid_kbd_process_data(kbd_dev, buffer, actual_size);
607 }
608
609 // not reached
610 assert(0);
611}
612
613/*----------------------------------------------------------------------------*/
614
615static int usbhid_kbd_fibril(void *arg)
616{
617 if (arg == NULL) {
618 usb_log_error("No device!\n");
619 return EINVAL;
620 }
621
622 usbhid_kbd_t *kbd_dev = (usbhid_kbd_t *)arg;
623
624 usbhid_kbd_poll(kbd_dev);
625
626 return EOK;
627}
628
629/*----------------------------------------------------------------------------*/
630/* API functions */
631/*----------------------------------------------------------------------------*/
632
633int usbhid_kbd_try_add_device(ddf_dev_t *dev)
634{
635 /*
636 * Create default function.
637 */
638 ddf_fun_t *kbd_fun = ddf_fun_create(dev, fun_exposed, "keyboard");
639 if (kbd_fun == NULL) {
640 usb_log_error("Could not create DDF function node.\n");
641 return ENOMEM;
642 }
643
644 /*
645 * Initialize device (get and process descriptors, get address, etc.)
646 */
647 usb_log_info("Initializing USB HID/KBD device...\n");
648
649 usbhid_kbd_t *kbd_dev = usbhid_kbd_new();
650 if (kbd_dev == NULL) {
651 usb_log_error("Error while creating USB HID/KBD device "
652 "structure.\n");
653 ddf_fun_destroy(kbd_fun);
654 return EINVAL; // TODO: some other code??
655 }
656
657 int rc = usbhid_kbd_init(kbd_dev, dev);
658
659 if (rc != EOK) {
660 usb_log_error("Failed to initialize USB HID/KBD device.\n");
661 ddf_fun_destroy(kbd_fun);
662 return rc;
663 }
664
665 usb_log_info("USB/KBD device structure initialized.\n");
666
667 /*
668 * Store the initialized keyboard device and keyboard ops
669 * to the DDF function.
670 */
671 kbd_fun->driver_data = kbd_dev;
672 kbd_fun->ops = &keyboard_ops;
673
674 rc = ddf_fun_bind(kbd_fun);
675 if (rc != EOK) {
676 usb_log_error("Could not bind DDF function.\n");
677 return rc;
678 }
679
680 rc = ddf_fun_add_to_class(kbd_fun, "keyboard");
681 if (rc != EOK) {
682 usb_log_error("Could not add DDF function to class 'keyboard'"
683 "\n");
684 return rc;
685 }
686
687 /*
688 * Create new fibril for handling this keyboard
689 */
690 fid_t fid = fibril_create(usbhid_kbd_fibril, kbd_dev);
691 if (fid == 0) {
692 usb_log_error("Failed to start fibril for HID device\n");
693 return ENOMEM;
694 }
695 fibril_add_ready(fid);
696
697 (void)keyboard_ops;
698
699 /*
700 * Hurrah, device is initialized.
701 */
702 return EOK;
703}
704
705/**
706 * @}
707 */
Note: See TracBrowser for help on using the repository browser.