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
RevLine 
[c7137738]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>
[2e15ac40]30#include <ipc/driver.h>
[c7137738]31#include <errno.h>
[2e15ac40]32#include <fibril.h>
33#include <usb/classes/hid.h>
[243cb86]34#include <usb/classes/hidparser.h>
35#include <usb/devreq.h>
[dafab9e0]36#include <usb/descriptor.h>
[c7137738]37
[91db50ac]38#define BUFFER_SIZE 32
[2e15ac40]39#define NAME "usbkbd"
40
[1b29d6fa]41#define GUESSED_POLL_ENDPOINT 1
[2e15ac40]42
[243cb86]43/*
44 * Callbacks for parser
45 */
46static void usbkbd_process_keycodes(const uint16_t *key_codes, size_t count,
47 void *arg)
[91db50ac]48{
49
[243cb86]50}
[0e126be7]51
[243cb86]52/*
53 * Kbd functions
54 */
[dafab9e0]55static int usbkbd_parse_descriptors(usb_hid_dev_kbd_t *kbd_dev,
56 const uint8_t *data, size_t size)
[243cb86]57{
[dafab9e0]58// const uint8_t *pos = data;
[243cb86]59
[dafab9e0]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// }
[243cb86]66
[dafab9e0]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}
[0e126be7]92
[dafab9e0]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
[91db50ac]117 if (rc != EOK) {
[243cb86]118 return rc;
[91db50ac]119 }
[dafab9e0]120 if (transferred != config_desc.total_length) {
121 return ELIMIT;
122 }
123
124 rc = usbkbd_parse_descriptors(kbd_dev, descriptors, transferred);
125 free(descriptors);
[243cb86]126
[dafab9e0]127 return rc;
[243cb86]128}
[91db50ac]129
[2e15ac40]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
[101ef25c]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
[2e15ac40]146 kbd_dev->address = usb_drv_get_my_address(dev->parent_phone,
147 dev);
148
[101ef25c]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// }
[2e15ac40]155
156 // default endpoint
[1b29d6fa]157 kbd_dev->poll_endpoint = GUESSED_POLL_ENDPOINT;
[dafab9e0]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 */
[2e15ac40]165
166 // TODO: get descriptors
[dafab9e0]167 usbkbd_get_descriptors(kbd_dev);
[2e15ac40]168 // TODO: parse descriptors and save endpoints
169
170 return kbd_dev;
171}
[91db50ac]172
[101ef25c]173static void usbkbd_process_interrupt_in(usb_hid_dev_kbd_t *kbd_dev,
[243cb86]174 uint8_t *buffer, size_t actual_size)
[101ef25c]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 */
[243cb86]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
[dafab9e0]186 usb_hid_parse_report(kbd_dev->parser, buffer, actual_size, callbacks,
187 NULL);
[101ef25c]188}
189
[2e15ac40]190static void usbkbd_poll_keyboard(usb_hid_dev_kbd_t *kbd_dev)
[91db50ac]191{
192 int rc;
193 usb_handle_t handle;
[243cb86]194 uint8_t buffer[BUFFER_SIZE];
[91db50ac]195 size_t actual_size;
[2e15ac40]196 //usb_endpoint_t poll_endpoint = 1;
[91db50ac]197
[2e15ac40]198// usb_address_t my_address = usb_drv_get_my_address(dev->parent_phone,
199// dev);
200// if (my_address < 0) {
201// return;
202// }
[0e126be7]203
204 usb_target_t poll_target = {
[2e15ac40]205 .address = kbd_dev->address,
[1b29d6fa]206 .endpoint = kbd_dev->poll_endpoint
[0e126be7]207 };
208
[101ef25c]209 while (true) {
[f9a0cef]210 async_usleep(1000 * 1000);
[101ef25c]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);
[91db50ac]235 }
236
[101ef25c]237 // not reached
238 assert(0);
[91db50ac]239}
240
[2e15ac40]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)
[c7137738]261{
262 /* For now, fail immediately. */
[101ef25c]263 //return ENOTSUP;
[c7137738]264
265 /*
266 * When everything is okay, connect to "our" HC.
[2e15ac40]267 *
268 * Not supported yet, skip..
[c7137738]269 */
[2e15ac40]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// }
[c7137738]278
[2e15ac40]279// dev->parent_phone = phone;
[91db50ac]280
281 /*
[2e15ac40]282 * Create new fibril for handling this keyboard
[91db50ac]283 */
[2e15ac40]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);
[91db50ac]290
[c7137738]291 /*
292 * Hurrah, device is initialized.
293 */
294 return EOK;
295}
296
297static driver_ops_t kbd_driver_ops = {
[2e15ac40]298 .add_device = usbkbd_add_device,
[c7137738]299};
300
301static driver_t kbd_driver = {
[2e15ac40]302 .name = NAME,
[c7137738]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.