aboutsummaryrefslogtreecommitdiffstats
path: root/net/nfc
diff options
context:
space:
mode:
authorMark A. Greer <mgreer@animalcreek.com>2014-07-22 00:24:39 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2014-07-22 19:17:31 -0400
commitbf30a67c947ed57c1cf7c68a47dc24331458037e (patch)
treeabd0341d5faa9431a964d3cd7349d5bc801b8f44 /net/nfc
parentf63bac94bfe2b7f98d28e5c7d3432a5060841f51 (diff)
NFC: digital: Add 'tg_listen_md' and 'tg_get_rf_tech' driver hooks
The digital layer of the NFC subsystem currently supports a 'tg_listen_mdaa' driver hook that supports devices that can do mode detection and automatic anticollision. However, there are some devices that can do mode detection but not automatic anitcollision so add the 'tg_listen_md' hook to support those devices. In order for the digital layer to get the RF technology detected by the device from the driver, add the 'tg_get_rf_tech' hook. It is only valid to call this hook immediately after a successful call to 'tg_listen_md'. CC: Thierry Escande <thierry.escande@linux.intel.com> Signed-off-by: Mark A. Greer <mgreer@animalcreek.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'net/nfc')
-rw-r--r--net/nfc/digital.h3
-rw-r--r--net/nfc/digital_core.c16
-rw-r--r--net/nfc/digital_technology.c71
3 files changed, 81 insertions, 9 deletions
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
122int digital_tg_listen_nfca(struct nfc_digital_dev *ddev, u8 rf_tech); 123int digital_tg_listen_nfca(struct nfc_digital_dev *ddev, u8 rf_tech);
123int digital_tg_listen_nfcf(struct nfc_digital_dev *ddev, u8 rf_tech); 124int digital_tg_listen_nfcf(struct nfc_digital_dev *ddev, u8 rf_tech);
125void digital_tg_recv_md_req(struct nfc_digital_dev *ddev, void *arg,
126 struct sk_buff *resp);
124 127
125typedef u16 (*crc_func_t)(u16, const u8 *, size_t); 128typedef 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
301static 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
296int digital_target_found(struct nfc_digital_dev *ddev, 307int 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
1221int digital_tg_listen_nfca(struct nfc_digital_dev *ddev, u8 rf_tech) 1221static 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
1234int 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
1237int digital_tg_listen_nfcf(struct nfc_digital_dev *ddev, u8 rf_tech) 1245static 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
1257int 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
1277void 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
1312exit_free_skb:
1313 digital_poll_next_tech(ddev);
1314 dev_kfree_skb(resp);
1315}