aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/nfc
diff options
context:
space:
mode:
authorSamuel Ortiz <sameo@linux.intel.com>2012-05-30 18:07:51 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2012-06-04 15:34:31 -0400
commit103b34cf5fe2bb72c38afa8523dd206e6ef3b5fe (patch)
treec0c6268d9089cdc679c7873bd12ca70fbb237e39 /drivers/nfc
parent73167ced31d15c04e57b9e0885ac05675e9195a4 (diff)
NFC: Implement the pn533 target mode data fetching routine
This one needs to be called as soon as we are activated as a target, for the pn533 to receive the first SYMM and keep the LLCP link alive. Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/nfc')
-rw-r--r--drivers/nfc/pn533.c85
1 files changed, 80 insertions, 5 deletions
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index fd94c6f5d6a8..6a506e267d20 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -75,6 +75,7 @@ MODULE_DEVICE_TABLE(usb, pn533_table);
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 77#define PN533_CMD_TG_INIT_AS_TARGET 0x8c
78#define PN533_CMD_TG_GET_DATA 0x86
78 79
79#define PN533_CMD_RESPONSE(cmd) (cmd + 1) 80#define PN533_CMD_RESPONSE(cmd) (cmd + 1)
80 81
@@ -83,6 +84,9 @@ MODULE_DEVICE_TABLE(usb, pn533_table);
83#define PN533_CMD_MI_MASK 0x40 84#define PN533_CMD_MI_MASK 0x40
84#define PN533_CMD_RET_SUCCESS 0x00 85#define PN533_CMD_RET_SUCCESS 0x00
85 86
87/* PN533 status codes */
88#define PN533_STATUS_TARGET_RELEASED 0x29
89
86struct pn533; 90struct pn533;
87 91
88typedef int (*pn533_cmd_complete_t) (struct pn533 *dev, void *arg, 92typedef int (*pn533_cmd_complete_t) (struct pn533 *dev, void *arg,
@@ -296,6 +300,7 @@ struct pn533 {
296 struct workqueue_struct *wq; 300 struct workqueue_struct *wq;
297 struct work_struct cmd_work; 301 struct work_struct cmd_work;
298 struct work_struct mi_work; 302 struct work_struct mi_work;
303 struct work_struct tg_work;
299 struct pn533_frame *wq_in_frame; 304 struct pn533_frame *wq_in_frame;
300 int wq_in_error; 305 int wq_in_error;
301 306
@@ -1132,6 +1137,68 @@ static int pn533_init_target_frame(struct pn533_frame *frame,
1132 return 0; 1137 return 0;
1133} 1138}
1134 1139
1140#define PN533_CMD_DATAEXCH_HEAD_LEN (sizeof(struct pn533_frame) + 3)
1141#define PN533_CMD_DATAEXCH_DATA_MAXLEN 262
1142static int pn533_tm_get_data_complete(struct pn533 *dev, void *arg,
1143 u8 *params, int params_len)
1144{
1145 struct sk_buff *skb_resp = arg;
1146 struct pn533_frame *in_frame = (struct pn533_frame *) skb_resp->data;
1147
1148 nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
1149
1150 if (params_len < 0) {
1151 nfc_dev_err(&dev->interface->dev,
1152 "Error %d when starting as a target",
1153 params_len);
1154
1155 return params_len;
1156 }
1157
1158 if (params_len > 0 && params[0] != 0) {
1159 nfc_tm_deactivated(dev->nfc_dev);
1160
1161 kfree_skb(skb_resp);
1162 return 0;
1163 }
1164
1165 skb_put(skb_resp, PN533_FRAME_SIZE(in_frame));
1166 skb_pull(skb_resp, PN533_CMD_DATAEXCH_HEAD_LEN);
1167 skb_trim(skb_resp, skb_resp->len - PN533_FRAME_TAIL_SIZE);
1168
1169 return nfc_tm_data_received(dev->nfc_dev, skb_resp);
1170}
1171
1172static void pn533_wq_tg_get_data(struct work_struct *work)
1173{
1174 struct pn533 *dev = container_of(work, struct pn533, tg_work);
1175 struct pn533_frame *in_frame;
1176 struct sk_buff *skb_resp;
1177 size_t skb_resp_len;
1178
1179 nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
1180
1181 skb_resp_len = PN533_CMD_DATAEXCH_HEAD_LEN +
1182 PN533_CMD_DATAEXCH_DATA_MAXLEN +
1183 PN533_FRAME_TAIL_SIZE;
1184
1185 skb_resp = nfc_alloc_recv_skb(skb_resp_len, GFP_KERNEL);
1186 if (!skb_resp)
1187 return;
1188
1189 in_frame = (struct pn533_frame *)skb_resp->data;
1190
1191 pn533_tx_frame_init(dev->out_frame, PN533_CMD_TG_GET_DATA);
1192 pn533_tx_frame_finish(dev->out_frame);
1193
1194 pn533_send_cmd_frame_async(dev, dev->out_frame, in_frame,
1195 skb_resp_len,
1196 pn533_tm_get_data_complete,
1197 skb_resp, GFP_KERNEL);
1198
1199 return;
1200}
1201
1135#define ATR_REQ_GB_OFFSET 17 1202#define ATR_REQ_GB_OFFSET 17
1136static int pn533_init_target_complete(struct pn533 *dev, void *arg, 1203static int pn533_init_target_complete(struct pn533 *dev, void *arg,
1137 u8 *params, int params_len) 1204 u8 *params, int params_len)
@@ -1139,6 +1206,7 @@ static int pn533_init_target_complete(struct pn533 *dev, void *arg,
1139 struct pn533_cmd_init_target_response *resp; 1206 struct pn533_cmd_init_target_response *resp;
1140 u8 frame, comm_mode = NFC_COMM_PASSIVE, *gb; 1207 u8 frame, comm_mode = NFC_COMM_PASSIVE, *gb;
1141 size_t gb_len; 1208 size_t gb_len;
1209 int rc;
1142 1210
1143 nfc_dev_dbg(&dev->interface->dev, "%s", __func__); 1211 nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
1144 1212
@@ -1169,8 +1237,17 @@ static int pn533_init_target_complete(struct pn533 *dev, void *arg,
1169 gb = resp->cmd + ATR_REQ_GB_OFFSET; 1237 gb = resp->cmd + ATR_REQ_GB_OFFSET;
1170 gb_len = params_len - (ATR_REQ_GB_OFFSET + 1); 1238 gb_len = params_len - (ATR_REQ_GB_OFFSET + 1);
1171 1239
1172 return nfc_tm_activated(dev->nfc_dev, NFC_PROTO_NFC_DEP_MASK, 1240 rc = nfc_tm_activated(dev->nfc_dev, NFC_PROTO_NFC_DEP_MASK,
1173 comm_mode, gb, gb_len); 1241 comm_mode, gb, gb_len);
1242 if (rc < 0) {
1243 nfc_dev_err(&dev->interface->dev,
1244 "Error when signaling target activation");
1245 return rc;
1246 }
1247
1248 queue_work(dev->wq, &dev->tg_work);
1249
1250 return 0;
1174} 1251}
1175 1252
1176static int pn533_init_target(struct nfc_dev *nfc_dev, u32 protocols) 1253static int pn533_init_target(struct nfc_dev *nfc_dev, u32 protocols)
@@ -1553,9 +1630,6 @@ static int pn533_dep_link_down(struct nfc_dev *nfc_dev)
1553 return 0; 1630 return 0;
1554} 1631}
1555 1632
1556#define PN533_CMD_DATAEXCH_HEAD_LEN (sizeof(struct pn533_frame) + 3)
1557#define PN533_CMD_DATAEXCH_DATA_MAXLEN 262
1558
1559static int pn533_data_exchange_tx_frame(struct pn533 *dev, struct sk_buff *skb) 1633static int pn533_data_exchange_tx_frame(struct pn533 *dev, struct sk_buff *skb)
1560{ 1634{
1561 int payload_len = skb->len; 1635 int payload_len = skb->len;
@@ -1920,6 +1994,7 @@ static int pn533_probe(struct usb_interface *interface,
1920 1994
1921 INIT_WORK(&dev->cmd_work, pn533_wq_cmd_complete); 1995 INIT_WORK(&dev->cmd_work, pn533_wq_cmd_complete);
1922 INIT_WORK(&dev->mi_work, pn533_wq_mi_recv); 1996 INIT_WORK(&dev->mi_work, pn533_wq_mi_recv);
1997 INIT_WORK(&dev->tg_work, pn533_wq_tg_get_data);
1923 dev->wq = alloc_workqueue("pn533", 1998 dev->wq = alloc_workqueue("pn533",
1924 WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM, 1999 WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM,
1925 1); 2000 1);