HRESULT CbSysStringSize(ULONG cchSize, BOOL isByteLen, ULONG *result) { if (result == NULL) return E_INVALIDARG; // +2 for the null terminator // + DWORD_PTR to store the byte length of the string int constant = sizeof(WCHAR) + sizeof(DWORD_PTR) + WIN32_ALLOC_ALIGN; if (isByteLen) { if (SUCCEEDED(ULongAdd(constant, cchSize, result))) { *result = *result & ~WIN32_ALLOC_ALIGN; return S_OK; } } else { ULONG temp = 0; // should not use in-place addition in ULongAdd if (SUCCEEDED(ULongMult(cchSize, sizeof(WCHAR), &temp)) & SUCCEEDED(ULongAdd(temp, constant, result))) { *result = *result & ~WIN32_ALLOC_ALIGN; return S_OK; } } return INTSAFE_E_ARITHMETIC_OVERFLOW; }
static VOID MainThreadProc (PVOID threadArg) { EncryptedIoQueue *queue = (EncryptedIoQueue *) threadArg; PLIST_ENTRY listEntry; EncryptedIoQueueItem *item; LARGE_INTEGER fragmentOffset; ULONG dataRemaining; PUCHAR activeFragmentBuffer = queue->FragmentBufferA; PUCHAR dataBuffer; EncryptedIoRequest *request; uint64 intersectStart; uint32 intersectLength; ULONGLONG addResult; HRESULT hResult; if (IsEncryptionThreadPoolRunning()) KeSetPriorityThread (KeGetCurrentThread(), LOW_REALTIME_PRIORITY); while (!queue->ThreadExitRequested) { if (!NT_SUCCESS (KeWaitForSingleObject (&queue->MainThreadQueueNotEmptyEvent, Executive, KernelMode, FALSE, NULL))) continue; while ((listEntry = ExInterlockedRemoveHeadList (&queue->MainThreadQueue, &queue->MainThreadQueueLock))) { PIRP irp = CONTAINING_RECORD (listEntry, IRP, Tail.Overlay.ListEntry); PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (irp); if (queue->Suspended) KeWaitForSingleObject (&queue->QueueResumedEvent, Executive, KernelMode, FALSE, NULL); item = GetPoolBuffer (queue, sizeof (EncryptedIoQueueItem)); if (!item) { TCCompleteDiskIrp (irp, STATUS_INSUFFICIENT_RESOURCES, 0); DecrementOutstandingIoCount (queue); IoReleaseRemoveLock (&queue->RemoveLock, irp); continue; } item->Queue = queue; item->OriginalIrp = irp; item->Status = STATUS_SUCCESS; IoSetCancelRoutine (irp, NULL); if (irp->Cancel) { CompleteOriginalIrp (item, STATUS_CANCELLED, 0); continue; } switch (irpSp->MajorFunction) { case IRP_MJ_READ: item->Write = FALSE; item->OriginalOffset = irpSp->Parameters.Read.ByteOffset; item->OriginalLength = irpSp->Parameters.Read.Length; break; case IRP_MJ_WRITE: item->Write = TRUE; item->OriginalOffset = irpSp->Parameters.Write.ByteOffset; item->OriginalLength = irpSp->Parameters.Write.Length; break; default: CompleteOriginalIrp (item, STATUS_INVALID_PARAMETER, 0); continue; } #ifdef TC_TRACE_IO_QUEUE item->OriginalIrpOffset = item->OriginalOffset; #endif // Handle misaligned read operations to work around a bug in Windows System Assessment Tool which does not follow FILE_FLAG_NO_BUFFERING requirements when benchmarking disk devices if (queue->IsFilterDevice && !item->Write && item->OriginalLength > 0 && (item->OriginalLength & (ENCRYPTION_DATA_UNIT_SIZE - 1)) == 0 && (item->OriginalOffset.QuadPart & (ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0) { byte *buffer; ULONG alignedLength; LARGE_INTEGER alignedOffset; hResult = ULongAdd(item->OriginalLength, ENCRYPTION_DATA_UNIT_SIZE, &alignedLength); if (hResult != S_OK) { CompleteOriginalIrp (item, STATUS_INVALID_PARAMETER, 0); continue; } alignedOffset.QuadPart = item->OriginalOffset.QuadPart & ~((LONGLONG) ENCRYPTION_DATA_UNIT_SIZE - 1); buffer = TCalloc (alignedLength); if (!buffer) { CompleteOriginalIrp (item, STATUS_INSUFFICIENT_RESOURCES, 0); continue; } item->Status = TCReadDevice (queue->LowerDeviceObject, buffer, alignedOffset, alignedLength); if (NT_SUCCESS (item->Status)) { UINT64_STRUCT dataUnit; dataBuffer = (PUCHAR) MmGetSystemAddressForMdlSafe (irp->MdlAddress, HighPagePriority); if (!dataBuffer) { TCfree (buffer); CompleteOriginalIrp (item, STATUS_INSUFFICIENT_RESOURCES, 0); continue; } if (queue->EncryptedAreaStart != -1 && queue->EncryptedAreaEnd != -1) { GetIntersection (alignedOffset.QuadPart, alignedLength, queue->EncryptedAreaStart, queue->EncryptedAreaEnd, &intersectStart, &intersectLength); if (intersectLength > 0) { dataUnit.Value = intersectStart / ENCRYPTION_DATA_UNIT_SIZE; DecryptDataUnits (buffer + (intersectStart - alignedOffset.QuadPart), &dataUnit, intersectLength / ENCRYPTION_DATA_UNIT_SIZE, queue->CryptoInfo); } } memcpy (dataBuffer, buffer + (item->OriginalOffset.LowPart & (ENCRYPTION_DATA_UNIT_SIZE - 1)), item->OriginalLength); } TCfree (buffer); CompleteOriginalIrp (item, item->Status, NT_SUCCESS (item->Status) ? item->OriginalLength : 0); continue; } // Validate offset and length if (item->OriginalLength == 0 || (item->OriginalLength & (ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0 || (item->OriginalOffset.QuadPart & (ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0 || ( !queue->IsFilterDevice && ( (S_OK != ULongLongAdd(item->OriginalOffset.QuadPart, item->OriginalLength, &addResult)) || (addResult > (ULONGLONG) queue->VirtualDeviceLength) ) ) ) { CompleteOriginalIrp (item, STATUS_INVALID_PARAMETER, 0); continue; } #ifdef TC_TRACE_IO_QUEUE Dump ("Q %I64d [%I64d] %c len=%d\n", item->OriginalOffset.QuadPart, GetElapsedTime (&queue->LastPerformanceCounter), item->Write ? 'W' : 'R', item->OriginalLength); #endif if (!queue->IsFilterDevice) { // Adjust the offset for host file or device if (queue->CryptoInfo->hiddenVolume) hResult = ULongLongAdd(item->OriginalOffset.QuadPart, queue->CryptoInfo->hiddenVolumeOffset, &addResult); else hResult = ULongLongAdd(item->OriginalOffset.QuadPart, queue->CryptoInfo->volDataAreaOffset, &addResult); if (hResult != S_OK) { CompleteOriginalIrp (item, STATUS_INVALID_PARAMETER, 0); continue; } else item->OriginalOffset.QuadPart = addResult; // Hidden volume protection if (item->Write && queue->CryptoInfo->bProtectHiddenVolume) { // If there has already been a write operation denied in order to protect the // hidden volume (since the volume mount time) if (queue->CryptoInfo->bHiddenVolProtectionAction) { // Do not allow writing to this volume anymore. This is to fake a complete volume // or system failure (otherwise certain kinds of inconsistency within the file // system could indicate that this volume has used hidden volume protection). CompleteOriginalIrp (item, STATUS_INVALID_PARAMETER, 0); continue; } // Verify that no byte is going to be written to the hidden volume area if (RegionsOverlap ((unsigned __int64) item->OriginalOffset.QuadPart, (unsigned __int64) item->OriginalOffset.QuadPart + item->OriginalLength - 1, queue->CryptoInfo->hiddenVolumeOffset, (unsigned __int64) queue->CryptoInfo->hiddenVolumeOffset + queue->CryptoInfo->hiddenVolumeProtectedSize - 1)) { Dump ("Hidden volume protection triggered: write %I64d-%I64d (protected %I64d-%I64d)\n", item->OriginalOffset.QuadPart, item->OriginalOffset.QuadPart + item->OriginalLength - 1, queue->CryptoInfo->hiddenVolumeOffset, queue->CryptoInfo->hiddenVolumeOffset + queue->CryptoInfo->hiddenVolumeProtectedSize - 1); queue->CryptoInfo->bHiddenVolProtectionAction = TRUE; // Deny this write operation to prevent the hidden volume from being overwritten CompleteOriginalIrp (item, STATUS_INVALID_PARAMETER, 0); continue; } } } else if (item->Write && RegionsOverlap (item->OriginalOffset.QuadPart, item->OriginalOffset.QuadPart + item->OriginalLength - 1, TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET, TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET + TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE - 1)) { // Prevent inappropriately designed software from damaging important data that may be out of sync with the backup on the Rescue Disk (such as the end of the encrypted area). Dump ("Preventing write to the system encryption key data area\n"); CompleteOriginalIrp (item, STATUS_MEDIA_WRITE_PROTECTED, 0); continue; } else if (item->Write && IsHiddenSystemRunning() && (RegionsOverlap (item->OriginalOffset.QuadPart, item->OriginalOffset.QuadPart + item->OriginalLength - 1, TC_SECTOR_SIZE_BIOS, TC_BOOT_LOADER_AREA_SECTOR_COUNT * TC_SECTOR_SIZE_BIOS - 1) || RegionsOverlap (item->OriginalOffset.QuadPart, item->OriginalOffset.QuadPart + item->OriginalLength - 1, GetBootDriveLength(), _I64_MAX))) { Dump ("Preventing write to boot loader or host protected area\n"); CompleteOriginalIrp (item, STATUS_MEDIA_WRITE_PROTECTED, 0); continue; } dataBuffer = (PUCHAR) MmGetSystemAddressForMdlSafe (irp->MdlAddress, HighPagePriority); if (dataBuffer == NULL) { CompleteOriginalIrp (item, STATUS_INSUFFICIENT_RESOURCES, 0); continue; } // Divide data block to fragments to enable efficient overlapping of encryption and IO operations dataRemaining = item->OriginalLength; fragmentOffset = item->OriginalOffset; while (dataRemaining > 0) { BOOL isLastFragment = dataRemaining <= TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE; ULONG dataFragmentLength = isLastFragment ? dataRemaining : TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE; activeFragmentBuffer = (activeFragmentBuffer == queue->FragmentBufferA ? queue->FragmentBufferB : queue->FragmentBufferA); InterlockedIncrement (&queue->IoThreadPendingRequestCount); // Create IO request request = GetPoolBuffer (queue, sizeof (EncryptedIoRequest)); if (!request) { CompleteOriginalIrp (item, STATUS_INSUFFICIENT_RESOURCES, 0); break; } request->Item = item; request->CompleteOriginalIrp = isLastFragment; request->Offset = fragmentOffset; request->Data = activeFragmentBuffer; request->OrigDataBufferFragment = dataBuffer; request->Length = dataFragmentLength; if (queue->IsFilterDevice) { if (queue->EncryptedAreaStart == -1 || queue->EncryptedAreaEnd == -1) { request->EncryptedLength = 0; } else { // Get intersection of data fragment with encrypted area GetIntersection (fragmentOffset.QuadPart, dataFragmentLength, queue->EncryptedAreaStart, queue->EncryptedAreaEnd, &intersectStart, &intersectLength); request->EncryptedOffset = intersectStart - fragmentOffset.QuadPart; request->EncryptedLength = intersectLength; } } else { request->EncryptedOffset = 0; request->EncryptedLength = dataFragmentLength; } AcquireFragmentBuffer (queue, activeFragmentBuffer); if (item->Write) { // Encrypt data memcpy (activeFragmentBuffer, dataBuffer, dataFragmentLength); if (request->EncryptedLength > 0) { UINT64_STRUCT dataUnit; ASSERT (request->EncryptedOffset + request->EncryptedLength <= request->Offset.QuadPart + request->Length); dataUnit.Value = (request->Offset.QuadPart + request->EncryptedOffset) / ENCRYPTION_DATA_UNIT_SIZE; if (queue->CryptoInfo->bPartitionInInactiveSysEncScope) dataUnit.Value += queue->CryptoInfo->FirstDataUnitNo.Value; else if (queue->RemapEncryptedArea) dataUnit.Value += queue->RemappedAreaDataUnitOffset; EncryptDataUnits (activeFragmentBuffer + request->EncryptedOffset, &dataUnit, request->EncryptedLength / ENCRYPTION_DATA_UNIT_SIZE, queue->CryptoInfo); } } // Queue IO request ExInterlockedInsertTailList (&queue->IoThreadQueue, &request->ListEntry, &queue->IoThreadQueueLock); KeSetEvent (&queue->IoThreadQueueNotEmptyEvent, IO_DISK_INCREMENT, FALSE); if (isLastFragment) break; dataRemaining -= TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE; dataBuffer += TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE; fragmentOffset.QuadPart += TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE; } } } PsTerminateSystemThread (STATUS_SUCCESS); }
int _tmain( int argc, _TCHAR* argv[] ) { cv::setUseOptimized( true ); // Kinectのインスタンス生成、初期化 INuiSensor* pSensor; HRESULT hResult = S_OK; hResult = NuiCreateSensorByIndex( 0, &pSensor ); if( FAILED( hResult ) ){ std::cerr << "Error : NuiCreateSensorByIndex" << std::endl; return -1; } hResult = pSensor->NuiInitialize( NUI_INITIALIZE_FLAG_USES_AUDIO ); if( FAILED( hResult ) ){ std::cerr << "Error : NuiInitialize" << std::endl; return -1; } // Audioストリームの初期化(InitializeAudioStream) std::cout << "InitializeAudioStream" << std::endl; INuiAudioBeam* pNuiAudioSource; hResult = pSensor->NuiGetAudioSource( &pNuiAudioSource ); if( FAILED( hResult ) ){ std::cerr << "Error : NuiGetAudioSource" << std::endl; return -1; } IMediaObject* pMediaObject = nullptr; IPropertyStore* pPropertyStore = nullptr; pNuiAudioSource->QueryInterface( IID_IMediaObject, reinterpret_cast<void**>( &pMediaObject ) ); pNuiAudioSource->QueryInterface( IID_IPropertyStore, reinterpret_cast<void**>( &pPropertyStore ) ); PROPVARIANT propvariant; PropVariantInit( &propvariant ); propvariant.vt = VT_I4; propvariant.lVal = static_cast<LONG>( 4 ); pPropertyStore->SetValue( MFPKEY_WMAAECMA_SYSTEM_MODE, propvariant ); PropVariantClear( &propvariant ); WAVEFORMATEX waveFormat = { AudioFormat, AudioChannels, AudioSamplesPerSecond, AudioAverageBytesPerSecond, AudioBlockAlign, AudioBitsPerSample, 0 }; DMO_MEDIA_TYPE mediaType = { 0 }; MoInitMediaType( &mediaType, sizeof( WAVEFORMATEX ) ); mediaType.majortype = MEDIATYPE_Audio; mediaType.subtype = MEDIASUBTYPE_PCM; mediaType.lSampleSize = 0; mediaType.bFixedSizeSamples = true; mediaType.bTemporalCompression = false; mediaType.formattype = FORMAT_WaveFormatEx; memcpy( mediaType.pbFormat, &waveFormat, sizeof( WAVEFORMATEX ) ); pMediaObject->SetOutputType( 0, &mediaType, 0 ); KinectAudioStream* audioStream = new KinectAudioStream( pMediaObject ); IStream* pStream = nullptr; audioStream->QueryInterface( IID_IStream, reinterpret_cast<void**>( &pStream ) ); CoInitialize( nullptr ); ISpStream* pSpeechStream = nullptr; CoCreateInstance( CLSID_SpStream, NULL, CLSCTX_INPROC_SERVER, __uuidof(ISpStream), reinterpret_cast<void**>( &pSpeechStream ) ); pSpeechStream->SetBaseStream( pStream, SPDFID_WaveFormatEx, &waveFormat ); MoFreeMediaType( &mediaType ); pStream->Release(); pPropertyStore->Release(); pMediaObject->Release(); pNuiAudioSource->Release(); // 音声認識器を作成(CreateSpeechRecognizer) std::cout << "CreateSpeechRecognizer" << std::endl; ISpRecognizer* pSpeechRecognizer; CoCreateInstance( CLSID_SpInprocRecognizer, nullptr, CLSCTX_INPROC_SERVER, __uuidof(ISpRecognizer), reinterpret_cast<void**>( &pSpeechRecognizer ) ); pSpeechRecognizer->SetInput( pSpeechStream, false ); /* // If can use ATL, easier to using SpFindBestToken(sphelper.h). When using Professional or more. ISpObjectToken* pEngineToken = nullptr; SpFindBestToken( SPCAT_RECOGNIZERS, L"Language=411;Kinect=True", NULL, &pEngineToken ); // Japanese "Language=411;Kinect=True" English "Language=409;Kinect=True" */ ///* // If can't use ATL, alternative to using SpFIndBestToken(sphelper.h). When using Express. const wchar_t* pVendorPreferred = L"VendorPreferred"; const unsigned long lengthVendorPreferred = static_cast<unsigned long>( wcslen( pVendorPreferred ) ); unsigned long length; ULongAdd( lengthVendorPreferred, 1, &length ); wchar_t* pAttribsVendorPreferred = new wchar_t[ length ]; StringCchCopyW( pAttribsVendorPreferred, length, pVendorPreferred ); ISpObjectTokenCategory* pTokenCategory = nullptr; CoCreateInstance( CLSID_SpObjectTokenCategory, nullptr, CLSCTX_ALL, __uuidof(ISpObjectTokenCategory), reinterpret_cast<void**>( &pTokenCategory ) ); pTokenCategory->SetId( SPCAT_RECOGNIZERS, false ); IEnumSpObjectTokens* pEnumTokens = nullptr; CoCreateInstance( CLSID_SpMMAudioEnum, nullptr, CLSCTX_ALL, __uuidof(IEnumSpObjectTokens), reinterpret_cast<void**>( &pEnumTokens ) ); pTokenCategory->EnumTokens( L"Language=411;Kinect=True", pAttribsVendorPreferred, &pEnumTokens ); // Japanese "Language=411;Kinect=True" English "Language=409;Kinect=True" delete[] pAttribsVendorPreferred; ISpObjectToken* pEngineToken = nullptr; pEnumTokens->Next( 1, &pEngineToken, nullptr ); //*/ pSpeechRecognizer->SetRecognizer( pEngineToken ); ISpRecoContext* pSpeechContext; pSpeechRecognizer->CreateRecoContext( &pSpeechContext ); pEngineToken->Release(); ///* pTokenCategory->Release(); pEnumTokens->Release(); //*/ // 音声認識辞書の作成(LoadSpeechGrammar) std::cout << "LoadSpeechGrammar" << std::endl; ISpRecoGrammar* pSpeechGrammar; pSpeechContext->CreateGrammar( 1, &pSpeechGrammar ); pSpeechGrammar->LoadCmdFromFile( L"SpeechRecognition_Ja.grxml", /*SPLO_STATIC*/SPLO_DYNAMIC ); // http://www.w3.org/TR/speech-grammar/ (UTF-8/CRLF) audioStream->StartCapture(); pSpeechGrammar->SetRuleState( nullptr, nullptr, SPRS_ACTIVE ); pSpeechRecognizer->SetRecoState( SPRST_ACTIVE_ALWAYS ); pSpeechContext->SetInterest( SPFEI( SPEI_RECOGNITION ), SPFEI( SPEI_RECOGNITION ) ); pSpeechContext->Resume( 0 ); HANDLE hSpeechEvent = INVALID_HANDLE_VALUE; hSpeechEvent = pSpeechContext->GetNotifyEventHandle(); HANDLE hEvents[1] = { hSpeechEvent }; int width = 640; int height = 480; cv::Mat audioMat = cv::Mat::zeros( height, width, CV_8UC3 ); cv::namedWindow( "Audio" ); bool exit = false; std::cout << std::endl << "Speech Recognition Start..." << std::endl << std::endl; while( 1 ){ // イベントの更新待ち ResetEvent( hSpeechEvent ); unsigned long waitObject = MsgWaitForMultipleObjectsEx( ARRAYSIZE( hEvents ), hEvents, INFINITE, QS_ALLINPUT, MWMO_INPUTAVAILABLE ); if( waitObject == WAIT_OBJECT_0 ){ // イベントの取得 const float confidenceThreshold = 0.3f; SPEVENT eventStatus; unsigned long eventFetch = 0; pSpeechContext->GetEvents( 1, &eventStatus, &eventFetch ); while( eventFetch > 0 ){ switch( eventStatus.eEventId ){ // 音声認識イベント(SPEI_HYPOTHESIS:推定またはSPEI_RECOGNITION:認識) case SPEI_HYPOTHESIS: case SPEI_RECOGNITION: if( eventStatus.elParamType == SPET_LPARAM_IS_OBJECT ){ // フレーズの取得 ISpRecoResult* pRecoResult = reinterpret_cast<ISpRecoResult*>( eventStatus.lParam ); SPPHRASE* pPhrase = nullptr; hResult = pRecoResult->GetPhrase( &pPhrase ); if( SUCCEEDED( hResult ) ){ if( ( pPhrase->pProperties != nullptr ) && ( pPhrase->pProperties->pFirstChild != nullptr ) ){ // 辞書のフレーズタグと比較 const SPPHRASEPROPERTY* pSemantic = pPhrase->pProperties->pFirstChild; if( pSemantic->SREngineConfidence > confidenceThreshold ){ if( wcscmp( L"あか", pSemantic->pszValue ) == 0 ){ std::cout << "あか" << std::endl; audioMat = cv::Scalar( 0, 0, 255 ); } else if( wcscmp( L"みどり", pSemantic->pszValue ) == 0 ){ std::cout << "みどり" << std::endl; audioMat = cv::Scalar( 0, 255, 0 ); } else if( wcscmp( L"あお", pSemantic->pszValue ) == 0 ){ std::cout << "あお" << std::endl; audioMat = cv::Scalar( 255, 0, 0 ); } else if( wcscmp( L"おわり", pSemantic->pszValue ) == 0 ){ exit = true; } } } CoTaskMemFree( pPhrase ); } } break; default: break; } pSpeechContext->GetEvents( 1, &eventStatus, &eventFetch ); } } // 表示 cv::imshow( "Audio", audioMat ); // ループの終了判定(Escキー) if( cv::waitKey( 30 ) == VK_ESCAPE || exit ){ break; } } // 終了処理 audioStream->StopCapture(); pSpeechRecognizer->SetRecoState( SPRST_INACTIVE ); CoUninitialize(); pSensor->NuiShutdown(); CloseHandle( hSpeechEvent ); cv::destroyAllWindows(); return 0; }
BOOLEAN FillDeviceInfo( IN PHID_DEVICE HidDevice ) { ULONG numValues; USHORT numCaps; PHIDP_BUTTON_CAPS buttonCaps; PHIDP_VALUE_CAPS valueCaps; PHID_DATA data; ULONG i; USAGE usage; UINT dataIdx; ULONG newFeatureDataLength; ULONG tmpSum; // // setup Input Data buffers. // // // Allocate memory to hold on input report // HidDevice->InputReportBuffer = (PCHAR) calloc (HidDevice->Caps.InputReportByteLength, sizeof (CHAR)); // // Allocate memory to hold the button and value capabilities. // NumberXXCaps is in terms of array elements. // HidDevice->InputButtonCaps = buttonCaps = (PHIDP_BUTTON_CAPS) calloc (HidDevice->Caps.NumberInputButtonCaps, sizeof (HIDP_BUTTON_CAPS)); if (NULL == buttonCaps) { free(HidDevice->InputReportBuffer); HidDevice->InputReportBuffer = NULL; free(buttonCaps); HidDevice->InputButtonCaps = NULL; return (FALSE); } HidDevice->InputValueCaps = valueCaps = (PHIDP_VALUE_CAPS) calloc (HidDevice->Caps.NumberInputValueCaps, sizeof (HIDP_VALUE_CAPS)); if (NULL == valueCaps) { free(HidDevice->InputReportBuffer); HidDevice->InputReportBuffer = NULL; free(buttonCaps); HidDevice->InputButtonCaps = NULL; free(valueCaps); HidDevice->InputValueCaps = NULL; return(FALSE); } // // Have the HidP_X functions fill in the capability structure arrays. // numCaps = HidDevice->Caps.NumberInputButtonCaps; if(numCaps > 0) { if(HIDP_STATUS_SUCCESS != (HidP_GetButtonCaps (HidP_Input, buttonCaps, &numCaps, HidDevice->Ppd))) { return(FALSE); } } numCaps = HidDevice->Caps.NumberInputValueCaps; if(numCaps > 0) { if(HIDP_STATUS_SUCCESS != (HidP_GetValueCaps (HidP_Input, valueCaps, &numCaps, HidDevice->Ppd))) { return(FALSE); } } // // Depending on the device, some value caps structures may represent more // than one value. (A range). In the interest of being verbose, over // efficient, we will expand these so that we have one and only one // struct _HID_DATA for each value. // // To do this we need to count up the total number of values are listed // in the value caps structure. For each element in the array we test // for range if it is a range then UsageMax and UsageMin describe the // usages for this range INCLUSIVE. // numValues = 0; for (i = 0; i < HidDevice->Caps.NumberInputValueCaps; i++, valueCaps++) { if (valueCaps->IsRange) { numValues += valueCaps->Range.UsageMax - valueCaps->Range.UsageMin + 1; if(valueCaps->Range.UsageMin >= valueCaps->Range.UsageMax + (HidDevice->Caps).NumberInputButtonCaps) { return (FALSE); // overrun check } } else { numValues++; } } valueCaps = HidDevice->InputValueCaps; // // Allocate a buffer to hold the struct _HID_DATA structures. // One element for each set of buttons, and one element for each value // found. // HidDevice->InputDataLength = HidDevice->Caps.NumberInputButtonCaps + numValues; HidDevice->InputData = data = (PHID_DATA) calloc (HidDevice->InputDataLength, sizeof (HID_DATA)); if (NULL == data) { free(data); HidDevice->InputData = NULL; return (FALSE); } // // Fill in the button data // dataIdx = 0; for (i = 0; i < HidDevice->Caps.NumberInputButtonCaps; i++, data++, buttonCaps++, dataIdx++) { data->IsButtonData = TRUE; data->Status = HIDP_STATUS_SUCCESS; data->UsagePage = buttonCaps->UsagePage; if (buttonCaps->IsRange) { data->ButtonData.UsageMin = buttonCaps -> Range.UsageMin; data->ButtonData.UsageMax = buttonCaps -> Range.UsageMax; } else { data -> ButtonData.UsageMin = data -> ButtonData.UsageMax = buttonCaps -> NotRange.Usage; } data->ButtonData.MaxUsageLength = HidP_MaxUsageListLength ( HidP_Input, buttonCaps->UsagePage, HidDevice->Ppd); data->ButtonData.Usages = (PUSAGE) calloc (data->ButtonData.MaxUsageLength, sizeof (USAGE)); data->ReportID = buttonCaps -> ReportID; } // // Fill in the value data // for (i = 0; i < HidDevice->Caps.NumberInputValueCaps ; i++, valueCaps++) { if (valueCaps->IsRange) { for (usage = valueCaps->Range.UsageMin; usage <= valueCaps->Range.UsageMax; usage++) { if(dataIdx >= (HidDevice->InputDataLength)) { return (FALSE); // error case } data->IsButtonData = FALSE; data->Status = HIDP_STATUS_SUCCESS; data->UsagePage = valueCaps->UsagePage; data->ValueData.Usage = usage; data->ReportID = valueCaps -> ReportID; data++; dataIdx++; } } else { if(dataIdx >= (HidDevice->InputDataLength)) { return (FALSE); // error case } data->IsButtonData = FALSE; data->Status = HIDP_STATUS_SUCCESS; data->UsagePage = valueCaps->UsagePage; data->ValueData.Usage = valueCaps->NotRange.Usage; data->ReportID = valueCaps -> ReportID; data++; dataIdx++; } } // // setup Output Data buffers. // HidDevice->OutputReportBuffer = (PCHAR) calloc (HidDevice->Caps.OutputReportByteLength, sizeof (CHAR)); HidDevice->OutputButtonCaps = buttonCaps = (PHIDP_BUTTON_CAPS) calloc (HidDevice->Caps.NumberOutputButtonCaps, sizeof (HIDP_BUTTON_CAPS)); if (NULL == buttonCaps) { free(HidDevice->OutputReportBuffer); HidDevice->OutputReportBuffer = NULL; free(buttonCaps); HidDevice->OutputButtonCaps = NULL; return (FALSE); } HidDevice->OutputValueCaps = valueCaps = (PHIDP_VALUE_CAPS) calloc (HidDevice->Caps.NumberOutputValueCaps, sizeof (HIDP_VALUE_CAPS)); if (NULL == valueCaps) { free(valueCaps); HidDevice->OutputValueCaps = NULL; return (FALSE); } numCaps = HidDevice->Caps.NumberOutputButtonCaps; if(numCaps > 0) { if(HIDP_STATUS_SUCCESS != (HidP_GetButtonCaps (HidP_Output, buttonCaps, &numCaps, HidDevice->Ppd))) { return(FALSE); } } numCaps = HidDevice->Caps.NumberOutputValueCaps; if(numCaps > 0) { if(HIDP_STATUS_SUCCESS != (HidP_GetValueCaps (HidP_Output, valueCaps, &numCaps, HidDevice->Ppd))) { return(FALSE); } } numValues = 0; for (i = 0; i < HidDevice->Caps.NumberOutputValueCaps; i++, valueCaps++) { if (valueCaps->IsRange) { numValues += valueCaps->Range.UsageMax - valueCaps->Range.UsageMin + 1; } else { numValues++; } } valueCaps = HidDevice->OutputValueCaps; HidDevice->OutputDataLength = HidDevice->Caps.NumberOutputButtonCaps + numValues; HidDevice->OutputData = data = (PHID_DATA) calloc (HidDevice->OutputDataLength, sizeof (HID_DATA)); if (NULL == data) { free(data); HidDevice->OutputData = NULL; return (FALSE); } for (i = 0; i < HidDevice->Caps.NumberOutputButtonCaps; i++, data++, buttonCaps++) { if (i >= HidDevice->OutputDataLength) { return (FALSE); } if(FAILED(ULongAdd((HidDevice->Caps).NumberOutputButtonCaps , (valueCaps->Range).UsageMax, &tmpSum))) { return(FALSE); } if((valueCaps->Range).UsageMin == tmpSum) { return (FALSE); } data->IsButtonData = TRUE; data->Status = HIDP_STATUS_SUCCESS; data->UsagePage = buttonCaps->UsagePage; if (buttonCaps->IsRange) { data->ButtonData.UsageMin = buttonCaps -> Range.UsageMin; data->ButtonData.UsageMax = buttonCaps -> Range.UsageMax; } else { data -> ButtonData.UsageMin = data -> ButtonData.UsageMax = buttonCaps -> NotRange.Usage; } data->ButtonData.MaxUsageLength = HidP_MaxUsageListLength ( HidP_Output, buttonCaps->UsagePage, HidDevice->Ppd); data->ButtonData.Usages = (PUSAGE) calloc (data->ButtonData.MaxUsageLength, sizeof (USAGE)); data->ReportID = buttonCaps -> ReportID; } for (i = 0; i < HidDevice->Caps.NumberOutputValueCaps ; i++, valueCaps++) { if (valueCaps->IsRange) { for (usage = valueCaps->Range.UsageMin; usage <= valueCaps->Range.UsageMax; usage++) { data->IsButtonData = FALSE; data->Status = HIDP_STATUS_SUCCESS; data->UsagePage = valueCaps->UsagePage; data->ValueData.Usage = usage; data->ReportID = valueCaps -> ReportID; data++; } } else { data->IsButtonData = FALSE; data->Status = HIDP_STATUS_SUCCESS; data->UsagePage = valueCaps->UsagePage; data->ValueData.Usage = valueCaps->NotRange.Usage; data->ReportID = valueCaps -> ReportID; data++; } } // // setup Feature Data buffers. // HidDevice->FeatureReportBuffer = (PCHAR) calloc (HidDevice->Caps.FeatureReportByteLength, sizeof (CHAR)); HidDevice->FeatureButtonCaps = buttonCaps = (PHIDP_BUTTON_CAPS) calloc (HidDevice->Caps.NumberFeatureButtonCaps, sizeof (HIDP_BUTTON_CAPS)); if (NULL == buttonCaps) { free(HidDevice->FeatureReportBuffer); HidDevice->FeatureReportBuffer = NULL; free(buttonCaps); HidDevice->FeatureButtonCaps = NULL; return (FALSE); } HidDevice->FeatureValueCaps = valueCaps = (PHIDP_VALUE_CAPS) calloc (HidDevice->Caps.NumberFeatureValueCaps, sizeof (HIDP_VALUE_CAPS)); if (NULL == valueCaps) { free(HidDevice->FeatureReportBuffer); HidDevice->FeatureReportBuffer = NULL; free(buttonCaps); HidDevice->FeatureButtonCaps = NULL; free(valueCaps); HidDevice->FeatureValueCaps = NULL; return (FALSE); } numCaps = HidDevice->Caps.NumberFeatureButtonCaps; if(numCaps > 0) { if(HIDP_STATUS_SUCCESS != (HidP_GetButtonCaps (HidP_Feature, buttonCaps, &numCaps, HidDevice->Ppd))) { return(FALSE); } } numCaps = HidDevice->Caps.NumberFeatureValueCaps; if(numCaps > 0) { if(HIDP_STATUS_SUCCESS != (HidP_GetValueCaps (HidP_Feature, valueCaps, &numCaps, HidDevice->Ppd))) { return(FALSE); } } numValues = 0; for (i = 0; i < HidDevice->Caps.NumberFeatureValueCaps; i++, valueCaps++) { if (valueCaps->IsRange) { numValues += valueCaps->Range.UsageMax - valueCaps->Range.UsageMin + 1; } else { numValues++; } } valueCaps = HidDevice->FeatureValueCaps; if(FAILED(ULongAdd(HidDevice->Caps.NumberFeatureButtonCaps, numValues, &newFeatureDataLength))) { return(FALSE); } HidDevice->FeatureDataLength = newFeatureDataLength; HidDevice->FeatureData = data = (PHID_DATA) calloc (HidDevice->FeatureDataLength, sizeof (HID_DATA)); if (NULL == data) { free(data); HidDevice->FeatureData = NULL; return (FALSE); } dataIdx = 0; for (i = 0; i < HidDevice->Caps.NumberFeatureButtonCaps; i++, data++, buttonCaps++, dataIdx++) { data->IsButtonData = TRUE; data->Status = HIDP_STATUS_SUCCESS; data->UsagePage = buttonCaps->UsagePage; if (buttonCaps->IsRange) { data->ButtonData.UsageMin = buttonCaps -> Range.UsageMin; data->ButtonData.UsageMax = buttonCaps -> Range.UsageMax; } else { data -> ButtonData.UsageMin = data -> ButtonData.UsageMax = buttonCaps -> NotRange.Usage; } data->ButtonData.MaxUsageLength = HidP_MaxUsageListLength ( HidP_Feature, buttonCaps->UsagePage, HidDevice->Ppd); data->ButtonData.Usages = (PUSAGE) calloc (data->ButtonData.MaxUsageLength, sizeof (USAGE)); data->ReportID = buttonCaps -> ReportID; } for (i = 0; i < HidDevice->Caps.NumberFeatureValueCaps ; i++, valueCaps++) { if (valueCaps->IsRange) { for (usage = valueCaps->Range.UsageMin; usage <= valueCaps->Range.UsageMax; usage++) { if(dataIdx >= (HidDevice->FeatureDataLength)) { return (FALSE); // error case } data->IsButtonData = FALSE; data->Status = HIDP_STATUS_SUCCESS; data->UsagePage = valueCaps->UsagePage; data->ValueData.Usage = usage; data->ReportID = valueCaps -> ReportID; data++; dataIdx++; } } else { if(dataIdx >= (HidDevice->FeatureDataLength)) { return (FALSE); // error case } data->IsButtonData = FALSE; data->Status = HIDP_STATUS_SUCCESS; data->UsagePage = valueCaps->UsagePage; data->ValueData.Usage = valueCaps->NotRange.Usage; data->ReportID = valueCaps -> ReportID; data++; dataIdx++; } } return (TRUE); }
// This routine is called by worker thread to read a single sample, compare threshold // and push it back to CLX. It simulates hardware thresholding by only generating data // when the change of data is greater than threshold. NTSTATUS PedometerDevice::GetData( ) { PHardwareSimulator pSimulator = GetHardwareSimulatorContextFromInstance(m_SimulatorInstance); BOOLEAN DataReady = FALSE; NTSTATUS Status = STATUS_SUCCESS; ULONG CachedStepCountLimit = 0; ULONG LastStepCountLimit = 0; PedometerSample Sample = {}; SENSOR_FunctionEnter(); if (nullptr == pSimulator) { Status = STATUS_INSUFFICIENT_RESOURCES; TraceError("PED %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status); goto Exit; } Status = pSimulator->GetSample(&Sample); if (!NT_SUCCESS(Status)) { TraceError("PED %!FUNC! GetSample failed %!STATUS!", Status); goto Exit; } if (FALSE != m_FirstSample) { Status = GetPerformanceTime(&m_StartTime); if (!NT_SUCCESS(Status)) { m_StartTime = 0; TraceError("PED %!FUNC! GetPerformanceTime failed %!STATUS!", Status); } m_SampleCount = 0; DataReady = TRUE; } else { if (0 == m_CachedThreshold || FALSE != Sample.IsFirstAfterReset) { // Streaming mode DataReady = TRUE; } else { if (FAILED(ULongAdd(Sample.UnknownStepCount, Sample.WalkingStepCount, &CachedStepCountLimit)) || FAILED(ULongAdd(Sample.RunningStepCount, CachedStepCountLimit, &CachedStepCountLimit))) { // If an overflow happened, we assume we reached the threshold // in other words, there is no threshold value that can be larger // than an overflowed value. DataReady = TRUE; } else if (FAILED(ULongAdd(m_LastSample.UnknownStepCount, m_LastSample.WalkingStepCount, &LastStepCountLimit)) || FAILED(ULongAdd(m_LastSample.RunningStepCount, LastStepCountLimit, &LastStepCountLimit))) { // If an overflow happened, we assume we reached the threshold // in other words, there is no threshold value that can be larger // than an overflowed value. DataReady = TRUE; } else if ((LastStepCountLimit < m_CachedThreshold && CachedStepCountLimit >= m_CachedThreshold) || (FALSE != Sample.IsFirstAfterReset)) { // Compare the change of data to threshold, and only push the data back to // clx if the change exceeds threshold or if this is the first sample after reset. This is usually done in HW. DataReady = TRUE; } } } if (FALSE != DataReady) { // update last sample m_LastSample = Sample; // push to clx InitPropVariantFromBoolean(m_LastSample.IsFirstAfterReset, &(m_pData->List[PEDOMETER_DATA_FIRST_AFTER_RESET].Value)); InitPropVariantFromUInt32(PedometerStepType_Unknown, &(m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_TYPE].Value)); InitPropVariantFromInt64(m_LastSample.UnknownStepDurationMs, &(m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_DURATION].Value)); InitPropVariantFromUInt32(m_LastSample.UnknownStepCount, &(m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_COUNT].Value)); InitPropVariantFromUInt32(PedometerStepType_Walking, &(m_pData->List[PEDOMETER_DATA_WALKING_STEP_TYPE].Value)); InitPropVariantFromInt64(m_LastSample.WalkingStepDurationMs, &(m_pData->List[PEDOMETER_DATA_WALKING_STEP_DURATION].Value)); InitPropVariantFromUInt32(m_LastSample.WalkingStepCount, &(m_pData->List[PEDOMETER_DATA_WALKING_STEP_COUNT].Value)); InitPropVariantFromUInt32(PedometerStepType_Running, &(m_pData->List[PEDOMETER_DATA_RUNNING_STEP_TYPE].Value)); InitPropVariantFromInt64(m_LastSample.RunningStepDurationMs, &(m_pData->List[PEDOMETER_DATA_RUNNING_STEP_DURATION].Value)); InitPropVariantFromUInt32(m_LastSample.RunningStepCount, &(m_pData->List[PEDOMETER_DATA_RUNNING_STEP_COUNT].Value)); // reset IsFirstAfterReset m_LastSample.IsFirstAfterReset = FALSE; InitPropVariantFromFileTime(&m_LastSample.Timestamp, &(m_pData->List[PEDOMETER_DATA_TIMESTAMP].Value)); SensorsCxSensorDataReady(m_SensorInstance, m_pData); m_FirstSample = FALSE; } else { Status = STATUS_DATA_NOT_ACCEPTED; TraceInformation("PED %!FUNC! Data did NOT meet the threshold"); } SENSOR_FunctionExit(Status); Exit: return Status; }