2011-09-18 11:19:35 +03:00
/*
* The NFC Controller Interface is the communication protocol between an
* NFC Controller ( NFCC ) and a Device Host ( DH ) .
*
* Copyright ( C ) 2011 Texas Instruments , Inc .
2013-05-29 15:35:02 +02:00
* Copyright ( C ) 2013 Intel Corporation . All rights reserved .
2011-09-18 11:19:35 +03:00
*
* Written by Ilan Elias < ilane @ ti . com >
*
* Acknowledgements :
* This file is based on hci_core . h , which was written
* by Maxim Krasnyansky .
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms 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
*
*/
# ifndef __NCI_CORE_H
# define __NCI_CORE_H
# include <linux/interrupt.h>
# include <linux/skbuff.h>
# include <net/nfc/nfc.h>
# include <net/nfc/nci.h>
2012-01-18 13:16:12 +02:00
/* NCI device flags */
enum nci_flag {
2011-09-18 11:19:35 +03:00
NCI_INIT ,
NCI_UP ,
2011-09-22 11:36:19 +03:00
NCI_DATA_EXCHANGE ,
2012-01-17 12:03:50 +02:00
NCI_DATA_EXCHANGE_TO ,
2011-09-18 11:19:35 +03:00
} ;
2012-01-18 13:16:12 +02:00
/* NCI device states */
enum nci_state {
NCI_IDLE ,
NCI_DISCOVERY ,
2012-01-18 13:16:14 +02:00
NCI_W4_ALL_DISCOVERIES ,
NCI_W4_HOST_SELECT ,
2012-01-18 13:16:12 +02:00
NCI_POLL_ACTIVE ,
} ;
2011-09-18 11:19:35 +03:00
/* NCI timeouts */
# define NCI_RESET_TIMEOUT 5000
# define NCI_INIT_TIMEOUT 5000
2012-08-15 11:46:22 +03:00
# define NCI_SET_CONFIG_TIMEOUT 5000
2011-09-18 11:19:35 +03:00
# define NCI_RF_DISC_TIMEOUT 5000
2012-01-18 13:16:14 +02:00
# define NCI_RF_DISC_SELECT_TIMEOUT 5000
2012-01-08 13:43:02 +02:00
# define NCI_RF_DEACTIVATE_TIMEOUT 30000
2011-09-18 11:19:35 +03:00
# define NCI_CMD_TIMEOUT 5000
2012-01-17 12:03:50 +02:00
# define NCI_DATA_TIMEOUT 700
2011-09-18 11:19:35 +03:00
struct nci_dev ;
struct nci_ops {
int ( * open ) ( struct nci_dev * ndev ) ;
int ( * close ) ( struct nci_dev * ndev ) ;
2013-05-22 11:36:17 +02:00
int ( * send ) ( struct nci_dev * ndev , struct sk_buff * skb ) ;
2011-09-18 11:19:35 +03:00
} ;
# define NCI_MAX_SUPPORTED_RF_INTERFACES 4
2012-01-18 13:16:14 +02:00
# define NCI_MAX_DISCOVERED_TARGETS 10
2011-09-18 11:19:35 +03:00
/* NCI Core structures */
struct nci_dev {
struct nfc_dev * nfc_dev ;
struct nci_ops * ops ;
int tx_headroom ;
int tx_tailroom ;
2012-01-18 13:16:12 +02:00
atomic_t state ;
2011-09-18 11:19:35 +03:00
unsigned long flags ;
atomic_t cmd_cnt ;
atomic_t credits_cnt ;
struct timer_list cmd_timer ;
2012-01-17 12:03:50 +02:00
struct timer_list data_timer ;
2011-09-18 11:19:35 +03:00
struct workqueue_struct * cmd_wq ;
struct work_struct cmd_work ;
struct workqueue_struct * rx_wq ;
struct work_struct rx_work ;
struct workqueue_struct * tx_wq ;
struct work_struct tx_work ;
struct sk_buff_head cmd_q ;
struct sk_buff_head rx_q ;
struct sk_buff_head tx_q ;
struct mutex req_lock ;
struct completion req_completion ;
__u32 req_status ;
__u32 req_result ;
void * driver_data ;
__u32 poll_prots ;
__u32 target_active_prot ;
2012-01-18 13:16:14 +02:00
struct nfc_target targets [ NCI_MAX_DISCOVERED_TARGETS ] ;
int n_targets ;
2011-09-18 11:19:35 +03:00
/* received during NCI_OP_CORE_RESET_RSP */
__u8 nci_ver ;
/* received during NCI_OP_CORE_INIT_RSP */
__u32 nfcc_features ;
__u8 num_supported_rf_interfaces ;
__u8 supported_rf_interfaces
[ NCI_MAX_SUPPORTED_RF_INTERFACES ] ;
__u8 max_logical_connections ;
__u16 max_routing_table_size ;
2011-11-09 12:09:14 +02:00
__u8 max_ctrl_pkt_payload_len ;
__u16 max_size_for_large_params ;
__u8 manufact_id ;
__u32 manufact_specific_info ;
2011-09-18 11:19:35 +03:00
2011-12-20 16:57:40 +02:00
/* received during NCI_OP_RF_INTF_ACTIVATED_NTF */
__u8 max_data_pkt_payload_size ;
__u8 initial_num_credits ;
2011-09-18 11:19:35 +03:00
/* stored during nci_data_exchange */
data_exchange_cb_t data_exchange_cb ;
void * data_exchange_cb_context ;
struct sk_buff * rx_data_reassembly ;
2012-08-15 11:46:24 +03:00
/* stored during intf_activated_ntf */
__u8 remote_gb [ NFC_MAX_GT_LEN ] ;
__u8 remote_gb_len ;
2011-09-18 11:19:35 +03:00
} ;
/* ----- NCI Devices ----- */
struct nci_dev * nci_allocate_device ( struct nci_ops * ops ,
2012-03-05 01:03:54 +01:00
__u32 supported_protocols ,
int tx_headroom ,
int tx_tailroom ) ;
2011-09-18 11:19:35 +03:00
void nci_free_device ( struct nci_dev * ndev ) ;
int nci_register_device ( struct nci_dev * ndev ) ;
void nci_unregister_device ( struct nci_dev * ndev ) ;
2013-05-22 11:36:17 +02:00
int nci_recv_frame ( struct nci_dev * ndev , struct sk_buff * skb ) ;
2011-09-18 11:19:35 +03:00
static inline struct sk_buff * nci_skb_alloc ( struct nci_dev * ndev ,
2012-03-05 01:03:54 +01:00
unsigned int len ,
gfp_t how )
2011-09-18 11:19:35 +03:00
{
struct sk_buff * skb ;
skb = alloc_skb ( len + ndev - > tx_headroom + ndev - > tx_tailroom , how ) ;
if ( skb )
skb_reserve ( skb , ndev - > tx_headroom ) ;
return skb ;
}
static inline void nci_set_parent_dev ( struct nci_dev * ndev , struct device * dev )
{
nfc_set_parent_dev ( ndev - > nfc_dev , dev ) ;
}
static inline void nci_set_drvdata ( struct nci_dev * ndev , void * data )
{
ndev - > driver_data = data ;
}
static inline void * nci_get_drvdata ( struct nci_dev * ndev )
{
return ndev - > driver_data ;
}
void nci_rsp_packet ( struct nci_dev * ndev , struct sk_buff * skb ) ;
void nci_ntf_packet ( struct nci_dev * ndev , struct sk_buff * skb ) ;
void nci_rx_data_packet ( struct nci_dev * ndev , struct sk_buff * skb ) ;
int nci_send_cmd ( struct nci_dev * ndev , __u16 opcode , __u8 plen , void * payload ) ;
int nci_send_data ( struct nci_dev * ndev , __u8 conn_id , struct sk_buff * skb ) ;
void nci_data_exchange_complete ( struct nci_dev * ndev , struct sk_buff * skb ,
int err ) ;
2012-01-18 13:16:14 +02:00
void nci_clear_target_list ( struct nci_dev * ndev ) ;
2011-09-18 11:19:35 +03:00
/* ----- NCI requests ----- */
# define NCI_REQ_DONE 0
# define NCI_REQ_PEND 1
# define NCI_REQ_CANCELED 2
void nci_req_complete ( struct nci_dev * ndev , int result ) ;
/* ----- NCI status code ----- */
int nci_to_errno ( __u8 code ) ;
2013-05-29 15:35:02 +02:00
/* ----- NCI over SPI acknowledge modes ----- */
# define NCI_SPI_CRC_DISABLED 0x00
# define NCI_SPI_CRC_ENABLED 0x01
/* ----- NCI SPI structures ----- */
struct nci_spi_dev ;
struct nci_spi_ops {
2013-09-02 12:35:39 +02:00
int ( * open ) ( struct nci_spi_dev * nsdev ) ;
int ( * close ) ( struct nci_spi_dev * nsdev ) ;
void ( * assert_int ) ( struct nci_spi_dev * nsdev ) ;
void ( * deassert_int ) ( struct nci_spi_dev * nsdev ) ;
2013-05-29 15:35:02 +02:00
} ;
struct nci_spi_dev {
2013-09-02 12:35:39 +02:00
struct nci_dev * ndev ;
2013-05-29 15:35:02 +02:00
struct spi_device * spi ;
struct nci_spi_ops * ops ;
unsigned int xfer_udelay ; /* microseconds delay between
transactions */
u8 acknowledge_mode ;
2013-05-29 15:35:03 +02:00
struct completion req_completion ;
u8 req_result ;
2013-05-29 15:35:02 +02:00
void * driver_data ;
} ;
/* ----- NCI SPI Devices ----- */
struct nci_spi_dev * nci_spi_allocate_device ( struct spi_device * spi ,
struct nci_spi_ops * ops ,
u32 supported_protocols ,
u32 supported_se ,
u8 acknowledge_mode ,
unsigned int delay ) ;
2013-09-02 12:35:39 +02:00
void nci_spi_free_device ( struct nci_spi_dev * nsdev ) ;
int nci_spi_register_device ( struct nci_spi_dev * nsdev ) ;
void nci_spi_unregister_device ( struct nci_spi_dev * nsdev ) ;
int nci_spi_recv_frame ( struct nci_spi_dev * nsdev ) ;
2013-05-29 15:35:02 +02:00
2013-09-02 12:35:39 +02:00
static inline void nci_spi_set_drvdata ( struct nci_spi_dev * nsdev ,
2013-05-29 15:35:02 +02:00
void * data )
{
2013-09-02 12:35:39 +02:00
nsdev - > driver_data = data ;
2013-05-29 15:35:02 +02:00
}
2013-09-02 12:35:39 +02:00
static inline void * nci_spi_get_drvdata ( struct nci_spi_dev * nsdev )
2013-05-29 15:35:02 +02:00
{
2013-09-02 12:35:39 +02:00
return nsdev - > driver_data ;
2013-05-29 15:35:02 +02:00
}
2011-09-18 11:19:35 +03:00
# endif /* __NCI_CORE_H */