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 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 47 HIDCollection::~HIDCollection() 48 { 49 for (int32 i = 0; i < fChildren.Count(); i++) 50 delete fChildren[i]; 51 } 52 53 54 uint16 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 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 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 * 84 HIDCollection::ChildAt(uint32 index) 85 { 86 if (index >= fChildren.Count()) 87 return NULL; 88 89 return fChildren[index]; 90 } 91 92 93 uint32 94 HIDCollection::CountChildrenFlat(uint8 type) 95 { 96 uint32 count = 0; 97 if (type == COLLECTION_ALL || fType == type) 98 count++; 99 100 for (int32 i = 0; i < fChildren.Count(); i++) { 101 HIDCollection *child = fChildren[i]; 102 if (child == NULL) 103 continue; 104 105 count += child->CountChildrenFlat(type); 106 } 107 108 return count; 109 } 110 111 112 HIDCollection * 113 HIDCollection::ChildAtFlat(uint8 type, uint32 index) 114 { 115 return _ChildAtFlat(type, index); 116 } 117 118 119 void 120 HIDCollection::AddItem(HIDReportItem *item) 121 { 122 if (fItems.PushBack(item) == B_NO_MEMORY) { 123 TRACE_ALWAYS("no memory when trying to resize collection items\n"); 124 } 125 126 } 127 128 129 HIDReportItem * 130 HIDCollection::ItemAt(uint32 index) 131 { 132 if (index >= fItems.Count()) 133 return NULL; 134 135 return fItems[index]; 136 } 137 138 139 uint32 140 HIDCollection::CountItemsFlat() 141 { 142 uint32 count = fItems.Count(); 143 144 for (int32 i = 0; i < fChildren.Count(); i++) { 145 HIDCollection *child = fChildren[i]; 146 if (child != NULL) 147 count += child->CountItemsFlat(); 148 } 149 150 return count; 151 } 152 153 154 HIDReportItem * 155 HIDCollection::ItemAtFlat(uint32 index) 156 { 157 return _ItemAtFlat(index); 158 } 159 160 161 void 162 HIDCollection::PrintToStream(uint32 indentLevel) 163 { 164 char indent[indentLevel + 1]; 165 memset(indent, '\t', indentLevel); 166 indent[indentLevel] = 0; 167 168 const char *typeName = "unknown"; 169 switch (fType) { 170 case COLLECTION_PHYSICAL: 171 typeName = "physical"; 172 break; 173 case COLLECTION_APPLICATION: 174 typeName = "application"; 175 break; 176 case COLLECTION_LOGICAL: 177 typeName = "logical"; 178 break; 179 case COLLECTION_REPORT: 180 typeName = "report"; 181 break; 182 case COLLECTION_NAMED_ARRAY: 183 typeName = "named array"; 184 break; 185 case COLLECTION_USAGE_SWITCH: 186 typeName = "usage switch"; 187 break; 188 case COLLECTION_USAGE_MODIFIER: 189 typeName = "usage modifier"; 190 break; 191 } 192 193 TRACE_ALWAYS("%sHIDCollection %p\n", indent, this); 194 TRACE_ALWAYS("%s\ttype: %u %s\n", indent, fType, typeName); 195 TRACE_ALWAYS("%s\tusage: 0x%08" B_PRIx32 "\n", indent, fUsage); 196 TRACE_ALWAYS("%s\tstring id: %u\n", indent, fStringID); 197 TRACE_ALWAYS("%s\tphysical id: %u\n", indent, fPhysicalID); 198 199 TRACE_ALWAYS("%s\titem count: %" B_PRIu32 "\n", indent, fItems.Count()); 200 for (int32 i = 0; i < fItems.Count(); i++) { 201 HIDReportItem *item = fItems[i]; 202 if (item != NULL) 203 item->PrintToStream(indentLevel + 1); 204 } 205 206 TRACE_ALWAYS("%s\tchild count: %" B_PRIu32 "\n", indent, fChildren.Count()); 207 for (int32 i = 0; i < fChildren.Count(); i++) { 208 HIDCollection *child = fChildren[i]; 209 if (child != NULL) 210 child->PrintToStream(indentLevel + 1); 211 } 212 } 213 214 215 HIDCollection * 216 HIDCollection::_ChildAtFlat(uint8 type, uint32 &index) 217 { 218 if (type == COLLECTION_ALL || fType == type) { 219 if (index == 0) 220 return this; 221 222 index--; 223 } 224 225 for (int32 i = 0; i < fChildren.Count(); i++) { 226 HIDCollection *child = fChildren[i]; 227 if (child == NULL) 228 continue; 229 230 HIDCollection *result = child->_ChildAtFlat(type, index); 231 if (result != NULL) 232 return result; 233 } 234 235 return NULL; 236 } 237 238 239 HIDReportItem * 240 HIDCollection::_ItemAtFlat(uint32 &index) 241 { 242 if (index < fItems.Count()) 243 return fItems[index]; 244 245 index -= fItems.Count(); 246 247 for (int32 i = 0; i < fChildren.Count(); i++) { 248 HIDCollection *child = fChildren[i]; 249 if (child == NULL) 250 continue; 251 252 HIDReportItem *result = child->_ItemAtFlat(index); 253 if (result != NULL) 254 return result; 255 } 256 257 return NULL; 258 } 259 260 261 void 262 HIDCollection::BuildReportList(uint8 reportType, 263 HIDReport **reportList, uint32 &reportCount) 264 { 265 266 for (int32 i = 0; i < fItems.Count(); i++) { 267 HIDReportItem *item = fItems[i]; 268 if (item == NULL) 269 continue; 270 271 HIDReport *report = item->Report(); 272 if (reportType != HID_REPORT_TYPE_ANY && report->Type() != reportType) 273 continue; 274 275 bool found = false; 276 for (uint32 j = 0; j < reportCount; j++) { 277 if (reportList[j] == report) { 278 found = true; 279 break; 280 } 281 } 282 283 if (found) 284 continue; 285 286 reportList[reportCount++] = report; 287 } 288 289 for (int32 i = 0; i < fChildren.Count(); i++) { 290 HIDCollection *child = fChildren[i]; 291 if (child == NULL) 292 continue; 293 294 child->BuildReportList(reportType, reportList, reportCount); 295 } 296 } 297