Created
August 20, 2012 01:32
-
-
Save dweinstein/3399105 to your computer and use it in GitHub Desktop.
main function for interacting with accessory protocol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// main.cpp | |
// AccessoryMode | |
// | |
// Created by David Weinstein on 07/30/2012. | |
// Copyright (c) 2012 David Weinstein. All rights reserved. | |
// Code based on documentation from apple: Working With USB Device Interfaces | |
// see https://developer.apple.com/library/mac/documentation/DeviceDrivers/Conceptual/USBBook/index.html | |
// | |
// *Important* If your application is sandboxed, it must request the | |
// com.apple.security.device.usb entitlement in order to access USB devices. | |
// | |
#include <CoreFoundation/CoreFoundation.h> | |
#include <IOKit/IOKitLib.h> | |
#include <IOKit/IOMessage.h> | |
#include <IOKit/IOCFPlugIn.h> | |
#include <IOKit/usb/IOUSBLib.h> | |
#include "accessory.h" | |
#define DBGPRINT printf("DEBUG: \"%s\", line %d: ", __FILE__,__LINE__),printf | |
// | |
// vendor / product identifiers for target device | |
// can grab these from e.g., USB Prober.app | |
// the following is for the Samsung Galaxy Nexus Android device | |
// | |
#define kGoogleVendorID 0x18D1 | |
#define kAccessoryProductID 0x2D00 | |
#define kAccessoryADBProductID 0x2D01 | |
//#define kAccessoryADBProductID 0x2D00 | |
#define kNexusVendorID 0x04E8 | |
#define kNexusProductID 0x6860 | |
//#define kNexusProductID 0x685C | |
static IONotificationPortRef gNotifyPort; | |
static io_iterator_t gAddedIter; | |
static CFRunLoopRef gRunLoop; | |
int main(int argc, const char *argv[]) | |
{ | |
CFMutableDictionaryRef matchingDict, matchingDict2; | |
CFRunLoopSourceRef runLoopSource; | |
CFNumberRef numberRef; | |
kern_return_t kr; | |
long usbVendor = kNexusVendorID; | |
long usbProduct = kNexusProductID; | |
long googleUSBVendor = kGoogleVendorID; | |
long googleUSBProduct = kAccessoryADBProductID; | |
sig_t oldHandler; | |
// pick up command line arguments | |
if (argc > 1) { | |
usbVendor = atoi(argv[1]); | |
} | |
if (argc > 2) { | |
usbProduct = atoi(argv[2]); | |
} | |
// Set up a signal handler so we can clean up when we're interrupted from the command line | |
// Otherwise we stay in our run loop forever. | |
oldHandler = signal(SIGINT, SignalHandler); | |
if (oldHandler == SIG_ERR) { | |
fprintf(stderr, "Could not establish new signal handler."); | |
} | |
fprintf(stderr, "Looking for devices matching vendor ID=%ld and product ID=%ld.\n", usbVendor, usbProduct); | |
// Set up the matching criteria for the devices we're interested in. | |
matchingDict = IOServiceMatching(kIOUSBDeviceClassName); | |
if (matchingDict == NULL) { | |
fprintf(stderr, "IOServiceMatching returned NULL.\n"); | |
return -1; | |
} | |
matchingDict2 = IOServiceMatching(kIOUSBDeviceClassName); | |
if (matchingDict2 == NULL) { | |
fprintf(stderr, "IOServiceMatching returned NULL.\n"); | |
return -1; | |
} | |
// We are interested in USB devices (as opposed to USB interfaces). | |
// Create a CFNumber for the idVendor and set the value in the dictionary | |
numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbVendor); | |
CFDictionarySetValue(matchingDict, | |
CFSTR(kUSBVendorID), | |
numberRef); | |
CFRelease(numberRef); | |
// Create a CFNumber for the idProduct and set the value in the dictionary | |
numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbProduct); | |
CFDictionarySetValue(matchingDict, | |
CFSTR(kUSBProductID), | |
numberRef); | |
CFRelease(numberRef); | |
numberRef = NULL; | |
//------------------------ | |
// Create a CFNumber for the accessory mode vendor and product IDs | |
numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &googleUSBVendor); | |
CFDictionarySetValue(matchingDict2, | |
CFSTR(kUSBVendorID), | |
numberRef); | |
CFRelease(numberRef); | |
numberRef = NULL; | |
numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &googleUSBProduct); | |
CFDictionarySetValue(matchingDict2, | |
CFSTR(kUSBProductID), | |
numberRef); | |
CFRelease(numberRef); | |
numberRef = NULL; | |
//------------------------ | |
// Create a notification port and add its run loop event source to our run loop | |
// This is how async notifications get set up. | |
gNotifyPort = IONotificationPortCreate(kIOMasterPortDefault); | |
runLoopSource = IONotificationPortGetRunLoopSource(gNotifyPort); | |
gRunLoop = CFRunLoopGetCurrent(); | |
CFRunLoopAddSource(gRunLoop, runLoopSource, kCFRunLoopDefaultMode); | |
if (1) { | |
// 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 | |
DeviceAdded, // callback | |
NULL, // refCon | |
&gAddedIter // notification | |
); | |
// Iterate once to get already-present devices and arm the notification | |
DeviceAdded(NULL, gAddedIter); | |
} | |
if (1) { | |
// Now set up a notification to be called when a device is first matched by I/O Kit. | |
kr = IOServiceAddMatchingNotification(gNotifyPort, // notifyPort | |
kIOFirstMatchNotification, // notificationType | |
matchingDict2, // matching | |
AccessoryModeDeviceAdded, // callback | |
NULL, // refCon | |
&gAddedIter // notification | |
); | |
// Iterate once to get already-present devices and arm the notification | |
AccessoryModeDeviceAdded(NULL, gAddedIter); | |
} | |
// Start the run loop. Now we'll receive notifications. | |
fprintf(stderr, "Starting run loop.\n\n"); | |
CFRunLoopRun(); | |
// We should never get here | |
fprintf(stderr, "Unexpectedly back from CFRunLoopRun()!\n"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment