Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

NFC: basic NCI protocol implementation

The NFC Controller Interface (NCI) is a standard
communication protocol between an NFC Controller (NFCC)
and a Device Host (DH), defined by the NFC Forum.

Signed-off-by: Ilan Elias <ilane@ti.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

authored by

Ilan Elias and committed by
John W. Linville
6a2968aa 55eb94f9

+2129
+313
include/net/nfc/nci.h
··· 1 + /* 2 + * The NFC Controller Interface is the communication protocol between an 3 + * NFC Controller (NFCC) and a Device Host (DH). 4 + * 5 + * Copyright (C) 2011 Texas Instruments, Inc. 6 + * 7 + * Written by Ilan Elias <ilane@ti.com> 8 + * 9 + * Acknowledgements: 10 + * This file is based on hci.h, which was written 11 + * by Maxim Krasnyansky. 12 + * 13 + * This program is free software; you can redistribute it and/or modify 14 + * it under the terms of the GNU General Public License version 2 15 + * as published by the Free Software Foundation 16 + * 17 + * This program is distributed in the hope that it will be useful, 18 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 + * GNU General Public License for more details. 21 + * 22 + * You should have received a copy of the GNU General Public License 23 + * along with this program; if not, write to the Free Software 24 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 25 + * 26 + */ 27 + 28 + #ifndef __NCI_H 29 + #define __NCI_H 30 + 31 + /* NCI constants */ 32 + #define NCI_MAX_NUM_MAPPING_CONFIGS 10 33 + #define NCI_MAX_NUM_RF_CONFIGS 10 34 + #define NCI_MAX_NUM_CONN 10 35 + 36 + /* NCI Status Codes */ 37 + #define NCI_STATUS_OK 0x00 38 + #define NCI_STATUS_REJECTED 0x01 39 + #define NCI_STATUS_MESSAGE_CORRUPTED 0x02 40 + #define NCI_STATUS_BUFFER_FULL 0x03 41 + #define NCI_STATUS_FAILED 0x04 42 + #define NCI_STATUS_NOT_INITIALIZED 0x05 43 + #define NCI_STATUS_SYNTAX_ERROR 0x06 44 + #define NCI_STATUS_SEMANTIC_ERROR 0x07 45 + #define NCI_STATUS_UNKNOWN_GID 0x08 46 + #define NCI_STATUS_UNKNOWN_OID 0x09 47 + #define NCI_STATUS_INVALID_PARAM 0x0a 48 + #define NCI_STATUS_MESSAGE_SIZE_EXCEEDED 0x0b 49 + /* Discovery Specific Status Codes */ 50 + #define NCI_STATUS_DISCOVERY_ALREADY_STARTED 0xa0 51 + #define NCI_STATUS_DISCOVERY_TARGET_ACTIVATION_FAILED 0xa1 52 + /* RF Interface Specific Status Codes */ 53 + #define NCI_STATUS_RF_TRANSMISSION_ERROR 0xb0 54 + #define NCI_STATUS_RF_PROTOCOL_ERROR 0xb1 55 + #define NCI_STATUS_RF_TIMEOUT_ERROR 0xb2 56 + #define NCI_STATUS_RF_LINK_LOSS_ERROR 0xb3 57 + /* NFCEE Interface Specific Status Codes */ 58 + #define NCI_STATUS_MAX_ACTIVE_NFCEE_INTERFACES_REACHED 0xc0 59 + #define NCI_STATUS_NFCEE_INTERFACE_ACTIVATION_FAILED 0xc1 60 + #define NCI_STATUS_NFCEE_TRANSMISSION_ERROR 0xc2 61 + #define NCI_STATUS_NFCEE_PROTOCOL_ERROR 0xc3 62 + #define NCI_STATUS_NFCEE_TIMEOUT_ERROR 0xc4 63 + 64 + /* NCI RF Technology and Mode */ 65 + #define NCI_NFC_A_PASSIVE_POLL_MODE 0x00 66 + #define NCI_NFC_B_PASSIVE_POLL_MODE 0x01 67 + #define NCI_NFC_F_PASSIVE_POLL_MODE 0x02 68 + #define NCI_NFC_A_ACTIVE_POLL_MODE 0x03 69 + #define NCI_NFC_F_ACTIVE_POLL_MODE 0x05 70 + #define NCI_NFC_A_PASSIVE_LISTEN_MODE 0x80 71 + #define NCI_NFC_B_PASSIVE_LISTEN_MODE 0x81 72 + #define NCI_NFC_F_PASSIVE_LISTEN_MODE 0x82 73 + #define NCI_NFC_A_ACTIVE_LISTEN_MODE 0x83 74 + #define NCI_NFC_F_ACTIVE_LISTEN_MODE 0x85 75 + 76 + /* NCI RF Protocols */ 77 + #define NCI_RF_PROTOCOL_UNKNOWN 0x00 78 + #define NCI_RF_PROTOCOL_T1T 0x01 79 + #define NCI_RF_PROTOCOL_T2T 0x02 80 + #define NCI_RF_PROTOCOL_T3T 0x03 81 + #define NCI_RF_PROTOCOL_ISO_DEP 0x04 82 + #define NCI_RF_PROTOCOL_NFC_DEP 0x05 83 + 84 + /* NCI RF Interfaces */ 85 + #define NCI_RF_INTERFACE_RFU 0x00 86 + #define NCI_RF_INTERFACE_FRAME 0x01 87 + #define NCI_RF_INTERFACE_ISO_DEP 0x02 88 + #define NCI_RF_INTERFACE_NFC_DEP 0x03 89 + 90 + /* NCI RF_DISCOVER_MAP_CMD modes */ 91 + #define NCI_DISC_MAP_MODE_POLL 0x01 92 + #define NCI_DISC_MAP_MODE_LISTEN 0x02 93 + #define NCI_DISC_MAP_MODE_BOTH 0x03 94 + 95 + /* NCI Discovery Types */ 96 + #define NCI_DISCOVERY_TYPE_POLL_A_PASSIVE 0x00 97 + #define NCI_DISCOVERY_TYPE_POLL_B_PASSIVE 0x01 98 + #define NCI_DISCOVERY_TYPE_POLL_F_PASSIVE 0x02 99 + #define NCI_DISCOVERY_TYPE_POLL_A_ACTIVE 0x03 100 + #define NCI_DISCOVERY_TYPE_POLL_F_ACTIVE 0x05 101 + #define NCI_DISCOVERY_TYPE_WAKEUP_A_PASSIVE 0x06 102 + #define NCI_DISCOVERY_TYPE_WAKEUP_B_PASSIVE 0x07 103 + #define NCI_DISCOVERY_TYPE_WAKEUP_A_ACTIVE 0x09 104 + #define NCI_DISCOVERY_TYPE_LISTEN_A_PASSIVE 0x80 105 + #define NCI_DISCOVERY_TYPE_LISTEN_B_PASSIVE 0x81 106 + #define NCI_DISCOVERY_TYPE_LISTEN_F_PASSIVE 0x82 107 + #define NCI_DISCOVERY_TYPE_LISTEN_A_ACTIVE 0x83 108 + #define NCI_DISCOVERY_TYPE_LISTEN_F_ACTIVE 0x85 109 + 110 + /* NCI Deactivation Type */ 111 + #define NCI_DEACTIVATE_TYPE_IDLE_MODE 0x00 112 + #define NCI_DEACTIVATE_TYPE_SLEEP_MODE 0x01 113 + #define NCI_DEACTIVATE_TYPE_SLEEP_AF_MODE 0x02 114 + #define NCI_DEACTIVATE_TYPE_RF_LINK_LOSS 0x03 115 + #define NCI_DEACTIVATE_TYPE_DISCOVERY_ERROR 0x04 116 + 117 + /* Message Type (MT) */ 118 + #define NCI_MT_DATA_PKT 0x00 119 + #define NCI_MT_CMD_PKT 0x01 120 + #define NCI_MT_RSP_PKT 0x02 121 + #define NCI_MT_NTF_PKT 0x03 122 + 123 + #define nci_mt(hdr) (((hdr)[0]>>5)&0x07) 124 + #define nci_mt_set(hdr, mt) ((hdr)[0] |= (__u8)(((mt)&0x07)<<5)) 125 + 126 + /* Packet Boundary Flag (PBF) */ 127 + #define NCI_PBF_LAST 0x00 128 + #define NCI_PBF_CONT 0x01 129 + 130 + #define nci_pbf(hdr) (__u8)(((hdr)[0]>>4)&0x01) 131 + #define nci_pbf_set(hdr, pbf) ((hdr)[0] |= (__u8)(((pbf)&0x01)<<4)) 132 + 133 + /* Control Opcode manipulation */ 134 + #define nci_opcode_pack(gid, oid) (__u16)((((__u16)((gid)&0x0f))<<8)|\ 135 + ((__u16)((oid)&0x3f))) 136 + #define nci_opcode(hdr) nci_opcode_pack(hdr[0], hdr[1]) 137 + #define nci_opcode_gid(op) (__u8)(((op)&0x0f00)>>8) 138 + #define nci_opcode_oid(op) (__u8)((op)&0x003f) 139 + 140 + /* Payload Length */ 141 + #define nci_plen(hdr) (__u8)((hdr)[2]) 142 + 143 + /* Connection ID */ 144 + #define nci_conn_id(hdr) (__u8)(((hdr)[0])&0x0f) 145 + 146 + /* GID values */ 147 + #define NCI_GID_CORE 0x0 148 + #define NCI_GID_RF_MGMT 0x1 149 + #define NCI_GID_NFCEE_MGMT 0x2 150 + #define NCI_GID_PROPRIETARY 0xf 151 + 152 + /* ---- NCI Packet structures ---- */ 153 + #define NCI_CTRL_HDR_SIZE 3 154 + #define NCI_DATA_HDR_SIZE 3 155 + 156 + struct nci_ctrl_hdr { 157 + __u8 gid; /* MT & PBF & GID */ 158 + __u8 oid; 159 + __u8 plen; 160 + } __packed; 161 + 162 + struct nci_data_hdr { 163 + __u8 conn_id; /* MT & PBF & ConnID */ 164 + __u8 rfu; 165 + __u8 plen; 166 + } __packed; 167 + 168 + /* ------------------------ */ 169 + /* ----- NCI Commands ---- */ 170 + /* ------------------------ */ 171 + #define NCI_OP_CORE_RESET_CMD nci_opcode_pack(NCI_GID_CORE, 0x00) 172 + 173 + #define NCI_OP_CORE_INIT_CMD nci_opcode_pack(NCI_GID_CORE, 0x01) 174 + 175 + #define NCI_OP_CORE_SET_CONFIG_CMD nci_opcode_pack(NCI_GID_CORE, 0x02) 176 + 177 + #define NCI_OP_CORE_CONN_CREATE_CMD nci_opcode_pack(NCI_GID_CORE, 0x04) 178 + struct nci_core_conn_create_cmd { 179 + __u8 target_handle; 180 + __u8 num_target_specific_params; 181 + } __packed; 182 + 183 + #define NCI_OP_CORE_CONN_CLOSE_CMD nci_opcode_pack(NCI_GID_CORE, 0x06) 184 + 185 + #define NCI_OP_RF_DISCOVER_MAP_CMD nci_opcode_pack(NCI_GID_RF_MGMT, 0x00) 186 + struct disc_map_config { 187 + __u8 rf_protocol; 188 + __u8 mode; 189 + __u8 rf_interface_type; 190 + } __packed; 191 + 192 + struct nci_rf_disc_map_cmd { 193 + __u8 num_mapping_configs; 194 + struct disc_map_config mapping_configs 195 + [NCI_MAX_NUM_MAPPING_CONFIGS]; 196 + } __packed; 197 + 198 + #define NCI_OP_RF_DISCOVER_CMD nci_opcode_pack(NCI_GID_RF_MGMT, 0x03) 199 + struct disc_config { 200 + __u8 type; 201 + __u8 frequency; 202 + } __packed; 203 + 204 + struct nci_rf_disc_cmd { 205 + __u8 num_disc_configs; 206 + struct disc_config disc_configs[NCI_MAX_NUM_RF_CONFIGS]; 207 + } __packed; 208 + 209 + #define NCI_OP_RF_DEACTIVATE_CMD nci_opcode_pack(NCI_GID_RF_MGMT, 0x06) 210 + struct nci_rf_deactivate_cmd { 211 + __u8 type; 212 + } __packed; 213 + 214 + /* ----------------------- */ 215 + /* ---- NCI Responses ---- */ 216 + /* ----------------------- */ 217 + #define NCI_OP_CORE_RESET_RSP nci_opcode_pack(NCI_GID_CORE, 0x00) 218 + struct nci_core_reset_rsp { 219 + __u8 status; 220 + __u8 nci_ver; 221 + } __packed; 222 + 223 + #define NCI_OP_CORE_INIT_RSP nci_opcode_pack(NCI_GID_CORE, 0x01) 224 + struct nci_core_init_rsp_1 { 225 + __u8 status; 226 + __le32 nfcc_features; 227 + __u8 num_supported_rf_interfaces; 228 + __u8 supported_rf_interfaces[0]; /* variable size array */ 229 + /* continuted in nci_core_init_rsp_2 */ 230 + } __packed; 231 + 232 + struct nci_core_init_rsp_2 { 233 + __u8 max_logical_connections; 234 + __le16 max_routing_table_size; 235 + __u8 max_control_packet_payload_length; 236 + __le16 rf_sending_buffer_size; 237 + __le16 rf_receiving_buffer_size; 238 + __le16 manufacturer_id; 239 + } __packed; 240 + 241 + #define NCI_OP_CORE_SET_CONFIG_RSP nci_opcode_pack(NCI_GID_CORE, 0x02) 242 + 243 + #define NCI_OP_CORE_CONN_CREATE_RSP nci_opcode_pack(NCI_GID_CORE, 0x04) 244 + struct nci_core_conn_create_rsp { 245 + __u8 status; 246 + __u8 max_pkt_payload_size; 247 + __u8 initial_num_credits; 248 + __u8 conn_id; 249 + } __packed; 250 + 251 + #define NCI_OP_CORE_CONN_CLOSE_RSP nci_opcode_pack(NCI_GID_CORE, 0x06) 252 + 253 + #define NCI_OP_RF_DISCOVER_MAP_RSP nci_opcode_pack(NCI_GID_RF_MGMT, 0x00) 254 + 255 + #define NCI_OP_RF_DISCOVER_RSP nci_opcode_pack(NCI_GID_RF_MGMT, 0x03) 256 + 257 + #define NCI_OP_RF_DEACTIVATE_RSP nci_opcode_pack(NCI_GID_RF_MGMT, 0x06) 258 + 259 + /* --------------------------- */ 260 + /* ---- NCI Notifications ---- */ 261 + /* --------------------------- */ 262 + #define NCI_OP_CORE_CONN_CREDITS_NTF nci_opcode_pack(NCI_GID_CORE, 0x07) 263 + struct conn_credit_entry { 264 + __u8 conn_id; 265 + __u8 credits; 266 + } __packed; 267 + 268 + struct nci_core_conn_credit_ntf { 269 + __u8 num_entries; 270 + struct conn_credit_entry conn_entries[NCI_MAX_NUM_CONN]; 271 + } __packed; 272 + 273 + #define NCI_OP_RF_FIELD_INFO_NTF nci_opcode_pack(NCI_GID_CORE, 0x08) 274 + struct nci_rf_field_info_ntf { 275 + __u8 rf_field_status; 276 + } __packed; 277 + 278 + #define NCI_OP_RF_ACTIVATE_NTF nci_opcode_pack(NCI_GID_RF_MGMT, 0x05) 279 + struct rf_tech_specific_params_nfca_poll { 280 + __u16 sens_res; 281 + __u8 nfcid1_len; /* 0, 4, 7, or 10 Bytes */ 282 + __u8 nfcid1[10]; 283 + __u8 sel_res_len; /* 0 or 1 Bytes */ 284 + __u8 sel_res; 285 + } __packed; 286 + 287 + struct activation_params_nfca_poll_iso_dep { 288 + __u8 rats_res_len; 289 + __u8 rats_res[20]; 290 + }; 291 + 292 + struct nci_rf_activate_ntf { 293 + __u8 target_handle; 294 + __u8 rf_protocol; 295 + __u8 rf_tech_and_mode; 296 + __u8 rf_tech_specific_params_len; 297 + 298 + union { 299 + struct rf_tech_specific_params_nfca_poll nfca_poll; 300 + } rf_tech_specific_params; 301 + 302 + __u8 rf_interface_type; 303 + __u8 activation_params_len; 304 + 305 + union { 306 + struct activation_params_nfca_poll_iso_dep nfca_poll_iso_dep; 307 + } activation_params; 308 + 309 + } __packed; 310 + 311 + #define NCI_OP_RF_DEACTIVATE_NTF nci_opcode_pack(NCI_GID_RF_MGMT, 0x06) 312 + 313 + #endif /* __NCI_H */
+183
include/net/nfc/nci_core.h
··· 1 + /* 2 + * The NFC Controller Interface is the communication protocol between an 3 + * NFC Controller (NFCC) and a Device Host (DH). 4 + * 5 + * Copyright (C) 2011 Texas Instruments, Inc. 6 + * 7 + * Written by Ilan Elias <ilane@ti.com> 8 + * 9 + * Acknowledgements: 10 + * This file is based on hci_core.h, which was written 11 + * by Maxim Krasnyansky. 12 + * 13 + * This program is free software; you can redistribute it and/or modify 14 + * it under the terms of the GNU General Public License version 2 15 + * as published by the Free Software Foundation 16 + * 17 + * This program is distributed in the hope that it will be useful, 18 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 + * GNU General Public License for more details. 21 + * 22 + * You should have received a copy of the GNU General Public License 23 + * along with this program; if not, write to the Free Software 24 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 25 + * 26 + */ 27 + 28 + #ifndef __NCI_CORE_H 29 + #define __NCI_CORE_H 30 + 31 + #include <linux/interrupt.h> 32 + #include <linux/skbuff.h> 33 + 34 + #include <net/nfc/nfc.h> 35 + #include <net/nfc/nci.h> 36 + 37 + /* NCI device state */ 38 + enum { 39 + NCI_INIT, 40 + NCI_UP, 41 + NCI_DISCOVERY, 42 + NCI_POLL_ACTIVE, 43 + }; 44 + 45 + /* NCI timeouts */ 46 + #define NCI_RESET_TIMEOUT 5000 47 + #define NCI_INIT_TIMEOUT 5000 48 + #define NCI_RF_DISC_TIMEOUT 5000 49 + #define NCI_RF_DEACTIVATE_TIMEOUT 5000 50 + #define NCI_CMD_TIMEOUT 5000 51 + 52 + struct nci_dev; 53 + 54 + struct nci_ops { 55 + int (*open)(struct nci_dev *ndev); 56 + int (*close)(struct nci_dev *ndev); 57 + int (*send)(struct sk_buff *skb); 58 + }; 59 + 60 + #define NCI_MAX_SUPPORTED_RF_INTERFACES 4 61 + 62 + /* NCI Core structures */ 63 + struct nci_dev { 64 + struct nfc_dev *nfc_dev; 65 + struct nci_ops *ops; 66 + 67 + int tx_headroom; 68 + int tx_tailroom; 69 + 70 + unsigned long flags; 71 + 72 + atomic_t cmd_cnt; 73 + atomic_t credits_cnt; 74 + 75 + struct timer_list cmd_timer; 76 + 77 + struct workqueue_struct *cmd_wq; 78 + struct work_struct cmd_work; 79 + 80 + struct workqueue_struct *rx_wq; 81 + struct work_struct rx_work; 82 + 83 + struct workqueue_struct *tx_wq; 84 + struct work_struct tx_work; 85 + 86 + struct sk_buff_head cmd_q; 87 + struct sk_buff_head rx_q; 88 + struct sk_buff_head tx_q; 89 + 90 + struct mutex req_lock; 91 + struct completion req_completion; 92 + __u32 req_status; 93 + __u32 req_result; 94 + 95 + void *driver_data; 96 + 97 + __u32 poll_prots; 98 + __u32 target_available_prots; 99 + __u32 target_active_prot; 100 + 101 + /* received during NCI_OP_CORE_RESET_RSP */ 102 + __u8 nci_ver; 103 + 104 + /* received during NCI_OP_CORE_INIT_RSP */ 105 + __u32 nfcc_features; 106 + __u8 num_supported_rf_interfaces; 107 + __u8 supported_rf_interfaces 108 + [NCI_MAX_SUPPORTED_RF_INTERFACES]; 109 + __u8 max_logical_connections; 110 + __u16 max_routing_table_size; 111 + __u8 max_control_packet_payload_length; 112 + __u16 rf_sending_buffer_size; 113 + __u16 rf_receiving_buffer_size; 114 + __u16 manufacturer_id; 115 + 116 + /* received during NCI_OP_CORE_CONN_CREATE_RSP for static conn 0 */ 117 + __u8 max_pkt_payload_size; 118 + __u8 initial_num_credits; 119 + __u8 conn_id; 120 + 121 + /* stored during nci_data_exchange */ 122 + data_exchange_cb_t data_exchange_cb; 123 + void *data_exchange_cb_context; 124 + struct sk_buff *rx_data_reassembly; 125 + }; 126 + 127 + /* ----- NCI Devices ----- */ 128 + struct nci_dev *nci_allocate_device(struct nci_ops *ops, 129 + __u32 supported_protocols, 130 + int tx_headroom, 131 + int tx_tailroom); 132 + void nci_free_device(struct nci_dev *ndev); 133 + int nci_register_device(struct nci_dev *ndev); 134 + void nci_unregister_device(struct nci_dev *ndev); 135 + int nci_recv_frame(struct sk_buff *skb); 136 + 137 + static inline struct sk_buff *nci_skb_alloc(struct nci_dev *ndev, 138 + unsigned int len, 139 + gfp_t how) 140 + { 141 + struct sk_buff *skb; 142 + 143 + skb = alloc_skb(len + ndev->tx_headroom + ndev->tx_tailroom, how); 144 + if (skb) 145 + skb_reserve(skb, ndev->tx_headroom); 146 + 147 + return skb; 148 + } 149 + 150 + static inline void nci_set_parent_dev(struct nci_dev *ndev, struct device *dev) 151 + { 152 + nfc_set_parent_dev(ndev->nfc_dev, dev); 153 + } 154 + 155 + static inline void nci_set_drvdata(struct nci_dev *ndev, void *data) 156 + { 157 + ndev->driver_data = data; 158 + } 159 + 160 + static inline void *nci_get_drvdata(struct nci_dev *ndev) 161 + { 162 + return ndev->driver_data; 163 + } 164 + 165 + void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb); 166 + void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb); 167 + void nci_rx_data_packet(struct nci_dev *ndev, struct sk_buff *skb); 168 + int nci_send_cmd(struct nci_dev *ndev, __u16 opcode, __u8 plen, void *payload); 169 + int nci_send_data(struct nci_dev *ndev, __u8 conn_id, struct sk_buff *skb); 170 + void nci_data_exchange_complete(struct nci_dev *ndev, struct sk_buff *skb, 171 + int err); 172 + 173 + /* ----- NCI requests ----- */ 174 + #define NCI_REQ_DONE 0 175 + #define NCI_REQ_PEND 1 176 + #define NCI_REQ_CANCELED 2 177 + 178 + void nci_req_complete(struct nci_dev *ndev, int result); 179 + 180 + /* ----- NCI status code ----- */ 181 + int nci_to_errno(__u8 code); 182 + 183 + #endif /* __NCI_CORE_H */
+2
net/nfc/Kconfig
··· 13 13 To compile this support as a module, choose M here: the module will 14 14 be called nfc. 15 15 16 + source "net/nfc/nci/Kconfig" 17 + 16 18 source "drivers/nfc/Kconfig"
+1
net/nfc/Makefile
··· 3 3 # 4 4 5 5 obj-$(CONFIG_NFC) += nfc.o 6 + obj-$(CONFIG_NFC_NCI) += nci/ 6 7 7 8 nfc-objs := core.o netlink.o af_nfc.o rawsock.o
+10
net/nfc/nci/Kconfig
··· 1 + config NFC_NCI 2 + depends on NFC && EXPERIMENTAL 3 + tristate "NCI protocol support (EXPERIMENTAL)" 4 + default n 5 + help 6 + NCI (NFC Controller Interface) is a communication protocol between 7 + an NFC Controller (NFCC) and a Device Host (DH). 8 + 9 + Say Y here to compile NCI support into the kernel or say M to 10 + compile it as module (nci).
+7
net/nfc/nci/Makefile
··· 1 + # 2 + # Makefile for the Linux NFC NCI layer. 3 + # 4 + 5 + obj-$(CONFIG_NFC_NCI) += nci.o 6 + 7 + nci-objs := core.o data.o lib.o ntf.o rsp.o
+790
net/nfc/nci/core.c
··· 1 + /* 2 + * The NFC Controller Interface is the communication protocol between an 3 + * NFC Controller (NFCC) and a Device Host (DH). 4 + * 5 + * Copyright (C) 2011 Texas Instruments, Inc. 6 + * 7 + * Written by Ilan Elias <ilane@ti.com> 8 + * 9 + * Acknowledgements: 10 + * This file is based on hci_core.c, which was written 11 + * by Maxim Krasnyansky. 12 + * 13 + * This program is free software; you can redistribute it and/or modify 14 + * it under the terms of the GNU General Public License version 2 15 + * as published by the Free Software Foundation 16 + * 17 + * This program is distributed in the hope that it will be useful, 18 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 + * GNU General Public License for more details. 21 + * 22 + * You should have received a copy of the GNU General Public License 23 + * along with this program; if not, write to the Free Software 24 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 25 + * 26 + */ 27 + 28 + #include <linux/types.h> 29 + #include <linux/workqueue.h> 30 + #include <linux/completion.h> 31 + #include <linux/sched.h> 32 + #include <linux/bitops.h> 33 + #include <linux/skbuff.h> 34 + 35 + #include "../nfc.h" 36 + #include <net/nfc/nci.h> 37 + #include <net/nfc/nci_core.h> 38 + #include <linux/nfc.h> 39 + 40 + static void nci_cmd_work(struct work_struct *work); 41 + static void nci_rx_work(struct work_struct *work); 42 + static void nci_tx_work(struct work_struct *work); 43 + 44 + /* ---- NCI requests ---- */ 45 + 46 + void nci_req_complete(struct nci_dev *ndev, int result) 47 + { 48 + if (ndev->req_status == NCI_REQ_PEND) { 49 + ndev->req_result = result; 50 + ndev->req_status = NCI_REQ_DONE; 51 + complete(&ndev->req_completion); 52 + } 53 + } 54 + 55 + static void nci_req_cancel(struct nci_dev *ndev, int err) 56 + { 57 + if (ndev->req_status == NCI_REQ_PEND) { 58 + ndev->req_result = err; 59 + ndev->req_status = NCI_REQ_CANCELED; 60 + complete(&ndev->req_completion); 61 + } 62 + } 63 + 64 + /* Execute request and wait for completion. */ 65 + static int __nci_request(struct nci_dev *ndev, 66 + void (*req)(struct nci_dev *ndev, unsigned long opt), 67 + unsigned long opt, 68 + __u32 timeout) 69 + { 70 + int rc = 0; 71 + unsigned long completion_rc; 72 + 73 + ndev->req_status = NCI_REQ_PEND; 74 + 75 + init_completion(&ndev->req_completion); 76 + req(ndev, opt); 77 + completion_rc = wait_for_completion_interruptible_timeout( 78 + &ndev->req_completion, 79 + timeout); 80 + 81 + nfc_dbg("wait_for_completion return %ld", completion_rc); 82 + 83 + if (completion_rc > 0) { 84 + switch (ndev->req_status) { 85 + case NCI_REQ_DONE: 86 + rc = nci_to_errno(ndev->req_result); 87 + break; 88 + 89 + case NCI_REQ_CANCELED: 90 + rc = -ndev->req_result; 91 + break; 92 + 93 + default: 94 + rc = -ETIMEDOUT; 95 + break; 96 + } 97 + } else { 98 + nfc_err("wait_for_completion_interruptible_timeout failed %ld", 99 + completion_rc); 100 + 101 + rc = ((completion_rc == 0) ? (-ETIMEDOUT) : (completion_rc)); 102 + } 103 + 104 + ndev->req_status = ndev->req_result = 0; 105 + 106 + return rc; 107 + } 108 + 109 + static inline int nci_request(struct nci_dev *ndev, 110 + void (*req)(struct nci_dev *ndev, unsigned long opt), 111 + unsigned long opt, __u32 timeout) 112 + { 113 + int rc; 114 + 115 + if (!test_bit(NCI_UP, &ndev->flags)) 116 + return -ENETDOWN; 117 + 118 + /* Serialize all requests */ 119 + mutex_lock(&ndev->req_lock); 120 + rc = __nci_request(ndev, req, opt, timeout); 121 + mutex_unlock(&ndev->req_lock); 122 + 123 + return rc; 124 + } 125 + 126 + static void nci_reset_req(struct nci_dev *ndev, unsigned long opt) 127 + { 128 + nci_send_cmd(ndev, NCI_OP_CORE_RESET_CMD, 0, NULL); 129 + } 130 + 131 + static void nci_init_req(struct nci_dev *ndev, unsigned long opt) 132 + { 133 + nci_send_cmd(ndev, NCI_OP_CORE_INIT_CMD, 0, NULL); 134 + } 135 + 136 + static void nci_init_complete_req(struct nci_dev *ndev, unsigned long opt) 137 + { 138 + struct nci_rf_disc_map_cmd cmd; 139 + struct nci_core_conn_create_cmd conn_cmd; 140 + int i; 141 + 142 + /* create static rf connection */ 143 + conn_cmd.target_handle = 0; 144 + conn_cmd.num_target_specific_params = 0; 145 + nci_send_cmd(ndev, NCI_OP_CORE_CONN_CREATE_CMD, 2, &conn_cmd); 146 + 147 + /* set rf mapping configurations */ 148 + cmd.num_mapping_configs = 0; 149 + 150 + /* by default mapping is set to NCI_RF_INTERFACE_FRAME */ 151 + for (i = 0; i < ndev->num_supported_rf_interfaces; i++) { 152 + if (ndev->supported_rf_interfaces[i] == 153 + NCI_RF_INTERFACE_ISO_DEP) { 154 + cmd.mapping_configs[cmd.num_mapping_configs] 155 + .rf_protocol = NCI_RF_PROTOCOL_ISO_DEP; 156 + cmd.mapping_configs[cmd.num_mapping_configs] 157 + .mode = NCI_DISC_MAP_MODE_BOTH; 158 + cmd.mapping_configs[cmd.num_mapping_configs] 159 + .rf_interface_type = NCI_RF_INTERFACE_ISO_DEP; 160 + cmd.num_mapping_configs++; 161 + } else if (ndev->supported_rf_interfaces[i] == 162 + NCI_RF_INTERFACE_NFC_DEP) { 163 + cmd.mapping_configs[cmd.num_mapping_configs] 164 + .rf_protocol = NCI_RF_PROTOCOL_NFC_DEP; 165 + cmd.mapping_configs[cmd.num_mapping_configs] 166 + .mode = NCI_DISC_MAP_MODE_BOTH; 167 + cmd.mapping_configs[cmd.num_mapping_configs] 168 + .rf_interface_type = NCI_RF_INTERFACE_NFC_DEP; 169 + cmd.num_mapping_configs++; 170 + } 171 + 172 + if (cmd.num_mapping_configs == NCI_MAX_NUM_MAPPING_CONFIGS) 173 + break; 174 + } 175 + 176 + nci_send_cmd(ndev, NCI_OP_RF_DISCOVER_MAP_CMD, 177 + (1 + (cmd.num_mapping_configs*sizeof(struct disc_map_config))), 178 + &cmd); 179 + } 180 + 181 + static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt) 182 + { 183 + struct nci_rf_disc_cmd cmd; 184 + __u32 protocols = opt; 185 + 186 + cmd.num_disc_configs = 0; 187 + 188 + if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) && 189 + (protocols & NFC_PROTO_JEWEL_MASK 190 + || protocols & NFC_PROTO_MIFARE_MASK 191 + || protocols & NFC_PROTO_ISO14443_MASK 192 + || protocols & NFC_PROTO_NFC_DEP_MASK)) { 193 + cmd.disc_configs[cmd.num_disc_configs].type = 194 + NCI_DISCOVERY_TYPE_POLL_A_PASSIVE; 195 + cmd.disc_configs[cmd.num_disc_configs].frequency = 1; 196 + cmd.num_disc_configs++; 197 + } 198 + 199 + if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) && 200 + (protocols & NFC_PROTO_ISO14443_MASK)) { 201 + cmd.disc_configs[cmd.num_disc_configs].type = 202 + NCI_DISCOVERY_TYPE_POLL_B_PASSIVE; 203 + cmd.disc_configs[cmd.num_disc_configs].frequency = 1; 204 + cmd.num_disc_configs++; 205 + } 206 + 207 + if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) && 208 + (protocols & NFC_PROTO_FELICA_MASK 209 + || protocols & NFC_PROTO_NFC_DEP_MASK)) { 210 + cmd.disc_configs[cmd.num_disc_configs].type = 211 + NCI_DISCOVERY_TYPE_POLL_F_PASSIVE; 212 + cmd.disc_configs[cmd.num_disc_configs].frequency = 1; 213 + cmd.num_disc_configs++; 214 + } 215 + 216 + nci_send_cmd(ndev, NCI_OP_RF_DISCOVER_CMD, 217 + (1 + (cmd.num_disc_configs*sizeof(struct disc_config))), 218 + &cmd); 219 + } 220 + 221 + static void nci_rf_deactivate_req(struct nci_dev *ndev, unsigned long opt) 222 + { 223 + struct nci_rf_deactivate_cmd cmd; 224 + 225 + cmd.type = NCI_DEACTIVATE_TYPE_IDLE_MODE; 226 + 227 + nci_send_cmd(ndev, NCI_OP_RF_DEACTIVATE_CMD, 228 + sizeof(struct nci_rf_deactivate_cmd), 229 + &cmd); 230 + } 231 + 232 + static int nci_open_device(struct nci_dev *ndev) 233 + { 234 + int rc = 0; 235 + 236 + mutex_lock(&ndev->req_lock); 237 + 238 + if (test_bit(NCI_UP, &ndev->flags)) { 239 + rc = -EALREADY; 240 + goto done; 241 + } 242 + 243 + if (ndev->ops->open(ndev)) { 244 + rc = -EIO; 245 + goto done; 246 + } 247 + 248 + atomic_set(&ndev->cmd_cnt, 1); 249 + 250 + set_bit(NCI_INIT, &ndev->flags); 251 + 252 + rc = __nci_request(ndev, nci_reset_req, 0, 253 + msecs_to_jiffies(NCI_RESET_TIMEOUT)); 254 + 255 + if (!rc) { 256 + rc = __nci_request(ndev, nci_init_req, 0, 257 + msecs_to_jiffies(NCI_INIT_TIMEOUT)); 258 + } 259 + 260 + if (!rc) { 261 + rc = __nci_request(ndev, nci_init_complete_req, 0, 262 + msecs_to_jiffies(NCI_INIT_TIMEOUT)); 263 + } 264 + 265 + clear_bit(NCI_INIT, &ndev->flags); 266 + 267 + if (!rc) { 268 + set_bit(NCI_UP, &ndev->flags); 269 + } else { 270 + /* Init failed, cleanup */ 271 + skb_queue_purge(&ndev->cmd_q); 272 + skb_queue_purge(&ndev->rx_q); 273 + skb_queue_purge(&ndev->tx_q); 274 + 275 + ndev->ops->close(ndev); 276 + ndev->flags = 0; 277 + } 278 + 279 + done: 280 + mutex_unlock(&ndev->req_lock); 281 + return rc; 282 + } 283 + 284 + static int nci_close_device(struct nci_dev *ndev) 285 + { 286 + nci_req_cancel(ndev, ENODEV); 287 + mutex_lock(&ndev->req_lock); 288 + 289 + if (!test_and_clear_bit(NCI_UP, &ndev->flags)) { 290 + del_timer_sync(&ndev->cmd_timer); 291 + mutex_unlock(&ndev->req_lock); 292 + return 0; 293 + } 294 + 295 + /* Drop RX and TX queues */ 296 + skb_queue_purge(&ndev->rx_q); 297 + skb_queue_purge(&ndev->tx_q); 298 + 299 + /* Flush RX and TX wq */ 300 + flush_workqueue(ndev->rx_wq); 301 + flush_workqueue(ndev->tx_wq); 302 + 303 + /* Reset device */ 304 + skb_queue_purge(&ndev->cmd_q); 305 + atomic_set(&ndev->cmd_cnt, 1); 306 + 307 + set_bit(NCI_INIT, &ndev->flags); 308 + __nci_request(ndev, nci_reset_req, 0, 309 + msecs_to_jiffies(NCI_RESET_TIMEOUT)); 310 + clear_bit(NCI_INIT, &ndev->flags); 311 + 312 + /* Flush cmd wq */ 313 + flush_workqueue(ndev->cmd_wq); 314 + 315 + /* After this point our queues are empty 316 + * and no works are scheduled. */ 317 + ndev->ops->close(ndev); 318 + 319 + /* Clear flags */ 320 + ndev->flags = 0; 321 + 322 + mutex_unlock(&ndev->req_lock); 323 + 324 + return 0; 325 + } 326 + 327 + /* NCI command timer function */ 328 + static void nci_cmd_timer(unsigned long arg) 329 + { 330 + struct nci_dev *ndev = (void *) arg; 331 + 332 + nfc_dbg("entry"); 333 + 334 + atomic_set(&ndev->cmd_cnt, 1); 335 + queue_work(ndev->cmd_wq, &ndev->cmd_work); 336 + } 337 + 338 + static int nci_dev_up(struct nfc_dev *nfc_dev) 339 + { 340 + struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); 341 + 342 + nfc_dbg("entry"); 343 + 344 + return nci_open_device(ndev); 345 + } 346 + 347 + static int nci_dev_down(struct nfc_dev *nfc_dev) 348 + { 349 + struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); 350 + 351 + nfc_dbg("entry"); 352 + 353 + return nci_close_device(ndev); 354 + } 355 + 356 + static int nci_start_poll(struct nfc_dev *nfc_dev, __u32 protocols) 357 + { 358 + struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); 359 + int rc; 360 + 361 + nfc_dbg("entry"); 362 + 363 + if (test_bit(NCI_DISCOVERY, &ndev->flags)) { 364 + nfc_err("unable to start poll, since poll is already active"); 365 + return -EBUSY; 366 + } 367 + 368 + if (test_bit(NCI_POLL_ACTIVE, &ndev->flags)) { 369 + nfc_dbg("target already active, first deactivate..."); 370 + 371 + rc = nci_request(ndev, nci_rf_deactivate_req, 0, 372 + msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT)); 373 + if (rc) 374 + return -EBUSY; 375 + } 376 + 377 + rc = nci_request(ndev, nci_rf_discover_req, protocols, 378 + msecs_to_jiffies(NCI_RF_DISC_TIMEOUT)); 379 + 380 + if (!rc) 381 + ndev->poll_prots = protocols; 382 + 383 + return rc; 384 + } 385 + 386 + static void nci_stop_poll(struct nfc_dev *nfc_dev) 387 + { 388 + struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); 389 + 390 + nfc_dbg("entry"); 391 + 392 + if (!test_bit(NCI_DISCOVERY, &ndev->flags)) { 393 + nfc_err("unable to stop poll, since poll is not active"); 394 + return; 395 + } 396 + 397 + nci_request(ndev, nci_rf_deactivate_req, 0, 398 + msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT)); 399 + } 400 + 401 + static int nci_activate_target(struct nfc_dev *nfc_dev, __u32 target_idx, 402 + __u32 protocol) 403 + { 404 + struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); 405 + 406 + nfc_dbg("entry, target_idx %d, protocol 0x%x", target_idx, protocol); 407 + 408 + if (!test_bit(NCI_POLL_ACTIVE, &ndev->flags)) { 409 + nfc_err("there is no available target to activate"); 410 + return -EINVAL; 411 + } 412 + 413 + if (ndev->target_active_prot) { 414 + nfc_err("there is already an active target"); 415 + return -EBUSY; 416 + } 417 + 418 + if (!(ndev->target_available_prots & (1 << protocol))) { 419 + nfc_err("target does not support the requested protocol 0x%x", 420 + protocol); 421 + return -EINVAL; 422 + } 423 + 424 + ndev->target_active_prot = protocol; 425 + ndev->target_available_prots = 0; 426 + 427 + return 0; 428 + } 429 + 430 + static void nci_deactivate_target(struct nfc_dev *nfc_dev, __u32 target_idx) 431 + { 432 + struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); 433 + 434 + nfc_dbg("entry, target_idx %d", target_idx); 435 + 436 + if (!ndev->target_active_prot) { 437 + nfc_err("unable to deactivate target, no active target"); 438 + return; 439 + } 440 + 441 + ndev->target_active_prot = 0; 442 + 443 + if (test_bit(NCI_POLL_ACTIVE, &ndev->flags)) { 444 + nci_request(ndev, nci_rf_deactivate_req, 0, 445 + msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT)); 446 + } 447 + } 448 + 449 + static int nci_data_exchange(struct nfc_dev *nfc_dev, __u32 target_idx, 450 + struct sk_buff *skb, 451 + data_exchange_cb_t cb, 452 + void *cb_context) 453 + { 454 + struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); 455 + 456 + nfc_dbg("entry, target_idx %d, len %d", target_idx, skb->len); 457 + 458 + if (!ndev->target_active_prot) { 459 + nfc_err("unable to exchange data, no active target"); 460 + return -EINVAL; 461 + } 462 + 463 + /* store cb and context to be used on receiving data */ 464 + ndev->data_exchange_cb = cb; 465 + ndev->data_exchange_cb_context = cb_context; 466 + 467 + return nci_send_data(ndev, ndev->conn_id, skb); 468 + } 469 + 470 + static struct nfc_ops nci_nfc_ops = { 471 + .dev_up = nci_dev_up, 472 + .dev_down = nci_dev_down, 473 + .start_poll = nci_start_poll, 474 + .stop_poll = nci_stop_poll, 475 + .activate_target = nci_activate_target, 476 + .deactivate_target = nci_deactivate_target, 477 + .data_exchange = nci_data_exchange, 478 + }; 479 + 480 + /* ---- Interface to NCI drivers ---- */ 481 + 482 + /** 483 + * nci_allocate_device - allocate a new nci device 484 + * 485 + * @ops: device operations 486 + * @supported_protocols: NFC protocols supported by the device 487 + */ 488 + struct nci_dev *nci_allocate_device(struct nci_ops *ops, 489 + __u32 supported_protocols, 490 + int tx_headroom, 491 + int tx_tailroom) 492 + { 493 + struct nci_dev *ndev = NULL; 494 + 495 + nfc_dbg("entry, supported_protocols 0x%x", supported_protocols); 496 + 497 + if (!ops->open || !ops->close || !ops->send) 498 + goto exit; 499 + 500 + if (!supported_protocols) 501 + goto exit; 502 + 503 + ndev = kzalloc(sizeof(struct nci_dev), GFP_KERNEL); 504 + if (!ndev) 505 + goto exit; 506 + 507 + ndev->ops = ops; 508 + ndev->tx_headroom = tx_headroom; 509 + ndev->tx_tailroom = tx_tailroom; 510 + 511 + ndev->nfc_dev = nfc_allocate_device(&nci_nfc_ops, 512 + supported_protocols, 513 + tx_headroom + NCI_DATA_HDR_SIZE, 514 + tx_tailroom); 515 + if (!ndev->nfc_dev) 516 + goto free_exit; 517 + 518 + nfc_set_drvdata(ndev->nfc_dev, ndev); 519 + 520 + goto exit; 521 + 522 + free_exit: 523 + kfree(ndev); 524 + 525 + exit: 526 + return ndev; 527 + } 528 + EXPORT_SYMBOL(nci_allocate_device); 529 + 530 + /** 531 + * nci_free_device - deallocate nci device 532 + * 533 + * @ndev: The nci device to deallocate 534 + */ 535 + void nci_free_device(struct nci_dev *ndev) 536 + { 537 + nfc_dbg("entry"); 538 + 539 + nfc_free_device(ndev->nfc_dev); 540 + kfree(ndev); 541 + } 542 + EXPORT_SYMBOL(nci_free_device); 543 + 544 + /** 545 + * nci_register_device - register a nci device in the nfc subsystem 546 + * 547 + * @dev: The nci device to register 548 + */ 549 + int nci_register_device(struct nci_dev *ndev) 550 + { 551 + int rc; 552 + struct device *dev = &ndev->nfc_dev->dev; 553 + char name[32]; 554 + 555 + nfc_dbg("entry"); 556 + 557 + rc = nfc_register_device(ndev->nfc_dev); 558 + if (rc) 559 + goto exit; 560 + 561 + ndev->flags = 0; 562 + 563 + INIT_WORK(&ndev->cmd_work, nci_cmd_work); 564 + snprintf(name, sizeof(name), "%s_nci_cmd_wq", dev_name(dev)); 565 + ndev->cmd_wq = create_singlethread_workqueue(name); 566 + if (!ndev->cmd_wq) { 567 + rc = -ENOMEM; 568 + goto unreg_exit; 569 + } 570 + 571 + INIT_WORK(&ndev->rx_work, nci_rx_work); 572 + snprintf(name, sizeof(name), "%s_nci_rx_wq", dev_name(dev)); 573 + ndev->rx_wq = create_singlethread_workqueue(name); 574 + if (!ndev->rx_wq) { 575 + rc = -ENOMEM; 576 + goto destroy_cmd_wq_exit; 577 + } 578 + 579 + INIT_WORK(&ndev->tx_work, nci_tx_work); 580 + snprintf(name, sizeof(name), "%s_nci_tx_wq", dev_name(dev)); 581 + ndev->tx_wq = create_singlethread_workqueue(name); 582 + if (!ndev->tx_wq) { 583 + rc = -ENOMEM; 584 + goto destroy_rx_wq_exit; 585 + } 586 + 587 + skb_queue_head_init(&ndev->cmd_q); 588 + skb_queue_head_init(&ndev->rx_q); 589 + skb_queue_head_init(&ndev->tx_q); 590 + 591 + setup_timer(&ndev->cmd_timer, nci_cmd_timer, 592 + (unsigned long) ndev); 593 + 594 + mutex_init(&ndev->req_lock); 595 + 596 + goto exit; 597 + 598 + destroy_rx_wq_exit: 599 + destroy_workqueue(ndev->rx_wq); 600 + 601 + destroy_cmd_wq_exit: 602 + destroy_workqueue(ndev->cmd_wq); 603 + 604 + unreg_exit: 605 + nfc_unregister_device(ndev->nfc_dev); 606 + 607 + exit: 608 + return rc; 609 + } 610 + EXPORT_SYMBOL(nci_register_device); 611 + 612 + /** 613 + * nci_unregister_device - unregister a nci device in the nfc subsystem 614 + * 615 + * @dev: The nci device to unregister 616 + */ 617 + void nci_unregister_device(struct nci_dev *ndev) 618 + { 619 + nfc_dbg("entry"); 620 + 621 + nci_close_device(ndev); 622 + 623 + destroy_workqueue(ndev->cmd_wq); 624 + destroy_workqueue(ndev->rx_wq); 625 + destroy_workqueue(ndev->tx_wq); 626 + 627 + nfc_unregister_device(ndev->nfc_dev); 628 + } 629 + EXPORT_SYMBOL(nci_unregister_device); 630 + 631 + /** 632 + * nci_recv_frame - receive frame from NCI drivers 633 + * 634 + * @skb: The sk_buff to receive 635 + */ 636 + int nci_recv_frame(struct sk_buff *skb) 637 + { 638 + struct nci_dev *ndev = (struct nci_dev *) skb->dev; 639 + 640 + nfc_dbg("entry, len %d", skb->len); 641 + 642 + if (!ndev || (!test_bit(NCI_UP, &ndev->flags) 643 + && !test_bit(NCI_INIT, &ndev->flags))) { 644 + kfree_skb(skb); 645 + return -ENXIO; 646 + } 647 + 648 + /* Queue frame for rx worker thread */ 649 + skb_queue_tail(&ndev->rx_q, skb); 650 + queue_work(ndev->rx_wq, &ndev->rx_work); 651 + 652 + return 0; 653 + } 654 + EXPORT_SYMBOL(nci_recv_frame); 655 + 656 + static int nci_send_frame(struct sk_buff *skb) 657 + { 658 + struct nci_dev *ndev = (struct nci_dev *) skb->dev; 659 + 660 + nfc_dbg("entry, len %d", skb->len); 661 + 662 + if (!ndev) { 663 + kfree_skb(skb); 664 + return -ENODEV; 665 + } 666 + 667 + /* Get rid of skb owner, prior to sending to the driver. */ 668 + skb_orphan(skb); 669 + 670 + return ndev->ops->send(skb); 671 + } 672 + 673 + /* Send NCI command */ 674 + int nci_send_cmd(struct nci_dev *ndev, __u16 opcode, __u8 plen, void *payload) 675 + { 676 + struct nci_ctrl_hdr *hdr; 677 + struct sk_buff *skb; 678 + 679 + nfc_dbg("entry, opcode 0x%x, plen %d", opcode, plen); 680 + 681 + skb = nci_skb_alloc(ndev, (NCI_CTRL_HDR_SIZE + plen), GFP_KERNEL); 682 + if (!skb) { 683 + nfc_err("no memory for command"); 684 + return -ENOMEM; 685 + } 686 + 687 + hdr = (struct nci_ctrl_hdr *) skb_put(skb, NCI_CTRL_HDR_SIZE); 688 + hdr->gid = nci_opcode_gid(opcode); 689 + hdr->oid = nci_opcode_oid(opcode); 690 + hdr->plen = plen; 691 + 692 + nci_mt_set((__u8 *)hdr, NCI_MT_CMD_PKT); 693 + nci_pbf_set((__u8 *)hdr, NCI_PBF_LAST); 694 + 695 + if (plen) 696 + memcpy(skb_put(skb, plen), payload, plen); 697 + 698 + skb->dev = (void *) ndev; 699 + 700 + skb_queue_tail(&ndev->cmd_q, skb); 701 + queue_work(ndev->cmd_wq, &ndev->cmd_work); 702 + 703 + return 0; 704 + } 705 + 706 + /* ---- NCI TX Data worker thread ---- */ 707 + 708 + static void nci_tx_work(struct work_struct *work) 709 + { 710 + struct nci_dev *ndev = container_of(work, struct nci_dev, tx_work); 711 + struct sk_buff *skb; 712 + 713 + nfc_dbg("entry, credits_cnt %d", atomic_read(&ndev->credits_cnt)); 714 + 715 + /* Send queued tx data */ 716 + while (atomic_read(&ndev->credits_cnt)) { 717 + skb = skb_dequeue(&ndev->tx_q); 718 + if (!skb) 719 + return; 720 + 721 + atomic_dec(&ndev->credits_cnt); 722 + 723 + nfc_dbg("NCI TX: MT=data, PBF=%d, conn_id=%d, plen=%d", 724 + nci_pbf(skb->data), 725 + nci_conn_id(skb->data), 726 + nci_plen(skb->data)); 727 + 728 + nci_send_frame(skb); 729 + } 730 + } 731 + 732 + /* ----- NCI RX worker thread (data & control) ----- */ 733 + 734 + static void nci_rx_work(struct work_struct *work) 735 + { 736 + struct nci_dev *ndev = container_of(work, struct nci_dev, rx_work); 737 + struct sk_buff *skb; 738 + 739 + while ((skb = skb_dequeue(&ndev->rx_q))) { 740 + /* Process frame */ 741 + switch (nci_mt(skb->data)) { 742 + case NCI_MT_RSP_PKT: 743 + nci_rsp_packet(ndev, skb); 744 + break; 745 + 746 + case NCI_MT_NTF_PKT: 747 + nci_ntf_packet(ndev, skb); 748 + break; 749 + 750 + case NCI_MT_DATA_PKT: 751 + nci_rx_data_packet(ndev, skb); 752 + break; 753 + 754 + default: 755 + nfc_err("unknown MT 0x%x", nci_mt(skb->data)); 756 + kfree_skb(skb); 757 + break; 758 + } 759 + } 760 + } 761 + 762 + /* ----- NCI TX CMD worker thread ----- */ 763 + 764 + static void nci_cmd_work(struct work_struct *work) 765 + { 766 + struct nci_dev *ndev = container_of(work, struct nci_dev, cmd_work); 767 + struct sk_buff *skb; 768 + 769 + nfc_dbg("entry, cmd_cnt %d", atomic_read(&ndev->cmd_cnt)); 770 + 771 + /* Send queued command */ 772 + if (atomic_read(&ndev->cmd_cnt)) { 773 + skb = skb_dequeue(&ndev->cmd_q); 774 + if (!skb) 775 + return; 776 + 777 + atomic_dec(&ndev->cmd_cnt); 778 + 779 + nfc_dbg("NCI TX: MT=cmd, PBF=%d, GID=0x%x, OID=0x%x, plen=%d", 780 + nci_pbf(skb->data), 781 + nci_opcode_gid(nci_opcode(skb->data)), 782 + nci_opcode_oid(nci_opcode(skb->data)), 783 + nci_plen(skb->data)); 784 + 785 + nci_send_frame(skb); 786 + 787 + mod_timer(&ndev->cmd_timer, 788 + jiffies + msecs_to_jiffies(NCI_CMD_TIMEOUT)); 789 + } 790 + }
+245
net/nfc/nci/data.c
··· 1 + /* 2 + * The NFC Controller Interface is the communication protocol between an 3 + * NFC Controller (NFCC) and a Device Host (DH). 4 + * 5 + * Copyright (C) 2011 Texas Instruments, Inc. 6 + * 7 + * Written by Ilan Elias <ilane@ti.com> 8 + * 9 + * This program is free software; you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License version 2 11 + * as published by the Free Software Foundation 12 + * 13 + * This program is distributed in the hope that it will be useful, 14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 + * GNU General Public License for more details. 17 + * 18 + * You should have received a copy of the GNU General Public License 19 + * along with this program; if not, write to the Free Software 20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 + * 22 + */ 23 + 24 + #include <linux/types.h> 25 + #include <linux/interrupt.h> 26 + #include <linux/wait.h> 27 + #include <linux/bitops.h> 28 + #include <linux/skbuff.h> 29 + 30 + #include "../nfc.h" 31 + #include <net/nfc/nci.h> 32 + #include <net/nfc/nci_core.h> 33 + #include <linux/nfc.h> 34 + 35 + /* Complete data exchange transaction and forward skb to nfc core */ 36 + void nci_data_exchange_complete(struct nci_dev *ndev, 37 + struct sk_buff *skb, 38 + int err) 39 + { 40 + data_exchange_cb_t cb = ndev->data_exchange_cb; 41 + void *cb_context = ndev->data_exchange_cb_context; 42 + 43 + nfc_dbg("entry, len %d, err %d", ((skb) ? (skb->len) : (0)), err); 44 + 45 + if (cb) { 46 + ndev->data_exchange_cb = NULL; 47 + ndev->data_exchange_cb_context = 0; 48 + 49 + /* forward skb to nfc core */ 50 + cb(cb_context, skb, err); 51 + } else if (skb) { 52 + nfc_err("no rx callback, dropping rx data..."); 53 + 54 + /* no waiting callback, free skb */ 55 + kfree_skb(skb); 56 + } 57 + } 58 + 59 + /* ----------------- NCI TX Data ----------------- */ 60 + 61 + static inline void nci_push_data_hdr(struct nci_dev *ndev, 62 + __u8 conn_id, 63 + struct sk_buff *skb, 64 + __u8 pbf) 65 + { 66 + struct nci_data_hdr *hdr; 67 + int plen = skb->len; 68 + 69 + hdr = (struct nci_data_hdr *) skb_push(skb, NCI_DATA_HDR_SIZE); 70 + hdr->conn_id = conn_id; 71 + hdr->rfu = 0; 72 + hdr->plen = plen; 73 + 74 + nci_mt_set((__u8 *)hdr, NCI_MT_DATA_PKT); 75 + nci_pbf_set((__u8 *)hdr, pbf); 76 + 77 + skb->dev = (void *) ndev; 78 + } 79 + 80 + static int nci_queue_tx_data_frags(struct nci_dev *ndev, 81 + __u8 conn_id, 82 + struct sk_buff *skb) { 83 + int total_len = skb->len; 84 + unsigned char *data = skb->data; 85 + unsigned long flags; 86 + struct sk_buff_head frags_q; 87 + struct sk_buff *skb_frag; 88 + int frag_len; 89 + int rc = 0; 90 + 91 + nfc_dbg("entry, conn_id 0x%x, total_len %d", conn_id, total_len); 92 + 93 + __skb_queue_head_init(&frags_q); 94 + 95 + while (total_len) { 96 + frag_len = min_t(int, total_len, ndev->max_pkt_payload_size); 97 + 98 + skb_frag = nci_skb_alloc(ndev, 99 + (NCI_DATA_HDR_SIZE + frag_len), 100 + GFP_KERNEL); 101 + if (skb_frag == NULL) { 102 + rc = -ENOMEM; 103 + goto free_exit; 104 + } 105 + skb_reserve(skb_frag, NCI_DATA_HDR_SIZE); 106 + 107 + /* first, copy the data */ 108 + memcpy(skb_put(skb_frag, frag_len), data, frag_len); 109 + 110 + /* second, set the header */ 111 + nci_push_data_hdr(ndev, conn_id, skb_frag, 112 + ((total_len == frag_len) ? (NCI_PBF_LAST) : (NCI_PBF_CONT))); 113 + 114 + __skb_queue_tail(&frags_q, skb_frag); 115 + 116 + data += frag_len; 117 + total_len -= frag_len; 118 + 119 + nfc_dbg("frag_len %d, remaining total_len %d", 120 + frag_len, total_len); 121 + } 122 + 123 + /* queue all fragments atomically */ 124 + spin_lock_irqsave(&ndev->tx_q.lock, flags); 125 + 126 + while ((skb_frag = __skb_dequeue(&frags_q)) != NULL) 127 + __skb_queue_tail(&ndev->tx_q, skb_frag); 128 + 129 + spin_unlock_irqrestore(&ndev->tx_q.lock, flags); 130 + 131 + /* free the original skb */ 132 + kfree_skb(skb); 133 + 134 + goto exit; 135 + 136 + free_exit: 137 + while ((skb_frag = __skb_dequeue(&frags_q)) != NULL) 138 + kfree_skb(skb_frag); 139 + 140 + exit: 141 + return rc; 142 + } 143 + 144 + /* Send NCI data */ 145 + int nci_send_data(struct nci_dev *ndev, __u8 conn_id, struct sk_buff *skb) 146 + { 147 + int rc = 0; 148 + 149 + nfc_dbg("entry, conn_id 0x%x, plen %d", conn_id, skb->len); 150 + 151 + /* check if the packet need to be fragmented */ 152 + if (skb->len <= ndev->max_pkt_payload_size) { 153 + /* no need to fragment packet */ 154 + nci_push_data_hdr(ndev, conn_id, skb, NCI_PBF_LAST); 155 + 156 + skb_queue_tail(&ndev->tx_q, skb); 157 + } else { 158 + /* fragment packet and queue the fragments */ 159 + rc = nci_queue_tx_data_frags(ndev, conn_id, skb); 160 + if (rc) { 161 + nfc_err("failed to fragment tx data packet"); 162 + goto free_exit; 163 + } 164 + } 165 + 166 + queue_work(ndev->tx_wq, &ndev->tx_work); 167 + 168 + goto exit; 169 + 170 + free_exit: 171 + kfree_skb(skb); 172 + 173 + exit: 174 + return rc; 175 + } 176 + 177 + /* ----------------- NCI RX Data ----------------- */ 178 + 179 + static void nci_add_rx_data_frag(struct nci_dev *ndev, 180 + struct sk_buff *skb, 181 + __u8 pbf) 182 + { 183 + int reassembly_len; 184 + int err = 0; 185 + 186 + if (ndev->rx_data_reassembly) { 187 + reassembly_len = ndev->rx_data_reassembly->len; 188 + 189 + /* first, make enough room for the already accumulated data */ 190 + if (skb_cow_head(skb, reassembly_len)) { 191 + nfc_err("error adding room for accumulated rx data"); 192 + 193 + kfree_skb(skb); 194 + skb = 0; 195 + 196 + kfree_skb(ndev->rx_data_reassembly); 197 + ndev->rx_data_reassembly = 0; 198 + 199 + err = -ENOMEM; 200 + goto exit; 201 + } 202 + 203 + /* second, combine the two fragments */ 204 + memcpy(skb_push(skb, reassembly_len), 205 + ndev->rx_data_reassembly->data, 206 + reassembly_len); 207 + 208 + /* third, free old reassembly */ 209 + kfree_skb(ndev->rx_data_reassembly); 210 + ndev->rx_data_reassembly = 0; 211 + } 212 + 213 + if (pbf == NCI_PBF_CONT) { 214 + /* need to wait for next fragment, store skb and exit */ 215 + ndev->rx_data_reassembly = skb; 216 + return; 217 + } 218 + 219 + exit: 220 + nci_data_exchange_complete(ndev, skb, err); 221 + } 222 + 223 + /* Rx Data packet */ 224 + void nci_rx_data_packet(struct nci_dev *ndev, struct sk_buff *skb) 225 + { 226 + __u8 pbf = nci_pbf(skb->data); 227 + 228 + nfc_dbg("entry, len %d", skb->len); 229 + 230 + nfc_dbg("NCI RX: MT=data, PBF=%d, conn_id=%d, plen=%d", 231 + nci_pbf(skb->data), 232 + nci_conn_id(skb->data), 233 + nci_plen(skb->data)); 234 + 235 + /* strip the nci data header */ 236 + skb_pull(skb, NCI_DATA_HDR_SIZE); 237 + 238 + if (ndev->target_active_prot == NFC_PROTO_MIFARE) { 239 + /* frame I/F => remove the status byte */ 240 + nfc_dbg("NFC_PROTO_MIFARE => remove the status byte"); 241 + skb_trim(skb, (skb->len - 1)); 242 + } 243 + 244 + nci_add_rx_data_frag(ndev, skb, pbf); 245 + }
+94
net/nfc/nci/lib.c
··· 1 + /* 2 + * The NFC Controller Interface is the communication protocol between an 3 + * NFC Controller (NFCC) and a Device Host (DH). 4 + * 5 + * Copyright (C) 2011 Texas Instruments, Inc. 6 + * 7 + * Written by Ilan Elias <ilane@ti.com> 8 + * 9 + * Acknowledgements: 10 + * This file is based on lib.c, which was written 11 + * by Maxim Krasnyansky. 12 + * 13 + * This program is free software; you can redistribute it and/or modify 14 + * it under the terms of the GNU General Public License version 2 15 + * as published by the Free Software Foundation 16 + * 17 + * This program is distributed in the hope that it will be useful, 18 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 + * GNU General Public License for more details. 21 + * 22 + * You should have received a copy of the GNU General Public License 23 + * along with this program; if not, write to the Free Software 24 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 25 + * 26 + */ 27 + 28 + #include <linux/module.h> 29 + #include <linux/kernel.h> 30 + #include <linux/types.h> 31 + #include <linux/errno.h> 32 + 33 + #include <net/nfc/nci.h> 34 + 35 + /* NCI status codes to Unix errno mapping */ 36 + int nci_to_errno(__u8 code) 37 + { 38 + switch (code) { 39 + case NCI_STATUS_OK: 40 + return 0; 41 + 42 + case NCI_STATUS_REJECTED: 43 + return -EBUSY; 44 + 45 + case NCI_STATUS_MESSAGE_CORRUPTED: 46 + return -EBADMSG; 47 + 48 + case NCI_STATUS_BUFFER_FULL: 49 + return -ENOBUFS; 50 + 51 + case NCI_STATUS_NOT_INITIALIZED: 52 + return -EHOSTDOWN; 53 + 54 + case NCI_STATUS_SYNTAX_ERROR: 55 + case NCI_STATUS_SEMANTIC_ERROR: 56 + case NCI_STATUS_INVALID_PARAM: 57 + case NCI_STATUS_RF_PROTOCOL_ERROR: 58 + case NCI_STATUS_NFCEE_PROTOCOL_ERROR: 59 + return -EPROTO; 60 + 61 + case NCI_STATUS_UNKNOWN_GID: 62 + case NCI_STATUS_UNKNOWN_OID: 63 + return -EBADRQC; 64 + 65 + case NCI_STATUS_MESSAGE_SIZE_EXCEEDED: 66 + return -EMSGSIZE; 67 + 68 + case NCI_STATUS_DISCOVERY_ALREADY_STARTED: 69 + return -EALREADY; 70 + 71 + case NCI_STATUS_DISCOVERY_TARGET_ACTIVATION_FAILED: 72 + case NCI_STATUS_NFCEE_INTERFACE_ACTIVATION_FAILED: 73 + return -ECONNREFUSED; 74 + 75 + case NCI_STATUS_RF_TRANSMISSION_ERROR: 76 + case NCI_STATUS_NFCEE_TRANSMISSION_ERROR: 77 + return -ECOMM; 78 + 79 + case NCI_STATUS_RF_TIMEOUT_ERROR: 80 + case NCI_STATUS_NFCEE_TIMEOUT_ERROR: 81 + return -ETIMEDOUT; 82 + 83 + case NCI_STATUS_RF_LINK_LOSS_ERROR: 84 + return -ENOLINK; 85 + 86 + case NCI_STATUS_MAX_ACTIVE_NFCEE_INTERFACES_REACHED: 87 + return -EDQUOT; 88 + 89 + case NCI_STATUS_FAILED: 90 + default: 91 + return -ENOSYS; 92 + } 93 + } 94 + EXPORT_SYMBOL(nci_to_errno);
+258
net/nfc/nci/ntf.c
··· 1 + /* 2 + * The NFC Controller Interface is the communication protocol between an 3 + * NFC Controller (NFCC) and a Device Host (DH). 4 + * 5 + * Copyright (C) 2011 Texas Instruments, Inc. 6 + * 7 + * Written by Ilan Elias <ilane@ti.com> 8 + * 9 + * Acknowledgements: 10 + * This file is based on hci_event.c, which was written 11 + * by Maxim Krasnyansky. 12 + * 13 + * This program is free software; you can redistribute it and/or modify 14 + * it under the terms of the GNU General Public License version 2 15 + * as published by the Free Software Foundation 16 + * 17 + * This program is distributed in the hope that it will be useful, 18 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 + * GNU General Public License for more details. 21 + * 22 + * You should have received a copy of the GNU General Public License 23 + * along with this program; if not, write to the Free Software 24 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 25 + * 26 + */ 27 + 28 + #include <linux/types.h> 29 + #include <linux/interrupt.h> 30 + #include <linux/bitops.h> 31 + #include <linux/skbuff.h> 32 + 33 + #include "../nfc.h" 34 + #include <net/nfc/nci.h> 35 + #include <net/nfc/nci_core.h> 36 + #include <linux/nfc.h> 37 + 38 + /* Handle NCI Notification packets */ 39 + 40 + static void nci_core_conn_credits_ntf_packet(struct nci_dev *ndev, 41 + struct sk_buff *skb) 42 + { 43 + struct nci_core_conn_credit_ntf *ntf = (void *) skb->data; 44 + int i; 45 + 46 + nfc_dbg("entry, num_entries %d", ntf->num_entries); 47 + 48 + if (ntf->num_entries > NCI_MAX_NUM_CONN) 49 + ntf->num_entries = NCI_MAX_NUM_CONN; 50 + 51 + /* update the credits */ 52 + for (i = 0; i < ntf->num_entries; i++) { 53 + nfc_dbg("entry[%d]: conn_id %d, credits %d", i, 54 + ntf->conn_entries[i].conn_id, 55 + ntf->conn_entries[i].credits); 56 + 57 + if (ntf->conn_entries[i].conn_id == ndev->conn_id) { 58 + /* found static rf connection */ 59 + atomic_add(ntf->conn_entries[i].credits, 60 + &ndev->credits_cnt); 61 + } 62 + } 63 + 64 + /* trigger the next tx */ 65 + if (!skb_queue_empty(&ndev->tx_q)) 66 + queue_work(ndev->tx_wq, &ndev->tx_work); 67 + } 68 + 69 + static void nci_rf_field_info_ntf_packet(struct nci_dev *ndev, 70 + struct sk_buff *skb) 71 + { 72 + struct nci_rf_field_info_ntf *ntf = (void *) skb->data; 73 + 74 + nfc_dbg("entry, rf_field_status %d", ntf->rf_field_status); 75 + } 76 + 77 + static int nci_rf_activate_nfca_passive_poll(struct nci_dev *ndev, 78 + struct nci_rf_activate_ntf *ntf, __u8 *data) 79 + { 80 + struct rf_tech_specific_params_nfca_poll *nfca_poll; 81 + struct activation_params_nfca_poll_iso_dep *nfca_poll_iso_dep; 82 + 83 + nfca_poll = &ntf->rf_tech_specific_params.nfca_poll; 84 + nfca_poll_iso_dep = &ntf->activation_params.nfca_poll_iso_dep; 85 + 86 + nfca_poll->sens_res = __le16_to_cpu(*((__u16 *)data)); 87 + data += 2; 88 + 89 + nfca_poll->nfcid1_len = *data++; 90 + 91 + nfc_dbg("sens_res 0x%x, nfcid1_len %d", 92 + nfca_poll->sens_res, 93 + nfca_poll->nfcid1_len); 94 + 95 + memcpy(nfca_poll->nfcid1, data, nfca_poll->nfcid1_len); 96 + data += nfca_poll->nfcid1_len; 97 + 98 + nfca_poll->sel_res_len = *data++; 99 + 100 + if (nfca_poll->sel_res_len != 0) 101 + nfca_poll->sel_res = *data++; 102 + 103 + ntf->rf_interface_type = *data++; 104 + ntf->activation_params_len = *data++; 105 + 106 + nfc_dbg("sel_res_len %d, sel_res 0x%x, rf_interface_type %d, activation_params_len %d", 107 + nfca_poll->sel_res_len, 108 + nfca_poll->sel_res, 109 + ntf->rf_interface_type, 110 + ntf->activation_params_len); 111 + 112 + switch (ntf->rf_interface_type) { 113 + case NCI_RF_INTERFACE_ISO_DEP: 114 + nfca_poll_iso_dep->rats_res_len = *data++; 115 + if (nfca_poll_iso_dep->rats_res_len > 0) { 116 + memcpy(nfca_poll_iso_dep->rats_res, 117 + data, 118 + nfca_poll_iso_dep->rats_res_len); 119 + } 120 + break; 121 + 122 + case NCI_RF_INTERFACE_FRAME: 123 + /* no activation params */ 124 + break; 125 + 126 + default: 127 + nfc_err("unsupported rf_interface_type 0x%x", 128 + ntf->rf_interface_type); 129 + return -EPROTO; 130 + } 131 + 132 + return 0; 133 + } 134 + 135 + static void nci_target_found(struct nci_dev *ndev, 136 + struct nci_rf_activate_ntf *ntf) 137 + { 138 + struct nfc_target nfc_tgt; 139 + 140 + if (ntf->rf_protocol == NCI_RF_PROTOCOL_T2T) /* T2T MifareUL */ 141 + nfc_tgt.supported_protocols = NFC_PROTO_MIFARE_MASK; 142 + else if (ntf->rf_protocol == NCI_RF_PROTOCOL_ISO_DEP) /* 4A */ 143 + nfc_tgt.supported_protocols = NFC_PROTO_ISO14443_MASK; 144 + 145 + nfc_tgt.sens_res = ntf->rf_tech_specific_params.nfca_poll.sens_res; 146 + nfc_tgt.sel_res = ntf->rf_tech_specific_params.nfca_poll.sel_res; 147 + 148 + if (!(nfc_tgt.supported_protocols & ndev->poll_prots)) { 149 + nfc_dbg("the target found does not have the desired protocol"); 150 + return; 151 + } 152 + 153 + nfc_dbg("new target found, supported_protocols 0x%x", 154 + nfc_tgt.supported_protocols); 155 + 156 + ndev->target_available_prots = nfc_tgt.supported_protocols; 157 + 158 + nfc_targets_found(ndev->nfc_dev, &nfc_tgt, 1); 159 + } 160 + 161 + static void nci_rf_activate_ntf_packet(struct nci_dev *ndev, 162 + struct sk_buff *skb) 163 + { 164 + struct nci_rf_activate_ntf ntf; 165 + __u8 *data = skb->data; 166 + int rc = -1; 167 + 168 + clear_bit(NCI_DISCOVERY, &ndev->flags); 169 + set_bit(NCI_POLL_ACTIVE, &ndev->flags); 170 + 171 + ntf.target_handle = *data++; 172 + ntf.rf_protocol = *data++; 173 + ntf.rf_tech_and_mode = *data++; 174 + ntf.rf_tech_specific_params_len = *data++; 175 + 176 + nfc_dbg("target_handle %d, rf_protocol 0x%x, rf_tech_and_mode 0x%x, rf_tech_specific_params_len %d", 177 + ntf.target_handle, 178 + ntf.rf_protocol, 179 + ntf.rf_tech_and_mode, 180 + ntf.rf_tech_specific_params_len); 181 + 182 + switch (ntf.rf_tech_and_mode) { 183 + case NCI_NFC_A_PASSIVE_POLL_MODE: 184 + rc = nci_rf_activate_nfca_passive_poll(ndev, &ntf, 185 + data); 186 + break; 187 + 188 + default: 189 + nfc_err("unsupported rf_tech_and_mode 0x%x", 190 + ntf.rf_tech_and_mode); 191 + return; 192 + } 193 + 194 + if (!rc) 195 + nci_target_found(ndev, &ntf); 196 + } 197 + 198 + static void nci_rf_deactivate_ntf_packet(struct nci_dev *ndev, 199 + struct sk_buff *skb) 200 + { 201 + __u8 type = skb->data[0]; 202 + 203 + nfc_dbg("entry, type 0x%x", type); 204 + 205 + clear_bit(NCI_POLL_ACTIVE, &ndev->flags); 206 + ndev->target_active_prot = 0; 207 + 208 + /* drop tx data queue */ 209 + skb_queue_purge(&ndev->tx_q); 210 + 211 + /* drop partial rx data packet */ 212 + if (ndev->rx_data_reassembly) { 213 + kfree_skb(ndev->rx_data_reassembly); 214 + ndev->rx_data_reassembly = 0; 215 + } 216 + 217 + /* complete the data exchange transaction, if exists */ 218 + if (ndev->data_exchange_cb) 219 + nci_data_exchange_complete(ndev, NULL, -EIO); 220 + } 221 + 222 + void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb) 223 + { 224 + __u16 ntf_opcode = nci_opcode(skb->data); 225 + 226 + nfc_dbg("NCI RX: MT=ntf, PBF=%d, GID=0x%x, OID=0x%x, plen=%d", 227 + nci_pbf(skb->data), 228 + nci_opcode_gid(ntf_opcode), 229 + nci_opcode_oid(ntf_opcode), 230 + nci_plen(skb->data)); 231 + 232 + /* strip the nci control header */ 233 + skb_pull(skb, NCI_CTRL_HDR_SIZE); 234 + 235 + switch (ntf_opcode) { 236 + case NCI_OP_CORE_CONN_CREDITS_NTF: 237 + nci_core_conn_credits_ntf_packet(ndev, skb); 238 + break; 239 + 240 + case NCI_OP_RF_FIELD_INFO_NTF: 241 + nci_rf_field_info_ntf_packet(ndev, skb); 242 + break; 243 + 244 + case NCI_OP_RF_ACTIVATE_NTF: 245 + nci_rf_activate_ntf_packet(ndev, skb); 246 + break; 247 + 248 + case NCI_OP_RF_DEACTIVATE_NTF: 249 + nci_rf_deactivate_ntf_packet(ndev, skb); 250 + break; 251 + 252 + default: 253 + nfc_err("unknown ntf opcode 0x%x", ntf_opcode); 254 + break; 255 + } 256 + 257 + kfree_skb(skb); 258 + }
+226
net/nfc/nci/rsp.c
··· 1 + /* 2 + * The NFC Controller Interface is the communication protocol between an 3 + * NFC Controller (NFCC) and a Device Host (DH). 4 + * 5 + * Copyright (C) 2011 Texas Instruments, Inc. 6 + * 7 + * Written by Ilan Elias <ilane@ti.com> 8 + * 9 + * Acknowledgements: 10 + * This file is based on hci_event.c, which was written 11 + * by Maxim Krasnyansky. 12 + * 13 + * This program is free software; you can redistribute it and/or modify 14 + * it under the terms of the GNU General Public License version 2 15 + * as published by the Free Software Foundation 16 + * 17 + * This program is distributed in the hope that it will be useful, 18 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 + * GNU General Public License for more details. 21 + * 22 + * You should have received a copy of the GNU General Public License 23 + * along with this program; if not, write to the Free Software 24 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 25 + * 26 + */ 27 + 28 + #include <linux/types.h> 29 + #include <linux/interrupt.h> 30 + #include <linux/bitops.h> 31 + #include <linux/skbuff.h> 32 + 33 + #include "../nfc.h" 34 + #include <net/nfc/nci.h> 35 + #include <net/nfc/nci_core.h> 36 + 37 + /* Handle NCI Response packets */ 38 + 39 + static void nci_core_reset_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) 40 + { 41 + struct nci_core_reset_rsp *rsp = (void *) skb->data; 42 + 43 + nfc_dbg("entry, status 0x%x", rsp->status); 44 + 45 + if (rsp->status == NCI_STATUS_OK) 46 + ndev->nci_ver = rsp->nci_ver; 47 + 48 + nfc_dbg("nci_ver 0x%x", ndev->nci_ver); 49 + 50 + nci_req_complete(ndev, rsp->status); 51 + } 52 + 53 + static void nci_core_init_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) 54 + { 55 + struct nci_core_init_rsp_1 *rsp_1 = (void *) skb->data; 56 + struct nci_core_init_rsp_2 *rsp_2; 57 + 58 + nfc_dbg("entry, status 0x%x", rsp_1->status); 59 + 60 + if (rsp_1->status != NCI_STATUS_OK) 61 + return; 62 + 63 + ndev->nfcc_features = __le32_to_cpu(rsp_1->nfcc_features); 64 + ndev->num_supported_rf_interfaces = rsp_1->num_supported_rf_interfaces; 65 + 66 + if (ndev->num_supported_rf_interfaces > 67 + NCI_MAX_SUPPORTED_RF_INTERFACES) { 68 + ndev->num_supported_rf_interfaces = 69 + NCI_MAX_SUPPORTED_RF_INTERFACES; 70 + } 71 + 72 + memcpy(ndev->supported_rf_interfaces, 73 + rsp_1->supported_rf_interfaces, 74 + ndev->num_supported_rf_interfaces); 75 + 76 + rsp_2 = (void *) (skb->data + 6 + ndev->num_supported_rf_interfaces); 77 + 78 + ndev->max_logical_connections = 79 + rsp_2->max_logical_connections; 80 + ndev->max_routing_table_size = 81 + __le16_to_cpu(rsp_2->max_routing_table_size); 82 + ndev->max_control_packet_payload_length = 83 + rsp_2->max_control_packet_payload_length; 84 + ndev->rf_sending_buffer_size = 85 + __le16_to_cpu(rsp_2->rf_sending_buffer_size); 86 + ndev->rf_receiving_buffer_size = 87 + __le16_to_cpu(rsp_2->rf_receiving_buffer_size); 88 + ndev->manufacturer_id = 89 + __le16_to_cpu(rsp_2->manufacturer_id); 90 + 91 + nfc_dbg("nfcc_features 0x%x", 92 + ndev->nfcc_features); 93 + nfc_dbg("num_supported_rf_interfaces %d", 94 + ndev->num_supported_rf_interfaces); 95 + nfc_dbg("supported_rf_interfaces[0] 0x%x", 96 + ndev->supported_rf_interfaces[0]); 97 + nfc_dbg("supported_rf_interfaces[1] 0x%x", 98 + ndev->supported_rf_interfaces[1]); 99 + nfc_dbg("supported_rf_interfaces[2] 0x%x", 100 + ndev->supported_rf_interfaces[2]); 101 + nfc_dbg("supported_rf_interfaces[3] 0x%x", 102 + ndev->supported_rf_interfaces[3]); 103 + nfc_dbg("max_logical_connections %d", 104 + ndev->max_logical_connections); 105 + nfc_dbg("max_routing_table_size %d", 106 + ndev->max_routing_table_size); 107 + nfc_dbg("max_control_packet_payload_length %d", 108 + ndev->max_control_packet_payload_length); 109 + nfc_dbg("rf_sending_buffer_size %d", 110 + ndev->rf_sending_buffer_size); 111 + nfc_dbg("rf_receiving_buffer_size %d", 112 + ndev->rf_receiving_buffer_size); 113 + nfc_dbg("manufacturer_id 0x%x", 114 + ndev->manufacturer_id); 115 + 116 + nci_req_complete(ndev, rsp_1->status); 117 + } 118 + 119 + static void nci_core_conn_create_rsp_packet(struct nci_dev *ndev, 120 + struct sk_buff *skb) 121 + { 122 + struct nci_core_conn_create_rsp *rsp = (void *) skb->data; 123 + 124 + nfc_dbg("entry, status 0x%x", rsp->status); 125 + 126 + if (rsp->status != NCI_STATUS_OK) 127 + return; 128 + 129 + ndev->max_pkt_payload_size = rsp->max_pkt_payload_size; 130 + ndev->initial_num_credits = rsp->initial_num_credits; 131 + ndev->conn_id = rsp->conn_id; 132 + 133 + atomic_set(&ndev->credits_cnt, ndev->initial_num_credits); 134 + 135 + nfc_dbg("max_pkt_payload_size %d", ndev->max_pkt_payload_size); 136 + nfc_dbg("initial_num_credits %d", ndev->initial_num_credits); 137 + nfc_dbg("conn_id %d", ndev->conn_id); 138 + } 139 + 140 + static void nci_rf_disc_map_rsp_packet(struct nci_dev *ndev, 141 + struct sk_buff *skb) 142 + { 143 + __u8 status = skb->data[0]; 144 + 145 + nfc_dbg("entry, status 0x%x", status); 146 + 147 + nci_req_complete(ndev, status); 148 + } 149 + 150 + static void nci_rf_disc_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) 151 + { 152 + __u8 status = skb->data[0]; 153 + 154 + nfc_dbg("entry, status 0x%x", status); 155 + 156 + if (status == NCI_STATUS_OK) 157 + set_bit(NCI_DISCOVERY, &ndev->flags); 158 + 159 + nci_req_complete(ndev, status); 160 + } 161 + 162 + static void nci_rf_deactivate_rsp_packet(struct nci_dev *ndev, 163 + struct sk_buff *skb) 164 + { 165 + __u8 status = skb->data[0]; 166 + 167 + nfc_dbg("entry, status 0x%x", status); 168 + 169 + clear_bit(NCI_DISCOVERY, &ndev->flags); 170 + 171 + nci_req_complete(ndev, status); 172 + } 173 + 174 + void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) 175 + { 176 + __u16 rsp_opcode = nci_opcode(skb->data); 177 + 178 + /* we got a rsp, stop the cmd timer */ 179 + del_timer(&ndev->cmd_timer); 180 + 181 + nfc_dbg("NCI RX: MT=rsp, PBF=%d, GID=0x%x, OID=0x%x, plen=%d", 182 + nci_pbf(skb->data), 183 + nci_opcode_gid(rsp_opcode), 184 + nci_opcode_oid(rsp_opcode), 185 + nci_plen(skb->data)); 186 + 187 + /* strip the nci control header */ 188 + skb_pull(skb, NCI_CTRL_HDR_SIZE); 189 + 190 + switch (rsp_opcode) { 191 + case NCI_OP_CORE_RESET_RSP: 192 + nci_core_reset_rsp_packet(ndev, skb); 193 + break; 194 + 195 + case NCI_OP_CORE_INIT_RSP: 196 + nci_core_init_rsp_packet(ndev, skb); 197 + break; 198 + 199 + case NCI_OP_CORE_CONN_CREATE_RSP: 200 + nci_core_conn_create_rsp_packet(ndev, skb); 201 + break; 202 + 203 + case NCI_OP_RF_DISCOVER_MAP_RSP: 204 + nci_rf_disc_map_rsp_packet(ndev, skb); 205 + break; 206 + 207 + case NCI_OP_RF_DISCOVER_RSP: 208 + nci_rf_disc_rsp_packet(ndev, skb); 209 + break; 210 + 211 + case NCI_OP_RF_DEACTIVATE_RSP: 212 + nci_rf_deactivate_rsp_packet(ndev, skb); 213 + break; 214 + 215 + default: 216 + nfc_err("unknown rsp opcode 0x%x", rsp_opcode); 217 + break; 218 + } 219 + 220 + kfree_skb(skb); 221 + 222 + /* trigger the next cmd */ 223 + atomic_set(&ndev->cmd_cnt, 1); 224 + if (!skb_queue_empty(&ndev->cmd_q)) 225 + queue_work(ndev->cmd_wq, &ndev->cmd_work); 226 + }