brought mac in sync from udev edits

This commit is contained in:
Jack Andersen 2015-04-30 15:11:25 -10:00
parent 1125e20b6e
commit d32dbbd694
4 changed files with 110 additions and 170 deletions

View File

@ -19,15 +19,6 @@ HEADERS += \
$$PWD/src/inputdev/IHIDDevice.hpp \ $$PWD/src/inputdev/IHIDDevice.hpp \
$$PWD/include/inputdev/SDeviceSignature.hpp $$PWD/include/inputdev/SDeviceSignature.hpp
unix:!macx:HEADERS += \
$$PWD/include/x11/CGLXContext.hpp
macx:HEADERS += \
$$PWD/include/mac/CCGLContext.hpp
win32:HEADERS += \
$$PWD/include/win/CWGLContext.hpp
SOURCES += \ SOURCES += \
$$PWD/InputDeviceClasses.cpp \ $$PWD/InputDeviceClasses.cpp \
$$PWD/src/CSurface.cpp \ $$PWD/src/CSurface.cpp \
@ -40,27 +31,45 @@ SOURCES += \
$$PWD/src/inputdev/CDualshockPad.cpp \ $$PWD/src/inputdev/CDualshockPad.cpp \
$$PWD/src/inputdev/CGenericPad.cpp \ $$PWD/src/inputdev/CGenericPad.cpp \
$$PWD/src/inputdev/CDeviceBase.cpp \ $$PWD/src/inputdev/CDeviceBase.cpp \
$$PWD/src/inputdev/CHIDListenerUdev.cpp \
$$PWD/src/inputdev/CHIDDeviceUdev.cpp \
$$PWD/src/inputdev/SDeviceSignature.cpp $$PWD/src/inputdev/SDeviceSignature.cpp
unix:!macx:SOURCES += \ unix:!macx {
$$PWD/src/x11/CGLXContext.cpp HEADERS += \
$$PWD/include/x11/CGLXContext.hpp
macx:SOURCES += \ SOURCES += \
$$PWD/src/mac/CCGLContext.cpp \ $$PWD/src/x11/CGLXContext.cpp
$$PWD/src/inputdev/CHIDDeviceIOKit.cpp \ }
$$PWD/src/inputdev/CHIDListenerIOKit.cpp
macx:OBJECTIVE_SOURCES += \ linux {
$$PWD/src/mac/CCGLCocoaView.mm \ SOURCES += \
$$PWD/src/inputdev/CHIDListenerUdev.cpp \
$$PWD/src/inputdev/CHIDDeviceUdev.cpp
LIBS += -ludev
}
win32:SOURCES += \ macx {
$$PWD/src/win/CWGLContext.cpp \ HEADERS += \
$$PWD/src/inputdev/CHIDDeviceWin32.cpp \ $$PWD/include/mac/CCGLContext.hpp
$$PWD/src/inputdev/CHIDListenerWin32.cpp
SOURCES += \
$$PWD/src/mac/CCGLContext.cpp \
$$PWD/src/inputdev/CHIDDeviceIOKit.cpp \
$$PWD/src/inputdev/CHIDListenerIOKit.cpp
OBJECTIVE_SOURCES += \
$$PWD/src/mac/CCGLCocoaView.mm
}
win32 {
HEADERS += \
$$PWD/include/win/CWGLContext.hpp
SOURCES += \
$$PWD/src/win/CWGLContext.cpp \
$$PWD/src/inputdev/CHIDDeviceWin32.cpp \
$$PWD/src/inputdev/CHIDListenerWin32.cpp
}
INCLUDEPATH += $$PWD/include INCLUDEPATH += $$PWD/include
unix:!macx:LIBS += -ludev

View File

