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
***************************************************************

Reply via email to