来自开源project yubikey : http://code.google.com/p/yubikey-core/
/* -*- mode:C; c-file-style: "bsd" -*- */ |
/* |
* Copyright (c) 2008, 2009, Yubico AB |
* Copyright (c) 2009, Christer Kaivo-oja <christer.kaivooja@gmail.com> |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions are |
* met: |
* |
* * Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* |
* * Redistributions in binary form must reproduce the above |
* copyright notice, this list of conditions and the following |
* disclaimer in the documentation and/or other materials provided |
* with the distribution. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include "ykcore.h" |
#include "ykdef.h" |
#include "ykcore_backend.h" |
#include <IOKit/hid/IOHIDLib.h> |
#include <IOKit/hid/IOHIDKeys.h> |
#include <CoreFoundation/CoreFoundation.h> |
#include "ykcore_backend.h" |
#define FEATURE_RPT_SIZE 8 |
static IOHIDManagerRef ykosxManager = NULL; |
static IOReturn _ykusb_IOReturn = 0; |
int _ykusb_start(void) |
{ |
ykosxManager = IOHIDManagerCreate( kCFAllocatorDefault, 0L ); |
|
return 1; |
} |
int _ykusb_stop(void) |
{ |
if (ykosxManager != NULL) { |
_ykusb_IOReturn = IOHIDManagerClose( ykosxManager, 0L ); |
|
if (_ykusb_IOReturn == kIOReturnSuccess) { |
ykosxManager = NULL; |
return 1; |
} |
} |
|
yk_errno = YK_EUSBERR; |
return 0; |
} |
static void _ykosx_CopyToCFArray(const void *value, void *context) |
{ |
CFArrayAppendValue( ( CFMutableArrayRef ) context, value ); |
} |
void *_ykusb_open_device(int vendor_id, int product_id) |
{ |
void *yk = NULL; |
CFDictionaryRef dict; |
CFStringRef keys[2]; |
CFStringRef values[2]; |
|
yk_errno = YK_EUSBERR; |
|
CFNumberRef vendorID = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, &vendor_id ); |
CFNumberRef productID = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, &product_id ); |
|
keys[0] = CFSTR( kIOHIDVendorIDKey ); values[0] = (void *) vendorID; |
keys[1] = CFSTR( kIOHIDProductIDKey ); values[1] = (void *) productID; |
dict = CFDictionaryCreate( kCFAllocatorDefault, (const void **) &keys, (const void **) &values, 1, NULL, NULL); |
IOHIDManagerSetDeviceMatching( ykosxManager, dict ); |
|
CFSetRef devSet = IOHIDManagerCopyDevices( ykosxManager ); |
|
if ( devSet ) { |
|
CFMutableArrayRef array = CFArrayCreateMutable( kCFAllocatorDefault, 0, NULL ); |
|
CFSetApplyFunction( devSet, _ykosx_CopyToCFArray, array ); |
CFIndex cnt = CFArrayGetCount( array ); |
|
if (cnt > 0) { |
yk = (void *) CFArrayGetValueAtIndex( array, 0 ); |
} |
else |
yk_errno = YK_ENOKEY; |
|
CFRelease( array ); |
CFRelease( devSet ); |
} |
|
CFRelease( dict ); |
CFRelease( vendorID ); |
CFRelease( productID ); |
|
if (yk) { |
_ykusb_IOReturn = IOHIDDeviceOpen( yk, 0L ); |
|
if ( _ykusb_IOReturn != kIOReturnSuccess ) { |
yk_release(); |
return 0; |
} |
|
return yk; |
} |
|
return 0; |
} |
int _ykusb_close_device(void *dev) |
{ |
_ykusb_IOReturn = IOHIDDeviceClose( dev, 0L ); |
|
if ( _ykusb_IOReturn == kIOReturnSuccess ) |
return 1; |
|
yk_errno = YK_EUSBERR; |
return 0; |
} |
int _ykusb_read(void *dev, int report_type, int report_number, |
char *buffer, int size) |
{ |
CFIndex sizecf = (CFIndex)size; |
if (report_type != REPORT_TYPE_FEATURE) |
{ |
yk_errno = YK_ENOTYETIMPL; |
return 0; |
} |
|
_ykusb_IOReturn = IOHIDDeviceGetReport( dev, kIOHIDReportTypeFeature, report_number, (uint8_t *)buffer, (CFIndex *) &sizecf ); |
|
if ( _ykusb_IOReturn != kIOReturnSuccess ) |
{ |
yk_errno = YK_EUSBERR; |
return 0; |
} |
return (int)sizecf; |
} |
int _ykusb_write(void *dev, int report_type, int report_number, |
char *buffer, int size) |
{ |
if (report_type != REPORT_TYPE_FEATURE) |
{ |
yk_errno = YK_ENOTYETIMPL; |
return 0; |
} |
|
_ykusb_IOReturn = IOHIDDeviceSetReport( dev, kIOHIDReportTypeFeature, report_number, (unsigned char *)buffer, size); |
|
if ( _ykusb_IOReturn != kIOReturnSuccess ) |
{ |
yk_errno = YK_EUSBERR; |
return 0; |
} |
|
return 1; |
} |
const char *_ykusb_strerror() |
{ |
return "USB error/n"; |
// fprintf(out, "USB error: %x/n", _ykusb_IOReturn); |
} |