aboutsummaryrefslogtreecommitdiffstats
path: root/net/nfc/netlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/nfc/netlink.c')
-rw-r--r--net/nfc/netlink.c157
1 files changed, 155 insertions, 2 deletions
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
index c1b5285cbde7..3568ae16786d 100644
--- a/net/nfc/netlink.c
+++ b/net/nfc/netlink.c
@@ -29,6 +29,8 @@
29 29
30#include "nfc.h" 30#include "nfc.h"
31 31
32#include "llcp/llcp.h"
33
32static struct genl_multicast_group nfc_genl_event_mcgrp = { 34static struct genl_multicast_group nfc_genl_event_mcgrp = {
33 .name = NFC_GENL_MCAST_EVENT_NAME, 35 .name = NFC_GENL_MCAST_EVENT_NAME,
34}; 36};
@@ -364,7 +366,8 @@ static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev,
364 if (nla_put_string(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev)) || 366 if (nla_put_string(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev)) ||
365 nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx) || 367 nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx) ||
366 nla_put_u32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols) || 368 nla_put_u32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols) ||
367 nla_put_u8(msg, NFC_ATTR_DEVICE_POWERED, dev->dev_up)) 369 nla_put_u8(msg, NFC_ATTR_DEVICE_POWERED, dev->dev_up) ||
370 nla_put_u8(msg, NFC_ATTR_RF_MODE, dev->rf_mode))
368 goto nla_put_failure; 371 goto nla_put_failure;
369 372
370 return genlmsg_end(msg, hdr); 373 return genlmsg_end(msg, hdr);
@@ -590,7 +593,7 @@ static int nfc_genl_start_poll(struct sk_buff *skb, struct genl_info *info)
590 if (!info->attrs[NFC_ATTR_DEVICE_INDEX] || 593 if (!info->attrs[NFC_ATTR_DEVICE_INDEX] ||
591 ((!info->attrs[NFC_ATTR_IM_PROTOCOLS] && 594 ((!info->attrs[NFC_ATTR_IM_PROTOCOLS] &&
592 !info->attrs[NFC_ATTR_PROTOCOLS]) && 595 !info->attrs[NFC_ATTR_PROTOCOLS]) &&
593 !info->attrs[NFC_ATTR_TM_PROTOCOLS])) 596 !info->attrs[NFC_ATTR_TM_PROTOCOLS]))
594 return -EINVAL; 597 return -EINVAL;
595 598
596 idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); 599 idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
@@ -715,6 +718,146 @@ static int nfc_genl_dep_link_down(struct sk_buff *skb, struct genl_info *info)
715 return rc; 718 return rc;
716} 719}
717 720
721static int nfc_genl_send_params(struct sk_buff *msg,
722 struct nfc_llcp_local *local,
723 u32 portid, u32 seq)
724{
725 void *hdr;
726
727 hdr = genlmsg_put(msg, portid, seq, &nfc_genl_family, 0,
728 NFC_CMD_LLC_GET_PARAMS);
729 if (!hdr)
730 return -EMSGSIZE;
731
732 if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, local->dev->idx) ||
733 nla_put_u8(msg, NFC_ATTR_LLC_PARAM_LTO, local->lto) ||
734 nla_put_u8(msg, NFC_ATTR_LLC_PARAM_RW, local->rw) ||
735 nla_put_u16(msg, NFC_ATTR_LLC_PARAM_MIUX, be16_to_cpu(local->miux)))
736 goto nla_put_failure;
737
738 return genlmsg_end(msg, hdr);
739
740nla_put_failure:
741
742 genlmsg_cancel(msg, hdr);
743 return -EMSGSIZE;
744}
745
746static int nfc_genl_llc_get_params(struct sk_buff *skb, struct genl_info *info)
747{
748 struct nfc_dev *dev;
749 struct nfc_llcp_local *local;
750 int rc = 0;
751 struct sk_buff *msg = NULL;
752 u32 idx;
753
754 if (!info->attrs[NFC_ATTR_DEVICE_INDEX])
755 return -EINVAL;
756
757 idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
758
759 dev = nfc_get_device(idx);
760 if (!dev)
761 return -ENODEV;
762
763 device_lock(&dev->dev);
764
765 local = nfc_llcp_find_local(dev);
766 if (!local) {
767 rc = -ENODEV;
768 goto exit;
769 }
770
771 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
772 if (!msg) {
773 rc = -ENOMEM;
774 goto exit;
775 }
776
777 rc = nfc_genl_send_params(msg, local, info->snd_portid, info->snd_seq);
778
779exit:
780 device_unlock(&dev->dev);
781
782 nfc_put_device(dev);
783
784 if (rc < 0) {
785 if (msg)
786 nlmsg_free(msg);
787
788 return rc;
789 }
790
791 return genlmsg_reply(msg, info);
792}
793
794static int nfc_genl_llc_set_params(struct sk_buff *skb, struct genl_info *info)
795{
796 struct nfc_dev *dev;
797 struct nfc_llcp_local *local;
798 u8 rw = 0;
799 u16 miux = 0;
800 u32 idx;
801 int rc = 0;
802
803 if (!info->attrs[NFC_ATTR_DEVICE_INDEX] ||
804 (!info->attrs[NFC_ATTR_LLC_PARAM_LTO] &&
805 !info->attrs[NFC_ATTR_LLC_PARAM_RW] &&
806 !info->attrs[NFC_ATTR_LLC_PARAM_MIUX]))
807 return -EINVAL;
808
809 if (info->attrs[NFC_ATTR_LLC_PARAM_RW]) {
810 rw = nla_get_u8(info->attrs[NFC_ATTR_LLC_PARAM_RW]);
811
812 if (rw > LLCP_MAX_RW)
813 return -EINVAL;
814 }
815
816 if (info->attrs[NFC_ATTR_LLC_PARAM_MIUX]) {
817 miux = nla_get_u16(info->attrs[NFC_ATTR_LLC_PARAM_MIUX]);
818
819 if (miux > LLCP_MAX_MIUX)
820 return -EINVAL;
821 }
822
823 idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
824
825 dev = nfc_get_device(idx);
826 if (!dev)
827 return -ENODEV;
828
829 device_lock(&dev->dev);
830
831 local = nfc_llcp_find_local(dev);
832 if (!local) {
833 nfc_put_device(dev);
834 rc = -ENODEV;
835 goto exit;
836 }
837
838 if (info->attrs[NFC_ATTR_LLC_PARAM_LTO]) {
839 if (dev->dep_link_up) {
840 rc = -EINPROGRESS;
841 goto exit;
842 }
843
844 local->lto = nla_get_u8(info->attrs[NFC_ATTR_LLC_PARAM_LTO]);
845 }
846
847 if (info->attrs[NFC_ATTR_LLC_PARAM_RW])
848 local->rw = rw;
849
850 if (info->attrs[NFC_ATTR_LLC_PARAM_MIUX])
851 local->miux = cpu_to_be16(miux);
852
853exit:
854 device_unlock(&dev->dev);
855
856 nfc_put_device(dev);
857
858 return rc;
859}
860
718static struct genl_ops nfc_genl_ops[] = { 861static struct genl_ops nfc_genl_ops[] = {
719 { 862 {
720 .cmd = NFC_CMD_GET_DEVICE, 863 .cmd = NFC_CMD_GET_DEVICE,
@@ -759,6 +902,16 @@ static struct genl_ops nfc_genl_ops[] = {
759 .done = nfc_genl_dump_targets_done, 902 .done = nfc_genl_dump_targets_done,
760 .policy = nfc_genl_policy, 903 .policy = nfc_genl_policy,
761 }, 904 },
905 {
906 .cmd = NFC_CMD_LLC_GET_PARAMS,
907 .doit = nfc_genl_llc_get_params,
908 .policy = nfc_genl_policy,
909 },
910 {
911 .cmd = NFC_CMD_LLC_SET_PARAMS,
912 .doit = nfc_genl_llc_set_params,
913 .policy = nfc_genl_policy,
914 },
762}; 915};
763 916
764 917