197f18414SEric Lapuyade /* 297f18414SEric Lapuyade * HCI based Driver for NXP PN544 NFC Chip 397f18414SEric Lapuyade * 497f18414SEric Lapuyade * Copyright (C) 2012 Intel Corporation. All rights reserved. 597f18414SEric Lapuyade * 697f18414SEric Lapuyade * This program is free software; you can redistribute it and/or modify it 797f18414SEric Lapuyade * under the terms and conditions of the GNU General Public License, 897f18414SEric Lapuyade * version 2, as published by the Free Software Foundation. 997f18414SEric Lapuyade * 1097f18414SEric Lapuyade * This program is distributed in the hope that it will be useful, 1197f18414SEric Lapuyade * but WITHOUT ANY WARRANTY; without even the implied warranty of 1297f18414SEric Lapuyade * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1397f18414SEric Lapuyade * GNU General Public License for more details. 1497f18414SEric Lapuyade * 1597f18414SEric Lapuyade * You should have received a copy of the GNU General Public License 1697f18414SEric Lapuyade * along with this program; if not, write to the 1797f18414SEric Lapuyade * Free Software Foundation, Inc., 1897f18414SEric Lapuyade * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 1997f18414SEric Lapuyade */ 2097f18414SEric Lapuyade 2197f18414SEric Lapuyade #include <linux/delay.h> 2297f18414SEric Lapuyade #include <linux/slab.h> 23aa741030SSamuel Ortiz #include <linux/module.h> 2497f18414SEric Lapuyade 2597f18414SEric Lapuyade #include <linux/nfc.h> 2697f18414SEric Lapuyade #include <net/nfc/hci.h> 2797f18414SEric Lapuyade #include <net/nfc/llc.h> 2897f18414SEric Lapuyade 2997f18414SEric Lapuyade #include "pn544.h" 3097f18414SEric Lapuyade 3197f18414SEric Lapuyade /* Timing restrictions (ms) */ 3297f18414SEric Lapuyade #define PN544_HCI_RESETVEN_TIME 30 3397f18414SEric Lapuyade 3497f18414SEric Lapuyade #define HCI_MODE 0 3597f18414SEric Lapuyade #define FW_MODE 1 3697f18414SEric Lapuyade 3797f18414SEric Lapuyade enum pn544_state { 3897f18414SEric Lapuyade PN544_ST_COLD, 3997f18414SEric Lapuyade PN544_ST_FW_READY, 4097f18414SEric Lapuyade PN544_ST_READY, 4197f18414SEric Lapuyade }; 4297f18414SEric Lapuyade 4397f18414SEric Lapuyade #define FULL_VERSION_LEN 11 4497f18414SEric Lapuyade 4597f18414SEric Lapuyade /* Proprietary commands */ 4697f18414SEric Lapuyade #define PN544_WRITE 0x3f 4797f18414SEric Lapuyade 4897f18414SEric Lapuyade /* Proprietary gates, events, commands and registers */ 4997f18414SEric Lapuyade 5097f18414SEric Lapuyade /* NFC_HCI_RF_READER_A_GATE additional registers and commands */ 5197f18414SEric Lapuyade #define PN544_RF_READER_A_AUTO_ACTIVATION 0x10 5297f18414SEric Lapuyade #define PN544_RF_READER_A_CMD_CONTINUE_ACTIVATION 0x12 5397f18414SEric Lapuyade #define PN544_MIFARE_CMD 0x21 5497f18414SEric Lapuyade 5597f18414SEric Lapuyade /* Commands that apply to all RF readers */ 5697f18414SEric Lapuyade #define PN544_RF_READER_CMD_PRESENCE_CHECK 0x30 5797f18414SEric Lapuyade #define PN544_RF_READER_CMD_ACTIVATE_NEXT 0x32 5897f18414SEric Lapuyade 5997f18414SEric Lapuyade /* NFC_HCI_ID_MGMT_GATE additional registers */ 6097f18414SEric Lapuyade #define PN544_ID_MGMT_FULL_VERSION_SW 0x10 6197f18414SEric Lapuyade 6297f18414SEric Lapuyade #define PN544_RF_READER_ISO15693_GATE 0x12 6397f18414SEric Lapuyade 6497f18414SEric Lapuyade #define PN544_RF_READER_F_GATE 0x14 6597f18414SEric Lapuyade #define PN544_FELICA_ID 0x04 6697f18414SEric Lapuyade #define PN544_FELICA_RAW 0x20 6797f18414SEric Lapuyade 6897f18414SEric Lapuyade #define PN544_RF_READER_JEWEL_GATE 0x15 6997f18414SEric Lapuyade #define PN544_JEWEL_RAW_CMD 0x23 7097f18414SEric Lapuyade 7197f18414SEric Lapuyade #define PN544_RF_READER_NFCIP1_INITIATOR_GATE 0x30 7297f18414SEric Lapuyade #define PN544_RF_READER_NFCIP1_TARGET_GATE 0x31 7397f18414SEric Lapuyade 7497f18414SEric Lapuyade #define PN544_SYS_MGMT_GATE 0x90 7597f18414SEric Lapuyade #define PN544_SYS_MGMT_INFO_NOTIFICATION 0x02 7697f18414SEric Lapuyade 7797f18414SEric Lapuyade #define PN544_POLLING_LOOP_MGMT_GATE 0x94 7897f18414SEric Lapuyade #define PN544_DEP_MODE 0x01 7997f18414SEric Lapuyade #define PN544_DEP_ATR_REQ 0x02 8097f18414SEric Lapuyade #define PN544_DEP_ATR_RES 0x03 8197f18414SEric Lapuyade #define PN544_DEP_MERGE 0x0D 8297f18414SEric Lapuyade #define PN544_PL_RDPHASES 0x06 8397f18414SEric Lapuyade #define PN544_PL_EMULATION 0x07 8497f18414SEric Lapuyade #define PN544_PL_NFCT_DEACTIVATED 0x09 8597f18414SEric Lapuyade 8697f18414SEric Lapuyade #define PN544_SWP_MGMT_GATE 0xA0 8797f18414SEric Lapuyade 8897f18414SEric Lapuyade #define PN544_NFC_WI_MGMT_GATE 0xA1 8997f18414SEric Lapuyade 9097f18414SEric Lapuyade #define PN544_HCI_EVT_SND_DATA 0x01 9197f18414SEric Lapuyade #define PN544_HCI_EVT_ACTIVATED 0x02 9297f18414SEric Lapuyade #define PN544_HCI_EVT_DEACTIVATED 0x03 9397f18414SEric Lapuyade #define PN544_HCI_EVT_RCV_DATA 0x04 9497f18414SEric Lapuyade #define PN544_HCI_EVT_CONTINUE_MI 0x05 9597f18414SEric Lapuyade 9697f18414SEric Lapuyade #define PN544_HCI_CMD_ATTREQUEST 0x12 9797f18414SEric Lapuyade #define PN544_HCI_CMD_CONTINUE_ACTIVATION 0x13 9897f18414SEric Lapuyade 9997f18414SEric Lapuyade static struct nfc_hci_gate pn544_gates[] = { 10097f18414SEric Lapuyade {NFC_HCI_ADMIN_GATE, NFC_HCI_INVALID_PIPE}, 10197f18414SEric Lapuyade {NFC_HCI_LOOPBACK_GATE, NFC_HCI_INVALID_PIPE}, 10297f18414SEric Lapuyade {NFC_HCI_ID_MGMT_GATE, NFC_HCI_INVALID_PIPE}, 10397f18414SEric Lapuyade {NFC_HCI_LINK_MGMT_GATE, NFC_HCI_INVALID_PIPE}, 10497f18414SEric Lapuyade {NFC_HCI_RF_READER_B_GATE, NFC_HCI_INVALID_PIPE}, 10597f18414SEric Lapuyade {NFC_HCI_RF_READER_A_GATE, NFC_HCI_INVALID_PIPE}, 10697f18414SEric Lapuyade {PN544_SYS_MGMT_GATE, NFC_HCI_INVALID_PIPE}, 10797f18414SEric Lapuyade {PN544_SWP_MGMT_GATE, NFC_HCI_INVALID_PIPE}, 10897f18414SEric Lapuyade {PN544_POLLING_LOOP_MGMT_GATE, NFC_HCI_INVALID_PIPE}, 10997f18414SEric Lapuyade {PN544_NFC_WI_MGMT_GATE, NFC_HCI_INVALID_PIPE}, 11097f18414SEric Lapuyade {PN544_RF_READER_F_GATE, NFC_HCI_INVALID_PIPE}, 11197f18414SEric Lapuyade {PN544_RF_READER_JEWEL_GATE, NFC_HCI_INVALID_PIPE}, 11297f18414SEric Lapuyade {PN544_RF_READER_ISO15693_GATE, NFC_HCI_INVALID_PIPE}, 11397f18414SEric Lapuyade {PN544_RF_READER_NFCIP1_INITIATOR_GATE, NFC_HCI_INVALID_PIPE}, 11497f18414SEric Lapuyade {PN544_RF_READER_NFCIP1_TARGET_GATE, NFC_HCI_INVALID_PIPE} 11597f18414SEric Lapuyade }; 11697f18414SEric Lapuyade 11797f18414SEric Lapuyade /* Largest headroom needed for outgoing custom commands */ 11897f18414SEric Lapuyade #define PN544_CMDS_HEADROOM 2 11997f18414SEric Lapuyade 12097f18414SEric Lapuyade struct pn544_hci_info { 12197f18414SEric Lapuyade struct nfc_phy_ops *phy_ops; 12297f18414SEric Lapuyade void *phy_id; 12397f18414SEric Lapuyade 12497f18414SEric Lapuyade struct nfc_hci_dev *hdev; 12597f18414SEric Lapuyade 12697f18414SEric Lapuyade enum pn544_state state; 12797f18414SEric Lapuyade 12897f18414SEric Lapuyade struct mutex info_lock; 12997f18414SEric Lapuyade 13097f18414SEric Lapuyade int async_cb_type; 13197f18414SEric Lapuyade data_exchange_cb_t async_cb; 13297f18414SEric Lapuyade void *async_cb_context; 13397f18414SEric Lapuyade }; 13497f18414SEric Lapuyade 13597f18414SEric Lapuyade static int pn544_hci_open(struct nfc_hci_dev *hdev) 13697f18414SEric Lapuyade { 13797f18414SEric Lapuyade struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev); 13897f18414SEric Lapuyade int r = 0; 13997f18414SEric Lapuyade 14097f18414SEric Lapuyade mutex_lock(&info->info_lock); 14197f18414SEric Lapuyade 14297f18414SEric Lapuyade if (info->state != PN544_ST_COLD) { 14397f18414SEric Lapuyade r = -EBUSY; 14497f18414SEric Lapuyade goto out; 14597f18414SEric Lapuyade } 14697f18414SEric Lapuyade 14797f18414SEric Lapuyade r = info->phy_ops->enable(info->phy_id); 14897f18414SEric Lapuyade 14997f18414SEric Lapuyade if (r == 0) 15097f18414SEric Lapuyade info->state = PN544_ST_READY; 15197f18414SEric Lapuyade 15297f18414SEric Lapuyade out: 15397f18414SEric Lapuyade mutex_unlock(&info->info_lock); 15497f18414SEric Lapuyade return r; 15597f18414SEric Lapuyade } 15697f18414SEric Lapuyade 15797f18414SEric Lapuyade static void pn544_hci_close(struct nfc_hci_dev *hdev) 15897f18414SEric Lapuyade { 15997f18414SEric Lapuyade struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev); 16097f18414SEric Lapuyade 16197f18414SEric Lapuyade mutex_lock(&info->info_lock); 16297f18414SEric Lapuyade 16397f18414SEric Lapuyade if (info->state == PN544_ST_COLD) 16497f18414SEric Lapuyade goto out; 16597f18414SEric Lapuyade 16697f18414SEric Lapuyade info->phy_ops->disable(info->phy_id); 16797f18414SEric Lapuyade 16897f18414SEric Lapuyade info->state = PN544_ST_COLD; 16997f18414SEric Lapuyade 17097f18414SEric Lapuyade out: 17197f18414SEric Lapuyade mutex_unlock(&info->info_lock); 17297f18414SEric Lapuyade } 17397f18414SEric Lapuyade 17497f18414SEric Lapuyade static int pn544_hci_ready(struct nfc_hci_dev *hdev) 17597f18414SEric Lapuyade { 17697f18414SEric Lapuyade struct sk_buff *skb; 17797f18414SEric Lapuyade static struct hw_config { 17897f18414SEric Lapuyade u8 adr[2]; 17997f18414SEric Lapuyade u8 value; 18097f18414SEric Lapuyade } hw_config[] = { 18197f18414SEric Lapuyade {{0x9f, 0x9a}, 0x00}, 18297f18414SEric Lapuyade 18397f18414SEric Lapuyade {{0x98, 0x10}, 0xbc}, 18497f18414SEric Lapuyade 18597f18414SEric Lapuyade {{0x9e, 0x71}, 0x00}, 18697f18414SEric Lapuyade 18797f18414SEric Lapuyade {{0x98, 0x09}, 0x00}, 18897f18414SEric Lapuyade 18997f18414SEric Lapuyade {{0x9e, 0xb4}, 0x00}, 19097f18414SEric Lapuyade 19197f18414SEric Lapuyade {{0x9e, 0xd9}, 0xff}, 19297f18414SEric Lapuyade {{0x9e, 0xda}, 0xff}, 19397f18414SEric Lapuyade {{0x9e, 0xdb}, 0x23}, 19497f18414SEric Lapuyade {{0x9e, 0xdc}, 0x21}, 19597f18414SEric Lapuyade {{0x9e, 0xdd}, 0x22}, 19697f18414SEric Lapuyade {{0x9e, 0xde}, 0x24}, 19797f18414SEric Lapuyade 19897f18414SEric Lapuyade {{0x9c, 0x01}, 0x08}, 19997f18414SEric Lapuyade 20097f18414SEric Lapuyade {{0x9e, 0xaa}, 0x01}, 20197f18414SEric Lapuyade 20297f18414SEric Lapuyade {{0x9b, 0xd1}, 0x0d}, 20397f18414SEric Lapuyade {{0x9b, 0xd2}, 0x24}, 20497f18414SEric Lapuyade {{0x9b, 0xd3}, 0x0a}, 20597f18414SEric Lapuyade {{0x9b, 0xd4}, 0x22}, 20697f18414SEric Lapuyade {{0x9b, 0xd5}, 0x08}, 20797f18414SEric Lapuyade {{0x9b, 0xd6}, 0x1e}, 20897f18414SEric Lapuyade {{0x9b, 0xdd}, 0x1c}, 20997f18414SEric Lapuyade 21097f18414SEric Lapuyade {{0x9b, 0x84}, 0x13}, 21197f18414SEric Lapuyade {{0x99, 0x81}, 0x7f}, 21297f18414SEric Lapuyade {{0x99, 0x31}, 0x70}, 21397f18414SEric Lapuyade 21497f18414SEric Lapuyade {{0x98, 0x00}, 0x3f}, 21597f18414SEric Lapuyade 21697f18414SEric Lapuyade {{0x9f, 0x09}, 0x00}, 21797f18414SEric Lapuyade 21897f18414SEric Lapuyade {{0x9f, 0x0a}, 0x05}, 21997f18414SEric Lapuyade 22097f18414SEric Lapuyade {{0x9e, 0xd1}, 0xa1}, 22197f18414SEric Lapuyade {{0x99, 0x23}, 0x00}, 22297f18414SEric Lapuyade 22397f18414SEric Lapuyade {{0x9e, 0x74}, 0x80}, 22497f18414SEric Lapuyade 22597f18414SEric Lapuyade {{0x9f, 0x28}, 0x10}, 22697f18414SEric Lapuyade 22797f18414SEric Lapuyade {{0x9f, 0x35}, 0x14}, 22897f18414SEric Lapuyade 22997f18414SEric Lapuyade {{0x9f, 0x36}, 0x60}, 23097f18414SEric Lapuyade 23197f18414SEric Lapuyade {{0x9c, 0x31}, 0x00}, 23297f18414SEric Lapuyade 23397f18414SEric Lapuyade {{0x9c, 0x32}, 0xc8}, 23497f18414SEric Lapuyade 23597f18414SEric Lapuyade {{0x9c, 0x19}, 0x40}, 23697f18414SEric Lapuyade 23797f18414SEric Lapuyade {{0x9c, 0x1a}, 0x40}, 23897f18414SEric Lapuyade 23997f18414SEric Lapuyade {{0x9c, 0x0c}, 0x00}, 24097f18414SEric Lapuyade 24197f18414SEric Lapuyade {{0x9c, 0x0d}, 0x00}, 24297f18414SEric Lapuyade 24397f18414SEric Lapuyade {{0x9c, 0x12}, 0x00}, 24497f18414SEric Lapuyade 24597f18414SEric Lapuyade {{0x9c, 0x13}, 0x00}, 24697f18414SEric Lapuyade 24797f18414SEric Lapuyade {{0x98, 0xa2}, 0x0e}, 24897f18414SEric Lapuyade 24997f18414SEric Lapuyade {{0x98, 0x93}, 0x40}, 25097f18414SEric Lapuyade 25197f18414SEric Lapuyade {{0x98, 0x7d}, 0x02}, 25297f18414SEric Lapuyade {{0x98, 0x7e}, 0x00}, 25397f18414SEric Lapuyade {{0x9f, 0xc8}, 0x01}, 25497f18414SEric Lapuyade }; 25597f18414SEric Lapuyade struct hw_config *p = hw_config; 25697f18414SEric Lapuyade int count = ARRAY_SIZE(hw_config); 25797f18414SEric Lapuyade struct sk_buff *res_skb; 25897f18414SEric Lapuyade u8 param[4]; 25997f18414SEric Lapuyade int r; 26097f18414SEric Lapuyade 26197f18414SEric Lapuyade param[0] = 0; 26297f18414SEric Lapuyade while (count--) { 26397f18414SEric Lapuyade param[1] = p->adr[0]; 26497f18414SEric Lapuyade param[2] = p->adr[1]; 26597f18414SEric Lapuyade param[3] = p->value; 26697f18414SEric Lapuyade 26797f18414SEric Lapuyade r = nfc_hci_send_cmd(hdev, PN544_SYS_MGMT_GATE, PN544_WRITE, 26897f18414SEric Lapuyade param, 4, &res_skb); 26997f18414SEric Lapuyade if (r < 0) 27097f18414SEric Lapuyade return r; 27197f18414SEric Lapuyade 27297f18414SEric Lapuyade if (res_skb->len != 1) { 27397f18414SEric Lapuyade kfree_skb(res_skb); 27497f18414SEric Lapuyade return -EPROTO; 27597f18414SEric Lapuyade } 27697f18414SEric Lapuyade 27797f18414SEric Lapuyade if (res_skb->data[0] != p->value) { 27897f18414SEric Lapuyade kfree_skb(res_skb); 27997f18414SEric Lapuyade return -EIO; 28097f18414SEric Lapuyade } 28197f18414SEric Lapuyade 28297f18414SEric Lapuyade kfree_skb(res_skb); 28397f18414SEric Lapuyade 28497f18414SEric Lapuyade p++; 28597f18414SEric Lapuyade } 28697f18414SEric Lapuyade 28797f18414SEric Lapuyade param[0] = NFC_HCI_UICC_HOST_ID; 28897f18414SEric Lapuyade r = nfc_hci_set_param(hdev, NFC_HCI_ADMIN_GATE, 28997f18414SEric Lapuyade NFC_HCI_ADMIN_WHITELIST, param, 1); 29097f18414SEric Lapuyade if (r < 0) 29197f18414SEric Lapuyade return r; 29297f18414SEric Lapuyade 29397f18414SEric Lapuyade param[0] = 0x3d; 29497f18414SEric Lapuyade r = nfc_hci_set_param(hdev, PN544_SYS_MGMT_GATE, 29597f18414SEric Lapuyade PN544_SYS_MGMT_INFO_NOTIFICATION, param, 1); 29697f18414SEric Lapuyade if (r < 0) 29797f18414SEric Lapuyade return r; 29897f18414SEric Lapuyade 29997f18414SEric Lapuyade param[0] = 0x0; 30097f18414SEric Lapuyade r = nfc_hci_set_param(hdev, NFC_HCI_RF_READER_A_GATE, 30197f18414SEric Lapuyade PN544_RF_READER_A_AUTO_ACTIVATION, param, 1); 30297f18414SEric Lapuyade if (r < 0) 30397f18414SEric Lapuyade return r; 30497f18414SEric Lapuyade 30597f18414SEric Lapuyade r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, 30697f18414SEric Lapuyade NFC_HCI_EVT_END_OPERATION, NULL, 0); 30797f18414SEric Lapuyade if (r < 0) 30897f18414SEric Lapuyade return r; 30997f18414SEric Lapuyade 31097f18414SEric Lapuyade param[0] = 0x1; 31197f18414SEric Lapuyade r = nfc_hci_set_param(hdev, PN544_POLLING_LOOP_MGMT_GATE, 31297f18414SEric Lapuyade PN544_PL_NFCT_DEACTIVATED, param, 1); 31397f18414SEric Lapuyade if (r < 0) 31497f18414SEric Lapuyade return r; 31597f18414SEric Lapuyade 31697f18414SEric Lapuyade param[0] = 0x0; 31797f18414SEric Lapuyade r = nfc_hci_set_param(hdev, PN544_POLLING_LOOP_MGMT_GATE, 31897f18414SEric Lapuyade PN544_PL_RDPHASES, param, 1); 31997f18414SEric Lapuyade if (r < 0) 32097f18414SEric Lapuyade return r; 32197f18414SEric Lapuyade 32297f18414SEric Lapuyade r = nfc_hci_get_param(hdev, NFC_HCI_ID_MGMT_GATE, 32397f18414SEric Lapuyade PN544_ID_MGMT_FULL_VERSION_SW, &skb); 32497f18414SEric Lapuyade if (r < 0) 32597f18414SEric Lapuyade return r; 32697f18414SEric Lapuyade 32797f18414SEric Lapuyade if (skb->len != FULL_VERSION_LEN) { 32897f18414SEric Lapuyade kfree_skb(skb); 32997f18414SEric Lapuyade return -EINVAL; 33097f18414SEric Lapuyade } 33197f18414SEric Lapuyade 33297f18414SEric Lapuyade print_hex_dump(KERN_DEBUG, "FULL VERSION SOFTWARE INFO: ", 33397f18414SEric Lapuyade DUMP_PREFIX_NONE, 16, 1, 33497f18414SEric Lapuyade skb->data, FULL_VERSION_LEN, false); 33597f18414SEric Lapuyade 33697f18414SEric Lapuyade kfree_skb(skb); 33797f18414SEric Lapuyade 33897f18414SEric Lapuyade return 0; 33997f18414SEric Lapuyade } 34097f18414SEric Lapuyade 34197f18414SEric Lapuyade static int pn544_hci_xmit(struct nfc_hci_dev *hdev, struct sk_buff *skb) 34297f18414SEric Lapuyade { 34397f18414SEric Lapuyade struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev); 34497f18414SEric Lapuyade 34597f18414SEric Lapuyade return info->phy_ops->write(info->phy_id, skb); 34697f18414SEric Lapuyade } 34797f18414SEric Lapuyade 34897f18414SEric Lapuyade static int pn544_hci_start_poll(struct nfc_hci_dev *hdev, 34997f18414SEric Lapuyade u32 im_protocols, u32 tm_protocols) 35097f18414SEric Lapuyade { 35197f18414SEric Lapuyade u8 phases = 0; 35297f18414SEric Lapuyade int r; 35397f18414SEric Lapuyade u8 duration[2]; 35497f18414SEric Lapuyade u8 activated; 35597f18414SEric Lapuyade u8 i_mode = 0x3f; /* Enable all supported modes */ 35697f18414SEric Lapuyade u8 t_mode = 0x0f; 35797f18414SEric Lapuyade u8 t_merge = 0x01; /* Enable merge by default */ 35897f18414SEric Lapuyade 35997f18414SEric Lapuyade pr_info(DRIVER_DESC ": %s protocols 0x%x 0x%x\n", 36097f18414SEric Lapuyade __func__, im_protocols, tm_protocols); 36197f18414SEric Lapuyade 36297f18414SEric Lapuyade r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, 36397f18414SEric Lapuyade NFC_HCI_EVT_END_OPERATION, NULL, 0); 36497f18414SEric Lapuyade if (r < 0) 36597f18414SEric Lapuyade return r; 36697f18414SEric Lapuyade 36797f18414SEric Lapuyade duration[0] = 0x18; 36897f18414SEric Lapuyade duration[1] = 0x6a; 36997f18414SEric Lapuyade r = nfc_hci_set_param(hdev, PN544_POLLING_LOOP_MGMT_GATE, 37097f18414SEric Lapuyade PN544_PL_EMULATION, duration, 2); 37197f18414SEric Lapuyade if (r < 0) 37297f18414SEric Lapuyade return r; 37397f18414SEric Lapuyade 37497f18414SEric Lapuyade activated = 0; 37597f18414SEric Lapuyade r = nfc_hci_set_param(hdev, PN544_POLLING_LOOP_MGMT_GATE, 37697f18414SEric Lapuyade PN544_PL_NFCT_DEACTIVATED, &activated, 1); 37797f18414SEric Lapuyade if (r < 0) 37897f18414SEric Lapuyade return r; 37997f18414SEric Lapuyade 38097f18414SEric Lapuyade if (im_protocols & (NFC_PROTO_ISO14443_MASK | NFC_PROTO_MIFARE_MASK | 38197f18414SEric Lapuyade NFC_PROTO_JEWEL_MASK)) 38297f18414SEric Lapuyade phases |= 1; /* Type A */ 38397f18414SEric Lapuyade if (im_protocols & NFC_PROTO_FELICA_MASK) { 38497f18414SEric Lapuyade phases |= (1 << 2); /* Type F 212 */ 38597f18414SEric Lapuyade phases |= (1 << 3); /* Type F 424 */ 38697f18414SEric Lapuyade } 38797f18414SEric Lapuyade 38897f18414SEric Lapuyade phases |= (1 << 5); /* NFC active */ 38997f18414SEric Lapuyade 39097f18414SEric Lapuyade r = nfc_hci_set_param(hdev, PN544_POLLING_LOOP_MGMT_GATE, 39197f18414SEric Lapuyade PN544_PL_RDPHASES, &phases, 1); 39297f18414SEric Lapuyade if (r < 0) 39397f18414SEric Lapuyade return r; 39497f18414SEric Lapuyade 39597f18414SEric Lapuyade if ((im_protocols | tm_protocols) & NFC_PROTO_NFC_DEP_MASK) { 39697f18414SEric Lapuyade hdev->gb = nfc_get_local_general_bytes(hdev->ndev, 39797f18414SEric Lapuyade &hdev->gb_len); 39897f18414SEric Lapuyade pr_debug("generate local bytes %p", hdev->gb); 39997f18414SEric Lapuyade if (hdev->gb == NULL || hdev->gb_len == 0) { 40097f18414SEric Lapuyade im_protocols &= ~NFC_PROTO_NFC_DEP_MASK; 40197f18414SEric Lapuyade tm_protocols &= ~NFC_PROTO_NFC_DEP_MASK; 40297f18414SEric Lapuyade } 40397f18414SEric Lapuyade } 40497f18414SEric Lapuyade 40597f18414SEric Lapuyade if (im_protocols & NFC_PROTO_NFC_DEP_MASK) { 40697f18414SEric Lapuyade r = nfc_hci_send_event(hdev, 40797f18414SEric Lapuyade PN544_RF_READER_NFCIP1_INITIATOR_GATE, 40897f18414SEric Lapuyade NFC_HCI_EVT_END_OPERATION, NULL, 0); 40997f18414SEric Lapuyade if (r < 0) 41097f18414SEric Lapuyade return r; 41197f18414SEric Lapuyade 41297f18414SEric Lapuyade r = nfc_hci_set_param(hdev, 41397f18414SEric Lapuyade PN544_RF_READER_NFCIP1_INITIATOR_GATE, 41497f18414SEric Lapuyade PN544_DEP_MODE, &i_mode, 1); 41597f18414SEric Lapuyade if (r < 0) 41697f18414SEric Lapuyade return r; 41797f18414SEric Lapuyade 41897f18414SEric Lapuyade r = nfc_hci_set_param(hdev, 41997f18414SEric Lapuyade PN544_RF_READER_NFCIP1_INITIATOR_GATE, 42097f18414SEric Lapuyade PN544_DEP_ATR_REQ, hdev->gb, hdev->gb_len); 42197f18414SEric Lapuyade if (r < 0) 42297f18414SEric Lapuyade return r; 42397f18414SEric Lapuyade 42497f18414SEric Lapuyade r = nfc_hci_send_event(hdev, 42597f18414SEric Lapuyade PN544_RF_READER_NFCIP1_INITIATOR_GATE, 42697f18414SEric Lapuyade NFC_HCI_EVT_READER_REQUESTED, NULL, 0); 42797f18414SEric Lapuyade if (r < 0) 42897f18414SEric Lapuyade nfc_hci_send_event(hdev, 42997f18414SEric Lapuyade PN544_RF_READER_NFCIP1_INITIATOR_GATE, 43097f18414SEric Lapuyade NFC_HCI_EVT_END_OPERATION, NULL, 0); 43197f18414SEric Lapuyade } 43297f18414SEric Lapuyade 43397f18414SEric Lapuyade if (tm_protocols & NFC_PROTO_NFC_DEP_MASK) { 43497f18414SEric Lapuyade r = nfc_hci_set_param(hdev, PN544_RF_READER_NFCIP1_TARGET_GATE, 43597f18414SEric Lapuyade PN544_DEP_MODE, &t_mode, 1); 43697f18414SEric Lapuyade if (r < 0) 43797f18414SEric Lapuyade return r; 43897f18414SEric Lapuyade 43997f18414SEric Lapuyade r = nfc_hci_set_param(hdev, PN544_RF_READER_NFCIP1_TARGET_GATE, 44097f18414SEric Lapuyade PN544_DEP_ATR_RES, hdev->gb, hdev->gb_len); 44197f18414SEric Lapuyade if (r < 0) 44297f18414SEric Lapuyade return r; 44397f18414SEric Lapuyade 44497f18414SEric Lapuyade r = nfc_hci_set_param(hdev, PN544_RF_READER_NFCIP1_TARGET_GATE, 44597f18414SEric Lapuyade PN544_DEP_MERGE, &t_merge, 1); 44697f18414SEric Lapuyade if (r < 0) 44797f18414SEric Lapuyade return r; 44897f18414SEric Lapuyade } 44997f18414SEric Lapuyade 45097f18414SEric Lapuyade r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, 45197f18414SEric Lapuyade NFC_HCI_EVT_READER_REQUESTED, NULL, 0); 45297f18414SEric Lapuyade if (r < 0) 45397f18414SEric Lapuyade nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, 45497f18414SEric Lapuyade NFC_HCI_EVT_END_OPERATION, NULL, 0); 45597f18414SEric Lapuyade 45697f18414SEric Lapuyade return r; 45797f18414SEric Lapuyade } 45897f18414SEric Lapuyade 45997f18414SEric Lapuyade static int pn544_hci_dep_link_up(struct nfc_hci_dev *hdev, 46097f18414SEric Lapuyade struct nfc_target *target, u8 comm_mode, 46197f18414SEric Lapuyade u8 *gb, size_t gb_len) 46297f18414SEric Lapuyade { 46397f18414SEric Lapuyade struct sk_buff *rgb_skb = NULL; 46497f18414SEric Lapuyade int r; 46597f18414SEric Lapuyade 46697f18414SEric Lapuyade r = nfc_hci_get_param(hdev, target->hci_reader_gate, 46797f18414SEric Lapuyade PN544_DEP_ATR_RES, &rgb_skb); 46897f18414SEric Lapuyade if (r < 0) 46997f18414SEric Lapuyade return r; 47097f18414SEric Lapuyade 47197f18414SEric Lapuyade if (rgb_skb->len == 0 || rgb_skb->len > NFC_GB_MAXSIZE) { 47297f18414SEric Lapuyade r = -EPROTO; 47397f18414SEric Lapuyade goto exit; 47497f18414SEric Lapuyade } 47597f18414SEric Lapuyade print_hex_dump(KERN_DEBUG, "remote gb: ", DUMP_PREFIX_OFFSET, 47697f18414SEric Lapuyade 16, 1, rgb_skb->data, rgb_skb->len, true); 47797f18414SEric Lapuyade 47897f18414SEric Lapuyade r = nfc_set_remote_general_bytes(hdev->ndev, rgb_skb->data, 47997f18414SEric Lapuyade rgb_skb->len); 48097f18414SEric Lapuyade 48197f18414SEric Lapuyade if (r == 0) 48297f18414SEric Lapuyade r = nfc_dep_link_is_up(hdev->ndev, target->idx, comm_mode, 48397f18414SEric Lapuyade NFC_RF_INITIATOR); 48497f18414SEric Lapuyade exit: 48597f18414SEric Lapuyade kfree_skb(rgb_skb); 48697f18414SEric Lapuyade return r; 48797f18414SEric Lapuyade } 48897f18414SEric Lapuyade 48997f18414SEric Lapuyade static int pn544_hci_dep_link_down(struct nfc_hci_dev *hdev) 49097f18414SEric Lapuyade { 49197f18414SEric Lapuyade 49297f18414SEric Lapuyade return nfc_hci_send_event(hdev, PN544_RF_READER_NFCIP1_INITIATOR_GATE, 49397f18414SEric Lapuyade NFC_HCI_EVT_END_OPERATION, NULL, 0); 49497f18414SEric Lapuyade } 49597f18414SEric Lapuyade 49697f18414SEric Lapuyade static int pn544_hci_target_from_gate(struct nfc_hci_dev *hdev, u8 gate, 49797f18414SEric Lapuyade struct nfc_target *target) 49897f18414SEric Lapuyade { 49997f18414SEric Lapuyade switch (gate) { 50097f18414SEric Lapuyade case PN544_RF_READER_F_GATE: 50197f18414SEric Lapuyade target->supported_protocols = NFC_PROTO_FELICA_MASK; 50297f18414SEric Lapuyade break; 50397f18414SEric Lapuyade case PN544_RF_READER_JEWEL_GATE: 50497f18414SEric Lapuyade target->supported_protocols = NFC_PROTO_JEWEL_MASK; 50597f18414SEric Lapuyade target->sens_res = 0x0c00; 50697f18414SEric Lapuyade break; 50797f18414SEric Lapuyade case PN544_RF_READER_NFCIP1_INITIATOR_GATE: 50897f18414SEric Lapuyade target->supported_protocols = NFC_PROTO_NFC_DEP_MASK; 50997f18414SEric Lapuyade break; 51097f18414SEric Lapuyade default: 51197f18414SEric Lapuyade return -EPROTO; 51297f18414SEric Lapuyade } 51397f18414SEric Lapuyade 51497f18414SEric Lapuyade return 0; 51597f18414SEric Lapuyade } 51697f18414SEric Lapuyade 51797f18414SEric Lapuyade static int pn544_hci_complete_target_discovered(struct nfc_hci_dev *hdev, 51897f18414SEric Lapuyade u8 gate, 51997f18414SEric Lapuyade struct nfc_target *target) 52097f18414SEric Lapuyade { 52197f18414SEric Lapuyade struct sk_buff *uid_skb; 52297f18414SEric Lapuyade int r = 0; 52397f18414SEric Lapuyade 52497f18414SEric Lapuyade if (gate == PN544_RF_READER_NFCIP1_INITIATOR_GATE) 52597f18414SEric Lapuyade return r; 52697f18414SEric Lapuyade 52797f18414SEric Lapuyade if (target->supported_protocols & NFC_PROTO_NFC_DEP_MASK) { 52897f18414SEric Lapuyade r = nfc_hci_send_cmd(hdev, 52997f18414SEric Lapuyade PN544_RF_READER_NFCIP1_INITIATOR_GATE, 53097f18414SEric Lapuyade PN544_HCI_CMD_CONTINUE_ACTIVATION, NULL, 0, NULL); 53197f18414SEric Lapuyade if (r < 0) 53297f18414SEric Lapuyade return r; 53397f18414SEric Lapuyade 53497f18414SEric Lapuyade target->hci_reader_gate = PN544_RF_READER_NFCIP1_INITIATOR_GATE; 53597f18414SEric Lapuyade } else if (target->supported_protocols & NFC_PROTO_MIFARE_MASK) { 53697f18414SEric Lapuyade if (target->nfcid1_len != 4 && target->nfcid1_len != 7 && 53797f18414SEric Lapuyade target->nfcid1_len != 10) 53897f18414SEric Lapuyade return -EPROTO; 53997f18414SEric Lapuyade 54097f18414SEric Lapuyade r = nfc_hci_send_cmd(hdev, NFC_HCI_RF_READER_A_GATE, 54197f18414SEric Lapuyade PN544_RF_READER_CMD_ACTIVATE_NEXT, 54297f18414SEric Lapuyade target->nfcid1, target->nfcid1_len, NULL); 54397f18414SEric Lapuyade } else if (target->supported_protocols & NFC_PROTO_FELICA_MASK) { 54497f18414SEric Lapuyade r = nfc_hci_get_param(hdev, PN544_RF_READER_F_GATE, 54597f18414SEric Lapuyade PN544_FELICA_ID, &uid_skb); 54697f18414SEric Lapuyade if (r < 0) 54797f18414SEric Lapuyade return r; 54897f18414SEric Lapuyade 54997f18414SEric Lapuyade if (uid_skb->len != 8) { 55097f18414SEric Lapuyade kfree_skb(uid_skb); 55197f18414SEric Lapuyade return -EPROTO; 55297f18414SEric Lapuyade } 55397f18414SEric Lapuyade 554*9c598440SArron Wang /* Type F NFC-DEP IDm has prefix 0x01FE */ 555*9c598440SArron Wang if ((uid_skb->data[0] == 0x01) && (uid_skb->data[1] == 0xfe)) { 55697f18414SEric Lapuyade kfree_skb(uid_skb); 55797f18414SEric Lapuyade r = nfc_hci_send_cmd(hdev, 55897f18414SEric Lapuyade PN544_RF_READER_NFCIP1_INITIATOR_GATE, 55997f18414SEric Lapuyade PN544_HCI_CMD_CONTINUE_ACTIVATION, 56097f18414SEric Lapuyade NULL, 0, NULL); 56197f18414SEric Lapuyade if (r < 0) 56297f18414SEric Lapuyade return r; 56397f18414SEric Lapuyade 56497f18414SEric Lapuyade target->supported_protocols = NFC_PROTO_NFC_DEP_MASK; 565*9c598440SArron Wang target->hci_reader_gate = 566*9c598440SArron Wang PN544_RF_READER_NFCIP1_INITIATOR_GATE; 567*9c598440SArron Wang } else { 568*9c598440SArron Wang r = nfc_hci_send_cmd(hdev, PN544_RF_READER_F_GATE, 569*9c598440SArron Wang PN544_RF_READER_CMD_ACTIVATE_NEXT, 570*9c598440SArron Wang uid_skb->data, uid_skb->len, NULL); 571*9c598440SArron Wang kfree_skb(uid_skb); 572*9c598440SArron Wang } 57397f18414SEric Lapuyade } else if (target->supported_protocols & NFC_PROTO_ISO14443_MASK) { 57497f18414SEric Lapuyade /* 57597f18414SEric Lapuyade * TODO: maybe other ISO 14443 require some kind of continue 57697f18414SEric Lapuyade * activation, but for now we've seen only this one below. 57797f18414SEric Lapuyade */ 57897f18414SEric Lapuyade if (target->sens_res == 0x4403) /* Type 4 Mifare DESFire */ 57997f18414SEric Lapuyade r = nfc_hci_send_cmd(hdev, NFC_HCI_RF_READER_A_GATE, 58097f18414SEric Lapuyade PN544_RF_READER_A_CMD_CONTINUE_ACTIVATION, 58197f18414SEric Lapuyade NULL, 0, NULL); 58297f18414SEric Lapuyade } 58397f18414SEric Lapuyade 58497f18414SEric Lapuyade return r; 58597f18414SEric Lapuyade } 58697f18414SEric Lapuyade 58797f18414SEric Lapuyade #define PN544_CB_TYPE_READER_F 1 58897f18414SEric Lapuyade 58997f18414SEric Lapuyade static void pn544_hci_data_exchange_cb(void *context, struct sk_buff *skb, 59097f18414SEric Lapuyade int err) 59197f18414SEric Lapuyade { 59297f18414SEric Lapuyade struct pn544_hci_info *info = context; 59397f18414SEric Lapuyade 59497f18414SEric Lapuyade switch (info->async_cb_type) { 59597f18414SEric Lapuyade case PN544_CB_TYPE_READER_F: 59697f18414SEric Lapuyade if (err == 0) 59797f18414SEric Lapuyade skb_pull(skb, 1); 59897f18414SEric Lapuyade info->async_cb(info->async_cb_context, skb, err); 59997f18414SEric Lapuyade break; 60097f18414SEric Lapuyade default: 60197f18414SEric Lapuyade if (err == 0) 60297f18414SEric Lapuyade kfree_skb(skb); 60397f18414SEric Lapuyade break; 60497f18414SEric Lapuyade } 60597f18414SEric Lapuyade } 60697f18414SEric Lapuyade 60797f18414SEric Lapuyade #define MIFARE_CMD_AUTH_KEY_A 0x60 60897f18414SEric Lapuyade #define MIFARE_CMD_AUTH_KEY_B 0x61 60997f18414SEric Lapuyade #define MIFARE_CMD_HEADER 2 61097f18414SEric Lapuyade #define MIFARE_UID_LEN 4 61197f18414SEric Lapuyade #define MIFARE_KEY_LEN 6 61297f18414SEric Lapuyade #define MIFARE_CMD_LEN 12 61397f18414SEric Lapuyade /* 61497f18414SEric Lapuyade * Returns: 61597f18414SEric Lapuyade * <= 0: driver handled the data exchange 61697f18414SEric Lapuyade * 1: driver doesn't especially handle, please do standard processing 61797f18414SEric Lapuyade */ 61897f18414SEric Lapuyade static int pn544_hci_im_transceive(struct nfc_hci_dev *hdev, 61997f18414SEric Lapuyade struct nfc_target *target, 62097f18414SEric Lapuyade struct sk_buff *skb, data_exchange_cb_t cb, 62197f18414SEric Lapuyade void *cb_context) 62297f18414SEric Lapuyade { 62397f18414SEric Lapuyade struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev); 62497f18414SEric Lapuyade 62597f18414SEric Lapuyade pr_info(DRIVER_DESC ": %s for gate=%d\n", __func__, 62697f18414SEric Lapuyade target->hci_reader_gate); 62797f18414SEric Lapuyade 62897f18414SEric Lapuyade switch (target->hci_reader_gate) { 62997f18414SEric Lapuyade case NFC_HCI_RF_READER_A_GATE: 63097f18414SEric Lapuyade if (target->supported_protocols & NFC_PROTO_MIFARE_MASK) { 63197f18414SEric Lapuyade /* 63297f18414SEric Lapuyade * It seems that pn544 is inverting key and UID for 63397f18414SEric Lapuyade * MIFARE authentication commands. 63497f18414SEric Lapuyade */ 63597f18414SEric Lapuyade if (skb->len == MIFARE_CMD_LEN && 63697f18414SEric Lapuyade (skb->data[0] == MIFARE_CMD_AUTH_KEY_A || 63797f18414SEric Lapuyade skb->data[0] == MIFARE_CMD_AUTH_KEY_B)) { 63897f18414SEric Lapuyade u8 uid[MIFARE_UID_LEN]; 63997f18414SEric Lapuyade u8 *data = skb->data + MIFARE_CMD_HEADER; 64097f18414SEric Lapuyade 64197f18414SEric Lapuyade memcpy(uid, data + MIFARE_KEY_LEN, 64297f18414SEric Lapuyade MIFARE_UID_LEN); 64397f18414SEric Lapuyade memmove(data + MIFARE_UID_LEN, data, 64497f18414SEric Lapuyade MIFARE_KEY_LEN); 64597f18414SEric Lapuyade memcpy(data, uid, MIFARE_UID_LEN); 64697f18414SEric Lapuyade } 64797f18414SEric Lapuyade 64897f18414SEric Lapuyade return nfc_hci_send_cmd_async(hdev, 64997f18414SEric Lapuyade target->hci_reader_gate, 65097f18414SEric Lapuyade PN544_MIFARE_CMD, 65197f18414SEric Lapuyade skb->data, skb->len, 65297f18414SEric Lapuyade cb, cb_context); 65397f18414SEric Lapuyade } else 65497f18414SEric Lapuyade return 1; 65597f18414SEric Lapuyade case PN544_RF_READER_F_GATE: 65697f18414SEric Lapuyade *skb_push(skb, 1) = 0; 65797f18414SEric Lapuyade *skb_push(skb, 1) = 0; 65897f18414SEric Lapuyade 65997f18414SEric Lapuyade info->async_cb_type = PN544_CB_TYPE_READER_F; 66097f18414SEric Lapuyade info->async_cb = cb; 66197f18414SEric Lapuyade info->async_cb_context = cb_context; 66297f18414SEric Lapuyade 66397f18414SEric Lapuyade return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate, 66497f18414SEric Lapuyade PN544_FELICA_RAW, skb->data, 66597f18414SEric Lapuyade skb->len, 66697f18414SEric Lapuyade pn544_hci_data_exchange_cb, info); 66797f18414SEric Lapuyade case PN544_RF_READER_JEWEL_GATE: 66897f18414SEric Lapuyade return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate, 66997f18414SEric Lapuyade PN544_JEWEL_RAW_CMD, skb->data, 67097f18414SEric Lapuyade skb->len, cb, cb_context); 67197f18414SEric Lapuyade case PN544_RF_READER_NFCIP1_INITIATOR_GATE: 67297f18414SEric Lapuyade *skb_push(skb, 1) = 0; 67397f18414SEric Lapuyade 67497f18414SEric Lapuyade return nfc_hci_send_event(hdev, target->hci_reader_gate, 67597f18414SEric Lapuyade PN544_HCI_EVT_SND_DATA, skb->data, 67697f18414SEric Lapuyade skb->len); 67797f18414SEric Lapuyade default: 67897f18414SEric Lapuyade return 1; 67997f18414SEric Lapuyade } 68097f18414SEric Lapuyade } 68197f18414SEric Lapuyade 68297f18414SEric Lapuyade static int pn544_hci_tm_send(struct nfc_hci_dev *hdev, struct sk_buff *skb) 68397f18414SEric Lapuyade { 684924d4a02SEric Lapuyade int r; 685924d4a02SEric Lapuyade 68697f18414SEric Lapuyade /* Set default false for multiple information chaining */ 68797f18414SEric Lapuyade *skb_push(skb, 1) = 0; 68897f18414SEric Lapuyade 689924d4a02SEric Lapuyade r = nfc_hci_send_event(hdev, PN544_RF_READER_NFCIP1_TARGET_GATE, 69097f18414SEric Lapuyade PN544_HCI_EVT_SND_DATA, skb->data, skb->len); 691924d4a02SEric Lapuyade 692924d4a02SEric Lapuyade kfree_skb(skb); 693924d4a02SEric Lapuyade 694924d4a02SEric Lapuyade return r; 69597f18414SEric Lapuyade } 69697f18414SEric Lapuyade 69797f18414SEric Lapuyade static int pn544_hci_check_presence(struct nfc_hci_dev *hdev, 69897f18414SEric Lapuyade struct nfc_target *target) 69997f18414SEric Lapuyade { 70097f18414SEric Lapuyade pr_debug("supported protocol %d", target->supported_protocols); 70197f18414SEric Lapuyade if (target->supported_protocols & (NFC_PROTO_ISO14443_MASK | 70297f18414SEric Lapuyade NFC_PROTO_ISO14443_B_MASK)) { 70397f18414SEric Lapuyade return nfc_hci_send_cmd(hdev, target->hci_reader_gate, 70497f18414SEric Lapuyade PN544_RF_READER_CMD_PRESENCE_CHECK, 70597f18414SEric Lapuyade NULL, 0, NULL); 70697f18414SEric Lapuyade } else if (target->supported_protocols & NFC_PROTO_MIFARE_MASK) { 70797f18414SEric Lapuyade if (target->nfcid1_len != 4 && target->nfcid1_len != 7 && 70897f18414SEric Lapuyade target->nfcid1_len != 10) 70997f18414SEric Lapuyade return -EOPNOTSUPP; 71097f18414SEric Lapuyade 71197f18414SEric Lapuyade return nfc_hci_send_cmd(hdev, NFC_HCI_RF_READER_A_GATE, 71297f18414SEric Lapuyade PN544_RF_READER_CMD_ACTIVATE_NEXT, 71397f18414SEric Lapuyade target->nfcid1, target->nfcid1_len, NULL); 71497f18414SEric Lapuyade } else if (target->supported_protocols & NFC_PROTO_JEWEL_MASK) { 71597f18414SEric Lapuyade return nfc_hci_send_cmd(hdev, target->hci_reader_gate, 71697f18414SEric Lapuyade PN544_JEWEL_RAW_CMD, NULL, 0, NULL); 71797f18414SEric Lapuyade } else if (target->supported_protocols & NFC_PROTO_FELICA_MASK) { 71897f18414SEric Lapuyade return nfc_hci_send_cmd(hdev, PN544_RF_READER_F_GATE, 71997f18414SEric Lapuyade PN544_FELICA_RAW, NULL, 0, NULL); 72097f18414SEric Lapuyade } else if (target->supported_protocols & NFC_PROTO_NFC_DEP_MASK) { 72197f18414SEric Lapuyade return nfc_hci_send_cmd(hdev, target->hci_reader_gate, 72297f18414SEric Lapuyade PN544_HCI_CMD_ATTREQUEST, 72397f18414SEric Lapuyade NULL, 0, NULL); 72497f18414SEric Lapuyade } 72597f18414SEric Lapuyade 72697f18414SEric Lapuyade return 0; 72797f18414SEric Lapuyade } 72897f18414SEric Lapuyade 72940d06d36SEric Lapuyade /* 73040d06d36SEric Lapuyade * Returns: 73140d06d36SEric Lapuyade * <= 0: driver handled the event, skb consumed 73240d06d36SEric Lapuyade * 1: driver does not handle the event, please do standard processing 73340d06d36SEric Lapuyade */ 73427c31191SEric Lapuyade static int pn544_hci_event_received(struct nfc_hci_dev *hdev, u8 gate, u8 event, 73527c31191SEric Lapuyade struct sk_buff *skb) 73697f18414SEric Lapuyade { 73797f18414SEric Lapuyade struct sk_buff *rgb_skb = NULL; 73840d06d36SEric Lapuyade int r; 73997f18414SEric Lapuyade 74097f18414SEric Lapuyade pr_debug("hci event %d", event); 74197f18414SEric Lapuyade switch (event) { 74297f18414SEric Lapuyade case PN544_HCI_EVT_ACTIVATED: 74340d06d36SEric Lapuyade if (gate == PN544_RF_READER_NFCIP1_INITIATOR_GATE) { 74427c31191SEric Lapuyade r = nfc_hci_target_discovered(hdev, gate); 74540d06d36SEric Lapuyade } else if (gate == PN544_RF_READER_NFCIP1_TARGET_GATE) { 74697f18414SEric Lapuyade r = nfc_hci_get_param(hdev, gate, PN544_DEP_ATR_REQ, 74797f18414SEric Lapuyade &rgb_skb); 74897f18414SEric Lapuyade if (r < 0) 74997f18414SEric Lapuyade goto exit; 75097f18414SEric Lapuyade 75127c31191SEric Lapuyade r = nfc_tm_activated(hdev->ndev, NFC_PROTO_NFC_DEP_MASK, 75297f18414SEric Lapuyade NFC_COMM_PASSIVE, rgb_skb->data, 75397f18414SEric Lapuyade rgb_skb->len); 75497f18414SEric Lapuyade 75597f18414SEric Lapuyade kfree_skb(rgb_skb); 75640d06d36SEric Lapuyade } else { 75740d06d36SEric Lapuyade r = -EINVAL; 75897f18414SEric Lapuyade } 75997f18414SEric Lapuyade break; 76097f18414SEric Lapuyade case PN544_HCI_EVT_DEACTIVATED: 76127c31191SEric Lapuyade r = nfc_hci_send_event(hdev, gate, NFC_HCI_EVT_END_OPERATION, 76227c31191SEric Lapuyade NULL, 0); 76397f18414SEric Lapuyade break; 76497f18414SEric Lapuyade case PN544_HCI_EVT_RCV_DATA: 76597f18414SEric Lapuyade if (skb->len < 2) { 76697f18414SEric Lapuyade r = -EPROTO; 76797f18414SEric Lapuyade goto exit; 76897f18414SEric Lapuyade } 76997f18414SEric Lapuyade 77097f18414SEric Lapuyade if (skb->data[0] != 0) { 77197f18414SEric Lapuyade pr_debug("data0 %d", skb->data[0]); 77297f18414SEric Lapuyade r = -EPROTO; 77397f18414SEric Lapuyade goto exit; 77497f18414SEric Lapuyade } 77597f18414SEric Lapuyade 77697f18414SEric Lapuyade skb_pull(skb, 2); 77727c31191SEric Lapuyade return nfc_tm_data_received(hdev->ndev, skb); 77897f18414SEric Lapuyade default: 77940d06d36SEric Lapuyade return 1; 78097f18414SEric Lapuyade } 78197f18414SEric Lapuyade 78297f18414SEric Lapuyade exit: 78397f18414SEric Lapuyade kfree_skb(skb); 78427c31191SEric Lapuyade 78527c31191SEric Lapuyade return r; 78697f18414SEric Lapuyade } 78797f18414SEric Lapuyade 78897f18414SEric Lapuyade static struct nfc_hci_ops pn544_hci_ops = { 78997f18414SEric Lapuyade .open = pn544_hci_open, 79097f18414SEric Lapuyade .close = pn544_hci_close, 79197f18414SEric Lapuyade .hci_ready = pn544_hci_ready, 79297f18414SEric Lapuyade .xmit = pn544_hci_xmit, 79397f18414SEric Lapuyade .start_poll = pn544_hci_start_poll, 79497f18414SEric Lapuyade .dep_link_up = pn544_hci_dep_link_up, 79597f18414SEric Lapuyade .dep_link_down = pn544_hci_dep_link_down, 79697f18414SEric Lapuyade .target_from_gate = pn544_hci_target_from_gate, 79797f18414SEric Lapuyade .complete_target_discovered = pn544_hci_complete_target_discovered, 79897f18414SEric Lapuyade .im_transceive = pn544_hci_im_transceive, 79997f18414SEric Lapuyade .tm_send = pn544_hci_tm_send, 80097f18414SEric Lapuyade .check_presence = pn544_hci_check_presence, 80197f18414SEric Lapuyade .event_received = pn544_hci_event_received, 80297f18414SEric Lapuyade }; 80397f18414SEric Lapuyade 80497f18414SEric Lapuyade int pn544_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name, 80597f18414SEric Lapuyade int phy_headroom, int phy_tailroom, int phy_payload, 80697f18414SEric Lapuyade struct nfc_hci_dev **hdev) 80797f18414SEric Lapuyade { 80897f18414SEric Lapuyade struct pn544_hci_info *info; 809390a1bd8SSamuel Ortiz u32 protocols, se; 81097f18414SEric Lapuyade struct nfc_hci_init_data init_data; 81197f18414SEric Lapuyade int r; 81297f18414SEric Lapuyade 81397f18414SEric Lapuyade info = kzalloc(sizeof(struct pn544_hci_info), GFP_KERNEL); 81497f18414SEric Lapuyade if (!info) { 81597f18414SEric Lapuyade pr_err("Cannot allocate memory for pn544_hci_info.\n"); 81697f18414SEric Lapuyade r = -ENOMEM; 81797f18414SEric Lapuyade goto err_info_alloc; 81897f18414SEric Lapuyade } 81997f18414SEric Lapuyade 82097f18414SEric Lapuyade info->phy_ops = phy_ops; 82197f18414SEric Lapuyade info->phy_id = phy_id; 82297f18414SEric Lapuyade info->state = PN544_ST_COLD; 82397f18414SEric Lapuyade mutex_init(&info->info_lock); 82497f18414SEric Lapuyade 82597f18414SEric Lapuyade init_data.gate_count = ARRAY_SIZE(pn544_gates); 82697f18414SEric Lapuyade 82797f18414SEric Lapuyade memcpy(init_data.gates, pn544_gates, sizeof(pn544_gates)); 82897f18414SEric Lapuyade 82997f18414SEric Lapuyade /* 83097f18414SEric Lapuyade * TODO: Session id must include the driver name + some bus addr 83197f18414SEric Lapuyade * persistent info to discriminate 2 identical chips 83297f18414SEric Lapuyade */ 83397f18414SEric Lapuyade strcpy(init_data.session_id, "ID544HCI"); 83497f18414SEric Lapuyade 83597f18414SEric Lapuyade protocols = NFC_PROTO_JEWEL_MASK | 83697f18414SEric Lapuyade NFC_PROTO_MIFARE_MASK | 83797f18414SEric Lapuyade NFC_PROTO_FELICA_MASK | 83897f18414SEric Lapuyade NFC_PROTO_ISO14443_MASK | 83997f18414SEric Lapuyade NFC_PROTO_ISO14443_B_MASK | 84097f18414SEric Lapuyade NFC_PROTO_NFC_DEP_MASK; 84197f18414SEric Lapuyade 842390a1bd8SSamuel Ortiz se = NFC_SE_UICC | NFC_SE_EMBEDDED; 843390a1bd8SSamuel Ortiz 844bf71ab8bSEric Lapuyade info->hdev = nfc_hci_allocate_device(&pn544_hci_ops, &init_data, 0, 845390a1bd8SSamuel Ortiz protocols, se, llc_name, 84697f18414SEric Lapuyade phy_headroom + PN544_CMDS_HEADROOM, 84797f18414SEric Lapuyade phy_tailroom, phy_payload); 84897f18414SEric Lapuyade if (!info->hdev) { 84997f18414SEric Lapuyade pr_err("Cannot allocate nfc hdev.\n"); 85097f18414SEric Lapuyade r = -ENOMEM; 85197f18414SEric Lapuyade goto err_alloc_hdev; 85297f18414SEric Lapuyade } 85397f18414SEric Lapuyade 85497f18414SEric Lapuyade nfc_hci_set_clientdata(info->hdev, info); 85597f18414SEric Lapuyade 85697f18414SEric Lapuyade r = nfc_hci_register_device(info->hdev); 85797f18414SEric Lapuyade if (r) 85897f18414SEric Lapuyade goto err_regdev; 85997f18414SEric Lapuyade 86097f18414SEric Lapuyade *hdev = info->hdev; 86197f18414SEric Lapuyade 86297f18414SEric Lapuyade return 0; 86397f18414SEric Lapuyade 86497f18414SEric Lapuyade err_regdev: 86597f18414SEric Lapuyade nfc_hci_free_device(info->hdev); 86697f18414SEric Lapuyade 86797f18414SEric Lapuyade err_alloc_hdev: 86897f18414SEric Lapuyade kfree(info); 86997f18414SEric Lapuyade 87097f18414SEric Lapuyade err_info_alloc: 87197f18414SEric Lapuyade return r; 87297f18414SEric Lapuyade } 873aa741030SSamuel Ortiz EXPORT_SYMBOL(pn544_hci_probe); 87497f18414SEric Lapuyade 87597f18414SEric Lapuyade void pn544_hci_remove(struct nfc_hci_dev *hdev) 87697f18414SEric Lapuyade { 87797f18414SEric Lapuyade struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev); 87897f18414SEric Lapuyade 87997f18414SEric Lapuyade nfc_hci_unregister_device(hdev); 88097f18414SEric Lapuyade nfc_hci_free_device(hdev); 88197f18414SEric Lapuyade kfree(info); 88297f18414SEric Lapuyade } 883aa741030SSamuel Ortiz EXPORT_SYMBOL(pn544_hci_remove); 884aa741030SSamuel Ortiz 885aa741030SSamuel Ortiz MODULE_LICENSE("GPL"); 886aa741030SSamuel Ortiz MODULE_DESCRIPTION(DRIVER_DESC); 887