diff options
author | Thierry Escande <thierry.escande@linux.intel.com> | 2014-01-26 18:31:32 -0500 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2014-02-16 17:49:54 -0500 |
commit | c813007f9ffb0b6e9f3dc43bfd9e28806aa57e5d (patch) | |
tree | 1a030aa83175313551eecfd7f23d08797481837b /net/nfc/digital_technology.c | |
parent | 12e3d241e42956da168fd499347855af799f62fb (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.c | 57 |
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 | |||
64 | static const u8 digital_ats_fsc[] = { | 73 | static 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 { | |||
118 | static int digital_in_send_sdd_req(struct nfc_digital_dev *ddev, | 127 | static int digital_in_send_sdd_req(struct nfc_digital_dev *ddev, |
119 | struct nfc_target *target); | 128 | struct nfc_target *target); |
120 | 129 | ||
130 | int 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 | |||
158 | int 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 | |||
121 | static void digital_in_recv_ats(struct nfc_digital_dev *ddev, void *arg, | 178 | static void digital_in_recv_ats(struct nfc_digital_dev *ddev, void *arg, |
122 | struct sk_buff *resp) | 179 | struct sk_buff *resp) |
123 | { | 180 | { |