vfs: check userland buffers before reading them.
[haiku.git] / src / add-ons / kernel / drivers / input / usb_hid / HIDCollection.cpp
blobbfa424de46ce040161d6eed4a2bb285feb6ea724
1 /*
2 * Copyright 2009-2011, Michael Lotz, mmlr@mlotz.ch.
3 * Distributed under the terms of the MIT License.
4 */
6 #ifndef USERLAND_HID
7 #include "Driver.h"
8 #else
9 #include "UserlandHID.h"
10 #endif
12 #include "HIDCollection.h"
13 #include "HIDReport.h"
14 #include "HIDReportItem.h"
16 #include <new>
17 #include <stdlib.h>
18 #include <string.h>
21 HIDCollection::HIDCollection(HIDCollection *parent, uint8 type,
22 local_item_state &localState)
23 : fParent(parent),
24 fType(type),
25 fStringID(localState.string_index),
26 fPhysicalID(localState.designator_index),
27 fChildCount(0),
28 fChildren(NULL),
29 fItemCount(0),
30 fItemsAllocated(0),
31 fItems(NULL)
33 usage_value usageValue;
34 if (localState.usage_stack != NULL && localState.usage_stack_used > 0)
35 usageValue.u.extended = localState.usage_stack[0].u.extended;
36 else if (localState.usage_minimum_set)
37 usageValue.u.extended = localState.usage_minimum.u.extended;
38 else if (localState.usage_maximum_set)
39 usageValue.u.extended = localState.usage_maximum.u.extended;
40 else if (type == COLLECTION_LOGICAL) {
41 // this is just a logical grouping collection
42 usageValue.u.extended = 0;
43 } else {
44 TRACE_ALWAYS("none of the possible usages for the collection are "
45 "set\n");
48 fUsage = usageValue.u.extended;
52 HIDCollection::~HIDCollection()
54 for (uint32 i = 0; i < fChildCount; i++)
55 delete fChildren[i];
56 free(fChildren);
57 free(fItems);
61 uint16
62 HIDCollection::UsagePage()
64 usage_value value;
65 value.u.extended = fUsage;
66 return value.u.s.usage_page;
70 uint16
71 HIDCollection::UsageID()
73 usage_value value;
74 value.u.extended = fUsage;
75 return value.u.s.usage_id;
79 status_t
80 HIDCollection::AddChild(HIDCollection *child)
82 HIDCollection **newChildren = (HIDCollection **)realloc(fChildren,
83 (fChildCount + 1) * sizeof(HIDCollection *));
84 if (newChildren == NULL) {
85 TRACE_ALWAYS("no memory when trying to resize collection child list\n");
86 return B_NO_MEMORY;
89 fChildren = newChildren;
90 fChildren[fChildCount++] = child;
91 return B_OK;
95 HIDCollection *
96 HIDCollection::ChildAt(uint32 index)
98 if (index >= fChildCount)
99 return NULL;
101 return fChildren[index];
105 uint32
106 HIDCollection::CountChildrenFlat(uint8 type)
108 uint32 count = 0;
109 if (type == COLLECTION_ALL || fType == type)
110 count++;
112 for (uint32 i = 0; i < fChildCount; i++) {
113 HIDCollection *child = fChildren[i];
114 if (child == NULL)
115 continue;
117 count += child->CountChildrenFlat(type);
120 return count;
124 HIDCollection *
125 HIDCollection::ChildAtFlat(uint8 type, uint32 index)
127 return _ChildAtFlat(type, index);
131 void
132 HIDCollection::AddItem(HIDReportItem *item)
134 if (fItemCount >= fItemsAllocated) {
135 fItemsAllocated += 10;
136 HIDReportItem **newItems = (HIDReportItem **)realloc(fItems,
137 fItemsAllocated * sizeof(HIDReportItem *));
138 if (newItems == NULL) {
139 TRACE_ALWAYS("no memory when trying to resize collection items\n");
140 fItemsAllocated -= 10;
141 return;
144 fItems = newItems;
147 fItems[fItemCount++] = item;
151 HIDReportItem *
152 HIDCollection::ItemAt(uint32 index)
154 if (index >= fItemCount)
155 return NULL;
157 return fItems[index];
161 uint32
162 HIDCollection::CountItemsFlat()
164 uint32 count = fItemCount;
166 for (uint32 i = 0; i < fChildCount; i++) {
167 HIDCollection *child = fChildren[i];
168 if (child != NULL)
169 count += child->CountItemsFlat();
172 return count;
176 HIDReportItem *
177 HIDCollection::ItemAtFlat(uint32 index)
179 return _ItemAtFlat(index);
183 void
184 HIDCollection::PrintToStream(uint32 indentLevel)
186 char indent[indentLevel + 1];
187 memset(indent, '\t', indentLevel);
188 indent[indentLevel] = 0;
190 const char *typeName = "unknown";
191 switch (fType) {
192 case COLLECTION_PHYSICAL:
193 typeName = "physical";
194 break;
195 case COLLECTION_APPLICATION:
196 typeName = "application";
197 break;
198 case COLLECTION_LOGICAL:
199 typeName = "logical";
200 break;
201 case COLLECTION_REPORT:
202 typeName = "report";
203 break;
204 case COLLECTION_NAMED_ARRAY:
205 typeName = "named array";
206 break;
207 case COLLECTION_USAGE_SWITCH:
208 typeName = "usage switch";
209 break;
210 case COLLECTION_USAGE_MODIFIER:
211 typeName = "usage modifier";
212 break;
215 TRACE_ALWAYS("%sHIDCollection %p\n", indent, this);
216 TRACE_ALWAYS("%s\ttype: %u %s\n", indent, fType, typeName);
217 TRACE_ALWAYS("%s\tusage: 0x%08" B_PRIx32 "\n", indent, fUsage);
218 TRACE_ALWAYS("%s\tstring id: %u\n", indent, fStringID);
219 TRACE_ALWAYS("%s\tphysical id: %u\n", indent, fPhysicalID);
221 TRACE_ALWAYS("%s\titem count: %" B_PRIu32 "\n", indent, fItemCount);
222 for (uint32 i = 0; i < fItemCount; i++) {
223 HIDReportItem *item = fItems[i];
224 if (item != NULL)
225 item->PrintToStream(indentLevel + 1);
228 TRACE_ALWAYS("%s\tchild count: %" B_PRIu32 "\n", indent, fChildCount);
229 for (uint32 i = 0; i < fChildCount; i++) {
230 HIDCollection *child = fChildren[i];
231 if (child != NULL)
232 child->PrintToStream(indentLevel + 1);
237 HIDCollection *
238 HIDCollection::_ChildAtFlat(uint8 type, uint32 &index)
240 if (type == COLLECTION_ALL || fType == type) {
241 if (index == 0)
242 return this;
244 index--;
247 for (uint32 i = 0; i < fChildCount; i++) {
248 HIDCollection *child = fChildren[i];
249 if (child == NULL)
250 continue;
252 HIDCollection *result = child->_ChildAtFlat(type, index);
253 if (result != NULL)
254 return result;
257 return NULL;
261 HIDReportItem *
262 HIDCollection::_ItemAtFlat(uint32 &index)
264 if (index < fItemCount)
265 return fItems[index];
267 index -= fItemCount;
269 for (uint32 i = 0; i < fChildCount; i++) {
270 HIDCollection *child = fChildren[i];
271 if (child == NULL)
272 continue;
274 HIDReportItem *result = child->_ItemAtFlat(index);
275 if (result != NULL)
276 return result;
279 return NULL;
283 void
284 HIDCollection::BuildReportList(uint8 reportType,
285 HIDReport **reportList, uint32 &reportCount)
288 for (uint32 i = 0; i < fItemCount; i++) {
289 HIDReportItem *item = fItems[i];
290 if (item == NULL)
291 continue;
293 HIDReport *report = item->Report();
294 if (reportType != HID_REPORT_TYPE_ANY && report->Type() != reportType)
295 continue;
297 bool found = false;
298 for (uint32 j = 0; j < reportCount; j++) {
299 if (reportList[j] == report) {
300 found = true;
301 break;
305 if (found)
306 continue;
308 reportList[reportCount++] = report;
311 for (uint32 i = 0; i < fChildCount; i++) {
312 HIDCollection *child = fChildren[i];
313 if (child == NULL)
314 continue;
316 child->BuildReportList(reportType, reportList, reportCount);