sim-card
/
sam7-util
Archived
10
0
Fork 0
This repository has been archived on 2022-03-30. You can view files and clone it, but cannot push or open issues or pull requests.
sam7-util/io_iokit.c

331 lines
7.5 KiB
C

/*
* io.c
*
* Copyright (C) 2005 Erik Gilling, all rights reserved
* Copyright (C) 2011 Holger Freyther, all rights reserved
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2.
*
*/
#include "config.h"
#include <stdio.h>
#include <mach/mach.h>
#include <CoreFoundation/CFNumber.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/IOCFPlugIn.h>
#include <IOKit/usb/IOUSBLib.h>
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
#include "io.h"
#include "samba.h"
static mach_port_t masterPort = 0;
static IOUSBDeviceInterface **usbDev = NULL;
static IOUSBInterfaceInterface **intf = NULL;
static UInt8 inPipeRef = 0;
static UInt8 outPipeRef = 0;
#undef DEBUG_IO
int do_intf(io_service_t usbInterfaceRef)
{
IOReturn err;
IOCFPlugInInterface **iodev;
SInt32 score;
UInt8 numPipes;
int i;
UInt8 direction, number, transferType, interval;
UInt16 maxPacketSize;
err = IOCreatePlugInInterfaceForService(usbInterfaceRef,
kIOUSBInterfaceUserClientTypeID,
kIOCFPlugInInterfaceID,
&iodev, &score);
if( err || !iodev ) {
printf("unable to create plugin. ret = %08x, iodev = %p\n", err, iodev);
return -1;
}
err = (*iodev)->QueryInterface(iodev,
CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID),
(LPVOID)&intf);
IODestroyPlugInInterface(iodev);
if (err || !intf) {
printf("unable to create a device interface. ret = %08x, intf = %p\n",
err, intf);
return -1;
}
err = (*intf)->USBInterfaceOpen(intf);
if (err) {
printf("unable to open interface. ret = %08x\n", err);
return -1;
}
err = (*intf)->GetNumEndpoints(intf, &numPipes);
if (err) {
printf("unable to get number of endpoints. ret = %08x\n", err);
return -1;
}
if (numPipes) {
for (i=1; i <= numPipes; i++) {
err = (*intf)->GetPipeProperties(intf, i, &direction,
&number, &transferType,
&maxPacketSize, &interval);
if (err) {
printf("unable to get pipe properties for pipe %d, err = %08x\n",
i, err);
continue;
}
if (transferType != kUSBBulk) {
continue;
}
if ((direction == kUSBIn) && !inPipeRef) {
inPipeRef = i;
}
if ((direction == kUSBOut) && !outPipeRef) {
outPipeRef = i;
}
}
}
if( !inPipeRef || !outPipeRef ) {
(*intf)->USBInterfaceClose(intf);
(*intf)->Release(intf);
intf = NULL;
return -1;
}
return 0;
}
static int do_dev( io_service_t usbDeviceRef )
{
IOReturn err;
IOCFPlugInInterface **iodev; // requires <IOKit/IOCFPlugIn.h>
SInt32 score;
UInt8 numConf;
IOUSBConfigurationDescriptorPtr confDesc;
IOUSBFindInterfaceRequest interfaceRequest;
io_iterator_t iterator;
io_service_t usbInterfaceRef;
err = IOCreatePlugInInterfaceForService(usbDeviceRef,
kIOUSBDeviceUserClientTypeID,
kIOCFPlugInInterfaceID, &iodev, &score);
if (err || !iodev) {
printf("unable to create plugin. ret = %08x, iodev = %p\n",
err, iodev);
return -1;
}
err = (*iodev)->QueryInterface(iodev,
CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
(LPVOID)&usbDev);
IODestroyPlugInInterface(iodev); // done with this
if (err || !usbDev) {
printf("unable to create a device interface. ret = %08x, dev = %p\n",
err, usbDev);
return -1;
}
err = (*usbDev)->USBDeviceOpen(usbDev);
if (err) {
printf("unable to open device. ret = %08x\n", err);
return -1;
}
err = (*usbDev)->GetNumberOfConfigurations(usbDev, &numConf);
if (err || !numConf) {
printf("unable to obtain the number of configurations. ret = %08x\n", err);
return -1;
}
err = (*usbDev)->GetConfigurationDescriptorPtr(usbDev, 0, &confDesc); // get the first config desc (index 0)
if (err) {
printf("unable to get config descriptor for index 0\n");
return -1;
}
err = (*usbDev)->SetConfiguration(usbDev, confDesc->bConfigurationValue);
if (err) {
printf("unable to set the configuration\n");
return -1;
}
// requested class
interfaceRequest.bInterfaceClass = kIOUSBFindInterfaceDontCare;
// requested subclass
interfaceRequest.bInterfaceSubClass = kIOUSBFindInterfaceDontCare;
// requested protocol
interfaceRequest.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
// requested alt setting
interfaceRequest.bAlternateSetting = kIOUSBFindInterfaceDontCare;
err = (*usbDev)->CreateInterfaceIterator(usbDev, &interfaceRequest, &iterator);
if (err) {
printf("unable to create interface iterator\n");
return -1;
}
while( (usbInterfaceRef = IOIteratorNext(iterator)) ) {
if( do_intf( usbInterfaceRef ) == 0 ) {
IOObjectRelease(iterator);
iterator = 0;
return 0;
}
}
IOObjectRelease(iterator);
iterator = 0;
return -1;
}
static int iokit_io_init( char *dev __attribute__((unused)) )
{
kern_return_t err;
CFMutableDictionaryRef matchingDictionary = 0;
CFNumberRef numberRef;
SInt32 idVendor = USB_VID_ATMEL;
SInt32 idProduct = USB_PID_SAMBA;
io_iterator_t iterator = 0;
io_service_t usbDeviceRef;
if( (err = IOMasterPort( MACH_PORT_NULL, &masterPort )) ) {
printf( "could not create master port, err = %08x\n", err );
return -1;
}
if( !(matchingDictionary = IOServiceMatching(kIOUSBDeviceClassName)) ) {
printf( "could not create matching dictionary\n" );
return -1;
}
if( !(numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type,
&idVendor)) ) {
printf( "could not create CFNumberRef for vendor\n" );
return -1;
}
CFDictionaryAddValue( matchingDictionary, CFSTR(kUSBVendorID), numberRef);
CFRelease( numberRef );
numberRef = 0;
if( !(numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type,
&idProduct)) ) {
printf( "could not create CFNumberRef for product\n" );
return -1;
}
CFDictionaryAddValue( matchingDictionary, CFSTR(kUSBProductID), numberRef);
CFRelease( numberRef );
numberRef = 0;
err = IOServiceGetMatchingServices( masterPort, matchingDictionary, &iterator );
matchingDictionary = 0; // consumed by the above call
if( (usbDeviceRef = IOIteratorNext( iterator )) ) {
printf( "found boot agent\n" );
do_dev( usbDeviceRef );
} else {
printf( "can not find boot agent\n" );
return -1;
}
IOObjectRelease(usbDeviceRef);
IOObjectRelease(iterator);
return samba_init();
IOObjectRelease(usbDeviceRef);
IOObjectRelease(iterator);
return -1;
}
static int iokit_io_cleanup( void )
{
if( intf ) {
(*intf)->USBInterfaceClose(intf);
(*intf)->Release(intf);
intf = NULL;
}
if( usbDev ) {
(*usbDev)->USBDeviceClose(usbDev);
(*usbDev)->Release(usbDev);
usbDev = NULL;
}
return 0;
}
static int iokit_io_write( void *buff, int len )
{
if( (*intf)->WritePipe( intf, outPipeRef, buff, (UInt32) len ) !=
kIOReturnSuccess ) {
printf( "write error\n");
}
return len;
}
static int iokit_io_read( void *buff, int len )
{
UInt32 size = len;
if( (*intf)->ReadPipe( intf, inPipeRef, buff, &size ) !=
kIOReturnSuccess ) {
printf( "read error\n");
}
return (int) size;
}
static struct io_driver iokit_driver = {
.name = "iokit",
.io_init = iokit_io_init,
.io_cleanup = iokit_io_cleanup,
.io_write = iokit_io_write,
.io_read = iokit_io_read,
};
static void __attribute__((constructor)) iokit_on_load(void)
{
io_driver_register(&iokit_driver);
}