diff options
Diffstat (limited to 'net/nfc')
-rw-r--r-- | net/nfc/Kconfig | 14 | ||||
-rw-r--r-- | net/nfc/Makefile | 2 | ||||
-rw-r--r-- | net/nfc/core.c | 22 | ||||
-rw-r--r-- | net/nfc/digital.h | 170 | ||||
-rw-r--r-- | net/nfc/digital_core.c | 737 | ||||
-rw-r--r-- | net/nfc/digital_dep.c | 729 | ||||
-rw-r--r-- | net/nfc/digital_technology.c | 770 | ||||
-rw-r--r-- | net/nfc/nci/spi.c | 239 | ||||
-rw-r--r-- | net/nfc/netlink.c | 91 | ||||
-rw-r--r-- | net/nfc/rawsock.c | 7 |
10 files changed, 2627 insertions, 154 deletions
diff --git a/net/nfc/Kconfig b/net/nfc/Kconfig index 5948b2fc72f6..6e0fa0cce198 100644 --- a/net/nfc/Kconfig +++ b/net/nfc/Kconfig | |||
@@ -14,6 +14,20 @@ menuconfig NFC | |||
14 | To compile this support as a module, choose M here: the module will | 14 | To compile this support as a module, choose M here: the module will |
15 | be called nfc. | 15 | be called nfc. |
16 | 16 | ||
17 | config NFC_DIGITAL | ||
18 | depends on NFC | ||
19 | select CRC_CCITT | ||
20 | select CRC_ITU_T | ||
21 | tristate "NFC Digital Protocol stack support" | ||
22 | default n | ||
23 | help | ||
24 | Say Y if you want to build NFC digital protocol stack support. | ||
25 | This is needed by NFC chipsets whose firmware only implement | ||
26 | the NFC analog layer. | ||
27 | |||
28 | To compile this support as a module, choose M here: the module will | ||
29 | be called nfc_digital. | ||
30 | |||
17 | source "net/nfc/nci/Kconfig" | 31 | source "net/nfc/nci/Kconfig" |
18 | source "net/nfc/hci/Kconfig" | 32 | source "net/nfc/hci/Kconfig" |
19 | 33 | ||
diff --git a/net/nfc/Makefile b/net/nfc/Makefile index a76f4533cb6c..2555ff8e7219 100644 --- a/net/nfc/Makefile +++ b/net/nfc/Makefile | |||
@@ -5,7 +5,9 @@ | |||
5 | obj-$(CONFIG_NFC) += nfc.o | 5 | obj-$(CONFIG_NFC) += nfc.o |
6 | obj-$(CONFIG_NFC_NCI) += nci/ | 6 | obj-$(CONFIG_NFC_NCI) += nci/ |
7 | obj-$(CONFIG_NFC_HCI) += hci/ | 7 | obj-$(CONFIG_NFC_HCI) += hci/ |
8 | obj-$(CONFIG_NFC_DIGITAL) += nfc_digital.o | ||
8 | 9 | ||
9 | nfc-objs := core.o netlink.o af_nfc.o rawsock.o llcp_core.o llcp_commands.o \ | 10 | nfc-objs := core.o netlink.o af_nfc.o rawsock.o llcp_core.o llcp_commands.o \ |
10 | llcp_sock.o | 11 | llcp_sock.o |
11 | 12 | ||
13 | nfc_digital-objs := digital_core.o digital_technology.o digital_dep.o | ||
diff --git a/net/nfc/core.c b/net/nfc/core.c index e92923cf3e03..872529105abc 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c | |||
@@ -384,6 +384,19 @@ int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx, | |||
384 | { | 384 | { |
385 | dev->dep_link_up = true; | 385 | dev->dep_link_up = true; |
386 | 386 | ||
387 | if (!dev->active_target) { | ||
388 | struct nfc_target *target; | ||
389 | |||
390 | target = nfc_find_target(dev, target_idx); | ||
391 | if (target == NULL) | ||
392 | return -ENOTCONN; | ||
393 | |||
394 | dev->active_target = target; | ||
395 | } | ||
396 | |||
397 | dev->polling = false; | ||
398 | dev->rf_mode = rf_mode; | ||
399 | |||
387 | nfc_llcp_mac_is_up(dev, target_idx, comm_mode, rf_mode); | 400 | nfc_llcp_mac_is_up(dev, target_idx, comm_mode, rf_mode); |
388 | 401 | ||
389 | return nfc_genl_dep_link_up_event(dev, target_idx, comm_mode, rf_mode); | 402 | return nfc_genl_dep_link_up_event(dev, target_idx, comm_mode, rf_mode); |
@@ -536,7 +549,7 @@ error: | |||
536 | return rc; | 549 | return rc; |
537 | } | 550 | } |
538 | 551 | ||
539 | static struct nfc_se *find_se(struct nfc_dev *dev, u32 se_idx) | 552 | struct nfc_se *nfc_find_se(struct nfc_dev *dev, u32 se_idx) |
540 | { | 553 | { |
541 | struct nfc_se *se, *n; | 554 | struct nfc_se *se, *n; |
542 | 555 | ||
@@ -546,6 +559,7 @@ static struct nfc_se *find_se(struct nfc_dev *dev, u32 se_idx) | |||
546 | 559 | ||
547 | return NULL; | 560 | return NULL; |
548 | } | 561 | } |
562 | EXPORT_SYMBOL(nfc_find_se); | ||
549 | 563 | ||
550 | int nfc_enable_se(struct nfc_dev *dev, u32 se_idx) | 564 | int nfc_enable_se(struct nfc_dev *dev, u32 se_idx) |
551 | { | 565 | { |
@@ -577,7 +591,7 @@ int nfc_enable_se(struct nfc_dev *dev, u32 se_idx) | |||
577 | goto error; | 591 | goto error; |
578 | } | 592 | } |
579 | 593 | ||
580 | se = find_se(dev, se_idx); | 594 | se = nfc_find_se(dev, se_idx); |
581 | if (!se) { | 595 | if (!se) { |
582 | rc = -EINVAL; | 596 | rc = -EINVAL; |
583 | goto error; | 597 | goto error; |
@@ -622,7 +636,7 @@ int nfc_disable_se(struct nfc_dev *dev, u32 se_idx) | |||
622 | goto error; | 636 | goto error; |
623 | } | 637 | } |
624 | 638 | ||
625 | se = find_se(dev, se_idx); | 639 | se = nfc_find_se(dev, se_idx); |
626 | if (!se) { | 640 | if (!se) { |
627 | rc = -EINVAL; | 641 | rc = -EINVAL; |
628 | goto error; | 642 | goto error; |
@@ -881,7 +895,7 @@ int nfc_add_se(struct nfc_dev *dev, u32 se_idx, u16 type) | |||
881 | 895 | ||
882 | pr_debug("%s se index %d\n", dev_name(&dev->dev), se_idx); | 896 | pr_debug("%s se index %d\n", dev_name(&dev->dev), se_idx); |
883 | 897 | ||
884 | se = find_se(dev, se_idx); | 898 | se = nfc_find_se(dev, se_idx); |
885 | if (se) | 899 | if (se) |
886 | return -EALREADY; | 900 | return -EALREADY; |
887 | 901 | ||
diff --git a/net/nfc/digital.h b/net/nfc/digital.h new file mode 100644 index 000000000000..08b29b55ea63 --- /dev/null +++ b/net/nfc/digital.h | |||
@@ -0,0 +1,170 @@ | |||
1 | /* | ||
2 | * NFC Digital Protocol stack | ||
3 | * Copyright (c) 2013, Intel Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #ifndef __DIGITAL_H | ||
17 | #define __DIGITAL_H | ||
18 | |||
19 | #include <net/nfc/nfc.h> | ||
20 | #include <net/nfc/digital.h> | ||
21 | |||
22 | #include <linux/crc-ccitt.h> | ||
23 | #include <linux/crc-itu-t.h> | ||
24 | |||
25 | #define PROTOCOL_ERR(req) pr_err("%d: NFC Digital Protocol error: %s\n", \ | ||
26 | __LINE__, req) | ||
27 | |||
28 | #define DIGITAL_CMD_IN_SEND 0 | ||
29 | #define DIGITAL_CMD_TG_SEND 1 | ||
30 | #define DIGITAL_CMD_TG_LISTEN 2 | ||
31 | #define DIGITAL_CMD_TG_LISTEN_MDAA 3 | ||
32 | |||
33 | #define DIGITAL_MAX_HEADER_LEN 7 | ||
34 | #define DIGITAL_CRC_LEN 2 | ||
35 | |||
36 | #define DIGITAL_SENSF_NFCID2_NFC_DEP_B1 0x01 | ||
37 | #define DIGITAL_SENSF_NFCID2_NFC_DEP_B2 0xFE | ||
38 | |||
39 | #define DIGITAL_SENS_RES_NFC_DEP 0x0100 | ||
40 | #define DIGITAL_SEL_RES_NFC_DEP 0x40 | ||
41 | #define DIGITAL_SENSF_FELICA_SC 0xFFFF | ||
42 | |||
43 | #define DIGITAL_DRV_CAPS_IN_CRC(ddev) \ | ||
44 | ((ddev)->driver_capabilities & NFC_DIGITAL_DRV_CAPS_IN_CRC) | ||
45 | #define DIGITAL_DRV_CAPS_TG_CRC(ddev) \ | ||
46 | ((ddev)->driver_capabilities & NFC_DIGITAL_DRV_CAPS_TG_CRC) | ||
47 | |||
48 | struct digital_data_exch { | ||
49 | data_exchange_cb_t cb; | ||
50 | void *cb_context; | ||
51 | }; | ||
52 | |||
53 | struct sk_buff *digital_skb_alloc(struct nfc_digital_dev *ddev, | ||
54 | unsigned int len); | ||
55 | |||
56 | int digital_send_cmd(struct nfc_digital_dev *ddev, u8 cmd_type, | ||
57 | struct sk_buff *skb, struct digital_tg_mdaa_params *params, | ||
58 | u16 timeout, nfc_digital_cmd_complete_t cmd_cb, | ||
59 | void *cb_context); | ||
60 | |||
61 | int digital_in_configure_hw(struct nfc_digital_dev *ddev, int type, int param); | ||
62 | static inline int digital_in_send_cmd(struct nfc_digital_dev *ddev, | ||
63 | struct sk_buff *skb, u16 timeout, | ||
64 | nfc_digital_cmd_complete_t cmd_cb, | ||
65 | void *cb_context) | ||
66 | { | ||
67 | return digital_send_cmd(ddev, DIGITAL_CMD_IN_SEND, skb, NULL, timeout, | ||
68 | cmd_cb, cb_context); | ||
69 | } | ||
70 | |||
71 | void digital_poll_next_tech(struct nfc_digital_dev *ddev); | ||
72 | |||
73 | int digital_in_send_sens_req(struct nfc_digital_dev *ddev, u8 rf_tech); | ||
74 | int digital_in_send_sensf_req(struct nfc_digital_dev *ddev, u8 rf_tech); | ||
75 | |||
76 | int digital_target_found(struct nfc_digital_dev *ddev, | ||
77 | struct nfc_target *target, u8 protocol); | ||
78 | |||
79 | int digital_in_recv_mifare_res(struct sk_buff *resp); | ||
80 | |||
81 | int digital_in_send_atr_req(struct nfc_digital_dev *ddev, | ||
82 | struct nfc_target *target, __u8 comm_mode, __u8 *gb, | ||
83 | size_t gb_len); | ||
84 | int digital_in_send_dep_req(struct nfc_digital_dev *ddev, | ||
85 | struct nfc_target *target, struct sk_buff *skb, | ||
86 | struct digital_data_exch *data_exch); | ||
87 | |||
88 | int digital_tg_configure_hw(struct nfc_digital_dev *ddev, int type, int param); | ||
89 | static inline int digital_tg_send_cmd(struct nfc_digital_dev *ddev, | ||
90 | struct sk_buff *skb, u16 timeout, | ||
91 | nfc_digital_cmd_complete_t cmd_cb, void *cb_context) | ||
92 | { | ||
93 | return digital_send_cmd(ddev, DIGITAL_CMD_TG_SEND, skb, NULL, timeout, | ||
94 | cmd_cb, cb_context); | ||
95 | } | ||
96 | |||
97 | void digital_tg_recv_sens_req(struct nfc_digital_dev *ddev, void *arg, | ||
98 | struct sk_buff *resp); | ||
99 | |||
100 | void digital_tg_recv_sensf_req(struct nfc_digital_dev *ddev, void *arg, | ||
101 | struct sk_buff *resp); | ||
102 | |||
103 | static inline int digital_tg_listen(struct nfc_digital_dev *ddev, u16 timeout, | ||
104 | nfc_digital_cmd_complete_t cb, void *arg) | ||
105 | { | ||
106 | return digital_send_cmd(ddev, DIGITAL_CMD_TG_LISTEN, NULL, NULL, | ||
107 | timeout, cb, arg); | ||
108 | } | ||
109 | |||
110 | void digital_tg_recv_atr_req(struct nfc_digital_dev *ddev, void *arg, | ||
111 | struct sk_buff *resp); | ||
112 | |||
113 | int digital_tg_send_dep_res(struct nfc_digital_dev *ddev, struct sk_buff *skb); | ||
114 | |||
115 | int digital_tg_listen_nfca(struct nfc_digital_dev *ddev, u8 rf_tech); | ||
116 | int digital_tg_listen_nfcf(struct nfc_digital_dev *ddev, u8 rf_tech); | ||
117 | |||
118 | typedef u16 (*crc_func_t)(u16, const u8 *, size_t); | ||
119 | |||
120 | #define CRC_A_INIT 0x6363 | ||
121 | #define CRC_B_INIT 0xFFFF | ||
122 | #define CRC_F_INIT 0x0000 | ||
123 | |||
124 | void digital_skb_add_crc(struct sk_buff *skb, crc_func_t crc_func, u16 init, | ||
125 | u8 bitwise_inv, u8 msb_first); | ||
126 | |||
127 | static inline void digital_skb_add_crc_a(struct sk_buff *skb) | ||
128 | { | ||
129 | digital_skb_add_crc(skb, crc_ccitt, CRC_A_INIT, 0, 0); | ||
130 | } | ||
131 | |||
132 | static inline void digital_skb_add_crc_b(struct sk_buff *skb) | ||
133 | { | ||
134 | digital_skb_add_crc(skb, crc_ccitt, CRC_B_INIT, 1, 0); | ||
135 | } | ||
136 | |||
137 | static inline void digital_skb_add_crc_f(struct sk_buff *skb) | ||
138 | { | ||
139 | digital_skb_add_crc(skb, crc_itu_t, CRC_F_INIT, 0, 1); | ||
140 | } | ||
141 | |||
142 | static inline void digital_skb_add_crc_none(struct sk_buff *skb) | ||
143 | { | ||
144 | return; | ||
145 | } | ||
146 | |||
147 | int digital_skb_check_crc(struct sk_buff *skb, crc_func_t crc_func, | ||
148 | u16 crc_init, u8 bitwise_inv, u8 msb_first); | ||
149 | |||
150 | static inline int digital_skb_check_crc_a(struct sk_buff *skb) | ||
151 | { | ||
152 | return digital_skb_check_crc(skb, crc_ccitt, CRC_A_INIT, 0, 0); | ||
153 | } | ||
154 | |||
155 | static inline int digital_skb_check_crc_b(struct sk_buff *skb) | ||
156 | { | ||
157 | return digital_skb_check_crc(skb, crc_ccitt, CRC_B_INIT, 1, 0); | ||
158 | } | ||
159 | |||
160 | static inline int digital_skb_check_crc_f(struct sk_buff *skb) | ||
161 | { | ||
162 | return digital_skb_check_crc(skb, crc_itu_t, CRC_F_INIT, 0, 1); | ||
163 | } | ||
164 | |||
165 | static inline int digital_skb_check_crc_none(struct sk_buff *skb) | ||
166 | { | ||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | #endif /* __DIGITAL_H */ | ||
diff --git a/net/nfc/digital_core.c b/net/nfc/digital_core.c new file mode 100644 index 000000000000..09fc95439955 --- /dev/null +++ b/net/nfc/digital_core.c | |||
@@ -0,0 +1,737 @@ | |||
1 | /* | ||
2 | * NFC Digital Protocol stack | ||
3 | * Copyright (c) 2013, Intel Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #define pr_fmt(fmt) "digital: %s: " fmt, __func__ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | |||
20 | #include "digital.h" | ||
21 | |||
22 | #define DIGITAL_PROTO_NFCA_RF_TECH \ | ||
23 | (NFC_PROTO_JEWEL_MASK | NFC_PROTO_MIFARE_MASK | NFC_PROTO_NFC_DEP_MASK) | ||
24 | |||
25 | #define DIGITAL_PROTO_NFCF_RF_TECH \ | ||
26 | (NFC_PROTO_FELICA_MASK | NFC_PROTO_NFC_DEP_MASK) | ||
27 | |||
28 | struct digital_cmd { | ||
29 | struct list_head queue; | ||
30 | |||
31 | u8 type; | ||
32 | u8 pending; | ||
33 | |||
34 | u16 timeout; | ||
35 | struct sk_buff *req; | ||
36 | struct sk_buff *resp; | ||
37 | struct digital_tg_mdaa_params *mdaa_params; | ||
38 | |||
39 | nfc_digital_cmd_complete_t cmd_cb; | ||
40 | void *cb_context; | ||
41 | }; | ||
42 | |||
43 | struct sk_buff *digital_skb_alloc(struct nfc_digital_dev *ddev, | ||
44 | unsigned int len) | ||
45 | { | ||
46 | struct sk_buff *skb; | ||
47 | |||
48 | skb = alloc_skb(len + ddev->tx_headroom + ddev->tx_tailroom, | ||
49 | GFP_KERNEL); | ||
50 | if (skb) | ||
51 | skb_reserve(skb, ddev->tx_headroom); | ||
52 | |||
53 | return skb; | ||
54 | } | ||
55 | |||
56 | void digital_skb_add_crc(struct sk_buff *skb, crc_func_t crc_func, u16 init, | ||
57 | u8 bitwise_inv, u8 msb_first) | ||
58 | { | ||
59 | u16 crc; | ||
60 | |||
61 | crc = crc_func(init, skb->data, skb->len); | ||
62 | |||
63 | if (bitwise_inv) | ||
64 | crc = ~crc; | ||
65 | |||
66 | if (msb_first) | ||
67 | crc = __fswab16(crc); | ||
68 | |||
69 | *skb_put(skb, 1) = crc & 0xFF; | ||
70 | *skb_put(skb, 1) = (crc >> 8) & 0xFF; | ||
71 | } | ||
72 | |||
73 | int digital_skb_check_crc(struct sk_buff *skb, crc_func_t crc_func, | ||
74 | u16 crc_init, u8 bitwise_inv, u8 msb_first) | ||
75 | { | ||
76 | int rc; | ||
77 | u16 crc; | ||
78 | |||
79 | if (skb->len <= 2) | ||
80 | return -EIO; | ||
81 | |||
82 | crc = crc_func(crc_init, skb->data, skb->len - 2); | ||
83 | |||
84 | if (bitwise_inv) | ||
85 | crc = ~crc; | ||
86 | |||
87 | if (msb_first) | ||
88 | crc = __swab16(crc); | ||
89 | |||
90 | rc = (skb->data[skb->len - 2] - (crc & 0xFF)) + | ||
91 | (skb->data[skb->len - 1] - ((crc >> 8) & 0xFF)); | ||
92 | |||
93 | if (rc) | ||
94 | return -EIO; | ||
95 | |||
96 | skb_trim(skb, skb->len - 2); | ||
97 | |||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | static inline void digital_switch_rf(struct nfc_digital_dev *ddev, bool on) | ||
102 | { | ||
103 | ddev->ops->switch_rf(ddev, on); | ||
104 | } | ||
105 | |||
106 | static inline void digital_abort_cmd(struct nfc_digital_dev *ddev) | ||
107 | { | ||
108 | ddev->ops->abort_cmd(ddev); | ||
109 | } | ||
110 | |||
111 | static void digital_wq_cmd_complete(struct work_struct *work) | ||
112 | { | ||
113 | struct digital_cmd *cmd; | ||
114 | struct nfc_digital_dev *ddev = container_of(work, | ||
115 | struct nfc_digital_dev, | ||
116 | cmd_complete_work); | ||
117 | |||
118 | mutex_lock(&ddev->cmd_lock); | ||
119 | |||
120 | cmd = list_first_entry_or_null(&ddev->cmd_queue, struct digital_cmd, | ||
121 | queue); | ||
122 | if (!cmd) { | ||
123 | mutex_unlock(&ddev->cmd_lock); | ||
124 | return; | ||
125 | } | ||
126 | |||
127 | list_del(&cmd->queue); | ||
128 | |||
129 | mutex_unlock(&ddev->cmd_lock); | ||
130 | |||
131 | if (!IS_ERR(cmd->resp)) | ||
132 | print_hex_dump_debug("DIGITAL RX: ", DUMP_PREFIX_NONE, 16, 1, | ||
133 | cmd->resp->data, cmd->resp->len, false); | ||
134 | |||
135 | cmd->cmd_cb(ddev, cmd->cb_context, cmd->resp); | ||
136 | |||
137 | kfree(cmd->mdaa_params); | ||
138 | kfree(cmd); | ||
139 | |||
140 | schedule_work(&ddev->cmd_work); | ||
141 | } | ||
142 | |||
143 | static void digital_send_cmd_complete(struct nfc_digital_dev *ddev, | ||
144 | void *arg, struct sk_buff *resp) | ||
145 | { | ||
146 | struct digital_cmd *cmd = arg; | ||
147 | |||
148 | cmd->resp = resp; | ||
149 | |||
150 | schedule_work(&ddev->cmd_complete_work); | ||
151 | } | ||
152 | |||
153 | static void digital_wq_cmd(struct work_struct *work) | ||
154 | { | ||
155 | int rc; | ||
156 | struct digital_cmd *cmd; | ||
157 | struct digital_tg_mdaa_params *params; | ||
158 | struct nfc_digital_dev *ddev = container_of(work, | ||
159 | struct nfc_digital_dev, | ||
160 | cmd_work); | ||
161 | |||
162 | mutex_lock(&ddev->cmd_lock); | ||
163 | |||
164 | cmd = list_first_entry_or_null(&ddev->cmd_queue, struct digital_cmd, | ||
165 | queue); | ||
166 | if (!cmd || cmd->pending) { | ||
167 | mutex_unlock(&ddev->cmd_lock); | ||
168 | return; | ||
169 | } | ||
170 | |||
171 | mutex_unlock(&ddev->cmd_lock); | ||
172 | |||
173 | if (cmd->req) | ||
174 | print_hex_dump_debug("DIGITAL TX: ", DUMP_PREFIX_NONE, 16, 1, | ||
175 | cmd->req->data, cmd->req->len, false); | ||
176 | |||
177 | switch (cmd->type) { | ||
178 | case DIGITAL_CMD_IN_SEND: | ||
179 | rc = ddev->ops->in_send_cmd(ddev, cmd->req, cmd->timeout, | ||
180 | digital_send_cmd_complete, cmd); | ||
181 | break; | ||
182 | |||
183 | case DIGITAL_CMD_TG_SEND: | ||
184 | rc = ddev->ops->tg_send_cmd(ddev, cmd->req, cmd->timeout, | ||
185 | digital_send_cmd_complete, cmd); | ||
186 | break; | ||
187 | |||
188 | case DIGITAL_CMD_TG_LISTEN: | ||
189 | rc = ddev->ops->tg_listen(ddev, cmd->timeout, | ||
190 | digital_send_cmd_complete, cmd); | ||
191 | break; | ||
192 | |||
193 | case DIGITAL_CMD_TG_LISTEN_MDAA: | ||
194 | params = cmd->mdaa_params; | ||
195 | |||
196 | rc = ddev->ops->tg_listen_mdaa(ddev, params, cmd->timeout, | ||
197 | digital_send_cmd_complete, cmd); | ||
198 | break; | ||
199 | |||
200 | default: | ||
201 | pr_err("Unknown cmd type %d\n", cmd->type); | ||
202 | return; | ||
203 | } | ||
204 | |||
205 | if (!rc) | ||
206 | return; | ||
207 | |||
208 | pr_err("in_send_command returned err %d\n", rc); | ||
209 | |||
210 | mutex_lock(&ddev->cmd_lock); | ||
211 | list_del(&cmd->queue); | ||
212 | mutex_unlock(&ddev->cmd_lock); | ||
213 | |||
214 | kfree_skb(cmd->req); | ||
215 | kfree(cmd->mdaa_params); | ||
216 | kfree(cmd); | ||
217 | |||
218 | schedule_work(&ddev->cmd_work); | ||
219 | } | ||
220 | |||
221 | int digital_send_cmd(struct nfc_digital_dev *ddev, u8 cmd_type, | ||
222 | struct sk_buff *skb, struct digital_tg_mdaa_params *params, | ||
223 | u16 timeout, nfc_digital_cmd_complete_t cmd_cb, | ||
224 | void *cb_context) | ||
225 | { | ||
226 | struct digital_cmd *cmd; | ||
227 | |||
228 | cmd = kzalloc(sizeof(struct digital_cmd), GFP_KERNEL); | ||
229 | if (!cmd) | ||
230 | return -ENOMEM; | ||
231 | |||
232 | cmd->type = cmd_type; | ||
233 | cmd->timeout = timeout; | ||
234 | cmd->req = skb; | ||
235 | cmd->mdaa_params = params; | ||
236 | cmd->cmd_cb = cmd_cb; | ||
237 | cmd->cb_context = cb_context; | ||
238 | INIT_LIST_HEAD(&cmd->queue); | ||
239 | |||
240 | mutex_lock(&ddev->cmd_lock); | ||
241 | list_add_tail(&cmd->queue, &ddev->cmd_queue); | ||
242 | mutex_unlock(&ddev->cmd_lock); | ||
243 | |||
244 | schedule_work(&ddev->cmd_work); | ||
245 | |||
246 | return 0; | ||
247 | } | ||
248 | |||
249 | int digital_in_configure_hw(struct nfc_digital_dev *ddev, int type, int param) | ||
250 | { | ||
251 | int rc; | ||
252 | |||
253 | rc = ddev->ops->in_configure_hw(ddev, type, param); | ||
254 | if (rc) | ||
255 | pr_err("in_configure_hw failed: %d\n", rc); | ||
256 | |||
257 | return rc; | ||
258 | } | ||
259 | |||
260 | int digital_tg_configure_hw(struct nfc_digital_dev *ddev, int type, int param) | ||
261 | { | ||
262 | int rc; | ||
263 | |||
264 | rc = ddev->ops->tg_configure_hw(ddev, type, param); | ||
265 | if (rc) | ||
266 | pr_err("tg_configure_hw failed: %d\n", rc); | ||
267 | |||
268 | return rc; | ||
269 | } | ||
270 | |||
271 | static int digital_tg_listen_mdaa(struct nfc_digital_dev *ddev, u8 rf_tech) | ||
272 | { | ||
273 | struct digital_tg_mdaa_params *params; | ||
274 | |||
275 | params = kzalloc(sizeof(struct digital_tg_mdaa_params), GFP_KERNEL); | ||
276 | if (!params) | ||
277 | return -ENOMEM; | ||
278 | |||
279 | params->sens_res = DIGITAL_SENS_RES_NFC_DEP; | ||
280 | get_random_bytes(params->nfcid1, sizeof(params->nfcid1)); | ||
281 | params->sel_res = DIGITAL_SEL_RES_NFC_DEP; | ||
282 | |||
283 | params->nfcid2[0] = DIGITAL_SENSF_NFCID2_NFC_DEP_B1; | ||
284 | params->nfcid2[1] = DIGITAL_SENSF_NFCID2_NFC_DEP_B2; | ||
285 | get_random_bytes(params->nfcid2 + 2, NFC_NFCID2_MAXSIZE - 2); | ||
286 | params->sc = DIGITAL_SENSF_FELICA_SC; | ||
287 | |||
288 | return digital_send_cmd(ddev, DIGITAL_CMD_TG_LISTEN_MDAA, NULL, params, | ||
289 | 500, digital_tg_recv_atr_req, NULL); | ||
290 | } | ||
291 | |||
292 | int digital_target_found(struct nfc_digital_dev *ddev, | ||
293 | struct nfc_target *target, u8 protocol) | ||
294 | { | ||
295 | int rc; | ||
296 | u8 framing; | ||
297 | u8 rf_tech; | ||
298 | int (*check_crc)(struct sk_buff *skb); | ||
299 | void (*add_crc)(struct sk_buff *skb); | ||
300 | |||
301 | rf_tech = ddev->poll_techs[ddev->poll_tech_index].rf_tech; | ||
302 | |||
303 | switch (protocol) { | ||
304 | case NFC_PROTO_JEWEL: | ||
305 | framing = NFC_DIGITAL_FRAMING_NFCA_T1T; | ||
306 | check_crc = digital_skb_check_crc_b; | ||
307 | add_crc = digital_skb_add_crc_b; | ||
308 | break; | ||
309 | |||
310 | case NFC_PROTO_MIFARE: | ||
311 | framing = NFC_DIGITAL_FRAMING_NFCA_T2T; | ||
312 | check_crc = digital_skb_check_crc_a; | ||
313 | add_crc = digital_skb_add_crc_a; | ||
314 | break; | ||
315 | |||
316 | case NFC_PROTO_FELICA: | ||
317 | framing = NFC_DIGITAL_FRAMING_NFCF_T3T; | ||
318 | check_crc = digital_skb_check_crc_f; | ||
319 | add_crc = digital_skb_add_crc_f; | ||
320 | break; | ||
321 | |||
322 | case NFC_PROTO_NFC_DEP: | ||
323 | if (rf_tech == NFC_DIGITAL_RF_TECH_106A) { | ||
324 | framing = NFC_DIGITAL_FRAMING_NFCA_NFC_DEP; | ||
325 | check_crc = digital_skb_check_crc_a; | ||
326 | add_crc = digital_skb_add_crc_a; | ||
327 | } else { | ||
328 | framing = NFC_DIGITAL_FRAMING_NFCF_NFC_DEP; | ||
329 | check_crc = digital_skb_check_crc_f; | ||
330 | add_crc = digital_skb_add_crc_f; | ||
331 | } | ||
332 | break; | ||
333 | |||
334 | default: | ||
335 | pr_err("Invalid protocol %d\n", protocol); | ||
336 | return -EINVAL; | ||
337 | } | ||
338 | |||
339 | pr_debug("rf_tech=%d, protocol=%d\n", rf_tech, protocol); | ||
340 | |||
341 | ddev->curr_rf_tech = rf_tech; | ||
342 | ddev->curr_protocol = protocol; | ||
343 | |||
344 | if (DIGITAL_DRV_CAPS_IN_CRC(ddev)) { | ||
345 | ddev->skb_add_crc = digital_skb_add_crc_none; | ||
346 | ddev->skb_check_crc = digital_skb_check_crc_none; | ||
347 | } else { | ||
348 | ddev->skb_add_crc = add_crc; | ||
349 | ddev->skb_check_crc = check_crc; | ||
350 | } | ||
351 | |||
352 | rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, framing); | ||
353 | if (rc) | ||
354 | return rc; | ||
355 | |||
356 | target->supported_protocols = (1 << protocol); | ||
357 | rc = nfc_targets_found(ddev->nfc_dev, target, 1); | ||
358 | if (rc) | ||
359 | return rc; | ||
360 | |||
361 | ddev->poll_tech_count = 0; | ||
362 | |||
363 | return 0; | ||
364 | } | ||
365 | |||
366 | void digital_poll_next_tech(struct nfc_digital_dev *ddev) | ||
367 | { | ||
368 | digital_switch_rf(ddev, 0); | ||
369 | |||
370 | mutex_lock(&ddev->poll_lock); | ||
371 | |||
372 | if (!ddev->poll_tech_count) { | ||
373 | mutex_unlock(&ddev->poll_lock); | ||
374 | return; | ||
375 | } | ||
376 | |||
377 | ddev->poll_tech_index = (ddev->poll_tech_index + 1) % | ||
378 | ddev->poll_tech_count; | ||
379 | |||
380 | mutex_unlock(&ddev->poll_lock); | ||
381 | |||
382 | schedule_work(&ddev->poll_work); | ||
383 | } | ||
384 | |||
385 | static void digital_wq_poll(struct work_struct *work) | ||
386 | { | ||
387 | int rc; | ||
388 | struct digital_poll_tech *poll_tech; | ||
389 | struct nfc_digital_dev *ddev = container_of(work, | ||
390 | struct nfc_digital_dev, | ||
391 | poll_work); | ||
392 | mutex_lock(&ddev->poll_lock); | ||
393 | |||
394 | if (!ddev->poll_tech_count) { | ||
395 | mutex_unlock(&ddev->poll_lock); | ||
396 | return; | ||
397 | } | ||
398 | |||
399 | poll_tech = &ddev->poll_techs[ddev->poll_tech_index]; | ||
400 | |||
401 | mutex_unlock(&ddev->poll_lock); | ||
402 | |||
403 | rc = poll_tech->poll_func(ddev, poll_tech->rf_tech); | ||
404 | if (rc) | ||
405 | digital_poll_next_tech(ddev); | ||
406 | } | ||
407 | |||
408 | static void digital_add_poll_tech(struct nfc_digital_dev *ddev, u8 rf_tech, | ||
409 | digital_poll_t poll_func) | ||
410 | { | ||
411 | struct digital_poll_tech *poll_tech; | ||
412 | |||
413 | if (ddev->poll_tech_count >= NFC_DIGITAL_POLL_MODE_COUNT_MAX) | ||
414 | return; | ||
415 | |||
416 | poll_tech = &ddev->poll_techs[ddev->poll_tech_count++]; | ||
417 | |||
418 | poll_tech->rf_tech = rf_tech; | ||
419 | poll_tech->poll_func = poll_func; | ||
420 | } | ||
421 | |||
422 | /** | ||
423 | * start_poll operation | ||
424 | * | ||
425 | * For every supported protocol, the corresponding polling function is added | ||
426 | * to the table of polling technologies (ddev->poll_techs[]) using | ||
427 | * digital_add_poll_tech(). | ||
428 | * When a polling function fails (by timeout or protocol error) the next one is | ||
429 | * schedule by digital_poll_next_tech() on the poll workqueue (ddev->poll_work). | ||
430 | */ | ||
431 | static int digital_start_poll(struct nfc_dev *nfc_dev, __u32 im_protocols, | ||
432 | __u32 tm_protocols) | ||
433 | { | ||
434 | struct nfc_digital_dev *ddev = nfc_get_drvdata(nfc_dev); | ||
435 | u32 matching_im_protocols, matching_tm_protocols; | ||
436 | |||
437 | pr_debug("protocols: im 0x%x, tm 0x%x, supported 0x%x\n", im_protocols, | ||
438 | tm_protocols, ddev->protocols); | ||
439 | |||
440 | matching_im_protocols = ddev->protocols & im_protocols; | ||
441 | matching_tm_protocols = ddev->protocols & tm_protocols; | ||
442 | |||
443 | if (!matching_im_protocols && !matching_tm_protocols) { | ||
444 | pr_err("Unknown protocol\n"); | ||
445 | return -EINVAL; | ||
446 | } | ||
447 | |||
448 | if (ddev->poll_tech_count) { | ||
449 | pr_err("Already polling\n"); | ||
450 | return -EBUSY; | ||
451 | } | ||
452 | |||
453 | if (ddev->curr_protocol) { | ||
454 | pr_err("A target is already active\n"); | ||
455 | return -EBUSY; | ||
456 | } | ||
457 | |||
458 | ddev->poll_tech_count = 0; | ||
459 | ddev->poll_tech_index = 0; | ||
460 | |||
461 | if (matching_im_protocols & DIGITAL_PROTO_NFCA_RF_TECH) | ||
462 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_106A, | ||
463 | digital_in_send_sens_req); | ||
464 | |||
465 | if (im_protocols & DIGITAL_PROTO_NFCF_RF_TECH) { | ||
466 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_212F, | ||
467 | digital_in_send_sensf_req); | ||
468 | |||
469 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_424F, | ||
470 | digital_in_send_sensf_req); | ||
471 | } | ||
472 | |||
473 | if (tm_protocols & NFC_PROTO_NFC_DEP_MASK) { | ||
474 | if (ddev->ops->tg_listen_mdaa) { | ||
475 | digital_add_poll_tech(ddev, 0, | ||
476 | digital_tg_listen_mdaa); | ||
477 | } else { | ||
478 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_106A, | ||
479 | digital_tg_listen_nfca); | ||
480 | |||
481 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_212F, | ||
482 | digital_tg_listen_nfcf); | ||
483 | |||
484 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_424F, | ||
485 | digital_tg_listen_nfcf); | ||
486 | } | ||
487 | } | ||
488 | |||
489 | if (!ddev->poll_tech_count) { | ||
490 | pr_err("Unsupported protocols: im=0x%x, tm=0x%x\n", | ||
491 | matching_im_protocols, matching_tm_protocols); | ||
492 | return -EINVAL; | ||
493 | } | ||
494 | |||
495 | schedule_work(&ddev->poll_work); | ||
496 | |||
497 | return 0; | ||
498 | } | ||
499 | |||
500 | static void digital_stop_poll(struct nfc_dev *nfc_dev) | ||
501 | { | ||
502 | struct nfc_digital_dev *ddev = nfc_get_drvdata(nfc_dev); | ||
503 | |||
504 | mutex_lock(&ddev->poll_lock); | ||
505 | |||
506 | if (!ddev->poll_tech_count) { | ||
507 | pr_err("Polling operation was not running\n"); | ||
508 | mutex_unlock(&ddev->poll_lock); | ||
509 | return; | ||
510 | } | ||
511 | |||
512 | ddev->poll_tech_count = 0; | ||
513 | |||
514 | mutex_unlock(&ddev->poll_lock); | ||
515 | |||
516 | cancel_work_sync(&ddev->poll_work); | ||
517 | |||
518 | digital_abort_cmd(ddev); | ||
519 | } | ||
520 | |||
521 | static int digital_dev_up(struct nfc_dev *nfc_dev) | ||
522 | { | ||
523 | struct nfc_digital_dev *ddev = nfc_get_drvdata(nfc_dev); | ||
524 | |||
525 | digital_switch_rf(ddev, 1); | ||
526 | |||
527 | return 0; | ||
528 | } | ||
529 | |||
530 | static int digital_dev_down(struct nfc_dev *nfc_dev) | ||
531 | { | ||
532 | struct nfc_digital_dev *ddev = nfc_get_drvdata(nfc_dev); | ||
533 | |||
534 | digital_switch_rf(ddev, 0); | ||
535 | |||
536 | return 0; | ||
537 | } | ||
538 | |||
539 | static int digital_dep_link_up(struct nfc_dev *nfc_dev, | ||
540 | struct nfc_target *target, | ||
541 | __u8 comm_mode, __u8 *gb, size_t gb_len) | ||
542 | { | ||
543 | struct nfc_digital_dev *ddev = nfc_get_drvdata(nfc_dev); | ||
544 | |||
545 | return digital_in_send_atr_req(ddev, target, comm_mode, gb, gb_len); | ||
546 | } | ||
547 | |||
548 | static int digital_dep_link_down(struct nfc_dev *nfc_dev) | ||
549 | { | ||
550 | struct nfc_digital_dev *ddev = nfc_get_drvdata(nfc_dev); | ||
551 | |||
552 | ddev->curr_protocol = 0; | ||
553 | |||
554 | return 0; | ||
555 | } | ||
556 | |||
557 | static int digital_activate_target(struct nfc_dev *nfc_dev, | ||
558 | struct nfc_target *target, __u32 protocol) | ||
559 | { | ||
560 | return 0; | ||
561 | } | ||
562 | |||
563 | static void digital_deactivate_target(struct nfc_dev *nfc_dev, | ||
564 | struct nfc_target *target) | ||
565 | { | ||
566 | struct nfc_digital_dev *ddev = nfc_get_drvdata(nfc_dev); | ||
567 | |||
568 | ddev->curr_protocol = 0; | ||
569 | } | ||
570 | |||
571 | static int digital_tg_send(struct nfc_dev *dev, struct sk_buff *skb) | ||
572 | { | ||
573 | struct nfc_digital_dev *ddev = nfc_get_drvdata(dev); | ||
574 | |||
575 | return digital_tg_send_dep_res(ddev, skb); | ||
576 | } | ||
577 | |||
578 | static void digital_in_send_complete(struct nfc_digital_dev *ddev, void *arg, | ||
579 | struct sk_buff *resp) | ||
580 | { | ||
581 | struct digital_data_exch *data_exch = arg; | ||
582 | int rc; | ||
583 | |||
584 | if (IS_ERR(resp)) { | ||
585 | rc = PTR_ERR(resp); | ||
586 | goto done; | ||
587 | } | ||
588 | |||
589 | if (ddev->curr_protocol == NFC_PROTO_MIFARE) | ||
590 | rc = digital_in_recv_mifare_res(resp); | ||
591 | else | ||
592 | rc = ddev->skb_check_crc(resp); | ||
593 | |||
594 | if (rc) { | ||
595 | kfree_skb(resp); | ||
596 | resp = NULL; | ||
597 | } | ||
598 | |||
599 | done: | ||
600 | data_exch->cb(data_exch->cb_context, resp, rc); | ||
601 | |||
602 | kfree(data_exch); | ||
603 | } | ||
604 | |||
605 | static int digital_in_send(struct nfc_dev *nfc_dev, struct nfc_target *target, | ||
606 | struct sk_buff *skb, data_exchange_cb_t cb, | ||
607 | void *cb_context) | ||
608 | { | ||
609 | struct nfc_digital_dev *ddev = nfc_get_drvdata(nfc_dev); | ||
610 | struct digital_data_exch *data_exch; | ||
611 | |||
612 | data_exch = kzalloc(sizeof(struct digital_data_exch), GFP_KERNEL); | ||
613 | if (!data_exch) { | ||
614 | pr_err("Failed to allocate data_exch struct\n"); | ||
615 | return -ENOMEM; | ||
616 | } | ||
617 | |||
618 | data_exch->cb = cb; | ||
619 | data_exch->cb_context = cb_context; | ||
620 | |||
621 | if (ddev->curr_protocol == NFC_PROTO_NFC_DEP) | ||
622 | return digital_in_send_dep_req(ddev, target, skb, data_exch); | ||
623 | |||
624 | ddev->skb_add_crc(skb); | ||
625 | |||
626 | return digital_in_send_cmd(ddev, skb, 500, digital_in_send_complete, | ||
627 | data_exch); | ||
628 | } | ||
629 | |||
630 | static struct nfc_ops digital_nfc_ops = { | ||
631 | .dev_up = digital_dev_up, | ||
632 | .dev_down = digital_dev_down, | ||
633 | .start_poll = digital_start_poll, | ||
634 | .stop_poll = digital_stop_poll, | ||
635 | .dep_link_up = digital_dep_link_up, | ||
636 | .dep_link_down = digital_dep_link_down, | ||
637 | .activate_target = digital_activate_target, | ||
638 | .deactivate_target = digital_deactivate_target, | ||
639 | .tm_send = digital_tg_send, | ||
640 | .im_transceive = digital_in_send, | ||
641 | }; | ||
642 | |||
643 | struct nfc_digital_dev *nfc_digital_allocate_device(struct nfc_digital_ops *ops, | ||
644 | __u32 supported_protocols, | ||
645 | __u32 driver_capabilities, | ||
646 | int tx_headroom, int tx_tailroom) | ||
647 | { | ||
648 | struct nfc_digital_dev *ddev; | ||
649 | |||
650 | if (!ops->in_configure_hw || !ops->in_send_cmd || !ops->tg_listen || | ||
651 | !ops->tg_configure_hw || !ops->tg_send_cmd || !ops->abort_cmd || | ||
652 | !ops->switch_rf) | ||
653 | return NULL; | ||
654 | |||
655 | ddev = kzalloc(sizeof(struct nfc_digital_dev), GFP_KERNEL); | ||
656 | if (!ddev) | ||
657 | return NULL; | ||
658 | |||
659 | ddev->driver_capabilities = driver_capabilities; | ||
660 | ddev->ops = ops; | ||
661 | |||
662 | mutex_init(&ddev->cmd_lock); | ||
663 | INIT_LIST_HEAD(&ddev->cmd_queue); | ||
664 | |||
665 | INIT_WORK(&ddev->cmd_work, digital_wq_cmd); | ||
666 | INIT_WORK(&ddev->cmd_complete_work, digital_wq_cmd_complete); | ||
667 | |||
668 | mutex_init(&ddev->poll_lock); | ||
669 | INIT_WORK(&ddev->poll_work, digital_wq_poll); | ||
670 | |||
671 | if (supported_protocols & NFC_PROTO_JEWEL_MASK) | ||
672 | ddev->protocols |= NFC_PROTO_JEWEL_MASK; | ||
673 | if (supported_protocols & NFC_PROTO_MIFARE_MASK) | ||
674 | ddev->protocols |= NFC_PROTO_MIFARE_MASK; | ||
675 | if (supported_protocols & NFC_PROTO_FELICA_MASK) | ||
676 | ddev->protocols |= NFC_PROTO_FELICA_MASK; | ||
677 | if (supported_protocols & NFC_PROTO_NFC_DEP_MASK) | ||
678 | ddev->protocols |= NFC_PROTO_NFC_DEP_MASK; | ||
679 | |||
680 | ddev->tx_headroom = tx_headroom + DIGITAL_MAX_HEADER_LEN; | ||
681 | ddev->tx_tailroom = tx_tailroom + DIGITAL_CRC_LEN; | ||
682 | |||
683 | ddev->nfc_dev = nfc_allocate_device(&digital_nfc_ops, ddev->protocols, | ||
684 | ddev->tx_headroom, | ||
685 | ddev->tx_tailroom); | ||
686 | if (!ddev->nfc_dev) { | ||
687 | pr_err("nfc_allocate_device failed\n"); | ||
688 | goto free_dev; | ||
689 | } | ||
690 | |||
691 | nfc_set_drvdata(ddev->nfc_dev, ddev); | ||
692 | |||
693 | return ddev; | ||
694 | |||
695 | free_dev: | ||
696 | kfree(ddev); | ||
697 | |||
698 | return NULL; | ||
699 | } | ||
700 | EXPORT_SYMBOL(nfc_digital_allocate_device); | ||
701 | |||
702 | void nfc_digital_free_device(struct nfc_digital_dev *ddev) | ||
703 | { | ||
704 | nfc_free_device(ddev->nfc_dev); | ||
705 | kfree(ddev); | ||
706 | } | ||
707 | EXPORT_SYMBOL(nfc_digital_free_device); | ||
708 | |||
709 | int nfc_digital_register_device(struct nfc_digital_dev *ddev) | ||
710 | { | ||
711 | return nfc_register_device(ddev->nfc_dev); | ||
712 | } | ||
713 | EXPORT_SYMBOL(nfc_digital_register_device); | ||
714 | |||
715 | void nfc_digital_unregister_device(struct nfc_digital_dev *ddev) | ||
716 | { | ||
717 | struct digital_cmd *cmd, *n; | ||
718 | |||
719 | nfc_unregister_device(ddev->nfc_dev); | ||
720 | |||
721 | mutex_lock(&ddev->poll_lock); | ||
722 | ddev->poll_tech_count = 0; | ||
723 | mutex_unlock(&ddev->poll_lock); | ||
724 | |||
725 | cancel_work_sync(&ddev->poll_work); | ||
726 | cancel_work_sync(&ddev->cmd_work); | ||
727 | cancel_work_sync(&ddev->cmd_complete_work); | ||
728 | |||
729 | list_for_each_entry_safe(cmd, n, &ddev->cmd_queue, queue) { | ||
730 | list_del(&cmd->queue); | ||
731 | kfree(cmd->mdaa_params); | ||
732 | kfree(cmd); | ||
733 | } | ||
734 | } | ||
735 | EXPORT_SYMBOL(nfc_digital_unregister_device); | ||
736 | |||
737 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/nfc/digital_dep.c b/net/nfc/digital_dep.c new file mode 100644 index 000000000000..07bbc24fb4c7 --- /dev/null +++ b/net/nfc/digital_dep.c | |||
@@ -0,0 +1,729 @@ | |||
1 | /* | ||
2 | * NFC Digital Protocol stack | ||
3 | * Copyright (c) 2013, Intel Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #define pr_fmt(fmt) "digital: %s: " fmt, __func__ | ||
17 | |||
18 | #include "digital.h" | ||
19 | |||
20 | #define DIGITAL_NFC_DEP_FRAME_DIR_OUT 0xD4 | ||
21 | #define DIGITAL_NFC_DEP_FRAME_DIR_IN 0xD5 | ||
22 | |||
23 | #define DIGITAL_NFC_DEP_NFCA_SOD_SB 0xF0 | ||
24 | |||
25 | #define DIGITAL_CMD_ATR_REQ 0x00 | ||
26 | #define DIGITAL_CMD_ATR_RES 0x01 | ||
27 | #define DIGITAL_CMD_PSL_REQ 0x04 | ||
28 | #define DIGITAL_CMD_PSL_RES 0x05 | ||
29 | #define DIGITAL_CMD_DEP_REQ 0x06 | ||
30 | #define DIGITAL_CMD_DEP_RES 0x07 | ||
31 | |||
32 | #define DIGITAL_ATR_REQ_MIN_SIZE 16 | ||
33 | #define DIGITAL_ATR_REQ_MAX_SIZE 64 | ||
34 | |||
35 | #define DIGITAL_NFCID3_LEN ((u8)8) | ||
36 | #define DIGITAL_LR_BITS_PAYLOAD_SIZE_254B 0x30 | ||
37 | #define DIGITAL_GB_BIT 0x02 | ||
38 | |||
39 | #define DIGITAL_NFC_DEP_PFB_TYPE(pfb) ((pfb) & 0xE0) | ||
40 | |||
41 | #define DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT 0x10 | ||
42 | |||
43 | #define DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb) \ | ||
44 | ((pfb) & DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT) | ||
45 | #define DIGITAL_NFC_DEP_MI_BIT_SET(pfb) ((pfb) & 0x10) | ||
46 | #define DIGITAL_NFC_DEP_NAD_BIT_SET(pfb) ((pfb) & 0x08) | ||
47 | #define DIGITAL_NFC_DEP_DID_BIT_SET(pfb) ((pfb) & 0x04) | ||
48 | #define DIGITAL_NFC_DEP_PFB_PNI(pfb) ((pfb) & 0x03) | ||
49 | |||
50 | #define DIGITAL_NFC_DEP_PFB_I_PDU 0x00 | ||
51 | #define DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU 0x40 | ||
52 | #define DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU 0x80 | ||
53 | |||
54 | struct digital_atr_req { | ||
55 | u8 dir; | ||
56 | u8 cmd; | ||
57 | u8 nfcid3[10]; | ||
58 | u8 did; | ||
59 | u8 bs; | ||
60 | u8 br; | ||
61 | u8 pp; | ||
62 | u8 gb[0]; | ||
63 | } __packed; | ||
64 | |||
65 | struct digital_atr_res { | ||
66 | u8 dir; | ||
67 | u8 cmd; | ||
68 | u8 nfcid3[10]; | ||
69 | u8 did; | ||
70 | u8 bs; | ||
71 | u8 br; | ||
72 | u8 to; | ||
73 | u8 pp; | ||
74 | u8 gb[0]; | ||
75 | } __packed; | ||
76 | |||
77 | struct digital_psl_req { | ||
78 | u8 dir; | ||
79 | u8 cmd; | ||
80 | u8 did; | ||
81 | u8 brs; | ||
82 | u8 fsl; | ||
83 | } __packed; | ||
84 | |||
85 | struct digital_psl_res { | ||
86 | u8 dir; | ||
87 | u8 cmd; | ||
88 | u8 did; | ||
89 | } __packed; | ||
90 | |||
91 | struct digital_dep_req_res { | ||
92 | u8 dir; | ||
93 | u8 cmd; | ||
94 | u8 pfb; | ||
95 | } __packed; | ||
96 | |||
97 | static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg, | ||
98 | struct sk_buff *resp); | ||
99 | |||
100 | static void digital_skb_push_dep_sod(struct nfc_digital_dev *ddev, | ||
101 | struct sk_buff *skb) | ||
102 | { | ||
103 | skb_push(skb, sizeof(u8)); | ||
104 | |||
105 | skb->data[0] = skb->len; | ||
106 | |||
107 | if (ddev->curr_rf_tech == NFC_DIGITAL_RF_TECH_106A) | ||
108 | *skb_push(skb, sizeof(u8)) = DIGITAL_NFC_DEP_NFCA_SOD_SB; | ||
109 | } | ||
110 | |||
111 | static int digital_skb_pull_dep_sod(struct nfc_digital_dev *ddev, | ||
112 | struct sk_buff *skb) | ||
113 | { | ||
114 | u8 size; | ||
115 | |||
116 | if (skb->len < 2) | ||
117 | return -EIO; | ||
118 | |||
119 | if (ddev->curr_rf_tech == NFC_DIGITAL_RF_TECH_106A) | ||
120 | skb_pull(skb, sizeof(u8)); | ||
121 | |||
122 | size = skb->data[0]; | ||
123 | if (size != skb->len) | ||
124 | return -EIO; | ||
125 | |||
126 | skb_pull(skb, sizeof(u8)); | ||
127 | |||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | static void digital_in_recv_atr_res(struct nfc_digital_dev *ddev, void *arg, | ||
132 | struct sk_buff *resp) | ||
133 | { | ||
134 | struct nfc_target *target = arg; | ||
135 | struct digital_atr_res *atr_res; | ||
136 | u8 gb_len; | ||
137 | int rc; | ||
138 | |||
139 | if (IS_ERR(resp)) { | ||
140 | rc = PTR_ERR(resp); | ||
141 | resp = NULL; | ||
142 | goto exit; | ||
143 | } | ||
144 | |||
145 | rc = ddev->skb_check_crc(resp); | ||
146 | if (rc) { | ||
147 | PROTOCOL_ERR("14.4.1.6"); | ||
148 | goto exit; | ||
149 | } | ||
150 | |||
151 | rc = digital_skb_pull_dep_sod(ddev, resp); | ||
152 | if (rc) { | ||
153 | PROTOCOL_ERR("14.4.1.2"); | ||
154 | goto exit; | ||
155 | } | ||
156 | |||
157 | if (resp->len < sizeof(struct digital_atr_res)) { | ||
158 | rc = -EIO; | ||
159 | goto exit; | ||
160 | } | ||
161 | |||
162 | gb_len = resp->len - sizeof(struct digital_atr_res); | ||
163 | |||
164 | atr_res = (struct digital_atr_res *)resp->data; | ||
165 | |||
166 | rc = nfc_set_remote_general_bytes(ddev->nfc_dev, atr_res->gb, gb_len); | ||
167 | if (rc) | ||
168 | goto exit; | ||
169 | |||
170 | rc = nfc_dep_link_is_up(ddev->nfc_dev, target->idx, NFC_COMM_ACTIVE, | ||
171 | NFC_RF_INITIATOR); | ||
172 | |||
173 | ddev->curr_nfc_dep_pni = 0; | ||
174 | |||
175 | exit: | ||
176 | dev_kfree_skb(resp); | ||
177 | |||
178 | if (rc) | ||
179 | ddev->curr_protocol = 0; | ||
180 | } | ||
181 | |||
182 | int digital_in_send_atr_req(struct nfc_digital_dev *ddev, | ||
183 | struct nfc_target *target, __u8 comm_mode, __u8 *gb, | ||
184 | size_t gb_len) | ||
185 | { | ||
186 | struct sk_buff *skb; | ||
187 | struct digital_atr_req *atr_req; | ||
188 | uint size; | ||
189 | |||
190 | size = DIGITAL_ATR_REQ_MIN_SIZE + gb_len; | ||
191 | |||
192 | if (size > DIGITAL_ATR_REQ_MAX_SIZE) { | ||
193 | PROTOCOL_ERR("14.6.1.1"); | ||
194 | return -EINVAL; | ||
195 | } | ||
196 | |||
197 | skb = digital_skb_alloc(ddev, size); | ||
198 | if (!skb) | ||
199 | return -ENOMEM; | ||
200 | |||
201 | skb_put(skb, sizeof(struct digital_atr_req)); | ||
202 | |||
203 | atr_req = (struct digital_atr_req *)skb->data; | ||
204 | memset(atr_req, 0, sizeof(struct digital_atr_req)); | ||
205 | |||
206 | atr_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT; | ||
207 | atr_req->cmd = DIGITAL_CMD_ATR_REQ; | ||
208 | if (target->nfcid2_len) | ||
209 | memcpy(atr_req->nfcid3, target->nfcid2, | ||
210 | max(target->nfcid2_len, DIGITAL_NFCID3_LEN)); | ||
211 | else | ||
212 | get_random_bytes(atr_req->nfcid3, DIGITAL_NFCID3_LEN); | ||
213 | |||
214 | atr_req->did = 0; | ||
215 | atr_req->bs = 0; | ||
216 | atr_req->br = 0; | ||
217 | |||
218 | atr_req->pp = DIGITAL_LR_BITS_PAYLOAD_SIZE_254B; | ||
219 | |||
220 | if (gb_len) { | ||
221 | atr_req->pp |= DIGITAL_GB_BIT; | ||
222 | memcpy(skb_put(skb, gb_len), gb, gb_len); | ||
223 | } | ||
224 | |||
225 | digital_skb_push_dep_sod(ddev, skb); | ||
226 | |||
227 | ddev->skb_add_crc(skb); | ||
228 | |||
229 | digital_in_send_cmd(ddev, skb, 500, digital_in_recv_atr_res, target); | ||
230 | |||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | static int digital_in_send_rtox(struct nfc_digital_dev *ddev, | ||
235 | struct digital_data_exch *data_exch, u8 rtox) | ||
236 | { | ||
237 | struct digital_dep_req_res *dep_req; | ||
238 | struct sk_buff *skb; | ||
239 | int rc; | ||
240 | |||
241 | skb = digital_skb_alloc(ddev, 1); | ||
242 | if (!skb) | ||
243 | return -ENOMEM; | ||
244 | |||
245 | *skb_put(skb, 1) = rtox; | ||
246 | |||
247 | skb_push(skb, sizeof(struct digital_dep_req_res)); | ||
248 | |||
249 | dep_req = (struct digital_dep_req_res *)skb->data; | ||
250 | |||
251 | dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT; | ||
252 | dep_req->cmd = DIGITAL_CMD_DEP_REQ; | ||
253 | dep_req->pfb = DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU | | ||
254 | DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT; | ||
255 | |||
256 | digital_skb_push_dep_sod(ddev, skb); | ||
257 | |||
258 | ddev->skb_add_crc(skb); | ||
259 | |||
260 | rc = digital_in_send_cmd(ddev, skb, 1500, digital_in_recv_dep_res, | ||
261 | data_exch); | ||
262 | |||
263 | return rc; | ||
264 | } | ||
265 | |||
266 | static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg, | ||
267 | struct sk_buff *resp) | ||
268 | { | ||
269 | struct digital_data_exch *data_exch = arg; | ||
270 | struct digital_dep_req_res *dep_res; | ||
271 | u8 pfb; | ||
272 | uint size; | ||
273 | int rc; | ||
274 | |||
275 | if (IS_ERR(resp)) { | ||
276 | rc = PTR_ERR(resp); | ||
277 | resp = NULL; | ||
278 | goto exit; | ||
279 | } | ||
280 | |||
281 | rc = ddev->skb_check_crc(resp); | ||
282 | if (rc) { | ||
283 | PROTOCOL_ERR("14.4.1.6"); | ||
284 | goto error; | ||
285 | } | ||
286 | |||
287 | rc = digital_skb_pull_dep_sod(ddev, resp); | ||
288 | if (rc) { | ||
289 | PROTOCOL_ERR("14.4.1.2"); | ||
290 | goto exit; | ||
291 | } | ||
292 | |||
293 | dep_res = (struct digital_dep_req_res *)resp->data; | ||
294 | |||
295 | if (resp->len < sizeof(struct digital_dep_req_res) || | ||
296 | dep_res->dir != DIGITAL_NFC_DEP_FRAME_DIR_IN || | ||
297 | dep_res->cmd != DIGITAL_CMD_DEP_RES) { | ||
298 | rc = -EIO; | ||
299 | goto error; | ||
300 | } | ||
301 | |||
302 | pfb = dep_res->pfb; | ||
303 | |||
304 | switch (DIGITAL_NFC_DEP_PFB_TYPE(pfb)) { | ||
305 | case DIGITAL_NFC_DEP_PFB_I_PDU: | ||
306 | if (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni) { | ||
307 | PROTOCOL_ERR("14.12.3.3"); | ||
308 | rc = -EIO; | ||
309 | goto error; | ||
310 | } | ||
311 | |||
312 | ddev->curr_nfc_dep_pni = | ||
313 | DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1); | ||
314 | rc = 0; | ||
315 | break; | ||
316 | |||
317 | case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU: | ||
318 | pr_err("Received a ACK/NACK PDU\n"); | ||
319 | rc = -EIO; | ||
320 | goto error; | ||
321 | |||
322 | case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU: | ||
323 | if (!DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb)) { | ||
324 | rc = -EINVAL; | ||
325 | goto error; | ||
326 | } | ||
327 | |||
328 | rc = digital_in_send_rtox(ddev, data_exch, resp->data[3]); | ||
329 | if (rc) | ||
330 | goto error; | ||
331 | |||
332 | kfree_skb(resp); | ||
333 | return; | ||
334 | } | ||
335 | |||
336 | if (DIGITAL_NFC_DEP_MI_BIT_SET(pfb)) { | ||
337 | pr_err("MI bit set. Chained PDU not supported\n"); | ||
338 | rc = -EIO; | ||
339 | goto error; | ||
340 | } | ||
341 | |||
342 | size = sizeof(struct digital_dep_req_res); | ||
343 | |||
344 | if (DIGITAL_NFC_DEP_DID_BIT_SET(pfb)) | ||
345 | size++; | ||
346 | |||
347 | if (size > resp->len) { | ||
348 | rc = -EIO; | ||
349 | goto error; | ||
350 | } | ||
351 | |||
352 | skb_pull(resp, size); | ||
353 | |||
354 | exit: | ||
355 | data_exch->cb(data_exch->cb_context, resp, rc); | ||
356 | |||
357 | error: | ||
358 | kfree(data_exch); | ||
359 | |||
360 | if (rc) | ||
361 | kfree_skb(resp); | ||
362 | } | ||
363 | |||
364 | int digital_in_send_dep_req(struct nfc_digital_dev *ddev, | ||
365 | struct nfc_target *target, struct sk_buff *skb, | ||
366 | struct digital_data_exch *data_exch) | ||
367 | { | ||
368 | struct digital_dep_req_res *dep_req; | ||
369 | |||
370 | skb_push(skb, sizeof(struct digital_dep_req_res)); | ||
371 | |||
372 | dep_req = (struct digital_dep_req_res *)skb->data; | ||
373 | dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT; | ||
374 | dep_req->cmd = DIGITAL_CMD_DEP_REQ; | ||
375 | dep_req->pfb = ddev->curr_nfc_dep_pni; | ||
376 | |||
377 | digital_skb_push_dep_sod(ddev, skb); | ||
378 | |||
379 | ddev->skb_add_crc(skb); | ||
380 | |||
381 | return digital_in_send_cmd(ddev, skb, 1500, digital_in_recv_dep_res, | ||
382 | data_exch); | ||
383 | } | ||
384 | |||
385 | static void digital_tg_recv_dep_req(struct nfc_digital_dev *ddev, void *arg, | ||
386 | struct sk_buff *resp) | ||
387 | { | ||
388 | int rc; | ||
389 | struct digital_dep_req_res *dep_req; | ||
390 | size_t size; | ||
391 | |||
392 | if (IS_ERR(resp)) { | ||
393 | rc = PTR_ERR(resp); | ||
394 | resp = NULL; | ||
395 | goto exit; | ||
396 | } | ||
397 | |||
398 | rc = ddev->skb_check_crc(resp); | ||
399 | if (rc) { | ||
400 | PROTOCOL_ERR("14.4.1.6"); | ||
401 | goto exit; | ||
402 | } | ||
403 | |||
404 | rc = digital_skb_pull_dep_sod(ddev, resp); | ||
405 | if (rc) { | ||
406 | PROTOCOL_ERR("14.4.1.2"); | ||
407 | goto exit; | ||
408 | } | ||
409 | |||
410 | size = sizeof(struct digital_dep_req_res); | ||
411 | dep_req = (struct digital_dep_req_res *)resp->data; | ||
412 | |||
413 | if (resp->len < size || dep_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT || | ||
414 | dep_req->cmd != DIGITAL_CMD_DEP_REQ) { | ||
415 | rc = -EIO; | ||
416 | goto exit; | ||
417 | } | ||
418 | |||
419 | if (DIGITAL_NFC_DEP_DID_BIT_SET(dep_req->pfb)) | ||
420 | size++; | ||
421 | |||
422 | if (resp->len < size) { | ||
423 | rc = -EIO; | ||
424 | goto exit; | ||
425 | } | ||
426 | |||
427 | switch (DIGITAL_NFC_DEP_PFB_TYPE(dep_req->pfb)) { | ||
428 | case DIGITAL_NFC_DEP_PFB_I_PDU: | ||
429 | pr_debug("DIGITAL_NFC_DEP_PFB_I_PDU\n"); | ||
430 | ddev->curr_nfc_dep_pni = DIGITAL_NFC_DEP_PFB_PNI(dep_req->pfb); | ||
431 | break; | ||
432 | case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU: | ||
433 | pr_err("Received a ACK/NACK PDU\n"); | ||
434 | rc = -EINVAL; | ||
435 | goto exit; | ||
436 | break; | ||
437 | case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU: | ||
438 | pr_err("Received a SUPERVISOR PDU\n"); | ||
439 | rc = -EINVAL; | ||
440 | goto exit; | ||
441 | break; | ||
442 | } | ||
443 | |||
444 | skb_pull(resp, size); | ||
445 | |||
446 | rc = nfc_tm_data_received(ddev->nfc_dev, resp); | ||
447 | |||
448 | exit: | ||
449 | if (rc) | ||
450 | kfree_skb(resp); | ||
451 | } | ||
452 | |||
453 | int digital_tg_send_dep_res(struct nfc_digital_dev *ddev, struct sk_buff *skb) | ||
454 | { | ||
455 | struct digital_dep_req_res *dep_res; | ||
456 | |||
457 | skb_push(skb, sizeof(struct digital_dep_req_res)); | ||
458 | dep_res = (struct digital_dep_req_res *)skb->data; | ||
459 | |||
460 | dep_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN; | ||
461 | dep_res->cmd = DIGITAL_CMD_DEP_RES; | ||
462 | dep_res->pfb = ddev->curr_nfc_dep_pni; | ||
463 | |||
464 | digital_skb_push_dep_sod(ddev, skb); | ||
465 | |||
466 | ddev->skb_add_crc(skb); | ||
467 | |||
468 | return digital_tg_send_cmd(ddev, skb, 1500, digital_tg_recv_dep_req, | ||
469 | NULL); | ||
470 | } | ||
471 | |||
472 | static void digital_tg_send_psl_res_complete(struct nfc_digital_dev *ddev, | ||
473 | void *arg, struct sk_buff *resp) | ||
474 | { | ||
475 | u8 rf_tech = PTR_ERR(arg); | ||
476 | |||
477 | if (IS_ERR(resp)) | ||
478 | return; | ||
479 | |||
480 | digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, rf_tech); | ||
481 | |||
482 | digital_tg_listen(ddev, 1500, digital_tg_recv_dep_req, NULL); | ||
483 | |||
484 | dev_kfree_skb(resp); | ||
485 | } | ||
486 | |||
487 | static int digital_tg_send_psl_res(struct nfc_digital_dev *ddev, u8 did, | ||
488 | u8 rf_tech) | ||
489 | { | ||
490 | struct digital_psl_res *psl_res; | ||
491 | struct sk_buff *skb; | ||
492 | int rc; | ||
493 | |||
494 | skb = digital_skb_alloc(ddev, sizeof(struct digital_psl_res)); | ||
495 | if (!skb) | ||
496 | return -ENOMEM; | ||
497 | |||
498 | skb_put(skb, sizeof(struct digital_psl_res)); | ||
499 | |||
500 | psl_res = (struct digital_psl_res *)skb->data; | ||
501 | |||
502 | psl_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN; | ||
503 | psl_res->cmd = DIGITAL_CMD_PSL_RES; | ||
504 | psl_res->did = did; | ||
505 | |||
506 | digital_skb_push_dep_sod(ddev, skb); | ||
507 | |||
508 | ddev->skb_add_crc(skb); | ||
509 | |||
510 | rc = digital_tg_send_cmd(ddev, skb, 0, digital_tg_send_psl_res_complete, | ||
511 | ERR_PTR(rf_tech)); | ||
512 | |||
513 | if (rc) | ||
514 | kfree_skb(skb); | ||
515 | |||
516 | return rc; | ||
517 | } | ||
518 | |||
519 | static void digital_tg_recv_psl_req(struct nfc_digital_dev *ddev, void *arg, | ||
520 | struct sk_buff *resp) | ||
521 | { | ||
522 | int rc; | ||
523 | struct digital_psl_req *psl_req; | ||
524 | u8 rf_tech; | ||
525 | u8 dsi; | ||
526 | |||
527 | if (IS_ERR(resp)) { | ||
528 | rc = PTR_ERR(resp); | ||
529 | resp = NULL; | ||
530 | goto exit; | ||
531 | } | ||
532 | |||
533 | rc = ddev->skb_check_crc(resp); | ||
534 | if (rc) { | ||
535 | PROTOCOL_ERR("14.4.1.6"); | ||
536 | goto exit; | ||
537 | } | ||
538 | |||
539 | rc = digital_skb_pull_dep_sod(ddev, resp); | ||
540 | if (rc) { | ||
541 | PROTOCOL_ERR("14.4.1.2"); | ||
542 | goto exit; | ||
543 | } | ||
544 | |||
545 | psl_req = (struct digital_psl_req *)resp->data; | ||
546 | |||
547 | if (resp->len != sizeof(struct digital_psl_req) || | ||
548 | psl_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT || | ||
549 | psl_req->cmd != DIGITAL_CMD_PSL_REQ) { | ||
550 | rc = -EIO; | ||
551 | goto exit; | ||
552 | } | ||
553 | |||
554 | dsi = (psl_req->brs >> 3) & 0x07; | ||
555 | switch (dsi) { | ||
556 | case 0: | ||
557 | rf_tech = NFC_DIGITAL_RF_TECH_106A; | ||
558 | break; | ||
559 | case 1: | ||
560 | rf_tech = NFC_DIGITAL_RF_TECH_212F; | ||
561 | break; | ||
562 | case 2: | ||
563 | rf_tech = NFC_DIGITAL_RF_TECH_424F; | ||
564 | break; | ||
565 | default: | ||
566 | pr_err("Unsuported dsi value %d\n", dsi); | ||
567 | goto exit; | ||
568 | } | ||
569 | |||
570 | rc = digital_tg_send_psl_res(ddev, psl_req->did, rf_tech); | ||
571 | |||
572 | exit: | ||
573 | kfree_skb(resp); | ||
574 | } | ||
575 | |||
576 | static void digital_tg_send_atr_res_complete(struct nfc_digital_dev *ddev, | ||
577 | void *arg, struct sk_buff *resp) | ||
578 | { | ||
579 | int offset; | ||
580 | |||
581 | if (IS_ERR(resp)) { | ||
582 | digital_poll_next_tech(ddev); | ||
583 | return; | ||
584 | } | ||
585 | |||
586 | offset = 2; | ||
587 | if (resp->data[0] == DIGITAL_NFC_DEP_NFCA_SOD_SB) | ||
588 | offset++; | ||
589 | |||
590 | if (resp->data[offset] == DIGITAL_CMD_PSL_REQ) | ||
591 | digital_tg_recv_psl_req(ddev, arg, resp); | ||
592 | else | ||
593 | digital_tg_recv_dep_req(ddev, arg, resp); | ||
594 | } | ||
595 | |||
596 | static int digital_tg_send_atr_res(struct nfc_digital_dev *ddev, | ||
597 | struct digital_atr_req *atr_req) | ||
598 | { | ||
599 | struct digital_atr_res *atr_res; | ||
600 | struct sk_buff *skb; | ||
601 | u8 *gb; | ||
602 | size_t gb_len; | ||
603 | int rc; | ||
604 | |||
605 | gb = nfc_get_local_general_bytes(ddev->nfc_dev, &gb_len); | ||
606 | if (!gb) | ||
607 | gb_len = 0; | ||
608 | |||
609 | skb = digital_skb_alloc(ddev, sizeof(struct digital_atr_res) + gb_len); | ||
610 | if (!skb) | ||
611 | return -ENOMEM; | ||
612 | |||
613 | skb_put(skb, sizeof(struct digital_atr_res)); | ||
614 | atr_res = (struct digital_atr_res *)skb->data; | ||
615 | |||
616 | memset(atr_res, 0, sizeof(struct digital_atr_res)); | ||
617 | |||
618 | atr_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN; | ||
619 | atr_res->cmd = DIGITAL_CMD_ATR_RES; | ||
620 | memcpy(atr_res->nfcid3, atr_req->nfcid3, sizeof(atr_req->nfcid3)); | ||
621 | atr_res->to = 8; | ||
622 | atr_res->pp = DIGITAL_LR_BITS_PAYLOAD_SIZE_254B; | ||
623 | if (gb_len) { | ||
624 | skb_put(skb, gb_len); | ||
625 | |||
626 | atr_res->pp |= DIGITAL_GB_BIT; | ||
627 | memcpy(atr_res->gb, gb, gb_len); | ||
628 | } | ||
629 | |||
630 | digital_skb_push_dep_sod(ddev, skb); | ||
631 | |||
632 | ddev->skb_add_crc(skb); | ||
633 | |||
634 | rc = digital_tg_send_cmd(ddev, skb, 999, | ||
635 | digital_tg_send_atr_res_complete, NULL); | ||
636 | if (rc) { | ||
637 | kfree_skb(skb); | ||
638 | return rc; | ||
639 | } | ||
640 | |||
641 | return rc; | ||
642 | } | ||
643 | |||
644 | void digital_tg_recv_atr_req(struct nfc_digital_dev *ddev, void *arg, | ||
645 | struct sk_buff *resp) | ||
646 | { | ||
647 | int rc; | ||
648 | struct digital_atr_req *atr_req; | ||
649 | size_t gb_len, min_size; | ||
650 | |||
651 | if (IS_ERR(resp)) { | ||
652 | rc = PTR_ERR(resp); | ||
653 | resp = NULL; | ||
654 | goto exit; | ||
655 | } | ||
656 | |||
657 | if (!resp->len) { | ||
658 | rc = -EIO; | ||
659 | goto exit; | ||
660 | } | ||
661 | |||
662 | if (resp->data[0] == DIGITAL_NFC_DEP_NFCA_SOD_SB) { | ||
663 | min_size = DIGITAL_ATR_REQ_MIN_SIZE + 2; | ||
664 | |||
665 | ddev->curr_rf_tech = NFC_DIGITAL_RF_TECH_106A; | ||
666 | ddev->skb_add_crc = digital_skb_add_crc_a; | ||
667 | ddev->skb_check_crc = digital_skb_check_crc_a; | ||
668 | } else { | ||
669 | min_size = DIGITAL_ATR_REQ_MIN_SIZE + 1; | ||
670 | |||
671 | ddev->curr_rf_tech = NFC_DIGITAL_RF_TECH_212F; | ||
672 | ddev->skb_add_crc = digital_skb_add_crc_f; | ||
673 | ddev->skb_check_crc = digital_skb_check_crc_f; | ||
674 | } | ||
675 | |||
676 | if (resp->len < min_size) { | ||
677 | rc = -EIO; | ||
678 | goto exit; | ||
679 | } | ||
680 | |||
681 | if (DIGITAL_DRV_CAPS_TG_CRC(ddev)) { | ||
682 | ddev->skb_add_crc = digital_skb_add_crc_none; | ||
683 | ddev->skb_check_crc = digital_skb_check_crc_none; | ||
684 | } | ||
685 | |||
686 | rc = ddev->skb_check_crc(resp); | ||
687 | if (rc) { | ||
688 | PROTOCOL_ERR("14.4.1.6"); | ||
689 | goto exit; | ||
690 | } | ||
691 | |||
692 | rc = digital_skb_pull_dep_sod(ddev, resp); | ||
693 | if (rc) { | ||
694 | PROTOCOL_ERR("14.4.1.2"); | ||
695 | goto exit; | ||
696 | } | ||
697 | |||
698 | atr_req = (struct digital_atr_req *)resp->data; | ||
699 | |||
700 | if (atr_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT || | ||
701 | atr_req->cmd != DIGITAL_CMD_ATR_REQ) { | ||
702 | rc = -EINVAL; | ||
703 | goto exit; | ||
704 | } | ||
705 | |||
706 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, | ||
707 | NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED); | ||
708 | if (rc) | ||
709 | goto exit; | ||
710 | |||
711 | rc = digital_tg_send_atr_res(ddev, atr_req); | ||
712 | if (rc) | ||
713 | goto exit; | ||
714 | |||
715 | gb_len = resp->len - sizeof(struct digital_atr_req); | ||
716 | rc = nfc_tm_activated(ddev->nfc_dev, NFC_PROTO_NFC_DEP_MASK, | ||
717 | NFC_COMM_PASSIVE, atr_req->gb, gb_len); | ||
718 | if (rc) | ||
719 | goto exit; | ||
720 | |||
721 | ddev->poll_tech_count = 0; | ||
722 | |||
723 | rc = 0; | ||
724 | exit: | ||
725 | if (rc) | ||
726 | digital_poll_next_tech(ddev); | ||
727 | |||
728 | dev_kfree_skb(resp); | ||
729 | } | ||
diff --git a/net/nfc/digital_technology.c b/net/nfc/digital_technology.c new file mode 100644 index 000000000000..251c8c753ebe --- /dev/null +++ b/net/nfc/digital_technology.c | |||
@@ -0,0 +1,770 @@ | |||
1 | /* | ||
2 | * NFC Digital Protocol stack | ||
3 | * Copyright (c) 2013, Intel Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #define pr_fmt(fmt) "digital: %s: " fmt, __func__ | ||
17 | |||
18 | #include "digital.h" | ||
19 | |||
20 | #define DIGITAL_CMD_SENS_REQ 0x26 | ||
21 | #define DIGITAL_CMD_ALL_REQ 0x52 | ||
22 | #define DIGITAL_CMD_SEL_REQ_CL1 0x93 | ||
23 | #define DIGITAL_CMD_SEL_REQ_CL2 0x95 | ||
24 | #define DIGITAL_CMD_SEL_REQ_CL3 0x97 | ||
25 | |||
26 | #define DIGITAL_SDD_REQ_SEL_PAR 0x20 | ||
27 | |||
28 | #define DIGITAL_SDD_RES_CT 0x88 | ||
29 | #define DIGITAL_SDD_RES_LEN 5 | ||
30 | |||
31 | #define DIGITAL_SEL_RES_NFCID1_COMPLETE(sel_res) (!((sel_res) & 0x04)) | ||
32 | #define DIGITAL_SEL_RES_IS_T2T(sel_res) (!((sel_res) & 0x60)) | ||
33 | #define DIGITAL_SEL_RES_IS_NFC_DEP(sel_res) ((sel_res) & 0x40) | ||
34 | |||
35 | #define DIGITAL_SENS_RES_IS_T1T(sens_res) (((sens_res) & 0x0C00) == 0x0C00) | ||
36 | #define DIGITAL_SENS_RES_IS_VALID(sens_res) \ | ||
37 | ((!((sens_res) & 0x001F) && (((sens_res) & 0x0C00) == 0x0C00)) || \ | ||
38 | (((sens_res) & 0x001F) && ((sens_res) & 0x0C00) != 0x0C00)) | ||
39 | |||
40 | #define DIGITAL_MIFARE_READ_RES_LEN 16 | ||
41 | #define DIGITAL_MIFARE_ACK_RES 0x0A | ||
42 | |||
43 | #define DIGITAL_CMD_SENSF_REQ 0x00 | ||
44 | #define DIGITAL_CMD_SENSF_RES 0x01 | ||
45 | |||
46 | #define DIGITAL_SENSF_RES_MIN_LENGTH 17 | ||
47 | #define DIGITAL_SENSF_RES_RD_AP_B1 0x00 | ||
48 | #define DIGITAL_SENSF_RES_RD_AP_B2 0x8F | ||
49 | |||
50 | #define DIGITAL_SENSF_REQ_RC_NONE 0 | ||
51 | #define DIGITAL_SENSF_REQ_RC_SC 1 | ||
52 | #define DIGITAL_SENSF_REQ_RC_AP 2 | ||
53 | |||
54 | struct digital_sdd_res { | ||
55 | u8 nfcid1[4]; | ||
56 | u8 bcc; | ||
57 | } __packed; | ||
58 | |||
59 | struct digital_sel_req { | ||
60 | u8 sel_cmd; | ||
61 | u8 b2; | ||
62 | u8 nfcid1[4]; | ||
63 | u8 bcc; | ||
64 | } __packed; | ||
65 | |||
66 | struct digital_sensf_req { | ||
67 | u8 cmd; | ||
68 | u8 sc1; | ||
69 | u8 sc2; | ||
70 | u8 rc; | ||
71 | u8 tsn; | ||
72 | } __packed; | ||
73 | |||
74 | struct digital_sensf_res { | ||
75 | u8 cmd; | ||
76 | u8 nfcid2[8]; | ||
77 | u8 pad0[2]; | ||
78 | u8 pad1[3]; | ||
79 | u8 mrti_check; | ||
80 | u8 mrti_update; | ||
81 | u8 pad2; | ||
82 | u8 rd[2]; | ||
83 | } __packed; | ||
84 | |||
85 | static int digital_in_send_sdd_req(struct nfc_digital_dev *ddev, | ||
86 | struct nfc_target *target); | ||
87 | |||
88 | static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg, | ||
89 | struct sk_buff *resp) | ||
90 | { | ||
91 | struct nfc_target *target = arg; | ||
92 | int rc; | ||
93 | u8 sel_res; | ||
94 | u8 nfc_proto; | ||
95 | |||
96 | if (IS_ERR(resp)) { | ||
97 | rc = PTR_ERR(resp); | ||
98 | resp = NULL; | ||
99 | goto exit; | ||
100 | } | ||
101 | |||
102 | if (!DIGITAL_DRV_CAPS_IN_CRC(ddev)) { | ||
103 | rc = digital_skb_check_crc_a(resp); | ||
104 | if (rc) { | ||
105 | PROTOCOL_ERR("4.4.1.3"); | ||
106 | goto exit; | ||
107 | } | ||
108 | } | ||
109 | |||
110 | if (!resp->len) { | ||
111 | rc = -EIO; | ||
112 | goto exit; | ||
113 | } | ||
114 | |||
115 | sel_res = resp->data[0]; | ||
116 | |||
117 | if (!DIGITAL_SEL_RES_NFCID1_COMPLETE(sel_res)) { | ||
118 | rc = digital_in_send_sdd_req(ddev, target); | ||
119 | if (rc) | ||
120 | goto exit; | ||
121 | |||
122 | goto exit_free_skb; | ||
123 | } | ||
124 | |||
125 | if (DIGITAL_SEL_RES_IS_T2T(sel_res)) { | ||
126 | nfc_proto = NFC_PROTO_MIFARE; | ||
127 | } else if (DIGITAL_SEL_RES_IS_NFC_DEP(sel_res)) { | ||
128 | nfc_proto = NFC_PROTO_NFC_DEP; | ||
129 | } else { | ||
130 | rc = -EOPNOTSUPP; | ||
131 | goto exit; | ||
132 | } | ||
133 | |||
134 | target->sel_res = sel_res; | ||
135 | |||
136 | rc = digital_target_found(ddev, target, nfc_proto); | ||
137 | |||
138 | exit: | ||
139 | kfree(target); | ||
140 | |||
141 | exit_free_skb: | ||
142 | dev_kfree_skb(resp); | ||
143 | |||
144 | if (rc) | ||
145 | digital_poll_next_tech(ddev); | ||
146 | } | ||
147 | |||
148 | static int digital_in_send_sel_req(struct nfc_digital_dev *ddev, | ||
149 | struct nfc_target *target, | ||
150 | struct digital_sdd_res *sdd_res) | ||
151 | { | ||
152 | struct sk_buff *skb; | ||
153 | struct digital_sel_req *sel_req; | ||
154 | u8 sel_cmd; | ||
155 | int rc; | ||
156 | |||
157 | skb = digital_skb_alloc(ddev, sizeof(struct digital_sel_req)); | ||
158 | if (!skb) | ||
159 | return -ENOMEM; | ||
160 | |||
161 | skb_put(skb, sizeof(struct digital_sel_req)); | ||
162 | sel_req = (struct digital_sel_req *)skb->data; | ||
163 | |||
164 | if (target->nfcid1_len <= 4) | ||
165 | sel_cmd = DIGITAL_CMD_SEL_REQ_CL1; | ||
166 | else if (target->nfcid1_len < 10) | ||
167 | sel_cmd = DIGITAL_CMD_SEL_REQ_CL2; | ||
168 | else | ||
169 | sel_cmd = DIGITAL_CMD_SEL_REQ_CL3; | ||
170 | |||
171 | sel_req->sel_cmd = sel_cmd; | ||
172 | sel_req->b2 = 0x70; | ||
173 | memcpy(sel_req->nfcid1, sdd_res->nfcid1, 4); | ||
174 | sel_req->bcc = sdd_res->bcc; | ||
175 | |||
176 | if (DIGITAL_DRV_CAPS_IN_CRC(ddev)) { | ||
177 | rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, | ||
178 | NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A); | ||
179 | if (rc) | ||
180 | goto exit; | ||
181 | } else { | ||
182 | digital_skb_add_crc_a(skb); | ||
183 | } | ||
184 | |||
185 | rc = digital_in_send_cmd(ddev, skb, 30, digital_in_recv_sel_res, | ||
186 | target); | ||
187 | exit: | ||
188 | if (rc) | ||
189 | kfree_skb(skb); | ||
190 | |||
191 | return rc; | ||
192 | } | ||
193 | |||
194 | static void digital_in_recv_sdd_res(struct nfc_digital_dev *ddev, void *arg, | ||
195 | struct sk_buff *resp) | ||
196 | { | ||
197 | struct nfc_target *target = arg; | ||
198 | struct digital_sdd_res *sdd_res; | ||
199 | int rc; | ||
200 | u8 offset, size; | ||
201 | u8 i, bcc; | ||
202 | |||
203 | if (IS_ERR(resp)) { | ||
204 | rc = PTR_ERR(resp); | ||
205 | resp = NULL; | ||
206 | goto exit; | ||
207 | } | ||
208 | |||
209 | if (resp->len < DIGITAL_SDD_RES_LEN) { | ||
210 | PROTOCOL_ERR("4.7.2.8"); | ||
211 | rc = -EINVAL; | ||
212 | goto exit; | ||
213 | } | ||
214 | |||
215 | sdd_res = (struct digital_sdd_res *)resp->data; | ||
216 | |||
217 | for (i = 0, bcc = 0; i < 4; i++) | ||
218 | bcc ^= sdd_res->nfcid1[i]; | ||
219 | |||
220 | if (bcc != sdd_res->bcc) { | ||
221 | PROTOCOL_ERR("4.7.2.6"); | ||
222 | rc = -EINVAL; | ||
223 | goto exit; | ||
224 | } | ||
225 | |||
226 | if (sdd_res->nfcid1[0] == DIGITAL_SDD_RES_CT) { | ||
227 | offset = 1; | ||
228 | size = 3; | ||
229 | } else { | ||
230 | offset = 0; | ||
231 | size = 4; | ||
232 | } | ||
233 | |||
234 | memcpy(target->nfcid1 + target->nfcid1_len, sdd_res->nfcid1 + offset, | ||
235 | size); | ||
236 | target->nfcid1_len += size; | ||
237 | |||
238 | rc = digital_in_send_sel_req(ddev, target, sdd_res); | ||
239 | |||
240 | exit: | ||
241 | dev_kfree_skb(resp); | ||
242 | |||
243 | if (rc) { | ||
244 | kfree(target); | ||
245 | digital_poll_next_tech(ddev); | ||
246 | } | ||
247 | } | ||
248 | |||
249 | static int digital_in_send_sdd_req(struct nfc_digital_dev *ddev, | ||
250 | struct nfc_target *target) | ||
251 | { | ||
252 | int rc; | ||
253 | struct sk_buff *skb; | ||
254 | u8 sel_cmd; | ||
255 | |||
256 | rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, | ||
257 | NFC_DIGITAL_FRAMING_NFCA_STANDARD); | ||
258 | if (rc) | ||
259 | return rc; | ||
260 | |||
261 | skb = digital_skb_alloc(ddev, 2); | ||
262 | if (!skb) | ||
263 | return -ENOMEM; | ||
264 | |||
265 | if (target->nfcid1_len == 0) | ||
266 | sel_cmd = DIGITAL_CMD_SEL_REQ_CL1; | ||
267 | else if (target->nfcid1_len == 3) | ||
268 | sel_cmd = DIGITAL_CMD_SEL_REQ_CL2; | ||
269 | else | ||
270 | sel_cmd = DIGITAL_CMD_SEL_REQ_CL3; | ||
271 | |||
272 | *skb_put(skb, sizeof(u8)) = sel_cmd; | ||
273 | *skb_put(skb, sizeof(u8)) = DIGITAL_SDD_REQ_SEL_PAR; | ||
274 | |||
275 | return digital_in_send_cmd(ddev, skb, 30, digital_in_recv_sdd_res, | ||
276 | target); | ||
277 | } | ||
278 | |||
279 | static void digital_in_recv_sens_res(struct nfc_digital_dev *ddev, void *arg, | ||
280 | struct sk_buff *resp) | ||
281 | { | ||
282 | struct nfc_target *target = NULL; | ||
283 | int rc; | ||
284 | |||
285 | if (IS_ERR(resp)) { | ||
286 | rc = PTR_ERR(resp); | ||
287 | resp = NULL; | ||
288 | goto exit; | ||
289 | } | ||
290 | |||
291 | if (resp->len < sizeof(u16)) { | ||
292 | rc = -EIO; | ||
293 | goto exit; | ||
294 | } | ||
295 | |||
296 | target = kzalloc(sizeof(struct nfc_target), GFP_KERNEL); | ||
297 | if (!target) { | ||
298 | rc = -ENOMEM; | ||
299 | goto exit; | ||
300 | } | ||
301 | |||
302 | target->sens_res = __le16_to_cpu(*(__le16 *)resp->data); | ||
303 | |||
304 | if (!DIGITAL_SENS_RES_IS_VALID(target->sens_res)) { | ||
305 | PROTOCOL_ERR("4.6.3.3"); | ||
306 | rc = -EINVAL; | ||
307 | goto exit; | ||
308 | } | ||
309 | |||
310 | if (DIGITAL_SENS_RES_IS_T1T(target->sens_res)) | ||
311 | rc = digital_target_found(ddev, target, NFC_PROTO_JEWEL); | ||
312 | else | ||
313 | rc = digital_in_send_sdd_req(ddev, target); | ||
314 | |||
315 | exit: | ||
316 | dev_kfree_skb(resp); | ||
317 | |||
318 | if (rc) { | ||
319 | kfree(target); | ||
320 | digital_poll_next_tech(ddev); | ||
321 | } | ||
322 | } | ||
323 | |||
324 | int digital_in_send_sens_req(struct nfc_digital_dev *ddev, u8 rf_tech) | ||
325 | { | ||
326 | struct sk_buff *skb; | ||
327 | int rc; | ||
328 | |||
329 | rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, | ||
330 | NFC_DIGITAL_RF_TECH_106A); | ||
331 | if (rc) | ||
332 | return rc; | ||
333 | |||
334 | rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, | ||
335 | NFC_DIGITAL_FRAMING_NFCA_SHORT); | ||
336 | if (rc) | ||
337 | return rc; | ||
338 | |||
339 | skb = digital_skb_alloc(ddev, 1); | ||
340 | if (!skb) | ||
341 | return -ENOMEM; | ||
342 | |||
343 | *skb_put(skb, sizeof(u8)) = DIGITAL_CMD_SENS_REQ; | ||
344 | |||
345 | rc = digital_in_send_cmd(ddev, skb, 30, digital_in_recv_sens_res, NULL); | ||
346 | if (rc) | ||
347 | kfree_skb(skb); | ||
348 | |||
349 | return rc; | ||
350 | } | ||
351 | |||
352 | int digital_in_recv_mifare_res(struct sk_buff *resp) | ||
353 | { | ||
354 | /* Successful READ command response is 16 data bytes + 2 CRC bytes long. | ||
355 | * Since the driver can't differentiate a ACK/NACK response from a valid | ||
356 | * READ response, the CRC calculation must be handled at digital level | ||
357 | * even if the driver supports it for this technology. | ||
358 | */ | ||
359 | if (resp->len == DIGITAL_MIFARE_READ_RES_LEN + DIGITAL_CRC_LEN) { | ||
360 | if (digital_skb_check_crc_a(resp)) { | ||
361 | PROTOCOL_ERR("9.4.1.2"); | ||
362 | return -EIO; | ||
363 | } | ||
364 | |||
365 | return 0; | ||
366 | } | ||
367 | |||
368 | /* ACK response (i.e. successful WRITE). */ | ||
369 | if (resp->len == 1 && resp->data[0] == DIGITAL_MIFARE_ACK_RES) { | ||
370 | resp->data[0] = 0; | ||
371 | return 0; | ||
372 | } | ||
373 | |||
374 | /* NACK and any other responses are treated as error. */ | ||
375 | return -EIO; | ||
376 | } | ||
377 | |||
378 | static void digital_in_recv_sensf_res(struct nfc_digital_dev *ddev, void *arg, | ||
379 | struct sk_buff *resp) | ||
380 | { | ||
381 | int rc; | ||
382 | u8 proto; | ||
383 | struct nfc_target target; | ||
384 | struct digital_sensf_res *sensf_res; | ||
385 | |||
386 | if (IS_ERR(resp)) { | ||
387 | rc = PTR_ERR(resp); | ||
388 | resp = NULL; | ||
389 | goto exit; | ||
390 | } | ||
391 | |||
392 | if (resp->len < DIGITAL_SENSF_RES_MIN_LENGTH) { | ||
393 | rc = -EIO; | ||
394 | goto exit; | ||
395 | } | ||
396 | |||
397 | if (!DIGITAL_DRV_CAPS_IN_CRC(ddev)) { | ||
398 | rc = digital_skb_check_crc_f(resp); | ||
399 | if (rc) { | ||
400 | PROTOCOL_ERR("6.4.1.8"); | ||
401 | goto exit; | ||
402 | } | ||
403 | } | ||
404 | |||
405 | skb_pull(resp, 1); | ||
406 | |||
407 | memset(&target, 0, sizeof(struct nfc_target)); | ||
408 | |||
409 | sensf_res = (struct digital_sensf_res *)resp->data; | ||
410 | |||
411 | memcpy(target.sensf_res, sensf_res, resp->len); | ||
412 | target.sensf_res_len = resp->len; | ||
413 | |||
414 | memcpy(target.nfcid2, sensf_res->nfcid2, NFC_NFCID2_MAXSIZE); | ||
415 | target.nfcid2_len = NFC_NFCID2_MAXSIZE; | ||
416 | |||
417 | if (target.nfcid2[0] == DIGITAL_SENSF_NFCID2_NFC_DEP_B1 && | ||
418 | target.nfcid2[1] == DIGITAL_SENSF_NFCID2_NFC_DEP_B2) | ||
419 | proto = NFC_PROTO_NFC_DEP; | ||
420 | else | ||
421 | proto = NFC_PROTO_FELICA; | ||
422 | |||
423 | rc = digital_target_found(ddev, &target, proto); | ||
424 | |||
425 | exit: | ||
426 | dev_kfree_skb(resp); | ||
427 | |||
428 | if (rc) | ||
429 | digital_poll_next_tech(ddev); | ||
430 | } | ||
431 | |||
432 | int digital_in_send_sensf_req(struct nfc_digital_dev *ddev, u8 rf_tech) | ||
433 | { | ||
434 | struct digital_sensf_req *sensf_req; | ||
435 | struct sk_buff *skb; | ||
436 | int rc; | ||
437 | u8 size; | ||
438 | |||
439 | rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, rf_tech); | ||
440 | if (rc) | ||
441 | return rc; | ||
442 | |||
443 | rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, | ||
444 | NFC_DIGITAL_FRAMING_NFCF); | ||
445 | if (rc) | ||
446 | return rc; | ||
447 | |||
448 | size = sizeof(struct digital_sensf_req); | ||
449 | |||
450 | skb = digital_skb_alloc(ddev, size); | ||
451 | if (!skb) | ||
452 | return -ENOMEM; | ||
453 | |||
454 | skb_put(skb, size); | ||
455 | |||
456 | sensf_req = (struct digital_sensf_req *)skb->data; | ||
457 | sensf_req->cmd = DIGITAL_CMD_SENSF_REQ; | ||
458 | sensf_req->sc1 = 0xFF; | ||
459 | sensf_req->sc2 = 0xFF; | ||
460 | sensf_req->rc = 0; | ||
461 | sensf_req->tsn = 0; | ||
462 | |||
463 | *skb_push(skb, 1) = size + 1; | ||
464 | |||
465 | if (!DIGITAL_DRV_CAPS_IN_CRC(ddev)) | ||
466 | digital_skb_add_crc_f(skb); | ||
467 | |||
468 | rc = digital_in_send_cmd(ddev, skb, 30, digital_in_recv_sensf_res, | ||
469 | NULL); | ||
470 | if (rc) | ||
471 | kfree_skb(skb); | ||
472 | |||
473 | return rc; | ||
474 | } | ||
475 | |||
476 | static int digital_tg_send_sel_res(struct nfc_digital_dev *ddev) | ||
477 | { | ||
478 | struct sk_buff *skb; | ||
479 | int rc; | ||
480 | |||
481 | skb = digital_skb_alloc(ddev, 1); | ||
482 | if (!skb) | ||
483 | return -ENOMEM; | ||
484 | |||
485 | *skb_put(skb, 1) = DIGITAL_SEL_RES_NFC_DEP; | ||
486 | |||
487 | if (!DIGITAL_DRV_CAPS_TG_CRC(ddev)) | ||
488 | digital_skb_add_crc_a(skb); | ||
489 | |||
490 | rc = digital_tg_send_cmd(ddev, skb, 300, digital_tg_recv_atr_req, | ||
491 | NULL); | ||
492 | if (rc) | ||
493 | kfree_skb(skb); | ||
494 | |||
495 | return rc; | ||
496 | } | ||
497 | |||
498 | static void digital_tg_recv_sel_req(struct nfc_digital_dev *ddev, void *arg, | ||
499 | struct sk_buff *resp) | ||
500 | { | ||
501 | int rc; | ||
502 | |||
503 | if (IS_ERR(resp)) { | ||
504 | rc = PTR_ERR(resp); | ||
505 | resp = NULL; | ||
506 | goto exit; | ||
507 | } | ||
508 | |||
509 | if (!DIGITAL_DRV_CAPS_TG_CRC(ddev)) { | ||
510 | rc = digital_skb_check_crc_a(resp); | ||
511 | if (rc) { | ||
512 | PROTOCOL_ERR("4.4.1.3"); | ||
513 | goto exit; | ||
514 | } | ||
515 | } | ||
516 | |||
517 | /* Silently ignore SEL_REQ content and send a SEL_RES for NFC-DEP */ | ||
518 | |||
519 | rc = digital_tg_send_sel_res(ddev); | ||
520 | |||
521 | exit: | ||
522 | if (rc) | ||
523 | digital_poll_next_tech(ddev); | ||
524 | |||
525 | dev_kfree_skb(resp); | ||
526 | } | ||
527 | |||
528 | static int digital_tg_send_sdd_res(struct nfc_digital_dev *ddev) | ||
529 | { | ||
530 | struct sk_buff *skb; | ||
531 | struct digital_sdd_res *sdd_res; | ||
532 | int rc, i; | ||
533 | |||
534 | skb = digital_skb_alloc(ddev, sizeof(struct digital_sdd_res)); | ||
535 | if (!skb) | ||
536 | return -ENOMEM; | ||
537 | |||
538 | skb_put(skb, sizeof(struct digital_sdd_res)); | ||
539 | sdd_res = (struct digital_sdd_res *)skb->data; | ||
540 | |||
541 | sdd_res->nfcid1[0] = 0x08; | ||
542 | get_random_bytes(sdd_res->nfcid1 + 1, 3); | ||
543 | |||
544 | sdd_res->bcc = 0; | ||
545 | for (i = 0; i < 4; i++) | ||
546 | sdd_res->bcc ^= sdd_res->nfcid1[i]; | ||
547 | |||
548 | rc = digital_tg_send_cmd(ddev, skb, 300, digital_tg_recv_sel_req, | ||
549 | NULL); | ||
550 | if (rc) | ||
551 | kfree_skb(skb); | ||
552 | |||
553 | return rc; | ||
554 | } | ||
555 | |||
556 | static void digital_tg_recv_sdd_req(struct nfc_digital_dev *ddev, void *arg, | ||
557 | struct sk_buff *resp) | ||
558 | { | ||
559 | u8 *sdd_req; | ||
560 | int rc; | ||
561 | |||
562 | if (IS_ERR(resp)) { | ||
563 | rc = PTR_ERR(resp); | ||
564 | resp = NULL; | ||
565 | goto exit; | ||
566 | } | ||
567 | |||
568 | sdd_req = resp->data; | ||
569 | |||
570 | if (resp->len < 2 || sdd_req[0] != DIGITAL_CMD_SEL_REQ_CL1 || | ||
571 | sdd_req[1] != DIGITAL_SDD_REQ_SEL_PAR) { | ||
572 | rc = -EINVAL; | ||
573 | goto exit; | ||
574 | } | ||
575 | |||
576 | rc = digital_tg_send_sdd_res(ddev); | ||
577 | |||
578 | exit: | ||
579 | if (rc) | ||
580 | digital_poll_next_tech(ddev); | ||
581 | |||
582 | dev_kfree_skb(resp); | ||
583 | } | ||
584 | |||
585 | static int digital_tg_send_sens_res(struct nfc_digital_dev *ddev) | ||
586 | { | ||
587 | struct sk_buff *skb; | ||
588 | u8 *sens_res; | ||
589 | int rc; | ||
590 | |||
591 | skb = digital_skb_alloc(ddev, 2); | ||
592 | if (!skb) | ||
593 | return -ENOMEM; | ||
594 | |||
595 | sens_res = skb_put(skb, 2); | ||
596 | |||
597 | sens_res[0] = (DIGITAL_SENS_RES_NFC_DEP >> 8) & 0xFF; | ||
598 | sens_res[1] = DIGITAL_SENS_RES_NFC_DEP & 0xFF; | ||
599 | |||
600 | rc = digital_tg_send_cmd(ddev, skb, 300, digital_tg_recv_sdd_req, | ||
601 | NULL); | ||
602 | if (rc) | ||
603 | kfree_skb(skb); | ||
604 | |||
605 | return rc; | ||
606 | } | ||
607 | |||
608 | void digital_tg_recv_sens_req(struct nfc_digital_dev *ddev, void *arg, | ||
609 | struct sk_buff *resp) | ||
610 | { | ||
611 | u8 sens_req; | ||
612 | int rc; | ||
613 | |||
614 | if (IS_ERR(resp)) { | ||
615 | rc = PTR_ERR(resp); | ||
616 | resp = NULL; | ||
617 | goto exit; | ||
618 | } | ||
619 | |||
620 | sens_req = resp->data[0]; | ||
621 | |||
622 | if (!resp->len || (sens_req != DIGITAL_CMD_SENS_REQ && | ||
623 | sens_req != DIGITAL_CMD_ALL_REQ)) { | ||
624 | rc = -EINVAL; | ||
625 | goto exit; | ||
626 | } | ||
627 | |||
628 | rc = digital_tg_send_sens_res(ddev); | ||
629 | |||
630 | exit: | ||
631 | if (rc) | ||
632 | digital_poll_next_tech(ddev); | ||
633 | |||
634 | dev_kfree_skb(resp); | ||
635 | } | ||
636 | |||
637 | static int digital_tg_send_sensf_res(struct nfc_digital_dev *ddev, | ||
638 | struct digital_sensf_req *sensf_req) | ||
639 | { | ||
640 | struct sk_buff *skb; | ||
641 | u8 size; | ||
642 | int rc; | ||
643 | struct digital_sensf_res *sensf_res; | ||
644 | |||
645 | size = sizeof(struct digital_sensf_res); | ||
646 | |||
647 | if (sensf_req->rc != DIGITAL_SENSF_REQ_RC_NONE) | ||
648 | size -= sizeof(sensf_res->rd); | ||
649 | |||
650 | skb = digital_skb_alloc(ddev, size); | ||
651 | if (!skb) | ||
652 | return -ENOMEM; | ||
653 | |||
654 | skb_put(skb, size); | ||
655 | |||
656 | sensf_res = (struct digital_sensf_res *)skb->data; | ||
657 | |||
658 | memset(sensf_res, 0, size); | ||
659 | |||
660 | sensf_res->cmd = DIGITAL_CMD_SENSF_RES; | ||
661 | sensf_res->nfcid2[0] = DIGITAL_SENSF_NFCID2_NFC_DEP_B1; | ||
662 | sensf_res->nfcid2[1] = DIGITAL_SENSF_NFCID2_NFC_DEP_B2; | ||
663 | get_random_bytes(&sensf_res->nfcid2[2], 6); | ||
664 | |||
665 | switch (sensf_req->rc) { | ||
666 | case DIGITAL_SENSF_REQ_RC_SC: | ||
667 | sensf_res->rd[0] = sensf_req->sc1; | ||
668 | sensf_res->rd[1] = sensf_req->sc2; | ||
669 | break; | ||
670 | case DIGITAL_SENSF_REQ_RC_AP: | ||
671 | sensf_res->rd[0] = DIGITAL_SENSF_RES_RD_AP_B1; | ||
672 | sensf_res->rd[1] = DIGITAL_SENSF_RES_RD_AP_B2; | ||
673 | break; | ||
674 | } | ||
675 | |||
676 | *skb_push(skb, sizeof(u8)) = size + 1; | ||
677 | |||
678 | if (!DIGITAL_DRV_CAPS_TG_CRC(ddev)) | ||
679 | digital_skb_add_crc_f(skb); | ||
680 | |||
681 | rc = digital_tg_send_cmd(ddev, skb, 300, | ||
682 | digital_tg_recv_atr_req, NULL); | ||
683 | if (rc) | ||
684 | kfree_skb(skb); | ||
685 | |||
686 | return rc; | ||
687 | } | ||
688 | |||
689 | void digital_tg_recv_sensf_req(struct nfc_digital_dev *ddev, void *arg, | ||
690 | struct sk_buff *resp) | ||
691 | { | ||
692 | struct digital_sensf_req *sensf_req; | ||
693 | int rc; | ||
694 | |||
695 | if (IS_ERR(resp)) { | ||
696 | rc = PTR_ERR(resp); | ||
697 | resp = NULL; | ||
698 | goto exit; | ||
699 | } | ||
700 | |||
701 | if (!DIGITAL_DRV_CAPS_TG_CRC(ddev)) { | ||
702 | rc = digital_skb_check_crc_f(resp); | ||
703 | if (rc) { | ||
704 | PROTOCOL_ERR("6.4.1.8"); | ||
705 | goto exit; | ||
706 | } | ||
707 | } | ||
708 | |||
709 | if (resp->len != sizeof(struct digital_sensf_req) + 1) { | ||
710 | rc = -EINVAL; | ||
711 | goto exit; | ||
712 | } | ||
713 | |||
714 | skb_pull(resp, 1); | ||
715 | sensf_req = (struct digital_sensf_req *)resp->data; | ||
716 | |||
717 | if (sensf_req->cmd != DIGITAL_CMD_SENSF_REQ) { | ||
718 | rc = -EINVAL; | ||
719 | goto exit; | ||
720 | } | ||
721 | |||
722 | rc = digital_tg_send_sensf_res(ddev, sensf_req); | ||
723 | |||
724 | exit: | ||
725 | if (rc) | ||
726 | digital_poll_next_tech(ddev); | ||
727 | |||
728 | dev_kfree_skb(resp); | ||
729 | } | ||
730 | |||
731 | int digital_tg_listen_nfca(struct nfc_digital_dev *ddev, u8 rf_tech) | ||
732 | { | ||
733 | int rc; | ||
734 | |||
735 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, rf_tech); | ||
736 | if (rc) | ||
737 | return rc; | ||
738 | |||
739 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, | ||
740 | NFC_DIGITAL_FRAMING_NFCA_NFC_DEP); | ||
741 | if (rc) | ||
742 | return rc; | ||
743 | |||
744 | return digital_tg_listen(ddev, 300, digital_tg_recv_sens_req, NULL); | ||
745 | } | ||
746 | |||
747 | int digital_tg_listen_nfcf(struct nfc_digital_dev *ddev, u8 rf_tech) | ||
748 | { | ||
749 | int rc; | ||
750 | u8 *nfcid2; | ||
751 | |||
752 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, rf_tech); | ||
753 | if (rc) | ||
754 | return rc; | ||
755 | |||
756 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, | ||
757 | NFC_DIGITAL_FRAMING_NFCF_NFC_DEP); | ||
758 | if (rc) | ||
759 | return rc; | ||
760 | |||
761 | nfcid2 = kzalloc(NFC_NFCID2_MAXSIZE, GFP_KERNEL); | ||
762 | if (!nfcid2) | ||
763 | return -ENOMEM; | ||
764 | |||
765 | nfcid2[0] = DIGITAL_SENSF_NFCID2_NFC_DEP_B1; | ||
766 | nfcid2[1] = DIGITAL_SENSF_NFCID2_NFC_DEP_B2; | ||
767 | get_random_bytes(nfcid2 + 2, NFC_NFCID2_MAXSIZE - 2); | ||
768 | |||
769 | return digital_tg_listen(ddev, 300, digital_tg_recv_sensf_req, nfcid2); | ||
770 | } | ||
diff --git a/net/nfc/nci/spi.c b/net/nfc/nci/spi.c index c7cf37ba7298..f1d426f10cce 100644 --- a/net/nfc/nci/spi.c +++ b/net/nfc/nci/spi.c | |||
@@ -21,11 +21,8 @@ | |||
21 | #include <linux/export.h> | 21 | #include <linux/export.h> |
22 | #include <linux/spi/spi.h> | 22 | #include <linux/spi/spi.h> |
23 | #include <linux/crc-ccitt.h> | 23 | #include <linux/crc-ccitt.h> |
24 | #include <linux/nfc.h> | ||
25 | #include <net/nfc/nci_core.h> | 24 | #include <net/nfc/nci_core.h> |
26 | 25 | ||
27 | #define NCI_SPI_HDR_LEN 4 | ||
28 | #define NCI_SPI_CRC_LEN 2 | ||
29 | #define NCI_SPI_ACK_SHIFT 6 | 26 | #define NCI_SPI_ACK_SHIFT 6 |
30 | #define NCI_SPI_MSB_PAYLOAD_MASK 0x3F | 27 | #define NCI_SPI_MSB_PAYLOAD_MASK 0x3F |
31 | 28 | ||
@@ -41,54 +38,48 @@ | |||
41 | 38 | ||
42 | #define CRC_INIT 0xFFFF | 39 | #define CRC_INIT 0xFFFF |
43 | 40 | ||
44 | static int nci_spi_open(struct nci_dev *nci_dev) | 41 | static int __nci_spi_send(struct nci_spi *nspi, struct sk_buff *skb, |
45 | { | 42 | int cs_change) |
46 | struct nci_spi_dev *ndev = nci_get_drvdata(nci_dev); | ||
47 | |||
48 | return ndev->ops->open(ndev); | ||
49 | } | ||
50 | |||
51 | static int nci_spi_close(struct nci_dev *nci_dev) | ||
52 | { | ||
53 | struct nci_spi_dev *ndev = nci_get_drvdata(nci_dev); | ||
54 | |||
55 | return ndev->ops->close(ndev); | ||
56 | } | ||
57 | |||
58 | static int __nci_spi_send(struct nci_spi_dev *ndev, struct sk_buff *skb) | ||
59 | { | 43 | { |
60 | struct spi_message m; | 44 | struct spi_message m; |
61 | struct spi_transfer t; | 45 | struct spi_transfer t; |
62 | 46 | ||
63 | t.tx_buf = skb->data; | 47 | memset(&t, 0, sizeof(struct spi_transfer)); |
64 | t.len = skb->len; | 48 | /* a NULL skb means we just want the SPI chip select line to raise */ |
65 | t.cs_change = 0; | 49 | if (skb) { |
66 | t.delay_usecs = ndev->xfer_udelay; | 50 | t.tx_buf = skb->data; |
51 | t.len = skb->len; | ||
52 | } else { | ||
53 | /* still set tx_buf non NULL to make the driver happy */ | ||
54 | t.tx_buf = &t; | ||
55 | t.len = 0; | ||
56 | } | ||
57 | t.cs_change = cs_change; | ||
58 | t.delay_usecs = nspi->xfer_udelay; | ||
67 | 59 | ||
68 | spi_message_init(&m); | 60 | spi_message_init(&m); |
69 | spi_message_add_tail(&t, &m); | 61 | spi_message_add_tail(&t, &m); |
70 | 62 | ||
71 | return spi_sync(ndev->spi, &m); | 63 | return spi_sync(nspi->spi, &m); |
72 | } | 64 | } |
73 | 65 | ||
74 | static int nci_spi_send(struct nci_dev *nci_dev, struct sk_buff *skb) | 66 | int nci_spi_send(struct nci_spi *nspi, |
67 | struct completion *write_handshake_completion, | ||
68 | struct sk_buff *skb) | ||
75 | { | 69 | { |
76 | struct nci_spi_dev *ndev = nci_get_drvdata(nci_dev); | ||
77 | unsigned int payload_len = skb->len; | 70 | unsigned int payload_len = skb->len; |
78 | unsigned char *hdr; | 71 | unsigned char *hdr; |
79 | int ret; | 72 | int ret; |
80 | long completion_rc; | 73 | long completion_rc; |
81 | 74 | ||
82 | ndev->ops->deassert_int(ndev); | ||
83 | |||
84 | /* add the NCI SPI header to the start of the buffer */ | 75 | /* add the NCI SPI header to the start of the buffer */ |
85 | hdr = skb_push(skb, NCI_SPI_HDR_LEN); | 76 | hdr = skb_push(skb, NCI_SPI_HDR_LEN); |
86 | hdr[0] = NCI_SPI_DIRECT_WRITE; | 77 | hdr[0] = NCI_SPI_DIRECT_WRITE; |
87 | hdr[1] = ndev->acknowledge_mode; | 78 | hdr[1] = nspi->acknowledge_mode; |
88 | hdr[2] = payload_len >> 8; | 79 | hdr[2] = payload_len >> 8; |
89 | hdr[3] = payload_len & 0xFF; | 80 | hdr[3] = payload_len & 0xFF; |
90 | 81 | ||
91 | if (ndev->acknowledge_mode == NCI_SPI_CRC_ENABLED) { | 82 | if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED) { |
92 | u16 crc; | 83 | u16 crc; |
93 | 84 | ||
94 | crc = crc_ccitt(CRC_INIT, skb->data, skb->len); | 85 | crc = crc_ccitt(CRC_INIT, skb->data, skb->len); |
@@ -96,123 +87,77 @@ static int nci_spi_send(struct nci_dev *nci_dev, struct sk_buff *skb) | |||
96 | *skb_put(skb, 1) = crc & 0xFF; | 87 | *skb_put(skb, 1) = crc & 0xFF; |
97 | } | 88 | } |
98 | 89 | ||
99 | ret = __nci_spi_send(ndev, skb); | 90 | if (write_handshake_completion) { |
91 | /* Trick SPI driver to raise chip select */ | ||
92 | ret = __nci_spi_send(nspi, NULL, 1); | ||
93 | if (ret) | ||
94 | goto done; | ||
100 | 95 | ||
101 | kfree_skb(skb); | 96 | /* wait for NFC chip hardware handshake to complete */ |
102 | ndev->ops->assert_int(ndev); | 97 | if (wait_for_completion_timeout(write_handshake_completion, |
98 | msecs_to_jiffies(1000)) == 0) { | ||
99 | ret = -ETIME; | ||
100 | goto done; | ||
101 | } | ||
102 | } | ||
103 | 103 | ||
104 | if (ret != 0 || ndev->acknowledge_mode == NCI_SPI_CRC_DISABLED) | 104 | ret = __nci_spi_send(nspi, skb, 0); |
105 | if (ret != 0 || nspi->acknowledge_mode == NCI_SPI_CRC_DISABLED) | ||
105 | goto done; | 106 | goto done; |
106 | 107 | ||
107 | init_completion(&ndev->req_completion); | 108 | init_completion(&nspi->req_completion); |
108 | completion_rc = | 109 | completion_rc = wait_for_completion_interruptible_timeout( |
109 | wait_for_completion_interruptible_timeout(&ndev->req_completion, | 110 | &nspi->req_completion, |
110 | NCI_SPI_SEND_TIMEOUT); | 111 | NCI_SPI_SEND_TIMEOUT); |
111 | 112 | ||
112 | if (completion_rc <= 0 || ndev->req_result == ACKNOWLEDGE_NACK) | 113 | if (completion_rc <= 0 || nspi->req_result == ACKNOWLEDGE_NACK) |
113 | ret = -EIO; | 114 | ret = -EIO; |
114 | 115 | ||
115 | done: | 116 | done: |
117 | kfree_skb(skb); | ||
118 | |||
116 | return ret; | 119 | return ret; |
117 | } | 120 | } |
118 | 121 | EXPORT_SYMBOL_GPL(nci_spi_send); | |
119 | static struct nci_ops nci_spi_ops = { | ||
120 | .open = nci_spi_open, | ||
121 | .close = nci_spi_close, | ||
122 | .send = nci_spi_send, | ||
123 | }; | ||
124 | 122 | ||
125 | /* ---- Interface to NCI SPI drivers ---- */ | 123 | /* ---- Interface to NCI SPI drivers ---- */ |
126 | 124 | ||
127 | /** | 125 | /** |
128 | * nci_spi_allocate_device - allocate a new nci spi device | 126 | * nci_spi_allocate_spi - allocate a new nci spi |
129 | * | 127 | * |
130 | * @spi: SPI device | 128 | * @spi: SPI device |
131 | * @ops: device operations | 129 | * @acknowledge_mode: Acknowledge mode used by the NFC device |
132 | * @supported_protocols: NFC protocols supported by the device | ||
133 | * @supported_se: NFC Secure Elements supported by the device | ||
134 | * @acknowledge_mode: Acknowledge mode used by the device | ||
135 | * @delay: delay between transactions in us | 130 | * @delay: delay between transactions in us |
131 | * @ndev: nci dev to send incoming nci frames to | ||
136 | */ | 132 | */ |
137 | struct nci_spi_dev *nci_spi_allocate_device(struct spi_device *spi, | 133 | struct nci_spi *nci_spi_allocate_spi(struct spi_device *spi, |
138 | struct nci_spi_ops *ops, | 134 | u8 acknowledge_mode, unsigned int delay, |
139 | u32 supported_protocols, | 135 | struct nci_dev *ndev) |
140 | u32 supported_se, | ||
141 | u8 acknowledge_mode, | ||
142 | unsigned int delay) | ||
143 | { | 136 | { |
144 | struct nci_spi_dev *ndev; | 137 | struct nci_spi *nspi; |
145 | int tailroom = 0; | ||
146 | 138 | ||
147 | if (!ops->open || !ops->close || !ops->assert_int || !ops->deassert_int) | 139 | nspi = devm_kzalloc(&spi->dev, sizeof(struct nci_spi), GFP_KERNEL); |
140 | if (!nspi) | ||
148 | return NULL; | 141 | return NULL; |
149 | 142 | ||
150 | if (!supported_protocols) | 143 | nspi->acknowledge_mode = acknowledge_mode; |
151 | return NULL; | 144 | nspi->xfer_udelay = delay; |
152 | |||
153 | ndev = devm_kzalloc(&spi->dev, sizeof(struct nci_dev), GFP_KERNEL); | ||
154 | if (!ndev) | ||
155 | return NULL; | ||
156 | 145 | ||
157 | ndev->ops = ops; | 146 | nspi->spi = spi; |
158 | ndev->acknowledge_mode = acknowledge_mode; | 147 | nspi->ndev = ndev; |
159 | ndev->xfer_udelay = delay; | ||
160 | 148 | ||
161 | if (acknowledge_mode == NCI_SPI_CRC_ENABLED) | 149 | return nspi; |
162 | tailroom += NCI_SPI_CRC_LEN; | ||
163 | |||
164 | ndev->nci_dev = nci_allocate_device(&nci_spi_ops, supported_protocols, | ||
165 | NCI_SPI_HDR_LEN, tailroom); | ||
166 | if (!ndev->nci_dev) | ||
167 | return NULL; | ||
168 | |||
169 | nci_set_drvdata(ndev->nci_dev, ndev); | ||
170 | |||
171 | return ndev; | ||
172 | } | 150 | } |
173 | EXPORT_SYMBOL_GPL(nci_spi_allocate_device); | 151 | EXPORT_SYMBOL_GPL(nci_spi_allocate_spi); |
174 | 152 | ||
175 | /** | 153 | static int send_acknowledge(struct nci_spi *nspi, u8 acknowledge) |
176 | * nci_spi_free_device - deallocate nci spi device | ||
177 | * | ||
178 | * @ndev: The nci spi device to deallocate | ||
179 | */ | ||
180 | void nci_spi_free_device(struct nci_spi_dev *ndev) | ||
181 | { | ||
182 | nci_free_device(ndev->nci_dev); | ||
183 | } | ||
184 | EXPORT_SYMBOL_GPL(nci_spi_free_device); | ||
185 | |||
186 | /** | ||
187 | * nci_spi_register_device - register a nci spi device in the nfc subsystem | ||
188 | * | ||
189 | * @pdev: The nci spi device to register | ||
190 | */ | ||
191 | int nci_spi_register_device(struct nci_spi_dev *ndev) | ||
192 | { | ||
193 | return nci_register_device(ndev->nci_dev); | ||
194 | } | ||
195 | EXPORT_SYMBOL_GPL(nci_spi_register_device); | ||
196 | |||
197 | /** | ||
198 | * nci_spi_unregister_device - unregister a nci spi device in the nfc subsystem | ||
199 | * | ||
200 | * @dev: The nci spi device to unregister | ||
201 | */ | ||
202 | void nci_spi_unregister_device(struct nci_spi_dev *ndev) | ||
203 | { | ||
204 | nci_unregister_device(ndev->nci_dev); | ||
205 | } | ||
206 | EXPORT_SYMBOL_GPL(nci_spi_unregister_device); | ||
207 | |||
208 | static int send_acknowledge(struct nci_spi_dev *ndev, u8 acknowledge) | ||
209 | { | 154 | { |
210 | struct sk_buff *skb; | 155 | struct sk_buff *skb; |
211 | unsigned char *hdr; | 156 | unsigned char *hdr; |
212 | u16 crc; | 157 | u16 crc; |
213 | int ret; | 158 | int ret; |
214 | 159 | ||
215 | skb = nci_skb_alloc(ndev->nci_dev, 0, GFP_KERNEL); | 160 | skb = nci_skb_alloc(nspi->ndev, 0, GFP_KERNEL); |
216 | 161 | ||
217 | /* add the NCI SPI header to the start of the buffer */ | 162 | /* add the NCI SPI header to the start of the buffer */ |
218 | hdr = skb_push(skb, NCI_SPI_HDR_LEN); | 163 | hdr = skb_push(skb, NCI_SPI_HDR_LEN); |
@@ -225,14 +170,14 @@ static int send_acknowledge(struct nci_spi_dev *ndev, u8 acknowledge) | |||
225 | *skb_put(skb, 1) = crc >> 8; | 170 | *skb_put(skb, 1) = crc >> 8; |
226 | *skb_put(skb, 1) = crc & 0xFF; | 171 | *skb_put(skb, 1) = crc & 0xFF; |
227 | 172 | ||
228 | ret = __nci_spi_send(ndev, skb); | 173 | ret = __nci_spi_send(nspi, skb, 0); |
229 | 174 | ||
230 | kfree_skb(skb); | 175 | kfree_skb(skb); |
231 | 176 | ||
232 | return ret; | 177 | return ret; |
233 | } | 178 | } |
234 | 179 | ||
235 | static struct sk_buff *__nci_spi_recv_frame(struct nci_spi_dev *ndev) | 180 | static struct sk_buff *__nci_spi_read(struct nci_spi *nspi) |
236 | { | 181 | { |
237 | struct sk_buff *skb; | 182 | struct sk_buff *skb; |
238 | struct spi_message m; | 183 | struct spi_message m; |
@@ -242,43 +187,49 @@ static struct sk_buff *__nci_spi_recv_frame(struct nci_spi_dev *ndev) | |||
242 | int ret; | 187 | int ret; |
243 | 188 | ||
244 | spi_message_init(&m); | 189 | spi_message_init(&m); |
190 | |||
191 | memset(&tx, 0, sizeof(struct spi_transfer)); | ||
245 | req[0] = NCI_SPI_DIRECT_READ; | 192 | req[0] = NCI_SPI_DIRECT_READ; |
246 | req[1] = ndev->acknowledge_mode; | 193 | req[1] = nspi->acknowledge_mode; |
247 | tx.tx_buf = req; | 194 | tx.tx_buf = req; |
248 | tx.len = 2; | 195 | tx.len = 2; |
249 | tx.cs_change = 0; | 196 | tx.cs_change = 0; |
250 | spi_message_add_tail(&tx, &m); | 197 | spi_message_add_tail(&tx, &m); |
198 | |||
199 | memset(&rx, 0, sizeof(struct spi_transfer)); | ||
251 | rx.rx_buf = resp_hdr; | 200 | rx.rx_buf = resp_hdr; |
252 | rx.len = 2; | 201 | rx.len = 2; |
253 | rx.cs_change = 1; | 202 | rx.cs_change = 1; |
254 | spi_message_add_tail(&rx, &m); | 203 | spi_message_add_tail(&rx, &m); |
255 | ret = spi_sync(ndev->spi, &m); | ||
256 | 204 | ||
205 | ret = spi_sync(nspi->spi, &m); | ||
257 | if (ret) | 206 | if (ret) |
258 | return NULL; | 207 | return NULL; |
259 | 208 | ||
260 | if (ndev->acknowledge_mode == NCI_SPI_CRC_ENABLED) | 209 | if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED) |
261 | rx_len = ((resp_hdr[0] & NCI_SPI_MSB_PAYLOAD_MASK) << 8) + | 210 | rx_len = ((resp_hdr[0] & NCI_SPI_MSB_PAYLOAD_MASK) << 8) + |
262 | resp_hdr[1] + NCI_SPI_CRC_LEN; | 211 | resp_hdr[1] + NCI_SPI_CRC_LEN; |
263 | else | 212 | else |
264 | rx_len = (resp_hdr[0] << 8) | resp_hdr[1]; | 213 | rx_len = (resp_hdr[0] << 8) | resp_hdr[1]; |
265 | 214 | ||
266 | skb = nci_skb_alloc(ndev->nci_dev, rx_len, GFP_KERNEL); | 215 | skb = nci_skb_alloc(nspi->ndev, rx_len, GFP_KERNEL); |
267 | if (!skb) | 216 | if (!skb) |
268 | return NULL; | 217 | return NULL; |
269 | 218 | ||
270 | spi_message_init(&m); | 219 | spi_message_init(&m); |
220 | |||
221 | memset(&rx, 0, sizeof(struct spi_transfer)); | ||
271 | rx.rx_buf = skb_put(skb, rx_len); | 222 | rx.rx_buf = skb_put(skb, rx_len); |
272 | rx.len = rx_len; | 223 | rx.len = rx_len; |
273 | rx.cs_change = 0; | 224 | rx.cs_change = 0; |
274 | rx.delay_usecs = ndev->xfer_udelay; | 225 | rx.delay_usecs = nspi->xfer_udelay; |
275 | spi_message_add_tail(&rx, &m); | 226 | spi_message_add_tail(&rx, &m); |
276 | ret = spi_sync(ndev->spi, &m); | ||
277 | 227 | ||
228 | ret = spi_sync(nspi->spi, &m); | ||
278 | if (ret) | 229 | if (ret) |
279 | goto receive_error; | 230 | goto receive_error; |
280 | 231 | ||
281 | if (ndev->acknowledge_mode == NCI_SPI_CRC_ENABLED) { | 232 | if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED) { |
282 | *skb_push(skb, 1) = resp_hdr[1]; | 233 | *skb_push(skb, 1) = resp_hdr[1]; |
283 | *skb_push(skb, 1) = resp_hdr[0]; | 234 | *skb_push(skb, 1) = resp_hdr[0]; |
284 | } | 235 | } |
@@ -318,61 +269,53 @@ static u8 nci_spi_get_ack(struct sk_buff *skb) | |||
318 | } | 269 | } |
319 | 270 | ||
320 | /** | 271 | /** |
321 | * nci_spi_recv_frame - receive frame from NCI SPI drivers | 272 | * nci_spi_read - read frame from NCI SPI drivers |
322 | * | 273 | * |
323 | * @ndev: The nci spi device | 274 | * @nspi: The nci spi |
324 | * Context: can sleep | 275 | * Context: can sleep |
325 | * | 276 | * |
326 | * This call may only be used from a context that may sleep. The sleep | 277 | * This call may only be used from a context that may sleep. The sleep |
327 | * is non-interruptible, and has no timeout. | 278 | * is non-interruptible, and has no timeout. |
328 | * | 279 | * |
329 | * It returns zero on success, else a negative error code. | 280 | * It returns an allocated skb containing the frame on success, or NULL. |
330 | */ | 281 | */ |
331 | int nci_spi_recv_frame(struct nci_spi_dev *ndev) | 282 | struct sk_buff *nci_spi_read(struct nci_spi *nspi) |
332 | { | 283 | { |
333 | struct sk_buff *skb; | 284 | struct sk_buff *skb; |
334 | int ret = 0; | ||
335 | |||
336 | ndev->ops->deassert_int(ndev); | ||
337 | 285 | ||
338 | /* Retrieve frame from SPI */ | 286 | /* Retrieve frame from SPI */ |
339 | skb = __nci_spi_recv_frame(ndev); | 287 | skb = __nci_spi_read(nspi); |
340 | if (!skb) { | 288 | if (!skb) |
341 | ret = -EIO; | ||
342 | goto done; | 289 | goto done; |
343 | } | ||
344 | 290 | ||
345 | if (ndev->acknowledge_mode == NCI_SPI_CRC_ENABLED) { | 291 | if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED) { |
346 | if (!nci_spi_check_crc(skb)) { | 292 | if (!nci_spi_check_crc(skb)) { |
347 | send_acknowledge(ndev, ACKNOWLEDGE_NACK); | 293 | send_acknowledge(nspi, ACKNOWLEDGE_NACK); |
348 | goto done; | 294 | goto done; |
349 | } | 295 | } |
350 | 296 | ||
351 | /* In case of acknowledged mode: if ACK or NACK received, | 297 | /* In case of acknowledged mode: if ACK or NACK received, |
352 | * unblock completion of latest frame sent. | 298 | * unblock completion of latest frame sent. |
353 | */ | 299 | */ |
354 | ndev->req_result = nci_spi_get_ack(skb); | 300 | nspi->req_result = nci_spi_get_ack(skb); |
355 | if (ndev->req_result) | 301 | if (nspi->req_result) |
356 | complete(&ndev->req_completion); | 302 | complete(&nspi->req_completion); |
357 | } | 303 | } |
358 | 304 | ||
359 | /* If there is no payload (ACK/NACK only frame), | 305 | /* If there is no payload (ACK/NACK only frame), |
360 | * free the socket buffer | 306 | * free the socket buffer |
361 | */ | 307 | */ |
362 | if (skb->len == 0) { | 308 | if (!skb->len) { |
363 | kfree_skb(skb); | 309 | kfree_skb(skb); |
310 | skb = NULL; | ||
364 | goto done; | 311 | goto done; |
365 | } | 312 | } |
366 | 313 | ||
367 | if (ndev->acknowledge_mode == NCI_SPI_CRC_ENABLED) | 314 | if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED) |
368 | send_acknowledge(ndev, ACKNOWLEDGE_ACK); | 315 | send_acknowledge(nspi, ACKNOWLEDGE_ACK); |
369 | |||
370 | /* Forward skb to NCI core layer */ | ||
371 | ret = nci_recv_frame(ndev->nci_dev, skb); | ||
372 | 316 | ||
373 | done: | 317 | done: |
374 | ndev->ops->assert_int(ndev); | ||
375 | 318 | ||
376 | return ret; | 319 | return skb; |
377 | } | 320 | } |
378 | EXPORT_SYMBOL_GPL(nci_spi_recv_frame); | 321 | EXPORT_SYMBOL_GPL(nci_spi_read); |
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index 68063b2025da..84b7e3ea7b7a 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c | |||
@@ -58,6 +58,7 @@ static const struct nla_policy nfc_genl_policy[NFC_ATTR_MAX + 1] = { | |||
58 | [NFC_ATTR_LLC_SDP] = { .type = NLA_NESTED }, | 58 | [NFC_ATTR_LLC_SDP] = { .type = NLA_NESTED }, |
59 | [NFC_ATTR_FIRMWARE_NAME] = { .type = NLA_STRING, | 59 | [NFC_ATTR_FIRMWARE_NAME] = { .type = NLA_STRING, |
60 | .len = NFC_FIRMWARE_NAME_MAXSIZE }, | 60 | .len = NFC_FIRMWARE_NAME_MAXSIZE }, |
61 | [NFC_ATTR_SE_APDU] = { .type = NLA_BINARY }, | ||
61 | }; | 62 | }; |
62 | 63 | ||
63 | static const struct nla_policy nfc_sdp_genl_policy[NFC_SDP_ATTR_MAX + 1] = { | 64 | static const struct nla_policy nfc_sdp_genl_policy[NFC_SDP_ATTR_MAX + 1] = { |
@@ -1278,6 +1279,91 @@ static int nfc_genl_dump_ses_done(struct netlink_callback *cb) | |||
1278 | return 0; | 1279 | return 0; |
1279 | } | 1280 | } |
1280 | 1281 | ||
1282 | struct se_io_ctx { | ||
1283 | u32 dev_idx; | ||
1284 | u32 se_idx; | ||
1285 | }; | ||
1286 | |||
1287 | static void se_io_cb(void *context, u8 *apdu, size_t apdu_len, int err) | ||
1288 | { | ||
1289 | struct se_io_ctx *ctx = context; | ||
1290 | struct sk_buff *msg; | ||
1291 | void *hdr; | ||
1292 | |||
1293 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
1294 | if (!msg) { | ||
1295 | kfree(ctx); | ||
1296 | return; | ||
1297 | } | ||
1298 | |||
1299 | hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, | ||
1300 | NFC_CMD_SE_IO); | ||
1301 | if (!hdr) | ||
1302 | goto free_msg; | ||
1303 | |||
1304 | if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, ctx->dev_idx) || | ||
1305 | nla_put_u32(msg, NFC_ATTR_SE_INDEX, ctx->se_idx) || | ||
1306 | nla_put(msg, NFC_ATTR_SE_APDU, apdu_len, apdu)) | ||
1307 | goto nla_put_failure; | ||
1308 | |||
1309 | genlmsg_end(msg, hdr); | ||
1310 | |||
1311 | genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL); | ||
1312 | |||
1313 | kfree(ctx); | ||
1314 | |||
1315 | return; | ||
1316 | |||
1317 | nla_put_failure: | ||
1318 | genlmsg_cancel(msg, hdr); | ||
1319 | free_msg: | ||
1320 | nlmsg_free(msg); | ||
1321 | kfree(ctx); | ||
1322 | |||
1323 | return; | ||
1324 | } | ||
1325 | |||
1326 | static int nfc_genl_se_io(struct sk_buff *skb, struct genl_info *info) | ||
1327 | { | ||
1328 | struct nfc_dev *dev; | ||
1329 | struct se_io_ctx *ctx; | ||
1330 | u32 dev_idx, se_idx; | ||
1331 | u8 *apdu; | ||
1332 | size_t apdu_len; | ||
1333 | |||
1334 | if (!info->attrs[NFC_ATTR_DEVICE_INDEX] || | ||
1335 | !info->attrs[NFC_ATTR_SE_INDEX] || | ||
1336 | !info->attrs[NFC_ATTR_SE_APDU]) | ||
1337 | return -EINVAL; | ||
1338 | |||
1339 | dev_idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); | ||
1340 | se_idx = nla_get_u32(info->attrs[NFC_ATTR_SE_INDEX]); | ||
1341 | |||
1342 | dev = nfc_get_device(dev_idx); | ||
1343 | if (!dev) | ||
1344 | return -ENODEV; | ||
1345 | |||
1346 | if (!dev->ops || !dev->ops->se_io) | ||
1347 | return -ENOTSUPP; | ||
1348 | |||
1349 | apdu_len = nla_len(info->attrs[NFC_ATTR_SE_APDU]); | ||
1350 | if (apdu_len == 0) | ||
1351 | return -EINVAL; | ||
1352 | |||
1353 | apdu = nla_data(info->attrs[NFC_ATTR_SE_APDU]); | ||
1354 | if (!apdu) | ||
1355 | return -EINVAL; | ||
1356 | |||
1357 | ctx = kzalloc(sizeof(struct se_io_ctx), GFP_KERNEL); | ||
1358 | if (!ctx) | ||
1359 | return -ENOMEM; | ||
1360 | |||
1361 | ctx->dev_idx = dev_idx; | ||
1362 | ctx->se_idx = se_idx; | ||
1363 | |||
1364 | return dev->ops->se_io(dev, se_idx, apdu, apdu_len, se_io_cb, ctx); | ||
1365 | } | ||
1366 | |||
1281 | static struct genl_ops nfc_genl_ops[] = { | 1367 | static struct genl_ops nfc_genl_ops[] = { |
1282 | { | 1368 | { |
1283 | .cmd = NFC_CMD_GET_DEVICE, | 1369 | .cmd = NFC_CMD_GET_DEVICE, |
@@ -1358,6 +1444,11 @@ static struct genl_ops nfc_genl_ops[] = { | |||
1358 | .done = nfc_genl_dump_ses_done, | 1444 | .done = nfc_genl_dump_ses_done, |
1359 | .policy = nfc_genl_policy, | 1445 | .policy = nfc_genl_policy, |
1360 | }, | 1446 | }, |
1447 | { | ||
1448 | .cmd = NFC_CMD_SE_IO, | ||
1449 | .doit = nfc_genl_se_io, | ||
1450 | .policy = nfc_genl_policy, | ||
1451 | }, | ||
1361 | }; | 1452 | }; |
1362 | 1453 | ||
1363 | 1454 | ||
diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c index 313bf1bc848a..cd958b381f96 100644 --- a/net/nfc/rawsock.c +++ b/net/nfc/rawsock.c | |||
@@ -142,11 +142,11 @@ static void rawsock_data_exchange_complete(void *context, struct sk_buff *skb, | |||
142 | 142 | ||
143 | err = rawsock_add_header(skb); | 143 | err = rawsock_add_header(skb); |
144 | if (err) | 144 | if (err) |
145 | goto error; | 145 | goto error_skb; |
146 | 146 | ||
147 | err = sock_queue_rcv_skb(sk, skb); | 147 | err = sock_queue_rcv_skb(sk, skb); |
148 | if (err) | 148 | if (err) |
149 | goto error; | 149 | goto error_skb; |
150 | 150 | ||
151 | spin_lock_bh(&sk->sk_write_queue.lock); | 151 | spin_lock_bh(&sk->sk_write_queue.lock); |
152 | if (!skb_queue_empty(&sk->sk_write_queue)) | 152 | if (!skb_queue_empty(&sk->sk_write_queue)) |
@@ -158,6 +158,9 @@ static void rawsock_data_exchange_complete(void *context, struct sk_buff *skb, | |||
158 | sock_put(sk); | 158 | sock_put(sk); |
159 | return; | 159 | return; |
160 | 160 | ||
161 | error_skb: | ||
162 | kfree_skb(skb); | ||
163 | |||
161 | error: | 164 | error: |
162 | rawsock_report_error(sk, err); | 165 | rawsock_report_error(sk, err); |
163 | sock_put(sk); | 166 | sock_put(sk); |