apcupsd-ups: ignore generated files
[networkupstools/kirr.git] / drivers / libusb.c
blob234b9f142a36af1dcba29f3e439566c4da6497dd
1 /*!
2 * @file libusb.c
3 * @brief HID Library - Generic USB communication sub driver (using libusb)
5 * @author Copyright (C)
6 * 2003 - 2007 Arnaud Quette <aquette.dev@gmail.com>
7 * 2005 - 2007 Peter Selinger <selinger@users.sourceforge.net>
9 * This program is sponsored by MGE UPS SYSTEMS - opensource.mgeups.com
11 * The logic of this file is ripped from mge-shut driver (also from
12 * Arnaud Quette), which is a "HID over serial link" UPS driver for
13 * Network UPS Tools <http://www.networkupstools.org/>
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 * -------------------------------------------------------------------------- */
31 #include "config.h" /* for HAVE_USB_DETACH_KERNEL_DRIVER_NP flag */
32 #include "common.h" /* for xmalloc, upsdebugx prototypes */
33 #include "usb-common.h"
34 #include "libusb.h"
36 /* USB standard timeout */
37 #define USB_TIMEOUT 5000
39 #define USB_DRIVER_NAME "USB communication driver"
40 #define USB_DRIVER_VERSION "0.32"
42 /* driver description structure */
43 upsdrv_info_t comm_upsdrv_info = {
44 USB_DRIVER_NAME,
45 USB_DRIVER_VERSION,
46 NULL,
48 { NULL }
51 #define MAX_REPORT_SIZE 0x1800
53 static void libusb_close(usb_dev_handle *udev);
55 /* From usbutils: workaround libusb API goofs: "byte" should never be sign extended;
56 * using "char" is trouble. Likewise, sizes should never be negative.
59 static inline int typesafe_control_msg(usb_dev_handle *dev,
60 unsigned char requesttype, unsigned char request,
61 int value, int index,
62 unsigned char *bytes, unsigned size, int timeout)
64 return usb_control_msg(dev, requesttype, request, value, index,
65 (char *) bytes, (int) size, timeout);
68 /* invoke matcher against device */
69 static inline int matches(USBDeviceMatcher_t *matcher, USBDevice_t *device) {
70 if (!matcher) {
71 return 1;
73 return matcher->match_function(device, matcher->privdata);
76 #define usb_control_msg typesafe_control_msg
78 /* On success, fill in the curDevice structure and return the report
79 * descriptor length. On failure, return -1.
80 * Note: When callback is not NULL, the report descriptor will be
81 * passed to this function together with the udev and USBDevice_t
82 * information. This callback should return a value > 0 if the device
83 * is accepted, or < 1 if not. If it isn't accepted, the next device
84 * (if any) will be tried, until there are no more devices left.
86 static int libusb_open(usb_dev_handle **udevp, USBDevice_t *curDevice, USBDeviceMatcher_t *matcher,
87 int (*callback)(usb_dev_handle *udev, USBDevice_t *hd, unsigned char *rdbuf, int rdlen))
89 #ifdef HAVE_USB_DETACH_KERNEL_DRIVER_NP
90 int retries;
91 #endif
92 int rdlen1, rdlen2; /* report descriptor length, method 1+2 */
93 USBDeviceMatcher_t *m;
94 struct usb_device *dev;
95 struct usb_bus *bus;
96 usb_dev_handle *udev;
97 struct usb_interface_descriptor *iface;
99 int ret, res;
100 unsigned char buf[20];
101 unsigned char *p;
102 char string[256];
103 int i;
105 /* report descriptor */
106 unsigned char rdbuf[MAX_REPORT_SIZE];
107 int rdlen;
109 /* libusb base init */
110 usb_init();
111 usb_find_busses();
112 usb_find_devices();
114 #ifndef __linux__ /* SUN_LIBUSB (confirmed to work on Solaris and FreeBSD) */
115 /* Causes a double free corruption in linux if device is detached! */
116 libusb_close(*udevp);
117 #endif
119 for (bus = usb_busses; bus; bus = bus->next) {
120 for (dev = bus->devices; dev; dev = dev->next) {
121 upsdebugx(2, "Checking device (%04X/%04X) (%s/%s)", dev->descriptor.idVendor,
122 dev->descriptor.idProduct, bus->dirname, dev->filename);
124 /* supported vendors are now checked by the
125 supplied matcher */
127 /* open the device */
128 *udevp = udev = usb_open(dev);
129 if (!udev) {
130 upsdebugx(2, "Failed to open device, skipping. (%s)", usb_strerror());
131 continue;
134 /* collect the identifying information of this
135 device. Note that this is safe, because
136 there's no need to claim an interface for
137 this (and therefore we do not yet need to
138 detach any kernel drivers). */
140 free(curDevice->Vendor);
141 free(curDevice->Product);
142 free(curDevice->Serial);
143 free(curDevice->Bus);
144 memset(curDevice, '\0', sizeof(*curDevice));
146 curDevice->VendorID = dev->descriptor.idVendor;
147 curDevice->ProductID = dev->descriptor.idProduct;
148 curDevice->Bus = strdup(bus->dirname);
150 if (dev->descriptor.iManufacturer) {
151 ret = usb_get_string_simple(udev, dev->descriptor.iManufacturer,
152 string, sizeof(string));
153 if (ret > 0) {
154 curDevice->Vendor = strdup(string);
158 if (dev->descriptor.iProduct) {
159 ret = usb_get_string_simple(udev, dev->descriptor.iProduct,
160 string, sizeof(string));
161 if (ret > 0) {
162 curDevice->Product = strdup(string);
166 if (dev->descriptor.iSerialNumber) {
167 ret = usb_get_string_simple(udev, dev->descriptor.iSerialNumber,
168 string, sizeof(string));
169 if (ret > 0) {
170 curDevice->Serial = strdup(string);
174 upsdebugx(2, "- VendorID: %04x", curDevice->VendorID);
175 upsdebugx(2, "- ProductID: %04x", curDevice->ProductID);
176 upsdebugx(2, "- Manufacturer: %s", curDevice->Vendor ? curDevice->Vendor : "unknown");
177 upsdebugx(2, "- Product: %s", curDevice->Product ? curDevice->Product : "unknown");
178 upsdebugx(2, "- Serial Number: %s", curDevice->Serial ? curDevice->Serial : "unknown");
179 upsdebugx(2, "- Bus: %s", curDevice->Bus ? curDevice->Bus : "unknown");
181 upsdebugx(2, "Trying to match device");
182 for (m = matcher; m; m=m->next) {
183 ret = matches(m, curDevice);
184 if (ret==0) {
185 upsdebugx(2, "Device does not match - skipping");
186 goto next_device;
187 } else if (ret==-1) {
188 fatal_with_errno(EXIT_FAILURE, "matcher");
189 goto next_device;
190 } else if (ret==-2) {
191 upsdebugx(2, "matcher: unspecified error");
192 goto next_device;
195 upsdebugx(2, "Device matches");
197 /* Now we have matched the device we wanted. Claim it. */
199 #ifdef HAVE_USB_DETACH_KERNEL_DRIVER_NP
200 /* this method requires at least libusb 0.1.8:
201 * it force device claiming by unbinding
202 * attached driver... From libhid */
203 retries = 3;
204 while (usb_claim_interface(udev, 0) < 0) {
206 upsdebugx(2, "failed to claim USB device: %s", usb_strerror());
208 if (usb_detach_kernel_driver_np(udev, 0) < 0) {
209 upsdebugx(2, "failed to detach kernel driver from USB device: %s", usb_strerror());
210 } else {
211 upsdebugx(2, "detached kernel driver from USB device...");
214 if (retries-- > 0) {
215 continue;
218 fatalx(EXIT_FAILURE, "Can't claim USB device [%04x:%04x]: %s", curDevice->VendorID, curDevice->ProductID, usb_strerror());
220 #else
221 if (usb_claim_interface(udev, 0) < 0) {
222 fatalx(EXIT_FAILURE, "Can't claim USB device [%04x:%04x]: %s", curDevice->VendorID, curDevice->ProductID, usb_strerror());
224 #endif
226 /* set default interface */
227 usb_set_altinterface(udev, 0);
229 if (!callback) {
230 return 1;
233 if (!dev->config) { /* ?? this should never happen */
234 upsdebugx(2, " Couldn't retrieve descriptors");
235 goto next_device;
238 rdlen1 = -1;
239 rdlen2 = -1;
241 /* Get HID descriptor */
243 /* FIRST METHOD: ask for HID descriptor directly. */
244 /* res = usb_get_descriptor(udev, USB_DT_HID, 0, buf, 0x9); */
245 res = usb_control_msg(udev, USB_ENDPOINT_IN+1, USB_REQ_GET_DESCRIPTOR,
246 (USB_DT_HID << 8) + 0, 0, buf, 0x9, USB_TIMEOUT);
248 if (res < 0) {
249 upsdebugx(2, "Unable to get HID descriptor (%s)", usb_strerror());
250 } else if (res < 9) {
251 upsdebugx(2, "HID descriptor too short (expected %d, got %d)", 8, res);
252 } else {
254 upsdebug_hex(3, "HID descriptor, method 1", buf, 9);
256 rdlen1 = buf[7] | (buf[8] << 8);
259 if (rdlen1 < -1) {
260 upsdebugx(2, "Warning: HID descriptor, method 1 failed");
263 /* SECOND METHOD: find HID descriptor among "extra" bytes of
264 interface descriptor, i.e., bytes tucked onto the end of
265 descriptor 2. */
267 /* Note: on some broken UPS's (e.g. Tripp Lite Smart1000LCD),
268 only this second method gives the correct result */
270 /* for now, we always assume configuration 0, interface 0,
271 altsetting 0, as above. */
272 iface = &dev->config[0].interface[0].altsetting[0];
273 for (i=0; i<iface->extralen; i+=iface->extra[i]) {
274 upsdebugx(4, "i=%d, extra[i]=%02x, extra[i+1]=%02x", i,
275 iface->extra[i], iface->extra[i+1]);
276 if (i+9 <= iface->extralen && iface->extra[i] >= 9 && iface->extra[i+1] == 0x21) {
277 p = &iface->extra[i];
278 upsdebug_hex(3, "HID descriptor, method 2", p, 9);
279 rdlen2 = p[7] | (p[8] << 8);
280 break;
284 if (rdlen2 < -1) {
285 upsdebugx(2, "Warning: HID descriptor, method 2 failed");
288 /* when available, always choose the second value, as it
289 seems to be more reliable (it is the one reported e.g. by
290 lsusb). Note: if the need arises, can change this to use
291 the maximum of the two values instead. */
292 rdlen = rdlen2 >= 0 ? rdlen2 : rdlen1;
294 if (rdlen < 0) {
295 upsdebugx(2, "Unable to retrieve any HID descriptor");
296 goto next_device;
298 if (rdlen1 >= 0 && rdlen2 >= 0 && rdlen1 != rdlen2) {
299 upsdebugx(2, "Warning: two different HID descriptors retrieved (Reportlen = %d vs. %d)", rdlen1, rdlen2);
302 upsdebugx(2, "HID descriptor length %d", rdlen);
304 if (rdlen > (int)sizeof(rdbuf)) {
305 upsdebugx(2, "HID descriptor too long %d (max %d)", rdlen, (int)sizeof(rdbuf));
306 goto next_device;
309 /* res = usb_get_descriptor(udev, USB_DT_REPORT, 0, bigbuf, rdlen); */
310 res = usb_control_msg(udev, USB_ENDPOINT_IN+1, USB_REQ_GET_DESCRIPTOR,
311 (USB_DT_REPORT << 8) + 0, 0, rdbuf, rdlen, USB_TIMEOUT);
313 if (res < 0)
315 upsdebug_with_errno(2, "Unable to get Report descriptor");
316 goto next_device;
319 if (res < rdlen)
321 upsdebugx(2, "Warning: report descriptor too short (expected %d, got %d)", rdlen, res);
322 rdlen = res; /* correct rdlen if necessary */
325 res = callback(udev, curDevice, rdbuf, rdlen);
326 if (res < 1) {
327 upsdebugx(2, "Caller doesn't like this device");
328 goto next_device;
331 upsdebugx(2, "Report descriptor retrieved (Reportlen = %d)", rdlen);
332 upsdebugx(2, "Found HID device");
333 fflush(stdout);
335 return rdlen;
337 next_device:
338 usb_close(udev);
342 *udevp = NULL;
343 upsdebugx(2, "No appropriate HID device found");
344 fflush(stdout);
346 return -1;
350 * Error handler for usb_get/set_* functions. Return value > 0 success,
351 * 0 unknown or temporary failure (ignored), < 0 permanent failure (reconnect)
353 static int libusb_strerror(const int ret, const char *desc)
355 if (ret > 0) {
356 return ret;
359 switch(ret)
361 case -EBUSY: /* Device or resource busy */
362 case -EPERM: /* Operation not permitted */
363 case -ENODEV: /* No such device */
364 case -EACCES: /* Permission denied */
365 case -EIO: /* I/O error */
366 case -ENXIO: /* No such device or address */
367 case -ENOENT: /* No such file or directory */
368 case -EPIPE: /* Broken pipe */
369 case -ENOSYS: /* Function not implemented */
370 upslogx(LOG_DEBUG, "%s: %s", desc, usb_strerror());
371 return ret;
373 case -ETIMEDOUT: /* Connection timed out */
374 upsdebugx(2, "%s: Connection timed out", desc);
375 return 0;
377 case -EOVERFLOW: /* Value too large for defined data type */
378 case -EPROTO: /* Protocol error */
379 upsdebugx(2, "%s: %s", desc, usb_strerror());
380 return 0;
382 default: /* Undetermined, log only */
383 upslogx(LOG_DEBUG, "%s: %s", desc, usb_strerror());
384 return 0;
388 /* return the report of ID=type in report
389 * return -1 on failure, report length on success
392 static int libusb_get_report(usb_dev_handle *udev, int ReportId, unsigned char *raw_buf, int ReportSize )
394 int ret;
396 upsdebugx(4, "Entering libusb_get_report");
398 if (!udev) {
399 return 0;
402 ret = usb_control_msg(udev,
403 USB_ENDPOINT_IN + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
404 0x01, /* HID_REPORT_GET */
405 ReportId+(0x03<<8), /* HID_REPORT_TYPE_FEATURE */
406 0, raw_buf, ReportSize, USB_TIMEOUT);
408 /* Ignore "protocol stall" (for unsupported request) on control endpoint */
409 if (ret == -EPIPE) {
410 return 0;
413 return libusb_strerror(ret, __func__);
416 static int libusb_set_report(usb_dev_handle *udev, int ReportId, unsigned char *raw_buf, int ReportSize )
418 int ret;
420 if (!udev) {
421 return 0;
424 ret = usb_control_msg(udev,
425 USB_ENDPOINT_OUT + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
426 0x09, /* HID_REPORT_SET = 0x09*/
427 ReportId+(0x03<<8), /* HID_REPORT_TYPE_FEATURE */
428 0, raw_buf, ReportSize, USB_TIMEOUT);
430 /* Ignore "protocol stall" (for unsupported request) on control endpoint */
431 if (ret == -EPIPE) {
432 return 0;
435 return libusb_strerror(ret, __func__);
438 static int libusb_get_string(usb_dev_handle *udev, int StringIdx, char *buf, size_t buflen)
440 int ret;
442 if (!udev) {
443 return -1;
446 ret = usb_get_string_simple(udev, StringIdx, buf, buflen);
448 return libusb_strerror(ret, __func__);
451 static int libusb_get_interrupt(usb_dev_handle *udev, unsigned char *buf, int bufsize, int timeout)
453 int ret;
455 if (!udev) {
456 return -1;
459 /* FIXME: hardcoded interrupt EP => need to get EP descr for IF descr */
460 ret = usb_interrupt_read(udev, 0x81, (char *)buf, bufsize, timeout);
462 /* Clear stall condition */
463 if (ret == -EPIPE) {
464 ret = usb_clear_halt(udev, 0x81);
467 return libusb_strerror(ret, __func__);
470 static void libusb_close(usb_dev_handle *udev)
472 if (!udev) {
473 return;
476 /* usb_release_interface() sometimes blocks and goes
477 into uninterruptible sleep. So don't do it. */
478 /* usb_release_interface(udev, 0); */
479 usb_close(udev);
482 usb_communication_subdriver_t usb_subdriver = {
483 USB_DRIVER_VERSION,
484 USB_DRIVER_NAME,
485 libusb_open,
486 libusb_close,
487 libusb_get_report,
488 libusb_set_report,
489 libusb_get_string,
490 libusb_get_interrupt