162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved. 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <net/nfc/hci.h> 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include "st21nfca.h" 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#define ST21NFCA_NFCIP1_INITIATOR 0x00 1162306a36Sopenharmony_ci#define ST21NFCA_NFCIP1_REQ 0xd4 1262306a36Sopenharmony_ci#define ST21NFCA_NFCIP1_RES 0xd5 1362306a36Sopenharmony_ci#define ST21NFCA_NFCIP1_ATR_REQ 0x00 1462306a36Sopenharmony_ci#define ST21NFCA_NFCIP1_ATR_RES 0x01 1562306a36Sopenharmony_ci#define ST21NFCA_NFCIP1_PSL_REQ 0x04 1662306a36Sopenharmony_ci#define ST21NFCA_NFCIP1_PSL_RES 0x05 1762306a36Sopenharmony_ci#define ST21NFCA_NFCIP1_DEP_REQ 0x06 1862306a36Sopenharmony_ci#define ST21NFCA_NFCIP1_DEP_RES 0x07 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#define ST21NFCA_NFC_DEP_PFB_PNI(pfb) ((pfb) & 0x03) 2162306a36Sopenharmony_ci#define ST21NFCA_NFC_DEP_PFB_TYPE(pfb) ((pfb) & 0xE0) 2262306a36Sopenharmony_ci#define ST21NFCA_NFC_DEP_PFB_IS_TIMEOUT(pfb) \ 2362306a36Sopenharmony_ci ((pfb) & ST21NFCA_NFC_DEP_PFB_TIMEOUT_BIT) 2462306a36Sopenharmony_ci#define ST21NFCA_NFC_DEP_DID_BIT_SET(pfb) ((pfb) & 0x04) 2562306a36Sopenharmony_ci#define ST21NFCA_NFC_DEP_NAD_BIT_SET(pfb) ((pfb) & 0x08) 2662306a36Sopenharmony_ci#define ST21NFCA_NFC_DEP_PFB_TIMEOUT_BIT 0x10 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#define ST21NFCA_NFC_DEP_PFB_IS_TIMEOUT(pfb) \ 2962306a36Sopenharmony_ci ((pfb) & ST21NFCA_NFC_DEP_PFB_TIMEOUT_BIT) 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#define ST21NFCA_NFC_DEP_PFB_I_PDU 0x00 3262306a36Sopenharmony_ci#define ST21NFCA_NFC_DEP_PFB_ACK_NACK_PDU 0x40 3362306a36Sopenharmony_ci#define ST21NFCA_NFC_DEP_PFB_SUPERVISOR_PDU 0x80 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#define ST21NFCA_ATR_REQ_MIN_SIZE 17 3662306a36Sopenharmony_ci#define ST21NFCA_ATR_REQ_MAX_SIZE 65 3762306a36Sopenharmony_ci#define ST21NFCA_LR_BITS_PAYLOAD_SIZE_254B 0x30 3862306a36Sopenharmony_ci#define ST21NFCA_GB_BIT 0x02 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci#define ST21NFCA_EVT_SEND_DATA 0x10 4162306a36Sopenharmony_ci#define ST21NFCA_EVT_FIELD_ON 0x11 4262306a36Sopenharmony_ci#define ST21NFCA_EVT_CARD_DEACTIVATED 0x12 4362306a36Sopenharmony_ci#define ST21NFCA_EVT_CARD_ACTIVATED 0x13 4462306a36Sopenharmony_ci#define ST21NFCA_EVT_FIELD_OFF 0x14 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci#define ST21NFCA_EVT_CARD_F_BITRATE 0x16 4762306a36Sopenharmony_ci#define ST21NFCA_EVT_READER_F_BITRATE 0x13 4862306a36Sopenharmony_ci#define ST21NFCA_PSL_REQ_SEND_SPEED(brs) (brs & 0x38) 4962306a36Sopenharmony_ci#define ST21NFCA_PSL_REQ_RECV_SPEED(brs) (brs & 0x07) 5062306a36Sopenharmony_ci#define ST21NFCA_PP2LRI(pp) ((pp & 0x30) >> 4) 5162306a36Sopenharmony_ci#define ST21NFCA_CARD_BITRATE_212 0x01 5262306a36Sopenharmony_ci#define ST21NFCA_CARD_BITRATE_424 0x02 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci#define ST21NFCA_DEFAULT_TIMEOUT 0x0a 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci#define PROTOCOL_ERR(req) pr_err("%d: ST21NFCA Protocol error: %s\n", \ 5862306a36Sopenharmony_ci __LINE__, req) 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_cistruct st21nfca_atr_req { 6162306a36Sopenharmony_ci u8 length; 6262306a36Sopenharmony_ci u8 cmd0; 6362306a36Sopenharmony_ci u8 cmd1; 6462306a36Sopenharmony_ci u8 nfcid3[NFC_NFCID3_MAXSIZE]; 6562306a36Sopenharmony_ci u8 did; 6662306a36Sopenharmony_ci u8 bsi; 6762306a36Sopenharmony_ci u8 bri; 6862306a36Sopenharmony_ci u8 ppi; 6962306a36Sopenharmony_ci u8 gbi[]; 7062306a36Sopenharmony_ci} __packed; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_cistruct st21nfca_atr_res { 7362306a36Sopenharmony_ci u8 length; 7462306a36Sopenharmony_ci u8 cmd0; 7562306a36Sopenharmony_ci u8 cmd1; 7662306a36Sopenharmony_ci u8 nfcid3[NFC_NFCID3_MAXSIZE]; 7762306a36Sopenharmony_ci u8 did; 7862306a36Sopenharmony_ci u8 bsi; 7962306a36Sopenharmony_ci u8 bri; 8062306a36Sopenharmony_ci u8 to; 8162306a36Sopenharmony_ci u8 ppi; 8262306a36Sopenharmony_ci u8 gbi[]; 8362306a36Sopenharmony_ci} __packed; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cistruct st21nfca_psl_req { 8662306a36Sopenharmony_ci u8 length; 8762306a36Sopenharmony_ci u8 cmd0; 8862306a36Sopenharmony_ci u8 cmd1; 8962306a36Sopenharmony_ci u8 did; 9062306a36Sopenharmony_ci u8 brs; 9162306a36Sopenharmony_ci u8 fsl; 9262306a36Sopenharmony_ci} __packed; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_cistruct st21nfca_psl_res { 9562306a36Sopenharmony_ci u8 length; 9662306a36Sopenharmony_ci u8 cmd0; 9762306a36Sopenharmony_ci u8 cmd1; 9862306a36Sopenharmony_ci u8 did; 9962306a36Sopenharmony_ci} __packed; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_cistruct st21nfca_dep_req_res { 10262306a36Sopenharmony_ci u8 length; 10362306a36Sopenharmony_ci u8 cmd0; 10462306a36Sopenharmony_ci u8 cmd1; 10562306a36Sopenharmony_ci u8 pfb; 10662306a36Sopenharmony_ci u8 did; 10762306a36Sopenharmony_ci u8 nad; 10862306a36Sopenharmony_ci} __packed; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_cistatic void st21nfca_tx_work(struct work_struct *work) 11162306a36Sopenharmony_ci{ 11262306a36Sopenharmony_ci struct st21nfca_hci_info *info = container_of(work, 11362306a36Sopenharmony_ci struct st21nfca_hci_info, 11462306a36Sopenharmony_ci dep_info.tx_work); 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci struct nfc_dev *dev; 11762306a36Sopenharmony_ci struct sk_buff *skb; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci if (info) { 12062306a36Sopenharmony_ci dev = info->hdev->ndev; 12162306a36Sopenharmony_ci skb = info->dep_info.tx_pending; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci device_lock(&dev->dev); 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci nfc_hci_send_cmd_async(info->hdev, ST21NFCA_RF_READER_F_GATE, 12662306a36Sopenharmony_ci ST21NFCA_WR_XCHG_DATA, skb->data, skb->len, 12762306a36Sopenharmony_ci info->async_cb, info); 12862306a36Sopenharmony_ci device_unlock(&dev->dev); 12962306a36Sopenharmony_ci kfree_skb(skb); 13062306a36Sopenharmony_ci } 13162306a36Sopenharmony_ci} 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_cistatic void st21nfca_im_send_pdu(struct st21nfca_hci_info *info, 13462306a36Sopenharmony_ci struct sk_buff *skb) 13562306a36Sopenharmony_ci{ 13662306a36Sopenharmony_ci info->dep_info.tx_pending = skb; 13762306a36Sopenharmony_ci schedule_work(&info->dep_info.tx_work); 13862306a36Sopenharmony_ci} 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_cistatic int st21nfca_tm_send_atr_res(struct nfc_hci_dev *hdev, 14162306a36Sopenharmony_ci struct st21nfca_atr_req *atr_req) 14262306a36Sopenharmony_ci{ 14362306a36Sopenharmony_ci struct st21nfca_atr_res *atr_res; 14462306a36Sopenharmony_ci struct sk_buff *skb; 14562306a36Sopenharmony_ci size_t gb_len; 14662306a36Sopenharmony_ci int r; 14762306a36Sopenharmony_ci struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci gb_len = atr_req->length - sizeof(struct st21nfca_atr_req); 15062306a36Sopenharmony_ci skb = alloc_skb(atr_req->length + 1, GFP_KERNEL); 15162306a36Sopenharmony_ci if (!skb) 15262306a36Sopenharmony_ci return -ENOMEM; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci skb_put(skb, sizeof(struct st21nfca_atr_res)); 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci atr_res = (struct st21nfca_atr_res *)skb->data; 15762306a36Sopenharmony_ci memset(atr_res, 0, sizeof(struct st21nfca_atr_res)); 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci atr_res->length = atr_req->length + 1; 16062306a36Sopenharmony_ci atr_res->cmd0 = ST21NFCA_NFCIP1_RES; 16162306a36Sopenharmony_ci atr_res->cmd1 = ST21NFCA_NFCIP1_ATR_RES; 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci memcpy(atr_res->nfcid3, atr_req->nfcid3, 6); 16462306a36Sopenharmony_ci atr_res->bsi = 0x00; 16562306a36Sopenharmony_ci atr_res->bri = 0x00; 16662306a36Sopenharmony_ci atr_res->to = ST21NFCA_DEFAULT_TIMEOUT; 16762306a36Sopenharmony_ci atr_res->ppi = ST21NFCA_LR_BITS_PAYLOAD_SIZE_254B; 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci if (gb_len) { 17062306a36Sopenharmony_ci skb_put(skb, gb_len); 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci atr_res->ppi |= ST21NFCA_GB_BIT; 17362306a36Sopenharmony_ci memcpy(atr_res->gbi, atr_req->gbi, gb_len); 17462306a36Sopenharmony_ci r = nfc_set_remote_general_bytes(hdev->ndev, atr_res->gbi, 17562306a36Sopenharmony_ci gb_len); 17662306a36Sopenharmony_ci if (r < 0) { 17762306a36Sopenharmony_ci kfree_skb(skb); 17862306a36Sopenharmony_ci return r; 17962306a36Sopenharmony_ci } 18062306a36Sopenharmony_ci } 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci info->dep_info.curr_nfc_dep_pni = 0; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE, 18562306a36Sopenharmony_ci ST21NFCA_EVT_SEND_DATA, skb->data, skb->len); 18662306a36Sopenharmony_ci kfree_skb(skb); 18762306a36Sopenharmony_ci return r; 18862306a36Sopenharmony_ci} 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_cistatic int st21nfca_tm_recv_atr_req(struct nfc_hci_dev *hdev, 19162306a36Sopenharmony_ci struct sk_buff *skb) 19262306a36Sopenharmony_ci{ 19362306a36Sopenharmony_ci struct st21nfca_atr_req *atr_req; 19462306a36Sopenharmony_ci size_t gb_len; 19562306a36Sopenharmony_ci int r; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci skb_trim(skb, skb->len - 1); 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci if (!skb->len) 20062306a36Sopenharmony_ci return -EIO; 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci if (skb->len < ST21NFCA_ATR_REQ_MIN_SIZE) 20362306a36Sopenharmony_ci return -EPROTO; 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci atr_req = (struct st21nfca_atr_req *)skb->data; 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci if (atr_req->length < sizeof(struct st21nfca_atr_req)) 20862306a36Sopenharmony_ci return -EPROTO; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci r = st21nfca_tm_send_atr_res(hdev, atr_req); 21162306a36Sopenharmony_ci if (r) 21262306a36Sopenharmony_ci return r; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci gb_len = skb->len - sizeof(struct st21nfca_atr_req); 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci r = nfc_tm_activated(hdev->ndev, NFC_PROTO_NFC_DEP_MASK, 21762306a36Sopenharmony_ci NFC_COMM_PASSIVE, atr_req->gbi, gb_len); 21862306a36Sopenharmony_ci if (r) 21962306a36Sopenharmony_ci return r; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci return 0; 22262306a36Sopenharmony_ci} 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_cistatic int st21nfca_tm_send_psl_res(struct nfc_hci_dev *hdev, 22562306a36Sopenharmony_ci struct st21nfca_psl_req *psl_req) 22662306a36Sopenharmony_ci{ 22762306a36Sopenharmony_ci struct st21nfca_psl_res *psl_res; 22862306a36Sopenharmony_ci struct sk_buff *skb; 22962306a36Sopenharmony_ci u8 bitrate[2] = {0, 0}; 23062306a36Sopenharmony_ci int r; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci skb = alloc_skb(sizeof(struct st21nfca_psl_res), GFP_KERNEL); 23362306a36Sopenharmony_ci if (!skb) 23462306a36Sopenharmony_ci return -ENOMEM; 23562306a36Sopenharmony_ci skb_put(skb, sizeof(struct st21nfca_psl_res)); 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci psl_res = (struct st21nfca_psl_res *)skb->data; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci psl_res->length = sizeof(struct st21nfca_psl_res); 24062306a36Sopenharmony_ci psl_res->cmd0 = ST21NFCA_NFCIP1_RES; 24162306a36Sopenharmony_ci psl_res->cmd1 = ST21NFCA_NFCIP1_PSL_RES; 24262306a36Sopenharmony_ci psl_res->did = psl_req->did; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE, 24562306a36Sopenharmony_ci ST21NFCA_EVT_SEND_DATA, skb->data, skb->len); 24662306a36Sopenharmony_ci if (r < 0) 24762306a36Sopenharmony_ci goto error; 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci /* 25062306a36Sopenharmony_ci * ST21NFCA only support P2P passive. 25162306a36Sopenharmony_ci * PSL_REQ BRS value != 0 has only a meaning to 25262306a36Sopenharmony_ci * change technology to type F. 25362306a36Sopenharmony_ci * We change to BITRATE 424Kbits. 25462306a36Sopenharmony_ci * In other case switch to BITRATE 106Kbits. 25562306a36Sopenharmony_ci */ 25662306a36Sopenharmony_ci if (ST21NFCA_PSL_REQ_SEND_SPEED(psl_req->brs) && 25762306a36Sopenharmony_ci ST21NFCA_PSL_REQ_RECV_SPEED(psl_req->brs)) { 25862306a36Sopenharmony_ci bitrate[0] = ST21NFCA_CARD_BITRATE_424; 25962306a36Sopenharmony_ci bitrate[1] = ST21NFCA_CARD_BITRATE_424; 26062306a36Sopenharmony_ci } 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci /* Send an event to change bitrate change event to card f */ 26362306a36Sopenharmony_ci r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE, 26462306a36Sopenharmony_ci ST21NFCA_EVT_CARD_F_BITRATE, bitrate, 2); 26562306a36Sopenharmony_cierror: 26662306a36Sopenharmony_ci kfree_skb(skb); 26762306a36Sopenharmony_ci return r; 26862306a36Sopenharmony_ci} 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_cistatic int st21nfca_tm_recv_psl_req(struct nfc_hci_dev *hdev, 27162306a36Sopenharmony_ci struct sk_buff *skb) 27262306a36Sopenharmony_ci{ 27362306a36Sopenharmony_ci struct st21nfca_psl_req *psl_req; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci skb_trim(skb, skb->len - 1); 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci if (!skb->len) 27862306a36Sopenharmony_ci return -EIO; 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci psl_req = (struct st21nfca_psl_req *)skb->data; 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci if (skb->len < sizeof(struct st21nfca_psl_req)) 28362306a36Sopenharmony_ci return -EIO; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci return st21nfca_tm_send_psl_res(hdev, psl_req); 28662306a36Sopenharmony_ci} 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ciint st21nfca_tm_send_dep_res(struct nfc_hci_dev *hdev, struct sk_buff *skb) 28962306a36Sopenharmony_ci{ 29062306a36Sopenharmony_ci int r; 29162306a36Sopenharmony_ci struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci *(u8 *)skb_push(skb, 1) = info->dep_info.curr_nfc_dep_pni; 29462306a36Sopenharmony_ci *(u8 *)skb_push(skb, 1) = ST21NFCA_NFCIP1_DEP_RES; 29562306a36Sopenharmony_ci *(u8 *)skb_push(skb, 1) = ST21NFCA_NFCIP1_RES; 29662306a36Sopenharmony_ci *(u8 *)skb_push(skb, 1) = skb->len; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE, 29962306a36Sopenharmony_ci ST21NFCA_EVT_SEND_DATA, skb->data, skb->len); 30062306a36Sopenharmony_ci kfree_skb(skb); 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci return r; 30362306a36Sopenharmony_ci} 30462306a36Sopenharmony_ciEXPORT_SYMBOL(st21nfca_tm_send_dep_res); 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_cistatic int st21nfca_tm_recv_dep_req(struct nfc_hci_dev *hdev, 30762306a36Sopenharmony_ci struct sk_buff *skb) 30862306a36Sopenharmony_ci{ 30962306a36Sopenharmony_ci struct st21nfca_dep_req_res *dep_req; 31062306a36Sopenharmony_ci u8 size; 31162306a36Sopenharmony_ci struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci skb_trim(skb, skb->len - 1); 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci size = 4; 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci dep_req = (struct st21nfca_dep_req_res *)skb->data; 31862306a36Sopenharmony_ci if (skb->len < size) 31962306a36Sopenharmony_ci return -EIO; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci if (ST21NFCA_NFC_DEP_DID_BIT_SET(dep_req->pfb)) 32262306a36Sopenharmony_ci size++; 32362306a36Sopenharmony_ci if (ST21NFCA_NFC_DEP_NAD_BIT_SET(dep_req->pfb)) 32462306a36Sopenharmony_ci size++; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci if (skb->len < size) 32762306a36Sopenharmony_ci return -EIO; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci /* Receiving DEP_REQ - Decoding */ 33062306a36Sopenharmony_ci switch (ST21NFCA_NFC_DEP_PFB_TYPE(dep_req->pfb)) { 33162306a36Sopenharmony_ci case ST21NFCA_NFC_DEP_PFB_I_PDU: 33262306a36Sopenharmony_ci info->dep_info.curr_nfc_dep_pni = 33362306a36Sopenharmony_ci ST21NFCA_NFC_DEP_PFB_PNI(dep_req->pfb); 33462306a36Sopenharmony_ci break; 33562306a36Sopenharmony_ci case ST21NFCA_NFC_DEP_PFB_ACK_NACK_PDU: 33662306a36Sopenharmony_ci pr_err("Received a ACK/NACK PDU\n"); 33762306a36Sopenharmony_ci break; 33862306a36Sopenharmony_ci case ST21NFCA_NFC_DEP_PFB_SUPERVISOR_PDU: 33962306a36Sopenharmony_ci pr_err("Received a SUPERVISOR PDU\n"); 34062306a36Sopenharmony_ci break; 34162306a36Sopenharmony_ci } 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci skb_pull(skb, size); 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci return nfc_tm_data_received(hdev->ndev, skb); 34662306a36Sopenharmony_ci} 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_cistatic int st21nfca_tm_event_send_data(struct nfc_hci_dev *hdev, 34962306a36Sopenharmony_ci struct sk_buff *skb) 35062306a36Sopenharmony_ci{ 35162306a36Sopenharmony_ci u8 cmd0, cmd1; 35262306a36Sopenharmony_ci int r; 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci cmd0 = skb->data[1]; 35562306a36Sopenharmony_ci switch (cmd0) { 35662306a36Sopenharmony_ci case ST21NFCA_NFCIP1_REQ: 35762306a36Sopenharmony_ci cmd1 = skb->data[2]; 35862306a36Sopenharmony_ci switch (cmd1) { 35962306a36Sopenharmony_ci case ST21NFCA_NFCIP1_ATR_REQ: 36062306a36Sopenharmony_ci r = st21nfca_tm_recv_atr_req(hdev, skb); 36162306a36Sopenharmony_ci break; 36262306a36Sopenharmony_ci case ST21NFCA_NFCIP1_PSL_REQ: 36362306a36Sopenharmony_ci r = st21nfca_tm_recv_psl_req(hdev, skb); 36462306a36Sopenharmony_ci break; 36562306a36Sopenharmony_ci case ST21NFCA_NFCIP1_DEP_REQ: 36662306a36Sopenharmony_ci r = st21nfca_tm_recv_dep_req(hdev, skb); 36762306a36Sopenharmony_ci break; 36862306a36Sopenharmony_ci default: 36962306a36Sopenharmony_ci return 1; 37062306a36Sopenharmony_ci } 37162306a36Sopenharmony_ci break; 37262306a36Sopenharmony_ci default: 37362306a36Sopenharmony_ci return 1; 37462306a36Sopenharmony_ci } 37562306a36Sopenharmony_ci return r; 37662306a36Sopenharmony_ci} 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci/* 37962306a36Sopenharmony_ci * Returns: 38062306a36Sopenharmony_ci * <= 0: driver handled the event, skb consumed 38162306a36Sopenharmony_ci * 1: driver does not handle the event, please do standard processing 38262306a36Sopenharmony_ci */ 38362306a36Sopenharmony_ciint st21nfca_dep_event_received(struct nfc_hci_dev *hdev, 38462306a36Sopenharmony_ci u8 event, struct sk_buff *skb) 38562306a36Sopenharmony_ci{ 38662306a36Sopenharmony_ci int r = 0; 38762306a36Sopenharmony_ci struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci pr_debug("dep event: %d\n", event); 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci switch (event) { 39262306a36Sopenharmony_ci case ST21NFCA_EVT_CARD_ACTIVATED: 39362306a36Sopenharmony_ci info->dep_info.curr_nfc_dep_pni = 0; 39462306a36Sopenharmony_ci break; 39562306a36Sopenharmony_ci case ST21NFCA_EVT_CARD_DEACTIVATED: 39662306a36Sopenharmony_ci break; 39762306a36Sopenharmony_ci case ST21NFCA_EVT_FIELD_ON: 39862306a36Sopenharmony_ci break; 39962306a36Sopenharmony_ci case ST21NFCA_EVT_FIELD_OFF: 40062306a36Sopenharmony_ci break; 40162306a36Sopenharmony_ci case ST21NFCA_EVT_SEND_DATA: 40262306a36Sopenharmony_ci r = st21nfca_tm_event_send_data(hdev, skb); 40362306a36Sopenharmony_ci if (r < 0) 40462306a36Sopenharmony_ci return r; 40562306a36Sopenharmony_ci return 0; 40662306a36Sopenharmony_ci default: 40762306a36Sopenharmony_ci nfc_err(&hdev->ndev->dev, "Unexpected event on card f gate\n"); 40862306a36Sopenharmony_ci return 1; 40962306a36Sopenharmony_ci } 41062306a36Sopenharmony_ci kfree_skb(skb); 41162306a36Sopenharmony_ci return r; 41262306a36Sopenharmony_ci} 41362306a36Sopenharmony_ciEXPORT_SYMBOL(st21nfca_dep_event_received); 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_cistatic void st21nfca_im_send_psl_req(struct nfc_hci_dev *hdev, u8 did, u8 bsi, 41662306a36Sopenharmony_ci u8 bri, u8 lri) 41762306a36Sopenharmony_ci{ 41862306a36Sopenharmony_ci struct sk_buff *skb; 41962306a36Sopenharmony_ci struct st21nfca_psl_req *psl_req; 42062306a36Sopenharmony_ci struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci skb = 42362306a36Sopenharmony_ci alloc_skb(sizeof(struct st21nfca_psl_req) + 1, GFP_KERNEL); 42462306a36Sopenharmony_ci if (!skb) 42562306a36Sopenharmony_ci return; 42662306a36Sopenharmony_ci skb_reserve(skb, 1); 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci skb_put(skb, sizeof(struct st21nfca_psl_req)); 42962306a36Sopenharmony_ci psl_req = (struct st21nfca_psl_req *) skb->data; 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci psl_req->length = sizeof(struct st21nfca_psl_req); 43262306a36Sopenharmony_ci psl_req->cmd0 = ST21NFCA_NFCIP1_REQ; 43362306a36Sopenharmony_ci psl_req->cmd1 = ST21NFCA_NFCIP1_PSL_REQ; 43462306a36Sopenharmony_ci psl_req->did = did; 43562306a36Sopenharmony_ci psl_req->brs = (0x30 & bsi << 4) | (bri & 0x03); 43662306a36Sopenharmony_ci psl_req->fsl = lri; 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci *(u8 *)skb_push(skb, 1) = info->dep_info.to | 0x10; 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci st21nfca_im_send_pdu(info, skb); 44162306a36Sopenharmony_ci} 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci#define ST21NFCA_CB_TYPE_READER_F 1 44462306a36Sopenharmony_cistatic void st21nfca_im_recv_atr_res_cb(void *context, struct sk_buff *skb, 44562306a36Sopenharmony_ci int err) 44662306a36Sopenharmony_ci{ 44762306a36Sopenharmony_ci struct st21nfca_hci_info *info = context; 44862306a36Sopenharmony_ci struct st21nfca_atr_res *atr_res; 44962306a36Sopenharmony_ci int r; 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci if (err != 0) 45262306a36Sopenharmony_ci return; 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci if (!skb) 45562306a36Sopenharmony_ci return; 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci switch (info->async_cb_type) { 45862306a36Sopenharmony_ci case ST21NFCA_CB_TYPE_READER_F: 45962306a36Sopenharmony_ci skb_trim(skb, skb->len - 1); 46062306a36Sopenharmony_ci atr_res = (struct st21nfca_atr_res *)skb->data; 46162306a36Sopenharmony_ci r = nfc_set_remote_general_bytes(info->hdev->ndev, 46262306a36Sopenharmony_ci atr_res->gbi, 46362306a36Sopenharmony_ci skb->len - sizeof(struct st21nfca_atr_res)); 46462306a36Sopenharmony_ci if (r < 0) 46562306a36Sopenharmony_ci return; 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci if (atr_res->to >= 0x0e) 46862306a36Sopenharmony_ci info->dep_info.to = 0x0e; 46962306a36Sopenharmony_ci else 47062306a36Sopenharmony_ci info->dep_info.to = atr_res->to + 1; 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci info->dep_info.to |= 0x10; 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci r = nfc_dep_link_is_up(info->hdev->ndev, info->dep_info.idx, 47562306a36Sopenharmony_ci NFC_COMM_PASSIVE, NFC_RF_INITIATOR); 47662306a36Sopenharmony_ci if (r < 0) 47762306a36Sopenharmony_ci return; 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci info->dep_info.curr_nfc_dep_pni = 0; 48062306a36Sopenharmony_ci if (ST21NFCA_PP2LRI(atr_res->ppi) != info->dep_info.lri) 48162306a36Sopenharmony_ci st21nfca_im_send_psl_req(info->hdev, atr_res->did, 48262306a36Sopenharmony_ci atr_res->bsi, atr_res->bri, 48362306a36Sopenharmony_ci ST21NFCA_PP2LRI(atr_res->ppi)); 48462306a36Sopenharmony_ci break; 48562306a36Sopenharmony_ci default: 48662306a36Sopenharmony_ci kfree_skb(skb); 48762306a36Sopenharmony_ci break; 48862306a36Sopenharmony_ci } 48962306a36Sopenharmony_ci} 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ciint st21nfca_im_send_atr_req(struct nfc_hci_dev *hdev, u8 *gb, size_t gb_len) 49262306a36Sopenharmony_ci{ 49362306a36Sopenharmony_ci struct sk_buff *skb; 49462306a36Sopenharmony_ci struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); 49562306a36Sopenharmony_ci struct st21nfca_atr_req *atr_req; 49662306a36Sopenharmony_ci struct nfc_target *target; 49762306a36Sopenharmony_ci uint size; 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci info->dep_info.to = ST21NFCA_DEFAULT_TIMEOUT; 50062306a36Sopenharmony_ci size = ST21NFCA_ATR_REQ_MIN_SIZE + gb_len; 50162306a36Sopenharmony_ci if (size > ST21NFCA_ATR_REQ_MAX_SIZE) { 50262306a36Sopenharmony_ci PROTOCOL_ERR("14.6.1.1"); 50362306a36Sopenharmony_ci return -EINVAL; 50462306a36Sopenharmony_ci } 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci skb = 50762306a36Sopenharmony_ci alloc_skb(sizeof(struct st21nfca_atr_req) + gb_len + 1, GFP_KERNEL); 50862306a36Sopenharmony_ci if (!skb) 50962306a36Sopenharmony_ci return -ENOMEM; 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci skb_reserve(skb, 1); 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci skb_put(skb, sizeof(struct st21nfca_atr_req)); 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci atr_req = (struct st21nfca_atr_req *)skb->data; 51662306a36Sopenharmony_ci memset(atr_req, 0, sizeof(struct st21nfca_atr_req)); 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci atr_req->cmd0 = ST21NFCA_NFCIP1_REQ; 51962306a36Sopenharmony_ci atr_req->cmd1 = ST21NFCA_NFCIP1_ATR_REQ; 52062306a36Sopenharmony_ci memset(atr_req->nfcid3, 0, NFC_NFCID3_MAXSIZE); 52162306a36Sopenharmony_ci target = hdev->ndev->targets; 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci if (target->sensf_res_len > 0) 52462306a36Sopenharmony_ci memcpy(atr_req->nfcid3, target->sensf_res, 52562306a36Sopenharmony_ci target->sensf_res_len); 52662306a36Sopenharmony_ci else 52762306a36Sopenharmony_ci get_random_bytes(atr_req->nfcid3, NFC_NFCID3_MAXSIZE); 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci atr_req->did = 0x0; 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci atr_req->bsi = 0x00; 53262306a36Sopenharmony_ci atr_req->bri = 0x00; 53362306a36Sopenharmony_ci atr_req->ppi = ST21NFCA_LR_BITS_PAYLOAD_SIZE_254B; 53462306a36Sopenharmony_ci if (gb_len) { 53562306a36Sopenharmony_ci atr_req->ppi |= ST21NFCA_GB_BIT; 53662306a36Sopenharmony_ci skb_put_data(skb, gb, gb_len); 53762306a36Sopenharmony_ci } 53862306a36Sopenharmony_ci atr_req->length = sizeof(struct st21nfca_atr_req) + hdev->gb_len; 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci *(u8 *)skb_push(skb, 1) = info->dep_info.to | 0x10; /* timeout */ 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci info->async_cb_type = ST21NFCA_CB_TYPE_READER_F; 54362306a36Sopenharmony_ci info->async_cb_context = info; 54462306a36Sopenharmony_ci info->async_cb = st21nfca_im_recv_atr_res_cb; 54562306a36Sopenharmony_ci info->dep_info.bri = atr_req->bri; 54662306a36Sopenharmony_ci info->dep_info.bsi = atr_req->bsi; 54762306a36Sopenharmony_ci info->dep_info.lri = ST21NFCA_PP2LRI(atr_req->ppi); 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci return nfc_hci_send_cmd_async(hdev, ST21NFCA_RF_READER_F_GATE, 55062306a36Sopenharmony_ci ST21NFCA_WR_XCHG_DATA, skb->data, 55162306a36Sopenharmony_ci skb->len, info->async_cb, info); 55262306a36Sopenharmony_ci} 55362306a36Sopenharmony_ciEXPORT_SYMBOL(st21nfca_im_send_atr_req); 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_cistatic void st21nfca_im_recv_dep_res_cb(void *context, struct sk_buff *skb, 55662306a36Sopenharmony_ci int err) 55762306a36Sopenharmony_ci{ 55862306a36Sopenharmony_ci struct st21nfca_hci_info *info = context; 55962306a36Sopenharmony_ci struct st21nfca_dep_req_res *dep_res; 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci int size; 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci if (err != 0) 56462306a36Sopenharmony_ci return; 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci if (!skb) 56762306a36Sopenharmony_ci return; 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci switch (info->async_cb_type) { 57062306a36Sopenharmony_ci case ST21NFCA_CB_TYPE_READER_F: 57162306a36Sopenharmony_ci dep_res = (struct st21nfca_dep_req_res *)skb->data; 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci size = 3; 57462306a36Sopenharmony_ci if (skb->len < size) 57562306a36Sopenharmony_ci goto exit; 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci if (ST21NFCA_NFC_DEP_DID_BIT_SET(dep_res->pfb)) 57862306a36Sopenharmony_ci size++; 57962306a36Sopenharmony_ci if (ST21NFCA_NFC_DEP_NAD_BIT_SET(dep_res->pfb)) 58062306a36Sopenharmony_ci size++; 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci if (skb->len < size) 58362306a36Sopenharmony_ci goto exit; 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci skb_trim(skb, skb->len - 1); 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ci /* Receiving DEP_REQ - Decoding */ 58862306a36Sopenharmony_ci switch (ST21NFCA_NFC_DEP_PFB_TYPE(dep_res->pfb)) { 58962306a36Sopenharmony_ci case ST21NFCA_NFC_DEP_PFB_ACK_NACK_PDU: 59062306a36Sopenharmony_ci pr_err("Received a ACK/NACK PDU\n"); 59162306a36Sopenharmony_ci fallthrough; 59262306a36Sopenharmony_ci case ST21NFCA_NFC_DEP_PFB_I_PDU: 59362306a36Sopenharmony_ci info->dep_info.curr_nfc_dep_pni = 59462306a36Sopenharmony_ci ST21NFCA_NFC_DEP_PFB_PNI(dep_res->pfb + 1); 59562306a36Sopenharmony_ci size++; 59662306a36Sopenharmony_ci skb_pull(skb, size); 59762306a36Sopenharmony_ci nfc_tm_data_received(info->hdev->ndev, skb); 59862306a36Sopenharmony_ci break; 59962306a36Sopenharmony_ci case ST21NFCA_NFC_DEP_PFB_SUPERVISOR_PDU: 60062306a36Sopenharmony_ci pr_err("Received a SUPERVISOR PDU\n"); 60162306a36Sopenharmony_ci skb_pull(skb, size); 60262306a36Sopenharmony_ci *(u8 *)skb_push(skb, 1) = ST21NFCA_NFCIP1_DEP_REQ; 60362306a36Sopenharmony_ci *(u8 *)skb_push(skb, 1) = ST21NFCA_NFCIP1_REQ; 60462306a36Sopenharmony_ci *(u8 *)skb_push(skb, 1) = skb->len; 60562306a36Sopenharmony_ci *(u8 *)skb_push(skb, 1) = info->dep_info.to | 0x10; 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci st21nfca_im_send_pdu(info, skb); 60862306a36Sopenharmony_ci break; 60962306a36Sopenharmony_ci } 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci return; 61262306a36Sopenharmony_ci default: 61362306a36Sopenharmony_ci break; 61462306a36Sopenharmony_ci } 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ciexit: 61762306a36Sopenharmony_ci kfree_skb(skb); 61862306a36Sopenharmony_ci} 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_ciint st21nfca_im_send_dep_req(struct nfc_hci_dev *hdev, struct sk_buff *skb) 62162306a36Sopenharmony_ci{ 62262306a36Sopenharmony_ci struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_ci info->async_cb_type = ST21NFCA_CB_TYPE_READER_F; 62562306a36Sopenharmony_ci info->async_cb_context = info; 62662306a36Sopenharmony_ci info->async_cb = st21nfca_im_recv_dep_res_cb; 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci *(u8 *)skb_push(skb, 1) = info->dep_info.curr_nfc_dep_pni; 62962306a36Sopenharmony_ci *(u8 *)skb_push(skb, 1) = ST21NFCA_NFCIP1_DEP_REQ; 63062306a36Sopenharmony_ci *(u8 *)skb_push(skb, 1) = ST21NFCA_NFCIP1_REQ; 63162306a36Sopenharmony_ci *(u8 *)skb_push(skb, 1) = skb->len; 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci *(u8 *)skb_push(skb, 1) = info->dep_info.to | 0x10; 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci return nfc_hci_send_cmd_async(hdev, ST21NFCA_RF_READER_F_GATE, 63662306a36Sopenharmony_ci ST21NFCA_WR_XCHG_DATA, 63762306a36Sopenharmony_ci skb->data, skb->len, 63862306a36Sopenharmony_ci info->async_cb, info); 63962306a36Sopenharmony_ci} 64062306a36Sopenharmony_ciEXPORT_SYMBOL(st21nfca_im_send_dep_req); 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_civoid st21nfca_dep_init(struct nfc_hci_dev *hdev) 64362306a36Sopenharmony_ci{ 64462306a36Sopenharmony_ci struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ci INIT_WORK(&info->dep_info.tx_work, st21nfca_tx_work); 64762306a36Sopenharmony_ci info->dep_info.curr_nfc_dep_pni = 0; 64862306a36Sopenharmony_ci info->dep_info.idx = 0; 64962306a36Sopenharmony_ci info->dep_info.to = ST21NFCA_DEFAULT_TIMEOUT; 65062306a36Sopenharmony_ci} 65162306a36Sopenharmony_ciEXPORT_SYMBOL(st21nfca_dep_init); 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_civoid st21nfca_dep_deinit(struct nfc_hci_dev *hdev) 65462306a36Sopenharmony_ci{ 65562306a36Sopenharmony_ci struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ci cancel_work_sync(&info->dep_info.tx_work); 65862306a36Sopenharmony_ci} 65962306a36Sopenharmony_ciEXPORT_SYMBOL(st21nfca_dep_deinit); 660