Commit 12e3d241 authored by Thierry Escande's avatar Thierry Escande Committed by Samuel Ortiz

NFC: digital: Add poll support for type 4A tag platform

This adds support for ATS request and response handling for type 4A tag
activation.
Signed-off-by: default avatarThierry Escande <thierry.escande@linux.intel.com>
Signed-off-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
parent d3815ea9
...@@ -51,6 +51,7 @@ enum { ...@@ -51,6 +51,7 @@ enum {
NFC_DIGITAL_FRAMING_NFCA_T1T, NFC_DIGITAL_FRAMING_NFCA_T1T,
NFC_DIGITAL_FRAMING_NFCA_T2T, NFC_DIGITAL_FRAMING_NFCA_T2T,
NFC_DIGITAL_FRAMING_NFCA_T4T,
NFC_DIGITAL_FRAMING_NFCA_NFC_DEP, NFC_DIGITAL_FRAMING_NFCA_NFC_DEP,
NFC_DIGITAL_FRAMING_NFCF, NFC_DIGITAL_FRAMING_NFCF,
...@@ -208,6 +209,8 @@ struct nfc_digital_dev { ...@@ -208,6 +209,8 @@ struct nfc_digital_dev {
u8 curr_rf_tech; u8 curr_rf_tech;
u8 curr_nfc_dep_pni; u8 curr_nfc_dep_pni;
u16 target_fsc;
int (*skb_check_crc)(struct sk_buff *skb); int (*skb_check_crc)(struct sk_buff *skb);
void (*skb_add_crc)(struct sk_buff *skb); void (*skb_add_crc)(struct sk_buff *skb);
}; };
......
...@@ -337,6 +337,11 @@ int digital_target_found(struct nfc_digital_dev *ddev, ...@@ -337,6 +337,11 @@ int digital_target_found(struct nfc_digital_dev *ddev,
framing = NFC_DIGITAL_FRAMING_ISO15693_TVT; framing = NFC_DIGITAL_FRAMING_ISO15693_TVT;
check_crc = digital_skb_check_crc_b; check_crc = digital_skb_check_crc_b;
add_crc = digital_skb_add_crc_b; add_crc = digital_skb_add_crc_b;
case NFC_PROTO_ISO14443:
framing = NFC_DIGITAL_FRAMING_NFCA_T4T;
check_crc = digital_skb_check_crc_a;
add_crc = digital_skb_add_crc_a;
break; break;
default: default:
...@@ -714,6 +719,8 @@ struct nfc_digital_dev *nfc_digital_allocate_device(struct nfc_digital_ops *ops, ...@@ -714,6 +719,8 @@ struct nfc_digital_dev *nfc_digital_allocate_device(struct nfc_digital_ops *ops,
ddev->protocols |= NFC_PROTO_NFC_DEP_MASK; ddev->protocols |= NFC_PROTO_NFC_DEP_MASK;
if (supported_protocols & NFC_PROTO_ISO15693_MASK) if (supported_protocols & NFC_PROTO_ISO15693_MASK)
ddev->protocols |= NFC_PROTO_ISO15693_MASK; ddev->protocols |= NFC_PROTO_ISO15693_MASK;
if (supported_protocols & NFC_PROTO_ISO14443_MASK)
ddev->protocols |= NFC_PROTO_ISO14443_MASK;
ddev->tx_headroom = tx_headroom + DIGITAL_MAX_HEADER_LEN; ddev->tx_headroom = tx_headroom + DIGITAL_MAX_HEADER_LEN;
ddev->tx_tailroom = tx_tailroom + DIGITAL_CRC_LEN; ddev->tx_tailroom = tx_tailroom + DIGITAL_CRC_LEN;
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#define DIGITAL_SEL_RES_NFCID1_COMPLETE(sel_res) (!((sel_res) & 0x04)) #define DIGITAL_SEL_RES_NFCID1_COMPLETE(sel_res) (!((sel_res) & 0x04))
#define DIGITAL_SEL_RES_IS_T2T(sel_res) (!((sel_res) & 0x60)) #define DIGITAL_SEL_RES_IS_T2T(sel_res) (!((sel_res) & 0x60))
#define DIGITAL_SEL_RES_IS_T4T(sel_res) ((sel_res) & 0x20)
#define DIGITAL_SEL_RES_IS_NFC_DEP(sel_res) ((sel_res) & 0x40) #define DIGITAL_SEL_RES_IS_NFC_DEP(sel_res) ((sel_res) & 0x40)
#define DIGITAL_SENS_RES_IS_T1T(sens_res) (((sens_res) & 0x0C00) == 0x0C00) #define DIGITAL_SENS_RES_IS_T1T(sens_res) (((sens_res) & 0x0C00) == 0x0C00)
...@@ -60,6 +61,16 @@ ...@@ -60,6 +61,16 @@
#define DIGITAL_ISO15693_RES_IS_VALID(flags) \ #define DIGITAL_ISO15693_RES_IS_VALID(flags) \
(!((flags) & DIGITAL_ISO15693_RES_FLAG_ERROR)) (!((flags) & DIGITAL_ISO15693_RES_FLAG_ERROR))
static const u8 digital_ats_fsc[] = {
16, 24, 32, 40, 48, 64, 96, 128,
};
#define DIGITAL_ATS_FSCI(t0) ((t0) & 0x0F)
#define DIGITAL_ATS_MAX_FSC 256
#define DIGITAL_RATS_BYTE1 0xE0
#define DIGITAL_RATS_PARAM 0x80
struct digital_sdd_res { struct digital_sdd_res {
u8 nfcid1[4]; u8 nfcid1[4];
u8 bcc; u8 bcc;
...@@ -107,6 +118,63 @@ struct digital_iso15693_inv_res { ...@@ -107,6 +118,63 @@ struct digital_iso15693_inv_res {
static int digital_in_send_sdd_req(struct nfc_digital_dev *ddev, static int digital_in_send_sdd_req(struct nfc_digital_dev *ddev,
struct nfc_target *target); struct nfc_target *target);
static void digital_in_recv_ats(struct nfc_digital_dev *ddev, void *arg,
struct sk_buff *resp)
{
struct nfc_target *target = arg;
u8 fsdi;
int rc;
if (IS_ERR(resp)) {
rc = PTR_ERR(resp);
resp = NULL;
goto exit;
}
if (resp->len < 2) {
rc = -EIO;
goto exit;
}
fsdi = DIGITAL_ATS_FSCI(resp->data[1]);
if (fsdi >= 8)
ddev->target_fsc = DIGITAL_ATS_MAX_FSC;
else
ddev->target_fsc = digital_ats_fsc[fsdi];
ddev->curr_nfc_dep_pni = 0;
rc = digital_target_found(ddev, target, NFC_PROTO_ISO14443);
exit:
dev_kfree_skb(resp);
kfree(target);
if (rc)
digital_poll_next_tech(ddev);
}
static int digital_in_send_rats(struct nfc_digital_dev *ddev,
struct nfc_target *target)
{
int rc;
struct sk_buff *skb;
skb = digital_skb_alloc(ddev, 2);
if (!skb)
return -ENOMEM;
*skb_put(skb, 1) = DIGITAL_RATS_BYTE1;
*skb_put(skb, 1) = DIGITAL_RATS_PARAM;
rc = digital_in_send_cmd(ddev, skb, 30, digital_in_recv_ats,
target);
if (rc)
kfree_skb(skb);
return rc;
}
static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg, static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg,
struct sk_buff *resp) struct sk_buff *resp)
{ {
...@@ -144,8 +212,19 @@ static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg, ...@@ -144,8 +212,19 @@ static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg,
goto exit_free_skb; goto exit_free_skb;
} }
target->sel_res = sel_res;
if (DIGITAL_SEL_RES_IS_T2T(sel_res)) { if (DIGITAL_SEL_RES_IS_T2T(sel_res)) {
nfc_proto = NFC_PROTO_MIFARE; nfc_proto = NFC_PROTO_MIFARE;
} else if (DIGITAL_SEL_RES_IS_T4T(sel_res)) {
rc = digital_in_send_rats(ddev, target);
if (rc)
goto exit;
/*
* Skip target_found and don't free it for now. This will be
* done when receiving the ATS
*/
goto exit_free_skb;
} else if (DIGITAL_SEL_RES_IS_NFC_DEP(sel_res)) { } else if (DIGITAL_SEL_RES_IS_NFC_DEP(sel_res)) {
nfc_proto = NFC_PROTO_NFC_DEP; nfc_proto = NFC_PROTO_NFC_DEP;
} else { } else {
...@@ -153,8 +232,6 @@ static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg, ...@@ -153,8 +232,6 @@ static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg,
goto exit; goto exit;
} }
target->sel_res = sel_res;
rc = digital_target_found(ddev, target, nfc_proto); rc = digital_target_found(ddev, target, nfc_proto);
exit: exit:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment