2010-01-15 10:18:11 +00:00
/*-
2009-12-06 16:36:55 +00:00
* Public platform independent Near Field Communication ( NFC ) library
2012-05-29 00:33:22 +00:00
*
2012-10-21 14:09:16 +00:00
* Copyright ( C ) 2009 Roel Verdult
* Copyright ( C ) 2010 , 2011 Romain Tartière
2012-10-21 14:10:43 +00:00
* Copyright ( C ) 2010 , 2011 , 2012 Romuald Conty
2012-05-29 00:33:22 +00:00
*
2009-12-06 16:36:55 +00:00
* This program is free software : you can redistribute it and / or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation , either version 3 of the License , or ( at your
* option ) any later version .
2012-05-29 00:33:22 +00:00
*
2009-12-06 16:36:55 +00:00
* This program is distributed in the hope that it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License for
* more details .
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>
2010-01-15 10:18:11 +00:00
*/
/**
2009-12-06 16:36:55 +00:00
* @ file pn53x_usb . c
2011-03-09 13:37:16 +00:00
* @ brief Driver for PN53x using USB
2009-12-06 16:36:55 +00:00
*/
2010-01-15 10:18:11 +00:00
# ifdef HAVE_CONFIG_H
2010-09-07 17:51:03 +00:00
# include "config.h"
2010-01-15 10:18:11 +00:00
# endif // HAVE_CONFIG_H
2009-12-06 16:36:55 +00:00
/*
Thanks to d18c7db and Okko for example code
*/
# include <stdio.h>
2009-12-23 11:56:56 +00:00
# include <stdlib.h>
2011-10-17 13:03:56 +00:00
# include <inttypes.h>
# include <sys/select.h>
# include <errno.h>
2009-12-06 16:36:55 +00:00
# include <string.h>
2010-08-15 14:08:29 +00:00
# include <nfc/nfc.h>
2009-12-06 16:36:55 +00:00
2011-03-05 19:54:52 +00:00
# include "nfc-internal.h"
2013-03-02 01:08:07 +01:00
# include "buses/usbbus.h"
2011-03-05 19:54:52 +00:00
# include "chips/pn53x.h"
# include "chips/pn53x-internal.h"
# include "drivers/pn53x_usb.h"
2011-10-17 13:03:56 +00:00
# define PN53X_USB_DRIVER_NAME "pn53x_usb"
2011-09-12 14:50:01 +00:00
# define LOG_CATEGORY "libnfc.driver.pn53x_usb"
2012-11-26 21:02:03 +01:00
# define LOG_GROUP NFC_LOG_GROUP_DRIVER
2009-12-06 16:36:55 +00:00
2011-08-08 10:02:47 +00:00
# define USB_INFINITE_TIMEOUT 0
2011-03-05 19:54:52 +00:00
# define DRIVER_DATA(pnd) ((struct pn53x_usb_data*)(pnd->driver_data))
typedef enum {
UNKNOWN ,
NXP_PN531 ,
2011-04-04 14:16:36 +00:00
SONY_PN531 ,
2011-03-05 19:54:52 +00:00
NXP_PN533 ,
ASK_LOGO ,
2011-06-05 22:25:05 +00:00
SCM_SCL3711 ,
2011-06-07 20:36:20 +00:00
SONY_RCS360
2011-03-05 19:54:52 +00:00
} pn53x_usb_model ;
2012-10-21 14:10:43 +00:00
// Internal data structs
2011-03-05 19:54:52 +00:00
struct pn53x_usb_data {
usb_dev_handle * pudh ;
pn53x_usb_model model ;
uint32_t uiEndPointIn ;
uint32_t uiEndPointOut ;
uint32_t uiMaxPacketSize ;
2011-05-05 09:27:17 +00:00
volatile bool abort_flag ;
2011-03-05 19:54:52 +00:00
} ;
const struct pn53x_io pn53x_usb_io ;
2012-10-21 14:10:43 +00:00
// Prototypes
2012-05-29 15:54:36 +00:00
bool pn53x_usb_get_usb_device_name ( struct usb_device * dev , usb_dev_handle * udev , char * buffer , size_t len ) ;
int pn53x_usb_init ( nfc_device * pnd ) ;
2011-03-05 19:54:52 +00:00
2012-05-13 14:50:18 +00:00
static int
2012-05-29 15:54:36 +00:00
pn53x_usb_bulk_read ( struct pn53x_usb_data * data , uint8_t abtRx [ ] , const size_t szRx , const int timeout )
2011-03-05 19:54:52 +00:00
{
2012-05-29 15:54:36 +00:00
int res = usb_bulk_read ( data - > pudh , data - > uiEndPointIn , ( char * ) abtRx , szRx , timeout ) ;
2011-06-09 14:00:45 +00:00
if ( res > 0 ) {
2012-11-26 21:02:03 +01:00
LOG_HEX ( NFC_LOG_GROUP_COM , " RX " , abtRx , res ) ;
2011-06-09 14:00:45 +00:00
} else if ( res < 0 ) {
2011-09-22 16:21:22 +00:00
if ( res ! = - USB_TIMEDOUT )
2012-11-26 21:02:03 +01:00
log_put ( NFC_LOG_GROUP_COM , LOG_CATEGORY , NFC_LOG_PRIORITY_ERROR , " Unable to read from USB (%s) " , _usb_strerror ( res ) ) ;
2011-06-09 14:00:45 +00:00
}
2011-03-09 13:37:16 +00:00
return res ;
2011-03-05 19:54:52 +00:00
}
2012-05-13 14:50:18 +00:00
static int
2012-05-29 15:54:36 +00:00
pn53x_usb_bulk_write ( struct pn53x_usb_data * data , uint8_t abtTx [ ] , const size_t szTx , const int timeout )
2011-03-05 19:54:52 +00:00
{
2012-11-26 21:02:03 +01:00
LOG_HEX ( NFC_LOG_GROUP_COM , " TX " , abtTx , szTx ) ;
2012-05-29 15:54:36 +00:00
int res = usb_bulk_write ( data - > pudh , data - > uiEndPointOut , ( char * ) abtTx , szTx , timeout ) ;
2011-06-09 14:00:45 +00:00
if ( res > 0 ) {
// HACK This little hack is a well know problem of USB, see http://www.libusb.org/ticket/6 for more details
if ( ( res % data - > uiMaxPacketSize ) = = 0 ) {
2012-05-29 15:54:36 +00:00
usb_bulk_write ( data - > pudh , data - > uiEndPointOut , " \0 " , 0 , timeout ) ;
2011-06-09 14:00:45 +00:00
}
} else {
2012-11-26 21:02:03 +01:00
log_put ( NFC_LOG_GROUP_COM , LOG_CATEGORY , NFC_LOG_PRIORITY_ERROR , " Unable to write to USB (%s) " , _usb_strerror ( res ) ) ;
2011-05-17 10:41:26 +00:00
}
return res ;
2011-03-05 19:54:52 +00:00
}
struct pn53x_usb_supported_device {
uint16_t vendor_id ;
uint16_t product_id ;
pn53x_usb_model model ;
const char * name ;
} ;
const struct pn53x_usb_supported_device pn53x_usb_supported_devices [ ] = {
2011-04-04 09:29:14 +00:00
{ 0x04CC , 0x0531 , NXP_PN531 , " Philips / PN531 " } ,
2011-03-05 19:54:52 +00:00
{ 0x04CC , 0x2533 , NXP_PN533 , " NXP / PN533 " } ,
{ 0x04E6 , 0x5591 , SCM_SCL3711 , " SCM Micro / SCL3711-NFC&RW " } ,
2011-05-17 10:41:26 +00:00
{ 0x054c , 0x0193 , SONY_PN531 , " Sony / PN531 " } ,
2011-06-05 22:25:05 +00:00
{ 0x1FD3 , 0x0608 , ASK_LOGO , " ASK / LoGO " } ,
2011-06-07 20:36:20 +00:00
{ 0x054C , 0x02E1 , SONY_RCS360 , " Sony / FeliCa S360 [PaSoRi] " }
2011-03-05 19:54:52 +00:00
} ;
2012-05-13 14:50:18 +00:00
static pn53x_usb_model
2012-05-29 15:54:36 +00:00
pn53x_usb_get_device_model ( uint16_t vendor_id , uint16_t product_id )
2011-03-05 19:54:52 +00:00
{
2012-05-29 15:54:36 +00:00
for ( size_t n = 0 ; n < sizeof ( pn53x_usb_supported_devices ) / sizeof ( struct pn53x_usb_supported_device ) ; n + + ) {
2011-03-05 19:54:52 +00:00
if ( ( vendor_id = = pn53x_usb_supported_devices [ n ] . vendor_id ) & &
2012-05-29 15:52:51 +00:00
( product_id = = pn53x_usb_supported_devices [ n ] . product_id ) )
2011-03-05 19:54:52 +00:00
return pn53x_usb_supported_devices [ n ] . model ;
}
2011-09-22 13:03:47 +00:00
2011-03-05 19:54:52 +00:00
return UNKNOWN ;
}
2012-05-29 15:54:36 +00:00
int pn53x_usb_ack ( nfc_device * pnd ) ;
2010-10-12 15:51:57 +00:00
2009-12-06 16:36:55 +00:00
// Find transfer endpoints for bulk transfers
2012-05-13 14:50:18 +00:00
static void
2012-05-29 15:54:36 +00:00
pn53x_usb_get_end_points ( struct usb_device * dev , struct pn53x_usb_data * data )
2009-12-06 16:36:55 +00:00
{
uint32_t uiIndex ;
uint32_t uiEndPoint ;
2010-09-07 17:51:03 +00:00
struct usb_interface_descriptor * puid = dev - > config - > interface - > altsetting ;
2009-12-06 16:36:55 +00:00
// 3 Endpoints maximum: Interrupt In, Bulk In, Bulk Out
2010-09-07 17:51:03 +00:00
for ( uiIndex = 0 ; uiIndex < puid - > bNumEndpoints ; uiIndex + + ) {
2009-12-06 16:36:55 +00:00
// Only accept bulk transfer endpoints (ignore interrupt endpoints)
2010-09-07 17:51:03 +00:00
if ( puid - > endpoint [ uiIndex ] . bmAttributes ! = USB_ENDPOINT_TYPE_BULK )
continue ;
2009-12-06 16:36:55 +00:00
// Copy the endpoint to a local var, makes it more readable code
uiEndPoint = puid - > endpoint [ uiIndex ] . bEndpointAddress ;
// Test if we dealing with a bulk IN endpoint
2010-09-07 17:51:03 +00:00
if ( ( uiEndPoint & USB_ENDPOINT_DIR_MASK ) = = USB_ENDPOINT_IN ) {
2011-03-05 19:54:52 +00:00
data - > uiEndPointIn = uiEndPoint ;
data - > uiMaxPacketSize = puid - > endpoint [ uiIndex ] . wMaxPacketSize ;
2009-12-06 16:36:55 +00:00
}
// Test if we dealing with a bulk OUT endpoint
2010-09-07 17:51:03 +00:00
if ( ( uiEndPoint & USB_ENDPOINT_DIR_MASK ) = = USB_ENDPOINT_OUT ) {
2011-03-05 19:54:52 +00:00
data - > uiEndPointOut = uiEndPoint ;
data - > uiMaxPacketSize = puid - > endpoint [ uiIndex ] . wMaxPacketSize ;
2009-12-06 16:36:55 +00:00
}
}
}
2012-10-21 14:11:17 +00:00
static size_t
2012-11-26 21:02:03 +01:00
pn53x_usb_scan ( const nfc_context * context , nfc_connstring connstrings [ ] , const size_t connstrings_len )
2009-12-06 16:36:55 +00:00
{
2012-11-26 21:02:03 +01:00
( void ) context ;
2013-03-02 01:08:07 +01:00
usb_prepare ( ) ;
2012-10-21 14:11:17 +00:00
size_t device_found = 0 ;
2011-03-05 19:54:52 +00:00
uint32_t uiBusIndex = 0 ;
struct usb_bus * bus ;
2012-05-29 15:54:36 +00:00
for ( bus = usb_get_busses ( ) ; bus ; bus = bus - > next ) {
2011-03-05 19:54:52 +00:00
struct usb_device * dev ;
2011-06-09 14:00:45 +00:00
2010-09-07 17:51:03 +00:00
for ( dev = bus - > devices ; dev ; dev = dev - > next , uiBusIndex + + ) {
2012-05-29 15:54:36 +00:00
for ( size_t n = 0 ; n < sizeof ( pn53x_usb_supported_devices ) / sizeof ( struct pn53x_usb_supported_device ) ; n + + ) {
2011-03-05 19:54:52 +00:00
if ( ( pn53x_usb_supported_devices [ n ] . vendor_id = = dev - > descriptor . idVendor ) & &
( pn53x_usb_supported_devices [ n ] . product_id = = dev - > descriptor . idProduct ) ) {
2009-12-08 21:06:59 +00:00
// Make sure there are 2 endpoints available
// with libusb-win32 we got some null pointers so be robust before looking at endpoints:
2010-09-07 17:51:03 +00:00
if ( dev - > config = = NULL | | dev - > config - > interface = = NULL | | dev - > config - > interface - > altsetting = = NULL ) {
2009-12-08 21:06:59 +00:00
// Nope, we maybe want the next one, let's try to find another
continue ;
}
2010-09-07 17:51:03 +00:00
if ( dev - > config - > interface - > altsetting - > bNumEndpoints < 2 ) {
2009-12-08 21:06:59 +00:00
// Nope, we maybe want the next one, let's try to find another
continue ;
}
2011-03-05 19:54:52 +00:00
2012-05-29 15:54:36 +00:00
usb_dev_handle * udev = usb_open ( dev ) ;
2011-05-25 12:08:42 +00:00
// Set configuration
2013-03-02 01:08:07 +01:00
int res = usb_set_configuration ( udev , 1 ) ;
2011-05-25 12:08:42 +00:00
if ( res < 0 ) {
2012-11-26 21:02:03 +01:00
log_put ( LOG_GROUP , LOG_CATEGORY , NFC_LOG_PRIORITY_ERROR , " Unable to set USB configuration (%s) " , _usb_strerror ( res ) ) ;
2012-05-29 15:54:36 +00:00
usb_close ( udev ) ;
2011-05-25 12:08:42 +00:00
// we failed to use the device
continue ;
}
2012-10-21 14:11:17 +00:00
// pn53x_usb_get_usb_device_name (dev, udev, pnddDevices[device_found].acDevice, sizeof (pnddDevices[device_found].acDevice));
2012-11-26 21:02:03 +01:00
log_put ( LOG_GROUP , LOG_CATEGORY , NFC_LOG_PRIORITY_DEBUG , " device found: Bus %s Device %s " , bus - > dirname , dev - > filename ) ;
2012-05-29 15:54:36 +00:00
usb_close ( udev ) ;
2012-10-21 14:11:17 +00:00
snprintf ( connstrings [ device_found ] , sizeof ( nfc_connstring ) , " %s:%s:%s " , PN53X_USB_DRIVER_NAME , bus - > dirname , dev - > filename ) ;
device_found + + ;
2009-12-08 21:06:59 +00:00
// Test if we reach the maximum "wanted" devices
2012-10-21 14:11:17 +00:00
if ( device_found = = connstrings_len ) {
return device_found ;
2009-12-08 21:06:59 +00:00
}
2009-12-06 16:36:55 +00:00
}
2009-12-07 21:13:36 +00:00
}
}
}
2011-03-09 13:49:33 +00:00
2012-10-21 14:11:17 +00:00
return device_found ;
2009-12-07 21:13:36 +00:00
}
2011-10-17 13:03:56 +00:00
struct pn53x_usb_descriptor {
2012-01-18 13:13:36 +00:00
char * dirname ;
char * filename ;
2011-10-17 13:03:56 +00:00
} ;
2012-05-13 14:50:18 +00:00
static int
2012-05-29 15:54:36 +00:00
pn53x_usb_connstring_decode ( const nfc_connstring connstring , struct pn53x_usb_descriptor * desc )
2011-10-17 13:03:56 +00:00
{
2012-05-29 15:54:36 +00:00
int n = strlen ( connstring ) + 1 ;
char * driver_name = malloc ( n ) ;
2013-03-02 02:25:13 +01:00
if ( ! driver_name ) {
perror ( " malloc " ) ;
return 0 ;
}
2012-05-29 15:54:36 +00:00
char * dirname = malloc ( n ) ;
2013-03-02 02:25:13 +01:00
if ( ! dirname ) {
perror ( " malloc " ) ;
free ( driver_name ) ;
return 0 ;
}
2012-05-29 15:54:36 +00:00
char * filename = malloc ( n ) ;
2013-03-02 02:25:13 +01:00
if ( ! filename ) {
perror ( " malloc " ) ;
free ( driver_name ) ;
free ( dirname ) ;
return 0 ;
}
2012-01-18 13:13:36 +00:00
driver_name [ 0 ] = ' \0 ' ;
2012-05-29 15:54:36 +00:00
int res = sscanf ( connstring , " %[^:]:%[^:]:%[^:] " , driver_name , dirname , filename ) ;
2011-10-17 13:03:56 +00:00
2012-06-06 01:10:05 +00:00
if ( ! res | | ( ( 0 ! = strcmp ( driver_name , PN53X_USB_DRIVER_NAME ) ) & & ( 0 ! = strcmp ( driver_name , " usb " ) ) ) ) {
2011-10-17 13:03:56 +00:00
// Driver name does not match.
2012-01-18 13:13:36 +00:00
res = 0 ;
} else {
2012-05-29 15:54:36 +00:00
desc - > dirname = strdup ( dirname ) ;
desc - > filename = strdup ( filename ) ;
2011-10-17 13:03:56 +00:00
}
2012-05-29 15:54:36 +00:00
free ( driver_name ) ;
free ( dirname ) ;
free ( filename ) ;
2011-10-17 13:03:56 +00:00
2012-01-18 13:13:36 +00:00
return res ;
2011-10-17 13:03:56 +00:00
}
2011-03-05 19:54:52 +00:00
bool
2012-05-29 15:54:36 +00:00
pn53x_usb_get_usb_device_name ( struct usb_device * dev , usb_dev_handle * udev , char * buffer , size_t len )
2011-03-05 19:54:52 +00:00
{
* buffer = ' \0 ' ;
if ( dev - > descriptor . iManufacturer | | dev - > descriptor . iProduct ) {
if ( udev ) {
2012-05-29 15:54:36 +00:00
usb_get_string_simple ( udev , dev - > descriptor . iManufacturer , buffer , len ) ;
if ( strlen ( buffer ) > 0 )
strcpy ( buffer + strlen ( buffer ) , " / " ) ;
usb_get_string_simple ( udev , dev - > descriptor . iProduct , buffer + strlen ( buffer ) , len - strlen ( buffer ) ) ;
2011-03-05 19:54:52 +00:00
}
}
if ( ! * buffer ) {
2012-05-29 15:54:36 +00:00
for ( size_t n = 0 ; n < sizeof ( pn53x_usb_supported_devices ) / sizeof ( struct pn53x_usb_supported_device ) ; n + + ) {
2011-03-05 19:54:52 +00:00
if ( ( pn53x_usb_supported_devices [ n ] . vendor_id = = dev - > descriptor . idVendor ) & &
( pn53x_usb_supported_devices [ n ] . product_id = = dev - > descriptor . idProduct ) ) {
2012-05-29 15:54:36 +00:00
strncpy ( buffer , pn53x_usb_supported_devices [ n ] . name , len ) ;
2011-03-05 19:54:52 +00:00
return true ;
}
}
}
return false ;
}
2012-10-21 14:10:43 +00:00
static nfc_device *
2012-11-26 21:02:03 +01:00
pn53x_usb_open ( const nfc_context * context , const nfc_connstring connstring )
2009-12-07 21:13:36 +00:00
{
2012-01-18 13:13:36 +00:00
nfc_device * pnd = NULL ;
2012-01-26 21:36:08 +00:00
struct pn53x_usb_descriptor desc = { NULL , NULL } ;
2012-05-29 15:54:36 +00:00
int connstring_decode_level = pn53x_usb_connstring_decode ( connstring , & desc ) ;
2012-11-26 21:02:03 +01:00
log_put ( LOG_GROUP , LOG_CATEGORY , NFC_LOG_PRIORITY_DEBUG , " %d element(s) have been decoded from \" %s \" " , connstring_decode_level , connstring ) ;
2011-10-17 13:03:56 +00:00
if ( connstring_decode_level < 1 ) {
2012-01-18 13:13:36 +00:00
goto free_mem ;
2011-10-17 13:03:56 +00:00
}
2011-03-05 19:54:52 +00:00
struct pn53x_usb_data data = {
. pudh = NULL ,
. uiEndPointIn = 0 ,
. uiEndPointOut = 0 ,
} ;
2009-12-07 21:13:36 +00:00
struct usb_bus * bus ;
struct usb_device * dev ;
2013-03-02 01:08:07 +01:00
usb_prepare ( ) ;
2012-01-18 13:13:36 +00:00
2012-05-29 15:54:36 +00:00
for ( bus = usb_get_busses ( ) ; bus ; bus = bus - > next ) {
2011-10-17 13:03:56 +00:00
if ( connstring_decode_level > 1 ) {
// A specific bus have been specified
2012-05-29 15:54:36 +00:00
if ( 0 ! = strcmp ( bus - > dirname , desc . dirname ) )
2011-10-17 13:03:56 +00:00
continue ;
}
for ( dev = bus - > devices ; dev ; dev = dev - > next ) {
if ( connstring_decode_level > 2 ) {
// A specific dev have been specified
2012-05-29 15:54:36 +00:00
if ( 0 ! = strcmp ( dev - > filename , desc . filename ) )
2011-10-17 13:03:56 +00:00
continue ;
}
// Open the USB device
2012-05-29 15:54:36 +00:00
data . pudh = usb_open ( dev ) ;
2011-10-17 13:03:56 +00:00
// Retrieve end points
2012-05-29 15:54:36 +00:00
pn53x_usb_get_end_points ( dev , & data ) ;
2011-10-17 13:03:56 +00:00
// Set configuration
2013-03-02 01:08:07 +01:00
int res = usb_set_configuration ( data . pudh , 1 ) ;
2011-10-17 13:03:56 +00:00
if ( res < 0 ) {
2012-11-26 21:02:03 +01:00
log_put ( LOG_GROUP , LOG_CATEGORY , NFC_LOG_PRIORITY_ERROR , " Unable to set USB configuration (%s) " , _usb_strerror ( res ) ) ;
2011-10-17 13:03:56 +00:00
if ( EPERM = = - res ) {
2012-11-26 21:02:03 +01:00
log_put ( LOG_GROUP , LOG_CATEGORY , NFC_LOG_PRIORITY_INFO , " Warning: Please double check USB permissions for device %04x:%04x " , dev - > descriptor . idVendor , dev - > descriptor . idProduct ) ;
2009-12-06 16:36:55 +00:00
}
2012-05-29 15:54:36 +00:00
usb_close ( data . pudh ) ;
2011-10-17 13:03:56 +00:00
// we failed to use the specified device
2012-01-18 13:13:36 +00:00
goto free_mem ;
2011-10-17 13:03:56 +00:00
}
2009-12-06 16:36:55 +00:00
2012-05-29 15:54:36 +00:00
res = usb_claim_interface ( data . pudh , 0 ) ;
2011-10-17 13:03:56 +00:00
if ( res < 0 ) {
2012-11-26 21:02:03 +01:00
log_put ( LOG_GROUP , LOG_CATEGORY , NFC_LOG_PRIORITY_ERROR , " Unable to claim USB interface (%s) " , _usb_strerror ( res ) ) ;
2012-05-29 15:54:36 +00:00
usb_close ( data . pudh ) ;
2011-10-17 13:03:56 +00:00
// we failed to use the specified device
2012-01-18 13:13:36 +00:00
goto free_mem ;
2011-10-17 13:03:56 +00:00
}
2012-05-29 15:54:36 +00:00
data . model = pn53x_usb_get_device_model ( dev - > descriptor . idVendor , dev - > descriptor . idProduct ) ;
2011-10-17 13:03:56 +00:00
// Allocate memory for the device info and specification, fill it and return the info
2012-11-26 21:02:03 +01:00
pnd = nfc_device_new ( context , connstring ) ;
2012-05-29 15:54:36 +00:00
pn53x_usb_get_usb_device_name ( dev , data . pudh , pnd - > name , sizeof ( pnd - > name ) ) ;
2011-10-17 13:03:56 +00:00
pnd - > driver_data = malloc ( sizeof ( struct pn53x_usb_data ) ) ;
2013-03-02 02:25:13 +01:00
if ( ! pnd - > driver_data ) {
perror ( " malloc " ) ;
goto error ;
}
2012-05-29 15:54:36 +00:00
* DRIVER_DATA ( pnd ) = data ;
2011-10-17 13:03:56 +00:00
// Alloc and init chip's data
2012-05-29 15:54:36 +00:00
pn53x_data_new ( pnd , & pn53x_usb_io ) ;
2011-10-17 13:03:56 +00:00
2012-05-29 15:54:36 +00:00
switch ( DRIVER_DATA ( pnd ) - > model ) {
2012-05-29 15:52:51 +00:00
// empirical tuning
2011-10-17 13:03:56 +00:00
case ASK_LOGO :
2012-05-29 15:54:36 +00:00
CHIP_DATA ( pnd ) - > timer_correction = 50 ;
2011-10-17 13:03:56 +00:00
break ;
case SCM_SCL3711 :
case NXP_PN533 :
2012-05-29 15:54:36 +00:00
CHIP_DATA ( pnd ) - > timer_correction = 46 ;
2011-10-17 13:03:56 +00:00
break ;
case NXP_PN531 :
2012-05-29 15:54:36 +00:00
CHIP_DATA ( pnd ) - > timer_correction = 50 ;
2011-10-17 13:03:56 +00:00
break ;
case SONY_PN531 :
2012-05-29 15:54:36 +00:00
CHIP_DATA ( pnd ) - > timer_correction = 54 ;
2011-10-17 13:03:56 +00:00
break ;
2012-05-16 18:08:42 +00:00
case SONY_RCS360 :
case UNKNOWN :
2012-05-29 15:54:36 +00:00
CHIP_DATA ( pnd ) - > timer_correction = 0 ; // TODO: allow user to know if timed functions are available
2011-10-17 13:03:56 +00:00
break ;
}
pnd - > driver = & pn53x_usb_driver ;
2010-09-29 09:57:50 +00:00
2011-10-17 13:03:56 +00:00
// HACK1: Send first an ACK as Abort command, to reset chip before talking to it:
2012-05-29 15:54:36 +00:00
pn53x_usb_ack ( pnd ) ;
2010-09-29 09:57:50 +00:00
2011-10-17 13:03:56 +00:00
// HACK2: Then send a GetFirmware command to resync USB toggle bit between host & device
// in case host used set_configuration and expects the device to have reset its toggle bit, which PN53x doesn't do
2012-05-29 15:54:36 +00:00
if ( pn53x_usb_init ( pnd ) < 0 ) {
usb_close ( data . pudh ) ;
2011-10-17 13:03:56 +00:00
goto error ;
2009-12-06 16:36:55 +00:00
}
2012-05-29 15:54:36 +00:00
DRIVER_DATA ( pnd ) - > abort_flag = false ;
2012-01-18 13:13:36 +00:00
goto free_mem ;
2009-12-06 16:36:55 +00:00
}
}
2009-12-07 21:13:36 +00:00
// We ran out of devices before the index required
2012-01-18 13:13:36 +00:00
goto free_mem ;
2011-03-05 19:54:52 +00:00
error :
// Free allocated structure on error.
2012-05-29 15:54:36 +00:00
nfc_device_free ( pnd ) ;
2012-03-05 07:28:45 +00:00
pnd = NULL ;
2012-01-18 13:13:36 +00:00
free_mem :
2012-05-29 15:54:36 +00:00
free ( desc . dirname ) ;
free ( desc . filename ) ;
2012-01-18 13:13:36 +00:00
return pnd ;
2009-12-06 16:36:55 +00:00
}
2012-10-21 14:10:43 +00:00
static void
2012-05-29 15:54:36 +00:00
pn53x_usb_close ( nfc_device * pnd )
2009-12-06 16:36:55 +00:00
{
2012-05-29 15:54:36 +00:00
pn53x_usb_ack ( pnd ) ;
2010-10-12 15:51:57 +00:00
2012-05-29 15:54:36 +00:00
if ( DRIVER_DATA ( pnd ) - > model = = ASK_LOGO ) {
2011-04-08 19:27:10 +00:00
/* Set P30, P31, P32, P33, P35 to logic 1 and P34 to 0 logic */
/* ie. Switch all LEDs off and turn off progressive field */
2012-05-29 15:54:36 +00:00
pn53x_write_register ( pnd , PN53X_SFR_P3 , 0xFF , _BV ( P30 ) | _BV ( P31 ) | _BV ( P32 ) | _BV ( P33 ) | _BV ( P35 ) ) ;
2011-04-08 19:27:10 +00:00
}
2013-01-31 01:18:23 +01:00
pn53x_idle ( pnd ) ;
2011-05-09 10:09:40 +00:00
int res ;
2012-05-29 15:54:36 +00:00
if ( ( res = usb_release_interface ( DRIVER_DATA ( pnd ) - > pudh , 0 ) ) < 0 ) {
2012-11-26 21:02:03 +01:00
log_put ( LOG_GROUP , LOG_CATEGORY , NFC_LOG_PRIORITY_ERROR , " Unable to release USB interface (%s) " , _usb_strerror ( res ) ) ;
2010-07-29 12:47:51 +00:00
}
2012-05-29 15:54:36 +00:00
if ( ( res = usb_close ( DRIVER_DATA ( pnd ) - > pudh ) ) < 0 ) {
2012-11-26 21:02:03 +01:00
log_put ( LOG_GROUP , LOG_CATEGORY , NFC_LOG_PRIORITY_ERROR , " Unable to close USB connection (%s) " , _usb_strerror ( res ) ) ;
2010-08-11 16:44:34 +00:00
}
2012-05-29 15:54:36 +00:00
pn53x_data_free ( pnd ) ;
nfc_device_free ( pnd ) ;
2009-12-06 16:36:55 +00:00
}
2011-03-05 19:54:52 +00:00
# define PN53X_USB_BUFFER_LEN (PN53x_EXTENDED_FRAME__DATA_MAX_LEN + PN53x_EXTENDED_FRAME__OVERHEAD)
2012-10-21 14:10:43 +00:00
static int
2012-05-29 15:54:36 +00:00
pn53x_usb_send ( nfc_device * pnd , const uint8_t * pbtData , const size_t szData , const int timeout )
2009-12-06 16:36:55 +00:00
{
2011-11-24 10:54:42 +00:00
uint8_t abtFrame [ PN53X_USB_BUFFER_LEN ] = { 0x00 , 0x00 , 0xff } ; // Every packet must start with "00 00 ff"
2011-03-05 19:54:52 +00:00
size_t szFrame = 0 ;
2012-01-12 13:52:48 +00:00
int res = 0 ;
2009-12-06 16:36:55 +00:00
2012-05-29 15:54:36 +00:00
pn53x_build_frame ( abtFrame , & szFrame , pbtData , szData ) ;
2009-12-06 16:36:55 +00:00
2012-05-29 15:54:36 +00:00
if ( ( res = pn53x_usb_bulk_write ( DRIVER_DATA ( pnd ) , abtFrame , szFrame , timeout ) ) < 0 ) {
2012-01-12 13:52:48 +00:00
pnd - > last_error = res ;
2012-01-05 13:24:41 +00:00
return pnd - > last_error ;
2009-12-06 16:36:55 +00:00
}
2011-11-24 10:54:42 +00:00
uint8_t abtRxBuf [ PN53X_USB_BUFFER_LEN ] ;
2012-05-29 15:54:36 +00:00
if ( ( res = pn53x_usb_bulk_read ( DRIVER_DATA ( pnd ) , abtRxBuf , sizeof ( abtRxBuf ) , timeout ) ) < 0 ) {
2010-10-12 16:04:40 +00:00
// try to interrupt current device state
pn53x_usb_ack ( pnd ) ;
2012-01-26 21:36:08 +00:00
pnd - > last_error = res ;
2012-01-05 13:24:41 +00:00
return pnd - > last_error ;
2009-12-06 16:36:55 +00:00
}
2012-05-29 15:54:36 +00:00
if ( pn53x_check_ack_frame ( pnd , abtRxBuf , res ) = = 0 ) {
2011-04-27 13:16:36 +00:00
// The PN53x is running the sent command
2011-03-05 19:54:52 +00:00
} else {
2011-05-17 10:41:26 +00:00
// For some reasons (eg. send another command while a previous one is
// running), the PN533 sometimes directly replies the response packet
// instead of ACK frame, so we send a NACK frame to force PN533 to resend
// response packet. With this hack, the nextly executed function (ie.
// pn53x_usb_receive()) will be able to retreive the correct response
// packet.
2011-10-10 00:40:34 +00:00
// FIXME Sony reader is also affected by this bug but NACK is not supported
2012-05-29 15:54:36 +00:00
if ( ( res = pn53x_usb_bulk_write ( DRIVER_DATA ( pnd ) , ( uint8_t * ) pn53x_nack_frame , sizeof ( pn53x_nack_frame ) , timeout ) ) < 0 ) {
2012-01-12 13:52:48 +00:00
pnd - > last_error = res ;
2011-05-17 10:41:26 +00:00
// try to interrupt current device state
pn53x_usb_ack ( pnd ) ;
2012-01-05 13:24:41 +00:00
return pnd - > last_error ;
2011-05-17 10:41:26 +00:00
}
2011-03-05 19:54:52 +00:00
}
2012-01-05 13:24:41 +00:00
return NFC_SUCCESS ;
2011-03-05 19:54:52 +00:00
}
2011-11-25 16:13:40 +00:00
# define USB_TIMEOUT_PER_PASS 200
2012-10-21 14:10:43 +00:00
static int
2012-05-29 15:54:36 +00:00
pn53x_usb_receive ( nfc_device * pnd , uint8_t * pbtData , const size_t szDataLen , const int timeout )
2011-03-05 19:54:52 +00:00
{
size_t len ;
off_t offset = 0 ;
2010-07-31 14:20:15 +00:00
2011-11-24 10:54:42 +00:00
uint8_t abtRxBuf [ PN53X_USB_BUFFER_LEN ] ;
2011-03-09 13:37:16 +00:00
int res ;
2011-09-22 13:03:47 +00:00
/*
2011-11-25 16:13:40 +00:00
* If no timeout is specified but the command is blocking , force a 200 ms ( USB_TIMEOUT_PER_PASS )
2011-09-22 13:03:47 +00:00
* timeout to allow breaking the loop if the user wants to stop it .
*/
2011-11-25 16:13:40 +00:00
int usb_timeout ;
int remaining_time = timeout ;
2011-03-09 13:37:16 +00:00
read :
2011-11-25 16:13:40 +00:00
if ( timeout = = USB_INFINITE_TIMEOUT ) {
usb_timeout = USB_TIMEOUT_PER_PASS ;
} else {
2011-12-06 10:05:35 +00:00
// A user-provided timeout is set, we have to cut it in multiple chunk to be able to keep an nfc_abort_command() mecanism
2011-11-25 16:13:40 +00:00
remaining_time - = USB_TIMEOUT_PER_PASS ;
if ( remaining_time < = 0 ) {
2011-12-19 00:23:21 +00:00
pnd - > last_error = NFC_ETIMEOUT ;
2012-01-05 13:24:41 +00:00
return pnd - > last_error ;
2011-09-22 16:21:22 +00:00
} else {
2011-11-25 16:13:40 +00:00
usb_timeout = MIN ( remaining_time , USB_TIMEOUT_PER_PASS ) ;
2011-09-22 16:21:22 +00:00
}
}
2011-11-25 16:13:40 +00:00
2012-05-29 15:54:36 +00:00
res = pn53x_usb_bulk_read ( DRIVER_DATA ( pnd ) , abtRxBuf , sizeof ( abtRxBuf ) , usb_timeout ) ;
2011-05-05 09:27:17 +00:00
2011-09-29 14:53:52 +00:00
if ( res = = - USB_TIMEDOUT ) {
2012-05-29 15:54:36 +00:00
if ( DRIVER_DATA ( pnd ) - > abort_flag ) {
DRIVER_DATA ( pnd ) - > abort_flag = false ;
pn53x_usb_ack ( pnd ) ;
2011-12-19 00:23:21 +00:00
pnd - > last_error = NFC_EOPABORTED ;
2012-01-05 13:24:41 +00:00
return pnd - > last_error ;
2011-05-05 09:27:17 +00:00
} else {
goto read ;
2011-03-09 13:37:16 +00:00
}
}
2011-03-05 19:54:52 +00:00
if ( res < 0 ) {
2010-10-12 16:04:40 +00:00
// try to interrupt current device state
pn53x_usb_ack ( pnd ) ;
2012-01-26 21:36:08 +00:00
pnd - > last_error = res ;
2012-01-05 13:24:41 +00:00
return pnd - > last_error ;
2010-09-07 17:51:03 +00:00
}
2009-12-06 16:36:55 +00:00
2011-11-24 10:54:42 +00:00
const uint8_t pn53x_preamble [ 3 ] = { 0x00 , 0x00 , 0xff } ;
2012-05-29 15:54:36 +00:00
if ( 0 ! = ( memcmp ( abtRxBuf , pn53x_preamble , 3 ) ) ) {
2012-11-26 21:02:03 +01:00
log_put ( LOG_GROUP , LOG_CATEGORY , NFC_LOG_PRIORITY_ERROR , " %s " , " Frame preamble+start code mismatch " ) ;
2011-12-19 00:23:21 +00:00
pnd - > last_error = NFC_EIO ;
2012-01-05 13:24:41 +00:00
return pnd - > last_error ;
2011-03-05 19:54:52 +00:00
}
offset + = 3 ;
if ( ( 0x01 = = abtRxBuf [ offset ] ) & & ( 0xff = = abtRxBuf [ offset + 1 ] ) ) {
// Error frame
2012-11-26 21:02:03 +01:00
log_put ( LOG_GROUP , LOG_CATEGORY , NFC_LOG_PRIORITY_ERROR , " %s " , " Application level error detected " ) ;
2011-12-19 00:23:21 +00:00
pnd - > last_error = NFC_EIO ;
2012-01-05 13:24:41 +00:00
return pnd - > last_error ;
2011-03-05 19:54:52 +00:00
} else if ( ( 0xff = = abtRxBuf [ offset ] ) & & ( 0xff = = abtRxBuf [ offset + 1 ] ) ) {
// Extended frame
2011-05-06 15:03:08 +00:00
offset + = 2 ;
// (abtRxBuf[offset] << 8) + abtRxBuf[offset + 1] (LEN) include TFI + (CC+1)
len = ( abtRxBuf [ offset ] < < 8 ) + abtRxBuf [ offset + 1 ] - 2 ;
if ( ( ( abtRxBuf [ offset ] + abtRxBuf [ offset + 1 ] + abtRxBuf [ offset + 2 ] ) % 256 ) ! = 0 ) {
// TODO: Retry
2012-11-26 21:02:03 +01:00
log_put ( LOG_GROUP , LOG_CATEGORY , NFC_LOG_PRIORITY_ERROR , " %s " , " Length checksum mismatch " ) ;
2011-12-19 00:23:21 +00:00
pnd - > last_error = NFC_EIO ;
2012-01-05 13:24:41 +00:00
return pnd - > last_error ;
2011-05-06 15:03:08 +00:00
}
2011-03-05 19:54:52 +00:00
offset + = 3 ;
} else {
// Normal frame
if ( 256 ! = ( abtRxBuf [ offset ] + abtRxBuf [ offset + 1 ] ) ) {
// TODO: Retry
2012-11-26 21:02:03 +01:00
log_put ( LOG_GROUP , LOG_CATEGORY , NFC_LOG_PRIORITY_ERROR , " %s " , " Length checksum mismatch " ) ;
2011-12-19 00:23:21 +00:00
pnd - > last_error = NFC_EIO ;
2012-01-05 13:24:41 +00:00
return pnd - > last_error ;
2011-03-05 19:54:52 +00:00
}
2010-08-20 10:06:19 +00:00
2011-03-05 19:54:52 +00:00
// abtRxBuf[3] (LEN) include TFI + (CC+1)
len = abtRxBuf [ offset ] - 2 ;
offset + = 2 ;
}
2009-12-06 16:36:55 +00:00
2011-03-05 19:54:52 +00:00
if ( len > szDataLen ) {
2012-11-26 21:02:03 +01:00
log_put ( LOG_GROUP , LOG_CATEGORY , NFC_LOG_PRIORITY_ERROR , " Unable to receive data: buffer too small. (szDataLen: %zu, len: %zu) " , szDataLen , len ) ;
2011-12-19 00:23:21 +00:00
pnd - > last_error = NFC_EIO ;
2012-01-05 13:24:41 +00:00
return pnd - > last_error ;
2009-12-07 21:13:36 +00:00
}
2009-12-06 16:36:55 +00:00
2011-03-05 19:54:52 +00:00
// TFI + PD0 (CC+1)
if ( abtRxBuf [ offset ] ! = 0xD5 ) {
2012-11-26 21:02:03 +01:00
log_put ( LOG_GROUP , LOG_CATEGORY , NFC_LOG_PRIORITY_ERROR , " %s " , " TFI Mismatch " ) ;
2011-12-19 00:23:21 +00:00
pnd - > last_error = NFC_EIO ;
2012-01-05 13:24:41 +00:00
return pnd - > last_error ;
2011-03-05 19:54:52 +00:00
}
offset + = 1 ;
2009-12-06 16:36:55 +00:00
2012-05-29 15:54:36 +00:00
if ( abtRxBuf [ offset ] ! = CHIP_DATA ( pnd ) - > last_command + 1 ) {
2012-11-26 21:02:03 +01:00
log_put ( LOG_GROUP , LOG_CATEGORY , NFC_LOG_PRIORITY_ERROR , " %s " , " Command Code verification failed " ) ;
2011-12-19 00:23:21 +00:00
pnd - > last_error = NFC_EIO ;
2012-01-05 13:24:41 +00:00
return pnd - > last_error ;
2011-03-05 19:54:52 +00:00
}
offset + = 1 ;
2012-05-29 15:54:36 +00:00
memcpy ( pbtData , abtRxBuf + offset , len ) ;
2011-03-05 19:54:52 +00:00
offset + = len ;
2011-11-24 10:54:42 +00:00
uint8_t btDCS = ( 256 - 0xD5 ) ;
2012-05-29 15:54:36 +00:00
btDCS - = CHIP_DATA ( pnd ) - > last_command + 1 ;
2011-03-05 19:54:52 +00:00
for ( size_t szPos = 0 ; szPos < len ; szPos + + ) {
btDCS - = pbtData [ szPos ] ;
}
if ( btDCS ! = abtRxBuf [ offset ] ) {
2012-11-26 21:02:03 +01:00
log_put ( LOG_GROUP , LOG_CATEGORY , NFC_LOG_PRIORITY_ERROR , " %s " , " Data checksum mismatch " ) ;
2011-12-19 00:23:21 +00:00
pnd - > last_error = NFC_EIO ;
2012-01-05 13:24:41 +00:00
return pnd - > last_error ;
2011-03-05 19:54:52 +00:00
}
offset + = 1 ;
if ( 0x00 ! = abtRxBuf [ offset ] ) {
2012-11-26 21:02:03 +01:00
log_put ( LOG_GROUP , LOG_CATEGORY , NFC_LOG_PRIORITY_ERROR , " %s " , " Frame postamble mismatch " ) ;
2011-12-19 00:23:21 +00:00
pnd - > last_error = NFC_EIO ;
2012-01-05 13:24:41 +00:00
return pnd - > last_error ;
2011-03-05 19:54:52 +00:00
}
2011-04-27 13:16:36 +00:00
// The PN53x command is done and we successfully received the reply
2011-12-15 16:02:38 +00:00
pnd - > last_error = 0 ;
2011-03-05 19:54:52 +00:00
return len ;
2009-12-06 16:36:55 +00:00
}
2010-10-12 15:51:57 +00:00
2011-03-05 19:54:52 +00:00
int
2012-05-29 15:54:36 +00:00
pn53x_usb_ack ( nfc_device * pnd )
2010-10-12 15:51:57 +00:00
{
2013-01-30 00:56:47 +01:00
return pn53x_usb_bulk_write ( DRIVER_DATA ( pnd ) , ( uint8_t * ) pn53x_ack_frame , sizeof ( pn53x_ack_frame ) , 1000 ) ;
2010-10-12 15:51:57 +00:00
}
2011-03-05 19:54:52 +00:00
2012-01-05 14:05:43 +00:00
int
2012-05-29 15:54:36 +00:00
pn53x_usb_init ( nfc_device * pnd )
2011-03-05 19:54:52 +00:00
{
2012-01-05 14:05:43 +00:00
int res = 0 ;
2011-05-05 09:27:17 +00:00
// Sometimes PN53x USB doesn't reply ACK one the first frame, so we need to send a dummy one...
2011-06-07 20:36:20 +00:00
//pn53x_check_communication (pnd); // Sony RC-S360 doesn't support this command for now so let's use a get_firmware_version instead:
2011-11-24 10:54:42 +00:00
const uint8_t abtCmd [ ] = { GetFirmwareVersion } ;
2012-05-30 23:02:34 +00:00
pn53x_transceive ( pnd , abtCmd , sizeof ( abtCmd ) , NULL , 0 , - 1 ) ;
2011-05-05 09:27:17 +00:00
// ...and we don't care about error
2011-12-15 16:02:38 +00:00
pnd - > last_error = 0 ;
2012-05-29 15:54:36 +00:00
if ( SONY_RCS360 = = DRIVER_DATA ( pnd ) - > model ) {
2012-11-26 21:02:03 +01:00
log_put ( LOG_GROUP , LOG_CATEGORY , NFC_LOG_PRIORITY_DEBUG , " %s " , " SONY RC-S360 initialization. " ) ;
2011-11-24 10:54:42 +00:00
const uint8_t abtCmd2 [ ] = { 0x18 , 0x01 } ;
2012-05-30 23:02:34 +00:00
pn53x_transceive ( pnd , abtCmd2 , sizeof ( abtCmd2 ) , NULL , 0 , - 1 ) ;
2012-05-29 15:54:36 +00:00
pn53x_usb_ack ( pnd ) ;
2011-06-07 20:36:20 +00:00
}
2011-05-05 09:27:17 +00:00
2012-05-29 15:54:36 +00:00
if ( ( res = pn53x_init ( pnd ) ) < 0 )
2012-01-05 14:05:43 +00:00
return res ;
2011-03-05 19:54:52 +00:00
2012-05-29 15:54:36 +00:00
if ( ASK_LOGO = = DRIVER_DATA ( pnd ) - > model ) {
2012-11-26 21:02:03 +01:00
log_put ( LOG_GROUP , LOG_CATEGORY , NFC_LOG_PRIORITY_DEBUG , " %s " , " ASK LoGO initialization. " ) ;
2011-03-07 02:47:21 +00:00
/* Internal registers */
/* Disable 100mA current limit, Power on Secure IC (SVDD) */
2012-05-29 15:54:36 +00:00
pn53x_write_register ( pnd , PN53X_REG_Control_switch_rng , 0xFF , SYMBOL_CURLIMOFF | SYMBOL_SIC_SWITCH_EN | SYMBOL_RANDOM_DATAREADY ) ;
2011-03-07 02:47:21 +00:00
/* Select the signal to be output on SIGOUT: Modulation signal (envelope) from the internal coder */
2012-05-29 15:54:36 +00:00
pn53x_write_register ( pnd , PN53X_REG_CIU_TxSel , 0xFF , 0x14 ) ;
2011-03-07 02:47:21 +00:00
/* SFR Registers */
/* Setup push-pulls for pins from P30 to P35 */
2012-05-29 15:54:36 +00:00
pn53x_write_register ( pnd , PN53X_SFR_P3CFGB , 0xFF , 0x37 ) ;
2011-03-07 02:47:21 +00:00
2012-05-29 15:52:51 +00:00
/*
On ASK LoGO hardware :
LEDs port bits definition :
* LED 1 : bit 2 ( P32 )
* LED 2 : bit 1 ( P31 )
* LED 3 : bit 0 or 3 ( depending of hardware revision ) ( P30 or P33 )
* LED 4 : bit 5 ( P35 )
Notes :
* Set logical 0 to switch LED on ; logical 1 to switch LED off .
* Bit 4 should be maintained at 1 to keep RF field on .
Progressive field activation :
The ASK LoGO hardware can progressively power - up the antenna .
To use this feature we have to switch on the field by switching on
the field on PN533 ( RFConfiguration ) then set P34 to ' 1 ' , and cut - off the
field by switching off the field on PN533 then set P34 to ' 0 ' .
*/
2011-03-07 02:47:21 +00:00
2011-05-05 12:45:56 +00:00
/* Set P30, P31, P33, P35 to logic 1 and P32, P34 to 0 logic */
/* ie. Switch LED1 on and turn off progressive field */
2012-05-29 15:54:36 +00:00
pn53x_write_register ( pnd , PN53X_SFR_P3 , 0xFF , _BV ( P30 ) | _BV ( P31 ) | _BV ( P33 ) | _BV ( P35 ) ) ;
2011-03-05 19:54:52 +00:00
}
2012-01-05 14:05:43 +00:00
return NFC_SUCCESS ;
2011-03-05 19:54:52 +00:00
}
2012-05-13 14:50:18 +00:00
static int
2012-05-29 15:54:36 +00:00
pn53x_usb_set_property_bool ( nfc_device * pnd , const nfc_property property , const bool bEnable )
2011-04-04 09:53:33 +00:00
{
2011-12-20 11:25:33 +00:00
int res = 0 ;
2012-05-29 15:54:36 +00:00
if ( ( res = pn53x_set_property_bool ( pnd , property , bEnable ) ) < 0 )
2011-12-15 16:02:38 +00:00
return res ;
2011-04-04 09:53:33 +00:00
2012-05-29 15:54:36 +00:00
switch ( DRIVER_DATA ( pnd ) - > model ) {
2011-04-08 14:42:29 +00:00
case ASK_LOGO :
2011-12-14 16:01:00 +00:00
if ( NP_ACTIVATE_FIELD = = property ) {
2011-05-05 12:45:56 +00:00
/* Switch on/off LED2 and Progressive Field GPIO according to ACTIVATE_FIELD option */
2012-11-26 21:02:03 +01:00
log_put ( LOG_GROUP , LOG_CATEGORY , NFC_LOG_PRIORITY_DEBUG , " Switch progressive field %s " , bEnable ? " On " : " Off " ) ;
2012-05-29 15:54:36 +00:00
if ( ( res = pn53x_write_register ( pnd , PN53X_SFR_P3 , _BV ( P31 ) | _BV ( P34 ) , bEnable ? _BV ( P34 ) : _BV ( P31 ) ) ) < 0 )
2011-12-15 16:02:38 +00:00
return NFC_ECHIP ;
2011-04-08 14:42:29 +00:00
}
break ;
case SCM_SCL3711 :
2011-12-14 16:01:00 +00:00
if ( NP_ACTIVATE_FIELD = = property ) {
2011-04-08 19:11:42 +00:00
// Switch on/off LED according to ACTIVATE_FIELD option
2012-05-29 15:54:36 +00:00
if ( ( res = pn53x_write_register ( pnd , PN53X_SFR_P3 , _BV ( P32 ) , bEnable ? 0 : _BV ( P32 ) ) ) < 0 )
2011-12-20 11:25:33 +00:00
return res ;
2011-04-08 14:42:29 +00:00
}
break ;
2012-05-16 18:08:42 +00:00
case NXP_PN531 :
case NXP_PN533 :
case SONY_PN531 :
case SONY_RCS360 :
case UNKNOWN :
// Nothing to do.
2011-04-08 14:42:29 +00:00
break ;
2011-04-04 09:53:33 +00:00
}
2011-12-14 16:01:00 +00:00
return NFC_SUCCESS ;
2011-04-04 09:53:33 +00:00
}
2012-05-13 14:50:18 +00:00
static int
2012-05-29 15:54:36 +00:00
pn53x_usb_abort_command ( nfc_device * pnd )
2011-05-05 09:27:17 +00:00
{
2012-05-29 15:54:36 +00:00
DRIVER_DATA ( pnd ) - > abort_flag = true ;
2012-01-05 14:49:02 +00:00
return NFC_SUCCESS ;
2011-05-05 09:27:17 +00:00
}
2011-03-05 19:54:52 +00:00
const struct pn53x_io pn53x_usb_io = {
. send = pn53x_usb_send ,
. receive = pn53x_usb_receive ,
} ;
2012-01-17 14:17:01 +00:00
const struct nfc_driver pn53x_usb_driver = {
2011-10-17 13:03:56 +00:00
. name = PN53X_USB_DRIVER_NAME ,
2012-10-21 14:11:17 +00:00
. scan = pn53x_usb_scan ,
2012-01-17 15:21:56 +00:00
. open = pn53x_usb_open ,
2012-01-17 14:52:39 +00:00
. close = pn53x_usb_close ,
2011-10-17 13:03:56 +00:00
. strerror = pn53x_strerror ,
2011-03-05 19:54:52 +00:00
2011-04-08 14:30:23 +00:00
. initiator_init = pn53x_initiator_init ,
2012-06-04 00:16:28 +00:00
. initiator_init_secure_element = NULL , // No secure-element support
2011-05-05 12:45:56 +00:00
. initiator_select_passive_target = pn53x_initiator_select_passive_target ,
2011-10-03 11:19:08 +00:00
. initiator_poll_target = pn53x_initiator_poll_target ,
2011-03-05 19:54:52 +00:00
. initiator_select_dep_target = pn53x_initiator_select_dep_target ,
. initiator_deselect_target = pn53x_initiator_deselect_target ,
. initiator_transceive_bytes = pn53x_initiator_transceive_bytes ,
. initiator_transceive_bits = pn53x_initiator_transceive_bits ,
2011-04-04 14:16:36 +00:00
. initiator_transceive_bytes_timed = pn53x_initiator_transceive_bytes_timed ,
. initiator_transceive_bits_timed = pn53x_initiator_transceive_bits_timed ,
2012-05-27 22:34:21 +00:00
. initiator_target_is_present = pn53x_initiator_target_is_present ,
2011-03-05 19:54:52 +00:00
. target_init = pn53x_target_init ,
. target_send_bytes = pn53x_target_send_bytes ,
. target_receive_bytes = pn53x_target_receive_bytes ,
. target_send_bits = pn53x_target_send_bits ,
. target_receive_bits = pn53x_target_receive_bits ,
2012-05-17 00:48:47 +00:00
. device_set_property_bool = pn53x_usb_set_property_bool ,
. device_set_property_int = pn53x_set_property_int ,
. get_supported_modulation = pn53x_get_supported_modulation ,
. get_supported_baud_rate = pn53x_get_supported_baud_rate ,
. device_get_information_about = pn53x_get_information_about ,
2011-05-05 09:27:17 +00:00
. abort_command = pn53x_usb_abort_command ,
2013-01-31 01:15:03 +01:00
. idle = pn53x_idle ,
. powerdown = pn53x_PowerDown ,
2011-03-05 19:54:52 +00:00
} ;