2012-05-07 12:31:29 +02:00
/*
* HCI based Driver for NXP PN544 NFC Chip
*
* Copyright ( C ) 2012 Intel Corporation . All rights reserved .
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms and conditions of the GNU General Public License ,
* version 2 , as published by the Free Software Foundation .
*
* 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 General Public License
* along with this program ; if not , write to the
* Free Software Foundation , Inc . ,
* 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*/
# include <linux/crc-ccitt.h>
# include <linux/module.h>
# include <linux/delay.h>
# include <linux/slab.h>
# include <linux/miscdevice.h>
# include <linux/interrupt.h>
# include <linux/gpio.h>
# include <linux/i2c.h>
# include <linux/nfc.h>
# include <net/nfc/hci.h>
2012-09-18 19:45:48 +02:00
# include <net/nfc/llc.h>
2012-05-07 12:31:29 +02:00
# include <linux/nfc/pn544.h>
# define DRIVER_DESC "HCI NFC driver for PN544"
# define PN544_HCI_DRIVER_NAME "pn544_hci"
/* Timing restrictions (ms) */
# define PN544_HCI_RESETVEN_TIME 30
static struct i2c_device_id pn544_hci_id_table [ ] = {
{ " pn544 " , 0 } ,
{ }
} ;
MODULE_DEVICE_TABLE ( i2c , pn544_hci_id_table ) ;
# define HCI_MODE 0
# define FW_MODE 1
/* framing in HCI mode */
# define PN544_HCI_LLC_LEN 1
# define PN544_HCI_LLC_CRC 2
# define PN544_HCI_LLC_LEN_CRC (PN544_HCI_LLC_LEN + PN544_HCI_LLC_CRC)
# define PN544_HCI_LLC_MIN_SIZE (1 + PN544_HCI_LLC_LEN_CRC)
# define PN544_HCI_LLC_MAX_PAYLOAD 29
# define PN544_HCI_LLC_MAX_SIZE (PN544_HCI_LLC_LEN_CRC + 1 + \
PN544_HCI_LLC_MAX_PAYLOAD )
enum pn544_state {
PN544_ST_COLD ,
PN544_ST_FW_READY ,
PN544_ST_READY ,
} ;
# define FULL_VERSION_LEN 11
/* Proprietary commands */
# define PN544_WRITE 0x3f
/* Proprietary gates, events, commands and registers */
/* NFC_HCI_RF_READER_A_GATE additional registers and commands */
# define PN544_RF_READER_A_AUTO_ACTIVATION 0x10
# define PN544_RF_READER_A_CMD_CONTINUE_ACTIVATION 0x12
# define PN544_MIFARE_CMD 0x21
/* Commands that apply to all RF readers */
# define PN544_RF_READER_CMD_PRESENCE_CHECK 0x30
# define PN544_RF_READER_CMD_ACTIVATE_NEXT 0x32
/* NFC_HCI_ID_MGMT_GATE additional registers */
# define PN544_ID_MGMT_FULL_VERSION_SW 0x10
# define PN544_RF_READER_ISO15693_GATE 0x12
# define PN544_RF_READER_F_GATE 0x14
# define PN544_FELICA_ID 0x04
# define PN544_FELICA_RAW 0x20
# define PN544_RF_READER_JEWEL_GATE 0x15
# define PN544_JEWEL_RAW_CMD 0x23
# define PN544_RF_READER_NFCIP1_INITIATOR_GATE 0x30
# define PN544_RF_READER_NFCIP1_TARGET_GATE 0x31
# define PN544_SYS_MGMT_GATE 0x90
# define PN544_SYS_MGMT_INFO_NOTIFICATION 0x02
# define PN544_POLLING_LOOP_MGMT_GATE 0x94
2012-09-27 17:32:54 +08:00
# define PN544_DEP_MODE 0x01
# define PN544_DEP_ATR_REQ 0x02
# define PN544_DEP_ATR_RES 0x03
# define PN544_DEP_MERGE 0x0D
2012-05-07 12:31:29 +02:00
# define PN544_PL_RDPHASES 0x06
# define PN544_PL_EMULATION 0x07
# define PN544_PL_NFCT_DEACTIVATED 0x09
# define PN544_SWP_MGMT_GATE 0xA0
# define PN544_NFC_WI_MGMT_GATE 0xA1
2012-06-05 14:42:11 +02:00
static struct nfc_hci_gate pn544_gates [ ] = {
{ NFC_HCI_ADMIN_GATE , NFC_HCI_INVALID_PIPE } ,
{ NFC_HCI_LOOPBACK_GATE , NFC_HCI_INVALID_PIPE } ,
{ NFC_HCI_ID_MGMT_GATE , NFC_HCI_INVALID_PIPE } ,
{ NFC_HCI_LINK_MGMT_GATE , NFC_HCI_INVALID_PIPE } ,
{ NFC_HCI_RF_READER_B_GATE , NFC_HCI_INVALID_PIPE } ,
{ NFC_HCI_RF_READER_A_GATE , NFC_HCI_INVALID_PIPE } ,
{ PN544_SYS_MGMT_GATE , NFC_HCI_INVALID_PIPE } ,
{ PN544_SWP_MGMT_GATE , NFC_HCI_INVALID_PIPE } ,
{ PN544_POLLING_LOOP_MGMT_GATE , NFC_HCI_INVALID_PIPE } ,
{ PN544_NFC_WI_MGMT_GATE , NFC_HCI_INVALID_PIPE } ,
{ PN544_RF_READER_F_GATE , NFC_HCI_INVALID_PIPE } ,
{ PN544_RF_READER_JEWEL_GATE , NFC_HCI_INVALID_PIPE } ,
{ PN544_RF_READER_ISO15693_GATE , NFC_HCI_INVALID_PIPE } ,
{ PN544_RF_READER_NFCIP1_INITIATOR_GATE , NFC_HCI_INVALID_PIPE } ,
{ PN544_RF_READER_NFCIP1_TARGET_GATE , NFC_HCI_INVALID_PIPE }
2012-05-07 12:31:29 +02:00
} ;
/* Largest headroom needed for outgoing custom commands */
# define PN544_CMDS_HEADROOM 2
2012-09-07 11:08:29 +02:00
# define PN544_FRAME_HEADROOM 1
# define PN544_FRAME_TAILROOM 2
2012-05-07 12:31:29 +02:00
struct pn544_hci_info {
struct i2c_client * i2c_dev ;
2012-09-18 19:45:48 +02:00
struct nfc_hci_dev * hdev ;
2012-05-07 12:31:29 +02:00
enum pn544_state state ;
struct mutex info_lock ;
unsigned int gpio_en ;
unsigned int gpio_irq ;
unsigned int gpio_fw ;
unsigned int en_polarity ;
int hard_fault ; /*
* < 0 if hardware error occured ( e . g . i2c err )
* and prevents normal operation .
*/
2012-09-11 10:43:50 +02:00
int async_cb_type ;
data_exchange_cb_t async_cb ;
void * async_cb_context ;
2012-05-07 12:31:29 +02:00
} ;
static void pn544_hci_platform_init ( struct pn544_hci_info * info )
{
int polarity , retry , ret ;
char rset_cmd [ ] = { 0x05 , 0xF9 , 0x04 , 0x00 , 0xC3 , 0xE5 } ;
int count = sizeof ( rset_cmd ) ;
pr_info ( DRIVER_DESC " : %s \n " , __func__ ) ;
dev_info ( & info - > i2c_dev - > dev , " Detecting nfc_en polarity \n " ) ;
/* Disable fw download */
gpio_set_value ( info - > gpio_fw , 0 ) ;
for ( polarity = 0 ; polarity < 2 ; polarity + + ) {
info - > en_polarity = polarity ;
retry = 3 ;
while ( retry - - ) {
/* power off */
gpio_set_value ( info - > gpio_en , ! info - > en_polarity ) ;
usleep_range ( 10000 , 15000 ) ;
/* power on */
gpio_set_value ( info - > gpio_en , info - > en_polarity ) ;
usleep_range ( 10000 , 15000 ) ;
/* send reset */
dev_dbg ( & info - > i2c_dev - > dev , " Sending reset cmd \n " ) ;
ret = i2c_master_send ( info - > i2c_dev , rset_cmd , count ) ;
if ( ret = = count ) {
dev_info ( & info - > i2c_dev - > dev ,
" nfc_en polarity : active %s \n " ,
( polarity = = 0 ? " low " : " high " ) ) ;
goto out ;
}
}
}
dev_err ( & info - > i2c_dev - > dev ,
" Could not detect nfc_en polarity, fallback to active high \n " ) ;
out :
gpio_set_value ( info - > gpio_en , ! info - > en_polarity ) ;
}
static int pn544_hci_enable ( struct pn544_hci_info * info , int mode )
{
pr_info ( DRIVER_DESC " : %s \n " , __func__ ) ;
gpio_set_value ( info - > gpio_fw , 0 ) ;
gpio_set_value ( info - > gpio_en , info - > en_polarity ) ;
usleep_range ( 10000 , 15000 ) ;
return 0 ;
}
static void pn544_hci_disable ( struct pn544_hci_info * info )
{
pr_info ( DRIVER_DESC " : %s \n " , __func__ ) ;
gpio_set_value ( info - > gpio_fw , 0 ) ;
gpio_set_value ( info - > gpio_en , ! info - > en_polarity ) ;
usleep_range ( 10000 , 15000 ) ;
gpio_set_value ( info - > gpio_en , info - > en_polarity ) ;
usleep_range ( 10000 , 15000 ) ;
gpio_set_value ( info - > gpio_en , ! info - > en_polarity ) ;
usleep_range ( 10000 , 15000 ) ;
}
static int pn544_hci_i2c_write ( struct i2c_client * client , u8 * buf , int len )
{
int r ;
usleep_range ( 3000 , 6000 ) ;
r = i2c_master_send ( client , buf , len ) ;
if ( r = = - EREMOTEIO ) { /* Retry, chip was in standby */
usleep_range ( 6000 , 10000 ) ;
r = i2c_master_send ( client , buf , len ) ;
}
2012-09-20 08:59:10 +02:00
if ( r > = 0 ) {
if ( r ! = len )
return - EREMOTEIO ;
else
return 0 ;
}
2012-05-07 12:31:29 +02:00
return r ;
}
static int check_crc ( u8 * buf , int buflen )
{
2012-05-18 10:36:47 +03:00
int len ;
2012-05-07 12:31:29 +02:00
u16 crc ;
len = buf [ 0 ] + 1 ;
crc = crc_ccitt ( 0xffff , buf , len - 2 ) ;
crc = ~ crc ;
if ( buf [ len - 2 ] ! = ( crc & 0xff ) | | buf [ len - 1 ] ! = ( crc > > 8 ) ) {
pr_err ( PN544_HCI_DRIVER_NAME " : CRC error 0x%x != 0x%x 0x%x \n " ,
crc , buf [ len - 1 ] , buf [ len - 2 ] ) ;
pr_info ( DRIVER_DESC " : %s : BAD CRC \n " , __func__ ) ;
print_hex_dump ( KERN_DEBUG , " crc: " , DUMP_PREFIX_NONE ,
16 , 2 , buf , buflen , false ) ;
return - EPERM ;
}
return 0 ;
}
/*
* Reads an shdlc frame and returns it in a newly allocated sk_buff . Guarantees
* that i2c bus will be flushed and that next read will start on a new frame .
* returned skb contains only LLC header and payload .
* returns :
* - EREMOTEIO : i2c read error ( fatal )
* - EBADMSG : frame was incorrect and discarded
* - ENOMEM : cannot allocate skb , frame dropped
*/
static int pn544_hci_i2c_read ( struct i2c_client * client , struct sk_buff * * skb )
{
int r ;
u8 len ;
u8 tmp [ PN544_HCI_LLC_MAX_SIZE - 1 ] ;
r = i2c_master_recv ( client , & len , 1 ) ;
if ( r ! = 1 ) {
dev_err ( & client - > dev , " cannot read len byte \n " ) ;
return - EREMOTEIO ;
}
if ( ( len < ( PN544_HCI_LLC_MIN_SIZE - 1 ) ) | |
( len > ( PN544_HCI_LLC_MAX_SIZE - 1 ) ) ) {
dev_err ( & client - > dev , " invalid len byte \n " ) ;
r = - EBADMSG ;
goto flush ;
}
* skb = alloc_skb ( 1 + len , GFP_KERNEL ) ;
if ( * skb = = NULL ) {
r = - ENOMEM ;
goto flush ;
}
* skb_put ( * skb , 1 ) = len ;
r = i2c_master_recv ( client , skb_put ( * skb , len ) , len ) ;
if ( r ! = len ) {
kfree_skb ( * skb ) ;
return - EREMOTEIO ;
}
r = check_crc ( ( * skb ) - > data , ( * skb ) - > len ) ;
if ( r ! = 0 ) {
kfree_skb ( * skb ) ;
r = - EBADMSG ;
goto flush ;
}
skb_pull ( * skb , 1 ) ;
skb_trim ( * skb , ( * skb ) - > len - 2 ) ;
usleep_range ( 3000 , 6000 ) ;
return 0 ;
flush :
if ( i2c_master_recv ( client , tmp , sizeof ( tmp ) ) < 0 )
r = - EREMOTEIO ;
usleep_range ( 3000 , 6000 ) ;
return r ;
}
/*
* Reads an shdlc frame from the chip . This is not as straightforward as it
* seems . There are cases where we could loose the frame start synchronization .
* The frame format is len - data - crc , and corruption can occur anywhere while
* transiting on i2c bus , such that we could read an invalid len .
* In order to recover synchronization with the next frame , we must be sure
* to read the real amount of data without using the len byte . We do this by
* assuming the following :
* - the chip will always present only one single complete frame on the bus
* before triggering the interrupt
* - the chip will not present a new frame until we have completely read
* the previous one ( or until we have handled the interrupt ) .
* The tricky case is when we read a corrupted len that is less than the real
* len . We must detect this here in order to determine that we need to flush
* the bus . This is the reason why we check the crc here .
*/
static irqreturn_t pn544_hci_irq_thread_fn ( int irq , void * dev_id )
{
struct pn544_hci_info * info = dev_id ;
2012-09-08 21:19:44 +08:00
struct i2c_client * client ;
2012-05-07 12:31:29 +02:00
struct sk_buff * skb = NULL ;
int r ;
2012-09-08 21:19:44 +08:00
if ( ! info | | irq ! = info - > i2c_dev - > irq ) {
WARN_ON_ONCE ( 1 ) ;
return IRQ_NONE ;
}
2012-05-07 12:31:29 +02:00
2012-09-08 21:19:44 +08:00
client = info - > i2c_dev ;
2012-05-07 12:31:29 +02:00
dev_dbg ( & client - > dev , " IRQ \n " ) ;
if ( info - > hard_fault ! = 0 )
return IRQ_HANDLED ;
r = pn544_hci_i2c_read ( client , & skb ) ;
if ( r = = - EREMOTEIO ) {
info - > hard_fault = r ;
2012-09-18 19:45:48 +02:00
nfc_hci_recv_frame ( info - > hdev , NULL ) ;
2012-05-07 12:31:29 +02:00
return IRQ_HANDLED ;
} else if ( ( r = = - ENOMEM ) | | ( r = = - EBADMSG ) ) {
return IRQ_HANDLED ;
}
2012-09-18 19:45:48 +02:00
nfc_hci_recv_frame ( info - > hdev , skb ) ;
2012-05-07 12:31:29 +02:00
return IRQ_HANDLED ;
}
2012-09-18 19:45:48 +02:00
static int pn544_hci_open ( struct nfc_hci_dev * hdev )
2012-05-07 12:31:29 +02:00
{
2012-09-18 19:45:48 +02:00
struct pn544_hci_info * info = nfc_hci_get_clientdata ( hdev ) ;
2012-05-07 12:31:29 +02:00
int r = 0 ;
mutex_lock ( & info - > info_lock ) ;
if ( info - > state ! = PN544_ST_COLD ) {
r = - EBUSY ;
goto out ;
}
r = pn544_hci_enable ( info , HCI_MODE ) ;
2012-05-30 18:13:06 +02:00
if ( r = = 0 )
info - > state = PN544_ST_READY ;
2012-05-07 12:31:29 +02:00
out :
mutex_unlock ( & info - > info_lock ) ;
return r ;
}
2012-09-18 19:45:48 +02:00
static void pn544_hci_close ( struct nfc_hci_dev * hdev )
2012-05-07 12:31:29 +02:00
{
2012-09-18 19:45:48 +02:00
struct pn544_hci_info * info = nfc_hci_get_clientdata ( hdev ) ;
2012-05-07 12:31:29 +02:00
mutex_lock ( & info - > info_lock ) ;
if ( info - > state = = PN544_ST_COLD )
goto out ;
pn544_hci_disable ( info ) ;
2012-05-30 18:13:06 +02:00
info - > state = PN544_ST_COLD ;
2012-05-07 12:31:29 +02:00
out :
mutex_unlock ( & info - > info_lock ) ;
}
2012-09-18 19:45:48 +02:00
static int pn544_hci_ready ( struct nfc_hci_dev * hdev )
2012-05-07 12:31:29 +02:00
{
struct sk_buff * skb ;
static struct hw_config {
u8 adr [ 2 ] ;
u8 value ;
} hw_config [ ] = {
{ { 0x9f , 0x9a } , 0x00 } ,
{ { 0x98 , 0x10 } , 0xbc } ,
{ { 0x9e , 0x71 } , 0x00 } ,
{ { 0x98 , 0x09 } , 0x00 } ,
{ { 0x9e , 0xb4 } , 0x00 } ,
{ { 0x9e , 0xd9 } , 0xff } ,
{ { 0x9e , 0xda } , 0xff } ,
{ { 0x9e , 0xdb } , 0x23 } ,
{ { 0x9e , 0xdc } , 0x21 } ,
{ { 0x9e , 0xdd } , 0x22 } ,
{ { 0x9e , 0xde } , 0x24 } ,
{ { 0x9c , 0x01 } , 0x08 } ,
{ { 0x9e , 0xaa } , 0x01 } ,
{ { 0x9b , 0xd1 } , 0x0d } ,
{ { 0x9b , 0xd2 } , 0x24 } ,
{ { 0x9b , 0xd3 } , 0x0a } ,
{ { 0x9b , 0xd4 } , 0x22 } ,
{ { 0x9b , 0xd5 } , 0x08 } ,
{ { 0x9b , 0xd6 } , 0x1e } ,
{ { 0x9b , 0xdd } , 0x1c } ,
{ { 0x9b , 0x84 } , 0x13 } ,
{ { 0x99 , 0x81 } , 0x7f } ,
{ { 0x99 , 0x31 } , 0x70 } ,
{ { 0x98 , 0x00 } , 0x3f } ,
{ { 0x9f , 0x09 } , 0x00 } ,
{ { 0x9f , 0x0a } , 0x05 } ,
{ { 0x9e , 0xd1 } , 0xa1 } ,
{ { 0x99 , 0x23 } , 0x00 } ,
{ { 0x9e , 0x74 } , 0x80 } ,
{ { 0x9f , 0x28 } , 0x10 } ,
{ { 0x9f , 0x35 } , 0x14 } ,
{ { 0x9f , 0x36 } , 0x60 } ,
{ { 0x9c , 0x31 } , 0x00 } ,
{ { 0x9c , 0x32 } , 0xc8 } ,
{ { 0x9c , 0x19 } , 0x40 } ,
{ { 0x9c , 0x1a } , 0x40 } ,
{ { 0x9c , 0x0c } , 0x00 } ,
{ { 0x9c , 0x0d } , 0x00 } ,
{ { 0x9c , 0x12 } , 0x00 } ,
{ { 0x9c , 0x13 } , 0x00 } ,
{ { 0x98 , 0xa2 } , 0x0e } ,
{ { 0x98 , 0x93 } , 0x40 } ,
{ { 0x98 , 0x7d } , 0x02 } ,
{ { 0x98 , 0x7e } , 0x00 } ,
{ { 0x9f , 0xc8 } , 0x01 } ,
} ;
struct hw_config * p = hw_config ;
int count = ARRAY_SIZE ( hw_config ) ;
struct sk_buff * res_skb ;
u8 param [ 4 ] ;
int r ;
param [ 0 ] = 0 ;
while ( count - - ) {
param [ 1 ] = p - > adr [ 0 ] ;
param [ 2 ] = p - > adr [ 1 ] ;
param [ 3 ] = p - > value ;
r = nfc_hci_send_cmd ( hdev , PN544_SYS_MGMT_GATE , PN544_WRITE ,
param , 4 , & res_skb ) ;
if ( r < 0 )
return r ;
if ( res_skb - > len ! = 1 ) {
kfree_skb ( res_skb ) ;
return - EPROTO ;
}
if ( res_skb - > data [ 0 ] ! = p - > value ) {
kfree_skb ( res_skb ) ;
return - EIO ;
}
kfree_skb ( res_skb ) ;
p + + ;
}
param [ 0 ] = NFC_HCI_UICC_HOST_ID ;
r = nfc_hci_set_param ( hdev , NFC_HCI_ADMIN_GATE ,
NFC_HCI_ADMIN_WHITELIST , param , 1 ) ;
if ( r < 0 )
return r ;
param [ 0 ] = 0x3d ;
r = nfc_hci_set_param ( hdev , PN544_SYS_MGMT_GATE ,
PN544_SYS_MGMT_INFO_NOTIFICATION , param , 1 ) ;
if ( r < 0 )
return r ;
param [ 0 ] = 0x0 ;
r = nfc_hci_set_param ( hdev , NFC_HCI_RF_READER_A_GATE ,
PN544_RF_READER_A_AUTO_ACTIVATION , param , 1 ) ;
if ( r < 0 )
return r ;
r = nfc_hci_send_event ( hdev , NFC_HCI_RF_READER_A_GATE ,
NFC_HCI_EVT_END_OPERATION , NULL , 0 ) ;
if ( r < 0 )
return r ;
param [ 0 ] = 0x1 ;
r = nfc_hci_set_param ( hdev , PN544_POLLING_LOOP_MGMT_GATE ,
PN544_PL_NFCT_DEACTIVATED , param , 1 ) ;
if ( r < 0 )
return r ;
param [ 0 ] = 0x0 ;
r = nfc_hci_set_param ( hdev , PN544_POLLING_LOOP_MGMT_GATE ,
PN544_PL_RDPHASES , param , 1 ) ;
if ( r < 0 )
return r ;
r = nfc_hci_get_param ( hdev , NFC_HCI_ID_MGMT_GATE ,
PN544_ID_MGMT_FULL_VERSION_SW , & skb ) ;
if ( r < 0 )
return r ;
if ( skb - > len ! = FULL_VERSION_LEN ) {
kfree_skb ( skb ) ;
return - EINVAL ;
}
print_hex_dump ( KERN_DEBUG , " FULL VERSION SOFTWARE INFO: " ,
DUMP_PREFIX_NONE , 16 , 1 ,
skb - > data , FULL_VERSION_LEN , false ) ;
kfree_skb ( skb ) ;
return 0 ;
}
2012-09-07 11:08:29 +02:00
static void pn544_hci_add_len_crc ( struct sk_buff * skb )
{
u16 crc ;
int len ;
len = skb - > len + 2 ;
* skb_push ( skb , 1 ) = len ;
crc = crc_ccitt ( 0xffff , skb - > data , skb - > len ) ;
crc = ~ crc ;
* skb_put ( skb , 1 ) = crc & 0xff ;
* skb_put ( skb , 1 ) = crc > > 8 ;
}
static void pn544_hci_remove_len_crc ( struct sk_buff * skb )
{
skb_pull ( skb , PN544_FRAME_HEADROOM ) ;
skb_trim ( skb , PN544_FRAME_TAILROOM ) ;
}
2012-09-18 19:45:48 +02:00
static int pn544_hci_xmit ( struct nfc_hci_dev * hdev , struct sk_buff * skb )
2012-05-07 12:31:29 +02:00
{
2012-09-18 19:45:48 +02:00
struct pn544_hci_info * info = nfc_hci_get_clientdata ( hdev ) ;
2012-05-07 12:31:29 +02:00
struct i2c_client * client = info - > i2c_dev ;
2012-09-07 11:08:29 +02:00
int r ;
2012-05-07 12:31:29 +02:00
if ( info - > hard_fault ! = 0 )
return info - > hard_fault ;
2012-09-07 11:08:29 +02:00
pn544_hci_add_len_crc ( skb ) ;
r = pn544_hci_i2c_write ( client , skb - > data , skb - > len ) ;
pn544_hci_remove_len_crc ( skb ) ;
return r ;
2012-05-07 12:31:29 +02:00
}
2012-09-18 19:45:48 +02:00
static int pn544_hci_start_poll ( struct nfc_hci_dev * hdev ,
2012-05-15 15:57:06 +02:00
u32 im_protocols , u32 tm_protocols )
2012-05-07 12:31:29 +02:00
{
u8 phases = 0 ;
int r ;
u8 duration [ 2 ] ;
u8 activated ;
2012-09-27 17:32:54 +08:00
u8 i_mode = 0x3f ; /* Enable all supported modes */
u8 t_mode = 0x0f ;
u8 t_merge = 0x01 ; /* Enable merge by default */
2012-05-07 12:31:29 +02:00
2012-05-15 15:57:06 +02:00
pr_info ( DRIVER_DESC " : %s protocols 0x%x 0x%x \n " ,
__func__ , im_protocols , tm_protocols ) ;
2012-05-07 12:31:29 +02:00
r = nfc_hci_send_event ( hdev , NFC_HCI_RF_READER_A_GATE ,
NFC_HCI_EVT_END_OPERATION , NULL , 0 ) ;
if ( r < 0 )
return r ;
duration [ 0 ] = 0x18 ;
duration [ 1 ] = 0x6a ;
r = nfc_hci_set_param ( hdev , PN544_POLLING_LOOP_MGMT_GATE ,
PN544_PL_EMULATION , duration , 2 ) ;
if ( r < 0 )
return r ;
activated = 0 ;
r = nfc_hci_set_param ( hdev , PN544_POLLING_LOOP_MGMT_GATE ,
PN544_PL_NFCT_DEACTIVATED , & activated , 1 ) ;
if ( r < 0 )
return r ;
2012-05-15 15:57:06 +02:00
if ( im_protocols & ( NFC_PROTO_ISO14443_MASK | NFC_PROTO_MIFARE_MASK |
2012-05-07 12:31:29 +02:00
NFC_PROTO_JEWEL_MASK ) )
phases | = 1 ; /* Type A */
2012-05-15 15:57:06 +02:00
if ( im_protocols & NFC_PROTO_FELICA_MASK ) {
2012-05-07 12:31:29 +02:00
phases | = ( 1 < < 2 ) ; /* Type F 212 */
phases | = ( 1 < < 3 ) ; /* Type F 424 */
}
phases | = ( 1 < < 5 ) ; /* NFC active */
r = nfc_hci_set_param ( hdev , PN544_POLLING_LOOP_MGMT_GATE ,
PN544_PL_RDPHASES , & phases , 1 ) ;
if ( r < 0 )
return r ;
2012-09-27 17:32:54 +08:00
if ( ( im_protocols | tm_protocols ) & NFC_PROTO_NFC_DEP_MASK ) {
hdev - > gb = nfc_get_local_general_bytes ( hdev - > ndev ,
& hdev - > gb_len ) ;
pr_debug ( " generate local bytes %p " , hdev - > gb ) ;
if ( hdev - > gb = = NULL | | hdev - > gb_len = = 0 ) {
im_protocols & = ~ NFC_PROTO_NFC_DEP_MASK ;
tm_protocols & = ~ NFC_PROTO_NFC_DEP_MASK ;
}
}
if ( im_protocols & NFC_PROTO_NFC_DEP_MASK ) {
r = nfc_hci_send_event ( hdev ,
PN544_RF_READER_NFCIP1_INITIATOR_GATE ,
NFC_HCI_EVT_END_OPERATION , NULL , 0 ) ;
if ( r < 0 )
return r ;
r = nfc_hci_set_param ( hdev ,
PN544_RF_READER_NFCIP1_INITIATOR_GATE ,
PN544_DEP_MODE , & i_mode , 1 ) ;
if ( r < 0 )
return r ;
r = nfc_hci_set_param ( hdev ,
PN544_RF_READER_NFCIP1_INITIATOR_GATE ,
PN544_DEP_ATR_REQ , hdev - > gb , hdev - > gb_len ) ;
if ( r < 0 )
return r ;
r = nfc_hci_send_event ( hdev ,
PN544_RF_READER_NFCIP1_INITIATOR_GATE ,
NFC_HCI_EVT_READER_REQUESTED , NULL , 0 ) ;
if ( r < 0 )
nfc_hci_send_event ( hdev ,
PN544_RF_READER_NFCIP1_INITIATOR_GATE ,
NFC_HCI_EVT_END_OPERATION , NULL , 0 ) ;
}
if ( tm_protocols & NFC_PROTO_NFC_DEP_MASK ) {
r = nfc_hci_set_param ( hdev , PN544_RF_READER_NFCIP1_TARGET_GATE ,
PN544_DEP_MODE , & t_mode , 1 ) ;
if ( r < 0 )
return r ;
r = nfc_hci_set_param ( hdev , PN544_RF_READER_NFCIP1_TARGET_GATE ,
PN544_DEP_ATR_RES , hdev - > gb , hdev - > gb_len ) ;
if ( r < 0 )
return r ;
r = nfc_hci_set_param ( hdev , PN544_RF_READER_NFCIP1_TARGET_GATE ,
PN544_DEP_MERGE , & t_merge , 1 ) ;
if ( r < 0 )
return r ;
}
2012-05-07 12:31:29 +02:00
r = nfc_hci_send_event ( hdev , NFC_HCI_RF_READER_A_GATE ,
NFC_HCI_EVT_READER_REQUESTED , NULL , 0 ) ;
if ( r < 0 )
nfc_hci_send_event ( hdev , NFC_HCI_RF_READER_A_GATE ,
NFC_HCI_EVT_END_OPERATION , NULL , 0 ) ;
return r ;
}
2012-09-18 19:45:48 +02:00
static int pn544_hci_target_from_gate ( struct nfc_hci_dev * hdev , u8 gate ,
2012-05-07 12:31:29 +02:00
struct nfc_target * target )
{
switch ( gate ) {
case PN544_RF_READER_F_GATE :
target - > supported_protocols = NFC_PROTO_FELICA_MASK ;
break ;
case PN544_RF_READER_JEWEL_GATE :
target - > supported_protocols = NFC_PROTO_JEWEL_MASK ;
target - > sens_res = 0x0c00 ;
break ;
default :
return - EPROTO ;
}
return 0 ;
}
2012-09-18 19:45:48 +02:00
static int pn544_hci_complete_target_discovered ( struct nfc_hci_dev * hdev ,
2012-05-07 12:31:29 +02:00
u8 gate ,
struct nfc_target * target )
{
struct sk_buff * uid_skb ;
int r = 0 ;
if ( target - > supported_protocols & NFC_PROTO_MIFARE_MASK ) {
if ( target - > nfcid1_len ! = 4 & & target - > nfcid1_len ! = 7 & &
target - > nfcid1_len ! = 10 )
return - EPROTO ;
r = nfc_hci_send_cmd ( hdev , NFC_HCI_RF_READER_A_GATE ,
PN544_RF_READER_CMD_ACTIVATE_NEXT ,
target - > nfcid1 , target - > nfcid1_len , NULL ) ;
} else if ( target - > supported_protocols & NFC_PROTO_FELICA_MASK ) {
r = nfc_hci_get_param ( hdev , PN544_RF_READER_F_GATE ,
PN544_FELICA_ID , & uid_skb ) ;
if ( r < 0 )
return r ;
if ( uid_skb - > len ! = 8 ) {
kfree_skb ( uid_skb ) ;
return - EPROTO ;
}
r = nfc_hci_send_cmd ( hdev , PN544_RF_READER_F_GATE ,
PN544_RF_READER_CMD_ACTIVATE_NEXT ,
uid_skb - > data , uid_skb - > len , NULL ) ;
kfree_skb ( uid_skb ) ;
} else if ( target - > supported_protocols & NFC_PROTO_ISO14443_MASK ) {
/*
* TODO : maybe other ISO 14443 require some kind of continue
* activation , but for now we ' ve seen only this one below .
*/
if ( target - > sens_res = = 0x4403 ) /* Type 4 Mifare DESFire */
r = nfc_hci_send_cmd ( hdev , NFC_HCI_RF_READER_A_GATE ,
PN544_RF_READER_A_CMD_CONTINUE_ACTIVATION ,
NULL , 0 , NULL ) ;
}
return r ;
}
2012-09-11 10:43:50 +02:00
# define PN544_CB_TYPE_READER_F 1
static void pn544_hci_data_exchange_cb ( void * context , struct sk_buff * skb ,
int err )
{
struct pn544_hci_info * info = context ;
switch ( info - > async_cb_type ) {
case PN544_CB_TYPE_READER_F :
if ( err = = 0 )
skb_pull ( skb , 1 ) ;
info - > async_cb ( info - > async_cb_context , skb , err ) ;
break ;
default :
if ( err = = 0 )
kfree_skb ( skb ) ;
break ;
}
}
2012-05-07 12:31:29 +02:00
# define MIFARE_CMD_AUTH_KEY_A 0x60
# define MIFARE_CMD_AUTH_KEY_B 0x61
# define MIFARE_CMD_HEADER 2
# define MIFARE_UID_LEN 4
# define MIFARE_KEY_LEN 6
# define MIFARE_CMD_LEN 12
/*
* Returns :
* < = 0 : driver handled the data exchange
* 1 : driver doesn ' t especially handle , please do standard processing
*/
2012-09-18 19:45:48 +02:00
static int pn544_hci_data_exchange ( struct nfc_hci_dev * hdev ,
2012-05-07 12:31:29 +02:00
struct nfc_target * target ,
2012-09-11 10:43:50 +02:00
struct sk_buff * skb , data_exchange_cb_t cb ,
void * cb_context )
2012-05-07 12:31:29 +02:00
{
2012-09-18 19:45:48 +02:00
struct pn544_hci_info * info = nfc_hci_get_clientdata ( hdev ) ;
2012-05-07 12:31:29 +02:00
pr_info ( DRIVER_DESC " : %s for gate=%d \n " , __func__ ,
target - > hci_reader_gate ) ;
switch ( target - > hci_reader_gate ) {
case NFC_HCI_RF_READER_A_GATE :
if ( target - > supported_protocols & NFC_PROTO_MIFARE_MASK ) {
/*
* It seems that pn544 is inverting key and UID for
* MIFARE authentication commands .
*/
if ( skb - > len = = MIFARE_CMD_LEN & &
( skb - > data [ 0 ] = = MIFARE_CMD_AUTH_KEY_A | |
skb - > data [ 0 ] = = MIFARE_CMD_AUTH_KEY_B ) ) {
u8 uid [ MIFARE_UID_LEN ] ;
u8 * data = skb - > data + MIFARE_CMD_HEADER ;
memcpy ( uid , data + MIFARE_KEY_LEN ,
MIFARE_UID_LEN ) ;
memmove ( data + MIFARE_UID_LEN , data ,
MIFARE_KEY_LEN ) ;
memcpy ( data , uid , MIFARE_UID_LEN ) ;
}
2012-09-11 10:43:50 +02:00
return nfc_hci_send_cmd_async ( hdev ,
target - > hci_reader_gate ,
PN544_MIFARE_CMD ,
skb - > data , skb - > len ,
cb , cb_context ) ;
2012-05-07 12:31:29 +02:00
} else
return 1 ;
case PN544_RF_READER_F_GATE :
* skb_push ( skb , 1 ) = 0 ;
* skb_push ( skb , 1 ) = 0 ;
2012-09-11 10:43:50 +02:00
info - > async_cb_type = PN544_CB_TYPE_READER_F ;
info - > async_cb = cb ;
info - > async_cb_context = cb_context ;
return nfc_hci_send_cmd_async ( hdev , target - > hci_reader_gate ,
PN544_FELICA_RAW , skb - > data ,
skb - > len ,
pn544_hci_data_exchange_cb , info ) ;
2012-05-07 12:31:29 +02:00
case PN544_RF_READER_JEWEL_GATE :
2012-09-11 10:43:50 +02:00
return nfc_hci_send_cmd_async ( hdev , target - > hci_reader_gate ,
PN544_JEWEL_RAW_CMD , skb - > data ,
skb - > len , cb , cb_context ) ;
2012-05-07 12:31:29 +02:00
default :
return 1 ;
}
}
2012-09-18 19:45:48 +02:00
static int pn544_hci_check_presence ( struct nfc_hci_dev * hdev ,
2012-05-07 12:31:29 +02:00
struct nfc_target * target )
{
return nfc_hci_send_cmd ( hdev , target - > hci_reader_gate ,
PN544_RF_READER_CMD_PRESENCE_CHECK ,
NULL , 0 , NULL ) ;
}
2012-09-18 19:45:48 +02:00
static struct nfc_hci_ops pn544_hci_ops = {
2012-05-07 12:31:29 +02:00
. open = pn544_hci_open ,
. close = pn544_hci_close ,
. hci_ready = pn544_hci_ready ,
. xmit = pn544_hci_xmit ,
. start_poll = pn544_hci_start_poll ,
. target_from_gate = pn544_hci_target_from_gate ,
. complete_target_discovered = pn544_hci_complete_target_discovered ,
. data_exchange = pn544_hci_data_exchange ,
. check_presence = pn544_hci_check_presence ,
} ;
static int __devinit pn544_hci_probe ( struct i2c_client * client ,
const struct i2c_device_id * id )
{
struct pn544_hci_info * info ;
struct pn544_nfc_platform_data * pdata ;
int r = 0 ;
u32 protocols ;
struct nfc_hci_init_data init_data ;
dev_dbg ( & client - > dev , " %s \n " , __func__ ) ;
dev_dbg ( & client - > dev , " IRQ: %d \n " , client - > irq ) ;
if ( ! i2c_check_functionality ( client - > adapter , I2C_FUNC_I2C ) ) {
dev_err ( & client - > dev , " Need I2C_FUNC_I2C \n " ) ;
return - ENODEV ;
}
info = kzalloc ( sizeof ( struct pn544_hci_info ) , GFP_KERNEL ) ;
if ( ! info ) {
dev_err ( & client - > dev ,
" Cannot allocate memory for pn544_hci_info. \n " ) ;
r = - ENOMEM ;
goto err_info_alloc ;
}
info - > i2c_dev = client ;
info - > state = PN544_ST_COLD ;
mutex_init ( & info - > info_lock ) ;
i2c_set_clientdata ( client , info ) ;
pdata = client - > dev . platform_data ;
if ( pdata = = NULL ) {
dev_err ( & client - > dev , " No platform data \n " ) ;
r = - EINVAL ;
goto err_pdata ;
}
if ( pdata - > request_resources = = NULL ) {
dev_err ( & client - > dev , " request_resources() missing \n " ) ;
r = - EINVAL ;
goto err_pdata ;
}
r = pdata - > request_resources ( client ) ;
if ( r ) {
dev_err ( & client - > dev , " Cannot get platform resources \n " ) ;
goto err_pdata ;
}
info - > gpio_en = pdata - > get_gpio ( NFC_GPIO_ENABLE ) ;
info - > gpio_fw = pdata - > get_gpio ( NFC_GPIO_FW_RESET ) ;
info - > gpio_irq = pdata - > get_gpio ( NFC_GPIO_IRQ ) ;
pn544_hci_platform_init ( info ) ;
r = request_threaded_irq ( client - > irq , NULL , pn544_hci_irq_thread_fn ,
2012-08-25 00:40:16 +02:00
IRQF_TRIGGER_RISING | IRQF_ONESHOT ,
PN544_HCI_DRIVER_NAME , info ) ;
2012-05-07 12:31:29 +02:00
if ( r < 0 ) {
dev_err ( & client - > dev , " Unable to register IRQ handler \n " ) ;
goto err_rti ;
}
2012-06-05 14:42:11 +02:00
init_data . gate_count = ARRAY_SIZE ( pn544_gates ) ;
2012-05-07 12:31:29 +02:00
2012-06-05 14:42:11 +02:00
memcpy ( init_data . gates , pn544_gates , sizeof ( pn544_gates ) ) ;
2012-05-07 12:31:29 +02:00
/*
* TODO : Session id must include the driver name + some bus addr
* persistent info to discriminate 2 identical chips
*/
strcpy ( init_data . session_id , " ID544HCI " ) ;
protocols = NFC_PROTO_JEWEL_MASK |
NFC_PROTO_MIFARE_MASK |
NFC_PROTO_FELICA_MASK |
NFC_PROTO_ISO14443_MASK |
2012-07-04 00:14:04 +02:00
NFC_PROTO_ISO14443_B_MASK |
2012-05-07 12:31:29 +02:00
NFC_PROTO_NFC_DEP_MASK ;
2012-09-18 19:45:48 +02:00
info - > hdev = nfc_hci_allocate_device ( & pn544_hci_ops , & init_data ,
protocols , LLC_SHDLC_NAME ,
PN544_FRAME_HEADROOM +
PN544_CMDS_HEADROOM ,
PN544_FRAME_TAILROOM ,
PN544_HCI_LLC_MAX_PAYLOAD ) ;
if ( ! info - > hdev ) {
dev_err ( & client - > dev , " Cannot allocate nfc hdev. \n " ) ;
2012-05-07 12:31:29 +02:00
r = - ENOMEM ;
2012-09-18 19:45:48 +02:00
goto err_alloc_hdev ;
2012-05-07 12:31:29 +02:00
}
2012-09-18 19:45:48 +02:00
nfc_hci_set_clientdata ( info - > hdev , info ) ;
r = nfc_hci_register_device ( info - > hdev ) ;
if ( r )
goto err_regdev ;
2012-05-07 12:31:29 +02:00
return 0 ;
2012-09-18 19:45:48 +02:00
err_regdev :
nfc_hci_free_device ( info - > hdev ) ;
err_alloc_hdev :
2012-05-07 12:31:29 +02:00
free_irq ( client - > irq , info ) ;
err_rti :
if ( pdata - > free_resources ! = NULL )
pdata - > free_resources ( ) ;
err_pdata :
kfree ( info ) ;
err_info_alloc :
return r ;
}
static __devexit int pn544_hci_remove ( struct i2c_client * client )
{
struct pn544_hci_info * info = i2c_get_clientdata ( client ) ;
struct pn544_nfc_platform_data * pdata = client - > dev . platform_data ;
dev_dbg ( & client - > dev , " %s \n " , __func__ ) ;
2012-09-18 19:45:48 +02:00
nfc_hci_free_device ( info - > hdev ) ;
2012-05-07 12:31:29 +02:00
if ( info - > state ! = PN544_ST_COLD ) {
if ( pdata - > disable )
pdata - > disable ( ) ;
}
free_irq ( client - > irq , info ) ;
if ( pdata - > free_resources )
pdata - > free_resources ( ) ;
kfree ( info ) ;
return 0 ;
}
static struct i2c_driver pn544_hci_driver = {
. driver = {
. name = PN544_HCI_DRIVER_NAME ,
} ,
. probe = pn544_hci_probe ,
. id_table = pn544_hci_id_table ,
. remove = __devexit_p ( pn544_hci_remove ) ,
} ;
static int __init pn544_hci_init ( void )
{
int r ;
pr_debug ( DRIVER_DESC " : %s \n " , __func__ ) ;
r = i2c_add_driver ( & pn544_hci_driver ) ;
if ( r ) {
pr_err ( PN544_HCI_DRIVER_NAME " : driver registration failed \n " ) ;
return r ;
}
return 0 ;
}
static void __exit pn544_hci_exit ( void )
{
i2c_del_driver ( & pn544_hci_driver ) ;
}
module_init ( pn544_hci_init ) ;
module_exit ( pn544_hci_exit ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_DESCRIPTION ( DRIVER_DESC ) ;