~ubuntu-branches/ubuntu/saucy/nut/saucy

« back to all changes in this revision

Viewing changes to drivers/libusb.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2005-07-20 19:48:50 UTC
  • mto: (16.1.1 squeeze)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20050720194850-oo61wjr33rrx2mre
Tags: upstream-2.0.2
ImportĀ upstreamĀ versionĀ 2.0.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
33
33
#include "libhid.h"
34
34
 
35
35
#include "hid-usb.h"
 
36
#include "config.h" /* for LIBUSB_HAS_DETACH_KRNL_DRV flag */
 
37
 
 
38
#include "common.h" /* for xmalloc prototype */
36
39
 
37
40
usb_dev_handle *udev = NULL;
38
 
 
39
 
#define USB_TIMEOUT 5000
 
41
struct usb_device *dev;
 
42
struct usb_bus *bus;
 
43
 
 
44
/* #define USB_TIMEOUT 5000 */
 
45
#define USB_TIMEOUT 4000
 
46
 
 
47
/* FIXME! */
 
48
#define MGE_UPS_SYSTEMS         0x0463          /* All models */
 
49
#define APC                                     0x051d          /* All models */
 
50
 
40
51
 
41
52
/* TODO: rework all that */
42
53
extern void upsdebugx(int level, const char *fmt, ...);
55
66
        u_int16_t wDescriptorLength;
56
67
};
57
68
 
 
69
/* From usbutils: workaround libusb API goofs:  "byte" should never be sign extended;
 
70
 * using "char" is trouble.  Likewise, sizes should never be negative.
 
71
 */
 
72
 
 
73
static inline int typesafe_control_msg(usb_dev_handle *dev,
 
74
        unsigned char requesttype, unsigned char request,
 
75
        int value, int index,
 
76
        unsigned char *bytes, unsigned size, int timeout)
 
77
{
 
78
        return usb_control_msg(dev, requesttype, request, value, index,
 
79
                (char *) bytes, (int) size, timeout);
 
80
}
 
81
 
 
82
#define usb_control_msg         typesafe_control_msg
 
83
 
58
84
/* return report descriptor on success, NULL otherwise */
59
 
int libusb_open(HIDDevice *curDevice, MatchFlags *flg, unsigned char *ReportDesc)
 
85
/* mode: MODE_OPEN for the 1rst time, MODE_REOPEN to skip getting
 
86
    report descriptor (the longer part) */
 
