5 /* Inspired by hiddata.c|h by Christian Starkjohann
6 * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
19 #define DEBUG_PRINT(arg) printf arg
21 #define DEBUG_PRINT(arg)
24 #include "targetver.h"
31 #pragma comment(lib, "setupapi")
32 #pragma comment(lib, "hid")
33 #define snprintf _snprintf
34 #else /* GCC, Mingw... */
38 * Convert UTF-16 null term. string to single byte (ASCII or ISO Latin)
39 * change all weird characters to "?"
41 static void usbstring_to_ascii(unsigned short *wp
, char *cp
, int size
)
43 unsigned short *wpend
= wp
+ (size
/sizeof(unsigned short));
46 unsigned short h
= *wp
++;
47 *cp
++ = (h
< 0xFF) ? (char)h
: '?';
54 * Read HID string for vendor and device, return as ASCII (or ISO Latin...)
56 int usbhidGetVendorString(USBDEVHANDLE usbh
, char *buffer
, int len
)
58 /* HidD_GetManufacturerString returns zero terminated UTF-16 string */
59 /* Error if buffer is too short */
60 if ( !HidD_GetManufacturerString((HANDLE
)usbh
, (void*)buffer
, len
) ) {
61 DEBUG_PRINT(("error obtaining vendor name\n"));
62 return USBHID_ERR_IO_HID
;
64 usbstring_to_ascii((UINT16
*)buffer
, buffer
, len
);
68 int usbhidGetProductString(USBDEVHANDLE usbh
, char *buffer
, int len
)
70 /* HidD_GetProductString returns zero terminated UTF-16 string */
71 /* Error if buffer is too short */
72 if (!HidD_GetProductString((HANDLE
)usbh
, (void*)buffer
, len
) ) {
73 DEBUG_PRINT(("error obtaining product name\n"));
74 return USBHID_ERR_IO_HID
;
76 usbstring_to_ascii((UINT16
*)buffer
, buffer
, len
);
81 * Enumerate HID USB devices.
82 * In Windows this will find also non-USB devices, but assume that
83 * filtering by PID & VID is enough.
84 * Some HID devices (mice, kbd) are locked by Windows and cannot be opened.
85 * If we cannot open a device for R&W, we skip it without error.
86 * Assume our devices are not of types reserved by Windows.
88 int usbhidEnumDevices(int vendor
, int product
,
90 int (*usbhidEnumFunc
)(USBDEVHANDLE usbh
, void *ctx
))
92 GUID hidGuid
; /* GUID for HID class */
93 HDEVINFO deviceInfoList
;
94 SP_DEVICE_INTERFACE_DATA deviceInfo
;
95 SP_DEVICE_INTERFACE_DETAIL_DATA_W
*deviceDetails
= NULL
;
97 int i
, openFlag
= 0; /* may be FILE_FLAG_OVERLAPPED */
98 int errorCode
= USBHID_ERR_NOTFOUND
;
99 HANDLE handle
= INVALID_HANDLE_VALUE
;
100 HIDD_ATTRIBUTES deviceAttributes
;
102 HidD_GetHidGuid(&hidGuid
);
103 deviceInfoList
= SetupDiGetClassDevsW(&hidGuid
, NULL
, NULL
, DIGCF_PRESENT
| DIGCF_INTERFACEDEVICE
);
104 if (!deviceInfoList
|| deviceInfoList
== INVALID_HANDLE_VALUE
)
106 return USBHID_ERR_NOTFOUND
;
109 deviceInfo
.cbSize
= sizeof(deviceInfo
);
111 if(handle
!= INVALID_HANDLE_VALUE
){
113 handle
= INVALID_HANDLE_VALUE
;
115 if( !SetupDiEnumDeviceInterfaces(deviceInfoList
, 0, &hidGuid
, i
, &deviceInfo
) )
116 break; /* no more entries */
117 /* first do a dummy call just to determine the actual size required */
118 SetupDiGetDeviceInterfaceDetailW(deviceInfoList
, &deviceInfo
, NULL
, 0, &size
, NULL
);
119 if(deviceDetails
!= NULL
)
121 deviceDetails
= malloc(size
);
122 deviceDetails
->cbSize
= sizeof(*deviceDetails
);
123 /* this call is for real: */
124 SetupDiGetDeviceInterfaceDetailW(deviceInfoList
, &deviceInfo
, deviceDetails
, size
, &size
, NULL
);
125 DEBUG_PRINT(("checking HID path \"%s\"\n", deviceDetails
->DevicePath
));
127 handle
= CreateFileW(deviceDetails
->DevicePath
,
128 GENERIC_READ
|GENERIC_WRITE
, FILE_SHARE_READ
|FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, openFlag
, NULL
);
129 if(handle
== INVALID_HANDLE_VALUE
){
130 DEBUG_PRINT(("open USB device failed: gle=%d\n", (int)GetLastError()));
131 /* errorCode = USBOPEN_ERR_ACCESS; opening will always fail for mouse -- ignore */
134 deviceAttributes
.Size
= sizeof(deviceAttributes
);
135 HidD_GetAttributes(handle
, &deviceAttributes
);
136 DEBUG_PRINT(("device attributes: vid=%d pid=%d ver=%4.4X\n", deviceAttributes
.VendorID
, deviceAttributes
.ProductID
, deviceAttributes
.VersionNumber
));
137 if(deviceAttributes
.VendorID
!= vendor
|| deviceAttributes
.ProductID
!= product
)
138 continue; /* skip this device */
141 if ( 0 == usbhidEnumFunc((USBDEVHANDLE
)handle
, context
) )
143 break; /* stop enumeration */
146 /* Now the handle is owned by the callback */
147 handle
= INVALID_HANDLE_VALUE
;
150 SetupDiDestroyDeviceInfoList(deviceInfoList
);
151 if(deviceDetails
!= NULL
)
158 void usbhidCloseDevice(USBDEVHANDLE usbh
)
160 CloseHandle((HANDLE
)usbh
);
164 int usbhidSetReport(USBDEVHANDLE usbh
, char *buffer
, int len
)
167 rval
= HidD_SetFeature((HANDLE
)usbh
, buffer
, len
);
168 return rval
== 0 ? USBHID_ERR_IO_HID
: 0;
172 int usbhidGetReport(USBDEVHANDLE usbh
, int reportNumber
, char *buffer
, int *len
)
175 buffer
[0] = reportNumber
;
176 rval
= HidD_GetFeature((HANDLE
)usbh
, buffer
, *len
);
177 return rval
== 0 ? USBHID_ERR_IO_HID
: 0;
181 int usbhidStrerror_r( int err
, char *buf
, int len
)
185 case USBHID_ERR_ACCESS
: s
= "Access to device denied";
186 case USBHID_ERR_NOTFOUND
: s
= "The specified device was not found";
187 case USBHID_ERR_IO
: s
= "Communication error with device";
188 case USBHID_ERR_IO_HID
: s
= "HID I/O error with device";
193 return snprintf(buf
, len
, "%s", s
);