source: mainline/uspace/drv/usbkbd/descparser.c@ 1c13dac

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

Add Doxygen groups to usbkbd driver

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