77 size_t globalDepth = 0;
80 bool bPhysPair =
false;
82 bool bLogPair =
false;
91 for (
size_t i = 0; i < nDescriptorLength; i++) {
102 item.raw = pDescriptor[i];
103 if (item.raw == 0xfe) {
104 if (nDescriptorLength - i < 3 || pDescriptor[i + 1] > nDescriptorLength - i - 3)
106 i += 2 + pDescriptor[i + 1];
109 uint8_t size = item.size == 3 ? 4 : item.size;
110 if (size > nDescriptorLength - i - 1)
116 value = pDescriptor[i + 1];
118 value = pDescriptor[i + 1] | (pDescriptor[i + 2] << 8);
120 value = pDescriptor[i + 1] | (pDescriptor[i + 2] << 8) | (pDescriptor[i + 3] << 16) |
121 (pDescriptor[i + 4] << 24);
128 if (!pCurrentCollection)
129 if (item.type == MainItem && item.tag != CollectionItem)
133 switch (MIX_TYPE_N_TAG(item.type, item.tag)) {
135 case MIX_TYPE_N_TAG(MainItem, InputItem): {
136 if (currentState.nReportSize <= 0 || currentState.nReportSize > 64 ||
137 currentState.nReportCount <= 0 || currentState.nReportCount > 1024)
139 const uint8_t reportId = currentState.nReportID == -1 ? 0 : currentState.nReportID;
140 const size_t bits = currentState.nReportSize * currentState.nReportCount;
141 if (bits > 8192 - m_ReportBits[reportId])
143 m_ReportBits[reportId] += bits;
147 pBlock->
state = currentState;
148 if (value & InputConstant) {
149 pBlock->
type = InputBlock::Constant;
150 ITEM_LOG(nDepth,
"Input",
"Constant");
152 if (value & InputVariable) {
153 if (value & InputRelative) {
154 pBlock->
type = InputBlock::Relative;
155 ITEM_LOG(nDepth,
"Input",
"Data, Variable, Relative");
157 pBlock->
type = InputBlock::Absolute;
158 ITEM_LOG(nDepth,
"Input",
"Data, Variable, Absolute");
161 pBlock->
type = InputBlock::Array;
162 ITEM_LOG(nDepth,
"Input",
"Data, Array");
170 case MIX_TYPE_N_TAG(MainItem, CollectionItem): {
175 pCollection->
pParent = pCurrentCollection;
176 pCollection->
state = currentState;
179 if (pCurrentCollection)
183 pCurrentCollection = pCollection;
184 ITEM_LOG(nDepth,
"Collection", value);
188 case MIX_TYPE_N_TAG(MainItem, EndCollectionItem):
192 pCurrentCollection = pCurrentCollection->
pParent;
194 TABBED_LOG(nDepth,
"End Collection");
198 case MIX_TYPE_N_TAG(GlobalItem, UsagePageItem):
199 currentState.nUsagePage = value;
200 ITEM_LOG_DEC(nDepth,
"Usage Page", value);
202 case MIX_TYPE_N_TAG(GlobalItem, LogMinItem):
203 currentState.nLogMin = value;
205 if (currentState.nLogMax != ~0 && !bLogPair) {
208 ITEM_LOG(nDepth,
"Logical Minimum", currentState.nLogMin);
209 ITEM_LOG(nDepth,
"Logical Maximum", currentState.nLogMax);
213 case MIX_TYPE_N_TAG(GlobalItem, LogMaxItem):
214 currentState.nLogMax = value;
216 if (currentState.nLogMin != ~0 && !bLogPair) {
219 ITEM_LOG(nDepth,
"Logical Minimum", currentState.nLogMin);
220 ITEM_LOG(nDepth,
"Logical Maximum", currentState.nLogMax);
224 case MIX_TYPE_N_TAG(GlobalItem, PhysMinItem):
225 currentState.nPhysMin = value;
227 if (currentState.nPhysMax != ~0 && !bPhysPair) {
230 ITEM_LOG_DEC(nDepth,
"Physical Minimum", currentState.nPhysMin);
231 ITEM_LOG_DEC(nDepth,
"Physical Maximum", currentState.nPhysMax);
235 case MIX_TYPE_N_TAG(GlobalItem, PhysMaxItem):
236 currentState.nPhysMax = value;
238 if (currentState.nPhysMin != ~0 && !bPhysPair) {
241 ITEM_LOG_DEC(nDepth,
"Physical Minimum", currentState.nPhysMin);
242 ITEM_LOG_DEC(nDepth,
"Physical Maximum", currentState.nPhysMax);
246 case MIX_TYPE_N_TAG(GlobalItem, ReportSizeItem):
247 currentState.nReportSize = value;
248 ITEM_LOG_DEC(nDepth,
"Report Size", value);
250 case MIX_TYPE_N_TAG(GlobalItem, ReportIDItem):
251 if (!value || value > 255)
253 currentState.nReportID = value;
254 m_HasReportIds =
true;
255 ITEM_LOG_DEC(nDepth,
"Report ID", value);
257 case MIX_TYPE_N_TAG(GlobalItem, ReportCountItem):
258 currentState.nReportCount = value;
259 ITEM_LOG_DEC(nDepth,
"Report Count", value);
262 case MIX_TYPE_N_TAG(GlobalItem, PushItem):
263 if (globalDepth == 16)
265 globalStack[globalDepth++].copyGlobals(currentState);
267 case MIX_TYPE_N_TAG(GlobalItem, PopItem):
270 currentState.copyGlobals(globalStack[--globalDepth]);
274 case MIX_TYPE_N_TAG(LocalItem, UsageItem):
275 if (!currentState.pUsages)
277 currentState.pUsages->
pushBack(value);
278 ITEM_LOG_DEC(nDepth,
"Usage", value);
280 case MIX_TYPE_N_TAG(LocalItem, UsageMinItem):
281 currentState.nUsageMin = value;
282 ITEM_LOG_DEC(nDepth,
"Usage Minimum", value);
284 case MIX_TYPE_N_TAG(LocalItem, UsageMaxItem):
285 currentState.nUsageMax = value;
286 ITEM_LOG_DEC(nDepth,
"Usage Maximum", value);
289 ITEM_LOG_DEC(nDepth,
"Unknown", item.type <<
" " << item.tag <<
" " <<
Hex << value);
294 if (item.type == MainItem)
298 (m_HasReportIds && m_ReportBits[0]))
300 for (
size_t id = 0;
id < 256; ++id) {
301 if (m_ReportBits[
id]) {
302 m_OldReports[id] =
new uint8_t[(m_ReportBits[id] + 7) / 8]();
325 size_t& nBitOffset, uint8_t reportId,
328 for (
size_t i = 0; i < childs.count(); i++) {
329 Child* pChild = childs[i];
332 if (pChild->type == CollectionChild) {
333 pChild->pCollection->
feedInput(pBuffer, pOldBuffer, nBufferSize, nBitOffset, reportId,
338 if (pChild->type == InputBlockChild) {
339 pChild->pInputBlock->
feedInput(pBuffer, pOldBuffer, nBufferSize, nBitOffset,
340 guessInputDevice(), reportId, inputState);
370 size_t& nBitOffset, HidDeviceType deviceType,
372 const uint8_t
id = state.nReportID == -1 ? 0 : state.nReportID;
377 int64_t nBlockSize = state.nReportCount * state.nReportSize;
381 if ((nBitOffset + nBlockSize > nBufferSize * 8) || type == Constant) {
382 nBitOffset += nBlockSize;
387 for (int64_t i = 0; i < state.nReportCount; i++) {
390 int64_t nRelativeValue = 0;
399 if (nRelativeValue) {
401 nRelativeValue, inputState);
406 nRelativeValue = nValue;
407 if (state.nLogMin < 0 && state.nReportSize < 64 &&
408 (nValue & (uint64_t{1} << (state.nReportSize - 1))))
409 nRelativeValue =
static_cast<int64_t
>(nValue | (~uint64_t{0} << state.nReportSize));
411 if (nRelativeValue) {
413 nRelativeValue, inputState);
421 for (int64_t j = 0; j < state.nReportCount; j++) {
423 state.nReportSize) == nValue) {
444 for (int64_t i = 0; i < state.nReportCount; i++) {
449 bool bDisapeared =
true;
450 for (int64_t j = 0; j < state.nReportCount; j++) {
452 state.nReportSize) == nOldValue) {
467 nBitOffset += nBlockSize;