@ -25,7 +25,6 @@ class CHIDDeviceIOKit final : public IHIDDevice
std::mutex m_initMutex; std::mutex m_initMutex;
std::condition_variable m_initCond; std::condition_variable m_initCond;
std::thread* m_thread; std::thread* m_thread;
CFRunLoopRef m_runLoop = NULL;
bool _sendUSBInterruptTransfer(uint8_t pipe, const uint8_t* data, size_t length) bool _sendUSBInterruptTransfer(uint8_t pipe, const uint8_t* data, size_t length)
{ {
@ -50,7 +49,7 @@ class CHIDDeviceIOKit final : public IHIDDevice
return 0; return 0;
} }
static void _threadProcLL(CHIDDeviceIOKit* device) static void _threadProcUSBLL(CHIDDeviceIOKit* device)
{ {
char thrName[128]; char thrName[128];
snprintf(thrName, 128, "%s Transfer Thread", device->m_token.getProductName().c_str()); snprintf(thrName, 128, "%s Transfer Thread", device->m_token.getProductName().c_str());
@ -148,6 +147,7 @@ class CHIDDeviceIOKit final : public IHIDDevice
device->m_initCond.notify_one(); device->m_initCond.notify_one();
/* Start transfer loop */ /* Start transfer loop */
device->m_devImp.initialCycle();
while (device->m_runningTransferLoop) while (device->m_runningTransferLoop)
device->m_devImp.transferCycle(); device->m_devImp.transferCycle();
device->m_devImp.finalCycle(); device->m_devImp.finalCycle();
@ -160,6 +160,23 @@ class CHIDDeviceIOKit final : public IHIDDevice
} }
static void _threadProcBTLL(CHIDDeviceIOKit* device)
{
std::unique_lock<std::mutex> lk(device->m_initMutex);
/* Return control to main thread */
device->m_runningTransferLoop = true;
lk.unlock();
device->m_initCond.notify_one();
/* Start transfer loop */
device->m_devImp.initialCycle();
while (device->m_runningTransferLoop)
device->m_devImp.transferCycle();
device->m_devImp.finalCycle();
}
static void _inputReport(CHIDDeviceIOKit* device, static void _inputReport(CHIDDeviceIOKit* device,
IOReturn result, IOReturn result,
@ -178,49 +195,29 @@ class CHIDDeviceIOKit final : public IHIDDevice
device->_deviceDisconnected(); device->_deviceDisconnected();
} }
static void _threadProcHL(CHIDDeviceIOKit* device) static void _threadProcHID(CHIDDeviceIOKit* device)
{ {
char thrName[128]; std::unique_lock<std::mutex> lk(device->m_initMutex);
snprintf(thrName, 128, "%s HID Thread", device->m_token.getProductName().c_str());
pthread_setname_np(thrName);
__block std::unique_lock<std::mutex> lk(device->m_initMutex);
device->m_runLoop = CFRunLoopGetCurrent();
CFRunLoopAddObserver(device->m_runLoop,
CFRunLoopObserverCreateWithHandler(kCFAllocatorDefault, kCFRunLoopEntry, false, 0,
^(CFRunLoopObserverRef, CFRunLoopActivity) {
lk.unlock();
device->m_initCond.notify_one();
}), kCFRunLoopCommonModes);
uint8_t* inputBuf = new uint8_t[MAX_REPORT_SIZE]; /* Return control to main thread */
io_registry_entry_t devServ = IORegistryEntryFromPath(kIOMasterPortDefault, device->m_devPath.c_str()); device->m_runningTransferLoop = true;
IOHIDDeviceRef dev = IOHIDDeviceCreate(kCFAllocatorDefault, devServ); lk.unlock();
IOHIDDeviceRegisterInputReportCallback(dev, inputBuf, MAX_REPORT_SIZE, device->m_initCond.notify_one();
(IOHIDReportCallback)_inputReport, device);
IOHIDDeviceRegisterRemovalCallback(dev, (IOHIDCallback)_disconnect, device); /* Start transfer loop */
IOHIDDeviceScheduleWithRunLoop(dev, device->m_runLoop, kCFRunLoopDefaultMode); device->m_devImp.initialCycle();
IOHIDDeviceOpen(dev, kIOHIDOptionsTypeNone); while (device->m_runningTransferLoop)
CFRunLoopRun(); device->m_devImp.transferCycle();
if (device->m_runLoop) device->m_devImp.finalCycle();
IOHIDDeviceClose(dev, kIOHIDOptionsTypeNone);
CFRelease(dev);
} }
void _deviceDisconnected() void _deviceDisconnected()
{ {
CFRunLoopRef rl = m_runLoop;
m_runLoop = NULL;
if (rl)
CFRunLoopStop(rl);
m_runningTransferLoop = false; m_runningTransferLoop = false;
} }
bool _sendHIDReport(const uint8_t* data, size_t length) bool _sendHIDReport(const uint8_t* data, size_t length)
{ {
if (m_runLoop)
{
}
return false; return false;
} }
@ -233,19 +230,22 @@ public:
{ {
devImp.m_hidDev = this; devImp.m_hidDev = this;
std::unique_lock<std::mutex> lk(m_initMutex); std::unique_lock<std::mutex> lk(m_initMutex);
if (lowLevel) CDeviceToken::TDeviceType dType = token.getDeviceType();
m_thread = new std::thread(_threadProcLL, this); if (dType == CDeviceToken::DEVTYPE_USB)
m_thread = new std::thread(_threadProcUSBLL, this);
else if (dType == CDeviceToken::DEVTYPE_BLUETOOTH)
m_thread = new std::thread(_threadProcBTLL, this);
else if (dType == CDeviceToken::DEVTYPE_GENERICHID)
m_thread = new std::thread(_threadProcHID, this);
else else
m_thread = new std::thread(_threadProcHL, this); throw std::runtime_error("invalid token supplied to device constructor");
m_initCond.wait(lk); m_initCond.wait(lk);
} }
~CHIDDeviceIOKit() ~CHIDDeviceIOKit()
{ {
if (m_runLoop)
CFRunLoopStop(m_runLoop);
m_runningTransferLoop = false; m_runningTransferLoop = false;
m_thread->detach(); m_thread->join();
delete m_thread; delete m_thread;
} }

