source: mainline/uspace/lib/usbhid/src/hidparser.c@ 07525cd

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 07525cd was 07525cd, checked in by Martin Decky <martin@…>, 12 years ago

cstyle

  • Property mode set to 100644
File size: 15.6 KB
RevLine 
[bf2063e9]1/*
[2571089]2 * Copyright (c) 2011 Matej Klonfar
[bf2063e9]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
[160b75e]29/** @addtogroup libusbhid
[bf2063e9]30 * @{
31 */
32/** @file
[5499a8b]33 * USB HID report data parser implementation.
[bf2063e9]34 */
[faa44e58]35#include <usb/hid/hidparser.h>
[bf2063e9]36#include <errno.h>
[976f546]37#include <stdio.h>
[e24e7b1]38#include <malloc.h>
39#include <mem.h>
[b7d9606]40#include <usb/debug.h>
[681f24b3]41#include <assert.h>
[976f546]42
[a76b01b4]43
[57d9c05e]44/*
45 * Data translation private functions
46 */
[1553cbf]47uint32_t usb_hid_report_tag_data_uint32(const uint8_t *data, size_t size);
[5499a8b]48
[cfbbe1d3]49int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data);
[5499a8b]50
51uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item,
52 int32_t value);
53
[a76b01b4]54
[2571089]55
[069b80d]56static int usb_pow(int a, int b)
[fad14d7]57{
[069b80d]58 switch (b) {
[5499a8b]59 case 0:
60 return 1;
61 break;
62 case 1:
63 return a;
64 break;
65 default:
[069b80d]66 return a * usb_pow(a, b - 1);
[5499a8b]67 break;
[fad14d7]68 }
69}
[a76b01b4]70
[976f546]71
[3a6e423]72/** Returns size of report of specified report id and type in items
73 *
74 * @param parser Opaque report parser structure
75 * @param report_id
76 * @param type
77 * @return Number of items in specified report
78 */
79size_t usb_hid_report_size(usb_hid_report_t *report, uint8_t report_id,
[069b80d]80 usb_hid_report_type_t type)
[3a6e423]81{
82 usb_hid_report_description_t *report_des;
83
[069b80d]84 if (report == NULL) {
[3a6e423]85 return 0;
86 }
87
[069b80d]88 report_des = usb_hid_report_find_description(report, report_id, type);
89 if (report_des == NULL) {
[3a6e423]90 return 0;
[069b80d]91 } else {
[3a6e423]92 return report_des->item_length;
93 }
94}
[1eee99f2]95
96/** Returns size of report of specified report id and type in bytes
97 *
98 * @param parser Opaque report parser structure
99 * @param report_id
100 * @param type
101 * @return Number of items in specified report
102 */
103size_t usb_hid_report_byte_size(usb_hid_report_t *report, uint8_t report_id,
[069b80d]104 usb_hid_report_type_t type)
[1eee99f2]105{
106 usb_hid_report_description_t *report_des;
107
[069b80d]108 if (report == NULL) {
[1eee99f2]109 return 0;
110 }
111
[069b80d]112 report_des = usb_hid_report_find_description(report, report_id, type);
113 if (report_des == NULL) {
[1eee99f2]114 return 0;
[069b80d]115 } else {
[d861c22]116 return ((report_des->bit_length + 7) / 8) ;
[1eee99f2]117 }
118}
[a76b01b4]119
[c7a2e7e]120
[fad14d7]121/** Parse and act upon a HID report.
122 *
123 * @see usb_hid_parse_report_descriptor
124 *
125 * @param parser Opaque HID report parser structure.
126 * @param data Data for the report.
127 * @return Error code.
128 */
[5499a8b]129int usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data,
[069b80d]130 size_t size, uint8_t *report_id)
[fad14d7]131{
[175ad13e]132 usb_hid_report_description_t *report_des;
133 usb_hid_report_type_t type = USB_HID_REPORT_TYPE_INPUT;
[07525cd]134
[069b80d]135 if (report == NULL) {
[55e388a1]136 return EINVAL;
137 }
[c156c2d]138
[069b80d]139 if (report->use_report_ids != 0) {
[cfbbe1d3]140 *report_id = data[0];
[069b80d]141 } else {
[cfbbe1d3]142 *report_id = 0;
[c156c2d]143 }
144
[8242dd86]145 report_des = usb_hid_report_find_description(report, *report_id,
[069b80d]146 type);
[8242dd86]147
[069b80d]148 if (report_des == NULL) {
[14e1bcc]149 return EINVAL;
150 }
[c156c2d]151
[175ad13e]152 /* read data */
[feeac0d]153 list_foreach(report_des->report_items, ritems_link,
154 usb_hid_report_field_t, item) {
[fad14d7]155
[069b80d]156 if (USB_HID_ITEM_FLAG_CONSTANT(item->item_flags) == 0) {
[07525cd]157
[069b80d]158 if (USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0) {
159 /* array */
[f3b39b4]160 item->value =
161 usb_hid_translate_data(item, data);
[07525cd]162
[5499a8b]163 item->usage = USB_HID_EXTENDED_USAGE(
[069b80d]164 item->usages[item->value -
165 item->physical_minimum]);
[f3b39b4]166
[8242dd86]167 item->usage_page =
168 USB_HID_EXTENDED_USAGE_PAGE(
[069b80d]169 item->usages[item->value -
170 item->physical_minimum]);
[3a6e423]171
[069b80d]172 usb_hid_report_set_last_item(
[8242dd86]173 item->collection_path,
174 USB_HID_TAG_CLASS_GLOBAL,
175 item->usage_page);
[f3b39b4]176
[069b80d]177 usb_hid_report_set_last_item(
[8242dd86]178 item->collection_path,
[5499a8b]179 USB_HID_TAG_CLASS_LOCAL, item->usage);
[069b80d]180 } else {
181 /* variable item */
[8242dd86]182 item->value = usb_hid_translate_data(item,
[feeac0d]183 data);
184 }
[fad14d7]185 }
186 }
[07525cd]187
[fad14d7]188 return EOK;
189}
190
[a76b01b4]191
[57d9c05e]192/**
[c156c2d]193 * Translate data from the report as specified in report descriptor item
[57d9c05e]194 *
195 * @param item Report descriptor item with definition of translation
196 * @param data Data to translate
197 * @return Translated data
198 */
[cfbbe1d3]199int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data)
[c7a2e7e]200{
[fad14d7]201 int resolution;
202 int offset;
203 int part_size;
204
[069b80d]205 int32_t value = 0;
206 int32_t mask = 0;
207 const uint8_t *foo = 0;
[bda06a3]208
[069b80d]209 /* now only short tags are allowed */
210 if (item->size > 32) {
[fad14d7]211 return 0;
212 }
213
[069b80d]214 if ((item->physical_minimum == 0) && (item->physical_maximum == 0)) {
[fad14d7]215 item->physical_minimum = item->logical_minimum;
[cfbbe1d3]216 item->physical_maximum = item->logical_maximum;
[fad14d7]217 }
[cfbbe1d3]218
[fad14d7]219
[069b80d]220 if (item->physical_maximum == item->physical_minimum) {
[60a228f]221 resolution = 1;
[069b80d]222 } else {
[60a228f]223 resolution = (item->logical_maximum - item->logical_minimum) /
224 ((item->physical_maximum - item->physical_minimum) *
[069b80d]225 (usb_pow(10, (item->unit_exponent))));
[60a228f]226 }
[bda06a3]227
[cfbbe1d3]228 offset = item->offset;
[fad14d7]229 // FIXME
[069b80d]230 if ((size_t) (offset / 8) != (size_t) ((offset+item->size - 1) / 8)) {
[fad14d7]231
[8242dd86]232 part_size = 0;
[fad14d7]233
[069b80d]234 size_t i = 0;
235 for (i = (size_t) (offset / 8);
236 i <= (size_t) (offset + item->size - 1) / 8; i++) {
237 if (i == (size_t) (offset / 8)) {
238 /* the higher one */
[8242dd86]239 part_size = 8 - (offset % 8);
[175ad13e]240 foo = data + i;
[069b80d]241 mask = ((1 << (item->size - part_size)) - 1);
[574f276]242 value = (*foo & mask);
[069b80d]243 } else if (i == ((offset + item->size - 1) / 8)) {
244 /* the lower one */
[175ad13e]245 foo = data + i;
[069b80d]246 mask = ((1 << (item->size - part_size)) - 1) <<
247 (8 - (item->size - part_size));
[574f276]248
249 value = (((*foo & mask) >> (8 -
[069b80d]250 (item->size - part_size))) << part_size) +
251 value;
252 } else {
253 value = (*(data + 1) << (part_size + 8)) +
254 value;
[8242dd86]255 part_size += 8;
[175ad13e]256 }
257 }
[069b80d]258 } else {
259 foo = data + (offset / 8);
260 mask = ((1 << item->size) - 1) <<
261 (8 - ((offset % 8) + item->size));
262 value = (*foo & mask) >> (8 - ((offset % 8) + item->size));
[175ad13e]263 }
[fad14d7]264
[069b80d]265 if ((item->logical_minimum < 0) || (item->logical_maximum < 0)) {
[1553cbf]266 value = USB_HID_UINT32_TO_INT32(value, item->size);
[fad14d7]267 }
268
[069b80d]269 return (int) (((value - item->logical_minimum) / resolution) +
270 item->physical_minimum);
[c7a2e7e]271}
[0bd4810c]272
[a76b01b4]273
[5499a8b]274/* OUTPUT API */
[57d9c05e]275
[a694a58]276/**
277 * Allocates output report buffer for output report
[57d9c05e]278 *
[a694a58]279 * @param parser Report parsed structure
280 * @param size Size of returned buffer
281 * @param report_id Report id of created output report
282 * @return Returns allocated output buffer for specified output
[57d9c05e]283 */
[5499a8b]284uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size,
[069b80d]285 uint8_t report_id)
[57d9c05e]286{
[069b80d]287 if (report == NULL) {
[57d9c05e]288 *size = 0;
289 return NULL;
290 }
291
[175ad13e]292 usb_hid_report_description_t *report_des = NULL;
[b72efe8]293
[feeac0d]294 list_foreach(report->reports, reports_link,
295 usb_hid_report_description_t, report_des) {
[069b80d]296 if ((report_des->report_id == report_id) &&
297 (report_des->type == USB_HID_REPORT_TYPE_OUTPUT)) {
[a694a58]298 break;
[c156c2d]299 }
[175ad13e]300 }
[841e6e5]301
[069b80d]302 if (report_des == NULL) {
[175ad13e]303 *size = 0;
304 return NULL;
[069b80d]305 } else {
306 *size = (report_des->bit_length + (8 - 1)) / 8;
[175ad13e]307 uint8_t *ret = malloc((*size) * sizeof(uint8_t));
308 memset(ret, 0, (*size) * sizeof(uint8_t));
309 return ret;
[57d9c05e]310 }
311}
312
313
314/** Frees output report buffer
315 *
316 * @param output Output report buffer
[a694a58]317 * @return void
[57d9c05e]318 */
319void usb_hid_report_output_free(uint8_t *output)
320{
[069b80d]321 if (output != NULL) {
322 free(output);
[57d9c05e]323 }
324}
325
[175ad13e]326/** Makes the output report buffer for data given in the report structure
[57d9c05e]327 *
[a694a58]328 * @param parser Opaque report parser structure
329 * @param path Usage path specifing which parts of output will be set
330 * @param flags Usage path structure comparison flags
331 * @param buffer Output buffer
332 * @param size Size of output buffer
333 * @return Error code
[57d9c05e]334 */
[5499a8b]335int usb_hid_report_output_translate(usb_hid_report_t *report,
[069b80d]336 uint8_t report_id, uint8_t *buffer, size_t size)
[57d9c05e]337{
[069b80d]338 int32_t value = 0;
[841e6e5]339 int offset;
340 int length;
341 int32_t tmp_value;
[07525cd]342
[069b80d]343 if (report == NULL) {
[57d9c05e]344 return EINVAL;
345 }
346
[069b80d]347 if (report->use_report_ids != 0) {
[feeac0d]348 buffer[0] = report_id;
[bda06a3]349 }
350
[175ad13e]351 usb_hid_report_description_t *report_des;
[069b80d]352 report_des = usb_hid_report_find_description(report, report_id,
353 USB_HID_REPORT_TYPE_OUTPUT);
[07525cd]354
[069b80d]355 if (report_des == NULL) {
[175ad13e]356 return EINVAL;
357 }
[57d9c05e]358
[feeac0d]359 list_foreach(report_des->report_items, ritems_link,
360 usb_hid_report_field_t, report_item) {
[574f276]361 value = usb_hid_translate_data_reverse(report_item,
[069b80d]362 report_item->value);
[841e6e5]363
[574f276]364 offset = report_des->bit_length - report_item->offset - 1;
365 length = report_item->size;
[07525cd]366
[9be8669]367 usb_log_debug("\ttranslated value: %x\n", value);
[841e6e5]368
[069b80d]369 if ((offset / 8) == ((offset + length - 1) / 8)) {
370 if (((size_t) (offset / 8) >= size) ||
371 ((size_t) (offset + length - 1) / 8) >= size) {
[9be8669]372 break; // TODO ErrorCode
[841e6e5]373 }
[069b80d]374 size_t shift = 8 - offset % 8 - length;
[feeac0d]375 value = value << shift;
[069b80d]376 value = value & (((1 << length) - 1) << shift);
[07525cd]377
[9be8669]378 uint8_t mask = 0;
379 mask = 0xff - (((1 << length) - 1) << shift);
[069b80d]380 buffer[offset / 8] = (buffer[offset / 8] & mask) |
381 value;
382 } else {
[9be8669]383 int i = 0;
384 uint8_t mask = 0;
[069b80d]385 for (i = (offset / 8);
386 i <= ((offset + length - 1) / 8); i++) {
387 if (i == (offset / 8)) {
[9be8669]388 tmp_value = value;
[f3b39b4]389 tmp_value = tmp_value &
[069b80d]390 ((1 << (8 - (offset % 8))) - 1);
[f3b39b4]391
[069b80d]392 tmp_value = tmp_value << (offset % 8);
[07525cd]393
[069b80d]394 mask = ~(((1 << (8 - (offset % 8))) - 1)
395 << (offset % 8));
[f3b39b4]396
397 buffer[i] = (buffer[i] & mask) |
[069b80d]398 tmp_value;
399 } else if (i == ((offset + length - 1) / 8)) {
[07525cd]400
[f3b39b4]401 value = value >> (length -
[069b80d]402 ((offset + length) % 8));
[f3b39b4]403
404 value = value & ((1 << (length -
[069b80d]405 ((offset + length) % 8))) - 1);
[07525cd]406
[f3b39b4]407 mask = (1 << (length -
[069b80d]408 ((offset + length) % 8))) - 1;
[f3b39b4]409
[9be8669]410 buffer[i] = (buffer[i] & mask) | value;
[069b80d]411 } else {
412 buffer[i] = value & (0xff << i);
[175ad13e]413 }
[841e6e5]414 }
[9be8669]415 }
[841e6e5]416
[069b80d]417 /* reset value */
[cfbbe1d3]418 report_item->value = 0;
[57d9c05e]419 }
[07525cd]420
[57d9c05e]421 return EOK;
422}
423
[a76b01b4]424
[841e6e5]425/**
[a694a58]426 * Translate given data for putting them into the outoput report
427 * @param item Report item structure
428 * @param value Value to translate
429 * @return ranslated value
[841e6e5]430 */
[5499a8b]431uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item,
[069b80d]432 int value)
[841e6e5]433{
[069b80d]434 int ret = 0;
[841e6e5]435 int resolution;
436
[069b80d]437 if (USB_HID_ITEM_FLAG_CONSTANT(item->item_flags)) {
[70a71e5]438 ret = item->logical_minimum;
439 }
440
[069b80d]441 if ((item->physical_minimum == 0) && (item->physical_maximum == 0)) {
[cfbbe1d3]442 item->physical_minimum = item->logical_minimum;
443 item->physical_maximum = item->logical_maximum;
444 }
445
[069b80d]446 /* variable item */
447 if (item->physical_maximum == item->physical_minimum) {
[9be8669]448 resolution = 1;
[069b80d]449 } else {
[9be8669]450 resolution = (item->logical_maximum - item->logical_minimum) /
451 ((item->physical_maximum - item->physical_minimum) *
[069b80d]452 (usb_pow(10, (item->unit_exponent))));
[841e6e5]453 }
454
[5499a8b]455 ret = ((value - item->physical_minimum) * resolution) +
[069b80d]456 item->logical_minimum;
[5499a8b]457
[069b80d]458 usb_log_debug("\tvalue(%x), resolution(%x), phymin(%x) logmin(%x), "
459 "ret(%x)\n", value, resolution, item->physical_minimum,
460 item->logical_minimum, ret);
[9be8669]461
[069b80d]462 if ((item->logical_minimum < 0) || (item->logical_maximum < 0)) {
[1553cbf]463 return USB_HID_INT32_TO_UINT32(ret, item->size);
464 }
[069b80d]465
466 return (int32_t) 0 + ret;
[841e6e5]467}
468
[a76b01b4]469
[5499a8b]470/**
471 * Clones given state table
472 *
473 * @param item State table to clone
474 * @return Pointer to the cloned item
475 */
476usb_hid_report_item_t *usb_hid_report_item_clone(
[069b80d]477 const usb_hid_report_item_t *item)
[64dbc83]478{
479 usb_hid_report_item_t *new_report_item;
480
[069b80d]481 if (!(new_report_item = malloc(sizeof(usb_hid_report_item_t)))) {
[64dbc83]482 return NULL;
483 }
484 memcpy(new_report_item,item, sizeof(usb_hid_report_item_t));
485 link_initialize(&(new_report_item->link));
486
487 return new_report_item;
488}
489
[a76b01b4]490
[5499a8b]491/**
492 * Function for sequence walking through the report. Returns next field in the
493 * report or the first one when no field is given.
494 *
495 * @param report Searched report structure
496 * @param field Current field. If NULL is given, the first one in the report
497 * is returned. Otherwise the next one i nthe list is returned.
498 * @param path Usage path specifying which fields wa are interested in.
499 * @param flags Flags defining mode of usage paths comparison
500 * @param type Type of report we search.
501 * @retval NULL if no field is founded
502 * @retval Pointer to the founded report structure when founded
503 */
[e50cd7f]504usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report,
[069b80d]505 usb_hid_report_field_t *field, usb_hid_report_path_t *path, int flags,
506 usb_hid_report_type_t type)
[e50cd7f]507{
[f3b39b4]508 usb_hid_report_description_t *report_des =
[069b80d]509 usb_hid_report_find_description(report, path->report_id, type);
[5499a8b]510
[e50cd7f]511 link_t *field_it;
512
[069b80d]513 if (report_des == NULL) {
[e50cd7f]514 return NULL;
515 }
516
[069b80d]517 if (field == NULL) {
[b72efe8]518 field_it = report_des->report_items.head.next;
[069b80d]519 } else {
[b72efe8]520 field_it = field->ritems_link.next;
[e50cd7f]521 }
522
[069b80d]523 while (field_it != &report_des->report_items.head) {
[f3b39b4]524 field = list_get_instance(field_it, usb_hid_report_field_t,
[069b80d]525 ritems_link);
[f3b39b4]526
[069b80d]527 if (USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) {
528 usb_hid_report_path_append_item(field->collection_path,
529 field->usage_page, field->usage);
[5499a8b]530
[069b80d]531 if (usb_hid_report_compare_usage_path(
532 field->collection_path, path, flags) == EOK) {
[f3b39b4]533 usb_hid_report_remove_last_item(
[069b80d]534 field->collection_path);
[c7c0984a]535 return field;
536 }
[069b80d]537 usb_hid_report_remove_last_item(field->collection_path);
[e50cd7f]538 }
539 field_it = field_it->next;
540 }
541
542 return NULL;
543}
[cfbbe1d3]544
[a76b01b4]545
[5499a8b]546/**
[1d10ca1]547 * Returns next report_id of report of specified type. If zero is given than
548 * first report_id of specified type is returned (0 is not legal value for
549 * repotr_id)
[5499a8b]550 *
[1d10ca1]551 * @param report_id Current report_id, 0 if there is no current report_id
[5499a8b]552 * @param type Type of searched report
553 * @param report Report structure inwhich we search
554 * @retval 0 if report structure is null or there is no specified report
555 * @retval report_id otherwise
556 */
[069b80d]557uint8_t usb_hid_get_next_report_id(usb_hid_report_t *report, uint8_t report_id,
558 usb_hid_report_type_t type)
[cfbbe1d3]559{
[069b80d]560 if (report == NULL) {
[cfbbe1d3]561 return 0;
562 }
563
564 usb_hid_report_description_t *report_des;
565 link_t *report_it;
566
[069b80d]567 if (report_id > 0) {
[0dd3e49]568 report_des = usb_hid_report_find_description(report, report_id,
[069b80d]569 type);
570 if (report_des == NULL) {
[0dd3e49]571 return 0;
[069b80d]572 } else {
[b72efe8]573 report_it = report_des->reports_link.next;
[0dd3e49]574 }
[069b80d]575 } else {
[b72efe8]576 report_it = report->reports.head.next;
[cfbbe1d3]577 }
578
[069b80d]579 while (report_it != &report->reports.head) {
[1d10ca1]580 report_des = list_get_instance(report_it,
[069b80d]581 usb_hid_report_description_t, reports_link);
[5499a8b]582
[069b80d]583 if (report_des->type == type) {
[cfbbe1d3]584 return report_des->report_id;
585 }
[0c904a3]586
587 report_it = report_it->next;
[cfbbe1d3]588 }
589
590 return 0;
591}
592
[a76b01b4]593
[5499a8b]594/**
595 * Reset all local items in given state table
596 *
597 * @param report_item State table containing current state of report
598 * descriptor parsing
599 *
600 * @return void
601 */
[2020927]602void usb_hid_report_reset_local_items(usb_hid_report_item_t *report_item)
603{
[069b80d]604 if (report_item == NULL) {
[2020927]605 return;
606 }
607
608 report_item->usages_count = 0;
609 memset(report_item->usages, 0, USB_HID_MAX_USAGES);
610
611 report_item->extended_usage_page = 0;
612 report_item->usage_minimum = 0;
613 report_item->usage_maximum = 0;
614 report_item->designator_index = 0;
615 report_item->designator_minimum = 0;
616 report_item->designator_maximum = 0;
617 report_item->string_index = 0;
618 report_item->string_minimum = 0;
619 report_item->string_maximum = 0;
620}
[069b80d]621
[976f546]622/**
623 * @}
[c7a2e7e]624 */
Note: See TracBrowser for help on using the repository browser.