73 size_t globalDepth = 0;
76 bool bPhysPair =
false;
78 bool bLogPair =
false;
87 for (
size_t i = 0; i < nDescriptorLength; i++) {
98 item.raw = pDescriptor[i];
99 if (item.raw == 0xfe) {
100 if (nDescriptorLength - i < 3 || pDescriptor[i + 1] > nDescriptorLength - i - 3)
102 i += 2 + pDescriptor[i + 1];
105 uint8_t size = item.size == 3 ? 4 : item.size;
106 if (size > nDescriptorLength - i - 1)
112 value = pDescriptor[i + 1];
114 value = pDescriptor[i + 1] | (pDescriptor[i + 2] << 8);
116 value = pDescriptor[i + 1] | (pDescriptor[i + 2] << 8) | (pDescriptor[i + 3] << 16) |
117 (pDescriptor[i + 4] << 24);
124 if (!pCurrentCollection)
125 if (item.type == MainItem && item.tag != CollectionItem)
129 switch (MIX_TYPE_N_TAG(item.type, item.tag)) {
131 case MIX_TYPE_N_TAG(MainItem, InputItem): {
132 if (currentState.nReportSize <= 0 || currentState.nReportSize > 64 ||
133 currentState.nReportCount <= 0 || currentState.nReportCount > 1024)
135 const uint8_t reportId = currentState.nReportID == -1 ? 0 : currentState.nReportID;
136 const size_t bits = currentState.nReportSize * currentState.nReportCount;
137 if (bits > 8192 - m_ReportBits[reportId])
139 m_ReportBits[reportId] += bits;
143 pBlock->
state = currentState;
144 if (value & InputConstant) {
145 pBlock->
type = InputBlock::Constant;
146 ITEM_LOG(nDepth,
"Input",
"Constant");
148 if (value & InputVariable) {
149 if (value & InputRelative) {
150 pBlock->
type = InputBlock::Relative;
151 ITEM_LOG(nDepth,
"Input",
"Data, Variable, Relative");
153 pBlock->
type = InputBlock::Absolute;
154 ITEM_LOG(nDepth,
"Input",
"Data, Variable, Absolute");
157 pBlock->
type = InputBlock::Array;
158 ITEM_LOG(nDepth,
"Input",
"Data, Array");
166 case MIX_TYPE_N_TAG(MainItem, CollectionItem): {
171 pCollection->
pParent = pCurrentCollection;
172 pCollection->
state = currentState;
175 if (pCurrentCollection)
179 pCurrentCollection = pCollection;
180 ITEM_LOG(nDepth,
"Collection", value);
184 case MIX_TYPE_N_TAG(MainItem, EndCollectionItem):
188 pCurrentCollection = pCurrentCollection->
pParent;
190 TABBED_LOG(nDepth,
"End Collection");
194 case MIX_TYPE_N_TAG(GlobalItem, UsagePageItem):
195 currentState.nUsagePage = value;
196 ITEM_LOG_DEC(nDepth,
"Usage Page", value);
198 case MIX_TYPE_N_TAG(GlobalItem, LogMinItem):
199 currentState.nLogMin = value;
201 if (currentState.nLogMax != ~0 && !bLogPair) {
204 ITEM_LOG(nDepth,
"Logical Minimum", currentState.nLogMin);
205 ITEM_LOG(nDepth,
"Logical Maximum", currentState.nLogMax);
209 case MIX_TYPE_N_TAG(GlobalItem, LogMaxItem):
210 currentState.nLogMax = value;
212 if (currentState.nLogMin != ~0 && !bLogPair) {
215 ITEM_LOG(nDepth,
"Logical Minimum", currentState.nLogMin);
216 ITEM_LOG(nDepth,
"Logical Maximum", currentState.nLogMax);
220 case MIX_TYPE_N_TAG(GlobalItem, PhysMinItem):
221 currentState.nPhysMin = value;
223 if (currentState.nPhysMax != ~0 && !bPhysPair) {
226 ITEM_LOG_DEC(nDepth,
"Physical Minimum", currentState.nPhysMin);
227 ITEM_LOG_DEC(nDepth,
"Physical Maximum", currentState.nPhysMax);
231 case MIX_TYPE_N_TAG(GlobalItem, PhysMaxItem):
232 currentState.nPhysMax = value;
234 if (currentState.nPhysMin != ~0 && !bPhysPair) {
237 ITEM_LOG_DEC(nDepth,
"Physical Minimum", currentState.nPhysMin);
238 ITEM_LOG_DEC(nDepth,
"Physical Maximum", currentState.nPhysMax);
242 case MIX_TYPE_N_TAG(GlobalItem, ReportSizeItem):
243 currentState.nReportSize = value;
244 ITEM_LOG_DEC(nDepth,
"Report Size", value);
246 case MIX_TYPE_N_TAG(GlobalItem, ReportIDItem):
247 if (!value || value > 255)
249 currentState.nReportID = value;
250 m_HasReportIds =
true;
251 ITEM_LOG_DEC(nDepth,
"Report ID", value);
253 case MIX_TYPE_N_TAG(GlobalItem, ReportCountItem):
254 currentState.nReportCount = value;
255 ITEM_LOG_DEC(nDepth,
"Report Count", value);
258 case MIX_TYPE_N_TAG(GlobalItem, PushItem):
259 if (globalDepth == 16)
261 globalStack[globalDepth++].copyGlobals(currentState);
263 case MIX_TYPE_N_TAG(GlobalItem, PopItem):
266 currentState.copyGlobals(globalStack[--globalDepth]);
270 case MIX_TYPE_N_TAG(LocalItem, UsageItem):
271 if (!currentState.pUsages)
273 currentState.pUsages->
pushBack(value);
274 ITEM_LOG_DEC(nDepth,
"Usage", value);
276 case MIX_TYPE_N_TAG(LocalItem, UsageMinItem):
277 currentState.nUsageMin = value;
278 ITEM_LOG_DEC(nDepth,
"Usage Minimum", value);
280 case MIX_TYPE_N_TAG(LocalItem, UsageMaxItem):
281 currentState.nUsageMax = value;
282 ITEM_LOG_DEC(nDepth,
"Usage Maximum", value);
285 ITEM_LOG_DEC(nDepth,
"Unknown", item.type <<
" " << item.tag <<
" " <<
Hex << value);
290 if (item.type == MainItem)
294 (m_HasReportIds && m_ReportBits[0]))
296 for (
size_t id = 0;
id < 256; ++id) {
297 if (m_ReportBits[
id]) {
298 m_OldReports[id] =
new uint8_t[(m_ReportBits[id] + 7) / 8]();
319 size_t& nBitOffset, uint8_t reportId) {
321 for (
size_t i = 0; i < childs.count(); i++) {
322 Child* pChild = childs[i];
325 if (pChild->type == CollectionChild)
326 pChild->pCollection->
feedInput(pBuffer, pOldBuffer, nBufferSize, nBitOffset, reportId);
329 if (pChild->type == InputBlockChild)
330 pChild->pInputBlock->
feedInput(pBuffer, pOldBuffer, nBufferSize, nBitOffset,
331 guessInputDevice(), reportId);
360 size_t& nBitOffset, HidDeviceType deviceType,
362 const uint8_t
id = state.nReportID == -1 ? 0 : state.nReportID;
367 int64_t nBlockSize = state.nReportCount * state.nReportSize;
371 if ((nBitOffset + nBlockSize > nBufferSize * 8) || type == Constant) {
372 nBitOffset += nBlockSize;
377 for (int64_t i = 0; i < state.nReportCount; i++) {
380 int64_t nRelativeValue = 0;
395 nRelativeValue = nValue;
396 if (state.nLogMin < 0 && state.nReportSize < 64 &&
397 (nValue & (uint64_t{1} << (state.nReportSize - 1))))
398 nRelativeValue =
static_cast<int64_t
>(nValue | (~uint64_t{0} << state.nReportSize));
409 for (int64_t j = 0; j < state.nReportCount; j++) {
411 state.nReportSize) == nValue) {
431 for (int64_t i = 0; i < state.nReportCount; i++) {
436 bool bDisapeared =
true;
437 for (int64_t j = 0; j < state.nReportCount; j++) {
439 state.nReportSize) == nOldValue) {
453 nBitOffset += nBlockSize;