View File

@ -57,72 +57,12 @@ class CHIDListenerIOKit final : public IHIDListener
CDeviceFinder& m_finder; CDeviceFinder& m_finder;
CFRunLoopRef m_listenerRunLoop; CFRunLoopRef m_listenerRunLoop;
IOHIDManagerRef m_hidManager;
IONotificationPortRef m_llPort; IONotificationPortRef m_llPort;
io_iterator_t m_llAddNotif, m_llRemoveNotif;
bool m_scanningEnabled; bool m_scanningEnabled;
static void deviceConnected(CHIDListenerIOKit* listener, static void devicesConnectedUSBLL(CHIDListenerIOKit* listener,
IOReturn, io_iterator_t iterator)
void*,
IOHIDDeviceRef device)
{
if (!listener->m_scanningEnabled)
return;
io_string_t devPath;
if (IORegistryEntryGetPath(IOHIDDeviceGetService(device), kIOServicePlane, devPath) != 0)
return;
if (listener->m_finder._hasToken(devPath))
return;
CFIndex vid, pid;
CFNumberGetValue((CFNumberRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDVendorIDKey)), kCFNumberCFIndexType, &vid);
CFNumberGetValue((CFNumberRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductIDKey)), kCFNumberCFIndexType, &pid);
CFStringRef manuf = (CFStringRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDManufacturerKey));
CFStringRef product = (CFStringRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey));
listener->m_finder._insertToken(CDeviceToken(vid, pid,
CFStringGetCStringPtr(manuf, kCFStringEncodingUTF8),
CFStringGetCStringPtr(product, kCFStringEncodingUTF8),
devPath));
}
static void deviceDisconnected(CHIDListenerIOKit* listener,
IOReturn ret,
void* sender,
IOHIDDeviceRef device)
{
if (CFRunLoopGetCurrent() != listener->m_listenerRunLoop)
{
CFRunLoopPerformBlock(listener->m_listenerRunLoop, kCFRunLoopDefaultMode, ^{
deviceDisconnected(listener, ret, sender, device);
});
CFRunLoopWakeUp(listener->m_listenerRunLoop);
return;
}
io_string_t devPath;
if (IORegistryEntryGetPath(IOHIDDeviceGetService(device), kIOServicePlane, devPath) != 0)
return;
listener->m_finder._removeToken(devPath);
}
static void applyDevice(IOHIDDeviceRef device, CHIDListenerIOKit* listener)
{
io_string_t devPath;
if (IORegistryEntryGetPath(IOHIDDeviceGetService(device), kIOServicePlane, devPath) != 0)
return;
if (listener->m_finder._hasToken(devPath))
return;
CFIndex vid, pid;
CFNumberGetValue((CFNumberRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDVendorIDKey)), kCFNumberCFIndexType, &vid);
CFNumberGetValue((CFNumberRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductIDKey)), kCFNumberCFIndexType, &pid);
CFStringRef manuf = (CFStringRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDManufacturerKey));
CFStringRef product = (CFStringRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey));
listener->m_finder._insertToken(CDeviceToken(vid, pid,
CFStringGetCStringPtr(manuf, kCFStringEncodingUTF8),
CFStringGetCStringPtr(product, kCFStringEncodingUTF8),
devPath));
}
static void devicesConnectedLL(CHIDListenerIOKit* listener,
io_iterator_t iterator)
{ {
io_object_t obj; io_object_t obj;
while ((obj = IOIteratorNext(iterator))) while ((obj = IOIteratorNext(iterator)))
@ -165,7 +105,12 @@ class CHIDListenerIOKit final : public IHIDListener
getUSBStringDescriptor(dev, vstridx, vstr); getUSBStringDescriptor(dev, vstridx, vstr);
getUSBStringDescriptor(dev, pstridx, pstr); getUSBStringDescriptor(dev, pstridx, pstr);
listener->m_finder._insertToken(CDeviceToken(vid, pid, vstr, pstr, devPath)); if (!listener->m_finder._insertToken(CDeviceToken(CDeviceToken::DEVTYPE_USB,
vid, pid, vstr, pstr, devPath)))
{
/* Matched-insertion failed; see if generic HID interface is available */
/* TODO: Do */
}
//printf("ADDED %08X %s\n", obj, devPath); //printf("ADDED %08X %s\n", obj, devPath);
(*dev)->Release(dev); (*dev)->Release(dev);
@ -175,13 +120,13 @@ class CHIDListenerIOKit final : public IHIDListener
} }
static void devicesDisconnectedLL(CHIDListenerIOKit* listener, static void devicesDisconnectedUSBLL(CHIDListenerIOKit* listener,
io_iterator_t iterator) io_iterator_t iterator)
{ {
if (CFRunLoopGetCurrent() != listener->m_listenerRunLoop) if (CFRunLoopGetCurrent() != listener->m_listenerRunLoop)
{ {
CFRunLoopPerformBlock(listener->m_listenerRunLoop, kCFRunLoopDefaultMode, ^{ CFRunLoopPerformBlock(listener->m_listenerRunLoop, kCFRunLoopDefaultMode, ^{
devicesDisconnectedLL(listener, iterator); devicesDisconnectedUSBLL(listener, iterator);
}); });
CFRunLoopWakeUp(listener->m_listenerRunLoop); CFRunLoopWakeUp(listener->m_listenerRunLoop);
return; return;
@ -203,48 +148,27 @@ public:
: m_finder(finder) : m_finder(finder)
{ {
/* Register HID Manager */ /* Register Low-Level USB Matcher */
m_hidManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDManagerOptionNone);
IOHIDManagerSetDeviceMatching(m_hidManager, NULL);
IOHIDManagerRegisterDeviceMatchingCallback(m_hidManager, (IOHIDDeviceCallback)deviceConnected, this);
IOHIDManagerRegisterDeviceRemovalCallback(m_hidManager, (IOHIDDeviceCallback)deviceDisconnected, this);
m_listenerRunLoop = CFRunLoopGetCurrent(); m_listenerRunLoop = CFRunLoopGetCurrent();
IOHIDManagerScheduleWithRunLoop(m_hidManager, m_listenerRunLoop, kCFRunLoopDefaultMode);
IOReturn ret = IOHIDManagerOpen(m_hidManager, kIOHIDManagerOptionNone);
if (ret != kIOReturnSuccess)
throw std::runtime_error("error establishing IOHIDManager");
/* Initial HID Device Add */
m_scanningEnabled = true;
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, false);
/* Register Low-Level Matcher */
m_llPort = IONotificationPortCreate(kIOMasterPortDefault); m_llPort = IONotificationPortCreate(kIOMasterPortDefault);
CFRunLoopAddSource(m_listenerRunLoop, IONotificationPortGetRunLoopSource(m_llPort), kCFRunLoopDefaultMode); CFRunLoopSourceRef rlSrc = IONotificationPortGetRunLoopSource(m_llPort);
CFRunLoopAddSource(m_listenerRunLoop, rlSrc, kCFRunLoopDefaultMode);
CFMutableDictionaryRef matchDict = IOServiceMatching(kIOUSBDeviceClassName); CFMutableDictionaryRef matchDict = IOServiceMatching(kIOUSBDeviceClassName);
CFIndex nintendoVid = VID_NINTENDO;
CFIndex smashPid = PID_SMASH_ADAPTER;
CFNumberRef nintendoVidNum = CFNumberCreate(kCFAllocatorDefault, kCFNumberCFIndexType, &nintendoVid);
CFNumberRef smashPidNum = CFNumberCreate(kCFAllocatorDefault, kCFNumberCFIndexType, &smashPid);
CFDictionaryAddValue(matchDict, CFSTR(kUSBVendorID), nintendoVidNum);
CFDictionaryAddValue(matchDict, CFSTR(kUSBProductID), smashPidNum);
CFRelease(nintendoVidNum);
CFRelease(smashPidNum);
CFRetain(matchDict); CFRetain(matchDict);
io_iterator_t initialIt; m_scanningEnabled = true;
kern_return_t llRet = kern_return_t llRet =
IOServiceAddMatchingNotification(m_llPort, kIOMatchedNotification, matchDict, IOServiceAddMatchingNotification(m_llPort, kIOMatchedNotification, matchDict,
(IOServiceMatchingCallback)devicesConnectedLL, this, &initialIt); (IOServiceMatchingCallback)devicesConnectedUSBLL, this, &m_llAddNotif);
if (llRet == 0) if (llRet == kIOReturnSuccess)
devicesConnectedLL(this, initialIt); devicesConnectedUSBLL(this, m_llAddNotif);
llRet = llRet =
IOServiceAddMatchingNotification(m_llPort, kIOTerminatedNotification, matchDict, IOServiceAddMatchingNotification(m_llPort, kIOTerminatedNotification, matchDict,
(IOServiceMatchingCallback)devicesDisconnectedLL, this, &initialIt); (IOServiceMatchingCallback)devicesDisconnectedUSBLL, this, &m_llRemoveNotif);
if (llRet == 0) if (llRet == kIOReturnSuccess)
devicesDisconnectedLL(this, initialIt); devicesDisconnectedUSBLL(this, m_llRemoveNotif);
m_scanningEnabled = false; m_scanningEnabled = false;
@ -252,10 +176,9 @@ public:
~CHIDListenerIOKit() ~CHIDListenerIOKit()
{ {
IOHIDManagerUnscheduleFromRunLoop(m_hidManager, m_listenerRunLoop, kCFRunLoopDefaultMode);
IOHIDManagerClose(m_hidManager, kIOHIDManagerOptionNone);
CFRelease(m_hidManager);
CFRunLoopRemoveSource(m_listenerRunLoop, IONotificationPortGetRunLoopSource(m_llPort), kCFRunLoopDefaultMode); CFRunLoopRemoveSource(m_listenerRunLoop, IONotificationPortGetRunLoopSource(m_llPort), kCFRunLoopDefaultMode);
IOObjectRelease(m_llAddNotif);
IOObjectRelease(m_llRemoveNotif);
IONotificationPortDestroy(m_llPort); IONotificationPortDestroy(m_llPort);
} }
@ -274,11 +197,13 @@ public:
/* Manual device scanning */ /* Manual device scanning */
bool scanNow() bool scanNow()
{ {
CFSetRef devs = IOHIDManagerCopyDevices(m_hidManager); io_iterator_t iter;
m_finder.m_tokensLock.lock(); if (IOServiceGetMatchingServices(kIOMasterPortDefault,
CFSetApplyFunction(devs, (CFSetApplierFunction)applyDevice, this); IOServiceMatching(kIOUSBDeviceClassName), &iter) == kIOReturnSuccess)
m_finder.m_tokensLock.unlock(); {
CFRelease(devs); devicesConnectedUSBLL(this, iter);
IOObjectRelease(iter);
}
return true; return true;
} }

View File

@ -2,6 +2,9 @@
#include "CCGLContext.hpp" #include "CCGLContext.hpp"
#include <iostream> #include <iostream>
namespace boo
{
CCGLContext::CCGLContext() CCGLContext::CCGLContext()
: m_minVersion(3), : m_minVersion(3),
m_majVersion(3) m_majVersion(3)
@ -58,4 +61,7 @@ int CCGLContext::blueDepth() const
{ {
return -1; return -1;
} }
}
#endif #endif