From 42b8d84dc8bbf41b7dcdecf8cdc1ad0ac285cba6 Mon Sep 17 00:00:00 2001 From: Olaf Matthes Date: Mon, 4 Dec 2006 20:23:28 +0000 Subject: *** empty log message *** svn path=/trunk/externals/olafmatt/; revision=6616 --- hidin/winNT_usb.c | 752 ------------------------------------------------------ 1 file changed, 752 deletions(-) delete mode 100644 hidin/winNT_usb.c (limited to 'hidin/winNT_usb.c') diff --git a/hidin/winNT_usb.c b/hidin/winNT_usb.c deleted file mode 100644 index 0e361b7..0000000 --- a/hidin/winNT_usb.c +++ /dev/null @@ -1,752 +0,0 @@ -/* - hidin USB HID support stuff for Windows 2000 / XP - - Written by Olaf Matthes - - This file contains the implementation for connecting to USB HID - (Human Interface Device) devices. It provides several functions - to open devices and to query information and capabilities. - -*/ - -#ifdef PD -#include "m_pd.h" /* we need this because we want to print() to the PD console */ -#include -#else -#include "ext.h" /* we need this because we want to print() to the Max window */ -#endif -#include "hidin.h" - - -/* - * get information for a given device (HANDLE) - * - */ - -void getDeviceInfo(HANDLE deviceHandle) -{ - HIDD_ATTRIBUTES deviceAttributes; - PWCHAR deviceName; - ULONG length = 256; - - if(deviceHandle == INVALID_HANDLE_VALUE) - { - post("hidin: -- couldn't get device info due to an invalid handle"); - return; - } - - if (!HidD_GetAttributes (deviceHandle, &deviceAttributes)) - { - post("hidin: -- failed to get attributes"); - return; - } - else - { - // post("hidin: ** VendorID: 0x%x", deviceAttributes.VendorID); - // post("hidin: ** ProductID: 0x%x", deviceAttributes.ProductID); - // post("hidin: ** VersionNumber: 0x%x", deviceAttributes.VersionNumber); - } - - deviceName = (PWCHAR)getbytes((short)(length)); - if(!HidD_GetProductString (deviceHandle, deviceName, length)) - { - freebytes(deviceName, (short)(length)); - return; - } - else - { - char name[256]; - int i = 0; - wcstombs(name, deviceName, length); - post("hidin: >> opening device: \"%s\"", name); - freebytes(deviceName, (short)(length)); - } - return; -} - -/* - * find name of attached HID devices - */ -t_symbol *findDeviceName(DWORD deviceID) -{ - HANDLE deviceHandle; - PWCHAR deviceName; - ULONG length = 256; - char name[256]; // this will be the return value - int i = 0; - - deviceHandle = connectDeviceNumber(deviceID); - - if(deviceHandle != INVALID_HANDLE_VALUE) - { - deviceName = (PWCHAR)getbytes((short)(length)); - if(!HidD_GetProductString (deviceHandle, deviceName, length)) - { - freebytes(deviceName, (short)(length)); - sprintf(name, "Unknown (Device #%d)", deviceID + 1); - return gensym(name); - } - else - { - wcstombs(name, deviceName, length); - freebytes(deviceName, (short)(length)); - } - - CloseHandle(deviceHandle); - - return gensym(name); - } - return gensym("Unsupported Device"); -} - -/* - * find number of attached HID devices - */ -int findHidDevices() -{ - HDEVINFO hardwareDeviceInfo; - SP_INTERFACE_DEVICE_DATA deviceInfoData; - ULONG i; - BOOLEAN done; - GUID hidGuid; - PSP_INTERFACE_DEVICE_DETAIL_DATA functionClassDeviceData = NULL; - ULONG predictedLength = 0; - ULONG requiredLength = 0; - ULONG NumberDevices = 0; - - HidD_GetHidGuid (&hidGuid); - - // - // Open a handle to the plug and play dev node. - // - hardwareDeviceInfo = SetupDiGetClassDevs ( &hidGuid, - NULL, // Define no enumerator (global) - NULL, // Define no - (DIGCF_PRESENT | // Only Devices present - DIGCF_DEVICEINTERFACE)); // Function class devices. - - // - // Take a wild guess to start - // - - NumberDevices = 4; - done = FALSE; - deviceInfoData.cbSize = sizeof (SP_INTERFACE_DEVICE_DATA); - - i=0; - while (!done) - { - NumberDevices *= 2; - - for (; i < NumberDevices; i++) - { - if (SetupDiEnumDeviceInterfaces (hardwareDeviceInfo, - 0, // No care about specific PDOs - &hidGuid, - i, - &deviceInfoData)) - { - // - // allocate a function class device data structure to receive the - // goods about this particular device. - // - - SetupDiGetDeviceInterfaceDetail ( - hardwareDeviceInfo, - &deviceInfoData, - NULL, // probing so no output buffer yet - 0, // probing so output buffer length of zero - &requiredLength, - NULL); // not interested in the specific dev-node - - - predictedLength = requiredLength; - - functionClassDeviceData = malloc (predictedLength); - if (functionClassDeviceData) - { - functionClassDeviceData->cbSize = sizeof (SP_INTERFACE_DEVICE_DETAIL_DATA); - } - else - { - SetupDiDestroyDeviceInfoList (hardwareDeviceInfo); - return 0; - } - - // - // Retrieve the information from Plug and Play. - // - - if (! SetupDiGetDeviceInterfaceDetail ( - hardwareDeviceInfo, - &deviceInfoData, - functionClassDeviceData, - predictedLength, - &requiredLength, - NULL)) - { - SetupDiDestroyDeviceInfoList (hardwareDeviceInfo); - return 0; - } - // - // get name of device - // - // HidDevices[i] = getbytes(1024 * sizeof(char)); - } - else - { - if (ERROR_NO_MORE_ITEMS == GetLastError()) - { - done = TRUE; - break; - } - } - } - } - - SetupDiDestroyDeviceInfoList (hardwareDeviceInfo); - - return (i); // return number of devices -} - - -/* - * connect to Ith USB device (count starting with 0) - */ - -HANDLE connectDeviceNumber(DWORD deviceIndex) -{ - GUID hidGUID; - HDEVINFO hardwareDeviceInfoSet; - SP_DEVICE_INTERFACE_DATA deviceInterfaceData; - PSP_INTERFACE_DEVICE_DETAIL_DATA deviceDetail; - ULONG requiredSize; - HANDLE deviceHandle = INVALID_HANDLE_VALUE; - DWORD result; - - //Get the HID GUID value - used as mask to get list of devices - HidD_GetHidGuid (&hidGUID); - - //Get a list of devices matching the criteria (hid interface, present) - hardwareDeviceInfoSet = SetupDiGetClassDevs (&hidGUID, - NULL, // Define no enumerator (global) - NULL, // Define no - (DIGCF_PRESENT | // Only Devices present - DIGCF_DEVICEINTERFACE)); // Function class devices. - - deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); - - //Go through the list and get the interface data - result = SetupDiEnumDeviceInterfaces (hardwareDeviceInfoSet, - NULL, //infoData, - &hidGUID, //interfaceClassGuid, - deviceIndex, - &deviceInterfaceData); - - /* Failed to get a device - possibly the index is larger than the number of devices */ - if (result == FALSE) - { - SetupDiDestroyDeviceInfoList (hardwareDeviceInfoSet); - post("hidin: -- failed to get specified device number"); - return INVALID_HANDLE_VALUE; - } - - //Get the details with null values to get the required size of the buffer - SetupDiGetDeviceInterfaceDetail (hardwareDeviceInfoSet, - &deviceInterfaceData, - NULL, //interfaceDetail, - 0, //interfaceDetailSize, - &requiredSize, - 0); //infoData)) - - //Allocate the buffer - deviceDetail = (PSP_INTERFACE_DEVICE_DETAIL_DATA)malloc(requiredSize); - deviceDetail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA); - - //Fill the buffer with the device details - if (!SetupDiGetDeviceInterfaceDetail (hardwareDeviceInfoSet, - &deviceInterfaceData, - deviceDetail, - requiredSize, - &requiredSize, - NULL)) - { - SetupDiDestroyDeviceInfoList (hardwareDeviceInfoSet); - free (deviceDetail); - post("hidin: -- failed to get device info"); - return INVALID_HANDLE_VALUE; - } - -#if 1 - //Open file on the device (read only) - deviceHandle = CreateFile - (deviceDetail->DevicePath, - GENERIC_READ, - FILE_SHARE_READ|FILE_SHARE_WRITE, - (LPSECURITY_ATTRIBUTES)NULL, - OPEN_EXISTING, - FILE_FLAG_OVERLAPPED, - NULL); -#else - //Open file on the device (read & write) - deviceHandle = CreateFile - (deviceDetail->DevicePath, - GENERIC_READ|GENERIC_WRITE, - FILE_SHARE_READ|FILE_SHARE_WRITE, - (LPSECURITY_ATTRIBUTES)NULL, - OPEN_EXISTING, - FILE_FLAG_OVERLAPPED, // was 0 - NULL); -#endif - - if(deviceHandle == INVALID_HANDLE_VALUE) - { - int err = GetLastError(); - LPVOID lpMsgBuf; - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL); - post("hidin: -- could not get device #%i: %s", deviceIndex + 1, (LPCTSTR)lpMsgBuf); - if(err == ERROR_ACCESS_DENIED) - post("hidin: -- can not read from mouse and keyboard"); - LocalFree(lpMsgBuf); - } - - SetupDiDestroyDeviceInfoList (hardwareDeviceInfoSet); - free (deviceDetail); - return deviceHandle; -} - -/* - * connect to USB device specified through VendorID, ProductID and VersionNumber - * - */ - -HANDLE connectDeviceName(DWORD *vendorID, DWORD *productID, DWORD *versionNumber) -{ - HANDLE deviceHandle = INVALID_HANDLE_VALUE; - DWORD index = 0; - HIDD_ATTRIBUTES deviceAttributes; - BOOL matched = FALSE; - - while (!matched && (deviceHandle = connectDeviceNumber(index)) != INVALID_HANDLE_VALUE) - { - if (!HidD_GetAttributes (deviceHandle, &deviceAttributes)) - return INVALID_HANDLE_VALUE; - - if ((vendorID == 0 || deviceAttributes.VendorID == *vendorID) && - (productID == 0 || deviceAttributes.ProductID == *productID) && - (versionNumber == 0 || deviceAttributes.VersionNumber == *versionNumber)) - return deviceHandle; /* matched */ - - CloseHandle (deviceHandle); /* not a match - close and try again */ - - index++; - } - - return INVALID_HANDLE_VALUE; -} - - -/* - * get device capabilities - * - */ -void getDeviceCapabilities(t_hid_device *hid) -{ - // Get the Capabilities structure for the device. - PHIDP_PREPARSED_DATA preparsedData; - HIDP_CAPS capabilities; - - if(hid->device == INVALID_HANDLE_VALUE) - { - post("hidin: -- couldn't get device capabilities due to an invalid handle"); - return; - } - - /* - API function: HidD_GetPreparsedData - Returns: a pointer to a buffer containing the information about the device's capabilities. - Requires: A handle returned by CreateFile. - There's no need to access the buffer directly, - but HidP_GetCaps and other API functions require a pointer to the buffer. - */ - - HidD_GetPreparsedData(hid->device, &preparsedData); - - /* get the device attributes */ - // HidD_GetAttributes (hid->device, &hid->attributes); - - /* - API function: HidP_GetCaps - Learn the device's capabilities. - For standard devices such as joysticks, you can find out the specific - capabilities of the device. - For a custom device, the software will probably know what the device is capable of, - and the call only verifies the information. - Requires: the pointer to the buffer returned by HidD_GetPreparsedData. - Returns: a Capabilities structure containing the information. - */ - - HidP_GetCaps(preparsedData, &capabilities); - - // Display the capabilities - - hid->caps = capabilities; - hid->ppd = preparsedData; - // No need for PreparsedData any more, so free the memory it's using. - // HidD_FreePreparsedData(preparsedData); -} - -/* - * Given a struct _hid_device, obtain a read report and unpack the values - * into the InputData array. - */ -int readHid(t_hid_device *hidDevice) -{ - long value = 0, ret; - long bytesRead; - - if(!ReadFile(hidDevice->device, - hidDevice->inputReportBuffer, - hidDevice->caps.InputReportByteLength, - &bytesRead, - NULL)) - { - int err = GetLastError(); - LPVOID lpMsgBuf; - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL); - post("hidin: -- could not read from device: %s", (LPCTSTR)lpMsgBuf); - LocalFree(lpMsgBuf); - return 0; - } - // we need: bytesRead == hidDevice->caps.InputReportByteLength - - return bytesRead; -} - -/* - * Given a struct _hid_device, obtain a read report and unpack the values - * into the InputData array. - */ -int readHidOverlapped(t_hid_device *hidDevice) -{ - long value = 0, ret; - long bytesRead; - - if(!ReadFile(hidDevice->device, - hidDevice->inputReportBuffer, - hidDevice->caps.InputReportByteLength, - &bytesRead, - (LPOVERLAPPED) &hidDevice->overlapped)) - { - return 0; - } - return bytesRead; -} - - - -BOOLEAN getFeature (t_hid_device *HidDevice) -/*++ -RoutineDescription: - Given a struct _HID_DEVICE, fill in the feature data structures with - all features on the device. May issue multiple HidD_GetFeature() calls to - deal with multiple report IDs. ---*/ -{ - ULONG Index; - t_hid_data *pData; - BOOLEAN FeatureStatus; - BOOLEAN Status; - - /* - // As with writing data, the IsDataSet value in all the structures should be - // set to FALSE to indicate that the value has yet to have been set - */ - - pData = HidDevice->featureData; - - for (Index = 0; Index < HidDevice->featureDataLength; Index++, pData++) - { - pData->IsDataSet = FALSE; - } - - /* - // Next, each structure in the HID_DATA buffer is filled in with a value - // that is retrieved from one or more calls to HidD_GetFeature. The - // number of calls is equal to the number of reportIDs on the device - */ - - Status = TRUE; - pData = HidDevice->featureData; - - for (Index = 0; Index < HidDevice->featureDataLength; Index++, pData++) - { - /* - // If a value has yet to have been set for this structure, build a report - // buffer with its report ID as the first byte of the buffer and pass - // it in the HidD_GetFeature call. Specifying the report ID in the - // first specifies which report is actually retrieved from the device. - // The rest of the buffer should be zeroed before the call - */ - - if (!pData->IsDataSet) - { - memset(HidDevice->featureReportBuffer, 0x00, HidDevice->caps.FeatureReportByteLength); - - HidDevice->featureReportBuffer[0] = (UCHAR) pData -> ReportID; - - FeatureStatus = HidD_GetFeature (HidDevice->device, - HidDevice->featureReportBuffer, - HidDevice->caps.FeatureReportByteLength); - - /* - // If the return value is TRUE, scan through the rest of the HID_DATA - // structures and fill whatever values we can from this report - */ - - - if (FeatureStatus) - { - FeatureStatus = unpackReport ( HidDevice->featureReportBuffer, - HidDevice->caps.FeatureReportByteLength, - HidP_Feature, - HidDevice->featureData, - HidDevice->featureDataLength, - HidDevice->ppd); - } - - Status = Status && FeatureStatus; - } - } - - return (Status); -} - - -BOOLEAN -unpackReport ( - PCHAR ReportBuffer, - USHORT ReportBufferLength, - HIDP_REPORT_TYPE ReportType, - t_hid_data *Data, - ULONG DataLength, - PHIDP_PREPARSED_DATA Ppd -) -/*++ -Routine Description: - Given ReportBuffer representing a report from a HID device where the first - byte of the buffer is the report ID for the report, extract all the HID_DATA - in the Data list from the given report. ---*/ -{ - ULONG numUsages; // Number of usages returned from GetUsages. - ULONG i; - UCHAR reportID; - ULONG Index; - ULONG nextUsage; - - reportID = ReportBuffer[0]; - - for (i = 0; i < DataLength; i++, Data++) - { - if (reportID == Data->ReportID) - { - if (Data->IsButtonData) - { - numUsages = Data->ButtonData.MaxUsageLength; - - Data->Status = HidP_GetUsages (ReportType, - Data->UsagePage, - 0, // All collections - Data->ButtonData.Usages, - &numUsages, - Ppd, - ReportBuffer, - ReportBufferLength); - - - // - // Get usages writes the list of usages into the buffer - // Data->ButtonData.Usages newUsage is set to the number of usages - // written into this array. - // A usage cannot not be defined as zero, so we'll mark a zero - // following the list of usages to indicate the end of the list of - // usages - // - // NOTE: One anomaly of the GetUsages function is the lack of ability - // to distinguish the data for one ButtonCaps from another - // if two different caps structures have the same UsagePage - // For instance: - // Caps1 has UsagePage 07 and UsageRange of 0x00 - 0x167 - // Caps2 has UsagePage 07 and UsageRange of 0xe0 - 0xe7 - // - // However, calling GetUsages for each of the data structs - // will return the same list of usages. It is the - // responsibility of the caller to set in the HID_DEVICE - // structure which usages actually are valid for the - // that structure. - // - - /* - // Search through the usage list and remove those that - // correspond to usages outside the define ranged for this - // data structure. - */ - - for (Index = 0, nextUsage = 0; Index < numUsages; Index++) - { - if (Data->ButtonData.UsageMin <= Data->ButtonData.Usages[Index] && - Data -> ButtonData.Usages[Index] <= Data->ButtonData.UsageMax) - { - Data->ButtonData.Usages[nextUsage++] = Data->ButtonData.Usages[Index]; - - } - } - - if (nextUsage < Data -> ButtonData.MaxUsageLength) - { - Data->ButtonData.Usages[nextUsage] = 0; - } - } - else - { - Data->Status = HidP_GetUsageValue ( - ReportType, - Data->UsagePage, - 0, // All Collections. - Data->ValueData.Usage, - &Data->ValueData.Value, - Ppd, - ReportBuffer, - ReportBufferLength); - - Data->Status = HidP_GetScaledUsageValue ( - ReportType, - Data->UsagePage, - 0, // All Collections. - Data->ValueData.Usage, - &Data->ValueData.ScaledValue, - Ppd, - ReportBuffer, - ReportBufferLength); - } - Data->IsDataSet = TRUE; - } - } - return (TRUE); -} - - -BOOLEAN -packReport ( - PCHAR ReportBuffer, - USHORT ReportBufferLength, - HIDP_REPORT_TYPE ReportType, - t_hid_data *Data, - ULONG DataLength, - PHIDP_PREPARSED_DATA Ppd - ) -/*++ -Routine Description: - This routine takes in a list of HID_DATA structures (DATA) and builds - in ReportBuffer the given report for all data values in the list that - correspond to the report ID of the first item in the list. - - For every data structure in the list that has the same report ID as the first - item in the list will be set in the report. Every data item that is - set will also have it's IsDataSet field marked with TRUE. - - A return value of FALSE indicates an unexpected error occurred when setting - a given data value. The caller should expect that assume that no values - within the given data structure were set. - - A return value of TRUE indicates that all data values for the given report - ID were set without error. ---*/ -{ - ULONG numUsages; // Number of usages to set for a given report. - ULONG i; - ULONG CurrReportID; - - /* - // All report buffers that are initially sent need to be zero'd out - */ - - memset (ReportBuffer, (UCHAR) 0, ReportBufferLength); - - /* - // Go through the data structures and set all the values that correspond to - // the CurrReportID which is obtained from the first data structure - // in the list - */ - - CurrReportID = Data -> ReportID; - - for (i = 0; i < DataLength; i++, Data++) - { - /* - // There are two different ways to determine if we set the current data - // structure: - // 1) Store the report ID were using and only attempt to set those - // data structures that correspond to the given report ID. This - // example shows this implementation. - // - // 2) Attempt to set all of the data structures and look for the - // returned status value of HIDP_STATUS_INVALID_REPORT_ID. This - // error code indicates that the given usage exists but has a - // different report ID than the report ID in the current report - // buffer - */ - - if (Data -> ReportID == CurrReportID) - { - if (Data->IsButtonData) - { - numUsages = Data->ButtonData.MaxUsageLength; - Data->Status = HidP_SetUsages (ReportType, - Data->UsagePage, - 0, // All collections - Data->ButtonData.Usages, - &numUsages, - Ppd, - ReportBuffer, - ReportBufferLength); - } - else - { - Data->Status = HidP_SetUsageValue (ReportType, - Data->UsagePage, - 0, // All Collections. - Data->ValueData.Usage, - Data->ValueData.Value, - Ppd, - ReportBuffer, - ReportBufferLength); - } - - if (HIDP_STATUS_SUCCESS != Data->Status) - { - return FALSE; - } - } - } - - /* - // At this point, all data structures that have the same ReportID as the - // first one will have been set in the given report. Time to loop - // through the structure again and mark all of those data structures as - // having been set. - */ - - for (i = 0; i < DataLength; i++, Data++) - { - if (CurrReportID == Data -> ReportID) - { - Data -> IsDataSet = TRUE; - } - } - return (TRUE); -} - -- cgit v1.2.1