source: mainline/uspace/drv/usbkbd/main.c@ 1f383dde

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

Debugging

  • disabled some output from other parts (virtual hcd)
  • added some debug output to descparser
  • Property mode set to 100644
File size: 7.0 KB
Line 
1/*
2 * Copyright (c) 2010 Vojtech Horky
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#include <usb/usbdrv.h>
29#include <driver.h>
30#include <ipc/driver.h>
31#include <errno.h>
32#include <fibril.h>
33#include <usb/classes/hid.h>
34#include <usb/classes/hidparser.h>
35#include <usb/devreq.h>
36#include <usb/descriptor.h>
37#include "descparser.h"
38
39#define BUFFER_SIZE 32
40#define NAME "usbkbd"
41
42#define GUESSED_POLL_ENDPOINT 1
43
44/*
45 * Callbacks for parser
46 */
47static void usbkbd_process_keycodes(const uint16_t *key_codes, size_t count,
48 void *arg)
49{
50 printf("Got keys: ");
51 unsigned i;
52 for (i = 0; i < count; ++i) {
53 printf("%d ", key_codes[i]);
54 }
55 printf("\n");
56}
57
58/*
59 * Kbd functions
60 */
61static int usbkbd_process_descriptors(usb_hid_dev_kbd_t *kbd_dev)
62{
63 // get the first configuration descriptor (TODO: parse also other!)
64 usb_standard_configuration_descriptor_t config_desc;
65
66 int rc = usb_drv_req_get_bare_configuration_descriptor(
67 kbd_dev->device->parent_phone, kbd_dev->address, 0, &config_desc);
68
69 if (rc != EOK) {
70 return rc;
71 }
72
73 // prepare space for all underlying descriptors
74 uint8_t *descriptors = (uint8_t *)malloc(config_desc.total_length);
75 if (descriptors == NULL) {
76 return ENOMEM;
77 }
78
79 size_t transferred = 0;
80 // get full configuration descriptor
81 rc = usb_drv_req_get_full_configuration_descriptor(
82 kbd_dev->device->parent_phone, kbd_dev->address, 0, descriptors,
83 config_desc.total_length, &transferred);
84
85 if (rc != EOK) {
86 return rc;
87 }
88 if (transferred != config_desc.total_length) {
89 return ELIMIT;
90 }
91
92 kbd_dev->conf = (usb_hid_configuration_t *)calloc(1,
93 sizeof(usb_hid_configuration_t));
94 if (kbd_dev->conf == NULL) {
95 free(descriptors);
96 return ENOMEM;
97 }
98
99 rc = usbkbd_parse_descriptors(descriptors, transferred, kbd_dev->conf);
100 free(descriptors);
101
102 //usbkbd_print_config(kbd_dev->conf);
103
104 return rc;
105}
106
107static usb_hid_dev_kbd_t *usbkbd_init_device(device_t *dev)
108{
109 usb_hid_dev_kbd_t *kbd_dev = (usb_hid_dev_kbd_t *)calloc(1,
110 sizeof(usb_hid_dev_kbd_t));
111
112 if (kbd_dev == NULL) {
113 fprintf(stderr, NAME ": No memory!\n");
114 return NULL;
115 }
116
117 kbd_dev->device = dev;
118
119 // get phone to my HC and save it as my parent's phone
120 // TODO: maybe not a good idea if DDF will use parent_phone
121 kbd_dev->device->parent_phone = usb_drv_hc_connect(dev, 0);
122
123 kbd_dev->address = usb_drv_get_my_address(dev->parent_phone,
124 dev);
125
126 // doesn't matter now that we have no address
127// if (kbd_dev->address < 0) {
128// fprintf(stderr, NAME ": No device address!\n");
129// free(kbd_dev);
130// return NULL;
131// }
132
133 // default endpoint
134 kbd_dev->poll_endpoint = GUESSED_POLL_ENDPOINT;
135
136 /*
137 * will need all descriptors:
138 * 1) choose one configuration from configuration descriptors
139 * (set it to the device)
140 * 2) set endpoints from endpoint descriptors
141 */
142
143 // TODO: get descriptors, parse descriptors and save endpoints
144 usbkbd_process_descriptors(kbd_dev);
145
146 return kbd_dev;
147}
148
149static void usbkbd_process_interrupt_in(usb_hid_dev_kbd_t *kbd_dev,
150 uint8_t *buffer, size_t actual_size)
151{
152 /*
153 * here, the parser will be called, probably with some callbacks
154 * now only take last 6 bytes and process, i.e. send to kbd
155 */
156
157 usb_hid_report_in_callbacks_t *callbacks =
158 (usb_hid_report_in_callbacks_t *)malloc(
159 sizeof(usb_hid_report_in_callbacks_t));
160 callbacks->keyboard = usbkbd_process_keycodes;
161
162 usb_hid_parse_report(kbd_dev->parser, buffer, actual_size, callbacks,
163 NULL);
164}
165
166static void usbkbd_poll_keyboard(usb_hid_dev_kbd_t *kbd_dev)
167{
168 int rc;
169 usb_handle_t handle;
170 uint8_t buffer[BUFFER_SIZE];
171 size_t actual_size;
172 //usb_endpoint_t poll_endpoint = 1;
173
174// usb_address_t my_address = usb_drv_get_my_address(dev->parent_phone,
175// dev);
176// if (my_address < 0) {
177// return;
178// }
179
180 usb_target_t poll_target = {
181 .address = kbd_dev->address,
182 .endpoint = kbd_dev->poll_endpoint
183 };
184
185 while (true) {
186 async_usleep(1000 * 1000);
187 rc = usb_drv_async_interrupt_in(kbd_dev->device->parent_phone,
188 poll_target, buffer, BUFFER_SIZE, &actual_size, &handle);
189
190 if (rc != EOK) {
191 continue;
192 }
193
194 rc = usb_drv_async_wait_for(handle);
195 if (rc != EOK) {
196 continue;
197 }
198
199 /*
200 * If the keyboard answered with NAK, it returned no data.
201 * This implies that no change happened since last query.
202 */
203 if (actual_size == 0) {
204 continue;
205 }
206
207 /*
208 * TODO: Process pressed keys.
209 */
210 usbkbd_process_interrupt_in(kbd_dev, buffer, actual_size);
211 }
212
213 // not reached
214 assert(0);
215}
216
217static int usbkbd_fibril_device(void *arg)
218{
219 printf("!!! USB device fibril\n");
220
221 if (arg == NULL) {
222 printf("No device!\n");
223 return -1;
224 }
225
226 device_t *dev = (device_t *)arg;
227
228 // initialize device (get and process descriptors, get address, etc.)
229 usb_hid_dev_kbd_t *kbd_dev = usbkbd_init_device(dev);
230
231 usbkbd_poll_keyboard(kbd_dev);
232
233 return EOK;
234}
235
236static int usbkbd_add_device(device_t *dev)
237{
238 /* For now, fail immediately. */
239 //return ENOTSUP;
240
241 /*
242 * When everything is okay, connect to "our" HC.
243 *
244 * Not supported yet, skip..
245 */
246// int phone = usb_drv_hc_connect(dev, 0);
247// if (phone < 0) {
248// /*
249// * Connecting to HC failed, roll-back and announce
250// * failure.
251// */
252// return phone;
253// }
254
255// dev->parent_phone = phone;
256
257 /*
258 * Create new fibril for handling this keyboard
259 */
260 fid_t fid = fibril_create(usbkbd_fibril_device, dev);
261 if (fid == 0) {
262 printf("%s: failed to start fibril for HID device\n", NAME);
263 return ENOMEM;
264 }
265 fibril_add_ready(fid);
266
267 /*
268 * Hurrah, device is initialized.
269 */
270 return EOK;
271}
272
273static driver_ops_t kbd_driver_ops = {
274 .add_device = usbkbd_add_device,
275};
276
277static driver_t kbd_driver = {
278 .name = NAME,
279 .driver_ops = &kbd_driver_ops
280};
281
282int main(int argc, char *argv[])
283{
284 return driver_main(&kbd_driver);
285}
Note: See TracBrowser for help on using the repository browser.