summaryrefslogtreecommitdiff
path: root/general/echo/umdf2/exe/echoapp.cpp
diff options
context:
space:
mode:
authorDave Wilson <[email protected]>2015-03-17 19:50:07 -0700
committerDave Wilson <[email protected]>2015-03-17 19:50:07 -0700
commit97cf5197cf5b882b2c689d8dc2b555f2edf8f418 (patch)
tree46f3701832d70b420eb0fc0eb93261f9da45db3f /general/echo/umdf2/exe/echoapp.cpp
parentef1905bf1e8825bb31120dfb27e0daf3154d859a (diff)
Initial publish
Diffstat (limited to 'general/echo/umdf2/exe/echoapp.cpp')
-rw-r--r--general/echo/umdf2/exe/echoapp.cpp700
1 files changed, 700 insertions, 0 deletions
diff --git a/general/echo/umdf2/exe/echoapp.cpp b/general/echo/umdf2/exe/echoapp.cpp
new file mode 100644
index 00000000..9649a407
--- /dev/null
+++ b/general/echo/umdf2/exe/echoapp.cpp
@@ -0,0 +1,700 @@
+/*++
+
+Copyright (c) Microsoft Corporation
+
+Module Name:
+
+ ioctl.cpp
+
+Abstract:
+
+ A simple asynch test for usb driver.
+
+
+Environment:
+
+ user mode only
+
+--*/
+
+
+#include <DriverSpecs.h>
+_Analysis_mode_(_Analysis_code_type_user_code_)
+
+#define INITGUID
+
+#include <windows.h>
+#include <strsafe.h>
+#include <setupapi.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "public.h"
+
+#define NUM_ASYNCH_IO 100
+#define BUFFER_SIZE (40*1024)
+
+#define READER_TYPE 1
+#define WRITER_TYPE 2
+
+#define MAX_DEVPATH_LENGTH 256
+
+BOOLEAN G_PerformAsyncIo;
+BOOLEAN G_LimitedLoops;
+ULONG G_AsyncIoLoopsNum;
+CHAR G_DevicePath[MAX_DEVPATH_LENGTH];
+
+
+ULONG
+AsyncIo(
+ PVOID ThreadParameter
+ );
+
+BOOLEAN
+PerformWriteReadTest(
+ IN HANDLE hDevice,
+ IN ULONG TestLength
+ );
+
+BOOL
+GetDevicePath(
+ IN LPGUID InterfaceGuid,
+ _Out_writes_(BufLen) PCHAR DevicePath,
+ _In_ size_t BufLen
+ );
+
+
+int __cdecl
+main(
+ _In_ int argc,
+ _In_reads_(argc) char* argv[]
+ )
+{
+ HANDLE hDevice = INVALID_HANDLE_VALUE;
+ HANDLE th1 = NULL;
+ BOOLEAN result = TRUE;
+
+
+ if (argc > 1) {
+ if(!_strnicmp (argv[1], "-Async", 6) ) {
+ G_PerformAsyncIo = TRUE;
+ if (argc > 2) {
+ G_AsyncIoLoopsNum = atoi(argv[2]);
+ G_LimitedLoops = TRUE;
+ }
+ else {
+ G_LimitedLoops = FALSE;
+ }
+
+ } else {
+ printf("Usage:\n");
+ printf(" Echoapp.exe --- Send single write and read request synchronously\n");
+ printf(" Echoapp.exe -Async --- Send reads and writes asynchronously without terminating\n");
+ printf(" Echoapp.exe -Async <number> --- Send <number> reads and writes asynchronously\n");
+ printf("Exit the app anytime by pressing Ctrl-C\n");
+ result = FALSE;
+ goto exit;
+ }
+ }
+
+ if ( !GetDevicePath(
+ (LPGUID) &GUID_DEVINTERFACE_ECHO,
+ G_DevicePath,
+ sizeof(G_DevicePath)/sizeof(G_DevicePath[0])) )
+ {
+ result = FALSE;
+ goto exit;
+ }
+
+ printf("DevicePath: %s\n", G_DevicePath);
+
+ hDevice = CreateFile(G_DevicePath,
+ GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL );
+
+ if (hDevice == INVALID_HANDLE_VALUE) {
+ printf("Failed to open device. Error %d\n",GetLastError());
+ result = FALSE;
+ goto exit;
+ }
+
+ printf("Opened device successfully\n");
+
+ if(G_PerformAsyncIo) {
+
+ printf("Starting AsyncIo\n");
+
+ //
+ // Create a reader thread
+ //
+ th1 = CreateThread( NULL, // Default Security Attrib.
+ 0, // Initial Stack Size,
+ (LPTHREAD_START_ROUTINE) AsyncIo, // Thread Func
+ (LPVOID)READER_TYPE,
+ 0, // Creation Flags
+ NULL ); // Don't need the Thread Id.
+
+ if (th1 == NULL) {
+ printf("Couldn't create reader thread - error %d\n", GetLastError());
+ result = FALSE;
+ goto exit;
+ }
+
+ //
+ // Use this thread for peforming write.
+ //
+ result = (BOOLEAN)AsyncIo((PVOID)WRITER_TYPE);
+
+ }else {
+ //
+ // Write pattern buffers and read them back, then verify them
+ //
+ result = PerformWriteReadTest(hDevice, 512);
+ if(!result) {
+ goto exit;
+ }
+
+ result = PerformWriteReadTest(hDevice, 30*1024);
+ if(!result) {
+ goto exit;
+ }
+
+ }
+
+exit:
+
+ if (th1 != NULL) {
+ WaitForSingleObject(th1, INFINITE);
+ CloseHandle(th1);
+ }
+
+ if (hDevice != INVALID_HANDLE_VALUE) {
+ CloseHandle(hDevice);
+ }
+
+ return ((result == TRUE) ? 0 : 1);
+
+}
+
+PUCHAR
+CreatePatternBuffer(
+ IN ULONG Length
+ )
+{
+ unsigned int i;
+ PUCHAR p, pBuf;
+
+ pBuf = (PUCHAR)malloc(Length);
+ if( pBuf == NULL ) {
+ printf("Could not allocate %d byte buffer\n",Length);
+ return NULL;
+ }
+
+ p = pBuf;
+
+ for(i=0; i < Length; i++ ) {
+ *p = (UCHAR)i;
+ p++;
+ }
+
+ return pBuf;
+}
+
+BOOLEAN
+VerifyPatternBuffer(
+ _In_reads_bytes_(Length) PUCHAR pBuffer,
+ _In_ ULONG Length
+ )
+{
+ unsigned int i;
+ PUCHAR p = pBuffer;
+
+ for( i=0; i < Length; i++ ) {
+
+ if( *p != (UCHAR)(i & 0xFF) ) {
+ printf("Pattern changed. SB 0x%x, Is 0x%x\n",
+ (UCHAR)(i & 0xFF), *p);
+ return FALSE;
+ }
+
+ p++;
+ }
+
+ return TRUE;
+}
+
+BOOLEAN
+PerformWriteReadTest(
+ IN HANDLE hDevice,
+ IN ULONG TestLength
+ )
+/*
+*/
+{
+ ULONG bytesReturned =0;
+ PUCHAR WriteBuffer = NULL,
+ ReadBuffer = NULL;
+ BOOLEAN result = TRUE;
+
+ WriteBuffer = CreatePatternBuffer(TestLength);
+ if( WriteBuffer == NULL ) {
+
+ result = FALSE;
+ goto Cleanup;
+ }
+
+ ReadBuffer = (PUCHAR)malloc(TestLength);
+ if( ReadBuffer == NULL ) {
+
+ printf("PerformWriteReadTest: Could not allocate %d "
+ "bytes ReadBuffer\n",TestLength);
+
+ result = FALSE;
+ goto Cleanup;
+
+ }
+
+ //
+ // Write the pattern to the device
+ //
+ bytesReturned = 0;
+
+ if (!WriteFile ( hDevice,
+ WriteBuffer,
+ TestLength,
+ &bytesReturned,
+ NULL)) {
+
+ printf ("PerformWriteReadTest: WriteFile failed: "
+ "Error %d\n", GetLastError());
+
+ result = FALSE;
+ goto Cleanup;
+
+ } else {
+
+ if( bytesReturned != TestLength ) {
+
+ printf("bytes written is not test length! Written %d, "
+ "SB %d\n",bytesReturned, TestLength);
+
+ result = FALSE;
+ goto Cleanup;
+ }
+
+ printf ("%d Pattern Bytes Written successfully\n",
+ bytesReturned);
+ }
+
+ bytesReturned = 0;
+
+ if ( !ReadFile (hDevice,
+ ReadBuffer,
+ TestLength,
+ &bytesReturned,
+ NULL)) {
+
+ printf ("PerformWriteReadTest: ReadFile failed: "
+ "Error %d\n", GetLastError());
+
+ result = FALSE;
+ goto Cleanup;
+
+ } else {
+
+ if( bytesReturned != TestLength ) {
+
+ printf("bytes Read is not test length! Read %d, "
+ "SB %d\n",bytesReturned, TestLength);
+
+ //
+ // Note: Is this a Failure Case??
+ //
+ result = FALSE;
+ goto Cleanup;
+ }
+
+ printf ("%d Pattern Bytes Read successfully\n",bytesReturned);
+ }
+
+ //
+ // Now compare
+ //
+ if( !VerifyPatternBuffer(ReadBuffer, TestLength) ) {
+
+ printf("Verify failed\n");
+
+ result = FALSE;
+ goto Cleanup;
+ }
+
+ printf("Pattern Verified successfully\n");
+
+Cleanup:
+
+ //
+ // Free WriteBuffer if non NULL.
+ //
+ if (WriteBuffer) {
+ free (WriteBuffer);
+ }
+
+ //
+ // Free ReadBuffer if non NULL
+ //
+ if (ReadBuffer) {
+ free (ReadBuffer);
+ }
+
+ return result;
+}
+
+
+
+ULONG
+AsyncIo(
+ PVOID ThreadParameter
+ )
+{
+ HANDLE hDevice = INVALID_HANDLE_VALUE;
+ HANDLE hCompletionPort = NULL;
+ OVERLAPPED *pOvList = NULL;
+ PUCHAR buf = NULL;
+ ULONG numberOfBytesTransferred;
+ OVERLAPPED *completedOv;
+ ULONG_PTR i;
+ ULONG ioType = (ULONG)(ULONG_PTR)ThreadParameter;
+ ULONG_PTR key;
+ ULONG error;
+ BOOLEAN result = TRUE;
+ ULONG maxPendingRequests = NUM_ASYNCH_IO;
+ ULONG remainingRequestsToSend = 0;
+ ULONG remainingRequestsToReceive = 0;
+
+ hDevice = CreateFile(G_DevicePath,
+ GENERIC_WRITE|GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_OVERLAPPED,
+ NULL );
+
+
+ if (hDevice == INVALID_HANDLE_VALUE) {
+ printf("Cannot open %s error %d\n", G_DevicePath, GetLastError());
+ result = FALSE;
+ goto Error;
+ }
+
+ hCompletionPort = CreateIoCompletionPort(hDevice, NULL, 1, 0);
+ if (hCompletionPort == NULL) {
+ printf("Cannot open completion port %d \n",GetLastError());
+ result = FALSE;
+ goto Error;
+ }
+
+ //
+ // We will only have NUM_ASYNCH_IO or G_AsyncIoLoopsNum pending at any
+ // time (whichever is less)
+ //
+ if (G_LimitedLoops == TRUE) {
+ remainingRequestsToReceive = G_AsyncIoLoopsNum;
+ if (G_AsyncIoLoopsNum > NUM_ASYNCH_IO) {
+ //
+ // After we send the initial NUM_ASYNCH_IO, we will have additional
+ // (G_AsyncIoLoopsNum - NUM_ASYNCH_IO) I/Os to send
+ //
+ maxPendingRequests = NUM_ASYNCH_IO;
+ remainingRequestsToSend = G_AsyncIoLoopsNum - NUM_ASYNCH_IO;
+ }
+ else {
+ maxPendingRequests = G_AsyncIoLoopsNum;
+ remainingRequestsToSend = 0;
+
+ }
+ }
+
+ pOvList = (OVERLAPPED *)malloc(maxPendingRequests * sizeof(OVERLAPPED));
+ if (pOvList == NULL) {
+ printf("Cannot allocate overlapped array \n");
+ result = FALSE;
+ goto Error;
+ }
+
+ buf = (PUCHAR)malloc(maxPendingRequests * BUFFER_SIZE);
+ if (buf == NULL) {
+ printf("Cannot allocate buffer \n");
+ result = FALSE;
+ goto Error;
+ }
+
+ ZeroMemory(pOvList, maxPendingRequests * sizeof(OVERLAPPED));
+ ZeroMemory(buf, maxPendingRequests * BUFFER_SIZE);
+
+ //
+ // Issue asynch I/O
+ //
+
+ for (i = 0; i < maxPendingRequests; i++) {
+ if (ioType == READER_TYPE) {
+ if ( ReadFile( hDevice,
+ buf + (i* BUFFER_SIZE),
+ BUFFER_SIZE,
+ NULL,
+ &pOvList[i]) == 0) {
+
+ error = GetLastError();
+ if (error != ERROR_IO_PENDING) {
+ printf(" %dth Read failed %d \n",i, GetLastError());
+ result = FALSE;
+ goto Error;
+ }
+ }
+
+ } else {
+ if ( WriteFile( hDevice,
+ buf + (i* BUFFER_SIZE),
+ BUFFER_SIZE,
+ NULL,
+ &pOvList[i]) == 0) {
+ error = GetLastError();
+ if (error != ERROR_IO_PENDING) {
+ printf(" %dth Write failed %d \n",i, GetLastError());
+ result = FALSE;
+ goto Error;
+ }
+ }
+ }
+ }
+
+ //
+ // Wait for the I/Os to complete. If one completes then reissue the I/O
+ //
+
+ WHILE (1) {
+
+ if ( GetQueuedCompletionStatus(hCompletionPort, &numberOfBytesTransferred, &key, &completedOv, INFINITE) == 0) {
+ printf("GetQueuedCompletionStatus failed %d\n", GetLastError());
+ result = FALSE;
+ goto Error;
+ }
+
+ //
+ // Read successfully completed. If we're doing unlimited I/Os then Issue another one.
+ //
+
+ if (ioType == READER_TYPE) {
+
+ i = completedOv - pOvList;
+ printf("Number of bytes read by request number %d is %d\n", i, numberOfBytesTransferred);
+
+ //
+ // If we're done with the I/Os, then exit
+ //
+ if (G_LimitedLoops == TRUE) {
+ if ((--remainingRequestsToReceive) == 0) {
+ break;
+ }
+
+ if (remainingRequestsToSend == 0) {
+ continue;
+ }
+ else {
+ remainingRequestsToSend--;
+ }
+ }
+
+
+ if ( ReadFile( hDevice,
+ buf + (i * BUFFER_SIZE),
+ BUFFER_SIZE,
+ NULL,
+ completedOv) == 0) {
+ error = GetLastError();
+ if (error != ERROR_IO_PENDING) {
+ printf("%dth Read failed %d \n", i, GetLastError());
+ result = FALSE;
+ goto Error;
+ }
+ }
+ } else {
+
+ i = completedOv - pOvList;
+
+ printf("Number of bytes written by request number %d is %d\n", i, numberOfBytesTransferred);
+
+ //
+ // If we're done with the I/Os, then exit
+ //
+ if (G_LimitedLoops == TRUE) {
+ if ((--remainingRequestsToReceive) == 0) {
+ break;
+ }
+
+ if (remainingRequestsToSend == 0) {
+ continue;
+ }
+ else {
+ remainingRequestsToSend--;
+ }
+ }
+
+
+ if ( WriteFile( hDevice,
+ buf + (i * BUFFER_SIZE),
+ BUFFER_SIZE,
+ NULL,
+ completedOv) == 0) {
+ error = GetLastError();
+ if (error != ERROR_IO_PENDING) {
+
+ printf("%dth write failed %d \n", i, GetLastError());
+ result = FALSE;
+ goto Error;
+ }
+ }
+ }
+ }
+
+Error:
+ if(hDevice != INVALID_HANDLE_VALUE) {
+ CloseHandle(hDevice);
+ }
+
+ if(hCompletionPort) {
+ CloseHandle(hCompletionPort);
+ }
+
+ if(buf) {
+ free(buf);
+ }
+ if(pOvList) {
+ free(pOvList);
+ }
+
+ return (ULONG)result;
+
+}
+
+
+BOOL
+GetDevicePath(
+ IN LPGUID InterfaceGuid,
+ _Out_writes_(BufLen) PCHAR DevicePath,
+ _In_ size_t BufLen
+ )
+{
+ HDEVINFO HardwareDeviceInfo;
+ SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
+ PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData = NULL;
+ ULONG Length, RequiredLength = 0;
+ BOOL bResult;
+ HRESULT hr;
+
+ HardwareDeviceInfo = SetupDiGetClassDevs(
+ InterfaceGuid,
+ NULL,
+ NULL,
+ (DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));
+
+ if (HardwareDeviceInfo == INVALID_HANDLE_VALUE) {
+ printf("SetupDiGetClassDevs failed!\n");
+ return FALSE;
+ }
+
+ DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
+
+ bResult = SetupDiEnumDeviceInterfaces(HardwareDeviceInfo,
+ 0,
+ InterfaceGuid,
+ 0,
+ &DeviceInterfaceData);
+
+ if (bResult == FALSE) {
+
+ LPVOID lpMsgBuf;
+
+ if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPSTR) &lpMsgBuf,
+ 0,
+ NULL
+ )) {
+
+ printf("SetupDiEnumDeviceInterfaces failed: %s", (LPTSTR)lpMsgBuf);
+ LocalFree(lpMsgBuf);
+ }
+
+ printf("SetupDiEnumDeviceInterfaces failed.\n");
+ SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
+ return FALSE;
+ }
+
+ SetupDiGetDeviceInterfaceDetail(
+ HardwareDeviceInfo,
+ &DeviceInterfaceData,
+ NULL,
+ 0,
+ &RequiredLength,
+ NULL
+ );
+
+ DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)LocalAlloc(LMEM_FIXED, RequiredLength);
+
+ if (DeviceInterfaceDetailData == NULL) {
+ SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
+ printf("Failed to allocate memory.\n");
+ return FALSE;
+ }
+
+ DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
+
+ Length = RequiredLength;
+
+ bResult = SetupDiGetDeviceInterfaceDetail(
+ HardwareDeviceInfo,
+ &DeviceInterfaceData,
+ DeviceInterfaceDetailData,
+ Length,
+ &RequiredLength,
+ NULL);
+
+ if (bResult == FALSE) {
+
+ LPVOID lpMsgBuf;
+
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPSTR) &lpMsgBuf,
+ 0,
+ NULL
+ );
+
+ SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
+ printf("Error in SetupDiGetDeviceInterfaceDetail: %s\n", (LPTSTR)lpMsgBuf);
+ LocalFree(DeviceInterfaceDetailData);
+ LocalFree(lpMsgBuf);
+ return FALSE;
+ }
+
+ hr = StringCchCopy(DevicePath,
+ BufLen,
+ DeviceInterfaceDetailData->DevicePath) ;
+
+ SetupDiDestroyDeviceInfoList(HardwareDeviceInfo); // It must be executed in both success and failure traces
+ LocalFree(DeviceInterfaceDetailData);
+
+ return ( !FAILED(hr) ); // Result depends on StringCchCopy()
+}
+