diff options
author | Eric Lapuyade <eric.lapuyade@linux.intel.com> | 2013-04-29 11:13:27 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2013-06-13 18:26:08 -0400 |
commit | 9674da8759df0d6c0d24e1ede6e2a1acdef91e3c (patch) | |
tree | 97363dfcf38f1e7c6bfb8a9abd76302c617eb705 /net/nfc/netlink.c | |
parent | 1095e69f47926db6f1350a9d6a38626521580e87 (diff) |
NFC: Add firmware upload netlink command
As several NFC chipsets can have their firmwares upgraded and
reflashed, this patchset adds a new netlink command to trigger
that the driver loads or flashes a new firmware. This will allows
userspace triggered firmware upgrade through netlink.
The firmware name or hint is passed as a parameter, and the driver
will eventually fetch the firmware binary through the request_firmware
API.
The cmd can only be executed when the nfc dev is not in use. Actual
firmware loading/flashing is an asynchronous operation. Result of the
operation shall send a new event up to user space through the nfc dev
multicast socket. During operation, the nfc dev is not openable and
thus not usable.
Signed-off-by: Eric Lapuyade <eric.lapuyade@intel.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'net/nfc/netlink.c')
-rw-r--r-- | net/nfc/netlink.c | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index f0c4d61f37c0..1deadad9a285 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c | |||
@@ -56,6 +56,8 @@ static const struct nla_policy nfc_genl_policy[NFC_ATTR_MAX + 1] = { | |||
56 | [NFC_ATTR_LLC_PARAM_RW] = { .type = NLA_U8 }, | 56 | [NFC_ATTR_LLC_PARAM_RW] = { .type = NLA_U8 }, |
57 | [NFC_ATTR_LLC_PARAM_MIUX] = { .type = NLA_U16 }, | 57 | [NFC_ATTR_LLC_PARAM_MIUX] = { .type = NLA_U16 }, |
58 | [NFC_ATTR_LLC_SDP] = { .type = NLA_NESTED }, | 58 | [NFC_ATTR_LLC_SDP] = { .type = NLA_NESTED }, |
59 | [NFC_ATTR_FIRMWARE_NAME] = { .type = NLA_STRING, | ||
60 | .len = NFC_FIRMWARE_NAME_MAXSIZE }, | ||
59 | }; | 61 | }; |
60 | 62 | ||
61 | static const struct nla_policy nfc_sdp_genl_policy[NFC_SDP_ATTR_MAX + 1] = { | 63 | static const struct nla_policy nfc_sdp_genl_policy[NFC_SDP_ATTR_MAX + 1] = { |
@@ -1025,6 +1027,62 @@ exit: | |||
1025 | return rc; | 1027 | return rc; |
1026 | } | 1028 | } |
1027 | 1029 | ||
1030 | static int nfc_genl_fw_upload(struct sk_buff *skb, struct genl_info *info) | ||
1031 | { | ||
1032 | struct nfc_dev *dev; | ||
1033 | int rc; | ||
1034 | u32 idx; | ||
1035 | char firmware_name[NFC_FIRMWARE_NAME_MAXSIZE + 1]; | ||
1036 | |||
1037 | if (!info->attrs[NFC_ATTR_DEVICE_INDEX]) | ||
1038 | return -EINVAL; | ||
1039 | |||
1040 | idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); | ||
1041 | |||
1042 | dev = nfc_get_device(idx); | ||
1043 | if (!dev) | ||
1044 | return -ENODEV; | ||
1045 | |||
1046 | nla_strlcpy(firmware_name, info->attrs[NFC_ATTR_FIRMWARE_NAME], | ||
1047 | sizeof(firmware_name)); | ||
1048 | |||
1049 | rc = nfc_fw_upload(dev, firmware_name); | ||
1050 | |||
1051 | nfc_put_device(dev); | ||
1052 | return rc; | ||
1053 | } | ||
1054 | |||
1055 | int nfc_genl_fw_upload_done(struct nfc_dev *dev, const char *firmware_name) | ||
1056 | { | ||
1057 | struct sk_buff *msg; | ||
1058 | void *hdr; | ||
1059 | |||
1060 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
1061 | if (!msg) | ||
1062 | return -ENOMEM; | ||
1063 | |||
1064 | hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, | ||
1065 | NFC_CMD_FW_UPLOAD); | ||
1066 | if (!hdr) | ||
1067 | goto free_msg; | ||
1068 | |||
1069 | if (nla_put_string(msg, NFC_ATTR_FIRMWARE_NAME, firmware_name) || | ||
1070 | nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx)) | ||
1071 | goto nla_put_failure; | ||
1072 | |||
1073 | genlmsg_end(msg, hdr); | ||
1074 | |||
1075 | genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL); | ||
1076 | |||
1077 | return 0; | ||
1078 | |||
1079 | nla_put_failure: | ||
1080 | genlmsg_cancel(msg, hdr); | ||
1081 | free_msg: | ||
1082 | nlmsg_free(msg); | ||
1083 | return -EMSGSIZE; | ||
1084 | } | ||
1085 | |||
1028 | static struct genl_ops nfc_genl_ops[] = { | 1086 | static struct genl_ops nfc_genl_ops[] = { |
1029 | { | 1087 | { |
1030 | .cmd = NFC_CMD_GET_DEVICE, | 1088 | .cmd = NFC_CMD_GET_DEVICE, |
@@ -1084,6 +1142,11 @@ static struct genl_ops nfc_genl_ops[] = { | |||
1084 | .doit = nfc_genl_llc_sdreq, | 1142 | .doit = nfc_genl_llc_sdreq, |
1085 | .policy = nfc_genl_policy, | 1143 | .policy = nfc_genl_policy, |
1086 | }, | 1144 | }, |
1145 | { | ||
1146 | .cmd = NFC_CMD_FW_UPLOAD, | ||
1147 | .doit = nfc_genl_fw_upload, | ||
1148 | .policy = nfc_genl_policy, | ||
1149 | }, | ||
1087 | }; | 1150 | }; |
1088 | 1151 | ||
1089 | 1152 | ||