aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/nfc
diff options
context:
space:
mode:
authorSamuel Ortiz <sameo@linux.intel.com>2011-12-14 10:43:11 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-12-14 14:50:13 -0500
commit361f3cb7f9cfdb82c80926d0e7843c098c034545 (patch)
treeed61b2e95795fc18cce925bc89eceb2f8a915484 /drivers/nfc
parent541d920b05b538ec0d9ae8ce619ee4fc6fb19e32 (diff)
NFC: DEP link hook implementation for pn533
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/nfc')
-rw-r--r--drivers/nfc/pn533.c159
1 files changed, 159 insertions, 0 deletions
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index dccd96552f5d..b8b6c2abbd4a 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -72,6 +72,7 @@ MODULE_DEVICE_TABLE(usb, pn533_table);
72#define PN533_CMD_IN_LIST_PASSIVE_TARGET 0x4A 72#define PN533_CMD_IN_LIST_PASSIVE_TARGET 0x4A
73#define PN533_CMD_IN_ATR 0x50 73#define PN533_CMD_IN_ATR 0x50
74#define PN533_CMD_IN_RELEASE 0x52 74#define PN533_CMD_IN_RELEASE 0x52
75#define PN533_CMD_IN_JUMP_FOR_DEP 0x56
75 76
76#define PN533_CMD_RESPONSE(cmd) (cmd + 1) 77#define PN533_CMD_RESPONSE(cmd) (cmd + 1)
77 78
@@ -231,6 +232,26 @@ struct pn533_cmd_activate_response {
231 u8 gt[]; 232 u8 gt[];
232} __packed; 233} __packed;
233 234
235/* PN533_CMD_IN_JUMP_FOR_DEP */
236struct pn533_cmd_jump_dep {
237 u8 active;
238 u8 baud;
239 u8 next;
240 u8 gt[];
241} __packed;
242
243struct pn533_cmd_jump_dep_response {
244 u8 status;
245 u8 tg;
246 u8 nfcid3t[10];
247 u8 didt;
248 u8 bst;
249 u8 brt;
250 u8 to;
251 u8 ppt;
252 /* optional */
253 u8 gt[];
254} __packed;
234 255
235struct pn533 { 256struct pn533 {
236 struct usb_device *udev; 257 struct usb_device *udev;
@@ -1244,6 +1265,142 @@ static void pn533_deactivate_target(struct nfc_dev *nfc_dev, u32 target_idx)
1244 return; 1265 return;
1245} 1266}
1246 1267
1268
1269static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg,
1270 u8 *params, int params_len)
1271{
1272 struct pn533_cmd_jump_dep *cmd;
1273 struct pn533_cmd_jump_dep_response *resp;
1274 struct nfc_target nfc_target;
1275 u8 target_gt_len;
1276 int rc;
1277
1278 if (params_len == -ENOENT) {
1279 nfc_dev_dbg(&dev->interface->dev, "");
1280 return 0;
1281 }
1282
1283 if (params_len < 0) {
1284 nfc_dev_err(&dev->interface->dev,
1285 "Error %d when bringing DEP link up",
1286 params_len);
1287 return 0;
1288 }
1289
1290 if (dev->tgt_available_prots &&
1291 !(dev->tgt_available_prots & (1 << NFC_PROTO_NFC_DEP))) {
1292 nfc_dev_err(&dev->interface->dev,
1293 "The target does not support DEP");
1294 return -EINVAL;
1295 }
1296
1297 resp = (struct pn533_cmd_jump_dep_response *) params;
1298 cmd = (struct pn533_cmd_jump_dep *) arg;
1299 rc = resp->status & PN533_CMD_RET_MASK;
1300 if (rc != PN533_CMD_RET_SUCCESS) {
1301 nfc_dev_err(&dev->interface->dev,
1302 "Bringing DEP link up failed %d", rc);
1303 return 0;
1304 }
1305
1306 if (!dev->tgt_available_prots) {
1307 nfc_dev_dbg(&dev->interface->dev, "Creating new target");
1308
1309 nfc_target.supported_protocols = NFC_PROTO_NFC_DEP_MASK;
1310 rc = nfc_targets_found(dev->nfc_dev, &nfc_target, 1);
1311 if (rc)
1312 return 0;
1313
1314 dev->tgt_available_prots = 0;
1315 }
1316
1317 dev->tgt_active_prot = NFC_PROTO_NFC_DEP;
1318
1319 /* ATR_RES general bytes are located at offset 17 */
1320 target_gt_len = PN533_FRAME_CMD_PARAMS_LEN(dev->in_frame) - 17;
1321 rc = nfc_set_remote_general_bytes(dev->nfc_dev,
1322 resp->gt, target_gt_len);
1323 if (rc == 0)
1324 rc = nfc_dep_link_is_up(dev->nfc_dev,
1325 dev->nfc_dev->targets[0].idx,
1326 !cmd->active, NFC_RF_INITIATOR);
1327
1328 return 0;
1329}
1330
1331static int pn533_dep_link_up(struct nfc_dev *nfc_dev, int target_idx,
1332 u8 comm_mode, u8 rf_mode)
1333{
1334 struct pn533 *dev = nfc_get_drvdata(nfc_dev);
1335 struct pn533_cmd_jump_dep *cmd;
1336 u8 cmd_len, local_gt_len, *local_gt;
1337 int rc;
1338
1339 nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
1340
1341 if (rf_mode == NFC_RF_TARGET) {
1342 nfc_dev_err(&dev->interface->dev, "Target mode not supported");
1343 return -EOPNOTSUPP;
1344 }
1345
1346
1347 if (dev->poll_mod_count) {
1348 nfc_dev_err(&dev->interface->dev,
1349 "Cannot bring the DEP link up while polling");
1350 return -EBUSY;
1351 }
1352
1353 if (dev->tgt_active_prot) {
1354 nfc_dev_err(&dev->interface->dev,
1355 "There is already an active target");
1356 return -EBUSY;
1357 }
1358
1359 local_gt = nfc_get_local_general_bytes(dev->nfc_dev, &local_gt_len);
1360 if (local_gt_len > NFC_MAX_GT_LEN)
1361 return -EINVAL;
1362
1363 cmd_len = sizeof(struct pn533_cmd_jump_dep) + local_gt_len;
1364 cmd = kzalloc(cmd_len, GFP_KERNEL);
1365 if (cmd == NULL)
1366 return -ENOMEM;
1367
1368 pn533_tx_frame_init(dev->out_frame, PN533_CMD_IN_JUMP_FOR_DEP);
1369
1370 cmd->active = !comm_mode;
1371 cmd->baud = 0;
1372 if (local_gt != NULL) {
1373 cmd->next = 4; /* We have some Gi */
1374 memcpy(cmd->gt, local_gt, local_gt_len);
1375 } else {
1376 cmd->next = 0;
1377 }
1378
1379 memcpy(PN533_FRAME_CMD_PARAMS_PTR(dev->out_frame), cmd, cmd_len);
1380 dev->out_frame->datalen += cmd_len;
1381
1382 pn533_tx_frame_finish(dev->out_frame);
1383
1384 rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame,
1385 dev->in_maxlen, pn533_in_dep_link_up_complete,
1386 cmd, GFP_KERNEL);
1387 if (rc)
1388 goto out;
1389
1390
1391out:
1392 kfree(cmd);
1393
1394 return rc;
1395}
1396
1397static int pn533_dep_link_down(struct nfc_dev *nfc_dev)
1398{
1399 pn533_deactivate_target(nfc_dev, 0);
1400
1401 return 0;
1402}
1403
1247#define PN533_CMD_DATAEXCH_HEAD_LEN (sizeof(struct pn533_frame) + 3) 1404#define PN533_CMD_DATAEXCH_HEAD_LEN (sizeof(struct pn533_frame) + 3)
1248#define PN533_CMD_DATAEXCH_DATA_MAXLEN 262 1405#define PN533_CMD_DATAEXCH_DATA_MAXLEN 262
1249 1406
@@ -1439,6 +1596,8 @@ static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata,
1439struct nfc_ops pn533_nfc_ops = { 1596struct nfc_ops pn533_nfc_ops = {
1440 .dev_up = NULL, 1597 .dev_up = NULL,
1441 .dev_down = NULL, 1598 .dev_down = NULL,
1599 .dep_link_up = pn533_dep_link_up,
1600 .dep_link_down = pn533_dep_link_down,
1442 .start_poll = pn533_start_poll, 1601 .start_poll = pn533_start_poll,
1443 .stop_poll = pn533_stop_poll, 1602 .stop_poll = pn533_stop_poll,
1444 .activate_target = pn533_activate_target, 1603 .activate_target = pn533_activate_target,