2 * Variant for libusb v 0.1 (old simple version, found in many PC Linux distros)
5 /* Inspired by hiddata.c|h by Christian Starkjohann
6 * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
17 #define DEBUG_PRINT(arg) printf arg
19 #define DEBUG_PRINT(arg)
23 // USBDEVHANDLE is same as struct usb_device *
24 // Open handles are stored in struct usb_device (HACK! revise for new libusb)
26 static inline struct usb_device
* usbDevStruct(USBDEVHANDLE usbh
) {
27 return (struct usb_device
*)usbh
;
30 static inline usb_dev_handle
* usbDevHandle(USBDEVHANDLE usbh
) {
31 return (usb_dev_handle
*)(usbDevStruct(usbh
)->children
);
34 // TO DO: for devices that prepend report ID, implement this somehow
35 static inline int usesReportIDs(USBDEVHANDLE usbh
) {
36 /* return 1 if 1st byte of get/set report buffer is report ID */
40 /* ------------------------------------------------------------------------- */
42 #define USBRQ_HID_GET_REPORT 0x01
43 #define USBRQ_HID_SET_REPORT 0x09
44 #define USB_HID_REPORT_TYPE_FEATURE 3
46 #define A_REPORT_REQUEST_TIMEOUT 5000 /* in milliseconds */
48 /* ------------------------------------------------------------------------- */
50 int usbhidEnumDevices(int vendor
, int product
,
52 int (*usbhidEnumFunc
)(USBDEVHANDLE usbh
, void *ctx
))
56 struct usb_device
*dev
;
57 usb_dev_handle
*handle
= NULL
;
58 int errorCode
= USBOPEN_ERR_NOTFOUND
;
59 static int didUsbInit
= 0;
67 for (bus
=usb_get_busses(); bus
; bus
=bus
->next
) {
68 for (dev
=bus
->devices
; dev
; dev
=dev
->next
) {
69 if (dev
->descriptor
.idVendor
== vendor
&& dev
->descriptor
.idProduct
== product
) {
70 handle
= usb_open(dev
); /* we need to open the device in order to query strings */
72 errorCode
= USBOPEN_ERR_ACCESS
;
73 fprintf(stderr
, "Warning: cannot open USB device: %s\n", usb_strerror());
79 // printf("Probing: [%s] nc=%u %p\n", dev->filename, dev->num_children, dev->children);
80 // Assume our devices are leaf, so we can use dev->children to store the handle
81 if ( dev
->children
) {
82 fprintf(stderr
, "ERROR: assertion failed for usb dev %p\n", dev
);
88 dev
->children
= (void*)handle
;
89 if ( 0 == usbhidEnumFunc((void*)dev
, context
) )
91 break; /* stop enumeration */
94 /* Now the handle is owned by the callback */
103 /* ------------------------------------------------------------------------- */
105 void usbhidCloseDevice(USBDEVHANDLE usbh
)
108 usb_close(usbDevHandle(usbh
));
109 usbDevStruct(usbh
)->children
= NULL
;
113 /* ------------------------------------------------------------------------- */
115 static int usbhidGetStringAscii(struct usb_dev_handle
*dev
, int index
, char *buf
, int buflen
)
118 if((rval
= usb_get_string_simple(dev
, index
, buf
, buflen
)) >= 0) /* use libusb version if it works */
121 fprintf(stderr
, "usbhid: Access denied to USB device. Run as root or adjust device permissions.\n");
123 fprintf(stderr
, "usbhid: %s error %s\n", __FUNCTION__
, usb_strerror());
127 int usbhidGetVendorString(USBDEVHANDLE usbh
, char *buffer
, int len
)
129 int len2
= usbhidGetStringAscii(usbDevHandle(usbh
), usbDevStruct(usbh
)->descriptor
.iManufacturer
, buffer
, len
);
131 fprintf(stderr
, "Warning: cannot query vendor for device\n");
132 return USBOPEN_ERR_IO
;
137 int usbhidGetProductString(USBDEVHANDLE usbh
, char *buffer
, int len
)
139 int len2
= usbhidGetStringAscii(usbDevHandle(usbh
), usbDevStruct(usbh
)->descriptor
.iProduct
, buffer
, len
);
141 fprintf(stderr
, "Warning: cannot query product for device\n");
142 return USBOPEN_ERR_IO
;
150 int usbhidSetReport(USBDEVHANDLE usbh
, char *buffer
, int len
)
152 int bytesSent
, reportId
= buffer
[0];
154 if ( !usesReportIDs(usbh
) ) {
155 buffer
++; /* skip dummy report ID */
158 bytesSent
= usb_control_msg(usbDevHandle(usbh
),
159 USB_TYPE_CLASS
| USB_RECIP_DEVICE
| USB_ENDPOINT_OUT
, USBRQ_HID_SET_REPORT
, USB_HID_REPORT_TYPE_FEATURE
<< 8 | (reportId
& 0xff),
160 0, buffer
, len
, A_REPORT_REQUEST_TIMEOUT
);
161 if (bytesSent
!= len
) {
163 fprintf(stderr
, "Error sending message: %s\n", usb_strerror());
164 return USBOPEN_ERR_IO
;
169 /* ------------------------------------------------------------------------- */
171 int usbhidGetReport(USBDEVHANDLE usbh
, int reportNumber
, char *buffer
, int *len
)
173 int bytesReceived
, maxLen
= *len
;
175 if (!usesReportIDs(usbh
)) {
176 buffer
++; /* make room for dummy report ID */
179 bytesReceived
= usb_control_msg(usbDevHandle(usbh
),
180 USB_TYPE_CLASS
| USB_RECIP_DEVICE
| USB_ENDPOINT_IN
, USBRQ_HID_GET_REPORT
, USB_HID_REPORT_TYPE_FEATURE
<< 8 | reportNumber
,
181 0, buffer
, maxLen
, A_REPORT_REQUEST_TIMEOUT
);
182 if(bytesReceived
< 0){
183 fprintf(stderr
, "Error sending message: %s\n", usb_strerror());
184 return USBOPEN_ERR_IO
;
186 *len
= bytesReceived
;
187 if (!usesReportIDs(usbh
)) {
188 buffer
[-1] = reportNumber
; /* add dummy report ID */
195 void usbhidSetUsesReportId(USBDEVHANDLE usbh
)
197 //TODO Implement if some devices prepend report IDs
198 //This differs among several versions of Linux HID libraries...
201 int usbhidStrerror_r( int err
, char *buf
, int len
)
205 case USBHID_ERR_ACCESS
: s
= "Access to device denied";
206 case USBHID_ERR_NOTFOUND
: s
= "The specified device was not found";
207 case USBHID_ERR_IO
: s
= "Communication error with device";
208 case USBHID_ERR_IO_HID
: s
= "HID I/O error with device";
213 return snprintf(buf
, len
, "%s", s
);