hid_opening.c

Go to the documentation of this file.
00001 #define HID_INTERNAL
00002 
00003 #include <hid.h>
00004 #include <hid_helpers.h>
00005 #include <os.h>
00006 
00007 #include <debug.h>
00008 #include <assert.h>
00009 
00010 enum USBMatchFlags {
00011   USB_MATCH_NONE = 0x0,
00012   USB_MATCH_VENDOR = 0x1,
00013   USB_MATCH_PRODUCT = 0x2,
00014   USB_MATCH_CUSTOM = 0x4,
00015   USB_MATCH_ALL = USB_MATCH_VENDOR | USB_MATCH_PRODUCT | USB_MATCH_CUSTOM
00016 };
00017 
00018 #define MAX_OPEN_DEVICES 20  // Should be changed to dynmaic 
00019 static struct t_open_hid_device_list {
00020   int nDevices;   // number of known open devices
00021   HIDInterface* hidif[MAX_OPEN_DEVICES];
00022 } open_hid_device_list = {0,
00023         {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
00024          NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}
00025                           };
00026 
00027 static int add_open_device(HIDInterface* hidif)
00028 {
00029   if (open_hid_device_list.nDevices < MAX_OPEN_DEVICES) {
00030     open_hid_device_list.hidif[open_hid_device_list.nDevices++] = hidif;
00031     return 0;
00032   } else {
00033     TRACE("open_hid_device_list is full.");
00034     return -1;
00035   }
00036 }
00037 
00038 static void remove_open_device(HIDInterface* hidif)
00039 {
00040   int i, j;
00041   for (i = 0; i < open_hid_device_list.nDevices; i++) {
00042     if (hidif == open_hid_device_list.hidif[i]) {
00043       for (j = i+1; j < open_hid_device_list.nDevices; j++) {
00044   open_hid_device_list.hidif[j-1] = open_hid_device_list.hidif[j];
00045       }
00046       open_hid_device_list.nDevices--;
00047       return;
00048     }
00049   }
00050 }
00051 
00052 static int hid_previously_matched(struct usb_dev_handle const* dev_h, int interface)
00053 {
00054   int i;
00055   struct usb_device const* usbdev = usb_device((usb_dev_handle*)dev_h);
00056 
00057   for (i = 0; i < open_hid_device_list.nDevices; i++) {
00058     if ((interface == open_hid_device_list.hidif[i]->interface) && 
00059   (usbdev == open_hid_device_list.hidif[i]->device)) {
00060       return 1;
00061      }
00062   }
00063   return 0;
00064 }
00065 
00066 static unsigned int hid_compare_usb_device(struct usb_dev_handle const* dev_h,
00067     HIDInterfaceMatcher const* const match)
00068 {
00069   ASSERT(dev_h);
00070   ASSERT(match);
00071 
00072   unsigned int ret = USB_MATCH_NONE;
00073 
00074   TRACE("comparing match specifications to USB device...");
00075 
00076   struct usb_device const* dev = usb_device((usb_dev_handle*)dev_h);
00077 
00078   TRACE("inspecting vendor ID...");
00079   if (dev->descriptor.idVendor > 0 &&
00080       (dev->descriptor.idVendor & match->vendor_id) == match->vendor_id) {
00081       TRACE("match on vendor ID: 0x%04x.", dev->descriptor.idVendor);
00082       ret |= USB_MATCH_VENDOR;
00083   }
00084   else TRACE("no match on vendor ID.");
00085 
00086   TRACE("inspecting product ID...");
00087   if ((dev->descriptor.idProduct & match->product_id) == match->product_id) {
00088       TRACE("match on product ID: 0x%04x.", dev->descriptor.idProduct);
00089       ret |= USB_MATCH_PRODUCT;
00090   }
00091   else TRACE("no match on product ID.");
00092 
00093   if (match->matcher_fn) {
00094     TRACE("calling custom matching function...");
00095     if ((*match->matcher_fn)(dev_h, match->custom_data, match->custom_data_length)) {
00096       TRACE("match on custom matching function.");
00097       ret |= USB_MATCH_CUSTOM;
00098     }
00099     else TRACE("no match on custom matching function.");
00100   }
00101   else {
00102     TRACE("no custom matching function supplied.");
00103     ret |= USB_MATCH_CUSTOM;
00104   }
00105 
00106   return ret;
00107 }
00108 
00109 static hid_return hid_find_usb_device(HIDInterface* const hidif,
00110     HIDInterfaceMatcher const* const match)
00111 {
00112   ASSERT(!hid_is_opened(hidif));
00113   ASSERT(match);
00114 
00115   /* WARNING: not thread-safe. usb_busses in libusb/usb.c is a global
00116    * variable.
00117    */
00118   struct usb_bus *usbbus = usb_get_busses();
00119   struct usb_device *usbdev;
00120 
00121   TRACE("enumerating USB busses...");
00122   for (; usbbus; usbbus = usbbus->next) {
00123 
00124     TRACE("enumerating USB devices on bus %s...", usbbus->dirname);
00125     for (usbdev = usbbus->devices; usbdev; usbdev=usbdev->next) {
00126 
00127       snprintf(hidif->id, sizeof(hidif->id), "%s/%s[%d]",
00128           usbbus->dirname, usbdev->filename, hidif->interface);
00129 
00130       TRACE("inspecting USB device %s...", hidif->id);
00131       usb_dev_handle *usbdev_h = usb_open(usbdev);
00132 
00133       if (usbdev_h) {
00134         if (!usb_claim_interface(usbdev_h, hidif->interface)) {
00135     TRACE("Could not claim interface %d...\n", hidif->interface);
00136   }
00137 
00138   // Make sure we are not considering an already matched device
00139   if (hid_previously_matched(usbdev_h, hidif->interface)) {
00140     TRACE("match of previously open device/interface...");
00141     continue;
00142   }
00143 
00144         unsigned int flags = hid_compare_usb_device(usbdev_h, match);
00145         if (flags == USB_MATCH_ALL) {
00146           NOTICE("found a matching USB device %s.", hidif->id);
00147           hidif->dev_handle = usbdev_h;
00148           hidif->device = usb_device(usbdev_h);
00149           return HID_RET_SUCCESS;
00150         }
00151 
00152         if (!(flags & USB_MATCH_VENDOR)) {
00153           NOTICE("vendor 0x%04x of USB device %s does not match 0x%04x.",
00154              usbdev->descriptor.idVendor, hidif->id, match->vendor_id);
00155         }
00156         else if (!(flags & USB_MATCH_PRODUCT)) {
00157           NOTICE("product 0x%04x of USB device %s does not match 0x%04x.",
00158              usbdev->descriptor.idProduct, hidif->id, match->product_id);
00159         }
00160         else if (!(flags & USB_MATCH_CUSTOM)) {
00161           NOTICE("custom matching function returned false on %s.", hidif->id);
00162         }
00163         //usb_release_interface(usbdev_h, hidif->interface);
00164         usb_close(usbdev_h);
00165       }
00166       else {
00167         ERROR("failed to open USB device %s", hidif->id);
00168         return HID_RET_FAIL_OPEN_DEVICE;
00169       }
00170     }
00171   }
00172   WARNING("no matching USB device found.");
00173   return HID_RET_DEVICE_NOT_FOUND;
00174 }
00175 
00176 static hid_return hid_get_usb_handle(HIDInterface* const hidif,
00177     HIDInterfaceMatcher const* const match)
00178 {
00179   ASSERT(!hid_is_opened(hidif));
00180   ASSERT(match);
00181 
00182   TRACE("acquiring handle for a USB device...");
00183   
00184   hid_return ret = hid_find_usb_device(hidif, match);
00185   if (ret != HID_RET_SUCCESS) {
00186     hidif->dev_handle = NULL;
00187     hidif->device = NULL;
00188     return ret;
00189   }
00190 
00191   return HID_RET_SUCCESS;
00192 }
00193 
00194 hid_return hid_open(HIDInterface* const hidif, int const interface,
00195     HIDInterfaceMatcher const* const matcher)
00196 {
00197   if (!hid_is_initialised()) {
00198     ERROR("cannot open HIDInterface when HID library has not been initialised.");
00199     return HID_RET_NOT_INITIALISED;
00200   }
00201 
00202   if (!hidif) {
00203     ERROR("cannot open NULL HIDInterface.");
00204     return HID_RET_INVALID_PARAMETER;
00205   }
00206 
00207   if (hid_is_opened(hidif)) {
00208     ERROR("cannot open already opened HIDInterface %s.", hidif->id);
00209     return HID_RET_DEVICE_ALREADY_OPENED;
00210   }
00211 
00212   if (!matcher) {
00213     ERROR("cannot match against NULL HIDInterfaceMatcher.");
00214     return HID_RET_INVALID_PARAMETER;
00215   }
00216 
00217   hidif->interface = interface;
00218 
00219   TRACE("opening a device interface according to matching criteria...");
00220   hid_return ret = hid_get_usb_handle(hidif, matcher);
00221   if (ret != HID_RET_SUCCESS) return ret;
00222 
00223   TRACE("claiming USB device %s.", hidif->id);
00224   if (usb_claim_interface(hidif->dev_handle, interface) < 0) {
00225     WARNING("failed to claim USB device %s.", hidif->id);
00226     hid_close(hidif);
00227     return HID_RET_FAIL_CLAIM_IFACE;
00228   }
00229   NOTICE("successfully claimed USB device %s.", hidif->id);
00230 
00231   ret = hid_prepare_interface(hidif);
00232   if (ret != HID_RET_SUCCESS) return ret;
00233 
00234   TRACE("add open device to list...");
00235   add_open_device(hidif);
00236 
00237   NOTICE("successfully opened USB device %s.", hidif->id);
00238   return HID_RET_SUCCESS;
00239 }
00240 
00241 hid_return hid_force_open(HIDInterface* const hidif, int const interface,
00242     HIDInterfaceMatcher const* const matcher, unsigned short retries)
00243 {
00244   if (!hid_is_initialised()) {
00245     ERROR("cannot open HIDInterface when HID library has not been initialised.");
00246     return HID_RET_NOT_INITIALISED;
00247   }
00248 
00249   if (!hidif) {
00250     ERROR("cannot open NULL HIDInterface.");
00251     return HID_RET_INVALID_PARAMETER;
00252   }
00253 
00254   if (hid_is_opened(hidif)) {
00255     ERROR("cannot open already opened HIDInterface %s.", hidif->id);
00256     return HID_RET_DEVICE_ALREADY_OPENED;
00257   }
00258 
00259   if (!matcher) {
00260     ERROR("cannot match against NULL HIDInterfaceMatcher.");
00261     return HID_RET_INVALID_PARAMETER;
00262   }
00263 
00264   hidif->interface = interface;
00265 
00266   TRACE("forcefully opening a device interface "
00267         "according to matching criteria...");
00268   hid_return ret = hid_get_usb_handle(hidif, matcher);
00269   if (ret != HID_RET_SUCCESS) return ret;
00270 
00271   TRACE("claiming USB device %s.", hidif->id);
00272   ret = hid_os_force_claim(hidif, interface, matcher, retries);
00273   if (ret != HID_RET_SUCCESS) {
00274     WARNING("failed to claim USB device %s.", hidif->id);
00275     hid_close(hidif);
00276     return ret;
00277   }
00278   NOTICE("successfully claimed USB device %s.", hidif->id);
00279  
00280   ret = hid_prepare_interface(hidif);
00281   if (ret != HID_RET_SUCCESS) return ret;
00282 
00283   TRACE("add open device to list...");
00284   add_open_device(hidif);
00285 
00286   NOTICE("successfully opened USB device %s.", hidif->id);
00287   return HID_RET_SUCCESS;
00288 }
00289 
00290 hid_return hid_close(HIDInterface* const hidif)
00291 {
00292   int ret = -1;
00293 
00294   if (hid_is_opened(hidif)) {
00295 
00296     TRACE("closing USB device %s...", hidif->id);
00297 
00298 #if 0
00299     TRACE("releasing USB device %s...", hidif->id);
00300     if (usb_release_interface(hidif->dev_handle, hidif->interface) < 0)
00301       WARNING("failed to release USB device %s.", hidif->id);
00302 #endif
00303 
00304     TRACE("closing handle of USB device %s...", hidif->id);
00305     if ((ret = usb_close(hidif->dev_handle)) < 0) {
00306       WARNING("failed to close USB device %s.", hidif->id);
00307     }
00308     else {
00309       NOTICE("successfully closed USB device %s.", hidif->id);
00310     }
00311   }
00312   else WARNING("attempt to close unopened USB device %s.", hidif->id);
00313     
00314   TRACE("remove hidif from open list...");  
00315   remove_open_device(hidif);
00316 
00317   if (hidif->hid_parser) hid_reset_parser(hidif);
00318     
00319   TRACE("freeing memory allocated for HID parser...");
00320   if(hidif->hid_parser) free(hidif->hid_parser);
00321   if(hidif->hid_data) free(hidif->hid_data);
00322 
00323   TRACE("resetting HIDInterface...");
00324   hid_reset_HIDInterface(hidif);
00325 
00326   if (ret < 0) return HID_RET_FAIL_CLOSE_DEVICE;
00327 
00328   return HID_RET_SUCCESS;
00329 }
00330 
00331 bool hid_is_opened(HIDInterface const* hidif)
00332 {
00333   if (!hidif) WARNING("attempt to query open status of NULL HIDInterface.");
00334   return hidif && hidif->dev_handle;
00335 }
00336 
00337 /* COPYRIGHT --
00338  *
00339  * This file is part of libhid, a user-space HID access library.
00340  * libhid is (c) 2003-2005
00341  *   Martin F. Krafft <libhid@pobox.madduck.net>
00342  *   Charles Lepple <clepple+libhid@ghz.cc>
00343  *   Arnaud Quette <arnaud.quette@free.fr> && <arnaud.quette@mgeups.com>
00344  * and distributed under the terms of the GNU General Public License.
00345  * See the file ./COPYING in the source distribution for more information.
00346  *
00347  * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
00348  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES
00349  * OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00350  */

Generated on Sun Mar 30 15:28:24 2008 for libhid by  doxygen 1.5.1