diff options
Diffstat (limited to 'net/nfc/netlink.c')
-rw-r--r-- | net/nfc/netlink.c | 157 |
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 | |||
32 | static struct genl_multicast_group nfc_genl_event_mcgrp = { | 34 | static 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 | ||
721 | static 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 | |||
740 | nla_put_failure: | ||
741 | |||
742 | genlmsg_cancel(msg, hdr); | ||
743 | return -EMSGSIZE; | ||
744 | } | ||
745 | |||
746 | static 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 | |||
779 | exit: | ||
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 | |||
794 | static 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 | |||
853 | exit: | ||
854 | device_unlock(&dev->dev); | ||
855 | |||
856 | nfc_put_device(dev); | ||
857 | |||
858 | return rc; | ||
859 | } | ||
860 | |||
718 | static struct genl_ops nfc_genl_ops[] = { | 861 | static 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 | ||