History

NFC: Add a GET_SE netlink API

In order to fetch the discovered secure elements from an NFC controller, we need to send a netlink command that will dump the list of available SEs from NFC.

Samuel Ortiz committed 13 years ago

Commit ac22ac41 parent 369f4d52 files · +93 −0Browse files

Unified · Split

2 files
  1. include/uapi/linux/nfc.h +2 −0
  2. net/nfc/netlink.c +91 −0
include/uapi/linux/nfc.h+2−0
@@ -84,6 +84,7 @@ · 83 unmodified lines
8484 * @NFC_EVENT_SE_TRANSACTION: This event is sent when an application running on
8585 * a specific SE notifies us about the end of a transaction. The parameter
8686 * for this event is the application ID (AID).
87+ * @NFC_CMD_GET_SE: Dump all discovered secure elements from an NFC controller.
8788 */
8889 enum nfc_commands {
8990 NFC_CMD_UNSPEC,
@@ -112,6 +113,7 @@ enum nfc_commands { · 22 unmodified lines
112113 NFC_EVENT_SE_REMOVED,
113114 NFC_EVENT_SE_CONNECTIVITY,
114115 NFC_EVENT_SE_TRANSACTION,
116+ NFC_CMD_GET_SE,
115117 /* private: internal use only */
116118 __NFC_CMD_AFTER_LAST
117119 };
net/nfc/netlink.c+91−0
@@ -1191,6 +1191,91 @@ static int nfc_genl_disable_se(struct sk_buff *skb, struct genl_info *info) · 1190 unmodified lines
11911191 return rc;
11921192 }
11931193
1194+static int nfc_genl_send_se(struct sk_buff *msg, struct nfc_dev *dev,
1195+ u32 portid, u32 seq,
1196+ struct netlink_callback *cb,
1197+ int flags)
1198+{
1199+ void *hdr;
1200+ struct nfc_se *se, *n;
1201+
1202+ list_for_each_entry_safe(se, n, &dev->secure_elements, list) {
1203+ hdr = genlmsg_put(msg, portid, seq, &nfc_genl_family, flags,
1204+ NFC_CMD_GET_SE);
1205+ if (!hdr)
1206+ goto nla_put_failure;
1207+
1208+ if (cb)
1209+ genl_dump_check_consistent(cb, hdr, &nfc_genl_family);
1210+
1211+ if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx) ||
1212+ nla_put_u32(msg, NFC_ATTR_SE_INDEX, se->idx) ||
1213+ nla_put_u8(msg, NFC_ATTR_SE_TYPE, se->type))
1214+ goto nla_put_failure;
1215+
1216+ if (genlmsg_end(msg, hdr) < 0)
1217+ goto nla_put_failure;
1218+ }
1219+
1220+ return 0;
1221+
1222+nla_put_failure:
1223+ genlmsg_cancel(msg, hdr);
1224+ return -EMSGSIZE;
1225+}
1226+
1227+static int nfc_genl_dump_ses(struct sk_buff *skb,
1228+ struct netlink_callback *cb)
1229+{
1230+ struct class_dev_iter *iter = (struct class_dev_iter *) cb->args[0];
1231+ struct nfc_dev *dev = (struct nfc_dev *) cb->args[1];
1232+ bool first_call = false;
1233+
1234+ if (!iter) {
1235+ first_call = true;
1236+ iter = kmalloc(sizeof(struct class_dev_iter), GFP_KERNEL);
1237+ if (!iter)
1238+ return -ENOMEM;
1239+ cb->args[0] = (long) iter;
1240+ }
1241+
1242+ mutex_lock(&nfc_devlist_mutex);
1243+
1244+ cb->seq = nfc_devlist_generation;
1245+
1246+ if (first_call) {
1247+ nfc_device_iter_init(iter);
1248+ dev = nfc_device_iter_next(iter);
1249+ }
1250+
1251+ while (dev) {
1252+ int rc;
1253+
1254+ rc = nfc_genl_send_se(skb, dev, NETLINK_CB(cb->skb).portid,
1255+ cb->nlh->nlmsg_seq, cb, NLM_F_MULTI);
1256+ if (rc < 0)
1257+ break;
1258+
1259+ dev = nfc_device_iter_next(iter);
1260+ }
1261+
1262+ mutex_unlock(&nfc_devlist_mutex);
1263+
1264+ cb->args[1] = (long) dev;
1265+
1266+ return skb->len;
1267+}
1268+
1269+static int nfc_genl_dump_ses_done(struct netlink_callback *cb)
1270+{
1271+ struct class_dev_iter *iter = (struct class_dev_iter *) cb->args[0];
1272+
1273+ nfc_device_iter_exit(iter);
1274+ kfree(iter);
1275+
1276+ return 0;
1277+}
1278+
11941279 static struct genl_ops nfc_genl_ops[] = {
11951280 {
11961281 .cmd = NFC_CMD_GET_DEVICE,
@@ -1265,6 +1350,12 @@ static struct genl_ops nfc_genl_ops[] = { · 68 unmodified lines
12651350 .doit = nfc_genl_disable_se,
12661351 .policy = nfc_genl_policy,
12671352 },
1353+ {
1354+ .cmd = NFC_CMD_GET_SE,
1355+ .dumpit = nfc_genl_dump_ses,
1356+ .done = nfc_genl_dump_ses_done,
1357+ .policy = nfc_genl_policy,
1358+ },
12681359 };
12691360
12701361