source: mainline/uspace/lib/usb/src/hidpath.c@ 9d05599

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 9d05599 was 9d05599, checked in by Matej Klonfar <maklf@…>, 14 years ago

usages order fixed

  • Property mode set to 100644
File size: 10.0 KB
Line 
1/*
2 * Copyright (c) 2011 Matej Klonfar
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 libusb
30 * @{
31 */
32/** @file
33 * HID report descriptor and report data parser implementation.
34 */
35#include <usb/classes/hidparser.h>
36#include <errno.h>
37#include <stdio.h>
38#include <malloc.h>
39#include <mem.h>
40#include <usb/debug.h>
41#include <assert.h>
42
43
44/**
45 * Appends one item (couple of usage_path and usage) into the usage path
46 * structure
47 *
48 * @param usage_path Usage path structure
49 * @param usage_page Usage page constant
50 * @param usage Usage constant
51 * @return Error code
52 */
53int usb_hid_report_path_append_item(usb_hid_report_path_t *usage_path,
54 int32_t usage_page, int32_t usage)
55{
56 usb_hid_report_usage_path_t *item;
57
58 if(!(item=malloc(sizeof(usb_hid_report_usage_path_t)))) {
59 return ENOMEM;
60 }
61 list_initialize(&item->link);
62
63 item->usage = usage;
64 item->usage_page = usage_page;
65 item->flags = 0;
66
67 list_append (&item->link, &usage_path->head);
68 usage_path->depth++;
69 return EOK;
70}
71
72/**
73 * Removes last item from the usage path structure
74 * @param usage_path
75 * @return void
76 */
77void usb_hid_report_remove_last_item(usb_hid_report_path_t *usage_path)
78{
79 usb_hid_report_usage_path_t *item;
80
81 if(!list_empty(&usage_path->head)){
82 item = list_get_instance(usage_path->head.prev,
83 usb_hid_report_usage_path_t, link);
84 list_remove(usage_path->head.prev);
85 usage_path->depth--;
86 free(item);
87 }
88}
89
90/**
91 * Nulls last item of the usage path structure.
92 *
93 * @param usage_path
94 * @return void
95 */
96void usb_hid_report_null_last_item(usb_hid_report_path_t *usage_path)
97{
98 usb_hid_report_usage_path_t *item;
99
100 if(!list_empty(&usage_path->head)){
101 item = list_get_instance(usage_path->head.prev, usb_hid_report_usage_path_t, link);
102 memset(item, 0, sizeof(usb_hid_report_usage_path_t));
103 }
104}
105
106/**
107 * Modifies last item of usage path structure by given usage page or usage
108 *
109 * @param usage_path Opaque usage path structure
110 * @param tag Class of currently processed tag (Usage page tag falls into Global
111 * class but Usage tag into the Local)
112 * @param data Value of the processed tag
113 * @return void
114 */
115void usb_hid_report_set_last_item(usb_hid_report_path_t *usage_path,
116 int32_t tag, int32_t data)
117{
118 usb_hid_report_usage_path_t *item;
119
120 if(!list_empty(&usage_path->head)){
121 item = list_get_instance(usage_path->head.prev,
122 usb_hid_report_usage_path_t, link);
123
124 switch(tag) {
125 case USB_HID_TAG_CLASS_GLOBAL:
126 item->usage_page = data;
127 break;
128 case USB_HID_TAG_CLASS_LOCAL:
129 item->usage = data;
130 break;
131 }
132 }
133
134}
135
136
137void usb_hid_print_usage_path(usb_hid_report_path_t *path)
138{
139 usb_log_debug("USAGE_PATH FOR RId(%d):\n", path->report_id);
140 usb_log_debug("\tLENGTH: %d\n", path->depth);
141
142 link_t *item = path->head.next;
143 usb_hid_report_usage_path_t *path_item;
144 while(item != &path->head) {
145
146 path_item = list_get_instance(item, usb_hid_report_usage_path_t, link);
147 usb_log_debug("\tUSAGE_PAGE: %X\n", path_item->usage_page);
148 usb_log_debug("\tUSAGE: %X\n", path_item->usage);
149 usb_log_debug("\tFLAGS: %d\n", path_item->flags);
150
151 item = item->next;
152 }
153}
154
155/**
156 * Compares two usage paths structures
157 *
158 * If USB_HID_PATH_COMPARE_COLLECTION_ONLY flag is given, the last item in report_path structure is forgotten
159 *
160 * @param report_path usage path structure to compare
161 * @param path usage patrh structure to compare
162 * @param flags Flags determining the mode of comparison
163 * @return EOK if both paths are identical, non zero number otherwise
164 */
165int usb_hid_report_compare_usage_path(usb_hid_report_path_t *report_path,
166 usb_hid_report_path_t *path,
167 int flags)
168{
169 usb_hid_report_usage_path_t *report_item;
170 usb_hid_report_usage_path_t *path_item;
171
172 link_t *report_link;
173 link_t *path_link;
174
175 int only_page;
176
177 if(report_path->report_id != path->report_id) {
178 return 1;
179 }
180
181 if(path->depth == 0){
182 return EOK;
183 }
184
185
186 if((only_page = flags & USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY) != 0){
187 flags -= USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY;
188 }
189
190 switch(flags){
191 /* path must be completly identical */
192 case USB_HID_PATH_COMPARE_STRICT:
193 if(report_path->depth != path->depth){
194 return 1;
195 }
196
197 report_link = report_path->head.next;
198 path_link = path->head.next;
199
200 while((report_link != &report_path->head) &&
201 (path_link != &path->head)) {
202
203 report_item = list_get_instance(report_link,
204 usb_hid_report_usage_path_t,
205 link);
206
207 path_item = list_get_instance(path_link,
208 usb_hid_report_usage_path_t,
209 link);
210
211 if((report_item->usage_page != path_item->usage_page) ||
212 ((only_page == 0) &&
213 (report_item->usage != path_item->usage))) {
214
215 return 1;
216 } else {
217 report_link = report_link->next;
218 path_link = path_link->next;
219 }
220
221 }
222
223 if(((report_link == &report_path->head) && (path_link == &path->head)) ||
224 (((flags & USB_HID_PATH_COMPARE_COLLECTION_ONLY) != 0) &&
225 (path_link = &path->head) &&
226 (report_link == report_path->head.prev))) {
227 return EOK;
228 }
229 else {
230 return 1;
231 }
232 break;
233
234 /* compare with only the end of path*/
235 case USB_HID_PATH_COMPARE_END:
236
237 if((flags & USB_HID_PATH_COMPARE_COLLECTION_ONLY) != 0) {
238 report_link = report_path->head.prev->prev;
239 }
240 else {
241 report_link = report_path->head.prev;
242 }
243 path_link = path->head.prev;
244
245 if(list_empty(&path->head)){
246 return EOK;
247 }
248
249 while((report_link != &report_path->head) &&
250 (path_link != &path->head)) {
251
252 report_item = list_get_instance(report_link,
253 usb_hid_report_usage_path_t,
254 link);
255 path_item = list_get_instance(path_link,
256 usb_hid_report_usage_path_t,
257 link);
258
259 if((report_item->usage_page != path_item->usage_page) ||
260 ((only_page == 0) &&
261 (report_item->usage != path_item->usage))) {
262 return 1;
263 } else {
264 report_link = report_link->prev;
265 path_link = path_link->prev;
266 }
267
268 }
269
270 if(path_link == &path->head) {
271 return EOK;
272 }
273 else {
274 return 1;
275 }
276
277 break;
278
279 default:
280 return EINVAL;
281 }
282}
283
284/**
285 * Allocates and initializes new usage path structure.
286 *
287 * @return Initialized usage path structure
288 */
289usb_hid_report_path_t *usb_hid_report_path(void)
290{
291 usb_hid_report_path_t *path;
292 path = malloc(sizeof(usb_hid_report_path_t));
293 if(path == NULL){
294 return NULL;
295 }
296 else {
297 path->depth = 0;
298 path->report_id = 0;
299 list_initialize(&path->link);
300 list_initialize(&path->head);
301 return path;
302 }
303}
304
305/**
306 * Releases given usage path structure.
307 *
308 * @param path usage path structure to release
309 * @return void
310 */
311void usb_hid_report_path_free(usb_hid_report_path_t *path)
312{
313 while(!list_empty(&path->head)){
314 usb_hid_report_remove_last_item(path);
315 }
316
317 list_remove(&path->link);
318 free(path);
319}
320
321
322/**
323 * Clone content of given usage path to the new one
324 *
325 * @param usage_path Usage path structure to clone
326 * @return New copy of given usage path structure
327 */
328usb_hid_report_path_t *usb_hid_report_path_clone(usb_hid_report_path_t *usage_path)
329{
330 link_t *path_link;
331 usb_hid_report_usage_path_t *path_item;
332 usb_hid_report_usage_path_t *new_path_item;
333 usb_hid_report_path_t *new_usage_path = usb_hid_report_path ();
334
335 if(new_usage_path == NULL){
336 return NULL;
337 }
338
339 new_usage_path->report_id = usage_path->report_id;
340
341 if(list_empty(&usage_path->head)){
342 return new_usage_path;
343 }
344
345 path_link = usage_path->head.next;
346 while(path_link != &usage_path->head) {
347 path_item = list_get_instance(path_link, usb_hid_report_usage_path_t,
348 link);
349 new_path_item = malloc(sizeof(usb_hid_report_usage_path_t));
350 if(new_path_item == NULL) {
351 return NULL;
352 }
353
354 list_initialize (&new_path_item->link);
355 new_path_item->usage_page = path_item->usage_page;
356 new_path_item->usage = path_item->usage;
357 new_path_item->flags = path_item->flags;
358
359 list_append(&new_path_item->link, &new_usage_path->head);
360 new_usage_path->depth++;
361
362 path_link = path_link->next;
363 }
364
365 return new_usage_path;
366}
367
368
369/**
370 * Sets report id in usage path structure
371 *
372 * @param path Usage path structure
373 * @param report_id Report id to set
374 * @return Error code
375 */
376int usb_hid_report_path_set_report_id(usb_hid_report_path_t *path, uint8_t report_id)
377{
378 if(path == NULL){
379 return EINVAL;
380 }
381
382 path->report_id = report_id;
383 return EOK;
384}
385
386/**
387 * @}
388 */
Note: See TracBrowser for help on using the repository browser.