Hi All,
I am developing an application that should support reading from a magnetic
stripe reader and pin pad (in one unit). Am using the INGENICO 3070
Pinpad.
I came across a program posted on the libusb-devel mailing list: usb_interrupt_read -- magnetic card reader.
The usb_interrupt_read function returns -22 and times out without waiting for input from the card reader.
How do I go about this problem so that the application can wait for input from the card reader.
Any help is highly appreciated.
Thanks
Juliet.
The device descriptor attributes and values are:
Dev #8: Silicon Labs - Ingenico 3070
- Serial Number: 0001
wTotalLength: 32
bNumInterfaces: 1
bConfigurationValue: 1
iConfiguration: 0
bmAttributes: 80h
MaxPower: 250
bInterfaceNumber: 0
bAlternateSetting: 0
bNumEndpoints: 2
bInterfaceClass: 255
bInterfaceSubClass: 0
bInterfaceProtocol: 0
iInterface: 2
bEndpointAddress: 81h
bmAttributes: 02h
wMaxPacketSize: 64
bInterval: 0
bRefresh: 0
bSynchAddress: 0
bEndpointAddress: 01h
bmAttributes: 02h
wMaxPacketSize: 64
bInterval: 0
bRefresh: 0
bSynchAddress: 0
The program(libusb-devel mailing list) is here:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <usb.h>
/// some values to distinguish the card reader (values may vary from vendor to vendor)
#define CRD_RDR__VENDOR_ID 2816 ///0x0b00
#define CRD_RDR__PRODUCT_ID 12400 ///0x3070
#define CRD_INRPT_INTERFACE 0
#define CRD_INRPT_ENDPOINT 0x81
#define READ_BUFFER_SIZE_B 512
#define READ_INRPT_TIMEOUT 31800
/// PROTOTYPES ......../
int claimCrdRdrInrptInterface(usb_dev_handle *devHandle, int useKernel);
void initLibusb();
int isCardReader(u_int16_t idVendor, u_int16_t idProduct);
usb_dev_handle *getCardReader();
int blockForCardSwipe(usb_dev_handle *devHandle);
void print_endpoint(struct usb_endpoint_descriptor *endpoint);
void print_altsetting(struct usb_interface_descriptor *interface);
void print_configuration(struct usb_config_descriptor *config);
void received_packet(unsigned char *buffer) {
if (buffer[0] == 0x00 && buffer[1] != 0x00) {
fwrite(buffer+2, 6, 1, stdout);
}
}
/// MAIN METHOD ......../
int main(int argv, char *argc[])
{
usb_dev_handle *crdRdr_handle = NULL;
int retval = 0;
/* This magickal packet seems to wake it up */
unsigned char ep2_packet[8] = {
0x20, 0x10, 0x24, 0x4c, 0x54, 0x43, 0x2c, 0x31,};
unsigned char buffer[8];
initLibusb(); // initialize libusb
/// get a handle to the card reader
if((crdRdr_handle = getCardReader()) == NULL)
{
printf("ERROR getting the card reader\n");
exit(1);
}
/// claim the swipe interface
if(argv == 3)
{ // support dynamic decsion to detach from the kernel
if(claimCrdRdrInrptInterface(crdRdr_handle, atoi(argc[2]))!= 1)
{
printf("ERROR claiming the swipe interface\n");
exit(1);
}
}
else
{
if(claimCrdRdrInrptInterface(crdRdr_handle, 1)!= 1)
{
printf("ERROR claiming the swipe interface\n");
exit(1);
}
}
if(argv >= 2)
{ // support dynamic descision to attempt to read
if(atoi(argc[1]) == 1)
{
blockForCardSwipe(crdRdr_handle);
}
}
usb_release_interface(crdRdr_handle, 0);
usb_close(crdRdr_handle);
exit(0);
}
/// IMPLEMENTATION ........./
/**
* claimCrdRdrInrptInterface()
* attempt to claim the card reader interface that can be used to data from a card swipe
* return 1 on success; 0 on failure
* the useKernel parameter determines whether or not to detach from the kernel driver
* 0 will continue to use the kernel; 1 will detach from the kernel
*/
int claimCrdRdrInrptInterface(usb_dev_handle *devHandle, int useKernel)
{
int claimSuccess = 0;
printf("--> Entering claimCrdRdrInrptInterface(); input, pointer to usb_dev_handle\n");
//// TODO: SUPPORT THIS THROUGH A COMMAND LINE OPTION
if(useKernel == 0)
{
/// detach the kernel driver
(this seems to be a requirement, because usb hid is hogging this at
first
if
(LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP &&
(usb_detach_kernel_driver_np(devHandle, (int)
CRD_INRPT_INTERFACE) < 0))
{
fprintf(stderr, "Could not detach kernel driver %s\n", usb_strerror());
}
else
{
printf("Sucessfully detached from the kernel.\n");
}
}
/// attempt to claim the interface
claimSuccess = usb_claim_interface(devHandle, CRD_INRPT_INTERFACE);
/// analyze the results of the claim attempt
if(claimSuccess == 0)
{
claimSuccess = 1;
printf("%s", "The card reader interface was claimed!\n");
}
else
{
printf("%s %i %s", "Claim Failure! Return value from claim:", claimSuccess, "\n");
}
printf("<-- Exiting claimCrdRdrInrptInterface(); claimSuccess: %i\n", claimSuccess);
return claimSuccess;
}
/**
* initLibusb()
* run methods required to initialize the libusb library
*/
void initLibusb()
{
/// calls to initialize the libusb library
printf("--> Entering initLibusb(), no inputs\n");
usb_init();
usb_find_busses();
usb_find_devices();
printf("<-- Exiting initLibusb(), library initialized\n");
}
/**
* isCardReader()
* scan the device descriptor vendor and product ids against the values know to match those of the usb
* card reader. if there is a match for both values return 1, otherwise return 0.
*/
int isCardReader(u_int16_t idVendor, u_int16_t idProduct)
{
int isCardReader = 0;
printf("--> Entering isCardReader(); idVendor: %i, idProduct: %i\n", idVendor, idProduct);
if((idVendor == CRD_RDR__VENDOR_ID) && (idProduct == CRD_RDR__PRODUCT_ID))
{
isCardReader = 1;
}
else
{
isCardReader = 0;
}
printf("<-- Exiting isCardReader(); isCardReader: %i\n", isCardReader);
return isCardReader;
}
/**
* getCardReader()
* loop through all available busses searching for the usb card reader
* if the card reader is found return a pointer to the handle
* other wise return NULL
*/
usb_dev_handle *getCardReader()
{
struct usb_bus *curBus;
struct usb_device *curDev;
struct usb_dev_handle *handle = NULL;
int foundCrdRdr = 0, gth = 0;
printf("--> Entering getCardReader(); no inputs\n");
/// cycle through the USB busses on localhost
for (curBus = usb_busses; curBus; curBus = curBus->next)
{
for (curDev = curBus->devices; curDev; curDev = curDev->next)
{ // cycle through the devices on curBus
/// check if curDev is the card reader
if(isCardReader(curDev->descriptor.idVendor,
curDev->descriptor.idProduct) == 1)
{
printf("The card reader has been
found.\n", CRD_RDR__VENDOR_ID, CRD_RDR__PRODUCT_ID);
/// attempt to open the card
reader
if (!(handle = usb_open(curDev)))
{
fprintf(stderr, "Could not open the card reader!\n");
}
foundCrdRdr = 1;
break;
}
}
if(foundCrdRdr == 1)
{ // no need to process additional busses after finding the card reader
break;
}
}
if(handle == NULL)
{
printf("<-- Exiting getCardReader(); the card reader handle was NOT obtained\n");
}
else
{
printf("<-- Exiting getCardReader(); the card reader handle was obtained\n");
}
//gth = usb_set_configuration(handle, 1);
//printf("\n GTH: %d", gth);
return handle;
}
/**
* blockForCardSwipe()
* internally call the usb_interrupt_read() method of libusb which is an asyncronous
* method. this method will internally issue the call until usb_interrupt_read()
* returns finds data.
//// TODO: RUN THESE CALLS INSIDE OF A THREAD
*
*/
int blockForCardSwipe(usb_dev_handle *devHandle)
{
int swipeReadSuccess = 0; // 1 indicates success
char *swipeData; // storage of payload
int timeout = 300; //READ_INRPT_TIMEOUT; // 5 minutes if metric is seconds
int bufsize = 512;
int uirResult = 0; // store the result of the card swipe
swipeData = malloc(512 * sizeof(char));
printf("--> Entering blockForCardSwipe(); input, pointer to usb device handle\n");
printf("Waiting %i seconds for input...\n", timeout);
//printf("\nUSB Endpoint IN: %d",USB_ENDPOINT_OUT);
//int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout);
while((uirResult = usb_interrupt_read(devHandle, 0x81, swipeData, 128, timeout)) >= 0)
{
//printf("ERROR reading input from interrupt pipe: %i\n", uirResult);
//if(swipeData != NULL) {
printf("value from read method: %i;\n", uirResult);
int curCRDataByte;
for(curCRDataByte = 0; curCRDataByte < READ_BUFFER_SIZE_B; curCRDataByte++)
{
// printf("%02x ", ((int)swipeData[curCRDataByte] & 0x0ff));
printf("%c", swipeData[curCRDataByte]);
}
// break;
//}
}
//printf("DATA from card swipe: %u\n", swipeData);
printf("\nInterrupt return value is: %d\n",uirResult);
printf("<-- Exiting blockForCardSwipe(); swipeReadSuccess: %i\n", swipeReadSuccess);
return swipeReadSuccess;
}
///----- INFORMATIVE DATA OUTPUT FUNCTIONS -- these are provided in the sample code shipped from libusb in testlibusb.c
/// TODO: THESE NEED TWEAKED
void print_endpoint(struct usb_endpoint_descriptor *endpoint)
{
printf(" bEndpointAddress: %02xh\n", endpoint->bEndpointAddress);
printf(" bmAttributes: %02xh\n", endpoint->bmAttributes);
printf(" wMaxPacketSize: %d\n", endpoint->wMaxPacketSize);
printf(" bInterval: %d\n", endpoint->bInterval);
printf(" bRefresh: %d\n", endpoint->bRefresh);
printf(" bSynchAddress: %d\n", endpoint->bSynchAddress);
}
void print_altsetting(struct usb_interface_descriptor *interface)
{
int i;
printf(" bInterfaceNumber: %d\n", interface->bInterfaceNumber);
printf(" bAlternateSetting: %d\n", interface->bAlternateSetting);
printf(" bNumEndpoints: %d\n", interface->bNumEndpoints);
printf(" bInterfaceClass: %d\n", interface->bInterfaceClass);
printf(" bInterfaceSubClass: %d\n", interface->bInterfaceSubClass);
printf(" bInterfaceProtocol: %d\n", interface->bInterfaceProtocol);
printf(" iInterface: %d\n", interface->iInterface);
for (i = 0; i < interface->bNumEndpoints; i++)
print_endpoint(&interface->endpoint[i]);
}
void print_interface(struct usb_interface *interface)
{
int i;
for (i = 0; i < interface->num_altsetting; i++)
print_altsetting(&interface->altsetting[i]);
}
void print_configuration(struct usb_config_descriptor *config)
{
int i;
printf(" wTotalLength: %d\n", config->wTotalLength);
printf(" bNumInterfaces: %d\n", config->bNumInterfaces);
printf(" bConfigurationValue: %d\n", config->bConfigurationValue);
printf(" iConfiguration: %d\n", config->iConfiguration);
printf(" bmAttributes: %02xh\n", config->bmAttributes);
printf(" MaxPower: %d\n", config->MaxPower);
for (i = 0; i < config->bNumInterfaces; i++)
print_interface(&config->interface[i]);
}