Commit 1a09c56f authored by Thierry Escande's avatar Thierry Escande Committed by Samuel Ortiz

NFC: digital: Add support for NFC DEP Response Waiting Time

When sending an ATR_REQ, the initiator must wait for the ATR_RES at
least 'RWT(nfcdep,activation) + dRWT(nfcdep)' and no more than
'RWT(nfcdep,activation) + dRWT(nfcdep) + dT(nfcdep,initiator)'. This
gives a timeout value between 1237 ms and 1337 ms. This patch defines
DIGITAL_ATR_RES_RWT to 1337 used for the timeout value of ATR_REQ
command.

For other DEP PDUs, the initiator must wait between 'RWT + dRWT(nfcdep)'
and 'RWT + dRWT(nfcdep) + dT(nfcdep,initiator)' where RWT is given by
the following formula: '(256 * 16 / f(c)) * 2^wt' where wt is the value
of the TO field in the ATR_RES response and is in the range between 0
and 14. This patch declares a mapping table for wt values and gives RWT
max values between 100 ms and 5049 ms.

This patch also defines DIGITAL_ATR_RES_TO_WT, the maximum wt value in
target mode, to 8.
Signed-off-by: default avatarThierry Escande <thierry.escande@collabora.com>
Signed-off-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
parent e200f008
...@@ -226,6 +226,7 @@ struct nfc_digital_dev { ...@@ -226,6 +226,7 @@ struct nfc_digital_dev {
u8 curr_rf_tech; u8 curr_rf_tech;
u8 curr_nfc_dep_pni; u8 curr_nfc_dep_pni;
u8 did; u8 did;
u16 dep_rwt;
u8 local_payload_max; u8 local_payload_max;
u8 remote_payload_max; u8 remote_payload_max;
......
...@@ -35,6 +35,8 @@ ...@@ -35,6 +35,8 @@
#define DIGITAL_ATR_REQ_MIN_SIZE 16 #define DIGITAL_ATR_REQ_MIN_SIZE 16
#define DIGITAL_ATR_REQ_MAX_SIZE 64 #define DIGITAL_ATR_REQ_MAX_SIZE 64
#define DIGITAL_ATR_RES_TO_WT(s) ((s) & 0xF)
#define DIGITAL_DID_MAX 14 #define DIGITAL_DID_MAX 14
#define DIGITAL_PAYLOAD_SIZE_MAX 254 #define DIGITAL_PAYLOAD_SIZE_MAX 254
...@@ -122,6 +124,37 @@ static const u8 digital_payload_bits_map[4] = { ...@@ -122,6 +124,37 @@ static const u8 digital_payload_bits_map[4] = {
[3] = 254 [3] = 254
}; };
/* Response Waiting Time for ATR_RES PDU in ms
*
* RWT(ATR_RES) = RWT(nfcdep,activation) + dRWT(nfcdep) + dT(nfcdep,initiator)
*
* with:
* RWT(nfcdep,activation) = 4096 * 2^12 / f(c) s
* dRWT(nfcdep) = 16 / f(c) s
* dT(nfcdep,initiator) = 100 ms
* f(c) = 13560000 Hz
*/
#define DIGITAL_ATR_RES_RWT 1337
/* Response Waiting Time for other DEP PDUs in ms
*
* max_rwt = rwt + dRWT(nfcdep) + dT(nfcdep,initiator)
*
* with:
* rwt = (256 * 16 / f(c)) * 2^wt s
* dRWT(nfcdep) = 16 / f(c) s
* dT(nfcdep,initiator) = 100 ms
* f(c) = 13560000 Hz
* 0 <= wt <= 14 (given by the target by the TO field of ATR_RES response)
*/
#define DIGITAL_NFC_DEP_IN_MAX_WT 14
#define DIGITAL_NFC_DEP_TG_MAX_WT 8
static const u16 digital_rwt_map[DIGITAL_NFC_DEP_IN_MAX_WT + 1] = {
100, 101, 101, 102, 105,
110, 119, 139, 177, 255,
409, 719, 1337, 2575, 5049,
};
static u8 digital_payload_bits_to_size(u8 payload_bits) static u8 digital_payload_bits_to_size(u8 payload_bits)
{ {
if (payload_bits >= ARRAY_SIZE(digital_payload_bits_map)) if (payload_bits >= ARRAY_SIZE(digital_payload_bits_map))
...@@ -366,8 +399,8 @@ static int digital_in_send_psl_req(struct nfc_digital_dev *ddev, ...@@ -366,8 +399,8 @@ static int digital_in_send_psl_req(struct nfc_digital_dev *ddev,
ddev->skb_add_crc(skb); ddev->skb_add_crc(skb);
rc = digital_in_send_cmd(ddev, skb, 500, digital_in_recv_psl_res, rc = digital_in_send_cmd(ddev, skb, ddev->dep_rwt,
target); digital_in_recv_psl_res, target);
if (rc) if (rc)
kfree_skb(skb); kfree_skb(skb);
...@@ -380,6 +413,7 @@ static void digital_in_recv_atr_res(struct nfc_digital_dev *ddev, void *arg, ...@@ -380,6 +413,7 @@ static void digital_in_recv_atr_res(struct nfc_digital_dev *ddev, void *arg,
struct nfc_target *target = arg; struct nfc_target *target = arg;
struct digital_atr_res *atr_res; struct digital_atr_res *atr_res;
u8 gb_len, payload_bits; u8 gb_len, payload_bits;
u8 wt;
int rc; int rc;
if (IS_ERR(resp)) { if (IS_ERR(resp)) {
...@@ -409,6 +443,11 @@ static void digital_in_recv_atr_res(struct nfc_digital_dev *ddev, void *arg, ...@@ -409,6 +443,11 @@ static void digital_in_recv_atr_res(struct nfc_digital_dev *ddev, void *arg,
atr_res = (struct digital_atr_res *)resp->data; atr_res = (struct digital_atr_res *)resp->data;
wt = DIGITAL_ATR_RES_TO_WT(atr_res->to);
if (wt > DIGITAL_NFC_DEP_IN_MAX_WT)
wt = DIGITAL_NFC_DEP_IN_MAX_WT;
ddev->dep_rwt = digital_rwt_map[wt];
payload_bits = DIGITAL_PAYLOAD_PP_TO_BITS(atr_res->pp); payload_bits = DIGITAL_PAYLOAD_PP_TO_BITS(atr_res->pp);
ddev->remote_payload_max = digital_payload_bits_to_size(payload_bits); ddev->remote_payload_max = digital_payload_bits_to_size(payload_bits);
...@@ -490,8 +529,8 @@ int digital_in_send_atr_req(struct nfc_digital_dev *ddev, ...@@ -490,8 +529,8 @@ int digital_in_send_atr_req(struct nfc_digital_dev *ddev,
ddev->skb_add_crc(skb); ddev->skb_add_crc(skb);
rc = digital_in_send_cmd(ddev, skb, 500, digital_in_recv_atr_res, rc = digital_in_send_cmd(ddev, skb, DIGITAL_ATR_RES_RWT,
target); digital_in_recv_atr_res, target);
if (rc) if (rc)
kfree_skb(skb); kfree_skb(skb);
...@@ -524,8 +563,8 @@ static int digital_in_send_ack(struct nfc_digital_dev *ddev, ...@@ -524,8 +563,8 @@ static int digital_in_send_ack(struct nfc_digital_dev *ddev,
ddev->saved_skb = pskb_copy(skb, GFP_KERNEL); ddev->saved_skb = pskb_copy(skb, GFP_KERNEL);
rc = digital_in_send_cmd(ddev, skb, 1500, digital_in_recv_dep_res, rc = digital_in_send_cmd(ddev, skb, ddev->dep_rwt,
data_exch); digital_in_recv_dep_res, data_exch);
if (rc) { if (rc) {
kfree_skb(skb); kfree_skb(skb);
kfree_skb(ddev->saved_skb); kfree_skb(ddev->saved_skb);
...@@ -559,8 +598,8 @@ static int digital_in_send_nack(struct nfc_digital_dev *ddev, ...@@ -559,8 +598,8 @@ static int digital_in_send_nack(struct nfc_digital_dev *ddev,
ddev->skb_add_crc(skb); ddev->skb_add_crc(skb);
rc = digital_in_send_cmd(ddev, skb, 1500, digital_in_recv_dep_res, rc = digital_in_send_cmd(ddev, skb, ddev->dep_rwt,
data_exch); digital_in_recv_dep_res, data_exch);
if (rc) if (rc)
kfree_skb(skb); kfree_skb(skb);
...@@ -590,8 +629,8 @@ static int digital_in_send_atn(struct nfc_digital_dev *ddev, ...@@ -590,8 +629,8 @@ static int digital_in_send_atn(struct nfc_digital_dev *ddev,
ddev->skb_add_crc(skb); ddev->skb_add_crc(skb);
rc = digital_in_send_cmd(ddev, skb, 1500, digital_in_recv_dep_res, rc = digital_in_send_cmd(ddev, skb, ddev->dep_rwt,
data_exch); digital_in_recv_dep_res, data_exch);
if (rc) if (rc)
kfree_skb(skb); kfree_skb(skb);
...@@ -624,8 +663,8 @@ static int digital_in_send_rtox(struct nfc_digital_dev *ddev, ...@@ -624,8 +663,8 @@ static int digital_in_send_rtox(struct nfc_digital_dev *ddev,
ddev->skb_add_crc(skb); ddev->skb_add_crc(skb);
rc = digital_in_send_cmd(ddev, skb, 1500, digital_in_recv_dep_res, rc = digital_in_send_cmd(ddev, skb, ddev->dep_rwt,
data_exch); digital_in_recv_dep_res, data_exch);
if (rc) if (rc)
kfree_skb(skb); kfree_skb(skb);
...@@ -642,7 +681,7 @@ static int digital_in_send_saved_skb(struct nfc_digital_dev *ddev, ...@@ -642,7 +681,7 @@ static int digital_in_send_saved_skb(struct nfc_digital_dev *ddev,
skb_get(ddev->saved_skb); skb_get(ddev->saved_skb);
rc = digital_in_send_cmd(ddev, ddev->saved_skb, 1500, rc = digital_in_send_cmd(ddev, ddev->saved_skb, ddev->dep_rwt,
digital_in_recv_dep_res, data_exch); digital_in_recv_dep_res, data_exch);
if (rc) if (rc)
kfree_skb(ddev->saved_skb); kfree_skb(ddev->saved_skb);
...@@ -885,8 +924,8 @@ int digital_in_send_dep_req(struct nfc_digital_dev *ddev, ...@@ -885,8 +924,8 @@ int digital_in_send_dep_req(struct nfc_digital_dev *ddev,
ddev->saved_skb = pskb_copy(tmp_skb, GFP_KERNEL); ddev->saved_skb = pskb_copy(tmp_skb, GFP_KERNEL);
rc = digital_in_send_cmd(ddev, tmp_skb, 1500, digital_in_recv_dep_res, rc = digital_in_send_cmd(ddev, tmp_skb, ddev->dep_rwt,
data_exch); digital_in_recv_dep_res, data_exch);
if (rc) { if (rc) {
if (tmp_skb != skb) if (tmp_skb != skb)
kfree_skb(tmp_skb); kfree_skb(tmp_skb);
...@@ -1465,7 +1504,7 @@ static int digital_tg_send_atr_res(struct nfc_digital_dev *ddev, ...@@ -1465,7 +1504,7 @@ static int digital_tg_send_atr_res(struct nfc_digital_dev *ddev,
atr_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN; atr_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
atr_res->cmd = DIGITAL_CMD_ATR_RES; atr_res->cmd = DIGITAL_CMD_ATR_RES;
memcpy(atr_res->nfcid3, atr_req->nfcid3, sizeof(atr_req->nfcid3)); memcpy(atr_res->nfcid3, atr_req->nfcid3, sizeof(atr_req->nfcid3));
atr_res->to = 8; atr_res->to = DIGITAL_NFC_DEP_TG_MAX_WT;
ddev->local_payload_max = DIGITAL_PAYLOAD_SIZE_MAX; ddev->local_payload_max = DIGITAL_PAYLOAD_SIZE_MAX;
payload_bits = digital_payload_size_to_bits(ddev->local_payload_max); payload_bits = digital_payload_size_to_bits(ddev->local_payload_max);
......
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