diff options
-rw-r--r-- | include/net/nfc/digital.h | 12 | ||||
-rw-r--r-- | net/nfc/digital.h | 3 | ||||
-rw-r--r-- | net/nfc/digital_core.c | 16 | ||||
-rw-r--r-- | net/nfc/digital_technology.c | 71 |
4 files changed, 93 insertions, 9 deletions
diff --git a/include/net/nfc/digital.h b/include/net/nfc/digital.h index 575d668b7852..d9a5cf7ac1c4 100644 --- a/include/net/nfc/digital.h +++ b/include/net/nfc/digital.h | |||
@@ -127,6 +127,15 @@ typedef void (*nfc_digital_cmd_complete_t)(struct nfc_digital_dev *ddev, | |||
127 | * the NFC-DEP ATR_REQ command through cb. The digital stack deducts the RF | 127 | * the NFC-DEP ATR_REQ command through cb. The digital stack deducts the RF |
128 | * tech by analyzing the SoD of the frame containing the ATR_REQ command. | 128 | * tech by analyzing the SoD of the frame containing the ATR_REQ command. |
129 | * This is an asynchronous function. | 129 | * This is an asynchronous function. |
130 | * @tg_listen_md: If supported, put the device in automatic listen mode with | ||
131 | * mode detection but without automatic anti-collision. In this mode, the | ||
132 | * device automatically detects the RF technology. What the actual | ||
133 | * RF technology is can be retrieved by calling @tg_get_rf_tech. | ||
134 | * The digital stack will then perform the appropriate anti-collision | ||
135 | * sequence. This is an asynchronous function. | ||
136 | * @tg_get_rf_tech: Required when @tg_listen_md is supported, unused otherwise. | ||
137 | * Return the RF Technology that was detected by the @tg_listen_md call. | ||
138 | * This is a synchronous function. | ||
130 | * | 139 | * |
131 | * @switch_rf: Turns device radio on or off. The stack does not call explicitly | 140 | * @switch_rf: Turns device radio on or off. The stack does not call explicitly |
132 | * switch_rf to turn the radio on. A call to in|tg_configure_hw must turn | 141 | * switch_rf to turn the radio on. A call to in|tg_configure_hw must turn |
@@ -161,6 +170,9 @@ struct nfc_digital_ops { | |||
161 | struct digital_tg_mdaa_params *mdaa_params, | 170 | struct digital_tg_mdaa_params *mdaa_params, |
162 | u16 timeout, nfc_digital_cmd_complete_t cb, | 171 | u16 timeout, nfc_digital_cmd_complete_t cb, |
163 | void *arg); | 172 | void *arg); |
173 | int (*tg_listen_md)(struct nfc_digital_dev *ddev, u16 timeout, | ||
174 | nfc_digital_cmd_complete_t cb, void *arg); | ||
175 | int (*tg_get_rf_tech)(struct nfc_digital_dev *ddev, u8 *rf_tech); | ||
164 | 176 | ||
165 | int (*switch_rf)(struct nfc_digital_dev *ddev, bool on); | 177 | int (*switch_rf)(struct nfc_digital_dev *ddev, bool on); |
166 | void (*abort_cmd)(struct nfc_digital_dev *ddev); | 178 | void (*abort_cmd)(struct nfc_digital_dev *ddev); |
diff --git a/net/nfc/digital.h b/net/nfc/digital.h index 71ad7eefddd4..3c39c72eb038 100644 --- a/net/nfc/digital.h +++ b/net/nfc/digital.h | |||
@@ -29,6 +29,7 @@ | |||
29 | #define DIGITAL_CMD_TG_SEND 1 | 29 | #define DIGITAL_CMD_TG_SEND 1 |
30 | #define DIGITAL_CMD_TG_LISTEN 2 | 30 | #define DIGITAL_CMD_TG_LISTEN 2 |
31 | #define DIGITAL_CMD_TG_LISTEN_MDAA 3 | 31 | #define DIGITAL_CMD_TG_LISTEN_MDAA 3 |
32 | #define DIGITAL_CMD_TG_LISTEN_MD 4 | ||
32 | 33 | ||
33 | #define DIGITAL_MAX_HEADER_LEN 7 | 34 | #define DIGITAL_MAX_HEADER_LEN 7 |
34 | #define DIGITAL_CRC_LEN 2 | 35 | #define DIGITAL_CRC_LEN 2 |
@@ -121,6 +122,8 @@ int digital_tg_send_dep_res(struct nfc_digital_dev *ddev, struct sk_buff *skb); | |||
121 | 122 | ||
122 | int digital_tg_listen_nfca(struct nfc_digital_dev *ddev, u8 rf_tech); | 123 | int digital_tg_listen_nfca(struct nfc_digital_dev *ddev, u8 rf_tech); |
123 | int digital_tg_listen_nfcf(struct nfc_digital_dev *ddev, u8 rf_tech); | 124 | int digital_tg_listen_nfcf(struct nfc_digital_dev *ddev, u8 rf_tech); |
125 | void digital_tg_recv_md_req(struct nfc_digital_dev *ddev, void *arg, | ||
126 | struct sk_buff *resp); | ||
124 | 127 | ||
125 | typedef u16 (*crc_func_t)(u16, const u8 *, size_t); | 128 | typedef u16 (*crc_func_t)(u16, const u8 *, size_t); |
126 | 129 | ||
diff --git a/net/nfc/digital_core.c b/net/nfc/digital_core.c index 361bc37d2db1..009bcf317101 100644 --- a/net/nfc/digital_core.c +++ b/net/nfc/digital_core.c | |||
@@ -201,6 +201,11 @@ static void digital_wq_cmd(struct work_struct *work) | |||
201 | digital_send_cmd_complete, cmd); | 201 | digital_send_cmd_complete, cmd); |
202 | break; | 202 | break; |
203 | 203 | ||
204 | case DIGITAL_CMD_TG_LISTEN_MD: | ||
205 | rc = ddev->ops->tg_listen_md(ddev, cmd->timeout, | ||
206 | digital_send_cmd_complete, cmd); | ||
207 | break; | ||
208 | |||
204 | default: | 209 | default: |
205 | pr_err("Unknown cmd type %d\n", cmd->type); | 210 | pr_err("Unknown cmd type %d\n", cmd->type); |
206 | return; | 211 | return; |
@@ -293,6 +298,12 @@ static int digital_tg_listen_mdaa(struct nfc_digital_dev *ddev, u8 rf_tech) | |||
293 | 500, digital_tg_recv_atr_req, NULL); | 298 | 500, digital_tg_recv_atr_req, NULL); |
294 | } | 299 | } |
295 | 300 | ||
301 | static int digital_tg_listen_md(struct nfc_digital_dev *ddev, u8 rf_tech) | ||
302 | { | ||
303 | return digital_send_cmd(ddev, DIGITAL_CMD_TG_LISTEN_MD, NULL, NULL, 500, | ||
304 | digital_tg_recv_md_req, NULL); | ||
305 | } | ||
306 | |||
296 | int digital_target_found(struct nfc_digital_dev *ddev, | 307 | int digital_target_found(struct nfc_digital_dev *ddev, |
297 | struct nfc_target *target, u8 protocol) | 308 | struct nfc_target *target, u8 protocol) |
298 | { | 309 | { |
@@ -510,6 +521,9 @@ static int digital_start_poll(struct nfc_dev *nfc_dev, __u32 im_protocols, | |||
510 | if (ddev->ops->tg_listen_mdaa) { | 521 | if (ddev->ops->tg_listen_mdaa) { |
511 | digital_add_poll_tech(ddev, 0, | 522 | digital_add_poll_tech(ddev, 0, |
512 | digital_tg_listen_mdaa); | 523 | digital_tg_listen_mdaa); |
524 | } else if (ddev->ops->tg_listen_md) { | ||
525 | digital_add_poll_tech(ddev, 0, | ||
526 | digital_tg_listen_md); | ||
513 | } else { | 527 | } else { |
514 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_106A, | 528 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_106A, |
515 | digital_tg_listen_nfca); | 529 | digital_tg_listen_nfca); |
@@ -737,7 +751,7 @@ struct nfc_digital_dev *nfc_digital_allocate_device(struct nfc_digital_ops *ops, | |||
737 | 751 | ||
738 | if (!ops->in_configure_hw || !ops->in_send_cmd || !ops->tg_listen || | 752 | if (!ops->in_configure_hw || !ops->in_send_cmd || !ops->tg_listen || |
739 | !ops->tg_configure_hw || !ops->tg_send_cmd || !ops->abort_cmd || | 753 | !ops->tg_configure_hw || !ops->tg_send_cmd || !ops->abort_cmd || |
740 | !ops->switch_rf) | 754 | !ops->switch_rf || (ops->tg_listen_md && !ops->tg_get_rf_tech)) |
741 | return NULL; | 755 | return NULL; |
742 | 756 | ||
743 | ddev = kzalloc(sizeof(struct nfc_digital_dev), GFP_KERNEL); | 757 | ddev = kzalloc(sizeof(struct nfc_digital_dev), GFP_KERNEL); |
diff --git a/net/nfc/digital_technology.c b/net/nfc/digital_technology.c index d276518cc8bf..fb58ed2dd41d 100644 --- a/net/nfc/digital_technology.c +++ b/net/nfc/digital_technology.c | |||
@@ -1218,33 +1218,48 @@ exit: | |||
1218 | dev_kfree_skb(resp); | 1218 | dev_kfree_skb(resp); |
1219 | } | 1219 | } |
1220 | 1220 | ||
1221 | int digital_tg_listen_nfca(struct nfc_digital_dev *ddev, u8 rf_tech) | 1221 | static int digital_tg_config_nfca(struct nfc_digital_dev *ddev) |
1222 | { | 1222 | { |
1223 | int rc; | 1223 | int rc; |
1224 | 1224 | ||
1225 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, rf_tech); | 1225 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, |
1226 | NFC_DIGITAL_RF_TECH_106A); | ||
1226 | if (rc) | 1227 | if (rc) |
1227 | return rc; | 1228 | return rc; |
1228 | 1229 | ||
1229 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, | 1230 | return digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, |
1230 | NFC_DIGITAL_FRAMING_NFCA_NFC_DEP); | 1231 | NFC_DIGITAL_FRAMING_NFCA_NFC_DEP); |
1232 | } | ||
1233 | |||
1234 | int digital_tg_listen_nfca(struct nfc_digital_dev *ddev, u8 rf_tech) | ||
1235 | { | ||
1236 | int rc; | ||
1237 | |||
1238 | rc = digital_tg_config_nfca(ddev); | ||
1231 | if (rc) | 1239 | if (rc) |
1232 | return rc; | 1240 | return rc; |
1233 | 1241 | ||
1234 | return digital_tg_listen(ddev, 300, digital_tg_recv_sens_req, NULL); | 1242 | return digital_tg_listen(ddev, 300, digital_tg_recv_sens_req, NULL); |
1235 | } | 1243 | } |
1236 | 1244 | ||
1237 | int digital_tg_listen_nfcf(struct nfc_digital_dev *ddev, u8 rf_tech) | 1245 | static int digital_tg_config_nfcf(struct nfc_digital_dev *ddev, u8 rf_tech) |
1238 | { | 1246 | { |
1239 | int rc; | 1247 | int rc; |
1240 | u8 *nfcid2; | ||
1241 | 1248 | ||
1242 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, rf_tech); | 1249 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, rf_tech); |
1243 | if (rc) | 1250 | if (rc) |
1244 | return rc; | 1251 | return rc; |
1245 | 1252 | ||
1246 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, | 1253 | return digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, |
1247 | NFC_DIGITAL_FRAMING_NFCF_NFC_DEP); | 1254 | NFC_DIGITAL_FRAMING_NFCF_NFC_DEP); |
1255 | } | ||
1256 | |||
1257 | int digital_tg_listen_nfcf(struct nfc_digital_dev *ddev, u8 rf_tech) | ||
1258 | { | ||
1259 | int rc; | ||
1260 | u8 *nfcid2; | ||
1261 | |||
1262 | rc = digital_tg_config_nfcf(ddev, rf_tech); | ||
1248 | if (rc) | 1263 | if (rc) |
1249 | return rc; | 1264 | return rc; |
1250 | 1265 | ||
@@ -1258,3 +1273,43 @@ int digital_tg_listen_nfcf(struct nfc_digital_dev *ddev, u8 rf_tech) | |||
1258 | 1273 | ||
1259 | return digital_tg_listen(ddev, 300, digital_tg_recv_sensf_req, nfcid2); | 1274 | return digital_tg_listen(ddev, 300, digital_tg_recv_sensf_req, nfcid2); |
1260 | } | 1275 | } |
1276 | |||
1277 | void digital_tg_recv_md_req(struct nfc_digital_dev *ddev, void *arg, | ||
1278 | struct sk_buff *resp) | ||
1279 | { | ||
1280 | u8 rf_tech; | ||
1281 | int rc; | ||
1282 | |||
1283 | if (IS_ERR(resp)) { | ||
1284 | resp = NULL; | ||
1285 | goto exit_free_skb; | ||
1286 | } | ||
1287 | |||
1288 | rc = ddev->ops->tg_get_rf_tech(ddev, &rf_tech); | ||
1289 | if (rc) | ||
1290 | goto exit_free_skb; | ||
1291 | |||
1292 | switch (rf_tech) { | ||
1293 | case NFC_DIGITAL_RF_TECH_106A: | ||
1294 | rc = digital_tg_config_nfca(ddev); | ||
1295 | if (rc) | ||
1296 | goto exit_free_skb; | ||
1297 | digital_tg_recv_sens_req(ddev, arg, resp); | ||
1298 | break; | ||
1299 | case NFC_DIGITAL_RF_TECH_212F: | ||
1300 | case NFC_DIGITAL_RF_TECH_424F: | ||
1301 | rc = digital_tg_config_nfcf(ddev, rf_tech); | ||
1302 | if (rc) | ||
1303 | goto exit_free_skb; | ||
1304 | digital_tg_recv_sensf_req(ddev, arg, resp); | ||
1305 | break; | ||
1306 | default: | ||
1307 | goto exit_free_skb; | ||
1308 | } | ||
1309 | |||
1310 | return; | ||
1311 | |||
1312 | exit_free_skb: | ||
1313 | digital_poll_next_tech(ddev); | ||
1314 | dev_kfree_skb(resp); | ||
1315 | } | ||