1 /*
2 * Copyright 2009-2011, Michael Lotz, mmlr@mlotz.ch.
3 * Distributed under the terms of the MIT License.
4 */
5
6 #ifndef USERLAND_HID
7 #include "Driver.h"
8 #else
9 #include "UserlandHID.h"
10 #endif
11
12 #include "HIDCollection.h"
13 #include "HIDReport.h"
14 #include "HIDReportItem.h"
15
16 #include <new>
17 #include <stdlib.h>
18 #include <string.h>
19
20
HIDCollection(HIDCollection * parent,uint8 type,local_item_state & localState)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 {
28 usage_value usageValue;
29 if (localState.usage_stack != NULL && localState.usage_stack_used > 0)
30 usageValue.u.extended = localState.usage_stack[0].u.extended;
31 else if (localState.usage_minimum_set)
32 usageValue.u.extended = localState.usage_minimum.u.extended;
33 else if (localState.usage_maximum_set)
34 usageValue.u.extended = localState.usage_maximum.u.extended;
35 else if (type == COLLECTION_LOGICAL) {
36 // this is just a logical grouping collection
37 usageValue.u.extended = 0;
38 } else {
39 TRACE_ALWAYS("none of the possible usages for the collection are "
40 "set\n");
41 }
42
43 fUsage = usageValue.u.extended;
44 }
45
46
~HIDCollection()47 HIDCollection::~HIDCollection()
48 {
49 for (int32 i = 0; i < fChildren.Count(); i++)
50 delete fChildren[i];
51 }
52
53
54 uint16
UsagePage()55 HIDCollection::UsagePage()
56 {
57 usage_value value;
58 value.u.extended = fUsage;
59 return value.u.s.usage_page;
60 }
61
62
63 uint16
UsageID()64 HIDCollection::UsageID()
65 {
66 usage_value value;
67 value.u.extended = fUsage;
68 return value.u.s.usage_id;
69 }
70
71
72 status_t
AddChild(HIDCollection * child)73 HIDCollection::AddChild(HIDCollection *child)
74 {
75 if (fChildren.PushBack(child) == B_NO_MEMORY) {
76 TRACE_ALWAYS("no memory when trying to resize collection child list\n");
77 }
78
79 return B_OK;
80 }
81
82
83 HIDCollection *
ChildAt(uint32 index)84 HIDCollection::ChildAt(uint32 index)
85 {
86 int32 count = fChildren.Count();
87 if (count < 0 || index >= (uint32)count)
88 return NULL;
89
90 return fChildren[index];
91 }
92
93
94 uint32
CountChildrenFlat(uint8 type)95 HIDCollection::CountChildrenFlat(uint8 type)
96 {
97 uint32 count = 0;
98 if (type == COLLECTION_ALL || fType == type)
99 count++;
100
101 for (int32 i = 0; i < fChildren.Count(); i++) {
102 HIDCollection *child = fChildren[i];
103 if (child == NULL)
104 continue;
105
106 count += child->CountChildrenFlat(type);
107 }
108
109 return count;
110 }
111
112
113 HIDCollection *
ChildAtFlat(uint8 type,uint32 index)114 HIDCollection::ChildAtFlat(uint8 type, uint32 index)
115 {
116 return _ChildAtFlat(type, index);
117 }
118
119
120 void
AddItem(HIDReportItem * item)121 HIDCollection::AddItem(HIDReportItem *item)
122 {
123 if (fItems.PushBack(item) == B_NO_MEMORY) {
124 TRACE_ALWAYS("no memory when trying to resize collection items\n");
125 }
126
127 }
128
129
130 HIDReportItem *
ItemAt(uint32 index)131 HIDCollection::ItemAt(uint32 index)
132 {
133 int32 count = fItems.Count();
134 if (count < 0 || index >= (uint32)count)
135 return NULL;
136
137 return fItems[index];
138 }
139
140
141 uint32
CountItemsFlat()142 HIDCollection::CountItemsFlat()
143 {
144 uint32 count = fItems.Count();
145
146 for (int32 i = 0; i < fChildren.Count(); i++) {
147 HIDCollection *child = fChildren[i];
148 if (child != NULL)
149 count += child->CountItemsFlat();
150 }
151
152 return count;
153 }
154
155
156 HIDReportItem *
ItemAtFlat(uint32 index)157 HIDCollection::ItemAtFlat(uint32 index)
158 {
159 return _ItemAtFlat(index);
160 }
161
162
163 void
PrintToStream(uint32 indentLevel)164 HIDCollection::PrintToStream(uint32 indentLevel)
165 {
166 char indent[indentLevel + 1];
167 memset(indent, '\t', indentLevel);
168 indent[indentLevel] = 0;
169
170 const char *typeName = "unknown";
171 switch (fType) {
172 case COLLECTION_PHYSICAL:
173 typeName = "physical";
174 break;
175 case COLLECTION_APPLICATION:
176 typeName = "application";
177 break;
178 case COLLECTION_LOGICAL:
179 typeName = "logical";
180 break;
181 case COLLECTION_REPORT:
182 typeName = "report";
183 break;
184 case COLLECTION_NAMED_ARRAY:
185 typeName = "named array";
186 break;
187 case COLLECTION_USAGE_SWITCH:
188 typeName = "usage switch";
189 break;
190 case COLLECTION_USAGE_MODIFIER:
191 typeName = "usage modifier";
192 break;
193 }
194
195 TRACE_ALWAYS("%sHIDCollection %p\n", indent, this);
196 TRACE_ALWAYS("%s\ttype: %u %s\n", indent, fType, typeName);
197 TRACE_ALWAYS("%s\tusage: 0x%08" B_PRIx32 "\n", indent, fUsage);
198 TRACE_ALWAYS("%s\tstring id: %u\n", indent, fStringID);
199 TRACE_ALWAYS("%s\tphysical id: %u\n", indent, fPhysicalID);
200
201 TRACE_ALWAYS("%s\titem count: %" B_PRIu32 "\n", indent, fItems.Count());
202 for (int32 i = 0; i < fItems.Count(); i++) {
203 HIDReportItem *item = fItems[i];
204 if (item != NULL)
205 item->PrintToStream(indentLevel + 1);
206 }
207
208 TRACE_ALWAYS("%s\tchild count: %" B_PRIu32 "\n", indent, fChildren.Count());
209 for (int32 i = 0; i < fChildren.Count(); i++) {
210 HIDCollection *child = fChildren[i];
211 if (child != NULL)
212 child->PrintToStream(indentLevel + 1);
213 }
214 }
215
216
217 HIDCollection *
_ChildAtFlat(uint8 type,uint32 & index)218 HIDCollection::_ChildAtFlat(uint8 type, uint32 &index)
219 {
220 if (type == COLLECTION_ALL || fType == type) {
221 if (index == 0)
222 return this;
223
224 index--;
225 }
226
227 for (int32 i = 0; i < fChildren.Count(); i++) {
228 HIDCollection *child = fChildren[i];
229 if (child == NULL)
230 continue;
231
232 HIDCollection *result = child->_ChildAtFlat(type, index);
233 if (result != NULL)
234 return result;
235 }
236
237 return NULL;
238 }
239
240
241 HIDReportItem *
_ItemAtFlat(uint32 & index)242 HIDCollection::_ItemAtFlat(uint32 &index)
243 {
244 int32 count = fItems.Count();
245 if (count > 0 && index < (uint32)count)
246 return fItems[index];
247
248 index -= fItems.Count();
249
250 for (int32 i = 0; i < fChildren.Count(); i++) {
251 HIDCollection *child = fChildren[i];
252 if (child == NULL)
253 continue;
254
255 HIDReportItem *result = child->_ItemAtFlat(index);
256 if (result != NULL)
257 return result;
258 }
259
260 return NULL;
261 }
262
263
264 void
BuildReportList(uint8 reportType,HIDReport ** reportList,uint32 & reportCount)265 HIDCollection::BuildReportList(uint8 reportType,
266 HIDReport **reportList, uint32 &reportCount)
267 {
268
269 for (int32 i = 0; i < fItems.Count(); i++) {
270 HIDReportItem *item = fItems[i];
271 if (item == NULL)
272 continue;
273
274 HIDReport *report = item->Report();
275 if (reportType != HID_REPORT_TYPE_ANY && report->Type() != reportType)
276 continue;
277
278 bool found = false;
279 for (uint32 j = 0; j < reportCount; j++) {
280 if (reportList[j] == report) {
281 found = true;
282 break;
283 }
284 }
285
286 if (found)
287 continue;
288
289 reportList[reportCount++] = report;
290 }
291
292 for (int32 i = 0; i < fChildren.Count(); i++) {
293 HIDCollection *child = fChildren[i];
294 if (child == NULL)
295 continue;
296
297 child->BuildReportList(reportType, reportList, reportCount);
298 }
299 }
300