main.c
#include <unistd.h>
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/IOCFPlugIn.h>
#include <IOKit/usb/IOUSBLib.h>
#include <mach/mach.h>
#include "hex2c.h"
extern INTEL_HEX_RECORD bulktest[];
#define k8051_USBCS 0x7f92
#define kOurVendorID 1351
#define kOurProductID 8193
#define kOurProductIDBulkTest 4098
#define kTestMessage "Bulk I/O Test"
static IONotificationPortRef gNotifyPort;
static io_iterator_t gRawAddedIter;
static io_iterator_t gRawRemovedIter;
static io_iterator_t gBulkTestAddedIter;
static io_iterator_t gBulkTestRemovedIter;
static char gBuffer[64];
IOReturn ConfigureAnchorDevice(IOUSBDeviceInterface245 **dev)
{
UInt8 numConf;
IOReturn kr;
IOUSBConfigurationDescriptorPtr confDesc;
kr = (*dev)->GetNumberOfConfigurations(dev, &numConf);
if (!numConf)
return -1;
kr = (*dev)->GetConfigurationDescriptorPtr(dev, 0, &confDesc);
if (kr)
{
printf("\tunable to get config descriptor for index %d (err = %08x)\n", 0, kr);
return -1;
}
kr = (*dev)->SetConfiguration(dev, confDesc->bConfigurationValue);
if (kr)
{
printf("\tunable to set configuration to value %d (err=%08x)\n", 0, kr);
return -1;
}
return kIOReturnSuccess;
}
IOReturn AnchorWrite(IOUSBDeviceInterface245 **dev, UInt16 anchorAddress, UInt16 count, UInt8 writeBuffer[])
{
IOUSBDevRequest request;
request.bmRequestType = USBmakebmRequestType(kUSBOut, kUSBVendor, kUSBDevice);
request.bRequest = 0xa0;
request.wValue = anchorAddress;
request.wIndex = 0;
request.wLength = count;
request.pData = writeBuffer;
return (*dev)->DeviceRequest(dev, &request);
}
IOReturn DownloadToAnchorDevice(IOUSBDeviceInterface245 **dev)
{
int i;
UInt8 writeVal;
IOReturn kr;
writeVal = 1;
kr = AnchorWrite(dev, k8051_USBCS, 1, &writeVal);
if (kIOReturnSuccess != kr)
{
printf("AnchorWrite reset returned err 0x%x!\n", kr);
(*dev)->USBDeviceClose(dev);
(*dev)->Release(dev);
return kr;
}
i = 0;
while (bulktest[i].Type == 0)
{
kr = AnchorWrite(dev, bulktest[i].Address, bulktest[i].Length, bulktest[i].Data);
if (kIOReturnSuccess != kr)
{
printf("AnchorWrite download %i returned err 0x%x!\n", i, kr);
(*dev)->USBDeviceClose(dev);
(*dev)->Release(dev);
return kr;
}
i++;
}
writeVal = 0;
kr = AnchorWrite(dev, k8051_USBCS, 1, &writeVal);
if (kIOReturnSuccess != kr)
{
printf("AnchorWrite run returned err 0x%x!\n", kr);
}
return kr;
}
void ReadCompletion(void *refCon, IOReturn result, void *arg0)
{
IOUSBInterfaceInterface245 **intf = (IOUSBInterfaceInterface245 **) refCon;
UInt32 numBytesRead = (UInt32) arg0;
UInt32 i;
printf("Async bulk read complete.\n");
if (kIOReturnSuccess != result)
{
printf("error from async bulk read (%08x)\n", result);
(void) (*intf)->USBInterfaceClose(intf);
(void) (*intf)->Release(intf);
return;
}
for (i = 0; i < numBytesRead; i++)
gBuffer[i] = ~gBuffer[i];
printf("Read \"%s\" (%ld bytes) from bulk endpoint\n", gBuffer, numBytesRead);
}
void WriteCompletion(void *refCon, IOReturn result, void *arg0)
{
IOUSBInterfaceInterface245 **intf = (IOUSBInterfaceInterface245 **) refCon;
UInt32 numBytesWritten = (UInt32) arg0;
UInt32 numBytesRead;
printf("Async write complete.\n");
if (kIOReturnSuccess != result)
{
printf("error from async bulk write (%08x)\n", result);
(void) (*intf)->USBInterfaceClose(intf);
(void) (*intf)->Release(intf);
return;
}
printf("Wrote \"%s\" (%ld bytes) to bulk endpoint\n", kTestMessage, numBytesWritten);
numBytesRead = sizeof(gBuffer) - 1; result = (*intf)->ReadPipeAsync(intf, 9, gBuffer, numBytesRead, ReadCompletion, refCon);
if (kIOReturnSuccess != result)
{
printf("unable to do async bulk read (%08x)\n", result);
(void) (*intf)->USBInterfaceClose(intf);
(void) (*intf)->Release(intf);
return;
}
}
IOReturn FindInterfaces(IOUSBDeviceInterface245 **dev)
{
IOReturn kr;
IOUSBFindInterfaceRequest request;
io_iterator_t iterator;
io_service_t usbInterface;
IOCFPlugInInterface **plugInInterface = NULL;
IOUSBInterfaceInterface245 **intf = NULL;
HRESULT res;
SInt32 score;
UInt8 intfClass;
UInt8 intfSubClass;
UInt8 intfNumEndpoints;
int pipeRef;
#ifndef USE_ASYNC_IO
UInt32 numBytesRead;
UInt32 i;
#else
CFRunLoopSourceRef runLoopSource;
#endif
request.bInterfaceClass = kIOUSBFindInterfaceDontCare;
request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare;
request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
request.bAlternateSetting = kIOUSBFindInterfaceDontCare;
kr = (*dev)->CreateInterfaceIterator(dev, &request, &iterator);
while ( (usbInterface = IOIteratorNext(iterator)) )
{
printf("Interface found.\n");
kr = IOCreatePlugInInterfaceForService(usbInterface, kIOUSBInterfaceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score);
kr = IOObjectRelease(usbInterface); if ((kIOReturnSuccess != kr) || !plugInInterface)
{
printf("unable to create a plugin (%08x)\n", kr);
break;
}
res = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID245), (LPVOID) &intf);
IODestroyPlugInInterface(plugInInterface);
if (res || !intf)
{
printf("couldn't create an IOUSBInterfaceInterface245 (%08x)\n", (int) res);
break;
}
kr = (*intf)->GetInterfaceClass(intf, &intfClass);
kr = (*intf)->GetInterfaceSubClass(intf, &intfSubClass);
printf("Interface class %d, subclass %d\n", intfClass, intfSubClass);
kr = (*intf)->USBInterfaceOpen(intf);
if (kIOReturnSuccess != kr)
{
printf("unable to open interface (%08x)\n", kr);
(void) (*intf)->Release(intf);
break;
}
kr = (*intf)->GetNumEndpoints(intf, &intfNumEndpoints);
if (kIOReturnSuccess != kr)
{
printf("unable to get number of endpoints (%08x)\n", kr);
(void) (*intf)->USBInterfaceClose(intf);
(void) (*intf)->Release(intf);
break;
}
printf("Interface has %d endpoints.\n", intfNumEndpoints);
for (pipeRef = 1; pipeRef <= intfNumEndpoints; pipeRef++)
{
IOReturn kr2;
UInt8 direction;
UInt8 number;
UInt8 transferType;
UInt16 maxPacketSize;
UInt8 interval;
char *message;
kr2 = (*intf)->GetPipeProperties(intf, pipeRef, &direction, &number, &transferType, &maxPacketSize, &interval);
if (kIOReturnSuccess != kr)
printf("unable to get properties of pipe %d (%08x)\n", pipeRef, kr2);
else {
printf("pipeRef %d: ", pipeRef);
switch (direction) {
case kUSBOut:
message = "out";
break;
case kUSBIn:
message = "in";
break;
case kUSBNone:
message = "none";
break;
case kUSBAnyDirn:
message = "any";
break;
default:
message = "???";
}
printf("direction %s, ", message);
switch (transferType) {
case kUSBControl:
message = "control";
break;
case kUSBIsoc:
message = "isoc";
break;
case kUSBBulk:
message = "bulk";
break;
case kUSBInterrupt:
message = "interrupt";
break;
case kUSBAnyType:
message = "any";
break;
default:
message = "???";
}
printf("transfer type %s, maxPacketSize %d\n", message, maxPacketSize);
}
}
#ifndef USE_ASYNC_IO
kr = (*intf)->WritePipe(intf, 2, kTestMessage, strlen(kTestMessage));
if (kIOReturnSuccess != kr)
{
printf("unable to do bulk write (%08x)\n", kr);
(void) (*intf)->USBInterfaceClose(intf);
(void) (*intf)->Release(intf);
break;
}
printf("Wrote \"%s\" (%ld bytes) to bulk endpoint\n", kTestMessage, (UInt32) strlen(kTestMessage));
numBytesRead = sizeof(gBuffer) - 1; kr = (*intf)->ReadPipe(intf, 9, gBuffer, &numBytesRead);
if (kIOReturnSuccess != kr)
{
printf("unable to do bulk read (%08x)\n", kr);
(void) (*intf)->USBInterfaceClose(intf);
(void) (*intf)->Release(intf);
break;
}
for (i = 0; i < numBytesRead; i++)
gBuffer[i] = ~gBuffer[i];
printf("Read \"%s\" (%ld bytes) from bulk endpoint\n", gBuffer, numBytesRead);
#else
kr = (*intf)->CreateInterfaceAsyncEventSource(intf, &runLoopSource);
if (kIOReturnSuccess != kr)
{
printf("unable to create async event source (%08x)\n", kr);
(void) (*intf)->USBInterfaceClose(intf);
(void) (*intf)->Release(intf);
break;
}
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode);
printf("Async event source added to run loop.\n");
bzero(gBuffer, sizeof(gBuffer));
strcpy(gBuffer, kTestMessage);
kr = (*intf)->WritePipeAsync(intf, 2, gBuffer, strlen(gBuffer), WriteCompletion, (void *) intf);
if (kIOReturnSuccess != kr)
{
printf("unable to do async bulk write (%08x)\n", kr);
(void) (*intf)->USBInterfaceClose(intf);
(void) (*intf)->Release(intf);
break;
}
#endif
break;
}
return kr;
}
void RawDeviceAdded(void *refCon, io_iterator_t iterator)
{
kern_return_t kr;
io_service_t usbDevice;
IOCFPlugInInterface **plugInInterface=NULL;
IOUSBDeviceInterface245 **dev=NULL;
HRESULT res;
SInt32 score;
UInt16 vendor;
UInt16 product;
UInt16 release;
while ( (usbDevice = IOIteratorNext(iterator)) )
{
printf("Raw device added.\n");
kr = IOCreatePlugInInterfaceForService(usbDevice, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score);
kr = IOObjectRelease(usbDevice); if ((kIOReturnSuccess != kr) || !plugInInterface)
{
printf("unable to create a plugin (%08x)\n", kr);
continue;
}
res = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID245), (LPVOID)&dev);
IODestroyPlugInInterface(plugInInterface);
if (res || !dev)
{
printf("couldn't create a device interface (%08x)\n", (int) res);
continue;
}
kr = (*dev)->GetDeviceVendor(dev, &vendor);
kr = (*dev)->GetDeviceProduct(dev, &product);
kr = (*dev)->GetDeviceReleaseNumber(dev, &release);
if ((vendor != kOurVendorID) || (product != kOurProductID) || (release != 1))
{
printf("found device i didn't want (vendor = %d, product = %d)\n", vendor, product);
(void) (*dev)->Release(dev);
continue;
}
kr = (*dev)->USBDeviceOpen(dev);
if (kIOReturnSuccess != kr)
{
printf("unable to open device: %08x\n", kr);
(void) (*dev)->Release(dev);
continue;
}
kr = ConfigureAnchorDevice(dev);
if (kIOReturnSuccess != kr)
{
printf("unable to configure device: %08x\n", kr);
(void) (*dev)->USBDeviceClose(dev);
(void) (*dev)->Release(dev);
continue;
}
kr = DownloadToAnchorDevice(dev);
if (kIOReturnSuccess != kr)
{
printf("unable to download to device: %08x\n", kr);
(void) (*dev)->USBDeviceClose(dev);
(void) (*dev)->Release(dev);
continue;
}
kr = (*dev)->USBDeviceClose(dev);
kr = (*dev)->Release(dev);
}
}
void RawDeviceRemoved(void *refCon, io_iterator_t iterator)
{
kern_return_t kr;
io_service_t obj;
while ( (obj = IOIteratorNext(iterator)) )
{
printf("Raw device removed.\n");
kr = IOObjectRelease(obj);
}
}
void BulkTestDeviceAdded(void *refCon, io_iterator_t iterator)
{
kern_return_t kr;
io_service_t usbDevice;
IOCFPlugInInterface **plugInInterface=NULL;
IOUSBDeviceInterface245 **dev=NULL;
HRESULT res;
SInt32 score;
UInt16 vendor;
UInt16 product;
UInt16 release;
while ( (usbDevice = IOIteratorNext(iterator)) )
{
printf("Bulk test device added.\n");
kr = IOCreatePlugInInterfaceForService(usbDevice, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score);
kr = IOObjectRelease(usbDevice); if ((kIOReturnSuccess != kr) || !plugInInterface)
{
printf("unable to create a plugin (%08x)\n", kr);
continue;
}
res = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID245), (LPVOID)&dev);
IODestroyPlugInInterface(plugInInterface);
if (res || !dev)
{
printf("couldn't create a device interface (%08x)\n", (int) res);
continue;
}
kr = (*dev)->GetDeviceVendor(dev, &vendor);
kr = (*dev)->GetDeviceProduct(dev, &product);
kr = (*dev)->GetDeviceReleaseNumber(dev, &release);
if ((vendor != kOurVendorID) || (product != kOurProductIDBulkTest) || (release != 1))
{
printf("found device i didn't want (vendor = %d, product = %d)\n", vendor, product);
(*dev)->Release(dev);
continue;
}
kr = (*dev)->USBDeviceOpen(dev);
if (kIOReturnSuccess != kr)
{
printf("unable to open device: %08x\n", kr);
(*dev)->Release(dev);
continue;
}
kr = ConfigureAnchorDevice(dev);
if (kIOReturnSuccess != kr)
{
printf("unable to configure device: %08x\n", kr);
(*dev)->USBDeviceClose(dev);
(*dev)->Release(dev);
continue;
}
kr = FindInterfaces(dev);
if (kIOReturnSuccess != kr)
{
printf("unable to find interfaces on device: %08x\n", kr);
(*dev)->USBDeviceClose(dev);
(*dev)->Release(dev);
continue;
}
#ifndef USE_ASYNC_IO
kr = (*dev)->USBDeviceClose(dev);
kr = (*dev)->Release(dev);
#endif
}
}
void BulkTestDeviceRemoved(void *refCon, io_iterator_t iterator)
{
kern_return_t kr;
io_service_t obj;
while ( (obj = IOIteratorNext(iterator)) )
{
printf("Bulk test device removed.\n");
kr = IOObjectRelease(obj);
}
}
void SignalHandler(int sigraised)
{
printf("\nInterrupted\n");
IONotificationPortDestroy(gNotifyPort);
if (gRawAddedIter)
{
IOObjectRelease(gRawAddedIter);
gRawAddedIter = 0;
}
if (gRawRemovedIter)
{
IOObjectRelease(gRawRemovedIter);
gRawRemovedIter = 0;
}
if (gBulkTestAddedIter)
{
IOObjectRelease(gBulkTestAddedIter);
gBulkTestAddedIter = 0;
}
if (gBulkTestRemovedIter)
{
IOObjectRelease(gBulkTestRemovedIter);
gBulkTestRemovedIter = 0;
}
_exit(0);
}
int main (int argc, const char *argv[])
{
mach_port_t masterPort;
CFMutableDictionaryRef matchingDict;
CFRunLoopSourceRef runLoopSource;
kern_return_t kr;
SInt32 usbVendor = kOurVendorID;
SInt32 usbProduct = kOurProductID;
sig_t oldHandler;
if (argc > 1)
usbVendor = atoi(argv[1]);
if (argc > 2)
usbProduct = atoi(argv[2]);
oldHandler = signal(SIGINT, SignalHandler);
if (oldHandler == SIG_ERR)
printf("Could not establish new signal handler");
kr = IOMasterPort(MACH_PORT_NULL, &masterPort);
if (kr || !masterPort)
{
printf("ERR: Couldn't create a master IOKit Port(%08x)\n", kr);
return -1;
}
printf("Looking for devices matching vendor ID=%ld and product ID=%ld\n", usbVendor, usbProduct);
matchingDict = IOServiceMatching(kIOUSBDeviceClassName); if (!matchingDict)
{
printf("Can't create a USB matching dictionary\n");
mach_port_deallocate(mach_task_self(), masterPort);
return -1;
}
CFDictionarySetValue(
matchingDict,
CFSTR(kUSBVendorID),
CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbVendor));
CFDictionarySetValue(
matchingDict,
CFSTR(kUSBProductID),
CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbProduct));
gNotifyPort = IONotificationPortCreate(masterPort);
runLoopSource = IONotificationPortGetRunLoopSource(gNotifyPort);
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode);
matchingDict = (CFMutableDictionaryRef) CFRetain( matchingDict );
matchingDict = (CFMutableDictionaryRef) CFRetain( matchingDict );
matchingDict = (CFMutableDictionaryRef) CFRetain( matchingDict );
kr = IOServiceAddMatchingNotification( gNotifyPort,
kIOFirstMatchNotification,
matchingDict,
RawDeviceAdded,
NULL,
&gRawAddedIter );
RawDeviceAdded(NULL, gRawAddedIter);
kr = IOServiceAddMatchingNotification( gNotifyPort,
kIOTerminatedNotification,
matchingDict,
RawDeviceRemoved,
NULL,
&gRawRemovedIter );
RawDeviceRemoved(NULL, gRawRemovedIter);
usbProduct = kOurProductIDBulkTest;
CFDictionarySetValue(
matchingDict,
CFSTR(kUSBProductID),
CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbProduct));
kr = IOServiceAddMatchingNotification( gNotifyPort,
kIOFirstMatchNotification,
matchingDict,
BulkTestDeviceAdded,
NULL,
&gBulkTestAddedIter );
BulkTestDeviceAdded(NULL, gBulkTestAddedIter);
kr = IOServiceAddMatchingNotification( gNotifyPort,
kIOTerminatedNotification,
matchingDict,
BulkTestDeviceRemoved,
NULL,
&gBulkTestRemovedIter );
BulkTestDeviceRemoved(NULL, gBulkTestRemovedIter);
mach_port_deallocate(mach_task_self(), masterPort);
masterPort = 0;
CFRunLoopRun();
return 0;
}
Generated by GNU enscript 1.6.4.