source: mainline/uspace/drv/usbhid/descparser.c@ e7b7ebd5

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

Merge mainline changes (DDF refactoring)

This merge includes DDF refactoring that brought multifunctional devices
(i.e. ddf_dev_t and ddf_fun_t). Please, see ticket #295 at HelenOS
upstream Trac.

The conflicts themselves were easy to solve (merely several renamings).

Changes to USB subsystem:

  • drivers uses ddf_dev_t and ddf_fun_t
  • different signatures of many library functions
  • several hacks around communication with parent device (now the communication is clearer and somehow what we have now is hack about other hacks)
    • will repair and clean later
  • maybe added some extra debugging messages (the diff has about 240K, and I admit I have no energy to double check that)

WARNING:

  • the diff is VERY long, recommended is viewing partial diffs of the merge (i.e. merges in mainline branch that lead to the parent one)
  • merging with your branches might involve huge renamings, sorry, no other way is possible

BUGS:

  • hub driver will not work (no function created)

GOOD NEWS:

  • QEMU keyboard seems to work with QEMU 0.13 and 0.14
  • we are up-to-date with mainline again
  • Property mode set to 100644
File size: 10.0 KB
Line 
1/*
2 * Copyright (c) 2010 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/** @file
33 * Descriptor parser.
34 */
35
36#include <errno.h>
37#include <stdint.h>
38#include <stdio.h>
39#include <usb/usb.h>
40#include <usb/classes/hid.h>
41#include <usb/descriptor.h>
42#include "descparser.h"
43#include "descdump.h"
44
45static void usbkbd_config_free(usb_hid_configuration_t *config)
46{
47 if (config == NULL) {
48 return;
49 }
50
51 if (config->interfaces == NULL) {
52 return;
53 }
54
55 int i;
56 for (i = 0; i < config->config_descriptor.interface_count; ++i) {
57
58 usb_hid_iface_t *iface = &config->interfaces[i];
59
60 if (iface->endpoints != NULL) {
61 free(config->interfaces[i].endpoints);
62 }
63 /*if (iface->class_desc_info != NULL) {
64 free(iface->class_desc_info);
65 }
66 if (iface->class_descs != NULL) {
67 int j;
68 for (j = 0;
69 j < iface->hid_desc.class_desc_count;
70 ++j) {
71 if (iface->class_descs[j] != NULL) {
72 free(iface->class_descs[j]);
73 }
74 }
75 }*/
76 }
77
78 free(config->interfaces);
79}
80
81/*----------------------------------------------------------------------------*/
82
83
84
85/*----------------------------------------------------------------------------*/
86
87int usbkbd_parse_descriptors(const uint8_t *data, size_t size,
88 usb_hid_configuration_t *config)
89{
90 if (config == NULL) {
91 return EINVAL;
92 }
93
94 const uint8_t *pos = data;
95
96 // get the configuration descriptor (should be first) || *config == NULL
97 if (*pos != sizeof(usb_standard_configuration_descriptor_t)
98 || *(pos + 1) != USB_DESCTYPE_CONFIGURATION) {
99 fprintf(stderr, "Wrong format of configuration descriptor.\n");
100 return EINVAL;
101 }
102
103 memcpy(&config->config_descriptor, pos,
104 sizeof(usb_standard_configuration_descriptor_t));
105 pos += sizeof(usb_standard_configuration_descriptor_t);
106
107 //printf("Parsed configuration descriptor: \n");
108 //dump_standard_configuration_descriptor(0, &config->config_descriptor);
109
110 int ret = EOK;
111
112 // first descriptor after configuration should be interface
113 if (*(pos + 1) != USB_DESCTYPE_INTERFACE) {
114 fprintf(stderr, "Expected interface descriptor, but got %u.\n",
115 *(pos + 1));
116 return EINVAL;
117 }
118
119 // prepare place for interface descriptors
120 config->interfaces = (usb_hid_iface_t *)calloc(
121 config->config_descriptor.interface_count, sizeof(usb_hid_iface_t));
122
123 int iface_i = 0;
124 // as long as these are < 0, there is no space allocated for
125 // the respective structures
126 int ep_i = -1;
127 //int hid_i = -1;
128
129 usb_hid_iface_t *actual_iface = NULL;
130 //usb_standard_endpoint_descriptor_t *actual_ep = NULL;
131
132 // parse other descriptors
133 while ((size_t)(pos - data) < size) {
134 uint8_t desc_size = *pos;
135 uint8_t desc_type = *(pos + 1); // 2nd byte is descriptor size
136
137 switch (desc_type) {
138 case USB_DESCTYPE_INTERFACE:
139 if (desc_size !=
140 sizeof(usb_standard_interface_descriptor_t)) {
141 ret = EINVAL;
142 goto end;
143 }
144
145 actual_iface = &config->interfaces[iface_i++];
146
147 memcpy(&actual_iface->iface_desc, pos, desc_size);
148 pos += desc_size;
149
150 //printf("Parsed interface descriptor: \n");
151 //dump_standard_interface_descriptor(&actual_iface->iface_desc);
152
153 // allocate space for endpoint descriptors
154 uint8_t eps = actual_iface->iface_desc.endpoint_count;
155 actual_iface->endpoints =
156 (usb_standard_endpoint_descriptor_t *)malloc(
157 eps * sizeof(usb_standard_endpoint_descriptor_t));
158 if (actual_iface->endpoints == NULL) {
159 ret = ENOMEM;
160 goto end;
161 }
162 ep_i = 0;
163
164 //printf("Remaining size: %d\n", size - (size_t)(pos - data));
165
166 break;
167 case USB_DESCTYPE_ENDPOINT:
168 if (desc_size !=
169 sizeof(usb_standard_endpoint_descriptor_t)) {
170 ret = EINVAL;
171 goto end;
172 }
173
174 if (ep_i < 0) {
175 fprintf(stderr, "Missing interface descriptor "
176 "before endpoint descriptor.\n");
177 ret = EINVAL;
178 goto end;
179 }
180 if (ep_i > actual_iface->iface_desc.endpoint_count) {
181 fprintf(stderr, "More endpoint descriptors than"
182 " expected.\n");
183 ret = EINVAL;
184 goto end;
185 }
186
187 // save the endpoint descriptor
188 memcpy(&actual_iface->endpoints[ep_i], pos, desc_size);
189 pos += desc_size;
190
191 //printf("Parsed endpoint descriptor: \n");
192 //dump_standard_endpoint_descriptor(&actual_iface->endpoints[ep_i]);
193 ++ep_i;
194
195 break;
196 case USB_DESCTYPE_HID:
197 if (desc_size < sizeof(usb_standard_hid_descriptor_t)) {
198 printf("Wrong size of descriptor: %d (should be %zu)\n",
199 desc_size, sizeof(usb_standard_hid_descriptor_t));
200 ret = EINVAL;
201 goto end;
202 }
203
204 // copy the header of the hid descriptor
205 memcpy(&actual_iface->hid_desc, pos,
206 sizeof(usb_standard_hid_descriptor_t));
207 pos += sizeof(usb_standard_hid_descriptor_t);
208
209 /*if (actual_iface->hid_desc.class_desc_count
210 * sizeof(usb_standard_hid_class_descriptor_info_t)
211 != desc_size
212 - sizeof(usb_standard_hid_descriptor_t)) {
213 fprintf(stderr, "Wrong size of HID descriptor."
214 "\n");
215 ret = EINVAL;
216 goto end;
217 }*/
218
219 //printf("Parsed HID descriptor header: \n");
220 //dump_standard_hid_descriptor_header(&actual_iface->hid_desc);
221
222 // allocate space for all class-specific descriptor info
223 /*actual_iface->class_desc_info =
224 (usb_standard_hid_class_descriptor_info_t *)malloc(
225 actual_iface->hid_desc.class_desc_count
226 * sizeof(usb_standard_hid_class_descriptor_info_t));
227 if (actual_iface->class_desc_info == NULL) {
228 ret = ENOMEM;
229 goto end;
230 }*/
231
232 // allocate space for all class-specific descriptors
233 /*actual_iface->class_descs = (uint8_t **)calloc(
234 actual_iface->hid_desc.class_desc_count,
235 sizeof(uint8_t *));
236 if (actual_iface->class_descs == NULL) {
237 ret = ENOMEM;
238 goto end;
239 }*/
240
241 // copy all class-specific descriptor info
242 // TODO: endianness
243 /*
244 memcpy(actual_iface->class_desc_info, pos,
245 actual_iface->hid_desc.class_desc_count
246 * sizeof(usb_standard_hid_class_descriptor_info_t));
247 pos += actual_iface->hid_desc.class_desc_count
248 * sizeof(usb_standard_hid_class_descriptor_info_t);
249
250 printf("Parsed HID descriptor info:\n");
251 dump_standard_hid_class_descriptor_info(
252 actual_iface->class_desc_info);
253 */
254
255 /*size_t tmp = (size_t)(pos - data);
256 printf("Parser position: %d, remaining: %d\n",
257 pos - data, size - tmp);*/
258
259 //hid_i = 0;
260
261 break;
262/* case USB_DESCTYPE_HID_REPORT:
263 case USB_DESCTYPE_HID_PHYSICAL: {
264 // check if the type matches
265 uint8_t exp_type =
266 actual_iface->class_desc_info[hid_i].type;
267 if (exp_type != desc_type) {
268 fprintf(stderr, "Expected descriptor type %u, "
269 "but got %u.\n", exp_type, desc_type);
270 ret = EINVAL;
271 goto end;
272 }
273
274 // the size of this descriptor is stored in the
275 // class-specific descriptor info
276 uint16_t length =
277 actual_iface->class_desc_info[hid_i].length;
278
279 printf("Saving class-specific descriptor #%d\n", hid_i);
280
281 actual_iface->class_descs[hid_i] =
282 (uint8_t *)malloc(length);
283 if (actual_iface->class_descs[hid_i] == NULL) {
284 ret = ENOMEM;
285 goto end;
286 }
287
288 memcpy(actual_iface->class_descs[hid_i], pos, length);
289 pos += length;
290
291 printf("Parsed class-specific descriptor:\n");
292 dump_hid_class_descriptor(hid_i, desc_type,
293 actual_iface->class_descs[hid_i], length);
294
295 ++hid_i;
296
297 break; }*/
298 default:
299 fprintf(stderr, "Got descriptor of unknown type: %u.\n",
300 desc_type);
301 ret = EINVAL;
302 goto end;
303 break;
304 }
305 }
306
307end:
308 if (ret != EOK) {
309 usbkbd_config_free(config);
310 }
311
312 return ret;
313}
314
315void usbkbd_print_config(const usb_hid_configuration_t *config)
316{
317 dump_standard_configuration_descriptor(0, &config->config_descriptor);
318 int i = 0;
319 for (; i < config->config_descriptor.interface_count; ++i) {
320 usb_hid_iface_t *iface_d = &config->interfaces[i];
321 dump_standard_interface_descriptor(&iface_d->iface_desc);
322 printf("\n");
323 int j = 0;
324 for (; j < iface_d->iface_desc.endpoint_count; ++j) {
325 dump_standard_endpoint_descriptor(
326 &iface_d->endpoints[j]);
327 printf("\n");
328 }
329 dump_standard_hid_descriptor_header(&iface_d->hid_desc);
330 printf("\n");
331 dump_hid_class_descriptor(0, USB_DESCTYPE_HID_REPORT,
332 iface_d->report_desc, iface_d->hid_desc.report_desc_info.length);
333 printf("\n");
334// printf("%d class-specific descriptors\n",
335// iface_d->hid_desc.class_desc_count);
336 /*for (j = 0; j < iface_d->hid_desc.class_desc_count; ++j) {
337 dump_standard_hid_class_descriptor_info(
338 &iface_d->class_desc_info[j]);
339 }
340
341 for (j = 0; j < iface_d->hid_desc.class_desc_count; ++j) {
342 dump_hid_class_descriptor(j,
343 iface_d->class_desc_info[j].type,
344 iface_d->class_descs[j],
345 iface_d->class_desc_info[j].length);
346 }*/
347 }
348}
349
350/**
351 * @}
352 */
Note: See TracBrowser for help on using the repository browser.