18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <net/nfc/hci.h> 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include "st21nfca.h" 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#define ST21NFCA_NFCIP1_INITIATOR 0x00 118c2ecf20Sopenharmony_ci#define ST21NFCA_NFCIP1_REQ 0xd4 128c2ecf20Sopenharmony_ci#define ST21NFCA_NFCIP1_RES 0xd5 138c2ecf20Sopenharmony_ci#define ST21NFCA_NFCIP1_ATR_REQ 0x00 148c2ecf20Sopenharmony_ci#define ST21NFCA_NFCIP1_ATR_RES 0x01 158c2ecf20Sopenharmony_ci#define ST21NFCA_NFCIP1_PSL_REQ 0x04 168c2ecf20Sopenharmony_ci#define ST21NFCA_NFCIP1_PSL_RES 0x05 178c2ecf20Sopenharmony_ci#define ST21NFCA_NFCIP1_DEP_REQ 0x06 188c2ecf20Sopenharmony_ci#define ST21NFCA_NFCIP1_DEP_RES 0x07 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#define ST21NFCA_NFC_DEP_PFB_PNI(pfb) ((pfb) & 0x03) 218c2ecf20Sopenharmony_ci#define ST21NFCA_NFC_DEP_PFB_TYPE(pfb) ((pfb) & 0xE0) 228c2ecf20Sopenharmony_ci#define ST21NFCA_NFC_DEP_PFB_IS_TIMEOUT(pfb) \ 238c2ecf20Sopenharmony_ci ((pfb) & ST21NFCA_NFC_DEP_PFB_TIMEOUT_BIT) 248c2ecf20Sopenharmony_ci#define ST21NFCA_NFC_DEP_DID_BIT_SET(pfb) ((pfb) & 0x04) 258c2ecf20Sopenharmony_ci#define ST21NFCA_NFC_DEP_NAD_BIT_SET(pfb) ((pfb) & 0x08) 268c2ecf20Sopenharmony_ci#define ST21NFCA_NFC_DEP_PFB_TIMEOUT_BIT 0x10 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#define ST21NFCA_NFC_DEP_PFB_IS_TIMEOUT(pfb) \ 298c2ecf20Sopenharmony_ci ((pfb) & ST21NFCA_NFC_DEP_PFB_TIMEOUT_BIT) 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci#define ST21NFCA_NFC_DEP_PFB_I_PDU 0x00 328c2ecf20Sopenharmony_ci#define ST21NFCA_NFC_DEP_PFB_ACK_NACK_PDU 0x40 338c2ecf20Sopenharmony_ci#define ST21NFCA_NFC_DEP_PFB_SUPERVISOR_PDU 0x80 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#define ST21NFCA_ATR_REQ_MIN_SIZE 17 368c2ecf20Sopenharmony_ci#define ST21NFCA_ATR_REQ_MAX_SIZE 65 378c2ecf20Sopenharmony_ci#define ST21NFCA_LR_BITS_PAYLOAD_SIZE_254B 0x30 388c2ecf20Sopenharmony_ci#define ST21NFCA_GB_BIT 0x02 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci#define ST21NFCA_EVT_SEND_DATA 0x10 418c2ecf20Sopenharmony_ci#define ST21NFCA_EVT_FIELD_ON 0x11 428c2ecf20Sopenharmony_ci#define ST21NFCA_EVT_CARD_DEACTIVATED 0x12 438c2ecf20Sopenharmony_ci#define ST21NFCA_EVT_CARD_ACTIVATED 0x13 448c2ecf20Sopenharmony_ci#define ST21NFCA_EVT_FIELD_OFF 0x14 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci#define ST21NFCA_EVT_CARD_F_BITRATE 0x16 478c2ecf20Sopenharmony_ci#define ST21NFCA_EVT_READER_F_BITRATE 0x13 488c2ecf20Sopenharmony_ci#define ST21NFCA_PSL_REQ_SEND_SPEED(brs) (brs & 0x38) 498c2ecf20Sopenharmony_ci#define ST21NFCA_PSL_REQ_RECV_SPEED(brs) (brs & 0x07) 508c2ecf20Sopenharmony_ci#define ST21NFCA_PP2LRI(pp) ((pp & 0x30) >> 4) 518c2ecf20Sopenharmony_ci#define ST21NFCA_CARD_BITRATE_212 0x01 528c2ecf20Sopenharmony_ci#define ST21NFCA_CARD_BITRATE_424 0x02 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci#define ST21NFCA_DEFAULT_TIMEOUT 0x0a 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci#define PROTOCOL_ERR(req) pr_err("%d: ST21NFCA Protocol error: %s\n", \ 588c2ecf20Sopenharmony_ci __LINE__, req) 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_cistruct st21nfca_atr_req { 618c2ecf20Sopenharmony_ci u8 length; 628c2ecf20Sopenharmony_ci u8 cmd0; 638c2ecf20Sopenharmony_ci u8 cmd1; 648c2ecf20Sopenharmony_ci u8 nfcid3[NFC_NFCID3_MAXSIZE]; 658c2ecf20Sopenharmony_ci u8 did; 668c2ecf20Sopenharmony_ci u8 bsi; 678c2ecf20Sopenharmony_ci u8 bri; 688c2ecf20Sopenharmony_ci u8 ppi; 698c2ecf20Sopenharmony_ci u8 gbi[]; 708c2ecf20Sopenharmony_ci} __packed; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_cistruct st21nfca_atr_res { 738c2ecf20Sopenharmony_ci u8 length; 748c2ecf20Sopenharmony_ci u8 cmd0; 758c2ecf20Sopenharmony_ci u8 cmd1; 768c2ecf20Sopenharmony_ci u8 nfcid3[NFC_NFCID3_MAXSIZE]; 778c2ecf20Sopenharmony_ci u8 did; 788c2ecf20Sopenharmony_ci u8 bsi; 798c2ecf20Sopenharmony_ci u8 bri; 808c2ecf20Sopenharmony_ci u8 to; 818c2ecf20Sopenharmony_ci u8 ppi; 828c2ecf20Sopenharmony_ci u8 gbi[]; 838c2ecf20Sopenharmony_ci} __packed; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_cistruct st21nfca_psl_req { 868c2ecf20Sopenharmony_ci u8 length; 878c2ecf20Sopenharmony_ci u8 cmd0; 888c2ecf20Sopenharmony_ci u8 cmd1; 898c2ecf20Sopenharmony_ci u8 did; 908c2ecf20Sopenharmony_ci u8 brs; 918c2ecf20Sopenharmony_ci u8 fsl; 928c2ecf20Sopenharmony_ci} __packed; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_cistruct st21nfca_psl_res { 958c2ecf20Sopenharmony_ci u8 length; 968c2ecf20Sopenharmony_ci u8 cmd0; 978c2ecf20Sopenharmony_ci u8 cmd1; 988c2ecf20Sopenharmony_ci u8 did; 998c2ecf20Sopenharmony_ci} __packed; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_cistruct st21nfca_dep_req_res { 1028c2ecf20Sopenharmony_ci u8 length; 1038c2ecf20Sopenharmony_ci u8 cmd0; 1048c2ecf20Sopenharmony_ci u8 cmd1; 1058c2ecf20Sopenharmony_ci u8 pfb; 1068c2ecf20Sopenharmony_ci u8 did; 1078c2ecf20Sopenharmony_ci u8 nad; 1088c2ecf20Sopenharmony_ci} __packed; 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_cistatic void st21nfca_tx_work(struct work_struct *work) 1118c2ecf20Sopenharmony_ci{ 1128c2ecf20Sopenharmony_ci struct st21nfca_hci_info *info = container_of(work, 1138c2ecf20Sopenharmony_ci struct st21nfca_hci_info, 1148c2ecf20Sopenharmony_ci dep_info.tx_work); 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci struct nfc_dev *dev; 1178c2ecf20Sopenharmony_ci struct sk_buff *skb; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci if (info) { 1208c2ecf20Sopenharmony_ci dev = info->hdev->ndev; 1218c2ecf20Sopenharmony_ci skb = info->dep_info.tx_pending; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci device_lock(&dev->dev); 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci nfc_hci_send_cmd_async(info->hdev, ST21NFCA_RF_READER_F_GATE, 1268c2ecf20Sopenharmony_ci ST21NFCA_WR_XCHG_DATA, skb->data, skb->len, 1278c2ecf20Sopenharmony_ci info->async_cb, info); 1288c2ecf20Sopenharmony_ci device_unlock(&dev->dev); 1298c2ecf20Sopenharmony_ci kfree_skb(skb); 1308c2ecf20Sopenharmony_ci } 1318c2ecf20Sopenharmony_ci} 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_cistatic void st21nfca_im_send_pdu(struct st21nfca_hci_info *info, 1348c2ecf20Sopenharmony_ci struct sk_buff *skb) 1358c2ecf20Sopenharmony_ci{ 1368c2ecf20Sopenharmony_ci info->dep_info.tx_pending = skb; 1378c2ecf20Sopenharmony_ci schedule_work(&info->dep_info.tx_work); 1388c2ecf20Sopenharmony_ci} 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_cistatic int st21nfca_tm_send_atr_res(struct nfc_hci_dev *hdev, 1418c2ecf20Sopenharmony_ci struct st21nfca_atr_req *atr_req) 1428c2ecf20Sopenharmony_ci{ 1438c2ecf20Sopenharmony_ci struct st21nfca_atr_res *atr_res; 1448c2ecf20Sopenharmony_ci struct sk_buff *skb; 1458c2ecf20Sopenharmony_ci size_t gb_len; 1468c2ecf20Sopenharmony_ci int r; 1478c2ecf20Sopenharmony_ci struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci gb_len = atr_req->length - sizeof(struct st21nfca_atr_req); 1508c2ecf20Sopenharmony_ci skb = alloc_skb(atr_req->length + 1, GFP_KERNEL); 1518c2ecf20Sopenharmony_ci if (!skb) 1528c2ecf20Sopenharmony_ci return -ENOMEM; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci skb_put(skb, sizeof(struct st21nfca_atr_res)); 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci atr_res = (struct st21nfca_atr_res *)skb->data; 1578c2ecf20Sopenharmony_ci memset(atr_res, 0, sizeof(struct st21nfca_atr_res)); 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci atr_res->length = atr_req->length + 1; 1608c2ecf20Sopenharmony_ci atr_res->cmd0 = ST21NFCA_NFCIP1_RES; 1618c2ecf20Sopenharmony_ci atr_res->cmd1 = ST21NFCA_NFCIP1_ATR_RES; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci memcpy(atr_res->nfcid3, atr_req->nfcid3, 6); 1648c2ecf20Sopenharmony_ci atr_res->bsi = 0x00; 1658c2ecf20Sopenharmony_ci atr_res->bri = 0x00; 1668c2ecf20Sopenharmony_ci atr_res->to = ST21NFCA_DEFAULT_TIMEOUT; 1678c2ecf20Sopenharmony_ci atr_res->ppi = ST21NFCA_LR_BITS_PAYLOAD_SIZE_254B; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci if (gb_len) { 1708c2ecf20Sopenharmony_ci skb_put(skb, gb_len); 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci atr_res->ppi |= ST21NFCA_GB_BIT; 1738c2ecf20Sopenharmony_ci memcpy(atr_res->gbi, atr_req->gbi, gb_len); 1748c2ecf20Sopenharmony_ci r = nfc_set_remote_general_bytes(hdev->ndev, atr_res->gbi, 1758c2ecf20Sopenharmony_ci gb_len); 1768c2ecf20Sopenharmony_ci if (r < 0) { 1778c2ecf20Sopenharmony_ci kfree_skb(skb); 1788c2ecf20Sopenharmony_ci return r; 1798c2ecf20Sopenharmony_ci } 1808c2ecf20Sopenharmony_ci } 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci info->dep_info.curr_nfc_dep_pni = 0; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE, 1858c2ecf20Sopenharmony_ci ST21NFCA_EVT_SEND_DATA, skb->data, skb->len); 1868c2ecf20Sopenharmony_ci kfree_skb(skb); 1878c2ecf20Sopenharmony_ci return r; 1888c2ecf20Sopenharmony_ci} 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_cistatic int st21nfca_tm_recv_atr_req(struct nfc_hci_dev *hdev, 1918c2ecf20Sopenharmony_ci struct sk_buff *skb) 1928c2ecf20Sopenharmony_ci{ 1938c2ecf20Sopenharmony_ci struct st21nfca_atr_req *atr_req; 1948c2ecf20Sopenharmony_ci size_t gb_len; 1958c2ecf20Sopenharmony_ci int r; 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci skb_trim(skb, skb->len - 1); 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci if (!skb->len) { 2008c2ecf20Sopenharmony_ci r = -EIO; 2018c2ecf20Sopenharmony_ci goto exit; 2028c2ecf20Sopenharmony_ci } 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci if (skb->len < ST21NFCA_ATR_REQ_MIN_SIZE) { 2058c2ecf20Sopenharmony_ci r = -EPROTO; 2068c2ecf20Sopenharmony_ci goto exit; 2078c2ecf20Sopenharmony_ci } 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci atr_req = (struct st21nfca_atr_req *)skb->data; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci if (atr_req->length < sizeof(struct st21nfca_atr_req)) { 2128c2ecf20Sopenharmony_ci r = -EPROTO; 2138c2ecf20Sopenharmony_ci goto exit; 2148c2ecf20Sopenharmony_ci } 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci r = st21nfca_tm_send_atr_res(hdev, atr_req); 2178c2ecf20Sopenharmony_ci if (r) 2188c2ecf20Sopenharmony_ci goto exit; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci gb_len = skb->len - sizeof(struct st21nfca_atr_req); 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci r = nfc_tm_activated(hdev->ndev, NFC_PROTO_NFC_DEP_MASK, 2238c2ecf20Sopenharmony_ci NFC_COMM_PASSIVE, atr_req->gbi, gb_len); 2248c2ecf20Sopenharmony_ci if (r) 2258c2ecf20Sopenharmony_ci goto exit; 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci r = 0; 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ciexit: 2308c2ecf20Sopenharmony_ci return r; 2318c2ecf20Sopenharmony_ci} 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_cistatic int st21nfca_tm_send_psl_res(struct nfc_hci_dev *hdev, 2348c2ecf20Sopenharmony_ci struct st21nfca_psl_req *psl_req) 2358c2ecf20Sopenharmony_ci{ 2368c2ecf20Sopenharmony_ci struct st21nfca_psl_res *psl_res; 2378c2ecf20Sopenharmony_ci struct sk_buff *skb; 2388c2ecf20Sopenharmony_ci u8 bitrate[2] = {0, 0}; 2398c2ecf20Sopenharmony_ci int r; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci skb = alloc_skb(sizeof(struct st21nfca_psl_res), GFP_KERNEL); 2428c2ecf20Sopenharmony_ci if (!skb) 2438c2ecf20Sopenharmony_ci return -ENOMEM; 2448c2ecf20Sopenharmony_ci skb_put(skb, sizeof(struct st21nfca_psl_res)); 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci psl_res = (struct st21nfca_psl_res *)skb->data; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci psl_res->length = sizeof(struct st21nfca_psl_res); 2498c2ecf20Sopenharmony_ci psl_res->cmd0 = ST21NFCA_NFCIP1_RES; 2508c2ecf20Sopenharmony_ci psl_res->cmd1 = ST21NFCA_NFCIP1_PSL_RES; 2518c2ecf20Sopenharmony_ci psl_res->did = psl_req->did; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE, 2548c2ecf20Sopenharmony_ci ST21NFCA_EVT_SEND_DATA, skb->data, skb->len); 2558c2ecf20Sopenharmony_ci if (r < 0) 2568c2ecf20Sopenharmony_ci goto error; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci /* 2598c2ecf20Sopenharmony_ci * ST21NFCA only support P2P passive. 2608c2ecf20Sopenharmony_ci * PSL_REQ BRS value != 0 has only a meaning to 2618c2ecf20Sopenharmony_ci * change technology to type F. 2628c2ecf20Sopenharmony_ci * We change to BITRATE 424Kbits. 2638c2ecf20Sopenharmony_ci * In other case switch to BITRATE 106Kbits. 2648c2ecf20Sopenharmony_ci */ 2658c2ecf20Sopenharmony_ci if (ST21NFCA_PSL_REQ_SEND_SPEED(psl_req->brs) && 2668c2ecf20Sopenharmony_ci ST21NFCA_PSL_REQ_RECV_SPEED(psl_req->brs)) { 2678c2ecf20Sopenharmony_ci bitrate[0] = ST21NFCA_CARD_BITRATE_424; 2688c2ecf20Sopenharmony_ci bitrate[1] = ST21NFCA_CARD_BITRATE_424; 2698c2ecf20Sopenharmony_ci } 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci /* Send an event to change bitrate change event to card f */ 2728c2ecf20Sopenharmony_ci r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE, 2738c2ecf20Sopenharmony_ci ST21NFCA_EVT_CARD_F_BITRATE, bitrate, 2); 2748c2ecf20Sopenharmony_cierror: 2758c2ecf20Sopenharmony_ci kfree_skb(skb); 2768c2ecf20Sopenharmony_ci return r; 2778c2ecf20Sopenharmony_ci} 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_cistatic int st21nfca_tm_recv_psl_req(struct nfc_hci_dev *hdev, 2808c2ecf20Sopenharmony_ci struct sk_buff *skb) 2818c2ecf20Sopenharmony_ci{ 2828c2ecf20Sopenharmony_ci struct st21nfca_psl_req *psl_req; 2838c2ecf20Sopenharmony_ci int r; 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci skb_trim(skb, skb->len - 1); 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci if (!skb->len) { 2888c2ecf20Sopenharmony_ci r = -EIO; 2898c2ecf20Sopenharmony_ci goto exit; 2908c2ecf20Sopenharmony_ci } 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci psl_req = (struct st21nfca_psl_req *)skb->data; 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci if (skb->len < sizeof(struct st21nfca_psl_req)) { 2958c2ecf20Sopenharmony_ci r = -EIO; 2968c2ecf20Sopenharmony_ci goto exit; 2978c2ecf20Sopenharmony_ci } 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci r = st21nfca_tm_send_psl_res(hdev, psl_req); 3008c2ecf20Sopenharmony_ciexit: 3018c2ecf20Sopenharmony_ci return r; 3028c2ecf20Sopenharmony_ci} 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ciint st21nfca_tm_send_dep_res(struct nfc_hci_dev *hdev, struct sk_buff *skb) 3058c2ecf20Sopenharmony_ci{ 3068c2ecf20Sopenharmony_ci int r; 3078c2ecf20Sopenharmony_ci struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci *(u8 *)skb_push(skb, 1) = info->dep_info.curr_nfc_dep_pni; 3108c2ecf20Sopenharmony_ci *(u8 *)skb_push(skb, 1) = ST21NFCA_NFCIP1_DEP_RES; 3118c2ecf20Sopenharmony_ci *(u8 *)skb_push(skb, 1) = ST21NFCA_NFCIP1_RES; 3128c2ecf20Sopenharmony_ci *(u8 *)skb_push(skb, 1) = skb->len; 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci r = nfc_hci_send_event(hdev, ST21NFCA_RF_CARD_F_GATE, 3158c2ecf20Sopenharmony_ci ST21NFCA_EVT_SEND_DATA, skb->data, skb->len); 3168c2ecf20Sopenharmony_ci kfree_skb(skb); 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci return r; 3198c2ecf20Sopenharmony_ci} 3208c2ecf20Sopenharmony_ciEXPORT_SYMBOL(st21nfca_tm_send_dep_res); 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_cistatic int st21nfca_tm_recv_dep_req(struct nfc_hci_dev *hdev, 3238c2ecf20Sopenharmony_ci struct sk_buff *skb) 3248c2ecf20Sopenharmony_ci{ 3258c2ecf20Sopenharmony_ci struct st21nfca_dep_req_res *dep_req; 3268c2ecf20Sopenharmony_ci u8 size; 3278c2ecf20Sopenharmony_ci int r; 3288c2ecf20Sopenharmony_ci struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci skb_trim(skb, skb->len - 1); 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci size = 4; 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci dep_req = (struct st21nfca_dep_req_res *)skb->data; 3358c2ecf20Sopenharmony_ci if (skb->len < size) { 3368c2ecf20Sopenharmony_ci r = -EIO; 3378c2ecf20Sopenharmony_ci goto exit; 3388c2ecf20Sopenharmony_ci } 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci if (ST21NFCA_NFC_DEP_DID_BIT_SET(dep_req->pfb)) 3418c2ecf20Sopenharmony_ci size++; 3428c2ecf20Sopenharmony_ci if (ST21NFCA_NFC_DEP_NAD_BIT_SET(dep_req->pfb)) 3438c2ecf20Sopenharmony_ci size++; 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci if (skb->len < size) { 3468c2ecf20Sopenharmony_ci r = -EIO; 3478c2ecf20Sopenharmony_ci goto exit; 3488c2ecf20Sopenharmony_ci } 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci /* Receiving DEP_REQ - Decoding */ 3518c2ecf20Sopenharmony_ci switch (ST21NFCA_NFC_DEP_PFB_TYPE(dep_req->pfb)) { 3528c2ecf20Sopenharmony_ci case ST21NFCA_NFC_DEP_PFB_I_PDU: 3538c2ecf20Sopenharmony_ci info->dep_info.curr_nfc_dep_pni = 3548c2ecf20Sopenharmony_ci ST21NFCA_NFC_DEP_PFB_PNI(dep_req->pfb); 3558c2ecf20Sopenharmony_ci break; 3568c2ecf20Sopenharmony_ci case ST21NFCA_NFC_DEP_PFB_ACK_NACK_PDU: 3578c2ecf20Sopenharmony_ci pr_err("Received a ACK/NACK PDU\n"); 3588c2ecf20Sopenharmony_ci break; 3598c2ecf20Sopenharmony_ci case ST21NFCA_NFC_DEP_PFB_SUPERVISOR_PDU: 3608c2ecf20Sopenharmony_ci pr_err("Received a SUPERVISOR PDU\n"); 3618c2ecf20Sopenharmony_ci break; 3628c2ecf20Sopenharmony_ci } 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci skb_pull(skb, size); 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci return nfc_tm_data_received(hdev->ndev, skb); 3678c2ecf20Sopenharmony_ciexit: 3688c2ecf20Sopenharmony_ci return r; 3698c2ecf20Sopenharmony_ci} 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_cistatic int st21nfca_tm_event_send_data(struct nfc_hci_dev *hdev, 3728c2ecf20Sopenharmony_ci struct sk_buff *skb) 3738c2ecf20Sopenharmony_ci{ 3748c2ecf20Sopenharmony_ci u8 cmd0, cmd1; 3758c2ecf20Sopenharmony_ci int r; 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci cmd0 = skb->data[1]; 3788c2ecf20Sopenharmony_ci switch (cmd0) { 3798c2ecf20Sopenharmony_ci case ST21NFCA_NFCIP1_REQ: 3808c2ecf20Sopenharmony_ci cmd1 = skb->data[2]; 3818c2ecf20Sopenharmony_ci switch (cmd1) { 3828c2ecf20Sopenharmony_ci case ST21NFCA_NFCIP1_ATR_REQ: 3838c2ecf20Sopenharmony_ci r = st21nfca_tm_recv_atr_req(hdev, skb); 3848c2ecf20Sopenharmony_ci break; 3858c2ecf20Sopenharmony_ci case ST21NFCA_NFCIP1_PSL_REQ: 3868c2ecf20Sopenharmony_ci r = st21nfca_tm_recv_psl_req(hdev, skb); 3878c2ecf20Sopenharmony_ci break; 3888c2ecf20Sopenharmony_ci case ST21NFCA_NFCIP1_DEP_REQ: 3898c2ecf20Sopenharmony_ci r = st21nfca_tm_recv_dep_req(hdev, skb); 3908c2ecf20Sopenharmony_ci break; 3918c2ecf20Sopenharmony_ci default: 3928c2ecf20Sopenharmony_ci return 1; 3938c2ecf20Sopenharmony_ci } 3948c2ecf20Sopenharmony_ci break; 3958c2ecf20Sopenharmony_ci default: 3968c2ecf20Sopenharmony_ci return 1; 3978c2ecf20Sopenharmony_ci } 3988c2ecf20Sopenharmony_ci return r; 3998c2ecf20Sopenharmony_ci} 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci/* 4028c2ecf20Sopenharmony_ci * Returns: 4038c2ecf20Sopenharmony_ci * <= 0: driver handled the event, skb consumed 4048c2ecf20Sopenharmony_ci * 1: driver does not handle the event, please do standard processing 4058c2ecf20Sopenharmony_ci */ 4068c2ecf20Sopenharmony_ciint st21nfca_dep_event_received(struct nfc_hci_dev *hdev, 4078c2ecf20Sopenharmony_ci u8 event, struct sk_buff *skb) 4088c2ecf20Sopenharmony_ci{ 4098c2ecf20Sopenharmony_ci int r = 0; 4108c2ecf20Sopenharmony_ci struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci pr_debug("dep event: %d\n", event); 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci switch (event) { 4158c2ecf20Sopenharmony_ci case ST21NFCA_EVT_CARD_ACTIVATED: 4168c2ecf20Sopenharmony_ci info->dep_info.curr_nfc_dep_pni = 0; 4178c2ecf20Sopenharmony_ci break; 4188c2ecf20Sopenharmony_ci case ST21NFCA_EVT_CARD_DEACTIVATED: 4198c2ecf20Sopenharmony_ci break; 4208c2ecf20Sopenharmony_ci case ST21NFCA_EVT_FIELD_ON: 4218c2ecf20Sopenharmony_ci break; 4228c2ecf20Sopenharmony_ci case ST21NFCA_EVT_FIELD_OFF: 4238c2ecf20Sopenharmony_ci break; 4248c2ecf20Sopenharmony_ci case ST21NFCA_EVT_SEND_DATA: 4258c2ecf20Sopenharmony_ci r = st21nfca_tm_event_send_data(hdev, skb); 4268c2ecf20Sopenharmony_ci if (r < 0) 4278c2ecf20Sopenharmony_ci return r; 4288c2ecf20Sopenharmony_ci return 0; 4298c2ecf20Sopenharmony_ci default: 4308c2ecf20Sopenharmony_ci nfc_err(&hdev->ndev->dev, "Unexpected event on card f gate\n"); 4318c2ecf20Sopenharmony_ci return 1; 4328c2ecf20Sopenharmony_ci } 4338c2ecf20Sopenharmony_ci kfree_skb(skb); 4348c2ecf20Sopenharmony_ci return r; 4358c2ecf20Sopenharmony_ci} 4368c2ecf20Sopenharmony_ciEXPORT_SYMBOL(st21nfca_dep_event_received); 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_cistatic void st21nfca_im_send_psl_req(struct nfc_hci_dev *hdev, u8 did, u8 bsi, 4398c2ecf20Sopenharmony_ci u8 bri, u8 lri) 4408c2ecf20Sopenharmony_ci{ 4418c2ecf20Sopenharmony_ci struct sk_buff *skb; 4428c2ecf20Sopenharmony_ci struct st21nfca_psl_req *psl_req; 4438c2ecf20Sopenharmony_ci struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci skb = 4468c2ecf20Sopenharmony_ci alloc_skb(sizeof(struct st21nfca_psl_req) + 1, GFP_KERNEL); 4478c2ecf20Sopenharmony_ci if (!skb) 4488c2ecf20Sopenharmony_ci return; 4498c2ecf20Sopenharmony_ci skb_reserve(skb, 1); 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ci skb_put(skb, sizeof(struct st21nfca_psl_req)); 4528c2ecf20Sopenharmony_ci psl_req = (struct st21nfca_psl_req *) skb->data; 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci psl_req->length = sizeof(struct st21nfca_psl_req); 4558c2ecf20Sopenharmony_ci psl_req->cmd0 = ST21NFCA_NFCIP1_REQ; 4568c2ecf20Sopenharmony_ci psl_req->cmd1 = ST21NFCA_NFCIP1_PSL_REQ; 4578c2ecf20Sopenharmony_ci psl_req->did = did; 4588c2ecf20Sopenharmony_ci psl_req->brs = (0x30 & bsi << 4) | (bri & 0x03); 4598c2ecf20Sopenharmony_ci psl_req->fsl = lri; 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci *(u8 *)skb_push(skb, 1) = info->dep_info.to | 0x10; 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci st21nfca_im_send_pdu(info, skb); 4648c2ecf20Sopenharmony_ci} 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci#define ST21NFCA_CB_TYPE_READER_F 1 4678c2ecf20Sopenharmony_cistatic void st21nfca_im_recv_atr_res_cb(void *context, struct sk_buff *skb, 4688c2ecf20Sopenharmony_ci int err) 4698c2ecf20Sopenharmony_ci{ 4708c2ecf20Sopenharmony_ci struct st21nfca_hci_info *info = context; 4718c2ecf20Sopenharmony_ci struct st21nfca_atr_res *atr_res; 4728c2ecf20Sopenharmony_ci int r; 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci if (err != 0) 4758c2ecf20Sopenharmony_ci return; 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci if (!skb) 4788c2ecf20Sopenharmony_ci return; 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci switch (info->async_cb_type) { 4818c2ecf20Sopenharmony_ci case ST21NFCA_CB_TYPE_READER_F: 4828c2ecf20Sopenharmony_ci skb_trim(skb, skb->len - 1); 4838c2ecf20Sopenharmony_ci atr_res = (struct st21nfca_atr_res *)skb->data; 4848c2ecf20Sopenharmony_ci r = nfc_set_remote_general_bytes(info->hdev->ndev, 4858c2ecf20Sopenharmony_ci atr_res->gbi, 4868c2ecf20Sopenharmony_ci skb->len - sizeof(struct st21nfca_atr_res)); 4878c2ecf20Sopenharmony_ci if (r < 0) 4888c2ecf20Sopenharmony_ci return; 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci if (atr_res->to >= 0x0e) 4918c2ecf20Sopenharmony_ci info->dep_info.to = 0x0e; 4928c2ecf20Sopenharmony_ci else 4938c2ecf20Sopenharmony_ci info->dep_info.to = atr_res->to + 1; 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci info->dep_info.to |= 0x10; 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci r = nfc_dep_link_is_up(info->hdev->ndev, info->dep_info.idx, 4988c2ecf20Sopenharmony_ci NFC_COMM_PASSIVE, NFC_RF_INITIATOR); 4998c2ecf20Sopenharmony_ci if (r < 0) 5008c2ecf20Sopenharmony_ci return; 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ci info->dep_info.curr_nfc_dep_pni = 0; 5038c2ecf20Sopenharmony_ci if (ST21NFCA_PP2LRI(atr_res->ppi) != info->dep_info.lri) 5048c2ecf20Sopenharmony_ci st21nfca_im_send_psl_req(info->hdev, atr_res->did, 5058c2ecf20Sopenharmony_ci atr_res->bsi, atr_res->bri, 5068c2ecf20Sopenharmony_ci ST21NFCA_PP2LRI(atr_res->ppi)); 5078c2ecf20Sopenharmony_ci break; 5088c2ecf20Sopenharmony_ci default: 5098c2ecf20Sopenharmony_ci kfree_skb(skb); 5108c2ecf20Sopenharmony_ci break; 5118c2ecf20Sopenharmony_ci } 5128c2ecf20Sopenharmony_ci} 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ciint st21nfca_im_send_atr_req(struct nfc_hci_dev *hdev, u8 *gb, size_t gb_len) 5158c2ecf20Sopenharmony_ci{ 5168c2ecf20Sopenharmony_ci struct sk_buff *skb; 5178c2ecf20Sopenharmony_ci struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); 5188c2ecf20Sopenharmony_ci struct st21nfca_atr_req *atr_req; 5198c2ecf20Sopenharmony_ci struct nfc_target *target; 5208c2ecf20Sopenharmony_ci uint size; 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci info->dep_info.to = ST21NFCA_DEFAULT_TIMEOUT; 5238c2ecf20Sopenharmony_ci size = ST21NFCA_ATR_REQ_MIN_SIZE + gb_len; 5248c2ecf20Sopenharmony_ci if (size > ST21NFCA_ATR_REQ_MAX_SIZE) { 5258c2ecf20Sopenharmony_ci PROTOCOL_ERR("14.6.1.1"); 5268c2ecf20Sopenharmony_ci return -EINVAL; 5278c2ecf20Sopenharmony_ci } 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci skb = 5308c2ecf20Sopenharmony_ci alloc_skb(sizeof(struct st21nfca_atr_req) + gb_len + 1, GFP_KERNEL); 5318c2ecf20Sopenharmony_ci if (!skb) 5328c2ecf20Sopenharmony_ci return -ENOMEM; 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci skb_reserve(skb, 1); 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci skb_put(skb, sizeof(struct st21nfca_atr_req)); 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci atr_req = (struct st21nfca_atr_req *)skb->data; 5398c2ecf20Sopenharmony_ci memset(atr_req, 0, sizeof(struct st21nfca_atr_req)); 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci atr_req->cmd0 = ST21NFCA_NFCIP1_REQ; 5428c2ecf20Sopenharmony_ci atr_req->cmd1 = ST21NFCA_NFCIP1_ATR_REQ; 5438c2ecf20Sopenharmony_ci memset(atr_req->nfcid3, 0, NFC_NFCID3_MAXSIZE); 5448c2ecf20Sopenharmony_ci target = hdev->ndev->targets; 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ci if (target->sensf_res_len > 0) 5478c2ecf20Sopenharmony_ci memcpy(atr_req->nfcid3, target->sensf_res, 5488c2ecf20Sopenharmony_ci target->sensf_res_len); 5498c2ecf20Sopenharmony_ci else 5508c2ecf20Sopenharmony_ci get_random_bytes(atr_req->nfcid3, NFC_NFCID3_MAXSIZE); 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci atr_req->did = 0x0; 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci atr_req->bsi = 0x00; 5558c2ecf20Sopenharmony_ci atr_req->bri = 0x00; 5568c2ecf20Sopenharmony_ci atr_req->ppi = ST21NFCA_LR_BITS_PAYLOAD_SIZE_254B; 5578c2ecf20Sopenharmony_ci if (gb_len) { 5588c2ecf20Sopenharmony_ci atr_req->ppi |= ST21NFCA_GB_BIT; 5598c2ecf20Sopenharmony_ci skb_put_data(skb, gb, gb_len); 5608c2ecf20Sopenharmony_ci } 5618c2ecf20Sopenharmony_ci atr_req->length = sizeof(struct st21nfca_atr_req) + hdev->gb_len; 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci *(u8 *)skb_push(skb, 1) = info->dep_info.to | 0x10; /* timeout */ 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci info->async_cb_type = ST21NFCA_CB_TYPE_READER_F; 5668c2ecf20Sopenharmony_ci info->async_cb_context = info; 5678c2ecf20Sopenharmony_ci info->async_cb = st21nfca_im_recv_atr_res_cb; 5688c2ecf20Sopenharmony_ci info->dep_info.bri = atr_req->bri; 5698c2ecf20Sopenharmony_ci info->dep_info.bsi = atr_req->bsi; 5708c2ecf20Sopenharmony_ci info->dep_info.lri = ST21NFCA_PP2LRI(atr_req->ppi); 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci return nfc_hci_send_cmd_async(hdev, ST21NFCA_RF_READER_F_GATE, 5738c2ecf20Sopenharmony_ci ST21NFCA_WR_XCHG_DATA, skb->data, 5748c2ecf20Sopenharmony_ci skb->len, info->async_cb, info); 5758c2ecf20Sopenharmony_ci} 5768c2ecf20Sopenharmony_ciEXPORT_SYMBOL(st21nfca_im_send_atr_req); 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_cistatic void st21nfca_im_recv_dep_res_cb(void *context, struct sk_buff *skb, 5798c2ecf20Sopenharmony_ci int err) 5808c2ecf20Sopenharmony_ci{ 5818c2ecf20Sopenharmony_ci struct st21nfca_hci_info *info = context; 5828c2ecf20Sopenharmony_ci struct st21nfca_dep_req_res *dep_res; 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci int size; 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ci if (err != 0) 5878c2ecf20Sopenharmony_ci return; 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_ci if (!skb) 5908c2ecf20Sopenharmony_ci return; 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_ci switch (info->async_cb_type) { 5938c2ecf20Sopenharmony_ci case ST21NFCA_CB_TYPE_READER_F: 5948c2ecf20Sopenharmony_ci dep_res = (struct st21nfca_dep_req_res *)skb->data; 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci size = 3; 5978c2ecf20Sopenharmony_ci if (skb->len < size) 5988c2ecf20Sopenharmony_ci goto exit; 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_ci if (ST21NFCA_NFC_DEP_DID_BIT_SET(dep_res->pfb)) 6018c2ecf20Sopenharmony_ci size++; 6028c2ecf20Sopenharmony_ci if (ST21NFCA_NFC_DEP_NAD_BIT_SET(dep_res->pfb)) 6038c2ecf20Sopenharmony_ci size++; 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ci if (skb->len < size) 6068c2ecf20Sopenharmony_ci goto exit; 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci skb_trim(skb, skb->len - 1); 6098c2ecf20Sopenharmony_ci 6108c2ecf20Sopenharmony_ci /* Receiving DEP_REQ - Decoding */ 6118c2ecf20Sopenharmony_ci switch (ST21NFCA_NFC_DEP_PFB_TYPE(dep_res->pfb)) { 6128c2ecf20Sopenharmony_ci case ST21NFCA_NFC_DEP_PFB_ACK_NACK_PDU: 6138c2ecf20Sopenharmony_ci pr_err("Received a ACK/NACK PDU\n"); 6148c2ecf20Sopenharmony_ci fallthrough; 6158c2ecf20Sopenharmony_ci case ST21NFCA_NFC_DEP_PFB_I_PDU: 6168c2ecf20Sopenharmony_ci info->dep_info.curr_nfc_dep_pni = 6178c2ecf20Sopenharmony_ci ST21NFCA_NFC_DEP_PFB_PNI(dep_res->pfb + 1); 6188c2ecf20Sopenharmony_ci size++; 6198c2ecf20Sopenharmony_ci skb_pull(skb, size); 6208c2ecf20Sopenharmony_ci nfc_tm_data_received(info->hdev->ndev, skb); 6218c2ecf20Sopenharmony_ci break; 6228c2ecf20Sopenharmony_ci case ST21NFCA_NFC_DEP_PFB_SUPERVISOR_PDU: 6238c2ecf20Sopenharmony_ci pr_err("Received a SUPERVISOR PDU\n"); 6248c2ecf20Sopenharmony_ci skb_pull(skb, size); 6258c2ecf20Sopenharmony_ci *(u8 *)skb_push(skb, 1) = ST21NFCA_NFCIP1_DEP_REQ; 6268c2ecf20Sopenharmony_ci *(u8 *)skb_push(skb, 1) = ST21NFCA_NFCIP1_REQ; 6278c2ecf20Sopenharmony_ci *(u8 *)skb_push(skb, 1) = skb->len; 6288c2ecf20Sopenharmony_ci *(u8 *)skb_push(skb, 1) = info->dep_info.to | 0x10; 6298c2ecf20Sopenharmony_ci 6308c2ecf20Sopenharmony_ci st21nfca_im_send_pdu(info, skb); 6318c2ecf20Sopenharmony_ci break; 6328c2ecf20Sopenharmony_ci } 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_ci return; 6358c2ecf20Sopenharmony_ci default: 6368c2ecf20Sopenharmony_ci break; 6378c2ecf20Sopenharmony_ci } 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ciexit: 6408c2ecf20Sopenharmony_ci kfree_skb(skb); 6418c2ecf20Sopenharmony_ci} 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ciint st21nfca_im_send_dep_req(struct nfc_hci_dev *hdev, struct sk_buff *skb) 6448c2ecf20Sopenharmony_ci{ 6458c2ecf20Sopenharmony_ci struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci info->async_cb_type = ST21NFCA_CB_TYPE_READER_F; 6488c2ecf20Sopenharmony_ci info->async_cb_context = info; 6498c2ecf20Sopenharmony_ci info->async_cb = st21nfca_im_recv_dep_res_cb; 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_ci *(u8 *)skb_push(skb, 1) = info->dep_info.curr_nfc_dep_pni; 6528c2ecf20Sopenharmony_ci *(u8 *)skb_push(skb, 1) = ST21NFCA_NFCIP1_DEP_REQ; 6538c2ecf20Sopenharmony_ci *(u8 *)skb_push(skb, 1) = ST21NFCA_NFCIP1_REQ; 6548c2ecf20Sopenharmony_ci *(u8 *)skb_push(skb, 1) = skb->len; 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci *(u8 *)skb_push(skb, 1) = info->dep_info.to | 0x10; 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_ci return nfc_hci_send_cmd_async(hdev, ST21NFCA_RF_READER_F_GATE, 6598c2ecf20Sopenharmony_ci ST21NFCA_WR_XCHG_DATA, 6608c2ecf20Sopenharmony_ci skb->data, skb->len, 6618c2ecf20Sopenharmony_ci info->async_cb, info); 6628c2ecf20Sopenharmony_ci} 6638c2ecf20Sopenharmony_ciEXPORT_SYMBOL(st21nfca_im_send_dep_req); 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_civoid st21nfca_dep_init(struct nfc_hci_dev *hdev) 6668c2ecf20Sopenharmony_ci{ 6678c2ecf20Sopenharmony_ci struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci INIT_WORK(&info->dep_info.tx_work, st21nfca_tx_work); 6708c2ecf20Sopenharmony_ci info->dep_info.curr_nfc_dep_pni = 0; 6718c2ecf20Sopenharmony_ci info->dep_info.idx = 0; 6728c2ecf20Sopenharmony_ci info->dep_info.to = ST21NFCA_DEFAULT_TIMEOUT; 6738c2ecf20Sopenharmony_ci} 6748c2ecf20Sopenharmony_ciEXPORT_SYMBOL(st21nfca_dep_init); 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_civoid st21nfca_dep_deinit(struct nfc_hci_dev *hdev) 6778c2ecf20Sopenharmony_ci{ 6788c2ecf20Sopenharmony_ci struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); 6798c2ecf20Sopenharmony_ci 6808c2ecf20Sopenharmony_ci cancel_work_sync(&info->dep_info.tx_work); 6818c2ecf20Sopenharmony_ci} 6828c2ecf20Sopenharmony_ciEXPORT_SYMBOL(st21nfca_dep_deinit); 683