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.
Unified · Split
| @@ -84,6 +84,7 @@ · 83 unmodified lines | ||
| 84 | 84 | * @NFC_EVENT_SE_TRANSACTION: This event is sent when an application running on |
| 85 | 85 | * a specific SE notifies us about the end of a transaction. The parameter |
| 86 | 86 | * for this event is the application ID (AID). |
| 87 | + * @NFC_CMD_GET_SE: Dump all discovered secure elements from an NFC controller. | |
| 87 | 88 | */ |
| 88 | 89 | enum nfc_commands { |
| 89 | 90 | NFC_CMD_UNSPEC, |
| @@ -112,6 +113,7 @@ enum nfc_commands { · 22 unmodified lines | ||
| 112 | 113 | NFC_EVENT_SE_REMOVED, |
| 113 | 114 | NFC_EVENT_SE_CONNECTIVITY, |
| 114 | 115 | NFC_EVENT_SE_TRANSACTION, |
| 116 | + NFC_CMD_GET_SE, | |
| 115 | 117 | /* private: internal use only */ |
| 116 | 118 | __NFC_CMD_AFTER_LAST |
| 117 | 119 | }; |
| @@ -1191,6 +1191,91 @@ static int nfc_genl_disable_se(struct sk_buff *skb, struct genl_info *info) · 1190 unmodified lines | ||
| 1191 | 1191 | return rc; |
| 1192 | 1192 | } |
| 1193 | 1193 | |
| 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 | + | |
| 1194 | 1279 | static struct genl_ops nfc_genl_ops[] = { |
| 1195 | 1280 | { |
| 1196 | 1281 | .cmd = NFC_CMD_GET_DEVICE, |
| @@ -1265,6 +1350,12 @@ static struct genl_ops nfc_genl_ops[] = { · 68 unmodified lines | ||
| 1265 | 1350 | .doit = nfc_genl_disable_se, |
| 1266 | 1351 | .policy = nfc_genl_policy, |
| 1267 | 1352 | }, |
| 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 | + }, | |
| 1268 | 1359 | }; |
| 1269 | 1360 | |
| 1270 | 1361 | |