Update ControllerListener_mac.cpp to our style guidelines
This commit is contained in:
parent
bc22754f8c
commit
c522173296
1 changed files with 59 additions and 54 deletions
|
|
@ -1,10 +1,17 @@
|
||||||
#include "ControllerListener.h"
|
//
|
||||||
|
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
|
||||||
|
//
|
||||||
|
// Copyright: See COPYING file that comes with this distribution
|
||||||
|
//
|
||||||
|
//
|
||||||
|
#include "service/ControllerListener.h"
|
||||||
|
|
||||||
#include <CoreFoundation/CoreFoundation.h>
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
#include <IOKit/IOKitLib.h>
|
#include <IOKit/IOKitLib.h>
|
||||||
#include <IOKit/IOMessage.h>
|
#include <IOKit/IOMessage.h>
|
||||||
#include <IOKit/IOCFPlugIn.h>
|
#include <IOKit/IOCFPlugIn.h>
|
||||||
#include <IOKit/usb/IOUSBLib.h>
|
#include <IOKit/usb/IOUSBLib.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
class TellStickData {
|
class TellStickData {
|
||||||
public:
|
public:
|
||||||
|
|
@ -22,15 +29,14 @@ public:
|
||||||
io_iterator_t gAddedIter;
|
io_iterator_t gAddedIter;
|
||||||
TelldusCore::EventRef event;
|
TelldusCore::EventRef event;
|
||||||
bool running;
|
bool running;
|
||||||
|
|
||||||
void addUsbFilter(int vid, int pid);
|
void addUsbFilter(int vid, int pid);
|
||||||
static void DeviceAdded(void *refCon, io_iterator_t iterator);
|
static void DeviceAdded(void *refCon, io_iterator_t iterator);
|
||||||
static void DeviceNotification(void *refCon, io_service_t service, natural_t messageType, void *messageArgument);
|
static void DeviceNotification(void *refCon, io_service_t service, natural_t messageType, void *messageArgument);
|
||||||
};
|
};
|
||||||
|
|
||||||
ControllerListener::ControllerListener(TelldusCore::EventRef event)
|
ControllerListener::ControllerListener(TelldusCore::EventRef event)
|
||||||
:Thread()
|
:Thread() {
|
||||||
{
|
|
||||||
d = new PrivateData;
|
d = new PrivateData;
|
||||||
d->event = event;
|
d->event = event;
|
||||||
d->running = true;
|
d->running = true;
|
||||||
|
|
@ -48,135 +54,134 @@ ControllerListener::~ControllerListener() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllerListener::run() {
|
void ControllerListener::run() {
|
||||||
CFRunLoopSourceRef runLoopSource;
|
CFRunLoopSourceRef runLoopSource;
|
||||||
|
|
||||||
d->gNotifyPort = IONotificationPortCreate(kIOMasterPortDefault);
|
d->gNotifyPort = IONotificationPortCreate(kIOMasterPortDefault);
|
||||||
runLoopSource = IONotificationPortGetRunLoopSource(d->gNotifyPort);
|
runLoopSource = IONotificationPortGetRunLoopSource(d->gNotifyPort);
|
||||||
|
|
||||||
d->gRunLoop = CFRunLoopGetCurrent();
|
d->gRunLoop = CFRunLoopGetCurrent();
|
||||||
CFRunLoopAddSource(d->gRunLoop, runLoopSource, kCFRunLoopDefaultMode);
|
CFRunLoopAddSource(d->gRunLoop, runLoopSource, kCFRunLoopDefaultMode);
|
||||||
|
|
||||||
d->addUsbFilter(0x1781, 0x0c30);
|
d->addUsbFilter(0x1781, 0x0c30);
|
||||||
d->addUsbFilter(0x1781, 0x0c31);
|
d->addUsbFilter(0x1781, 0x0c31);
|
||||||
|
|
||||||
// Race check, if destructor was called really close to thread init,
|
// Race check, if destructor was called really close to thread init,
|
||||||
// running might have gone false. Make sure we don't get stuck
|
// running might have gone false. Make sure we don't get stuck
|
||||||
if(d->running)
|
if (d->running) {
|
||||||
CFRunLoopRun();
|
CFRunLoopRun();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllerListener::PrivateData::addUsbFilter(int vid, int pid) {
|
void ControllerListener::PrivateData::addUsbFilter(int vid, int pid) {
|
||||||
CFNumberRef numberRef;
|
CFNumberRef numberRef;
|
||||||
kern_return_t kr;
|
kern_return_t kr;
|
||||||
CFMutableDictionaryRef matchingDict;
|
CFMutableDictionaryRef matchingDict;
|
||||||
|
|
||||||
matchingDict = IOServiceMatching(kIOUSBDeviceClassName); // Interested in instances of class
|
matchingDict = IOServiceMatching(kIOUSBDeviceClassName); // Interested in instances of class
|
||||||
// IOUSBDevice and its subclasses
|
// IOUSBDevice and its subclasses
|
||||||
if (matchingDict == NULL) {
|
if (matchingDict == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a CFNumber for the idVendor and set the value in the dictionary
|
// Create a CFNumber for the idVendor and set the value in the dictionary
|
||||||
numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vid);
|
numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vid);
|
||||||
CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID), numberRef);
|
CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID), numberRef);
|
||||||
CFRelease(numberRef);
|
CFRelease(numberRef);
|
||||||
|
|
||||||
// Create a CFNumber for the idProduct and set the value in the dictionary
|
// Create a CFNumber for the idProduct and set the value in the dictionary
|
||||||
numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &pid);
|
numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &pid);
|
||||||
CFDictionarySetValue(matchingDict, CFSTR(kUSBProductID), numberRef);
|
CFDictionarySetValue(matchingDict, CFSTR(kUSBProductID), numberRef);
|
||||||
CFRelease(numberRef);
|
CFRelease(numberRef);
|
||||||
|
|
||||||
// Now set up a notification to be called when a device is first matched by I/O Kit.
|
|
||||||
kr = IOServiceAddMatchingNotification(gNotifyPort, // notifyPort
|
|
||||||
kIOFirstMatchNotification, // notificationType
|
|
||||||
matchingDict, // matching
|
|
||||||
PrivateData::DeviceAdded, // callback
|
|
||||||
this, // refCon
|
|
||||||
&gAddedIter // notification
|
|
||||||
);
|
|
||||||
// Iterate once to get already-present devices and arm the notification
|
|
||||||
PrivateData::DeviceAdded(this, gAddedIter);
|
|
||||||
|
|
||||||
|
// Now set up a notification to be called when a device is first matched by I/O Kit.
|
||||||
|
kr = IOServiceAddMatchingNotification(gNotifyPort, // notifyPort
|
||||||
|
kIOFirstMatchNotification, // notificationType
|
||||||
|
matchingDict, // matching
|
||||||
|
PrivateData::DeviceAdded, // callback
|
||||||
|
this, // refCon
|
||||||
|
&gAddedIter // notification
|
||||||
|
);
|
||||||
|
// Iterate once to get already-present devices and arm the notification
|
||||||
|
PrivateData::DeviceAdded(this, gAddedIter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllerListener::PrivateData::DeviceNotification(void *refCon, io_service_t service, natural_t messageType, void *messageArgument) {
|
void ControllerListener::PrivateData::DeviceNotification(void *refCon, io_service_t service, natural_t messageType, void *messageArgument) {
|
||||||
kern_return_t kr;
|
kern_return_t kr;
|
||||||
|
|
||||||
if (messageType != kIOMessageServiceIsTerminated) {
|
if (messageType != kIOMessageServiceIsTerminated) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TellStickData *tsd = reinterpret_cast<TellStickData*> (refCon);
|
TellStickData *tsd = reinterpret_cast<TellStickData*> (refCon);
|
||||||
if (!tsd) {
|
if (!tsd) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CFIndex size = CFStringGetLength(tsd->serialNumber);
|
CFIndex size = CFStringGetLength(tsd->serialNumber);
|
||||||
char *s = new char[size+1];
|
char *s = new char[size+1];
|
||||||
CFStringGetCString(tsd->serialNumber, s, size+1, kCFStringEncodingASCII);
|
CFStringGetCString(tsd->serialNumber, s, size+1, kCFStringEncodingASCII);
|
||||||
std::string serial(s); //Copy the string to the stack
|
std::string serial(s); // Copy the string to the stack
|
||||||
delete[] s;
|
delete[] s;
|
||||||
|
|
||||||
ControllerChangeEventData *data = new ControllerChangeEventData;
|
ControllerChangeEventData *data = new ControllerChangeEventData;
|
||||||
data->vid = tsd->vid;
|
data->vid = tsd->vid;
|
||||||
data->pid = tsd->pid;
|
data->pid = tsd->pid;
|
||||||
data->inserted = false;
|
data->inserted = false;
|
||||||
tsd->event->signal(data);
|
tsd->event->signal(data);
|
||||||
|
|
||||||
// Free the data we're no longer using now that the device is going away
|
// Free the data we're no longer using now that the device is going away
|
||||||
CFRelease(tsd->serialNumber);
|
CFRelease(tsd->serialNumber);
|
||||||
|
|
||||||
kr = IOObjectRelease(tsd->notification);
|
kr = IOObjectRelease(tsd->notification);
|
||||||
|
|
||||||
delete tsd;
|
delete tsd;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllerListener::PrivateData::DeviceAdded(void *refCon, io_iterator_t iterator) {
|
void ControllerListener::PrivateData::DeviceAdded(void *refCon, io_iterator_t iterator) {
|
||||||
io_service_t usbDevice;
|
io_service_t usbDevice;
|
||||||
kern_return_t kr;
|
kern_return_t kr;
|
||||||
|
|
||||||
PrivateData *pd = reinterpret_cast<PrivateData*> (refCon);
|
PrivateData *pd = reinterpret_cast<PrivateData*> (refCon);
|
||||||
|
|
||||||
while ((usbDevice = IOIteratorNext(iterator))) {
|
while ((usbDevice = IOIteratorNext(iterator))) {
|
||||||
TellStickData *tsd = new TellStickData;
|
TellStickData *tsd = new TellStickData;
|
||||||
tsd->event = pd->event;
|
tsd->event = pd->event;
|
||||||
|
|
||||||
// Get the serial number
|
// Get the serial number
|
||||||
CFStringRef serialRef = reinterpret_cast<CFStringRef>(IORegistryEntryCreateCFProperty( usbDevice, CFSTR("USB Serial Number" ), kCFAllocatorDefault, 0 ));
|
CFStringRef serialRef = reinterpret_cast<CFStringRef>(IORegistryEntryCreateCFProperty( usbDevice, CFSTR("USB Serial Number" ), kCFAllocatorDefault, 0 ));
|
||||||
if (serialRef == NULL) {
|
if (serialRef == NULL) {
|
||||||
//No serial number, we cannot continue. Sorry
|
// No serial number, we cannot continue. Sorry
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CFNumberRef vidRef = reinterpret_cast<CFNumberRef> (IORegistryEntryCreateCFProperty(usbDevice, CFSTR("idVendor"), kCFAllocatorDefault, 0));
|
CFNumberRef vidRef = reinterpret_cast<CFNumberRef> (IORegistryEntryCreateCFProperty(usbDevice, CFSTR("idVendor"), kCFAllocatorDefault, 0));
|
||||||
if (vidRef) {
|
if (vidRef) {
|
||||||
CFNumberGetValue(vidRef, kCFNumberIntType, &(tsd->vid));
|
CFNumberGetValue(vidRef, kCFNumberIntType, &(tsd->vid));
|
||||||
CFRelease(vidRef);
|
CFRelease(vidRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
CFNumberRef pidRef = reinterpret_cast<CFNumberRef> (IORegistryEntryCreateCFProperty(usbDevice, CFSTR("idProduct"), kCFAllocatorDefault, 0));
|
CFNumberRef pidRef = reinterpret_cast<CFNumberRef> (IORegistryEntryCreateCFProperty(usbDevice, CFSTR("idProduct"), kCFAllocatorDefault, 0));
|
||||||
if (pidRef) {
|
if (pidRef) {
|
||||||
CFNumberGetValue(pidRef, kCFNumberIntType, &(tsd->pid));
|
CFNumberGetValue(pidRef, kCFNumberIntType, &(tsd->pid));
|
||||||
CFRelease(pidRef);
|
CFRelease(pidRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
CFStringRef serialNumberAsCFString = CFStringCreateCopy(kCFAllocatorDefault, serialRef);
|
CFStringRef serialNumberAsCFString = CFStringCreateCopy(kCFAllocatorDefault, serialRef);
|
||||||
tsd->serialNumber = serialNumberAsCFString;
|
tsd->serialNumber = serialNumberAsCFString;
|
||||||
CFRelease(serialRef);
|
CFRelease(serialRef);
|
||||||
|
|
||||||
// Register for an interest notification of this device being removed. Use a reference to our
|
// Register for an interest notification of this device being removed. Use a reference to our
|
||||||
// private data as the refCon which will be passed to the notification callback.
|
// private data as the refCon which will be passed to the notification callback.
|
||||||
kr = IOServiceAddInterestNotification(pd->gNotifyPort, usbDevice, kIOGeneralInterest, DeviceNotification, tsd, &(tsd->notification));
|
kr = IOServiceAddInterestNotification(pd->gNotifyPort, usbDevice, kIOGeneralInterest, DeviceNotification, tsd, &(tsd->notification));
|
||||||
|
|
||||||
CFIndex size = CFStringGetLength(serialNumberAsCFString);
|
CFIndex size = CFStringGetLength(serialNumberAsCFString);
|
||||||
char *s = new char[size+1];
|
char *s = new char[size+1];
|
||||||
CFStringGetCString(serialNumberAsCFString, s, size+1, kCFStringEncodingASCII);
|
CFStringGetCString(serialNumberAsCFString, s, size+1, kCFStringEncodingASCII);
|
||||||
std::string serial(s); //Copy the string to the stack
|
std::string serial(s); // Copy the string to the stack
|
||||||
delete[] s;
|
delete[] s;
|
||||||
|
|
||||||
kr = IOObjectRelease(usbDevice);
|
kr = IOObjectRelease(usbDevice);
|
||||||
|
|
||||||
ControllerChangeEventData *data = new ControllerChangeEventData;
|
ControllerChangeEventData *data = new ControllerChangeEventData;
|
||||||
data->vid = tsd->vid;
|
data->vid = tsd->vid;
|
||||||
data->pid = tsd->pid;
|
data->pid = tsd->pid;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue