aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/nfc
diff options
context:
space:
mode:
authorSamuel Ortiz <sameo@linux.intel.com>2012-05-30 17:54:55 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2012-06-04 15:34:29 -0400
commitad3823cef650bdc1ca9e7bf1a01b87ad3c0425de (patch)
treeee616628813e0fe244afb55e568a769203cc4c0a /drivers/nfc
parentfe7c580073280c15bb4eb4f82bf20dddc1a68383 (diff)
NFC: Implement pn533 target mode polling loop
We only want to support p2p target mode for now, no host card emulation. Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/nfc')
-rw-r--r--drivers/nfc/pn533.c109
1 files changed, 104 insertions, 5 deletions
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index 38a523c62132..605a08a62e45 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -74,6 +74,8 @@ MODULE_DEVICE_TABLE(usb, pn533_table);
74#define PN533_CMD_IN_RELEASE 0x52 74#define PN533_CMD_IN_RELEASE 0x52
75#define PN533_CMD_IN_JUMP_FOR_DEP 0x56 75#define PN533_CMD_IN_JUMP_FOR_DEP 0x56
76 76
77#define PN533_CMD_TG_INIT_AS_TARGET 0x8c
78
77#define PN533_CMD_RESPONSE(cmd) (cmd + 1) 79#define PN533_CMD_RESPONSE(cmd) (cmd + 1)
78 80
79/* PN533 Return codes */ 81/* PN533 Return codes */
@@ -253,6 +255,25 @@ struct pn533_cmd_jump_dep_response {
253 u8 gt[]; 255 u8 gt[];
254} __packed; 256} __packed;
255 257
258
259/* PN533_TG_INIT_AS_TARGET */
260#define PN533_INIT_TARGET_PASSIVE 0x1
261#define PN533_INIT_TARGET_DEP 0x2
262
263struct pn533_cmd_init_target {
264 u8 mode;
265 u8 mifare[6];
266 u8 felica[18];
267 u8 nfcid3[10];
268 u8 gb_len;
269 u8 gb[];
270} __packed;
271
272struct pn533_cmd_init_target_response {
273 u8 mode;
274 u8 cmd[];
275} __packed;
276
256struct pn533 { 277struct pn533 {
257 struct usb_device *udev; 278 struct usb_device *udev;
258 struct usb_interface *interface; 279 struct usb_interface *interface;
@@ -1078,11 +1099,88 @@ stop_poll:
1078 return 0; 1099 return 0;
1079} 1100}
1080 1101
1081static int pn533_init_target(struct nfc_dev *nfc_dev, u32 protocols) 1102static int pn533_init_target_frame(struct pn533_frame *frame,
1103 u8 *gb, size_t gb_len)
1082{ 1104{
1105 struct pn533_cmd_init_target *cmd;
1106 size_t cmd_len;
1107
1108 cmd_len = sizeof(struct pn533_cmd_init_target) + gb_len + 1;
1109 cmd = kzalloc(cmd_len, GFP_KERNEL);
1110 if (cmd == NULL)
1111 return -ENOMEM;
1112
1113 pn533_tx_frame_init(frame, PN533_CMD_TG_INIT_AS_TARGET);
1114
1115 /* DEP support only */
1116 cmd->mode |= PN533_INIT_TARGET_DEP;
1117 get_random_bytes(cmd->nfcid3, 10);
1118 cmd->gb_len = gb_len;
1119 memcpy(cmd->gb, gb, gb_len);
1120 /* Len Tk */
1121 cmd->gb[gb_len] = 0;
1122
1123 memcpy(PN533_FRAME_CMD_PARAMS_PTR(frame), cmd, cmd_len);
1124 frame->datalen += cmd_len;
1125
1126 pn533_tx_frame_finish(frame);
1127
1083 return 0; 1128 return 0;
1084} 1129}
1085 1130
1131static int pn533_init_target_complete(struct pn533 *dev, void *arg,
1132 u8 *params, int params_len)
1133{
1134 struct pn533_cmd_init_target_response *resp;
1135
1136 nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
1137
1138 if (params_len < 0) {
1139 nfc_dev_err(&dev->interface->dev,
1140 "Error %d when starting as a target",
1141 params_len);
1142
1143 return params_len;
1144 }
1145
1146 resp = (struct pn533_cmd_init_target_response *) params;
1147
1148 nfc_dev_dbg(&dev->interface->dev, "Target mode 0x%x\n", resp->mode);
1149
1150 return 0;
1151}
1152
1153static int pn533_init_target(struct nfc_dev *nfc_dev, u32 protocols)
1154{
1155 struct pn533 *dev = nfc_get_drvdata(nfc_dev);
1156 u8 *gb;
1157 size_t gb_len;
1158 int rc;
1159
1160 pn533_poll_reset_mod_list(dev);
1161
1162 gb = nfc_get_local_general_bytes(nfc_dev, &gb_len);
1163 if (gb == NULL)
1164 return -ENOMEM;
1165
1166 rc = pn533_init_target_frame(dev->out_frame, gb, gb_len);
1167 if (rc < 0)
1168 return rc;
1169
1170 rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame,
1171 dev->in_maxlen,
1172 pn533_init_target_complete,
1173 NULL, GFP_KERNEL);
1174
1175 if (rc)
1176 nfc_dev_err(&dev->interface->dev,
1177 "Error %d when trying to initiate as a target", rc);
1178
1179 dev->poll_mod_count++;
1180
1181 return rc;
1182}
1183
1086static int pn533_start_im_poll(struct nfc_dev *nfc_dev, u32 protocols) 1184static int pn533_start_im_poll(struct nfc_dev *nfc_dev, u32 protocols)
1087{ 1185{
1088 struct pn533 *dev = nfc_get_drvdata(nfc_dev); 1186 struct pn533 *dev = nfc_get_drvdata(nfc_dev);
@@ -1146,12 +1244,13 @@ static int pn533_start_poll(struct nfc_dev *nfc_dev,
1146 return -EBUSY; 1244 return -EBUSY;
1147 } 1245 }
1148 1246
1149 if (!tm_protocols) 1247 if (im_protocols)
1150 return pn533_start_im_poll(nfc_dev, im_protocols); 1248 return pn533_start_im_poll(nfc_dev, im_protocols);
1151 else if (!im_protocols) 1249
1250 if (tm_protocols)
1152 return pn533_init_target(nfc_dev, tm_protocols); 1251 return pn533_init_target(nfc_dev, tm_protocols);
1153 else 1252
1154 return -EINVAL; 1253 return -EINVAL;
1155} 1254}
1156 1255
1157static void pn533_stop_poll(struct nfc_dev *nfc_dev) 1256static void pn533_stop_poll(struct nfc_dev *nfc_dev)