181 lines
6.4 KiB
C
181 lines
6.4 KiB
C
/* Name: usb-windows.c
|
|
* Project: usbcalls library
|
|
* Author: Christian Starkjohann
|
|
* Creation Date: 2006-02-02
|
|
* Tabsize: 4
|
|
* Copyright: (c) 2006 by OBJECTIVE DEVELOPMENT Software GmbH
|
|
* License: Proprietary, free under certain conditions. See Documentation.
|
|
* This Revision: $Id: usb-windows.c 281 2007-03-20 13:22:10Z cs $
|
|
*/
|
|
|
|
/*
|
|
General Description:
|
|
This module implements USB HID report receiving and sending with native
|
|
Windows API functions. If you compile with MinGW, no software from Microsoft
|
|
(no DDK) is needed. We supply the missing types and function prototypes in
|
|
hidsdi.h.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <windows.h>
|
|
#include <setupapi.h>
|
|
#include "hidsdi.h"
|
|
#include <ddk/hidpi.h>
|
|
|
|
#include "usbcalls.h"
|
|
|
|
#ifdef DEBUG
|
|
#define DEBUG_PRINT(arg) printf arg
|
|
#else
|
|
#define DEBUG_PRINT(arg)
|
|
#endif
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
static void convertUniToAscii(char *buffer)
|
|
{
|
|
unsigned short *uni = (void *)buffer;
|
|
char *ascii = buffer;
|
|
|
|
while(*uni != 0){
|
|
if(*uni >= 256){
|
|
*ascii++ = '?';
|
|
}else{
|
|
*ascii++ = *uni++;
|
|
}
|
|
}
|
|
*ascii++ = 0;
|
|
}
|
|
|
|
int usbOpenDevice(usbDevice_t **device, int vendor, char *vendorName, int product, char *productName, int usesReportIDs)
|
|
{
|
|
GUID hidGuid; /* GUID for HID driver */
|
|
HDEVINFO deviceInfoList;
|
|
SP_DEVICE_INTERFACE_DATA deviceInfo;
|
|
SP_DEVICE_INTERFACE_DETAIL_DATA *deviceDetails = NULL;
|
|
DWORD size;
|
|
int i, openFlag = 0; /* may be FILE_FLAG_OVERLAPPED */
|
|
int errorCode = USB_ERROR_NOTFOUND;
|
|
HANDLE handle = INVALID_HANDLE_VALUE;
|
|
HIDD_ATTRIBUTES deviceAttributes;
|
|
|
|
HidD_GetHidGuid(&hidGuid);
|
|
deviceInfoList = SetupDiGetClassDevs(&hidGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
|
|
deviceInfo.cbSize = sizeof(deviceInfo);
|
|
for(i=0;;i++){
|
|
if(handle != INVALID_HANDLE_VALUE){
|
|
CloseHandle(handle);
|
|
handle = INVALID_HANDLE_VALUE;
|
|
}
|
|
if(!SetupDiEnumDeviceInterfaces(deviceInfoList, 0, &hidGuid, i, &deviceInfo))
|
|
break; /* no more entries */
|
|
/* first do a dummy call just to determine the actual size required */
|
|
SetupDiGetDeviceInterfaceDetail(deviceInfoList, &deviceInfo, NULL, 0, &size, NULL);
|
|
if(deviceDetails != NULL)
|
|
free(deviceDetails);
|
|
deviceDetails = malloc(size);
|
|
deviceDetails->cbSize = sizeof(*deviceDetails);
|
|
/* this call is for real: */
|
|
SetupDiGetDeviceInterfaceDetail(deviceInfoList, &deviceInfo, deviceDetails, size, &size, NULL);
|
|
DEBUG_PRINT(("checking HID path \"%s\"\n", deviceDetails->DevicePath));
|
|
/* attempt opening for R/W -- we don't care about devices which can't be accessed */
|
|
handle = CreateFile(deviceDetails->DevicePath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, openFlag, NULL);
|
|
if(handle == INVALID_HANDLE_VALUE){
|
|
DEBUG_PRINT(("opening failed: %d\n", (int)GetLastError()));
|
|
/* errorCode = USB_ERROR_ACCESS; opening will always fail for mouse -- ignore */
|
|
continue;
|
|
}
|
|
deviceAttributes.Size = sizeof(deviceAttributes);
|
|
HidD_GetAttributes(handle, &deviceAttributes);
|
|
DEBUG_PRINT(("device attributes: vid=%d pid=%d\n", deviceAttributes.VendorID, deviceAttributes.ProductID));
|
|
if(deviceAttributes.VendorID != vendor || deviceAttributes.ProductID != product)
|
|
continue; /* ignore this device */
|
|
errorCode = USB_ERROR_NOTFOUND;
|
|
if(vendorName != NULL && productName != NULL){
|
|
char buffer[512];
|
|
if(!HidD_GetManufacturerString(handle, buffer, sizeof(buffer))){
|
|
DEBUG_PRINT(("error obtaining vendor name\n"));
|
|
errorCode = USB_ERROR_IO;
|
|
continue;
|
|
}
|
|
convertUniToAscii(buffer);
|
|
DEBUG_PRINT(("vendorName = \"%s\"\n", buffer));
|
|
if(strcmp(vendorName, buffer) != 0)
|
|
continue;
|
|
if(!HidD_GetProductString(handle, buffer, sizeof(buffer))){
|
|
DEBUG_PRINT(("error obtaining product name\n"));
|
|
errorCode = USB_ERROR_IO;
|
|
continue;
|
|
}
|
|
convertUniToAscii(buffer);
|
|
DEBUG_PRINT(("productName = \"%s\"\n", buffer));
|
|
if(strcmp(productName, buffer) != 0)
|
|
continue;
|
|
}
|
|
break; /* we have found the device we are looking for! */
|
|
}
|
|
SetupDiDestroyDeviceInfoList(deviceInfoList);
|
|
if(deviceDetails != NULL)
|
|
free(deviceDetails);
|
|
if(handle != INVALID_HANDLE_VALUE){
|
|
*device = (usbDevice_t *)handle;
|
|
errorCode = 0;
|
|
}
|
|
return errorCode;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
void usbCloseDevice(usbDevice_t *device)
|
|
{
|
|
CloseHandle((HANDLE)device);
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
int usbSetReport(usbDevice_t *device, int reportType, char *buffer, int len)
|
|
{
|
|
HANDLE handle = (HANDLE)device;
|
|
BOOLEAN rval = 0;
|
|
DWORD bytesWritten;
|
|
|
|
switch(reportType){
|
|
case USB_HID_REPORT_TYPE_INPUT:
|
|
break;
|
|
case USB_HID_REPORT_TYPE_OUTPUT:
|
|
rval = WriteFile(handle, buffer, len, &bytesWritten, NULL);
|
|
break;
|
|
case USB_HID_REPORT_TYPE_FEATURE:
|
|
rval = HidD_SetFeature(handle, buffer, len);
|
|
break;
|
|
}
|
|
return rval == 0 ? USB_ERROR_IO : 0;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
int usbGetReport(usbDevice_t *device, int reportType, int reportNumber, char *buffer, int *len)
|
|
{
|
|
HANDLE handle = (HANDLE)device;
|
|
BOOLEAN rval = 0;
|
|
DWORD bytesRead;
|
|
|
|
switch(reportType){
|
|
case USB_HID_REPORT_TYPE_INPUT:
|
|
buffer[0] = reportNumber;
|
|
rval = ReadFile(handle, buffer, *len, &bytesRead, NULL);
|
|
if(rval)
|
|
*len = bytesRead;
|
|
break;
|
|
case USB_HID_REPORT_TYPE_OUTPUT:
|
|
break;
|
|
case USB_HID_REPORT_TYPE_FEATURE:
|
|
buffer[0] = reportNumber;
|
|
rval = HidD_GetFeature(handle, buffer, *len);
|
|
break;
|
|
}
|
|
return rval == 0 ? USB_ERROR_IO : 0;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------ */
|