add usb_get_driver_np() support in libusb driver, de-magic some numbers
authorMark Cannon <vyhdycokio@gmail.com>
Thu, 17 Mar 2011 20:33:15 +0000 (16:33 -0400)
committerCarl Myers <cmyers@cmyers.org>
Sun, 20 Mar 2011 04:51:06 +0000 (21:51 -0700)
src/arch/USB/USBDriver_Impl_Libusb.cpp

index 85a3c9c..ce36be3 100644 (file)
@@ -1,7 +1,11 @@
 #include "global.h"
 #include "RageLog.h"
 #include "USBDriver_Impl_Libusb.h"
+#include <cerrno>
+
+extern "C" {
 #include <usb.h>
+}
 
 USBDriver_Impl_Libusb::USBDriver_Impl_Libusb()
 {
@@ -21,8 +25,7 @@ static struct usb_device *FindDevice( int iVendorID, int iProductID )
                        if( iVendorID == dev->descriptor.idVendor && iProductID == dev->descriptor.idProduct )
                                return dev;
 
-       // fall through
-       LOG->Trace( "FindDevice() found no matches." );
+       LOG->Trace( "FindDevice(): no match for VID 0x%04x, PID 0x%04x.", iVendorID, iProductID );
        return NULL;
 }
 
@@ -60,26 +63,36 @@ bool USBDriver_Impl_Libusb::Open( int iVendorID, int iProductID )
        }
 
 #ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
-               // The device may be claimed by a kernel driver. Attempt to reclaim it.
-               for( unsigned i = 0; i < dev->config->bNumInterfaces; i++ )
+       // The device may be claimed by a kernel driver. Attempt to reclaim it.
+
+       for( unsigned iface = 0; iface < dev->config->bNumInterfaces; iface++ )
+       {
+               int iResult = usb_detach_kernel_driver_np( m_pHandle, iface );
+
+               // no attached driver, no error -- ignore these
+               if( iResult == -ENODATA || iResult == 0 )
+                       continue;
+
+               /* we have an error we can't handle; try and get more info. */
+               LOG->Warn( "usb_detach_kernel_driver_np: %s\n", usb_strerror() );
+
+
+#ifdef LIBUSB_HAS_GET_DRIVER_NP
+               // on EPERM, a driver exists and we can't detach - report which one
+               if( iResult == -EPERM )
                {
-                       int iResult = usb_detach_kernel_driver_np( m_pHandle, i );
-
-                       switch( iResult )
-                       {
-                       case -61:       // "No data available" (no driver attached) - continue
-                       case 0:         // no error
-                               continue;
-                               break;
-                       default:        // unhandled error
-                               LOG->Warn( "Libusb: usb_detach_kernel_driver_np: %s", usb_strerror() );
-                               Close();
-                               return false;
-                               break;
-                       }
+                       char szDriverName[16];
+                       strcpy( szDriverName, "(unknown)" );
+                       usb_get_driver_np(m_pHandle, iface, szDriverName, 16);
+
+                       LOG->Warn( "(cannot detach kernel driver \"%s\")", szDriverName );
                }
+#endif // LIBUSB_HAS_GET_DRIVER_NP
 
-#endif
+               Close();
+               return false;
+       }
+#endif // LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
 
        if ( !SetConfiguration(dev->config->bConfigurationValue) )
        {