source: mainline/uspace/drv/usbkbd/descparser.c@ df175fa

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

Fix wrong printf directive

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