1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-03-15 07:29:15 +01:00

OP-334 USB HID now working again on mac

git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@3060 ebee16cc-31ac-478f-84a7-5cbb03baadba
This commit is contained in:
peabody124 2011-03-22 11:50:26 +00:00 committed by peabody124
parent 183ca03cc9
commit 593ccfad7b
2 changed files with 189 additions and 39 deletions

View File

@ -31,27 +31,12 @@
#include "rawhid_global.h"
#include <QThread>
struct USBPortInfo {
QString friendName; ///< Friendly name.
QString physName;
QString enumName; ///< It seems its the only one with meaning
QString serialNumber; // As a string as it can be anything, really...
QString manufacturer;
QString product;
QString devicePath; //only has meaning on windows
int UsagePage;
int Usage;
int vendorID; ///< Vendor ID.
int productID; ///< Product ID
int bcdDevice;
};
#include <QMutex>
// Depending on the OS, we'll need different things:
#if defined( Q_OS_MAC)
// TODO
#include <IOKit/IOKitLib.h>
#include <IOKit/hid/IOHIDLib.h>
#elif defined(Q_OS_UNIX)
#include <libudev.h>
@ -97,6 +82,25 @@ protected:
#endif
#endif
struct USBPortInfo {
//QString friendName; ///< Friendly name.
//QString physName;
//QString enumName; ///< It seems its the only one with meaning
QString serialNumber; // As a string as it can be anything, really...
QString manufacturer;
QString product;
#if defined(Q_OS_WIN32)
QString devicePath; //only has meaning on windows
#elif defined(Q_OS_MAC)
IOHIDDeviceRef dev_handle;
#endif
int UsagePage;
int Usage;
int vendorID; ///< Vendor ID.
int productID; ///< Product ID
int bcdDevice;
};
/**
* A monitoring thread which will wait for device events.
*/
@ -154,14 +158,23 @@ private slots:
private:
//! Mutex for modifying the list of available devices
QMutex * listMutex;
//! List of known devices maintained by callbacks
QList<USBPortInfo> knowndevices;
Q_DISABLE_COPY(USBMonitor)
static USBMonitor *m_instance;
// Depending on the OS, we'll need different things:
#if defined( Q_OS_MAC)
// TODO
static void attach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev);
static void detach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev);
void addDevice(USBPortInfo info);
void removeDevice(IOHIDDeviceRef dev);
IOHIDManagerRef hid_manager;
#elif defined(Q_OS_UNIX)
struct udev *context;
struct udev_monitor *monitor;
@ -169,7 +182,6 @@ private:
USBPortInfo makePortInfo(struct udev_device *dev);
#elif defined (Q_OS_WIN32)
GUID guid_hid;
QList<USBPortInfo> knowndevices;
void setUpNotifications();
/*!
* Get specific property from registry.

View File

@ -27,10 +27,64 @@
#include "usbmonitor.h"
#include <IOKit/IOKitLib.h>
#include <IOKit/hid/IOHIDLib.h>
#include <CoreFoundation/CFString.h>
#include <CoreFoundation/CFArray.h>
#include <QMutexLocker>
#include <QDebug>
#define printf qDebug
//! Local helper functions
static bool HID_GetIntProperty(IOHIDDeviceRef dev, CFStringRef property, int * value);
static bool HID_GetStrProperty(IOHIDDeviceRef dev, CFStringRef property, QString & value);
/**
Initialize the USB monitor here
*/
USBMonitor::USBMonitor(QObject *parent): QThread(parent) {
hid_manager=NULL;
CFMutableDictionaryRef dict;
CFNumberRef num;
IOReturn ret;
m_instance = this;
listMutex = new QMutex();
knowndevices.clear();
hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
if (hid_manager == NULL || CFGetTypeID(hid_manager) != IOHIDManagerGetTypeID()) {
if (hid_manager) CFRelease(hid_manager);
Q_ASSERT(0);
}
// No matching filter
IOHIDManagerSetDeviceMatching(hid_manager, NULL);
// set up a callbacks for device attach & detach
IOHIDManagerScheduleWithRunLoop(hid_manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
IOHIDManagerRegisterDeviceMatchingCallback(hid_manager, attach_callback, NULL);
IOHIDManagerRegisterDeviceRemovalCallback(hid_manager, detach_callback, NULL);
ret = IOHIDManagerOpen(hid_manager, kIOHIDOptionsTypeNone);
if (ret != kIOReturnSuccess) {
IOHIDManagerUnscheduleFromRunLoop(hid_manager,
CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
CFRelease(hid_manager);
return;
}
start();
}
USBMonitor::~USBMonitor()
{
//if(hid_manager != NULL)
// IOHIDManagerUnscheduleFromRunLoop(hid_manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
quit();
}
void USBMonitor::deviceEventReceived() {
qDebug() << "Device event";
@ -44,20 +98,59 @@ USBMonitor* USBMonitor::instance()
USBMonitor* USBMonitor::m_instance = 0;
void USBMonitor::removeDevice(IOHIDDeviceRef dev) {
//QMutexLocker locker(listMutex);
for( int i = 0; i < knowndevices.length(); i++) {
USBPortInfo port = knowndevices.at(i);
if(port.dev_handle == dev) {
qDebug() << "Found device to remove";
knowndevices.removeAt(i);
emit deviceRemoved(port);
return;
}
}
/**
Initialize the USB monitor here
*/
USBMonitor::USBMonitor(QObject *parent): QThread(parent) {
qDebug() << "TODO: implement the Mac version of USB Monitor!!!";
start(); // Start the thread event loop so that the socketnotifier works
}
USBMonitor::~USBMonitor()
/**
* @brief Static callback for the USB driver to indicate device removed
*/
void USBMonitor::detach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev)
{
quit();
//instance()->removeDevice(dev);
}
void USBMonitor::addDevice(USBPortInfo info) {
//QMutexLocker locker(listMutex);
knowndevices.append(info);
emit deviceDiscovered(info);
}
void USBMonitor::attach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev)
{
bool got_properties = true;
CFTypeRef prop;
USBPortInfo deviceInfo;
deviceInfo.dev_handle = dev;
// Populate the device info structure
got_properties &= HID_GetIntProperty(dev, CFSTR( kIOHIDVendorIDKey ), &deviceInfo.vendorID);
got_properties &= HID_GetIntProperty(dev, CFSTR( kIOHIDProductIDKey ), &deviceInfo.productID);
got_properties &= HID_GetIntProperty(dev, CFSTR( kIOHIDVersionNumberKey ), &deviceInfo.bcdDevice);
got_properties &= HID_GetStrProperty(dev, CFSTR( kIOHIDSerialNumberKey ), deviceInfo.serialNumber);
got_properties &= HID_GetStrProperty(dev, CFSTR( kIOHIDProductKey ), deviceInfo.product);
got_properties &= HID_GetStrProperty(dev, CFSTR( kIOHIDManufacturerKey ), deviceInfo.manufacturer);
// TOOD: Eventually want to take array of usages if devices start needing that
got_properties &= HID_GetIntProperty(dev, CFSTR( kIOHIDPrimaryUsageKey ), &deviceInfo.Usage);
got_properties &= HID_GetIntProperty(dev, CFSTR( kIOHIDPrimaryUsagePageKey ), &deviceInfo.UsagePage);
qDebug() << "New device HAH";
if(got_properties) {
qDebug() << "New device";
instance()->addDevice(deviceInfo);
}
}
/**
@ -65,16 +158,21 @@ Returns a list of all currently available devices
*/
QList<USBPortInfo> USBMonitor::availableDevices()
{
QList<USBPortInfo> devicesList;
return devicesList;
//QMutexLocker locker(listMutex);
qDebug() << "Queried available devices. Count: " << knowndevices.count();
return knowndevices;
}
/**
Be a bit more picky and ask only for a specific type of device:
On OpenPilot, the bcdDeviceLSB indicates the run state: bootloader or running.
bcdDeviceMSB indicates the board model.
* @brief Be a bit more picky and ask only for a specific type of device:
* @param[in] vid VID to screen or -1 to ignore
* @param[in] pid PID to screen or -1 to ignore
* @param[in] bcdDeviceMSB MSB of bcdDevice to screen or -1 to ignore
* @param[in] bcdDeviceLSB LSB of bcdDevice to screen or -1 to ignore
* @return List of USBPortInfo that meet this criterion
* @note
* On OpenPilot, the bcdDeviceLSB indicates the run state: bootloader or running.
* bcdDeviceMSB indicates the board model.
*/
QList<USBPortInfo> USBMonitor::availableDevices(int vid, int pid, int bcdDeviceMSB, int bcdDeviceLSB)
{
@ -83,8 +181,48 @@ QList<USBPortInfo> USBMonitor::availableDevices(int vid, int pid, int bcdDeviceM
foreach (USBPortInfo port, allPorts) {
if((port.vendorID==vid || vid==-1) && (port.productID==pid || pid==-1) && ((port.bcdDevice>>8)==bcdDeviceMSB || bcdDeviceMSB==-1) &&
( (port.bcdDevice&0x00ff) ==bcdDeviceLSB || bcdDeviceLSB==-1))
( (port.bcdDevice&0x00ff) ==bcdDeviceLSB || bcdDeviceLSB==-1))
thePortsWeWant.append(port);
}
qDebug() << "Queried filtered available devices. Count: " << thePortsWeWant.count();
return thePortsWeWant;
}
/**
* @brief Helper function get get a HID integer property
* @param[in] dev Device reference
* @param[in] property The property to get (constants defined in IOKIT)
* @param[out] value Pointer to integer to set
* @return True if successful, false otherwise
*/
static bool HID_GetIntProperty(IOHIDDeviceRef dev, CFStringRef property, int * value) {
CFTypeRef prop = IOHIDDeviceGetProperty(dev, property);
if (prop) {
if (CFNumberGetTypeID() == CFGetTypeID(prop)) { // if a number
CFNumberGetValue((CFNumberRef) prop, kCFNumberSInt32Type, value);
return true;
}
}
return false;
}
/**
* @brief Helper function get get a HID string property
* @param[in] dev Device reference
* @param[in] property The property to get (constants defined in IOKIT)
* @param[out] value The QString to set
* @return True if successful, false otherwise
*/
static bool HID_GetStrProperty(IOHIDDeviceRef dev, CFStringRef property, QString & value) {
CFTypeRef prop = IOHIDDeviceGetProperty(dev, property);
if (prop) {
if (CFStringGetTypeID() == CFGetTypeID(prop)) { // if a string
char buffer[2550];
bool success = CFStringGetCString ( (CFStringRef) prop, buffer, sizeof(buffer), kCFStringEncodingMacRoman );
value = QString(buffer);
return success;
}
}
return false;
}