87
int libusb_open(HIDDevice *curDevice, MatchFlags *flg, unsigned char *ReportDesc, int mode)
60
88
{
61
 
  struct usb_bus *bus;
62
 
  struct usb_device *dev;
63
 
  int found = 0;
64
 
  struct my_usb_hid_descriptor *desc;
65
 
 
66
 
  int ret = -1, res; 
67
 
  char buf[20];
68
 
 
69
 
  /* libusb base init */
70
 
  usb_init();
71
 
  usb_find_busses();
72
 
  usb_find_devices();
73
 
 
74
 
  for (bus = usb_busses; bus && !found; bus = bus->next) {
75
 
    for (dev = bus->devices; dev && !found; dev = dev->next) {
76
 
      char string[256];
77
 
      
78
 
      TRACE(2, "Opening new device");
79
 
      udev = usb_open(dev);
80
 
      if (udev) {
81
 
 
82
 
        /* Check the VendorID for matching flag */
83
 
        if ((flg->VendorID != -1) && (dev->descriptor.idVendor != flg->VendorID))
84
 
          {
85
 
            TRACE(2, "Found %x, not matching VendorID", dev->descriptor.idVendor);
86
 
            usb_close(udev);
87
 
            continue;
88
 
          }
89
 
        else {
90
 
          TRACE(2, "Found %x, matching VendorID", dev->descriptor.idVendor);
91
 
          curDevice->VendorID = dev->descriptor.idVendor;
92
 
        }
93
 
        
94
 
        /* Check the ProductID for matching flag */
95
 
        if ((flg->ProductID != -1) && (dev->descriptor.idProduct != flg->ProductID))
96
 
          {
97
 
            TRACE(2, "Found %x, not matching ProductID", dev->descriptor.idProduct);
98
 
            usb_close(udev);
99
 
            continue;
100
 
          }
101
 
        else {
102
 
          TRACE(2, "Found %x, matching ProductID", dev->descriptor.idProduct);
103
 
          curDevice->ProductID = dev->descriptor.idProduct;
104
 
        }
105
 
        
106
 
        /* set default interface and claim it */
107
 
        usb_set_altinterface(udev, 0);  
108
 
        usb_claim_interface(udev, 0);
109
 
 
110
 
        /* Get HID descriptor */
111
 
        desc = (struct my_usb_hid_descriptor *)buf;
112
 
        /* res = usb_get_descriptor(udev, USB_DT_HID, 0, buf, 0x9); */
113
 
        res = usb_control_msg(udev, USB_ENDPOINT_IN+1, USB_REQ_GET_DESCRIPTOR,
114
 
                              (USB_DT_HID << 8) + 0, 0, buf, 0x9, USB_TIMEOUT);
115
 
 
116
 
        if (res < 9) {
117
 
          if (res < 0) {
118
 
            TRACE(2, "Not a HID device: Unable to get HID descriptor (%d)", res);
119
 
            continue;
120
 
          }
121
 
          else
122
 
            TRACE(2, "HID descriptor too short (expected %d, got %d)", 8, res);
123
 
        }
124
 
        else {
125
 
          /* USB_LE16_TO_CPU(desc->wDescriptorLength); */
126
 
          desc->wDescriptorLength = buf[7] + (buf[8]<<8);
127
 
          TRACE(2, "HID descriptor retrieved (Reportlen = %i)",
128
 
                  desc->wDescriptorLength);
129
 
        }
130
 
        
131
 
        if (dev->descriptor.iManufacturer) {
132
 
          ret = usb_get_string_simple(udev, dev->descriptor.iManufacturer, 
133
 
                                      string, sizeof(string));
134
 
          if (ret > 0)
135
 
            {
136
 
              TRACE(2, "- Manufacturer : %s", string);
137
 
              curDevice->Vendor = strdup(string);
138
 
              curDevice->Name = curDevice->Vendor; /* FIXME: cat Vendor+Prod?! */
139
 
            }
140
 
          else
141
 
            TRACE(2, "- Unable to fetch manufacturer string");
142
 
        }
143
 
        
144
 
        if (dev->descriptor.iProduct) {
145
 
          ret = usb_get_string_simple(udev, dev->descriptor.iProduct,
146
 
                                      string, sizeof(string));
147
 
          if (ret > 0) {
148
 
            TRACE(2, "- Product      : %s", string);
149
 
            curDevice->Product = strdup(string);
150
 
          }
151
 
          else
152
 
            TRACE(2, "- Unable to fetch product string");
153
 
        }
154
 
        
155
 
        if (dev->descriptor.iSerialNumber) {
156
 
          ret = usb_get_string_simple(udev, dev->descriptor.iSerialNumber,
157
 
                                      string, sizeof(string));
158
 
          if (ret > 0)
159
 
            {
160
 
              TRACE(2, "- Serial Number: %s", string);
161
 
              curDevice->Serial = strdup(string);
162
 
            }
163
 
          else
164
 
            TRACE(2, "- Unable to fetch serial number string");
165
 
        } else
166
 
          TRACE(2, "- No serial number string");
167
 
      
168
 
      if (!dev->config) {
169
 
        TRACE(2, "  Couldn't retrieve descriptors");
170
 
        continue;
171
 
      }
172
 
      
173
 
      /* usb_claim_interface(udev, 0); */
174
 
      
175
 
      /* usb_fetch_and_parse_descriptors(udev); => already done by usb_find_devices() */
176
 
      
177
 
      /* res = usb_get_descriptor(udev, USB_DT_REPORT, 0, bigbuf, desc->wDescriptorLength); */
178
 
      res = usb_control_msg(udev, USB_ENDPOINT_IN+1, USB_REQ_GET_DESCRIPTOR,
179
 
                            (USB_DT_REPORT << 8) + 0, 0, ReportDesc, 
180
 
                            desc->wDescriptorLength, USB_TIMEOUT);
181
 
      if (res < desc->wDescriptorLength) {
182
 
        if (res < 0) {
183
 
          TRACE(2, "Unable to get Report descriptor (%d)", res);
184
 
        }
185
 
        else {
186
 
          TRACE(2, "Report descriptor too short (expected %d, got %d)", 
187
 
                  desc->wDescriptorLength, res);
188
 
        }
189
 
        usb_close(udev);
190
 
        continue;
191
 
      }
192
 
      else {
193
 
        TRACE(2, "Report descriptor retrieved (Reportlen = %i)", 
194
 
                desc->wDescriptorLength);
195
 
        ret = desc->wDescriptorLength;
196
 
      }
197
 
      
198
 
      /* we can break there, and be sure there's a HID device */
199
 
      found = 1;
200
 
      break;
201
 
      } /* if udev */
202
 
    }
203
 
  }
204
 
  TRACE(2, "found %i (%i)", found, ret);
205
 
  fflush(stdout);
206
 
 
207
 
  return ret;
 
89
        int found = 0;
 
90
#if LIBUSB_HAS_DETACH_KRNL_DRV
 
91
        int retries = 3;
 
92
#endif
 
93
        struct my_usb_hid_descriptor *desc;
 
94
 
 
95
        int ret = -1, res; 
 
96
        unsigned char buf[20];
 
97
 
 
98
        /* libusb base init */
 
99
        usb_init();
 
100
        usb_find_busses();
 
101
        usb_find_devices();
 
102
 
 
103
 
 
104
        for (bus = usb_busses; bus && !found; bus = bus->next) {
 
105
                for (dev = bus->devices; dev && !found; dev = dev->next) {
 
106
                        char string[256];
 
107
      
 
108
                        TRACE(2, "Opening new device (%04X/%04X)",
 
109
                                  dev->descriptor.idVendor, dev->descriptor.idProduct);
 
110
                        udev = usb_open(dev);
 
111
                        if (udev) {
 
112
 
 
113
                          /* Check the VendorID for matching flag */
 
114
                          /* FIXME: temporary method, not generic/flexible enough */
 
115
                          if ((dev->descriptor.idVendor == MGE_UPS_SYSTEMS)
 
116
                                  || (dev->descriptor.idVendor == APC))
 
117
                                {
 
118
                                  TRACE(2, "Found 0x%x", dev->descriptor.idVendor);
 
119
                                  if (mode == MODE_REOPEN)
 
120
                                        return 1;
 
121
 
 
122
                                  curDevice->VendorID = dev->descriptor.idVendor;
 
123
                                  curDevice->iProduct = dev->descriptor.iProduct;
 
124
                                }
 
125
                          else
 
126
                                {
 
127
                                  usb_close(udev);
 
128
                                  udev = NULL;
 
129
                                  continue;
 
130
                                }
 
131
 
 
132
#if LIBUSB_HAS_DETACH_KRNL_DRV
 
133
                          /* this method requires libusb 0.1.8:
 
134
                           * it force device claiming by unbinding
 
135
                           * attached driver... From libhid */
 
136
                          while ((ret = usb_claim_interface(udev, 0)) != 0 && retries-- > 0) {
 
137
          
 
138
                                TRACE(2, "failed to claim USB device, trying %d more time(s)...", retries);
 
139
          
 
140
                                TRACE(2, "detaching kernel driver from USB device...");
 
141
                                if (usb_detach_kernel_driver_np(udev, 0) < 0) {
 
142
                                  TRACE(2, "failed to detach kernel driver from USB device...");
 
143
                                }
 
144
          
 
145
                                TRACE(2, "trying again to claim USB device...");
 
146
                          }
 
147
#else
 
148
                          if (usb_claim_interface(udev, 0) < 0)
 
149
                                TRACE(2, "failed to claim USB device...");
 
150
#endif
 
151
        
 
152
                          /* set default interface and claim it */
 
153
                          usb_set_altinterface(udev, 0);
 
154
 
 
155
                          if (dev->descriptor.iManufacturer) {
 
156
                                ret = usb_get_string_simple(udev, dev->descriptor.iManufacturer, 
 
157
                                                                                        string, sizeof(string));
 
158
                                if (ret > 0)
 
159
                                  {
 
160
                                        TRACE(2, "- Manufacturer : %s", string);
 
161
                                        curDevice->Vendor = strdup(string);
 
162
                                        curDevice->Name = curDevice->Vendor; /* FIXME: cat Vendor+Prod?! */
 
163
                                  }
 
164
                                else
 
165
                                  {
 
166
                                        TRACE(2, "- Unable to fetch manufacturer string");
 
167
                                        curDevice->Vendor = xmalloc(30);
 
168
                                        snprintf(curDevice->Vendor, 30, "Unknown vendor (0x%04x)",
 
169
                                                         dev->descriptor.idVendor);
 
170
                                  }
 
171
                          }
 
172
        
 
173
                          if (dev->descriptor.iProduct) {
 
174
                                ret = usb_get_string_simple(udev, dev->descriptor.iProduct,
 
175
                                                                                        string, sizeof(string));
 
176
                                if (ret > 0) {
 
177
                                  TRACE(2, "- Product      : %s", string);
 
178
                                  curDevice->Product = strdup(string);
 
179
                                }
 
180
                                else
 
181
                                  {
 
182
                                        TRACE(2, "-      Unable to fetch product string");
 
183
                                        curDevice->Product = xmalloc(30);
 
184
                                        snprintf(curDevice->Product, 30, "Unknown product (0x%04x)",
 
185
                                                         dev->descriptor.idProduct);
 
186
                                  }
 
187
                          }
 
188
        
 
189
                          if (dev->descriptor.iSerialNumber) {
 
190
                                ret = usb_get_string_simple(udev, dev->descriptor.iSerialNumber,
 
191
                                                                                        string, sizeof(string));
 
192
                                if (ret > 0)
 
193
                                  {
 
194
                                        TRACE(2, "- Serial Number: %s", string);
 
195
                                        curDevice->Serial = strdup(string);
 
196
                                  }
 
197
                                else
 
198
                                  TRACE(2, "- Unable to fetch serial number string");
 
199
                          } else
 
200
                                TRACE(2, "- No serial number string");
 
201
        
 
202
                          /* Get HID descriptor */
 
203
                          desc = (struct my_usb_hid_descriptor *)buf;
 
204
                          /* res = usb_get_descriptor(udev, USB_DT_HID, 0, buf, 0x9); */
 
205
                          res = usb_control_msg(udev, USB_ENDPOINT_IN+1, USB_REQ_GET_DESCRIPTOR,
 
206
                                                                        (USB_DT_HID << 8) + 0, 0, buf, 0x9, USB_TIMEOUT);
 
207
        
 
208
                          if (res < 9) {
 
209
                                if (res < 0) {
 
210
                                  TRACE(2, "Unable to get HID descriptor (%s)", usb_strerror());
 
211
                                  usb_close(udev);
 
212
                                  udev = NULL;
 
213
                                  continue;
 
214
                                }
 
215
                                else
 
216
                                  TRACE(2, "HID descriptor too short (expected %d, got %d)", 8, res);
 
217
                          }
 
218
                          else {
 
219
                                /* USB_LE16_TO_CPU(desc->wDescriptorLength); */
 
220
                                desc->wDescriptorLength = buf[7] | (buf[8] << 8);
 
221
                                TRACE(2, "HID descriptor retrieved (Reportlen = %5u)",
 
222
                                          desc->wDescriptorLength);
 
223
                          }
 
224
        
 
225
                          if (!dev->config) {
 
226
                                TRACE(2, "  Couldn't retrieve descriptors");
 
227
                                usb_close(udev);
 
228
                                udev = NULL;
 
229
                                continue;
 
230
                          }
 
231
 
 
232
                          /* Skip getting Report descriptor upon reconnexion */
 
233
                          if (mode == MODE_OPEN)
 
234
                                {      
 
235
                                  /* res = usb_get_descriptor(udev, USB_DT_REPORT, 0, bigbuf, desc->wDescriptorLength); */
 
236
                                  res = usb_control_msg(udev, USB_ENDPOINT_IN+1, USB_REQ_GET_DESCRIPTOR,
 
237
                                                                                (USB_DT_REPORT << 8) + 0, 0, ReportDesc, 
 
238
                                                                                desc->wDescriptorLength, USB_TIMEOUT);
 
239
                                  if (res < desc->wDescriptorLength) {
 
240
                                        if (res < 0)
 
241
                                          {
 
242
                                                TRACE(2, "Unable to get Report descriptor (%d)", res);
 
243
                                          }
 
244
                                        else
 
245
                                          {
 
246
                                                TRACE(2, "Report descriptor too short (expected %d, got %d)", 
 
247
                                                          desc->wDescriptorLength, res);
 
248
                                          }
 
249
                                        usb_close(udev);
 
250
                                        udev = NULL;
 
251
                                        continue;
 
252
                                  }
 
253
                                  else
 
254
                                        {
 
255
                                          TRACE(2, "Report descriptor retrieved (Reportlen = %i)", 
 
256
                                                        desc->wDescriptorLength);
 
257
                                          ret = desc->wDescriptorLength;
 
258
                                        }
 
259
                                }
 
260
      
 
261
                          /* we can break there, and be sure there's a HID device */
 
262
                          found = 1;
 
263
                          break;
 
264
                        } /* if udev */
 
265
                }
 
266
        }
 
267
        TRACE(2, "found %i (%i)", found, ret);
 
268
        fflush(stdout);
 
269
 
 
270
        return ret;
208
271
}
209
272
 
