Hello,
Here is some code snibblet that creates a serial like API for some USB
readers on OS X. This particular codes uses 2 enpoints bulk in/out. If
you need code that does Control or Interrupt pipes please let me know. I
think it would be interesting to make the iKey work on OS X.
Best Regards,
Dave
/* Title: usbserial.c
/ Author: David Corcoran
/ Purpose: Abstracts usb API to serial like calls
*/
#include <stdio.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/usb/IOUSBLib.h>
#include <assert.h>
#include "usbserial.h"
#define USBDEBUG 1
/* Change the following to uniquely match your reader. */
enum {
kMyVendorID = 0x0000, /* change to match your
reader */
kMyProductID = 0x0000, /* change to match your
reader */
kMyDeviceClass = kIOUSBAnyClass,
kMyDeviceSubClass = kIOUSBAnySubClass,
kMyDeviceProtocol = kIOUSBAnyProtocol
};
static IOUSBPipeRef outPipe;
static IOUSBPipeRef inPipe;
static IOUSBInterfaceRef newInterface;
static IOUSBIteratorRef usbIterator;
RESPONSECODE OpenUSB( DWORD lun )
{
IOUSBFindEndpointRequest epReq;
IONotificationPortRef ioNotify;
IOUSBInterfaceDescriptor interfaceDesc;
IOUSBDeviceDescriptor desc;
IOUSBMatch usbMatch;
IOUSBDeviceRef newDevice;
IOReturn iorv;
IOReturn dorv;
kern_return_t kr;
mach_port_t masterPort;
mach_port_t notifyPort;
int isInterface;
iorv = IOMasterPort( bootstrap_port, &masterPort );
if ( iorv != 0 )
{
return STATUS_UNSUCCESSFUL;
}
ioNotify = IONotificationPortCreate( masterPort );
notifyPort = IONotificationPortGetMachPort( ioNotify );
usbMatch.usbClass = kMyDeviceClass;
usbMatch.usbSubClass = kMyDeviceSubClass;
usbMatch.usbProtocol = kMyDeviceProtocol;
usbMatch.usbVendor = kMyVendorID;
usbMatch.usbProduct = kMyProductID;
/* Only concerned about devices */
kr = IOUSBCreateIterator( masterPort, notifyPort, &usbMatch,
&usbIterator );
if ( kr != KERN_SUCCESS )
{
return STATUS_UNSUCCESSFUL;
}
while ( ( iorv = IOUSBIteratorNext( usbIterator )) == kIOReturnSuccess ) {
IOUSBIsInterface( usbIterator, &isInterface );
/* Must be a device */
if ( isInterface == 0 ) {
dorv = IOUSBGetDeviceDescriptor( usbIterator, &desc,
sizeof(desc) );
#if USBDEBUG
printf("Device found\n");
if ( dorv == kIOReturnSuccess ) {
printf("Found the following device\n");
printf("Length %x\n", desc.length);
printf("descType %x\n", desc.descType);
printf("usbRel %x\n", desc.usbRel);
printf("deviceClass %x\n", desc.deviceClass);
printf("deviceSubClass %x\n", desc.deviceSubClass);
printf("protocol %x\n", desc.protocol);
printf("maxPacketSize %x\n", desc.maxPacketSize);
printf("vendor %x\n", EndianSwap16(desc.vendor));
printf("product %x\n", EndianSwap16(desc.product));
printf("devRel %x\n", EndianSwap16(desc.devRel));
printf("manuIdx %x\n", desc.manuIdx);
printf("prodIdx %x\n", desc.prodIdx);
printf("serialIdx %x\n", desc.serialIdx);
printf("numConf %x\n", desc.numConf);
printf("\n\n");
}
#endif
/* Create a reference to the device */
iorv = IOUSBNewDeviceRef( usbIterator, &newDevice );
if ( iorv != kIOReturnSuccess ) {
return STATUS_UNSUCCESSFUL;
}
/* Reset the reader */
iorv = IOUSBResetDevice( newDevice );
assert( iorv == kIOReturnSuccess );
iorv = IOUSBSetConfiguration( newDevice, 1 );
if ( iorv != kIOReturnSuccess ) {
return STATUS_UNSUCCESSFUL;
}
iorv = IOUSBDisposeRef( newDevice );
if ( iorv != kIOReturnSuccess ) {
return STATUS_UNSUCCESSFUL;
}
/* Must be an interface */
}
else {
dorv = IOUSBGetInterfaceDescriptor( usbIterator, &interfaceDesc,
sizeof(interfaceDesc) );
#if USBDEBUG
printf("Interface found\n");
if ( dorv == 0 ) {
printf("length %x\n", interfaceDesc.length);
printf("descriptorType %x\n", interfaceDesc.descriptorType);
printf("interfaceNumber %x\n",
interfaceDesc.interfaceNumber);
printf("alternateSetting %x\n",
interfaceDesc.alternateSetting);
printf("numEndpoints %x\n", interfaceDesc.numEndpoints);
printf("interfaceClass %x\n", interfaceDesc.interfaceClass);
printf("interfaceSubClass %x\n",
interfaceDesc.interfaceSubClass);
printf("interfaceProtocol %x\n",
interfaceDesc.interfaceProtocol);
printf("interfaceStrIndex %x\n",
interfaceDesc.interfaceStrIndex);
}
#endif
iorv = IOUSBNewInterfaceRef( usbIterator, &newInterface );
if ( iorv != kIOReturnSuccess ) {
return STATUS_UNSUCCESSFUL;
}
iorv = IOUSBOpenInterface( newInterface, 1 );
if ( iorv != kIOReturnSuccess ) {
return STATUS_UNSUCCESSFUL;
}
/* Open the first endpoint */
epReq.type = kUSBAnyType;
epReq.direction = kUSBOut;
epReq.maxPacketSize = 64;
epReq.interval = 255;
iorv = IOUSBFindNextPipe( newInterface, NULL, &epReq, &outPipe );
if ( iorv != kIOReturnSuccess || outPipe == NULL ) {
return STATUS_UNSUCCESSFUL;
}
/* Open the second endpoint */
epReq.type = kUSBAnyType;
epReq.direction = kUSBIn;
epReq.maxPacketSize = 64;
epReq.interval = 255;
iorv = IOUSBFindNextPipe( newInterface, outPipe, &epReq, &inPipe );
if ( iorv != kIOReturnSuccess || inPipe == NULL ) {
return STATUS_UNSUCCESSFUL;
}
}
}
return STATUS_SUCCESS;
}
RESPONSECODE WriteUSB( DWORD lun, DWORD length, unsigned char *buffer )
{
IOReturn iorv;
#if USBDEBUG
int i;
#endif
#if USBDEBUG
if ( lun != 50 ) {
printf("Attempt to write: ");
for ( i = 0; i < length; i++ ) {
printf("%x ", buffer[i]);
}
printf("\n");
}
#endif
iorv = IOUSBSetPipeActive( outPipe );
if ( iorv != kIOReturnSuccess ) {
return STATUS_UNSUCCESSFUL;
}
iorv = IOUSBGetPipeStatus( outPipe );
if ( iorv != kIOReturnSuccess ) {
return STATUS_UNSUCCESSFUL;
}
iorv = IOUSBWritePipe( outPipe, buffer, length );
if ( iorv != kIOReturnSuccess ) {
return STATUS_UNSUCCESSFUL;
}
iorv = IOUSBSetPipeIdle( outPipe );
if ( iorv != kIOReturnSuccess ) {
return STATUS_UNSUCCESSFUL;
}
return STATUS_SUCCESS;
}
RESPONSECODE ReadUSB( DWORD lun, DWORD *length, unsigned char *buffer )
{
IOReturn iorv;
UInt32 recvLen;
#if USBDEBUG
int i;
#endif
#if USBDEBUG
if ( lun != 50 ) {
printf("Attempt to read %ld bytes\n", *length);
}
#endif
iorv = IOUSBSetPipeActive( inPipe );
if ( iorv != kIOReturnSuccess ) {
return STATUS_UNSUCCESSFUL;
}
iorv = IOUSBGetPipeStatus( inPipe );
if ( iorv != kIOReturnSuccess ) {
return STATUS_UNSUCCESSFUL;
}
recvLen = 256;
iorv = IOUSBReadPipe( inPipe, buffer, &recvLen );
if ( iorv != 0 ) {
return STATUS_UNSUCCESSFUL;
}
#if USBDEBUG
if ( lun != 50 ) {
printf("recvLen %ld\n", recvLen);
for ( i = 0; i < recvLen; i++ ) {
printf("%x ", buffer[i]);
}
printf("\n");
}
#endif
iorv = IOUSBSetPipeIdle( inPipe );
if ( iorv != kIOReturnSuccess ) {
return STATUS_UNSUCCESSFUL;
}
*length = recvLen;
return STATUS_SUCCESS;
}
RESPONSECODE CloseUSB( DWORD lun )
{
IOReturn iorv;
iorv = IOUSBClosePipe( inPipe );
if ( iorv != kIOReturnSuccess ) {
return STATUS_UNSUCCESSFUL;
}
iorv = IOUSBClosePipe( outPipe );
if ( iorv != kIOReturnSuccess ) {
return STATUS_UNSUCCESSFUL;
}
iorv = IOUSBCloseInterface( newInterface );
if ( iorv != kIOReturnSuccess ) {
return STATUS_UNSUCCESSFUL;
}
iorv = IOUSBDisposeIterator( usbIterator );
if ( iorv != kIOReturnSuccess ) {
return STATUS_UNSUCCESSFUL;
}
return STATUS_SUCCESS;
}
David Corcoran Purdue University
1008 Cherry Lane
West Lafayette, IN 47906
[EMAIL PROTECTED]
765 - 427 - 5147 http://www.linuxnet.com
***************************************************************
Linux Smart Card Developers - M.U.S.C.L.E.
(Movement for the Use of Smart Cards in a Linux Environment)
http://www.linuxnet.com/smartcard/index.html
***************************************************************