#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include <sys/errno.h>
#include <sys/fcntl.h>
#include <sys/stat.h>
#include <mach/mach.h>
#include <mach/mach_error.h>
#include <CoreFoundation/CoreFoundation.h>
#include <CoreFoundation/CFURL.h>
#include <CoreFoundation/CFPlugin.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/IOCFPlugIn.h>
#include <IOKit/usb/IOUSBLib.h>
#define mach_test(expr, msg) do { \
kern_return_t err = (expr); \
if (KERN_SUCCESS != err) { \
fprintf(stderr, "%s: %s - %s(%x,%d)\n", cmdName, \
msg, mach_error_string(err), \
err, err & 0xffffff); \
fflush(stderr); \
*((char *) 0) = 0; \
} \
} while(0)
#define plain_test(expr, msg) do { \
if (expr) { \
fprintf(stderr, "%s: %s\n", cmdName, msg); \
fflush(stderr); \
*((char *) 0) = 0; \
} \
} while(0)
static const char *cmdName;
static Boolean runAsync = 0;
static volatile void usage(void)
{
fprintf(stderr, "Usage: %s [-a]", cmdName);
fprintf(stderr, " where -a indicates async run");
exit(EX_USAGE);
}
static void init(int argc, const char *argv[])
{
char c;
if (cmdName = strrchr(argv[0], '/'))
cmdName++;
else
cmdName = argv[0];
while ((c = getopt(argc, argv, "a")) != -1) {
switch(c) {
case 'a': runAsync = 1; break;
case '?':
default:
usage();
}
}
}
static void
showDeviceInfo(IOUSBDeviceInterface **dev)
{
UInt8 devClass;
UInt8 devSubClass;
UInt8 devProtocol;
UInt16 devVendor;
UInt16 devProduct;
UInt16 devRelNum;
IOReturn kr;
kr = (*dev)->GetDeviceClass(dev, &devClass);
mach_test(kr, "Couldn't get class");
kr = (*dev)->GetDeviceSubClass(dev, &devSubClass);
mach_test(kr, "Couldn't get subclass");
kr = (*dev)->GetDeviceProtocol(dev, &devProtocol);
mach_test(kr, "Couldn't get protocol");
kr = (*dev)->GetDeviceVendor(dev, &devVendor);
mach_test(kr, "Couldn't get vendor");
kr = (*dev)->GetDeviceProduct(dev, &devProduct);
mach_test(kr, "Couldn't get product");
kr = (*dev)->GetDeviceReleaseNumber(dev, &devRelNum);
mach_test(kr, "Couldn't get relnum");
printf("----------------------------\n");
printf("USB device\n");
printf("----------------------------\n");
printf("\tclass: %d\n", devClass);
printf("\tsubclass: %d\n", devSubClass);
printf("\tprotocol: %d\n", devProtocol);
printf("\tVendor: %04x\n", devVendor);
printf("\tProduct: %04x\n", devProduct);
printf("\tRelease: %04x\n", devRelNum);
}
static void dosomethingtodevice(io_service_t USBDevice);
static void
showInterfaceInfo(IOUSBInterfaceInterface **intf)
{
UInt8 intfClass;
UInt8 intfSubClass;
UInt8 intfProtocol;
UInt16 devVendor;
UInt16 devProduct;
UInt16 devRelNum;
UInt8 configValue;
UInt8 intfNumber;
io_service_t USBdevice = 0;
IOReturn kr;
kr = (*intf)->GetInterfaceClass(intf, &intfClass);
mach_test(kr, "Couldn't get class");
kr = (*intf)->GetInterfaceSubClass(intf, &intfSubClass);
mach_test(kr, "Couldn't get subclass");
kr = (*intf)->GetInterfaceProtocol(intf, &intfProtocol);
mach_test(kr, "Couldn't get protocol");
kr = (*intf)->GetDeviceVendor(intf, &devVendor);
mach_test(kr, "Couldn't get vendor");
kr = (*intf)->GetDeviceProduct(intf, &devProduct);
mach_test(kr, "Couldn't get product");
kr = (*intf)->GetDeviceReleaseNumber(intf, &devRelNum);
mach_test(kr, "Couldn't get relnum");
kr = (*intf)->GetConfigurationValue(intf, &configValue);
mach_test(kr, "Couldn't get configvalue");
kr = (*intf)->GetInterfaceNumber(intf, &intfNumber);
mach_test(kr, "Couldn't get interface number");
kr = (*intf)->GetDevice(intf, &USBdevice);
mach_test(kr, "Couldn't get device");
printf("----------------------------\n");
printf("USB interface\n");
printf("----------------------------\n");
printf("\tclass: %d\n", intfClass);
printf("\tsubclass: %d\n", intfSubClass);
printf("\tprotocol: %d\n", intfProtocol);
printf("\tVendor: %04x\n", devVendor);
printf("\tProduct: %04x\n", devProduct);
printf("\tRelease: %04x\n", devRelNum);
printf("\tConfigValue: %d\n", configValue);
printf("\tInterfaceNumber: %d\n", intfNumber);
dosomethingtodevice(USBdevice);
}
#if 0
static void printinquirydata(USBInquiry *d, UInt32 s)
{
char vendorName[sizeof(d->vendorName)+1];
char productName[sizeof(d->productName)+1];
char productRevision[sizeof(d->productRevision)+1];
char vendorSpecific[sizeof(d->vendorSpecific)+1];
int i, size;
vendorName[sizeof(d->vendorName)] = '\0';
strncpy(vendorName, d->vendorName, sizeof(d->vendorName));
productName[sizeof(d->productName)] = '\0';
strncpy(productName, d->productName, sizeof(d->productName));
productRevision[sizeof(d->productRevision)] = '\0';
strncpy(productRevision, d->productRevision, sizeof(d->productRevision));
vendorSpecific[sizeof(d->vendorSpecific)] = '\0';
strncpy(vendorSpecific, d->vendorSpecific, sizeof(d->vendorSpecific));
printf("%s: Got inquiry results size = %ld\n", cmdName, s);
printf(" devType = 0x%x\n", d->devType);
printf(" devTypeMod = 0x%x\n", d->devTypeMod);
printf(" version = 0x%x\n", d->version);
printf(" format = 0x%x\n", d->format);
printf(" length = 0x%x\n", d->length);
printf(" reserved5 = 0x%x\n", d->reserved5);
printf(" reserved6 = 0x%x\n", d->reserved6);
printf(" flags = 0x%x\n", d->flags);
printf(" vendorName = \"%s\"\n", vendorName);
printf(" productName = \"%s\"\n", productName);
printf(" productRevision = \"%s\"\n", productRevision);
printf(" vendorSpecific = \"%s\"\n", vendorSpecific);
size = s - ((char *) &d->moreReserved - (char *) d);
if (size > 0) {
printf(" moreReserved(%d) = ", size);
for (i = 0; i < size; i++) {
if ( !(i & 0xf) )
printf("\n");
printf("%02x ", ((UInt8 *) d->moreReserved)[i]);
}
printf("\n");
}
}
static IOCDBCommandInterface **
allocCommand(IOUSBDeviceInterface **dev)
{
HRESULT res;
IOCDBCommandInterface **cmd;
printf("%s: opened device\n", cmdName);
res = (*dev)->QueryInterface(dev,
CFUUIDGetUUIDBytes(kIOCDBCommandInterfaceID), (LPVOID) &cmd);
plain_test(res != S_OK, "Couldn't create a CDB Command");
return cmd;
}
static void executeSyncInquiry(IOCDBCommandInterface **cmd)
{
UInt8 data[255];
IOVirtualRange range[1];
CDBInfo cdb;
USBResults results;
UInt32 seqNumber;
IOReturn kr;
bzero(data, sizeof(data));
range[0].address = (IOVirtualAddress) data;
range[0].length = sizeof(data);
bzero(&cdb, sizeof(cdb));
cdb.cdbLength = 6;
cdb.cdb[0] = kUSBCmdInquiry;
cdb.cdb[4] = sizeof(data);
kr = (*cmd)->setAndExecuteCommand(cmd,
&cdb,
sizeof(data),
range,
sizeof(range)/sizeof(range[0]),
0,
0,
0,
0,
0,
&seqNumber);
if (kr == kIOReturnUnderrun)
printf("%s: Command Underrun\n", cmdName);
else
mach_test(kr, "Couldn't execute a CDB Command");
kr = (*cmd)->getResults(cmd, &results);
if (kr == kIOReturnUnderrun)
printf("%s: getResults Underrun\n", cmdName);
else
mach_test(kr, "Couldn't get results of a command");
printinquirydata((USBInquiry *) data, results.bytesTransferred);
}
#endif
static void
dosomethingtodevice(io_service_t USBDevice)
{
io_name_t className;
IOCFPlugInInterface **iodev;
IOUSBDeviceInterface **dev;
HRESULT res;
kern_return_t kr;
SInt32 score;
printf("Doing something to device: %d (%08x)\n", USBDevice, USBDevice);
mach_test(IOObjectGetClass(USBDevice, className),
"Failed to get class name");
printf("%s: found device type %s\n", cmdName, className);
kr = IOCreatePlugInInterfaceForService(USBDevice,
kIOUSBDeviceUserClientTypeID,
kIOCFPlugInInterfaceID,
&iodev,
&score);
if (kr)
printf("--unable to create plugin\n");
else
printf("!!PLUGIN SUCCESS\n");
res = (*iodev)->QueryInterface(iodev,
CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID) &dev);
plain_test(res != S_OK, "Couldn't create USB Device interface");
(*iodev)->Release(iodev);
showDeviceInfo(dev);
#if 0
kr = (*dev)->open(dev);
if (kIOReturnSuccess != kr)
printf("%s: failed to open 0x%08x\n", cmdName, kr);
else {
IOCDBCommandInterface **cmd = allocCommand(dev);
if (cmd) {
executeSyncInquiry(cmd);
(*cmd)->Release(cmd);
}
(*dev)->close(dev);
}
(*dev)->Release(dev);
#endif
IOObjectRelease(USBDevice);
}
static void
dosomethingtointerface(io_service_t USBInterface)
{
io_name_t className;
IOCFPlugInInterface **iodev;
IOUSBInterfaceInterface **intf;
HRESULT res;
kern_return_t kr;
SInt32 score;
printf("Doing something to interface: %d (%08x)\n", USBInterface, USBInterface);
mach_test(IOObjectGetClass(USBInterface, className),
"Failed to get class name");
printf("%s: found device type %s\n", cmdName, className);
kr = IOCreatePlugInInterfaceForService(USBInterface,
kIOUSBInterfaceUserClientTypeID,
kIOCFPlugInInterfaceID,
&iodev,
&score);
if (kr)
{
printf("--unable to create plugin\n");
return;
}
else
printf("!!PLUGIN SUCCESS\n");
res = (*iodev)->QueryInterface(iodev,
CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), (LPVOID) &intf);
plain_test(res != S_OK, "Couldn't create USB Interface interface");
(*iodev)->Release(iodev);
showInterfaceInfo(intf);
#if 0
kr = (*dev)->open(dev);
if (kIOReturnSuccess != kr)
printf("%s: failed to open 0x%08x\n", cmdName, kr);
else {
IOCDBCommandInterface **cmd = allocCommand(dev);
if (cmd) {
executeSyncInquiry(cmd);
(*cmd)->Release(cmd);
}
(*dev)->close(dev);
}
(*dev)->Release(dev);
#endif
IOObjectRelease(USBInterface);
}
static void
findUSBDevices(void)
{
mach_port_t masterPort = 0;
CFDictionaryRef USBMatch = 0;
io_iterator_t iter = 0;
io_service_t USBDevice = 0;
mach_test(IOMasterPort(bootstrap_port, &masterPort),
"Couldn't create a master IOKit Port");
USBMatch = IOServiceMatching(kIOUSBDeviceClassName);
plain_test(!USBMatch, "Can't create a USB matching dictionary");
mach_test(IOServiceGetMatchingServices(masterPort, USBMatch, &iter),
"Can't create a USB Service iterator");
USBMatch = 0;
while ( (USBDevice = IOIteratorNext(iter)) )
dosomethingtodevice(USBDevice);
if (iter)
{
IOObjectRelease(iter);
iter = 0;
}
if (USBMatch)
{
CFRelease(USBMatch);
USBMatch = 0;
}
if (masterPort)
{
mach_port_deallocate(mach_task_self(), masterPort);
masterPort = 0;
}
}
static void findUSBInterfaces(void)
{
mach_port_t masterPort = 0;
CFDictionaryRef USBMatch = 0;
io_iterator_t iter = 0;
io_service_t USBInterface = 0;
mach_test(IOMasterPort(bootstrap_port, &masterPort),
"Couldn't create a master IOKit Port");
USBMatch = IOServiceMatching(kIOUSBInterfaceClassName);
plain_test(!USBMatch, "Can't create a USB matching dictionary");
mach_test(IOServiceGetMatchingServices(masterPort, USBMatch, &iter),
"Can't create a USB Service iterator");
USBMatch = 0;
while ( (USBInterface = IOIteratorNext(iter)) )
dosomethingtointerface(USBInterface);
if (iter)
{
IOObjectRelease(iter);
iter = 0;
}
if (USBMatch)
{
CFRelease(USBMatch);
USBMatch = 0;
}
if (masterPort)
{
mach_port_deallocate(mach_task_self(), masterPort);
masterPort = 0;
}
}
static unsigned char desc[1024];
CFRunLoopSourceRef cfSource;
void
MyCallBackFunction(IOUSBConfigurationDescriptorPtr desc, IOReturn result, void *arg0)
{
printf("MyCallbackfunction: %d, %d, %d\n", (int)desc, (int)result, (int)arg0);
CFRunLoopStop(CFRunLoopGetCurrent());
}
static void
findUnconfiguredDevices(void)
{
mach_port_t masterPort = 0;
CFDictionaryRef USBMatch = 0;
io_iterator_t iter = 0;
io_service_t USBDevice = 0;
kern_return_t kr;
kr = IOMasterPort(bootstrap_port, &masterPort);
if (kr || !masterPort)
{
printf("ERR: Couldn't create a master IOKit Port(%08x)\n", kr);
return;
}
USBMatch = IOServiceMatching(kIOUSBDeviceClassName);
if (!USBMatch)
{
printf("Can't create a USB matching dictionary\n");
mach_port_deallocate(mach_task_self(), masterPort);
return;
}
kr = IOServiceGetMatchingServices(masterPort, USBMatch, &iter);
if (kr)
{
printf("Can't create a USB Service iterator(%08x)\n", kr);
CFRelease(USBMatch);
mach_port_deallocate(mach_task_self(), masterPort);
return;
}
while ( (USBDevice = IOIteratorNext(iter)) )
{
IOCFPlugInInterface **iodev;
IOUSBDeviceInterface **dev;
HRESULT res;
SInt32 score;
UInt8 numConf;
UInt8 curConf = 0;
UInt8 devClass = 0, devSubClass = 0;
int i;
IOUSBConfigurationDescriptorPtr confDesc;
kr = IOCreatePlugInInterfaceForService(USBDevice, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &iodev, &score);
IOObjectRelease(USBDevice); if (kr || !iodev)
{
printf("unable to create a plugin (%08x)\n", kr);
continue;
}
res = (*iodev)->QueryInterface(iodev, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID)&dev);
(*iodev)->Release(iodev); if (res || !dev)
{
printf("couldn't create a device interface (%08x)\n", (int)res);
continue;
}
kr = (*dev)->GetConfiguration(dev, &curConf);
kr = (*dev)->GetDeviceClass(dev, &devClass);
kr = (*dev)->GetDeviceSubClass(dev, &devSubClass);
if (curConf != 0)
{
printf("found configured device (class = %d, subclass = %d)\n", devClass, devSubClass);
(*dev)->Release(dev);
continue;
}
printf("found UNCONFIGURED device (class = %d, subclass = %d)\n", devClass, devSubClass);
kr = (*dev)->USBDeviceOpen(dev);
if (kr)
{
printf("unable to open device: %08x\n", kr);
continue;
}
kr = (*dev)->GetNumberOfConfigurations(dev, &numConf);
printf("\tfound %d configurations\n", numConf);
for (i=0; i<numConf; i++)
{
kr = (*dev)->GetConfigurationDescriptorPtr(dev, i, &confDesc);
if (kr)
{
printf("\tunable to get config descriptor for index %d\n", i);
continue;
}
printf("\t--------------------------------\n");
printf("\tConfig Descriptor index #%d\n", i);
printf("\t--------------------------------\n");
printf("\tTotal Length: %d\n", USBToHostWord(confDesc->wTotalLength));
printf("\tConfig Value: %d\n", confDesc->bConfigurationValue);
printf("\t--------------------------------\n");
if (i==0)
{
printf("\tsetting the config to %d\n", confDesc->bConfigurationValue);
kr = (*dev)->SetConfiguration(dev, confDesc->bConfigurationValue);
kr = (*dev)->GetConfiguration(dev, &curConf);
if (curConf != confDesc->bConfigurationValue)
printf("\t\tSET CONFIG FAILED!\n");
}
}
printf("Trying to do a device request\n");
{
IOUSBDevRequest request;
kr = (*dev)->CreateDeviceAsyncEventSource(dev, &cfSource);
CFRunLoopAddSource(CFRunLoopGetCurrent(), cfSource, kCFRunLoopDefaultMode);
desc[0]='H'; desc[1]='i';
request.bmRequestType = (kUSBIn << kUSBRqDirnShift)
| (kUSBStandard << kUSBRqTypeShift)
| kUSBDevice;
request.bRequest = kUSBRqGetDescriptor;
request.wValue = (kUSBConfDesc << 8) + 0;
request.wIndex = 0;
request.wLength = USBToHostWord(confDesc->wTotalLength);
request.pData = desc;
kr = (*dev)->DeviceRequestAsync(dev, &request, (IOAsyncCallback1)MyCallBackFunction, (void*)desc);
if (kr)
printf("device request failed\n");
else
{
printf("about to call RunLoopRun\n");
CFRunLoopRun();
printf("RunLoopRun returned\n");
}
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), cfSource, kCFRunLoopDefaultMode);
}
kr = (*dev)->USBDeviceClose(dev);
kr = (*dev)->Release(dev);
}
if (iter)
{
IOObjectRelease(iter);
iter = 0;
}
if (USBMatch)
{
CFRelease(USBMatch);
USBMatch = 0;
}
if (masterPort)
{
mach_port_deallocate(mach_task_self(), masterPort);
masterPort = 0;
}
}
static void
findVendorSpecificInterfaces(void)
{
mach_port_t masterPort = 0;
CFDictionaryRef USBMatch = 0;
io_iterator_t iter = 0;
io_service_t USBInterface = 0;
kern_return_t kr;
kr = IOMasterPort(bootstrap_port, &masterPort);
if (kr || !masterPort)
{
printf("ERR: Couldn't create a master IOKit Port(%08x)\n", kr);
return;
}
USBMatch = IOServiceMatching(kIOUSBInterfaceClassName);
if (!USBMatch)
{
printf("Can't create a USB matching dictionary\n");
mach_port_deallocate(mach_task_self(), masterPort);
return;
}
kr = IOServiceGetMatchingServices(masterPort, USBMatch, &iter);
if (kr)
{
printf("Can't create a USB Service iterator(%08x)\n", kr);
CFRelease(USBMatch);
mach_port_deallocate(mach_task_self(), masterPort);
return;
}
while ( (USBInterface = IOIteratorNext(iter)) )
{
IOCFPlugInInterface **iodev=NULL;
IOUSBInterfaceInterface **intf=NULL;
HRESULT res;
SInt32 score;
int i;
UInt16 vendor;
UInt16 product;
UInt8 numPipes;
kr = IOCreatePlugInInterfaceForService(USBInterface, kIOUSBInterfaceUserClientTypeID, kIOCFPlugInInterfaceID, &iodev, &score);
IOObjectRelease(USBInterface); if (kr || !iodev)
{
printf("unable to create a plugin (%08x)\n", kr);
continue;
}
res = (*iodev)->QueryInterface(iodev, CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), (LPVOID)&intf);
(*iodev)->Release(iodev); if (res || !intf)
{
printf("couldn't create a device interface (%08x)\n", (int)res);
continue;
}
kr = (*intf)->GetDeviceVendor(intf, &vendor);
kr = (*intf)->GetDeviceProduct(intf, &product);
if ((vendor != 1215) || (product != 275))
{
printf("found interface i didn't want (vendor = %d, product = %d)\n", vendor, product);
(*intf)->Release(intf);
continue;
}
printf("found my interface (vendor = %d, product = %d)\n", vendor, product);
kr = (*intf)->USBInterfaceOpen(intf);
if (kr)
{
printf("unable to open interface: %08x\n", kr);
continue;
}
kr = (*intf)->GetNumEndpoints(intf, &numPipes);
printf("\tfound %d pipes\n", numPipes);
for (i=1; i<=numPipes; i++)
{
UInt8 number, direction, transferType, interval;
UInt16 mps;
kr = (*intf)->GetPipeProperties(intf, i, &direction, &number, &transferType, &mps, &interval);
printf("pipe %d: dir=%d, num=%d, tt=%d, mps=%d, interval=%d\n", i, direction, number, transferType, mps, interval);
}
kr = (*intf)->USBInterfaceClose(intf);
kr = (*intf)->Release(intf);
}
if (iter)
{
IOObjectRelease(iter);
iter = 0;
}
if (USBMatch)
{
CFRelease(USBMatch);
USBMatch = 0;
}
if (masterPort)
{
mach_port_deallocate(mach_task_self(), masterPort);
masterPort = 0;
}
}
__private_extern__ int
main(int argc, const char *argv[])
{
init(argc, argv);
findUSBDevices();
exit(EX_OK);
}