2 * Copyright 2009-2011, Michael Lotz, mmlr@mlotz.ch.
3 * Distributed under the terms of the MIT License.
9 #include "UserlandHID.h"
12 #include "HIDCollection.h"
13 #include "HIDReport.h"
14 #include "HIDReportItem.h"
21 HIDCollection::HIDCollection(HIDCollection
*parent
, uint8 type
,
22 local_item_state
&localState
)
25 fStringID(localState
.string_index
),
26 fPhysicalID(localState
.designator_index
),
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;
44 TRACE_ALWAYS("none of the possible usages for the collection are "
48 fUsage
= usageValue
.u
.extended
;
52 HIDCollection::~HIDCollection()
54 for (uint32 i
= 0; i
< fChildCount
; i
++)
62 HIDCollection::UsagePage()
65 value
.u
.extended
= fUsage
;
66 return value
.u
.s
.usage_page
;
71 HIDCollection::UsageID()
74 value
.u
.extended
= fUsage
;
75 return value
.u
.s
.usage_id
;
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");
89 fChildren
= newChildren
;
90 fChildren
[fChildCount
++] = child
;
96 HIDCollection::ChildAt(uint32 index
)
98 if (index
>= fChildCount
)
101 return fChildren
[index
];
106 HIDCollection::CountChildrenFlat(uint8 type
)
109 if (type
== COLLECTION_ALL
|| fType
== type
)
112 for (uint32 i
= 0; i
< fChildCount
; i
++) {
113 HIDCollection
*child
= fChildren
[i
];
117 count
+= child
->CountChildrenFlat(type
);
125 HIDCollection::ChildAtFlat(uint8 type
, uint32 index
)
127 return _ChildAtFlat(type
, index
);
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;
147 fItems
[fItemCount
++] = item
;
152 HIDCollection::ItemAt(uint32 index
)
154 if (index
>= fItemCount
)
157 return fItems
[index
];
162 HIDCollection::CountItemsFlat()
164 uint32 count
= fItemCount
;
166 for (uint32 i
= 0; i
< fChildCount
; i
++) {
167 HIDCollection
*child
= fChildren
[i
];
169 count
+= child
->CountItemsFlat();
177 HIDCollection::ItemAtFlat(uint32 index
)
179 return _ItemAtFlat(index
);
184 HIDCollection::PrintToStream(uint32 indentLevel
)
186 char indent
[indentLevel
+ 1];
187 memset(indent
, '\t', indentLevel
);
188 indent
[indentLevel
] = 0;
190 const char *typeName
= "unknown";
192 case COLLECTION_PHYSICAL
:
193 typeName
= "physical";
195 case COLLECTION_APPLICATION
:
196 typeName
= "application";
198 case COLLECTION_LOGICAL
:
199 typeName
= "logical";
201 case COLLECTION_REPORT
:
204 case COLLECTION_NAMED_ARRAY
:
205 typeName
= "named array";
207 case COLLECTION_USAGE_SWITCH
:
208 typeName
= "usage switch";
210 case COLLECTION_USAGE_MODIFIER
:
211 typeName
= "usage modifier";
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
];
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
];
232 child
->PrintToStream(indentLevel
+ 1);
238 HIDCollection::_ChildAtFlat(uint8 type
, uint32
&index
)
240 if (type
== COLLECTION_ALL
|| fType
== type
) {
247 for (uint32 i
= 0; i
< fChildCount
; i
++) {
248 HIDCollection
*child
= fChildren
[i
];
252 HIDCollection
*result
= child
->_ChildAtFlat(type
, index
);
262 HIDCollection::_ItemAtFlat(uint32
&index
)
264 if (index
< fItemCount
)
265 return fItems
[index
];
269 for (uint32 i
= 0; i
< fChildCount
; i
++) {
270 HIDCollection
*child
= fChildren
[i
];
274 HIDReportItem
*result
= child
->_ItemAtFlat(index
);
284 HIDCollection::BuildReportList(uint8 reportType
,
285 HIDReport
**reportList
, uint32
&reportCount
)
288 for (uint32 i
= 0; i
< fItemCount
; i
++) {
289 HIDReportItem
*item
= fItems
[i
];
293 HIDReport
*report
= item
->Report();
294 if (reportType
!= HID_REPORT_TYPE_ANY
&& report
->Type() != reportType
)
298 for (uint32 j
= 0; j
< reportCount
; j
++) {
299 if (reportList
[j
] == report
) {
308 reportList
[reportCount
++] = report
;
311 for (uint32 i
= 0; i
< fChildCount
; i
++) {
312 HIDCollection
*child
= fChildren
[i
];
316 child
->BuildReportList(reportType
, reportList
, reportCount
);