diff options
Diffstat (limited to 'net/nfc')
-rw-r--r-- | net/nfc/digital_dep.c | 108 |
1 files changed, 98 insertions, 10 deletions
diff --git a/net/nfc/digital_dep.c b/net/nfc/digital_dep.c index 95a69898d5f5..b78790088b8e 100644 --- a/net/nfc/digital_dep.c +++ b/net/nfc/digital_dep.c | |||
@@ -34,9 +34,12 @@ | |||
34 | 34 | ||
35 | #define DIGITAL_DID_MAX 14 | 35 | #define DIGITAL_DID_MAX 14 |
36 | 36 | ||
37 | #define DIGITAL_LR_BITS_PAYLOAD_SIZE_254B 0x30 | 37 | #define DIGITAL_PAYLOAD_SIZE_MAX 254 |
38 | #define DIGITAL_FSL_BITS_PAYLOAD_SIZE_254B \ | 38 | #define DIGITAL_PAYLOAD_BITS_TO_PP(s) (((s) & 0x3) << 4) |
39 | (DIGITAL_LR_BITS_PAYLOAD_SIZE_254B >> 4) | 39 | #define DIGITAL_PAYLOAD_PP_TO_BITS(s) (((s) >> 4) & 0x3) |
40 | #define DIGITAL_PAYLOAD_BITS_TO_FSL(s) ((s) & 0x3) | ||
41 | #define DIGITAL_PAYLOAD_FSL_TO_BITS(s) ((s) & 0x3) | ||
42 | |||
40 | #define DIGITAL_GB_BIT 0x02 | 43 | #define DIGITAL_GB_BIT 0x02 |
41 | 44 | ||
42 | #define DIGITAL_NFC_DEP_PFB_TYPE(pfb) ((pfb) & 0xE0) | 45 | #define DIGITAL_NFC_DEP_PFB_TYPE(pfb) ((pfb) & 0xE0) |
@@ -101,6 +104,32 @@ struct digital_dep_req_res { | |||
101 | static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg, | 104 | static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg, |
102 | struct sk_buff *resp); | 105 | struct sk_buff *resp); |
103 | 106 | ||
107 | static const u8 digital_payload_bits_map[4] = { | ||
108 | [0] = 64, | ||
109 | [1] = 128, | ||
110 | [2] = 192, | ||
111 | [3] = 254 | ||
112 | }; | ||
113 | |||
114 | static u8 digital_payload_bits_to_size(u8 payload_bits) | ||
115 | { | ||
116 | if (payload_bits >= ARRAY_SIZE(digital_payload_bits_map)) | ||
117 | return 0; | ||
118 | |||
119 | return digital_payload_bits_map[payload_bits]; | ||
120 | } | ||
121 | |||
122 | static u8 digital_payload_size_to_bits(u8 payload_size) | ||
123 | { | ||
124 | int i; | ||
125 | |||
126 | for (i = 0; i < ARRAY_SIZE(digital_payload_bits_map); i++) | ||
127 | if (digital_payload_bits_map[i] == payload_size) | ||
128 | return i; | ||
129 | |||
130 | return 0xff; | ||
131 | } | ||
132 | |||
104 | static void digital_skb_push_dep_sod(struct nfc_digital_dev *ddev, | 133 | static void digital_skb_push_dep_sod(struct nfc_digital_dev *ddev, |
105 | struct sk_buff *skb) | 134 | struct sk_buff *skb) |
106 | { | 135 | { |
@@ -202,6 +231,7 @@ static int digital_in_send_psl_req(struct nfc_digital_dev *ddev, | |||
202 | struct sk_buff *skb; | 231 | struct sk_buff *skb; |
203 | struct digital_psl_req *psl_req; | 232 | struct digital_psl_req *psl_req; |
204 | int rc; | 233 | int rc; |
234 | u8 payload_size, payload_bits; | ||
205 | 235 | ||
206 | skb = digital_skb_alloc(ddev, sizeof(*psl_req)); | 236 | skb = digital_skb_alloc(ddev, sizeof(*psl_req)); |
207 | if (!skb) | 237 | if (!skb) |
@@ -215,7 +245,13 @@ static int digital_in_send_psl_req(struct nfc_digital_dev *ddev, | |||
215 | psl_req->cmd = DIGITAL_CMD_PSL_REQ; | 245 | psl_req->cmd = DIGITAL_CMD_PSL_REQ; |
216 | psl_req->did = 0; | 246 | psl_req->did = 0; |
217 | psl_req->brs = (0x2 << 3) | 0x2; /* 424F both directions */ | 247 | psl_req->brs = (0x2 << 3) | 0x2; /* 424F both directions */ |
218 | psl_req->fsl = DIGITAL_FSL_BITS_PAYLOAD_SIZE_254B; | 248 | |
249 | payload_size = min(ddev->local_payload_max, ddev->remote_payload_max); | ||
250 | payload_bits = digital_payload_size_to_bits(payload_size); | ||
251 | psl_req->fsl = DIGITAL_PAYLOAD_BITS_TO_FSL(payload_bits); | ||
252 | |||
253 | ddev->local_payload_max = payload_size; | ||
254 | ddev->remote_payload_max = payload_size; | ||
219 | 255 | ||
220 | digital_skb_push_dep_sod(ddev, skb); | 256 | digital_skb_push_dep_sod(ddev, skb); |
221 | 257 | ||
@@ -234,7 +270,7 @@ static void digital_in_recv_atr_res(struct nfc_digital_dev *ddev, void *arg, | |||
234 | { | 270 | { |
235 | struct nfc_target *target = arg; | 271 | struct nfc_target *target = arg; |
236 | struct digital_atr_res *atr_res; | 272 | struct digital_atr_res *atr_res; |
237 | u8 gb_len; | 273 | u8 gb_len, payload_bits; |
238 | int rc; | 274 | int rc; |
239 | 275 | ||
240 | if (IS_ERR(resp)) { | 276 | if (IS_ERR(resp)) { |
@@ -264,6 +300,14 @@ static void digital_in_recv_atr_res(struct nfc_digital_dev *ddev, void *arg, | |||
264 | 300 | ||
265 | atr_res = (struct digital_atr_res *)resp->data; | 301 | atr_res = (struct digital_atr_res *)resp->data; |
266 | 302 | ||
303 | payload_bits = DIGITAL_PAYLOAD_PP_TO_BITS(atr_res->pp); | ||
304 | ddev->remote_payload_max = digital_payload_bits_to_size(payload_bits); | ||
305 | |||
306 | if (!ddev->remote_payload_max) { | ||
307 | rc = -EINVAL; | ||
308 | goto exit; | ||
309 | } | ||
310 | |||
267 | rc = nfc_set_remote_general_bytes(ddev->nfc_dev, atr_res->gb, gb_len); | 311 | rc = nfc_set_remote_general_bytes(ddev->nfc_dev, atr_res->gb, gb_len); |
268 | if (rc) | 312 | if (rc) |
269 | goto exit; | 313 | goto exit; |
@@ -295,6 +339,7 @@ int digital_in_send_atr_req(struct nfc_digital_dev *ddev, | |||
295 | struct digital_atr_req *atr_req; | 339 | struct digital_atr_req *atr_req; |
296 | uint size; | 340 | uint size; |
297 | int rc; | 341 | int rc; |
342 | u8 payload_bits; | ||
298 | 343 | ||
299 | size = DIGITAL_ATR_REQ_MIN_SIZE + gb_len; | 344 | size = DIGITAL_ATR_REQ_MIN_SIZE + gb_len; |
300 | 345 | ||
@@ -323,7 +368,9 @@ int digital_in_send_atr_req(struct nfc_digital_dev *ddev, | |||
323 | atr_req->bs = 0; | 368 | atr_req->bs = 0; |
324 | atr_req->br = 0; | 369 | atr_req->br = 0; |
325 | 370 | ||
326 | atr_req->pp = DIGITAL_LR_BITS_PAYLOAD_SIZE_254B; | 371 | ddev->local_payload_max = DIGITAL_PAYLOAD_SIZE_MAX; |
372 | payload_bits = digital_payload_size_to_bits(ddev->local_payload_max); | ||
373 | atr_req->pp = DIGITAL_PAYLOAD_BITS_TO_PP(payload_bits); | ||
327 | 374 | ||
328 | if (gb_len) { | 375 | if (gb_len) { |
329 | atr_req->pp |= DIGITAL_GB_BIT; | 376 | atr_req->pp |= DIGITAL_GB_BIT; |
@@ -403,6 +450,11 @@ static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg, | |||
403 | goto exit; | 450 | goto exit; |
404 | } | 451 | } |
405 | 452 | ||
453 | if (resp->len > ddev->local_payload_max) { | ||
454 | rc = -EMSGSIZE; | ||
455 | goto exit; | ||
456 | } | ||
457 | |||
406 | size = sizeof(struct digital_dep_req_res); | 458 | size = sizeof(struct digital_dep_req_res); |
407 | dep_res = (struct digital_dep_req_res *)resp->data; | 459 | dep_res = (struct digital_dep_req_res *)resp->data; |
408 | 460 | ||
@@ -498,6 +550,9 @@ int digital_in_send_dep_req(struct nfc_digital_dev *ddev, | |||
498 | 550 | ||
499 | skb_push(skb, sizeof(struct digital_dep_req_res)); | 551 | skb_push(skb, sizeof(struct digital_dep_req_res)); |
500 | 552 | ||
553 | if (skb->len > ddev->remote_payload_max) | ||
554 | return -EMSGSIZE; | ||
555 | |||
501 | dep_req = (struct digital_dep_req_res *)skb->data; | 556 | dep_req = (struct digital_dep_req_res *)skb->data; |
502 | dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT; | 557 | dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT; |
503 | dep_req->cmd = DIGITAL_CMD_DEP_REQ; | 558 | dep_req->cmd = DIGITAL_CMD_DEP_REQ; |
@@ -564,6 +619,11 @@ static void digital_tg_recv_dep_req(struct nfc_digital_dev *ddev, void *arg, | |||
564 | goto exit; | 619 | goto exit; |
565 | } | 620 | } |
566 | 621 | ||
622 | if (resp->len > ddev->local_payload_max) { | ||
623 | rc = -EMSGSIZE; | ||
624 | goto exit; | ||
625 | } | ||
626 | |||
567 | size = sizeof(struct digital_dep_req_res); | 627 | size = sizeof(struct digital_dep_req_res); |
568 | dep_req = (struct digital_dep_req_res *)resp->data; | 628 | dep_req = (struct digital_dep_req_res *)resp->data; |
569 | 629 | ||
@@ -639,6 +699,10 @@ int digital_tg_send_dep_res(struct nfc_digital_dev *ddev, struct sk_buff *skb) | |||
639 | struct digital_dep_req_res *dep_res; | 699 | struct digital_dep_req_res *dep_res; |
640 | 700 | ||
641 | skb_push(skb, sizeof(struct digital_dep_req_res)); | 701 | skb_push(skb, sizeof(struct digital_dep_req_res)); |
702 | |||
703 | if (skb->len > ddev->remote_payload_max) | ||
704 | return -EMSGSIZE; | ||
705 | |||
642 | dep_res = (struct digital_dep_req_res *)skb->data; | 706 | dep_res = (struct digital_dep_req_res *)skb->data; |
643 | 707 | ||
644 | dep_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN; | 708 | dep_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN; |
@@ -719,7 +783,7 @@ static void digital_tg_recv_psl_req(struct nfc_digital_dev *ddev, void *arg, | |||
719 | int rc; | 783 | int rc; |
720 | struct digital_psl_req *psl_req; | 784 | struct digital_psl_req *psl_req; |
721 | u8 rf_tech; | 785 | u8 rf_tech; |
722 | u8 dsi; | 786 | u8 dsi, payload_size, payload_bits; |
723 | 787 | ||
724 | if (IS_ERR(resp)) { | 788 | if (IS_ERR(resp)) { |
725 | rc = PTR_ERR(resp); | 789 | rc = PTR_ERR(resp); |
@@ -764,6 +828,18 @@ static void digital_tg_recv_psl_req(struct nfc_digital_dev *ddev, void *arg, | |||
764 | goto exit; | 828 | goto exit; |
765 | } | 829 | } |
766 | 830 | ||
831 | payload_bits = DIGITAL_PAYLOAD_FSL_TO_BITS(psl_req->fsl); | ||
832 | payload_size = digital_payload_bits_to_size(payload_bits); | ||
833 | |||
834 | if (!payload_size || (payload_size > min(ddev->local_payload_max, | ||
835 | ddev->remote_payload_max))) { | ||
836 | rc = -EINVAL; | ||
837 | goto exit; | ||
838 | } | ||
839 | |||
840 | ddev->local_payload_max = payload_size; | ||
841 | ddev->remote_payload_max = payload_size; | ||
842 | |||
767 | rc = digital_tg_send_psl_res(ddev, psl_req->did, rf_tech); | 843 | rc = digital_tg_send_psl_res(ddev, psl_req->did, rf_tech); |
768 | 844 | ||
769 | exit: | 845 | exit: |
@@ -795,7 +871,7 @@ static int digital_tg_send_atr_res(struct nfc_digital_dev *ddev, | |||
795 | { | 871 | { |
796 | struct digital_atr_res *atr_res; | 872 | struct digital_atr_res *atr_res; |
797 | struct sk_buff *skb; | 873 | struct sk_buff *skb; |
798 | u8 *gb; | 874 | u8 *gb, payload_bits; |
799 | size_t gb_len; | 875 | size_t gb_len; |
800 | int rc; | 876 | int rc; |
801 | 877 | ||
@@ -816,7 +892,11 @@ static int digital_tg_send_atr_res(struct nfc_digital_dev *ddev, | |||
816 | atr_res->cmd = DIGITAL_CMD_ATR_RES; | 892 | atr_res->cmd = DIGITAL_CMD_ATR_RES; |
817 | memcpy(atr_res->nfcid3, atr_req->nfcid3, sizeof(atr_req->nfcid3)); | 893 | memcpy(atr_res->nfcid3, atr_req->nfcid3, sizeof(atr_req->nfcid3)); |
818 | atr_res->to = 8; | 894 | atr_res->to = 8; |
819 | atr_res->pp = DIGITAL_LR_BITS_PAYLOAD_SIZE_254B; | 895 | |
896 | ddev->local_payload_max = DIGITAL_PAYLOAD_SIZE_MAX; | ||
897 | payload_bits = digital_payload_size_to_bits(ddev->local_payload_max); | ||
898 | atr_res->pp = DIGITAL_PAYLOAD_BITS_TO_PP(payload_bits); | ||
899 | |||
820 | if (gb_len) { | 900 | if (gb_len) { |
821 | skb_put(skb, gb_len); | 901 | skb_put(skb, gb_len); |
822 | 902 | ||
@@ -844,7 +924,7 @@ void digital_tg_recv_atr_req(struct nfc_digital_dev *ddev, void *arg, | |||
844 | int rc; | 924 | int rc; |
845 | struct digital_atr_req *atr_req; | 925 | struct digital_atr_req *atr_req; |
846 | size_t gb_len, min_size; | 926 | size_t gb_len, min_size; |
847 | u8 poll_tech_count; | 927 | u8 poll_tech_count, payload_bits; |
848 | 928 | ||
849 | if (IS_ERR(resp)) { | 929 | if (IS_ERR(resp)) { |
850 | rc = PTR_ERR(resp); | 930 | rc = PTR_ERR(resp); |
@@ -893,6 +973,14 @@ void digital_tg_recv_atr_req(struct nfc_digital_dev *ddev, void *arg, | |||
893 | goto exit; | 973 | goto exit; |
894 | } | 974 | } |
895 | 975 | ||
976 | payload_bits = DIGITAL_PAYLOAD_PP_TO_BITS(atr_req->pp); | ||
977 | ddev->remote_payload_max = digital_payload_bits_to_size(payload_bits); | ||
978 | |||
979 | if (!ddev->remote_payload_max) { | ||
980 | rc = -EINVAL; | ||
981 | goto exit; | ||
982 | } | ||
983 | |||
896 | ddev->did = atr_req->did; | 984 | ddev->did = atr_req->did; |
897 | 985 | ||
898 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, | 986 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, |