/* * libusb_wrap.c * $Id: libusb_wrap.c,v 1.16 2004/07/03 21:13:24 rousseau Exp $ * USB access routines using the libusb library * * Created by Ludovic Rousseau on Sep 27 2002 * Copyright (c) 2002 Ludovic Rousseau * License: See file COPYING.GPL */ #include #include #include #include #include "gempc_ifdhandler.h" #include "Config.h" #include "GCdebug.h" #include "GCUtils.h" #include "GemCore.h" #include "libusb_wrap.h" #define USB_INEP 0 #define USB_OUTEP 1 /* read timeout * we must wait enough so that the card can finish its calculation */ #define USB_READ_TIMEOUT 60000 /* 1 minute timeout */ /* write timeout * we don't have to wait a long time since the card was doing nothing */ #define USB_WRITE_TIMEOUT 5000 /* 5 seconds timeout */ typedef struct { int kMyVendorID; int kMyProductID; } _usbID; /* * Add an entry to match your reader. */ static _usbID UsbIDs[] = { { 0x08E6, 0x0430 }, /* GemPC 430 */ { 0x08E6, 0x0432 }, /* GemPC 432 */ { 0x08E6, 0x0435 } /* GemPC 435 */ }; /* used to store string %s/%s (dirname/filename) like: * (/proc/bus/usb/) 001/002 (Linux) * /dev/usb0//dev/ (FreeBSD) * /dev/usb0//dev/ugen0 (OpenBSD) */ #define BUS_DEVICE_STRSIZE 32 typedef struct { usb_dev_handle *handle; struct usb_device *dev; } _usbDevice; #if (PCSCLITE_MAX_READERS-16) #error Edit this file and set the number of initialiser to PCSCLITE_MAX_READERS (default was 16 but it has changed) #endif static _usbDevice usbDevice[PCSCLITE_MAX_READERS] = { [ 0 ... (PCSCLITE_MAX_READERS-1) ] = { NULL, NULL } }; /***************************************************************************** * * OpenUSB * ****************************************************************************/ status_t OpenUSB(DWORD lun, LPTSTR device) { static struct usb_bus *busses = NULL; int id, id_number; int reader = LunToReaderIndex(lun); struct usb_bus *bus; struct usb_dev_handle *dev_handle; int device_vendor, device_product; DEBUG_COMM3("Lun: %X, Device: %s", lun, device); /* device name specified */ if (device) { if (strncmp("usb:", device, 4) != 0) { DEBUG_CRITICAL2("device name does not start with \"usb:\": %s", device); return STATUS_UNSUCCESSFUL; } if (sscanf(device, "usb:%x/%x", &device_vendor, &device_product) != 2) { DEBUG_CRITICAL2("device name can't be parsed: %s", device); return STATUS_UNSUCCESSFUL; } } if (busses == NULL) usb_init(); usb_find_busses(); usb_find_devices(); busses = usb_get_busses(); if (busses == NULL) { DEBUG_CRITICAL("No USB busses found"); return STATUS_UNSUCCESSFUL; } /* is the lun already used? */ if (usbDevice[reader].handle != NULL) { DEBUG_CRITICAL2("USB driver with lun %X already in use", lun); return STATUS_UNSUCCESSFUL; } /* find any devide corresponding to a UsbIDs entry */ id_number = sizeof(UsbIDs)/sizeof(UsbIDs[0]); /* for any supported reader */ for (id=0; idnext) { struct usb_device *dev; /* any device on this bus */ for (dev = bus->devices; dev; dev = dev->next) { if (dev->descriptor.idVendor == UsbIDs[id].kMyVendorID && dev->descriptor.idProduct == UsbIDs[id].kMyProductID) { int r, already_used; int interface; /* is it already opened? */ already_used = FALSE; for (r=0; rdirname, dev->filename); if (strcmp(usbDevice[r].dev->bus->dirname, bus->dirname) == 0 && strcmp(usbDevice[r].dev->filename, dev->filename) == 0) already_used = TRUE; } } /* this reader is already managed by us */ if (already_used) { DEBUG_INFO3("USB device %s/%s already in use. Checking next one.", bus->dirname, dev->filename); continue; } DEBUG_COMM3("Trying to open USB device: %s/%s", bus->dirname, dev->filename); dev_handle = usb_open(dev); if (dev_handle == NULL) { DEBUG_CRITICAL4("Can't usb_open(%s/%s): %s", bus->dirname, dev->filename, strerror(errno)); continue; } /* now we found a free reader and we try to use it */ if (dev->config == NULL) { DEBUG_CRITICAL3("No dev->config found for %s/%s", bus->dirname, dev->filename); return STATUS_UNSUCCESSFUL; } interface = dev->config->interface->altsetting->bInterfaceNumber; if (usb_claim_interface(dev_handle, interface) < 0) { DEBUG_CRITICAL4("Can't claim interface %s/%s: %s", bus->dirname, dev->filename, strerror(errno)); return STATUS_UNSUCCESSFUL; } DEBUG_COMM3("Using USB device: %s/%s", bus->dirname, dev->filename); /* store device information */ usbDevice[reader].handle = dev_handle; usbDevice[reader].dev = dev; goto end; } } } } if (usbDevice[reader].handle == NULL) return STATUS_UNSUCCESSFUL; end: return STATUS_SUCCESS; } /* OpenUSB */ /***************************************************************************** * * WriteUSB * ****************************************************************************/ status_t WriteUSB(DWORD lun, DWORD length, unsigned char *buffer) { int rv; int reader = LunToReaderIndex(lun); #ifdef DEBUG_LEVEL_COMM char debug_header[] = "-> 121234 "; sprintf(debug_header, "-> %06X ", (int)lun); #endif #ifdef DEBUG_LEVEL_COMM DEBUG_XXD(debug_header, buffer, length); #endif rv = usb_bulk_write(usbDevice[reader].handle, usbDevice[reader].dev->config->interface->altsetting->endpoint[USB_OUTEP].bEndpointAddress, buffer, length, USB_WRITE_TIMEOUT); if (rv < 0) { DEBUG_CRITICAL4("%s/%s: %s", usbDevice[reader].dev->bus->dirname, usbDevice[reader].dev->filename, strerror(errno)); /* reset in case of timeout (usually means a reader freeze) * The application will receive an error but can try to reconnect. * Without the patch the reader must be physically unpluged-repluged */ if (errno == ETIMEDOUT) { DEBUG_CRITICAL3("Reseting the reader: %s/%s", usbDevice[reader].dev->bus->dirname, usbDevice[reader].dev->filename); usb_reset(usbDevice[reader].handle); } return STATUS_UNSUCCESSFUL; } return STATUS_SUCCESS; } /* WriteUSB */ /***************************************************************************** * * ReadUSB * ****************************************************************************/ status_t ReadUSB(DWORD lun, DWORD * length, unsigned char *buffer) { int rv; int reader = LunToReaderIndex(lun); #ifdef DEBUG_LEVEL_COMM char debug_header[] = "<- 121234 "; sprintf(debug_header, "<- %06X ", (int)lun); #endif rv = usb_bulk_read(usbDevice[reader].handle, usbDevice[reader].dev->config->interface->altsetting->endpoint[USB_INEP].bEndpointAddress, buffer, *length, USB_READ_TIMEOUT); *length = rv; if (rv < 0) { DEBUG_CRITICAL4("%s/%s: %s", usbDevice[reader].dev->bus->dirname, usbDevice[reader].dev->filename, strerror(errno)); return STATUS_UNSUCCESSFUL; } #ifdef DEBUG_LEVEL_COMM DEBUG_XXD(debug_header, buffer, *length); #endif return STATUS_SUCCESS; } /* ReadUSB */ /***************************************************************************** * * CloseUSB * ****************************************************************************/ status_t CloseUSB(DWORD lun) { int reader = LunToReaderIndex(lun); DEBUG_COMM3("device: %s/%s", usbDevice[reader].dev->bus->dirname, usbDevice[reader].dev->filename); usb_release_interface(usbDevice[reader].handle, usbDevice[reader].dev->config->interface->altsetting->bInterfaceNumber); usb_close(usbDevice[reader].handle); /* mark the resource unused */ usbDevice[reader].handle = NULL; usbDevice[reader].dev = NULL; return STATUS_SUCCESS; } /* CloseUSB */