source: mainline/uspace/drv/usbkbd/main.c@ e080332

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since e080332 was f9a0cef, checked in by Vojtech Horky <vojtechhorky@…>, 15 years ago

Add clearing status changes in hub driver

Also, both keyboard and hub driver question with interval of 1s.

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