162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * HCI based Driver for STMicroelectronics NFC Chip 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/module.h> 962306a36Sopenharmony_ci#include <linux/nfc.h> 1062306a36Sopenharmony_ci#include <net/nfc/hci.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include "st21nfca.h" 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#define DRIVER_DESC "HCI NFC driver for ST21NFCA" 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#define FULL_VERSION_LEN 3 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci/* Proprietary gates, events, commands and registers */ 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci/* Commands that apply to all RF readers */ 2162306a36Sopenharmony_ci#define ST21NFCA_RF_READER_CMD_PRESENCE_CHECK 0x30 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#define ST21NFCA_RF_READER_ISO15693_GATE 0x12 2462306a36Sopenharmony_ci#define ST21NFCA_RF_READER_ISO15693_INVENTORY 0x01 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci/* 2762306a36Sopenharmony_ci * Reader gate for communication with contact-less cards using Type A 2862306a36Sopenharmony_ci * protocol ISO14443-3 but not compliant with ISO14443-4 2962306a36Sopenharmony_ci */ 3062306a36Sopenharmony_ci#define ST21NFCA_RF_READER_14443_3_A_GATE 0x15 3162306a36Sopenharmony_ci#define ST21NFCA_RF_READER_14443_3_A_UID 0x02 3262306a36Sopenharmony_ci#define ST21NFCA_RF_READER_14443_3_A_ATQA 0x03 3362306a36Sopenharmony_ci#define ST21NFCA_RF_READER_14443_3_A_SAK 0x04 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#define ST21NFCA_RF_READER_F_DATARATE 0x01 3662306a36Sopenharmony_ci#define ST21NFCA_RF_READER_F_DATARATE_106 0x01 3762306a36Sopenharmony_ci#define ST21NFCA_RF_READER_F_DATARATE_212 0x02 3862306a36Sopenharmony_ci#define ST21NFCA_RF_READER_F_DATARATE_424 0x04 3962306a36Sopenharmony_ci#define ST21NFCA_RF_READER_F_POL_REQ 0x02 4062306a36Sopenharmony_ci#define ST21NFCA_RF_READER_F_POL_REQ_DEFAULT 0xffff0000 4162306a36Sopenharmony_ci#define ST21NFCA_RF_READER_F_NFCID2 0x03 4262306a36Sopenharmony_ci#define ST21NFCA_RF_READER_F_NFCID1 0x04 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci#define ST21NFCA_RF_CARD_F_MODE 0x01 4562306a36Sopenharmony_ci#define ST21NFCA_RF_CARD_F_NFCID2_LIST 0x04 4662306a36Sopenharmony_ci#define ST21NFCA_RF_CARD_F_NFCID1 0x05 4762306a36Sopenharmony_ci#define ST21NFCA_RF_CARD_F_SENS_RES 0x06 4862306a36Sopenharmony_ci#define ST21NFCA_RF_CARD_F_SEL_RES 0x07 4962306a36Sopenharmony_ci#define ST21NFCA_RF_CARD_F_DATARATE 0x08 5062306a36Sopenharmony_ci#define ST21NFCA_RF_CARD_F_DATARATE_212_424 0x01 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci#define ST21NFCA_DEVICE_MGNT_PIPE 0x02 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci#define ST21NFCA_DM_GETINFO 0x13 5562306a36Sopenharmony_ci#define ST21NFCA_DM_GETINFO_PIPE_LIST 0x02 5662306a36Sopenharmony_ci#define ST21NFCA_DM_GETINFO_PIPE_INFO 0x01 5762306a36Sopenharmony_ci#define ST21NFCA_DM_PIPE_CREATED 0x02 5862306a36Sopenharmony_ci#define ST21NFCA_DM_PIPE_OPEN 0x04 5962306a36Sopenharmony_ci#define ST21NFCA_DM_RF_ACTIVE 0x80 6062306a36Sopenharmony_ci#define ST21NFCA_DM_DISCONNECT 0x30 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci#define ST21NFCA_DM_IS_PIPE_OPEN(p) \ 6362306a36Sopenharmony_ci ((p & 0x0f) == (ST21NFCA_DM_PIPE_CREATED | ST21NFCA_DM_PIPE_OPEN)) 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci#define ST21NFCA_NFC_MODE 0x03 /* NFC_MODE parameter*/ 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci#define ST21NFCA_EVT_HOT_PLUG 0x03 6862306a36Sopenharmony_ci#define ST21NFCA_EVT_HOT_PLUG_IS_INHIBITED(x) (x->data[0] & 0x80) 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci#define ST21NFCA_SE_TO_PIPES 2000 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_cistatic DECLARE_BITMAP(dev_mask, ST21NFCA_NUM_DEVICES); 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_cistatic const struct nfc_hci_gate st21nfca_gates[] = { 7562306a36Sopenharmony_ci {NFC_HCI_ADMIN_GATE, NFC_HCI_ADMIN_PIPE}, 7662306a36Sopenharmony_ci {NFC_HCI_LINK_MGMT_GATE, NFC_HCI_LINK_MGMT_PIPE}, 7762306a36Sopenharmony_ci {ST21NFCA_DEVICE_MGNT_GATE, ST21NFCA_DEVICE_MGNT_PIPE}, 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci {NFC_HCI_LOOPBACK_GATE, NFC_HCI_INVALID_PIPE}, 8062306a36Sopenharmony_ci {NFC_HCI_ID_MGMT_GATE, NFC_HCI_INVALID_PIPE}, 8162306a36Sopenharmony_ci {NFC_HCI_RF_READER_B_GATE, NFC_HCI_INVALID_PIPE}, 8262306a36Sopenharmony_ci {NFC_HCI_RF_READER_A_GATE, NFC_HCI_INVALID_PIPE}, 8362306a36Sopenharmony_ci {ST21NFCA_RF_READER_F_GATE, NFC_HCI_INVALID_PIPE}, 8462306a36Sopenharmony_ci {ST21NFCA_RF_READER_14443_3_A_GATE, NFC_HCI_INVALID_PIPE}, 8562306a36Sopenharmony_ci {ST21NFCA_RF_READER_ISO15693_GATE, NFC_HCI_INVALID_PIPE}, 8662306a36Sopenharmony_ci {ST21NFCA_RF_CARD_F_GATE, NFC_HCI_INVALID_PIPE}, 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci /* Secure element pipes are created by secure element host */ 8962306a36Sopenharmony_ci {ST21NFCA_CONNECTIVITY_GATE, NFC_HCI_DO_NOT_CREATE_PIPE}, 9062306a36Sopenharmony_ci {ST21NFCA_APDU_READER_GATE, NFC_HCI_DO_NOT_CREATE_PIPE}, 9162306a36Sopenharmony_ci}; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_cistruct st21nfca_pipe_info { 9462306a36Sopenharmony_ci u8 pipe_state; 9562306a36Sopenharmony_ci u8 src_host_id; 9662306a36Sopenharmony_ci u8 src_gate_id; 9762306a36Sopenharmony_ci u8 dst_host_id; 9862306a36Sopenharmony_ci u8 dst_gate_id; 9962306a36Sopenharmony_ci} __packed; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci/* Largest headroom needed for outgoing custom commands */ 10262306a36Sopenharmony_ci#define ST21NFCA_CMDS_HEADROOM 7 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_cistatic int st21nfca_hci_load_session(struct nfc_hci_dev *hdev) 10562306a36Sopenharmony_ci{ 10662306a36Sopenharmony_ci int i, j, r; 10762306a36Sopenharmony_ci struct sk_buff *skb_pipe_list, *skb_pipe_info; 10862306a36Sopenharmony_ci struct st21nfca_pipe_info *info; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci u8 pipe_list[] = { ST21NFCA_DM_GETINFO_PIPE_LIST, 11162306a36Sopenharmony_ci NFC_HCI_TERMINAL_HOST_ID 11262306a36Sopenharmony_ci }; 11362306a36Sopenharmony_ci u8 pipe_info[] = { ST21NFCA_DM_GETINFO_PIPE_INFO, 11462306a36Sopenharmony_ci NFC_HCI_TERMINAL_HOST_ID, 0 11562306a36Sopenharmony_ci }; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci /* On ST21NFCA device pipes number are dynamics 11862306a36Sopenharmony_ci * A maximum of 16 pipes can be created at the same time 11962306a36Sopenharmony_ci * If pipes are already created, hci_dev_up will fail. 12062306a36Sopenharmony_ci * Doing a clear all pipe is a bad idea because: 12162306a36Sopenharmony_ci * - It does useless EEPROM cycling 12262306a36Sopenharmony_ci * - It might cause issue for secure elements support 12362306a36Sopenharmony_ci * (such as removing connectivity or APDU reader pipe) 12462306a36Sopenharmony_ci * A better approach on ST21NFCA is to: 12562306a36Sopenharmony_ci * - get a pipe list for each host. 12662306a36Sopenharmony_ci * (eg: NFC_HCI_HOST_CONTROLLER_ID for now). 12762306a36Sopenharmony_ci * (TODO Later on UICC HOST and eSE HOST) 12862306a36Sopenharmony_ci * - get pipe information 12962306a36Sopenharmony_ci * - match retrieved pipe list in st21nfca_gates 13062306a36Sopenharmony_ci * ST21NFCA_DEVICE_MGNT_GATE is a proprietary gate 13162306a36Sopenharmony_ci * with ST21NFCA_DEVICE_MGNT_PIPE. 13262306a36Sopenharmony_ci * Pipe can be closed and need to be open. 13362306a36Sopenharmony_ci */ 13462306a36Sopenharmony_ci r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID, 13562306a36Sopenharmony_ci ST21NFCA_DEVICE_MGNT_GATE, 13662306a36Sopenharmony_ci ST21NFCA_DEVICE_MGNT_PIPE); 13762306a36Sopenharmony_ci if (r < 0) 13862306a36Sopenharmony_ci return r; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci /* Get pipe list */ 14162306a36Sopenharmony_ci r = nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE, 14262306a36Sopenharmony_ci ST21NFCA_DM_GETINFO, pipe_list, sizeof(pipe_list), 14362306a36Sopenharmony_ci &skb_pipe_list); 14462306a36Sopenharmony_ci if (r < 0) 14562306a36Sopenharmony_ci return r; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci /* Complete the existing gate_pipe table */ 14862306a36Sopenharmony_ci for (i = 0; i < skb_pipe_list->len; i++) { 14962306a36Sopenharmony_ci pipe_info[2] = skb_pipe_list->data[i]; 15062306a36Sopenharmony_ci r = nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE, 15162306a36Sopenharmony_ci ST21NFCA_DM_GETINFO, pipe_info, 15262306a36Sopenharmony_ci sizeof(pipe_info), &skb_pipe_info); 15362306a36Sopenharmony_ci if (r) 15462306a36Sopenharmony_ci continue; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci /* 15762306a36Sopenharmony_ci * Match pipe ID and gate ID 15862306a36Sopenharmony_ci * Output format from ST21NFC_DM_GETINFO is: 15962306a36Sopenharmony_ci * - pipe state (1byte) 16062306a36Sopenharmony_ci * - source hid (1byte) 16162306a36Sopenharmony_ci * - source gid (1byte) 16262306a36Sopenharmony_ci * - destination hid (1byte) 16362306a36Sopenharmony_ci * - destination gid (1byte) 16462306a36Sopenharmony_ci */ 16562306a36Sopenharmony_ci info = (struct st21nfca_pipe_info *) skb_pipe_info->data; 16662306a36Sopenharmony_ci if (info->dst_gate_id == ST21NFCA_APDU_READER_GATE && 16762306a36Sopenharmony_ci info->src_host_id == NFC_HCI_UICC_HOST_ID) { 16862306a36Sopenharmony_ci pr_err("Unexpected apdu_reader pipe on host %x\n", 16962306a36Sopenharmony_ci info->src_host_id); 17062306a36Sopenharmony_ci kfree_skb(skb_pipe_info); 17162306a36Sopenharmony_ci continue; 17262306a36Sopenharmony_ci } 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci for (j = 3; (j < ARRAY_SIZE(st21nfca_gates)) && 17562306a36Sopenharmony_ci (st21nfca_gates[j].gate != info->dst_gate_id) ; j++) 17662306a36Sopenharmony_ci ; 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci if (j < ARRAY_SIZE(st21nfca_gates) && 17962306a36Sopenharmony_ci st21nfca_gates[j].gate == info->dst_gate_id && 18062306a36Sopenharmony_ci ST21NFCA_DM_IS_PIPE_OPEN(info->pipe_state)) { 18162306a36Sopenharmony_ci hdev->init_data.gates[j].pipe = pipe_info[2]; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci hdev->gate2pipe[st21nfca_gates[j].gate] = 18462306a36Sopenharmony_ci pipe_info[2]; 18562306a36Sopenharmony_ci hdev->pipes[pipe_info[2]].gate = 18662306a36Sopenharmony_ci st21nfca_gates[j].gate; 18762306a36Sopenharmony_ci hdev->pipes[pipe_info[2]].dest_host = 18862306a36Sopenharmony_ci info->src_host_id; 18962306a36Sopenharmony_ci } 19062306a36Sopenharmony_ci kfree_skb(skb_pipe_info); 19162306a36Sopenharmony_ci } 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci /* 19462306a36Sopenharmony_ci * 3 gates have a well known pipe ID. Only NFC_HCI_LINK_MGMT_GATE 19562306a36Sopenharmony_ci * is not yet open at this stage. 19662306a36Sopenharmony_ci */ 19762306a36Sopenharmony_ci r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID, 19862306a36Sopenharmony_ci NFC_HCI_LINK_MGMT_GATE, 19962306a36Sopenharmony_ci NFC_HCI_LINK_MGMT_PIPE); 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci kfree_skb(skb_pipe_list); 20262306a36Sopenharmony_ci return r; 20362306a36Sopenharmony_ci} 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_cistatic int st21nfca_hci_open(struct nfc_hci_dev *hdev) 20662306a36Sopenharmony_ci{ 20762306a36Sopenharmony_ci struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); 20862306a36Sopenharmony_ci int r; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci mutex_lock(&info->info_lock); 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci if (info->state != ST21NFCA_ST_COLD) { 21362306a36Sopenharmony_ci r = -EBUSY; 21462306a36Sopenharmony_ci goto out; 21562306a36Sopenharmony_ci } 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci r = info->phy_ops->enable(info->phy_id); 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci if (r == 0) 22062306a36Sopenharmony_ci info->state = ST21NFCA_ST_READY; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ciout: 22362306a36Sopenharmony_ci mutex_unlock(&info->info_lock); 22462306a36Sopenharmony_ci return r; 22562306a36Sopenharmony_ci} 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_cistatic void st21nfca_hci_close(struct nfc_hci_dev *hdev) 22862306a36Sopenharmony_ci{ 22962306a36Sopenharmony_ci struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci mutex_lock(&info->info_lock); 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci if (info->state == ST21NFCA_ST_COLD) 23462306a36Sopenharmony_ci goto out; 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci info->phy_ops->disable(info->phy_id); 23762306a36Sopenharmony_ci info->state = ST21NFCA_ST_COLD; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ciout: 24062306a36Sopenharmony_ci mutex_unlock(&info->info_lock); 24162306a36Sopenharmony_ci} 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_cistatic int st21nfca_hci_ready(struct nfc_hci_dev *hdev) 24462306a36Sopenharmony_ci{ 24562306a36Sopenharmony_ci struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); 24662306a36Sopenharmony_ci struct sk_buff *skb; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci u8 param; 24962306a36Sopenharmony_ci u8 white_list[2]; 25062306a36Sopenharmony_ci int wl_size = 0; 25162306a36Sopenharmony_ci int r; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci if (info->se_status->is_uicc_present) 25462306a36Sopenharmony_ci white_list[wl_size++] = NFC_HCI_UICC_HOST_ID; 25562306a36Sopenharmony_ci if (info->se_status->is_ese_present) 25662306a36Sopenharmony_ci white_list[wl_size++] = ST21NFCA_ESE_HOST_ID; 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci if (wl_size) { 25962306a36Sopenharmony_ci r = nfc_hci_set_param(hdev, NFC_HCI_ADMIN_GATE, 26062306a36Sopenharmony_ci NFC_HCI_ADMIN_WHITELIST, 26162306a36Sopenharmony_ci (u8 *) &white_list, wl_size); 26262306a36Sopenharmony_ci if (r < 0) 26362306a36Sopenharmony_ci return r; 26462306a36Sopenharmony_ci } 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci /* Set NFC_MODE in device management gate to enable */ 26762306a36Sopenharmony_ci r = nfc_hci_get_param(hdev, ST21NFCA_DEVICE_MGNT_GATE, 26862306a36Sopenharmony_ci ST21NFCA_NFC_MODE, &skb); 26962306a36Sopenharmony_ci if (r < 0) 27062306a36Sopenharmony_ci return r; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci param = skb->data[0]; 27362306a36Sopenharmony_ci kfree_skb(skb); 27462306a36Sopenharmony_ci if (param == 0) { 27562306a36Sopenharmony_ci param = 1; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci r = nfc_hci_set_param(hdev, ST21NFCA_DEVICE_MGNT_GATE, 27862306a36Sopenharmony_ci ST21NFCA_NFC_MODE, ¶m, 1); 27962306a36Sopenharmony_ci if (r < 0) 28062306a36Sopenharmony_ci return r; 28162306a36Sopenharmony_ci } 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, 28462306a36Sopenharmony_ci NFC_HCI_EVT_END_OPERATION, NULL, 0); 28562306a36Sopenharmony_ci if (r < 0) 28662306a36Sopenharmony_ci return r; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci r = nfc_hci_get_param(hdev, NFC_HCI_ID_MGMT_GATE, 28962306a36Sopenharmony_ci NFC_HCI_ID_MGMT_VERSION_SW, &skb); 29062306a36Sopenharmony_ci if (r < 0) 29162306a36Sopenharmony_ci return r; 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci if (skb->len != FULL_VERSION_LEN) { 29462306a36Sopenharmony_ci kfree_skb(skb); 29562306a36Sopenharmony_ci return -EINVAL; 29662306a36Sopenharmony_ci } 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci print_hex_dump(KERN_DEBUG, "FULL VERSION SOFTWARE INFO: ", 29962306a36Sopenharmony_ci DUMP_PREFIX_NONE, 16, 1, 30062306a36Sopenharmony_ci skb->data, FULL_VERSION_LEN, false); 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci kfree_skb(skb); 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci return 0; 30562306a36Sopenharmony_ci} 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_cistatic int st21nfca_hci_xmit(struct nfc_hci_dev *hdev, struct sk_buff *skb) 30862306a36Sopenharmony_ci{ 30962306a36Sopenharmony_ci struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci return info->phy_ops->write(info->phy_id, skb); 31262306a36Sopenharmony_ci} 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_cistatic int st21nfca_hci_start_poll(struct nfc_hci_dev *hdev, 31562306a36Sopenharmony_ci u32 im_protocols, u32 tm_protocols) 31662306a36Sopenharmony_ci{ 31762306a36Sopenharmony_ci int r; 31862306a36Sopenharmony_ci u32 pol_req; 31962306a36Sopenharmony_ci u8 param[19]; 32062306a36Sopenharmony_ci struct sk_buff *datarate_skb; 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci pr_info(DRIVER_DESC ": %s protocols 0x%x 0x%x\n", 32362306a36Sopenharmony_ci __func__, im_protocols, tm_protocols); 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, 32662306a36Sopenharmony_ci NFC_HCI_EVT_END_OPERATION, NULL, 0); 32762306a36Sopenharmony_ci if (r < 0) 32862306a36Sopenharmony_ci return r; 32962306a36Sopenharmony_ci if (im_protocols) { 33062306a36Sopenharmony_ci /* 33162306a36Sopenharmony_ci * enable polling according to im_protocols & tm_protocols 33262306a36Sopenharmony_ci * - CLOSE pipe according to im_protocols & tm_protocols 33362306a36Sopenharmony_ci */ 33462306a36Sopenharmony_ci if ((NFC_HCI_RF_READER_B_GATE & im_protocols) == 0) { 33562306a36Sopenharmony_ci r = nfc_hci_disconnect_gate(hdev, 33662306a36Sopenharmony_ci NFC_HCI_RF_READER_B_GATE); 33762306a36Sopenharmony_ci if (r < 0) 33862306a36Sopenharmony_ci return r; 33962306a36Sopenharmony_ci } 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci if ((NFC_HCI_RF_READER_A_GATE & im_protocols) == 0) { 34262306a36Sopenharmony_ci r = nfc_hci_disconnect_gate(hdev, 34362306a36Sopenharmony_ci NFC_HCI_RF_READER_A_GATE); 34462306a36Sopenharmony_ci if (r < 0) 34562306a36Sopenharmony_ci return r; 34662306a36Sopenharmony_ci } 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci if ((ST21NFCA_RF_READER_F_GATE & im_protocols) == 0) { 34962306a36Sopenharmony_ci r = nfc_hci_disconnect_gate(hdev, 35062306a36Sopenharmony_ci ST21NFCA_RF_READER_F_GATE); 35162306a36Sopenharmony_ci if (r < 0) 35262306a36Sopenharmony_ci return r; 35362306a36Sopenharmony_ci } else { 35462306a36Sopenharmony_ci hdev->gb = nfc_get_local_general_bytes(hdev->ndev, 35562306a36Sopenharmony_ci &hdev->gb_len); 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci if (hdev->gb == NULL || hdev->gb_len == 0) { 35862306a36Sopenharmony_ci im_protocols &= ~NFC_PROTO_NFC_DEP_MASK; 35962306a36Sopenharmony_ci tm_protocols &= ~NFC_PROTO_NFC_DEP_MASK; 36062306a36Sopenharmony_ci } 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci param[0] = ST21NFCA_RF_READER_F_DATARATE_106 | 36362306a36Sopenharmony_ci ST21NFCA_RF_READER_F_DATARATE_212 | 36462306a36Sopenharmony_ci ST21NFCA_RF_READER_F_DATARATE_424; 36562306a36Sopenharmony_ci r = nfc_hci_set_param(hdev, ST21NFCA_RF_READER_F_GATE, 36662306a36Sopenharmony_ci ST21NFCA_RF_READER_F_DATARATE, 36762306a36Sopenharmony_ci param, 1); 36862306a36Sopenharmony_ci if (r < 0) 36962306a36Sopenharmony_ci return r; 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci pol_req = be32_to_cpu((__force __be32) 37262306a36Sopenharmony_ci ST21NFCA_RF_READER_F_POL_REQ_DEFAULT); 37362306a36Sopenharmony_ci r = nfc_hci_set_param(hdev, ST21NFCA_RF_READER_F_GATE, 37462306a36Sopenharmony_ci ST21NFCA_RF_READER_F_POL_REQ, 37562306a36Sopenharmony_ci (u8 *) &pol_req, 4); 37662306a36Sopenharmony_ci if (r < 0) 37762306a36Sopenharmony_ci return r; 37862306a36Sopenharmony_ci } 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci if ((ST21NFCA_RF_READER_14443_3_A_GATE & im_protocols) == 0) { 38162306a36Sopenharmony_ci r = nfc_hci_disconnect_gate(hdev, 38262306a36Sopenharmony_ci ST21NFCA_RF_READER_14443_3_A_GATE); 38362306a36Sopenharmony_ci if (r < 0) 38462306a36Sopenharmony_ci return r; 38562306a36Sopenharmony_ci } 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci if ((ST21NFCA_RF_READER_ISO15693_GATE & im_protocols) == 0) { 38862306a36Sopenharmony_ci r = nfc_hci_disconnect_gate(hdev, 38962306a36Sopenharmony_ci ST21NFCA_RF_READER_ISO15693_GATE); 39062306a36Sopenharmony_ci if (r < 0) 39162306a36Sopenharmony_ci return r; 39262306a36Sopenharmony_ci } 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, 39562306a36Sopenharmony_ci NFC_HCI_EVT_READER_REQUESTED, NULL, 0); 39662306a36Sopenharmony_ci if (r < 0) 39762306a36Sopenharmony_ci nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, 39862306a36Sopenharmony_ci NFC_HCI_EVT_END_OPERATION, NULL, 0); 39962306a36Sopenharmony_ci } 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci if (tm_protocols & NFC_PROTO_NFC_DEP_MASK) { 40262306a36Sopenharmony_ci r = nfc_hci_get_param(hdev, ST21NFCA_RF_CARD_F_GATE, 40362306a36Sopenharmony_ci ST21NFCA_RF_CARD_F_DATARATE, 40462306a36Sopenharmony_ci &datarate_skb); 40562306a36Sopenharmony_ci if (r < 0) 40662306a36Sopenharmony_ci return r; 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci /* Configure the maximum supported datarate to 424Kbps */ 40962306a36Sopenharmony_ci if (datarate_skb->len > 0 && 41062306a36Sopenharmony_ci datarate_skb->data[0] != 41162306a36Sopenharmony_ci ST21NFCA_RF_CARD_F_DATARATE_212_424) { 41262306a36Sopenharmony_ci param[0] = ST21NFCA_RF_CARD_F_DATARATE_212_424; 41362306a36Sopenharmony_ci r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE, 41462306a36Sopenharmony_ci ST21NFCA_RF_CARD_F_DATARATE, 41562306a36Sopenharmony_ci param, 1); 41662306a36Sopenharmony_ci if (r < 0) { 41762306a36Sopenharmony_ci kfree_skb(datarate_skb); 41862306a36Sopenharmony_ci return r; 41962306a36Sopenharmony_ci } 42062306a36Sopenharmony_ci } 42162306a36Sopenharmony_ci kfree_skb(datarate_skb); 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci /* 42462306a36Sopenharmony_ci * Configure sens_res 42562306a36Sopenharmony_ci * 42662306a36Sopenharmony_ci * NFC Forum Digital Spec Table 7: 42762306a36Sopenharmony_ci * NFCID1 size: triple (10 bytes) 42862306a36Sopenharmony_ci */ 42962306a36Sopenharmony_ci param[0] = 0x00; 43062306a36Sopenharmony_ci param[1] = 0x08; 43162306a36Sopenharmony_ci r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE, 43262306a36Sopenharmony_ci ST21NFCA_RF_CARD_F_SENS_RES, param, 2); 43362306a36Sopenharmony_ci if (r < 0) 43462306a36Sopenharmony_ci return r; 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci /* 43762306a36Sopenharmony_ci * Configure sel_res 43862306a36Sopenharmony_ci * 43962306a36Sopenharmony_ci * NFC Forum Digistal Spec Table 17: 44062306a36Sopenharmony_ci * b3 set to 0b (value b7-b6): 44162306a36Sopenharmony_ci * - 10b: Configured for NFC-DEP Protocol 44262306a36Sopenharmony_ci */ 44362306a36Sopenharmony_ci param[0] = 0x40; 44462306a36Sopenharmony_ci r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE, 44562306a36Sopenharmony_ci ST21NFCA_RF_CARD_F_SEL_RES, param, 1); 44662306a36Sopenharmony_ci if (r < 0) 44762306a36Sopenharmony_ci return r; 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci /* Configure NFCID1 Random uid */ 45062306a36Sopenharmony_ci r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE, 45162306a36Sopenharmony_ci ST21NFCA_RF_CARD_F_NFCID1, NULL, 0); 45262306a36Sopenharmony_ci if (r < 0) 45362306a36Sopenharmony_ci return r; 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci /* Configure NFCID2_LIST */ 45662306a36Sopenharmony_ci /* System Code */ 45762306a36Sopenharmony_ci param[0] = 0x00; 45862306a36Sopenharmony_ci param[1] = 0x00; 45962306a36Sopenharmony_ci /* NFCID2 */ 46062306a36Sopenharmony_ci param[2] = 0x01; 46162306a36Sopenharmony_ci param[3] = 0xfe; 46262306a36Sopenharmony_ci param[4] = 'S'; 46362306a36Sopenharmony_ci param[5] = 'T'; 46462306a36Sopenharmony_ci param[6] = 'M'; 46562306a36Sopenharmony_ci param[7] = 'i'; 46662306a36Sopenharmony_ci param[8] = 'c'; 46762306a36Sopenharmony_ci param[9] = 'r'; 46862306a36Sopenharmony_ci /* 8 byte Pad bytes used for polling respone frame */ 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci /* 47162306a36Sopenharmony_ci * Configuration byte: 47262306a36Sopenharmony_ci * - bit 0: define the default NFCID2 entry used when the 47362306a36Sopenharmony_ci * system code is equal to 'FFFF' 47462306a36Sopenharmony_ci * - bit 1: use a random value for lowest 6 bytes of 47562306a36Sopenharmony_ci * NFCID2 value 47662306a36Sopenharmony_ci * - bit 2: ignore polling request frame if request code 47762306a36Sopenharmony_ci * is equal to '01' 47862306a36Sopenharmony_ci * - Other bits are RFU 47962306a36Sopenharmony_ci */ 48062306a36Sopenharmony_ci param[18] = 0x01; 48162306a36Sopenharmony_ci r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE, 48262306a36Sopenharmony_ci ST21NFCA_RF_CARD_F_NFCID2_LIST, param, 48362306a36Sopenharmony_ci 19); 48462306a36Sopenharmony_ci if (r < 0) 48562306a36Sopenharmony_ci return r; 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci param[0] = 0x02; 48862306a36Sopenharmony_ci r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE, 48962306a36Sopenharmony_ci ST21NFCA_RF_CARD_F_MODE, param, 1); 49062306a36Sopenharmony_ci } 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci return r; 49362306a36Sopenharmony_ci} 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_cistatic void st21nfca_hci_stop_poll(struct nfc_hci_dev *hdev) 49662306a36Sopenharmony_ci{ 49762306a36Sopenharmony_ci nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE, 49862306a36Sopenharmony_ci ST21NFCA_DM_DISCONNECT, NULL, 0, NULL); 49962306a36Sopenharmony_ci} 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_cistatic int st21nfca_get_iso14443_3_atqa(struct nfc_hci_dev *hdev, u16 *atqa) 50262306a36Sopenharmony_ci{ 50362306a36Sopenharmony_ci int r; 50462306a36Sopenharmony_ci struct sk_buff *atqa_skb = NULL; 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_14443_3_A_GATE, 50762306a36Sopenharmony_ci ST21NFCA_RF_READER_14443_3_A_ATQA, &atqa_skb); 50862306a36Sopenharmony_ci if (r < 0) 50962306a36Sopenharmony_ci goto exit; 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci if (atqa_skb->len != 2) { 51262306a36Sopenharmony_ci r = -EPROTO; 51362306a36Sopenharmony_ci goto exit; 51462306a36Sopenharmony_ci } 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci *atqa = be16_to_cpu(*(__be16 *) atqa_skb->data); 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ciexit: 51962306a36Sopenharmony_ci kfree_skb(atqa_skb); 52062306a36Sopenharmony_ci return r; 52162306a36Sopenharmony_ci} 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_cistatic int st21nfca_get_iso14443_3_sak(struct nfc_hci_dev *hdev, u8 *sak) 52462306a36Sopenharmony_ci{ 52562306a36Sopenharmony_ci int r; 52662306a36Sopenharmony_ci struct sk_buff *sak_skb = NULL; 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_14443_3_A_GATE, 52962306a36Sopenharmony_ci ST21NFCA_RF_READER_14443_3_A_SAK, &sak_skb); 53062306a36Sopenharmony_ci if (r < 0) 53162306a36Sopenharmony_ci goto exit; 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci if (sak_skb->len != 1) { 53462306a36Sopenharmony_ci r = -EPROTO; 53562306a36Sopenharmony_ci goto exit; 53662306a36Sopenharmony_ci } 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci *sak = sak_skb->data[0]; 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ciexit: 54162306a36Sopenharmony_ci kfree_skb(sak_skb); 54262306a36Sopenharmony_ci return r; 54362306a36Sopenharmony_ci} 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_cistatic int st21nfca_get_iso14443_3_uid(struct nfc_hci_dev *hdev, u8 *uid, 54662306a36Sopenharmony_ci int *len) 54762306a36Sopenharmony_ci{ 54862306a36Sopenharmony_ci int r; 54962306a36Sopenharmony_ci struct sk_buff *uid_skb = NULL; 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_14443_3_A_GATE, 55262306a36Sopenharmony_ci ST21NFCA_RF_READER_14443_3_A_UID, &uid_skb); 55362306a36Sopenharmony_ci if (r < 0) 55462306a36Sopenharmony_ci goto exit; 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci if (uid_skb->len == 0 || uid_skb->len > NFC_NFCID1_MAXSIZE) { 55762306a36Sopenharmony_ci r = -EPROTO; 55862306a36Sopenharmony_ci goto exit; 55962306a36Sopenharmony_ci } 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci memcpy(uid, uid_skb->data, uid_skb->len); 56262306a36Sopenharmony_ci *len = uid_skb->len; 56362306a36Sopenharmony_ciexit: 56462306a36Sopenharmony_ci kfree_skb(uid_skb); 56562306a36Sopenharmony_ci return r; 56662306a36Sopenharmony_ci} 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_cistatic int st21nfca_get_iso15693_inventory(struct nfc_hci_dev *hdev, 56962306a36Sopenharmony_ci struct nfc_target *target) 57062306a36Sopenharmony_ci{ 57162306a36Sopenharmony_ci int r; 57262306a36Sopenharmony_ci struct sk_buff *inventory_skb = NULL; 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_ISO15693_GATE, 57562306a36Sopenharmony_ci ST21NFCA_RF_READER_ISO15693_INVENTORY, 57662306a36Sopenharmony_ci &inventory_skb); 57762306a36Sopenharmony_ci if (r < 0) 57862306a36Sopenharmony_ci goto exit; 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci skb_pull(inventory_skb, 2); 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci if (inventory_skb->len == 0 || 58362306a36Sopenharmony_ci inventory_skb->len > NFC_ISO15693_UID_MAXSIZE) { 58462306a36Sopenharmony_ci r = -EPROTO; 58562306a36Sopenharmony_ci goto exit; 58662306a36Sopenharmony_ci } 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci memcpy(target->iso15693_uid, inventory_skb->data, inventory_skb->len); 58962306a36Sopenharmony_ci target->iso15693_dsfid = inventory_skb->data[1]; 59062306a36Sopenharmony_ci target->is_iso15693 = 1; 59162306a36Sopenharmony_ciexit: 59262306a36Sopenharmony_ci kfree_skb(inventory_skb); 59362306a36Sopenharmony_ci return r; 59462306a36Sopenharmony_ci} 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_cistatic int st21nfca_hci_dep_link_up(struct nfc_hci_dev *hdev, 59762306a36Sopenharmony_ci struct nfc_target *target, u8 comm_mode, 59862306a36Sopenharmony_ci u8 *gb, size_t gb_len) 59962306a36Sopenharmony_ci{ 60062306a36Sopenharmony_ci struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci info->dep_info.idx = target->idx; 60362306a36Sopenharmony_ci return st21nfca_im_send_atr_req(hdev, gb, gb_len); 60462306a36Sopenharmony_ci} 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_cistatic int st21nfca_hci_dep_link_down(struct nfc_hci_dev *hdev) 60762306a36Sopenharmony_ci{ 60862306a36Sopenharmony_ci struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci info->state = ST21NFCA_ST_READY; 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_ci return nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE, 61362306a36Sopenharmony_ci ST21NFCA_DM_DISCONNECT, NULL, 0, NULL); 61462306a36Sopenharmony_ci} 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_cistatic int st21nfca_hci_target_from_gate(struct nfc_hci_dev *hdev, u8 gate, 61762306a36Sopenharmony_ci struct nfc_target *target) 61862306a36Sopenharmony_ci{ 61962306a36Sopenharmony_ci int r, len; 62062306a36Sopenharmony_ci u16 atqa; 62162306a36Sopenharmony_ci u8 sak; 62262306a36Sopenharmony_ci u8 uid[NFC_NFCID1_MAXSIZE]; 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_ci switch (gate) { 62562306a36Sopenharmony_ci case ST21NFCA_RF_READER_F_GATE: 62662306a36Sopenharmony_ci target->supported_protocols = NFC_PROTO_FELICA_MASK; 62762306a36Sopenharmony_ci break; 62862306a36Sopenharmony_ci case ST21NFCA_RF_READER_14443_3_A_GATE: 62962306a36Sopenharmony_ci /* ISO14443-3 type 1 or 2 tags */ 63062306a36Sopenharmony_ci r = st21nfca_get_iso14443_3_atqa(hdev, &atqa); 63162306a36Sopenharmony_ci if (r < 0) 63262306a36Sopenharmony_ci return r; 63362306a36Sopenharmony_ci if (atqa == 0x000c) { 63462306a36Sopenharmony_ci target->supported_protocols = NFC_PROTO_JEWEL_MASK; 63562306a36Sopenharmony_ci target->sens_res = 0x0c00; 63662306a36Sopenharmony_ci } else { 63762306a36Sopenharmony_ci r = st21nfca_get_iso14443_3_sak(hdev, &sak); 63862306a36Sopenharmony_ci if (r < 0) 63962306a36Sopenharmony_ci return r; 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ci r = st21nfca_get_iso14443_3_uid(hdev, uid, &len); 64262306a36Sopenharmony_ci if (r < 0) 64362306a36Sopenharmony_ci return r; 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_ci target->supported_protocols = 64662306a36Sopenharmony_ci nfc_hci_sak_to_protocol(sak); 64762306a36Sopenharmony_ci if (target->supported_protocols == 0xffffffff) 64862306a36Sopenharmony_ci return -EPROTO; 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci target->sens_res = atqa; 65162306a36Sopenharmony_ci target->sel_res = sak; 65262306a36Sopenharmony_ci memcpy(target->nfcid1, uid, len); 65362306a36Sopenharmony_ci target->nfcid1_len = len; 65462306a36Sopenharmony_ci } 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci break; 65762306a36Sopenharmony_ci case ST21NFCA_RF_READER_ISO15693_GATE: 65862306a36Sopenharmony_ci target->supported_protocols = NFC_PROTO_ISO15693_MASK; 65962306a36Sopenharmony_ci r = st21nfca_get_iso15693_inventory(hdev, target); 66062306a36Sopenharmony_ci if (r < 0) 66162306a36Sopenharmony_ci return r; 66262306a36Sopenharmony_ci break; 66362306a36Sopenharmony_ci default: 66462306a36Sopenharmony_ci return -EPROTO; 66562306a36Sopenharmony_ci } 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci return 0; 66862306a36Sopenharmony_ci} 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_cistatic int st21nfca_hci_complete_target_discovered(struct nfc_hci_dev *hdev, 67162306a36Sopenharmony_ci u8 gate, 67262306a36Sopenharmony_ci struct nfc_target *target) 67362306a36Sopenharmony_ci{ 67462306a36Sopenharmony_ci int r; 67562306a36Sopenharmony_ci struct sk_buff *nfcid_skb = NULL; 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci if (gate == ST21NFCA_RF_READER_F_GATE) { 67862306a36Sopenharmony_ci r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_F_GATE, 67962306a36Sopenharmony_ci ST21NFCA_RF_READER_F_NFCID2, &nfcid_skb); 68062306a36Sopenharmony_ci if (r < 0) 68162306a36Sopenharmony_ci goto exit; 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ci if (nfcid_skb->len > NFC_SENSF_RES_MAXSIZE) { 68462306a36Sopenharmony_ci r = -EPROTO; 68562306a36Sopenharmony_ci goto exit; 68662306a36Sopenharmony_ci } 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_ci /* 68962306a36Sopenharmony_ci * - After the recepton of polling response for type F frame 69062306a36Sopenharmony_ci * at 212 or 424 Kbit/s, NFCID2 registry parameters will be 69162306a36Sopenharmony_ci * updated. 69262306a36Sopenharmony_ci * - After the reception of SEL_RES with NFCIP-1 compliant bit 69362306a36Sopenharmony_ci * set for type A frame NFCID1 will be updated 69462306a36Sopenharmony_ci */ 69562306a36Sopenharmony_ci if (nfcid_skb->len > 0) { 69662306a36Sopenharmony_ci /* P2P in type F */ 69762306a36Sopenharmony_ci memcpy(target->sensf_res, nfcid_skb->data, 69862306a36Sopenharmony_ci nfcid_skb->len); 69962306a36Sopenharmony_ci target->sensf_res_len = nfcid_skb->len; 70062306a36Sopenharmony_ci /* NFC Forum Digital Protocol Table 44 */ 70162306a36Sopenharmony_ci if (target->sensf_res[0] == 0x01 && 70262306a36Sopenharmony_ci target->sensf_res[1] == 0xfe) 70362306a36Sopenharmony_ci target->supported_protocols = 70462306a36Sopenharmony_ci NFC_PROTO_NFC_DEP_MASK; 70562306a36Sopenharmony_ci else 70662306a36Sopenharmony_ci target->supported_protocols = 70762306a36Sopenharmony_ci NFC_PROTO_FELICA_MASK; 70862306a36Sopenharmony_ci } else { 70962306a36Sopenharmony_ci kfree_skb(nfcid_skb); 71062306a36Sopenharmony_ci nfcid_skb = NULL; 71162306a36Sopenharmony_ci /* P2P in type A */ 71262306a36Sopenharmony_ci r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_F_GATE, 71362306a36Sopenharmony_ci ST21NFCA_RF_READER_F_NFCID1, 71462306a36Sopenharmony_ci &nfcid_skb); 71562306a36Sopenharmony_ci if (r < 0) 71662306a36Sopenharmony_ci goto exit; 71762306a36Sopenharmony_ci 71862306a36Sopenharmony_ci if (nfcid_skb->len > NFC_NFCID1_MAXSIZE) { 71962306a36Sopenharmony_ci r = -EPROTO; 72062306a36Sopenharmony_ci goto exit; 72162306a36Sopenharmony_ci } 72262306a36Sopenharmony_ci memcpy(target->sensf_res, nfcid_skb->data, 72362306a36Sopenharmony_ci nfcid_skb->len); 72462306a36Sopenharmony_ci target->sensf_res_len = nfcid_skb->len; 72562306a36Sopenharmony_ci target->supported_protocols = NFC_PROTO_NFC_DEP_MASK; 72662306a36Sopenharmony_ci } 72762306a36Sopenharmony_ci target->hci_reader_gate = ST21NFCA_RF_READER_F_GATE; 72862306a36Sopenharmony_ci } 72962306a36Sopenharmony_ci r = 1; 73062306a36Sopenharmony_ciexit: 73162306a36Sopenharmony_ci kfree_skb(nfcid_skb); 73262306a36Sopenharmony_ci return r; 73362306a36Sopenharmony_ci} 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci#define ST21NFCA_CB_TYPE_READER_ISO15693 1 73662306a36Sopenharmony_cistatic void st21nfca_hci_data_exchange_cb(void *context, struct sk_buff *skb, 73762306a36Sopenharmony_ci int err) 73862306a36Sopenharmony_ci{ 73962306a36Sopenharmony_ci struct st21nfca_hci_info *info = context; 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_ci switch (info->async_cb_type) { 74262306a36Sopenharmony_ci case ST21NFCA_CB_TYPE_READER_ISO15693: 74362306a36Sopenharmony_ci if (err == 0) 74462306a36Sopenharmony_ci skb_trim(skb, skb->len - 1); 74562306a36Sopenharmony_ci info->async_cb(info->async_cb_context, skb, err); 74662306a36Sopenharmony_ci break; 74762306a36Sopenharmony_ci default: 74862306a36Sopenharmony_ci if (err == 0) 74962306a36Sopenharmony_ci kfree_skb(skb); 75062306a36Sopenharmony_ci break; 75162306a36Sopenharmony_ci } 75262306a36Sopenharmony_ci} 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci/* 75562306a36Sopenharmony_ci * Returns: 75662306a36Sopenharmony_ci * <= 0: driver handled the data exchange 75762306a36Sopenharmony_ci * 1: driver doesn't especially handle, please do standard processing 75862306a36Sopenharmony_ci */ 75962306a36Sopenharmony_cistatic int st21nfca_hci_im_transceive(struct nfc_hci_dev *hdev, 76062306a36Sopenharmony_ci struct nfc_target *target, 76162306a36Sopenharmony_ci struct sk_buff *skb, 76262306a36Sopenharmony_ci data_exchange_cb_t cb, void *cb_context) 76362306a36Sopenharmony_ci{ 76462306a36Sopenharmony_ci struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); 76562306a36Sopenharmony_ci 76662306a36Sopenharmony_ci pr_info(DRIVER_DESC ": %s for gate=%d len=%d\n", __func__, 76762306a36Sopenharmony_ci target->hci_reader_gate, skb->len); 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_ci switch (target->hci_reader_gate) { 77062306a36Sopenharmony_ci case ST21NFCA_RF_READER_F_GATE: 77162306a36Sopenharmony_ci if (target->supported_protocols == NFC_PROTO_NFC_DEP_MASK) 77262306a36Sopenharmony_ci return st21nfca_im_send_dep_req(hdev, skb); 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_ci *(u8 *)skb_push(skb, 1) = 0x1a; 77562306a36Sopenharmony_ci return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate, 77662306a36Sopenharmony_ci ST21NFCA_WR_XCHG_DATA, skb->data, 77762306a36Sopenharmony_ci skb->len, cb, cb_context); 77862306a36Sopenharmony_ci case ST21NFCA_RF_READER_14443_3_A_GATE: 77962306a36Sopenharmony_ci *(u8 *)skb_push(skb, 1) = 0x1a; /* CTR, see spec:10.2.2.1 */ 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_ci return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate, 78262306a36Sopenharmony_ci ST21NFCA_WR_XCHG_DATA, skb->data, 78362306a36Sopenharmony_ci skb->len, cb, cb_context); 78462306a36Sopenharmony_ci case ST21NFCA_RF_READER_ISO15693_GATE: 78562306a36Sopenharmony_ci info->async_cb_type = ST21NFCA_CB_TYPE_READER_ISO15693; 78662306a36Sopenharmony_ci info->async_cb = cb; 78762306a36Sopenharmony_ci info->async_cb_context = cb_context; 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ci *(u8 *)skb_push(skb, 1) = 0x17; 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_ci return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate, 79262306a36Sopenharmony_ci ST21NFCA_WR_XCHG_DATA, skb->data, 79362306a36Sopenharmony_ci skb->len, 79462306a36Sopenharmony_ci st21nfca_hci_data_exchange_cb, 79562306a36Sopenharmony_ci info); 79662306a36Sopenharmony_ci default: 79762306a36Sopenharmony_ci return 1; 79862306a36Sopenharmony_ci } 79962306a36Sopenharmony_ci} 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_cistatic int st21nfca_hci_tm_send(struct nfc_hci_dev *hdev, struct sk_buff *skb) 80262306a36Sopenharmony_ci{ 80362306a36Sopenharmony_ci return st21nfca_tm_send_dep_res(hdev, skb); 80462306a36Sopenharmony_ci} 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_cistatic int st21nfca_hci_check_presence(struct nfc_hci_dev *hdev, 80762306a36Sopenharmony_ci struct nfc_target *target) 80862306a36Sopenharmony_ci{ 80962306a36Sopenharmony_ci u8 fwi = 0x11; 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_ci switch (target->hci_reader_gate) { 81262306a36Sopenharmony_ci case NFC_HCI_RF_READER_A_GATE: 81362306a36Sopenharmony_ci case NFC_HCI_RF_READER_B_GATE: 81462306a36Sopenharmony_ci /* 81562306a36Sopenharmony_ci * PRESENCE_CHECK on those gates is available 81662306a36Sopenharmony_ci * However, the answer to this command is taking 3 * fwi 81762306a36Sopenharmony_ci * if the card is no present. 81862306a36Sopenharmony_ci * Instead, we send an empty I-Frame with a very short 81962306a36Sopenharmony_ci * configurable fwi ~604µs. 82062306a36Sopenharmony_ci */ 82162306a36Sopenharmony_ci return nfc_hci_send_cmd(hdev, target->hci_reader_gate, 82262306a36Sopenharmony_ci ST21NFCA_WR_XCHG_DATA, &fwi, 1, NULL); 82362306a36Sopenharmony_ci case ST21NFCA_RF_READER_14443_3_A_GATE: 82462306a36Sopenharmony_ci return nfc_hci_send_cmd(hdev, target->hci_reader_gate, 82562306a36Sopenharmony_ci ST21NFCA_RF_READER_CMD_PRESENCE_CHECK, 82662306a36Sopenharmony_ci NULL, 0, NULL); 82762306a36Sopenharmony_ci default: 82862306a36Sopenharmony_ci return -EOPNOTSUPP; 82962306a36Sopenharmony_ci } 83062306a36Sopenharmony_ci} 83162306a36Sopenharmony_ci 83262306a36Sopenharmony_cistatic void st21nfca_hci_cmd_received(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd, 83362306a36Sopenharmony_ci struct sk_buff *skb) 83462306a36Sopenharmony_ci{ 83562306a36Sopenharmony_ci struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); 83662306a36Sopenharmony_ci u8 gate = hdev->pipes[pipe].gate; 83762306a36Sopenharmony_ci 83862306a36Sopenharmony_ci pr_debug("cmd: %x\n", cmd); 83962306a36Sopenharmony_ci 84062306a36Sopenharmony_ci switch (cmd) { 84162306a36Sopenharmony_ci case NFC_HCI_ANY_OPEN_PIPE: 84262306a36Sopenharmony_ci if (gate != ST21NFCA_APDU_READER_GATE && 84362306a36Sopenharmony_ci hdev->pipes[pipe].dest_host != NFC_HCI_UICC_HOST_ID) 84462306a36Sopenharmony_ci info->se_info.count_pipes++; 84562306a36Sopenharmony_ci 84662306a36Sopenharmony_ci if (info->se_info.count_pipes == info->se_info.expected_pipes) { 84762306a36Sopenharmony_ci del_timer_sync(&info->se_info.se_active_timer); 84862306a36Sopenharmony_ci info->se_info.se_active = false; 84962306a36Sopenharmony_ci info->se_info.count_pipes = 0; 85062306a36Sopenharmony_ci complete(&info->se_info.req_completion); 85162306a36Sopenharmony_ci } 85262306a36Sopenharmony_ci break; 85362306a36Sopenharmony_ci } 85462306a36Sopenharmony_ci} 85562306a36Sopenharmony_ci 85662306a36Sopenharmony_cistatic int st21nfca_admin_event_received(struct nfc_hci_dev *hdev, u8 event, 85762306a36Sopenharmony_ci struct sk_buff *skb) 85862306a36Sopenharmony_ci{ 85962306a36Sopenharmony_ci struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ci pr_debug("admin event: %x\n", event); 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_ci switch (event) { 86462306a36Sopenharmony_ci case ST21NFCA_EVT_HOT_PLUG: 86562306a36Sopenharmony_ci if (info->se_info.se_active) { 86662306a36Sopenharmony_ci if (!ST21NFCA_EVT_HOT_PLUG_IS_INHIBITED(skb)) { 86762306a36Sopenharmony_ci del_timer_sync(&info->se_info.se_active_timer); 86862306a36Sopenharmony_ci info->se_info.se_active = false; 86962306a36Sopenharmony_ci complete(&info->se_info.req_completion); 87062306a36Sopenharmony_ci } else { 87162306a36Sopenharmony_ci mod_timer(&info->se_info.se_active_timer, 87262306a36Sopenharmony_ci jiffies + 87362306a36Sopenharmony_ci msecs_to_jiffies(ST21NFCA_SE_TO_PIPES)); 87462306a36Sopenharmony_ci } 87562306a36Sopenharmony_ci } 87662306a36Sopenharmony_ci break; 87762306a36Sopenharmony_ci default: 87862306a36Sopenharmony_ci nfc_err(&hdev->ndev->dev, "Unexpected event on admin gate\n"); 87962306a36Sopenharmony_ci } 88062306a36Sopenharmony_ci kfree_skb(skb); 88162306a36Sopenharmony_ci return 0; 88262306a36Sopenharmony_ci} 88362306a36Sopenharmony_ci 88462306a36Sopenharmony_ci/* 88562306a36Sopenharmony_ci * Returns: 88662306a36Sopenharmony_ci * <= 0: driver handled the event, skb consumed 88762306a36Sopenharmony_ci * 1: driver does not handle the event, please do standard processing 88862306a36Sopenharmony_ci */ 88962306a36Sopenharmony_cistatic int st21nfca_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, 89062306a36Sopenharmony_ci u8 event, struct sk_buff *skb) 89162306a36Sopenharmony_ci{ 89262306a36Sopenharmony_ci u8 gate = hdev->pipes[pipe].gate; 89362306a36Sopenharmony_ci u8 host = hdev->pipes[pipe].dest_host; 89462306a36Sopenharmony_ci 89562306a36Sopenharmony_ci pr_debug("hci event: %d gate: %x\n", event, gate); 89662306a36Sopenharmony_ci 89762306a36Sopenharmony_ci switch (gate) { 89862306a36Sopenharmony_ci case NFC_HCI_ADMIN_GATE: 89962306a36Sopenharmony_ci return st21nfca_admin_event_received(hdev, event, skb); 90062306a36Sopenharmony_ci case ST21NFCA_RF_CARD_F_GATE: 90162306a36Sopenharmony_ci return st21nfca_dep_event_received(hdev, event, skb); 90262306a36Sopenharmony_ci case ST21NFCA_CONNECTIVITY_GATE: 90362306a36Sopenharmony_ci return st21nfca_connectivity_event_received(hdev, host, 90462306a36Sopenharmony_ci event, skb); 90562306a36Sopenharmony_ci case ST21NFCA_APDU_READER_GATE: 90662306a36Sopenharmony_ci return st21nfca_apdu_reader_event_received(hdev, event, skb); 90762306a36Sopenharmony_ci case NFC_HCI_LOOPBACK_GATE: 90862306a36Sopenharmony_ci return st21nfca_hci_loopback_event_received(hdev, event, skb); 90962306a36Sopenharmony_ci default: 91062306a36Sopenharmony_ci return 1; 91162306a36Sopenharmony_ci } 91262306a36Sopenharmony_ci} 91362306a36Sopenharmony_ci 91462306a36Sopenharmony_cistatic const struct nfc_hci_ops st21nfca_hci_ops = { 91562306a36Sopenharmony_ci .open = st21nfca_hci_open, 91662306a36Sopenharmony_ci .close = st21nfca_hci_close, 91762306a36Sopenharmony_ci .load_session = st21nfca_hci_load_session, 91862306a36Sopenharmony_ci .hci_ready = st21nfca_hci_ready, 91962306a36Sopenharmony_ci .xmit = st21nfca_hci_xmit, 92062306a36Sopenharmony_ci .start_poll = st21nfca_hci_start_poll, 92162306a36Sopenharmony_ci .stop_poll = st21nfca_hci_stop_poll, 92262306a36Sopenharmony_ci .dep_link_up = st21nfca_hci_dep_link_up, 92362306a36Sopenharmony_ci .dep_link_down = st21nfca_hci_dep_link_down, 92462306a36Sopenharmony_ci .target_from_gate = st21nfca_hci_target_from_gate, 92562306a36Sopenharmony_ci .complete_target_discovered = st21nfca_hci_complete_target_discovered, 92662306a36Sopenharmony_ci .im_transceive = st21nfca_hci_im_transceive, 92762306a36Sopenharmony_ci .tm_send = st21nfca_hci_tm_send, 92862306a36Sopenharmony_ci .check_presence = st21nfca_hci_check_presence, 92962306a36Sopenharmony_ci .event_received = st21nfca_hci_event_received, 93062306a36Sopenharmony_ci .cmd_received = st21nfca_hci_cmd_received, 93162306a36Sopenharmony_ci .discover_se = st21nfca_hci_discover_se, 93262306a36Sopenharmony_ci .enable_se = st21nfca_hci_enable_se, 93362306a36Sopenharmony_ci .disable_se = st21nfca_hci_disable_se, 93462306a36Sopenharmony_ci .se_io = st21nfca_hci_se_io, 93562306a36Sopenharmony_ci}; 93662306a36Sopenharmony_ci 93762306a36Sopenharmony_ciint st21nfca_hci_probe(void *phy_id, const struct nfc_phy_ops *phy_ops, 93862306a36Sopenharmony_ci char *llc_name, int phy_headroom, int phy_tailroom, 93962306a36Sopenharmony_ci int phy_payload, struct nfc_hci_dev **hdev, 94062306a36Sopenharmony_ci struct st21nfca_se_status *se_status) 94162306a36Sopenharmony_ci{ 94262306a36Sopenharmony_ci struct st21nfca_hci_info *info; 94362306a36Sopenharmony_ci int r = 0; 94462306a36Sopenharmony_ci int dev_num; 94562306a36Sopenharmony_ci u32 protocols; 94662306a36Sopenharmony_ci struct nfc_hci_init_data init_data; 94762306a36Sopenharmony_ci unsigned long quirks = 0; 94862306a36Sopenharmony_ci 94962306a36Sopenharmony_ci info = kzalloc(sizeof(struct st21nfca_hci_info), GFP_KERNEL); 95062306a36Sopenharmony_ci if (!info) 95162306a36Sopenharmony_ci return -ENOMEM; 95262306a36Sopenharmony_ci 95362306a36Sopenharmony_ci info->phy_ops = phy_ops; 95462306a36Sopenharmony_ci info->phy_id = phy_id; 95562306a36Sopenharmony_ci info->state = ST21NFCA_ST_COLD; 95662306a36Sopenharmony_ci mutex_init(&info->info_lock); 95762306a36Sopenharmony_ci 95862306a36Sopenharmony_ci init_data.gate_count = ARRAY_SIZE(st21nfca_gates); 95962306a36Sopenharmony_ci 96062306a36Sopenharmony_ci memcpy(init_data.gates, st21nfca_gates, sizeof(st21nfca_gates)); 96162306a36Sopenharmony_ci 96262306a36Sopenharmony_ci /* 96362306a36Sopenharmony_ci * Session id must include the driver name + i2c bus addr 96462306a36Sopenharmony_ci * persistent info to discriminate 2 identical chips 96562306a36Sopenharmony_ci */ 96662306a36Sopenharmony_ci dev_num = find_first_zero_bit(dev_mask, ST21NFCA_NUM_DEVICES); 96762306a36Sopenharmony_ci if (dev_num >= ST21NFCA_NUM_DEVICES) { 96862306a36Sopenharmony_ci r = -ENODEV; 96962306a36Sopenharmony_ci goto err_alloc_hdev; 97062306a36Sopenharmony_ci } 97162306a36Sopenharmony_ci 97262306a36Sopenharmony_ci set_bit(dev_num, dev_mask); 97362306a36Sopenharmony_ci 97462306a36Sopenharmony_ci scnprintf(init_data.session_id, sizeof(init_data.session_id), "%s%2x", 97562306a36Sopenharmony_ci "ST21AH", dev_num); 97662306a36Sopenharmony_ci 97762306a36Sopenharmony_ci protocols = NFC_PROTO_JEWEL_MASK | 97862306a36Sopenharmony_ci NFC_PROTO_MIFARE_MASK | 97962306a36Sopenharmony_ci NFC_PROTO_FELICA_MASK | 98062306a36Sopenharmony_ci NFC_PROTO_ISO14443_MASK | 98162306a36Sopenharmony_ci NFC_PROTO_ISO14443_B_MASK | 98262306a36Sopenharmony_ci NFC_PROTO_ISO15693_MASK | 98362306a36Sopenharmony_ci NFC_PROTO_NFC_DEP_MASK; 98462306a36Sopenharmony_ci 98562306a36Sopenharmony_ci set_bit(NFC_HCI_QUIRK_SHORT_CLEAR, &quirks); 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_ci info->hdev = 98862306a36Sopenharmony_ci nfc_hci_allocate_device(&st21nfca_hci_ops, &init_data, quirks, 98962306a36Sopenharmony_ci protocols, llc_name, 99062306a36Sopenharmony_ci phy_headroom + ST21NFCA_CMDS_HEADROOM, 99162306a36Sopenharmony_ci phy_tailroom, phy_payload); 99262306a36Sopenharmony_ci 99362306a36Sopenharmony_ci if (!info->hdev) { 99462306a36Sopenharmony_ci pr_err("Cannot allocate nfc hdev.\n"); 99562306a36Sopenharmony_ci r = -ENOMEM; 99662306a36Sopenharmony_ci goto err_alloc_hdev; 99762306a36Sopenharmony_ci } 99862306a36Sopenharmony_ci 99962306a36Sopenharmony_ci info->se_status = se_status; 100062306a36Sopenharmony_ci 100162306a36Sopenharmony_ci nfc_hci_set_clientdata(info->hdev, info); 100262306a36Sopenharmony_ci 100362306a36Sopenharmony_ci r = nfc_hci_register_device(info->hdev); 100462306a36Sopenharmony_ci if (r) 100562306a36Sopenharmony_ci goto err_regdev; 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_ci *hdev = info->hdev; 100862306a36Sopenharmony_ci st21nfca_dep_init(info->hdev); 100962306a36Sopenharmony_ci st21nfca_se_init(info->hdev); 101062306a36Sopenharmony_ci st21nfca_vendor_cmds_init(info->hdev); 101162306a36Sopenharmony_ci 101262306a36Sopenharmony_ci return 0; 101362306a36Sopenharmony_ci 101462306a36Sopenharmony_cierr_regdev: 101562306a36Sopenharmony_ci nfc_hci_free_device(info->hdev); 101662306a36Sopenharmony_ci 101762306a36Sopenharmony_cierr_alloc_hdev: 101862306a36Sopenharmony_ci kfree(info); 101962306a36Sopenharmony_ci 102062306a36Sopenharmony_ci return r; 102162306a36Sopenharmony_ci} 102262306a36Sopenharmony_ciEXPORT_SYMBOL(st21nfca_hci_probe); 102362306a36Sopenharmony_ci 102462306a36Sopenharmony_civoid st21nfca_hci_remove(struct nfc_hci_dev *hdev) 102562306a36Sopenharmony_ci{ 102662306a36Sopenharmony_ci struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); 102762306a36Sopenharmony_ci 102862306a36Sopenharmony_ci st21nfca_dep_deinit(hdev); 102962306a36Sopenharmony_ci st21nfca_se_deinit(hdev); 103062306a36Sopenharmony_ci nfc_hci_unregister_device(hdev); 103162306a36Sopenharmony_ci nfc_hci_free_device(hdev); 103262306a36Sopenharmony_ci kfree(info); 103362306a36Sopenharmony_ci} 103462306a36Sopenharmony_ciEXPORT_SYMBOL(st21nfca_hci_remove); 103562306a36Sopenharmony_ci 103662306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 103762306a36Sopenharmony_ciMODULE_DESCRIPTION(DRIVER_DESC); 1038