210
273
/* return the report of ID=type in report 
213
276
 
214
277
int libusb_get_report(int ReportId, unsigned char *raw_buf, int ReportSize )
215
278
{
216
 
  return usb_control_msg(udev, 
 
279
        TRACE(4, "Entering libusb_get_report");
 
280
 
 
281
        if (udev != NULL)
 
282
        {
 
283
                return usb_control_msg(udev, 
217
284
                         USB_ENDPOINT_IN + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
218
285
                         0x01, /* HID_REPORT_GET */
219
286
                         ReportId+(0x03<<8), /* HID_REPORT_TYPE_FEATURE */
220
287
                         0, raw_buf, ReportSize, USB_TIMEOUT);
 
288
        }
 
289
        else
 
290
                return 0;
221
291
}
222
292
 
223
293
 
224
294
int libusb_set_report(int ReportId, unsigned char *raw_buf, int ReportSize )
225
295
{
226
 
  return usb_control_msg(udev, 
 
296
        if (udev != NULL)
 
297
        {
 
298
                return usb_control_msg(udev, 
227
299
                         USB_ENDPOINT_OUT + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
228
300
                         0x09, /* HID_REPORT_SET = 0x09*/
229
301
                         ReportId+(0x03<<8), /* HID_REPORT_TYPE_FEATURE */
230
302
                         0, raw_buf, ReportSize, USB_TIMEOUT);
 
303
        }
 
304
        else
 
305
                return 0;
231
306
}
232
307
 
233
308
int libusb_get_string(int StringIdx, char *string)
234
309
{
235
 
  int ret;
 
310
  int ret = -1; 
236
311
 
237
 
  ret = usb_get_string_simple(udev, StringIdx, string, 20); /* sizeof(string)); */
238
 
  if (ret > 0)
239
 
    {
240
 
      TRACE(2, "-> String: %s (len = %i/%i)", string, ret, sizeof(string));
241
 
    }
242
 
  else
243
 
    TRACE(2, "- Unable to fetch string");
 
312
  if (udev != NULL)
 
313
        {
 
314
          ret = usb_get_string_simple(udev, StringIdx, string, 20); /* sizeof(string)); */
 
315
          if (ret > 0)
 
316
                {
 
317
                  TRACE(2, "-> String: %s (len = %i/%i)", string, ret, sizeof(string));
 
318
                }
 
319
          else
 
320
                TRACE(2, "- Unable to fetch string");
 
321
        }
244
322
 
245
323
  return ret;
246
324
}
249
327
{
250
328
  int ret = -1;
251
329
 
252
 
  /* FIXME: hardcoded interrupt EP => need to get EP descr for IF descr */
253
 
  /*  ret = usb_interrupt_read(udev, 0x81, buf, bufsize, timeout);
254
 
  if (ret > 0)
255
 
    {
256
 
      TRACE(2, "-> Got a notification!\n");
257
 
    }
258
 
  else
259
 
    TRACE(2, "- No notification\n");
260
 
  */
 
330
  if (udev != NULL)
 
331
        {
 
332
          /* FIXME: hardcoded interrupt EP => need to get EP descr for IF descr */
 
333
          ret = usb_interrupt_read(udev, 0x81, buf, bufsize, timeout);
 
334
          if (ret > 0)
 
335
                TRACE(2, " ok\n");
 
336
          else
 
337
                TRACE(2, " none (%i)\n", ret);
 
338
        }
 
339
 
261
340
  return ret;
262
341
}
263
342
 
264
343
void libusb_close(HIDDevice *curDevice)
265
344
{
266
 
  if (udev != NULL)
267
 
    usb_close(udev);
 
345
        if (udev != NULL)
 
346
        {
 
347
                usb_release_interface(udev, 0);
 
348
                usb_close(udev);
 
349
        }
 
350
        udev = NULL;
268
351
}