/* *------------------------------------------------------------------------------ * * HIDSetButton - Set the state of a button for a Page * * Input: * reportType - HIDP_Input, HIDP_Output, HIDP_Feature * usagePage - Page Criteria or zero * iCollection - Collection Criteria or zero * usage - Usages for pressed button * ptPreparsedData - Pre-Parsed Data * psReport - An HID Report * iReportLength - The length of the Report * Output: * Returns: * *------------------------------------------------------------------------------ */ OSStatus HIDSetButton (HIDReportType reportType, HIDUsage usagePage, UInt32 collection, HIDUsage usage, HIDPreparsedDataRef preparsedDataRef, void * report, IOByteCount reportLength) { HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr) preparsedDataRef; HIDCollection *ptCollection; HIDReportItem *ptReportItem; OSStatus iStatus; int iR, iX; SInt32 data; int iStart; int iReportItem; UInt32 iUsageIndex; Boolean bIncompatibleReport = false; Boolean butNotReally = false; /* * Disallow Null Pointers */ if ((ptPreparsedData == NULL) || (report == NULL)) return kHIDNullPointerErr; if (ptPreparsedData->hidTypeIfValid != kHIDOSType) return kHIDInvalidPreparsedDataErr; /* * The Collection must be in range */ if (collection >= ptPreparsedData->collectionCount) return kHIDBadParameterErr; /* * Search only the scope of the Collection specified * Go through the ReportItems * Filter on ReportType and usagePage */ ptCollection = &ptPreparsedData->collections[collection]; for (iR=0; iR<ptCollection->reportItemCount; iR++) { iReportItem = ptCollection->firstReportItem + iR; ptReportItem = &ptPreparsedData->reportItems[iReportItem]; if (HIDIsButton(ptReportItem, preparsedDataRef) && HIDHasUsage(preparsedDataRef,ptReportItem,usagePage,usage,&iUsageIndex,NULL)) { /* * This may be the proper data to get * Let's check for the proper Report ID, Type, and Length */ iStatus = HIDCheckReport(reportType,preparsedDataRef,ptReportItem,report,reportLength); /* * The Report ID or Type may not match. * This may not be an error (yet) */ if (iStatus == kHIDIncompatibleReportErr) bIncompatibleReport = true; else if (iStatus != kHIDSuccess) return iStatus; else { butNotReally = true; /* * Save Arrays */ if ((ptReportItem->dataModes & kHIDDataArrayBit) == kHIDDataArray) { for (iX=0; iX<ptReportItem->globals.reportCount; iX++) { iStart = ptReportItem->startBit + (ptReportItem->globals.reportSize * iX); iStatus = HIDGetData(report, reportLength, iStart, ptReportItem->globals.reportSize, &data, true); if (!iStatus) iStatus = HIDPostProcessRIValue (ptReportItem, &data); if (iStatus != kHIDSuccess) return iStatus; // if not already in the list, add it (is this code right??) if (data == 0) return HIDPutData(report, reportLength, iStart, ptReportItem->globals.reportSize, iUsageIndex + ptReportItem->globals.logicalMinimum); } return kHIDBufferTooSmallErr; } /* * Save Bitmaps */ else if (ptReportItem->globals.reportSize == 1) { iStart = ptReportItem->startBit + (ptReportItem->globals.reportSize * iUsageIndex); // should we call HIDPreProcessRIValue here? // we are passing '-1' as trhe value, is this right? Some hack to set the right bit to 1? iStatus = HIDPutData(report, reportLength, iStart, ptReportItem->globals.reportSize, -1); if (iStatus != kHIDSuccess) return iStatus; return kHIDSuccess; } } } } // If any of the report items were not the right type, we have set the bIncompatibleReport flag. // However, if any of the report items really were the correct type, we have done our job of checking // and really didn't find a usage. Don't let the bIncompatibleReport flag wipe out our valid test. if (bIncompatibleReport && !butNotReally) return kHIDIncompatibleReportErr; return kHIDUsageNotFoundErr; }
/* *------------------------------------------------------------------------------ * * HIDGetUsageValue - Get the value for a usage * * Input: * reportType - HIDP_Input, HIDP_Output, HIDP_Feature * usagePage - Page Criteria or zero * iCollection - Collection Criteria or zero * usage - The usage to get the value for * piUsageValue - User-supplied place to put value * ptPreparsedData - Pre-Parsed Data * psReport - An HID Report * iReportLength - The length of the Report * Output: * piValue - Pointer to usage Value * Returns: * *------------------------------------------------------------------------------ */ OSStatus HIDGetUsageValue (HIDReportType reportType, HIDUsage usagePage, UInt32 iCollection, HIDUsage usage, SInt32 * piUsageValue, HIDPreparsedDataRef preparsedDataRef, void * psReport, ByteCount iReportLength) { HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr) preparsedDataRef; HIDCollection *ptCollection; HIDReportItem *ptReportItem; OSStatus iStatus; int iR; SInt32 iValue; int iStart; int iReportItem; UInt32 iUsageIndex; Boolean bIncompatibleReport = false; /* * Disallow Null Pointers */ if ((ptPreparsedData == NULL) || (piUsageValue == NULL) || (psReport == NULL)) return kHIDNullPointerErr; if (ptPreparsedData->hidTypeIfValid != kHIDOSType) return kHIDInvalidPreparsedDataErr; /* * The Collection must be in range */ if ((iCollection < 0) || (iCollection >= ptPreparsedData->collectionCount)) return kHIDBadParameterErr; /* * Search only the scope of the Collection specified * Go through the ReportItems * Filter on ReportType and usagePage */ ptCollection = &ptPreparsedData->collections[iCollection]; for (iR=0; iR<ptCollection->reportItemCount; iR++) { iReportItem = ptCollection->firstReportItem + iR; ptReportItem = &ptPreparsedData->reportItems[iReportItem]; if (HIDIsVariable(ptReportItem, preparsedDataRef) && HIDHasUsage(preparsedDataRef,ptReportItem,usagePage,usage,&iUsageIndex,NULL)) { /* * This may be the proper data to get * Let's check for the proper Report ID, Type, and Length */ iStatus = HIDCheckReport(reportType,preparsedDataRef,ptReportItem, psReport,iReportLength); /* * The Report ID or Type may not match. * This may not be an error (yet) */ if (iStatus == kHIDIncompatibleReportErr) bIncompatibleReport = true; else if (iStatus != kHIDSuccess) return iStatus; else { /* * Pick up the data */ iStart = ptReportItem->startBit + (ptReportItem->globals.reportSize * iUsageIndex); iStatus = HIDGetData(psReport, iReportLength, iStart, ptReportItem->globals.reportSize, &iValue, ((ptReportItem->globals.logicalMinimum < 0) ||(ptReportItem->globals.logicalMaximum < 0))); if (!iStatus) iStatus = HIDPostProcessRIValue (ptReportItem, &iValue); *piUsageValue = iValue; return iStatus; } } } if (bIncompatibleReport) return kHIDIncompatibleReportErr; return kHIDUsageNotFoundErr; }