20 #include "modules/drivers/common/hid/HidReport.h" 21 #include "modules/drivers/common/hid/HidUsages.h" 22 #include "modules/drivers/common/hid/HidUtils.h" 23 #include "pedigree/kernel/Log.h" 24 #include "pedigree/kernel/utilities/utility.h" 27 #define MIX_TYPE_N_TAG(type, tag) (type | (tag << 2)) 30 #define TABBED_LOG(tabs, text) \ 33 char *sTabs = new char[(tabs * 4) + 1]; \ 34 ByteSet(sTabs, ' ', tabs * 4); \ 35 sTabs[tabs * 4] = '\0'; \ 36 DEBUG_LOG(sTabs << text); \ 40 #define ITEM_LOG(tabs, type, value) \ 41 TABBED_LOG(tabs, type << " (" << value << ")" << Hex) 42 #define ITEM_LOG_DEC(tabs, type, value) \ 43 TABBED_LOG(tabs, Dec << type << " (" << value << ")" << Hex) 45 HidReport::HidReport()
49 HidReport::~HidReport()
59 bool bPhysPair =
false;
61 bool bLogPair =
false;
70 for (
size_t i = 0; i < nDescriptorLength; i++)
84 item.raw = pDescriptor[i];
85 uint8_t size = item.size == 3 ? 4 : item.size;
90 value = pDescriptor[i + 1];
92 value = pDescriptor[i + 1] | (pDescriptor[i + 2] << 8);
94 value = pDescriptor[i + 1] | (pDescriptor[i + 2] << 8) |
95 (pDescriptor[i + 3] << 16) | (pDescriptor[i + 4] << 24);
102 if (!pCurrentCollection)
103 if (item.type == MainItem && item.tag != CollectionItem)
107 switch (MIX_TYPE_N_TAG(item.type, item.tag))
110 case MIX_TYPE_N_TAG(MainItem, InputItem):
114 pBlock->
state = currentState;
115 if (value & InputConstant)
117 pBlock->
type = InputBlock::Constant;
118 ITEM_LOG(nDepth,
"Input",
"Constant");
122 if (value & InputVariable)
124 if (value & InputRelative)
126 pBlock->
type = InputBlock::Relative;
128 nDepth,
"Input",
"Data, Variable, Relative");
132 pBlock->
type = InputBlock::Absolute;
134 nDepth,
"Input",
"Data, Variable, Absolute");
139 pBlock->
type = InputBlock::Array;
140 ITEM_LOG(nDepth,
"Input",
"Data, Array");
145 pCurrentCollection->
childs.pushBack(
149 case MIX_TYPE_N_TAG(MainItem, CollectionItem):
153 pCollection->
pParent = pCurrentCollection;
154 pCollection->
state = currentState;
157 if (pCurrentCollection)
158 pCurrentCollection->
childs.pushBack(
162 pCurrentCollection = pCollection;
163 ITEM_LOG(nDepth,
"Collection", value);
167 case MIX_TYPE_N_TAG(MainItem, EndCollectionItem):
169 if (pCurrentCollection)
172 if (!pCurrentCollection->
pParent)
174 pCurrentCollection = pCurrentCollection->
pParent;
178 TABBED_LOG(nDepth,
"End Collection");
182 case MIX_TYPE_N_TAG(GlobalItem, UsagePageItem):
183 currentState.nUsagePage = value;
184 ITEM_LOG_DEC(nDepth,
"Usage Page", value);
186 case MIX_TYPE_N_TAG(GlobalItem, LogMinItem):
187 currentState.nLogMin = value;
189 if (currentState.nLogMax != ~0 && !bLogPair)
192 currentState.nLogMin, currentState.nLogMax);
194 ITEM_LOG(nDepth,
"Logical Minimum", currentState.nLogMin);
195 ITEM_LOG(nDepth,
"Logical Maximum", currentState.nLogMax);
200 case MIX_TYPE_N_TAG(GlobalItem, LogMaxItem):
201 currentState.nLogMax = value;
203 if (currentState.nLogMin != ~0 && !bLogPair)
206 currentState.nLogMin, currentState.nLogMax);
208 ITEM_LOG(nDepth,
"Logical Minimum", currentState.nLogMin);
209 ITEM_LOG(nDepth,
"Logical Maximum", currentState.nLogMax);
214 case MIX_TYPE_N_TAG(GlobalItem, PhysMinItem):
215 currentState.nPhysMin = value;
217 if (currentState.nPhysMax != ~0 && !bPhysPair)
220 currentState.nPhysMin, currentState.nPhysMax);
223 nDepth,
"Physical Minimum", currentState.nPhysMin);
225 nDepth,
"Physical Maximum", currentState.nPhysMax);
230 case MIX_TYPE_N_TAG(GlobalItem, PhysMaxItem):
231 currentState.nPhysMax = value;
233 if (currentState.nPhysMin != ~0 && !bPhysPair)
236 currentState.nPhysMin, currentState.nPhysMax);
239 nDepth,
"Physical Minimum", currentState.nPhysMin);
241 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 currentState.nReportID = value;
252 ITEM_LOG_DEC(nDepth,
"Report ID", value);
254 case MIX_TYPE_N_TAG(GlobalItem, ReportCountItem):
255 currentState.nReportCount = value;
256 ITEM_LOG_DEC(nDepth,
"Report Count", value);
260 case MIX_TYPE_N_TAG(LocalItem, UsageItem):
261 if (!currentState.pUsages)
263 currentState.pUsages->
pushBack(value);
264 ITEM_LOG_DEC(nDepth,
"Usage", value);
266 case MIX_TYPE_N_TAG(LocalItem, UsageMinItem):
267 currentState.nUsageMin = value;
268 ITEM_LOG_DEC(nDepth,
"Usage Minimum", value);
270 case MIX_TYPE_N_TAG(LocalItem, UsageMaxItem):
271 currentState.nUsageMax = value;
272 ITEM_LOG_DEC(nDepth,
"Usage Maximum", value);
277 item.type <<
" " << item.tag <<
" " <<
Hex << value);
282 if (item.type == MainItem)
288 uint8_t *pBuffer, uint8_t *pOldBuffer,
size_t nBufferSize)
295 size_t nBitOffset = 0;
299 MemoryCopy(pOldBuffer, pBuffer, nBufferSize);
303 uint8_t *pBuffer, uint8_t *pOldBuffer,
size_t nBufferSize,
307 for (
size_t i = 0; i < childs.count(); i++)
309 Child *pChild = childs[i];
312 if (pChild->type == CollectionChild)
314 pBuffer, pOldBuffer, nBufferSize, nBitOffset);
317 if (pChild->type == InputBlockChild)
319 pBuffer, pOldBuffer, nBufferSize, nBitOffset,
331 if (pCollection->
state.nUsagePage == HidUsagePages::GenericDesktop)
344 pCollection = pCollection->
pParent;
348 return UnknownDevice;
352 uint8_t *pBuffer, uint8_t *pOldBuffer,
size_t nBufferSize,
353 size_t &nBitOffset, HidDeviceType deviceType)
356 if (state.nReportID != ~0)
361 WARNING(
"HidReport::InputBlock::feedInput: TODO: Implement support for " 367 int64_t nBlockSize = state.nReportCount * state.nReportSize;
371 if ((nBitOffset + nBlockSize > nBufferSize * 8) || type == Constant)
373 nBitOffset += nBlockSize;
378 for (int64_t i = 0; i < state.nReportCount; i++)
381 pBuffer, nBitOffset + i * state.nReportSize, state.nReportSize);
382 int64_t nRelativeValue = 0;
390 pOldBuffer, nBitOffset + i * state.nReportSize,
395 deviceType, state.nUsagePage, state.getUsageByIndex(i),
400 nRelativeValue = nValue;
402 state.nLogMin, state.nLogMax, nRelativeValue);
406 deviceType, state.nUsagePage, state.getUsageByIndex(i),
415 for (int64_t j = 0; j < state.nReportCount; j++)
417 if (HidUtils::getBufferField(
418 pOldBuffer, nBitOffset + j * state.nReportSize,
419 state.nReportSize) == nValue)
429 deviceType, state.nUsagePage, nValue, 1);
442 for (int64_t i = 0; i < state.nReportCount; i++)
445 pOldBuffer, nBitOffset + i * state.nReportSize,
450 bool bDisapeared =
true;
451 for (int64_t j = 0; j < state.nReportCount; j++)
454 pBuffer, nBitOffset + j * state.nReportSize,
455 state.nReportSize) == nOldValue)
465 deviceType, state.nUsagePage, nOldValue, -1);
471 nBitOffset += nBlockSize;
475 : nUsagePage(~0), nLogMin(~0), nLogMax(~0), nPhysMin(~0), nPhysMax(~0),
476 nReportSize(~0), nReportID(~0), nReportCount(~0), pUsages(0),
477 nUsageMin(~0), nUsageMax(~0)
481 HidReport::LocalState::~LocalState()
509 return nUsageIndex < pUsages->
count() ? (*pUsages)[nUsageIndex] : 0;
512 return (nUsageMin + nUsageIndex) <= nUsageMax ? nUsageMin + nUsageIndex : 0;
519 nUsagePage = s.nUsagePage;
522 nPhysMin = s.nPhysMin;
523 nPhysMax = s.nPhysMax;
524 nReportSize = s.nReportSize;
525 nReportID = s.nReportID;
526 nReportCount = s.nReportCount;
528 nUsageMin = s.nUsageMin;
529 nUsageMax = s.nUsageMax;
void pushBack(const T &value)
void feedInput(uint8_t *pBuffer, uint8_t *pOldBuffer, size_t nBufferSize, size_t &nBitOffset)
Collection * m_pRootCollection
The root collection, under which everything is.
void feedInput(uint8_t *pBuffer, uint8_t *pOldBuffer, size_t nBufferSize)
Feeds the input interpreter with a new input buffer.
Structure representing a Collection whitin a report.
LocalState()
Constructor, sets all values to ~0 (invalid)
void sendInputToManager(HidDeviceType deviceType, uint16_t nUsagePage, uint16_t nUsage, int64_t nRelativeValue)
Sends the input to the right handler in HidInputManager or InputManager.
LocalState & operator=(LocalState &s)
Copy constructor.
void parseDescriptor(uint8_t *pDescriptor, size_t nDescriptorLength)
Parses a HID report descriptor and stores the resulted data.
Collection * pParent
Our parent.
Structure holding various global and local values for a Main item.
LocalState state
The local state of the collection.
void fixNegativeMinimum(int64_t &nMin, int64_t nMax)
Converts.
uint64_t getBufferField(uint8_t *pBuffer, size_t nStart, size_t nLength)
Retrieves a field in a buffer.
HidDeviceType guessInputDevice()
Vector< Child * > childs
All the childs in this collection.
uint16_t getUsageByIndex(uint16_t nUsageIndex)
Returns the usage number represented by the given index.
void resetLocalValues()
Resets the local values (called every time a Main item occurs)
void fixNegativeValue(int64_t nMin, int64_t nMax, int64_t &nValue)
Converts.