aboutsummaryrefslogtreecommitdiffstats
path: root/net/nfc/digital_technology.c
diff options
context:
space:
mode:
authorThierry Escande <thierry.escande@linux.intel.com>2014-01-26 18:31:32 -0500
committerSamuel Ortiz <sameo@linux.intel.com>2014-02-16 17:49:54 -0500
commitc813007f9ffb0b6e9f3dc43bfd9e28806aa57e5d (patch)
tree1a030aa83175313551eecfd7f23d08797481837b /net/nfc/digital_technology.c
parent12e3d241e42956da168fd499347855af799f62fb (diff)
NFC: digital: Add ISO-DEP support for data exchange
When a type 4A target is activated, this change adds the ISO-DEP SoD when sending frames and removes it when receiving responses. Chaining is not supported so sent frames are rejected if they exceed remote FSC bytes. Signed-off-by: Thierry Escande <thierry.escande@linux.intel.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'net/nfc/digital_technology.c')
-rw-r--r--net/nfc/digital_technology.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/net/nfc/digital_technology.c b/net/nfc/digital_technology.c
index 6649d9461dff..278c3fed27e0 100644
--- a/net/nfc/digital_technology.c
+++ b/net/nfc/digital_technology.c
@@ -61,6 +61,15 @@
61#define DIGITAL_ISO15693_RES_IS_VALID(flags) \ 61#define DIGITAL_ISO15693_RES_IS_VALID(flags) \
62 (!((flags) & DIGITAL_ISO15693_RES_FLAG_ERROR)) 62 (!((flags) & DIGITAL_ISO15693_RES_FLAG_ERROR))
63 63
64#define DIGITAL_ISO_DEP_I_PCB 0x02
65#define DIGITAL_ISO_DEP_PNI(pni) ((pni) & 0x01)
66
67#define DIGITAL_ISO_DEP_PCB_TYPE(pcb) ((pcb) & 0xC0)
68
69#define DIGITAL_ISO_DEP_I_BLOCK 0x00
70
71#define DIGITAL_ISO_DEP_BLOCK_HAS_DID(pcb) ((pcb) & 0x08)
72
64static const u8 digital_ats_fsc[] = { 73static const u8 digital_ats_fsc[] = {
65 16, 24, 32, 40, 48, 64, 96, 128, 74 16, 24, 32, 40, 48, 64, 96, 128,
66}; 75};
@@ -118,6 +127,54 @@ struct digital_iso15693_inv_res {
118static int digital_in_send_sdd_req(struct nfc_digital_dev *ddev, 127static int digital_in_send_sdd_req(struct nfc_digital_dev *ddev,
119 struct nfc_target *target); 128 struct nfc_target *target);
120 129
130int digital_in_iso_dep_pull_sod(struct nfc_digital_dev *ddev,
131 struct sk_buff *skb)
132{
133 u8 pcb;
134 u8 block_type;
135
136 if (skb->len < 1)
137 return -EIO;
138
139 pcb = *skb->data;
140 block_type = DIGITAL_ISO_DEP_PCB_TYPE(pcb);
141
142 /* No support fo R-block nor S-block */
143 if (block_type != DIGITAL_ISO_DEP_I_BLOCK) {
144 pr_err("ISO_DEP R-block and S-block not supported\n");
145 return -EIO;
146 }
147
148 if (DIGITAL_ISO_DEP_BLOCK_HAS_DID(pcb)) {
149 pr_err("DID field in ISO_DEP PCB not supported\n");
150 return -EIO;
151 }
152
153 skb_pull(skb, 1);
154
155 return 0;
156}
157
158int digital_in_iso_dep_push_sod(struct nfc_digital_dev *ddev,
159 struct sk_buff *skb)
160{
161 /*
162 * Chaining not supported so skb->len + 1 PCB byte + 2 CRC bytes must
163 * not be greater than remote FSC
164 */
165 if (skb->len + 3 > ddev->target_fsc)
166 return -EIO;
167
168 skb_push(skb, 1);
169
170 *skb->data = DIGITAL_ISO_DEP_I_PCB | ddev->curr_nfc_dep_pni;
171
172 ddev->curr_nfc_dep_pni =
173 DIGITAL_ISO_DEP_PNI(ddev->curr_nfc_dep_pni + 1);
174
175 return 0;
176}
177
121static void digital_in_recv_ats(struct nfc_digital_dev *ddev, void *arg, 178static void digital_in_recv_ats(struct nfc_digital_dev *ddev, void *arg,
122 struct sk_buff *resp) 179 struct sk_buff *resp)
123{ 180{