aboutsummaryrefslogtreecommitdiffstats
path: root/net/nfc
diff options
context:
space:
mode:
authorThierry Escande <thierry.escande@linux.intel.com>2012-10-17 08:43:39 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2012-10-28 19:25:11 -0400
commit52feb444a90304eb13c03115bb9758101dbb9254 (patch)
tree6cf939501bc6c51d46649a51d8cd45c3e9dea015 /net/nfc
parentf31652a58bee6ef145c066c8d0ae6d0b11dca1e8 (diff)
NFC: Extend netlink interface for LTO, RW, and MIUX parameters support
NFC_CMD_LLC_GET_PARAMS: request LTO, RW, and MIUX parameters for a device NFC_CMD_LLC_SET_PARAMS: set one or more of LTO, RW, and MIUX parameters for a device. LTO must be set before the link is up otherwise -EINPROGRESS is returned. RW and MIUX can be set at anytime and will be passed in subsequent CONNECT and CC messages. If one of the passed parameters is wrong none is set and -EINVAL is returned. Signed-off-by: Thierry Escande <thierry.escande@linux.intel.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'net/nfc')
-rw-r--r--net/nfc/llcp/commands.c18
-rw-r--r--net/nfc/llcp/llcp.c14
-rw-r--r--net/nfc/llcp/llcp.h3
-rw-r--r--net/nfc/netlink.c152
-rw-r--r--net/nfc/nfc.h6
5 files changed, 174 insertions, 19 deletions
diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c
index 79415353cc28..ed2d17312d61 100644
--- a/net/nfc/llcp/commands.c
+++ b/net/nfc/llcp/commands.c
@@ -316,8 +316,7 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock)
316 struct sk_buff *skb; 316 struct sk_buff *skb;
317 u8 *service_name_tlv = NULL, service_name_tlv_length; 317 u8 *service_name_tlv = NULL, service_name_tlv_length;
318 u8 *miux_tlv = NULL, miux_tlv_length; 318 u8 *miux_tlv = NULL, miux_tlv_length;
319 u8 *rw_tlv = NULL, rw_tlv_length, rw; 319 u8 *rw_tlv = NULL, rw_tlv_length;
320 __be16 miux;
321 int err; 320 int err;
322 u16 size = 0; 321 u16 size = 0;
323 322
@@ -335,13 +334,11 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock)
335 size += service_name_tlv_length; 334 size += service_name_tlv_length;
336 } 335 }
337 336
338 miux = cpu_to_be16(LLCP_MAX_MIUX); 337 miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&local->miux, 0,
339 miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0,
340 &miux_tlv_length); 338 &miux_tlv_length);
341 size += miux_tlv_length; 339 size += miux_tlv_length;
342 340
343 rw = LLCP_MAX_RW; 341 rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &local->rw, 0, &rw_tlv_length);
344 rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &rw, 0, &rw_tlv_length);
345 size += rw_tlv_length; 342 size += rw_tlv_length;
346 343
347 pr_debug("SKB size %d SN length %zu\n", size, sock->service_name_len); 344 pr_debug("SKB size %d SN length %zu\n", size, sock->service_name_len);
@@ -378,8 +375,7 @@ int nfc_llcp_send_cc(struct nfc_llcp_sock *sock)
378 struct nfc_llcp_local *local; 375 struct nfc_llcp_local *local;
379 struct sk_buff *skb; 376 struct sk_buff *skb;
380 u8 *miux_tlv = NULL, miux_tlv_length; 377 u8 *miux_tlv = NULL, miux_tlv_length;
381 u8 *rw_tlv = NULL, rw_tlv_length, rw; 378 u8 *rw_tlv = NULL, rw_tlv_length;
382 __be16 miux;
383 int err; 379 int err;
384 u16 size = 0; 380 u16 size = 0;
385 381
@@ -389,13 +385,11 @@ int nfc_llcp_send_cc(struct nfc_llcp_sock *sock)
389 if (local == NULL) 385 if (local == NULL)
390 return -ENODEV; 386 return -ENODEV;
391 387
392 miux = cpu_to_be16(LLCP_MAX_MIUX); 388 miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&local->miux, 0,
393 miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0,
394 &miux_tlv_length); 389 &miux_tlv_length);
395 size += miux_tlv_length; 390 size += miux_tlv_length;
396 391
397 rw = LLCP_MAX_RW; 392 rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &local->rw, 0, &rw_tlv_length);
398 rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &rw, 0, &rw_tlv_length);
399 size += rw_tlv_length; 393 size += rw_tlv_length;
400 394
401 skb = llcp_allocate_pdu(sock, LLCP_PDU_CC, size); 395 skb = llcp_allocate_pdu(sock, LLCP_PDU_CC, size);
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c
index 2e23bd348ebd..f6804532047a 100644
--- a/net/nfc/llcp/llcp.c
+++ b/net/nfc/llcp/llcp.c
@@ -467,10 +467,9 @@ static u8 nfc_llcp_reserve_sdp_ssap(struct nfc_llcp_local *local)
467static int nfc_llcp_build_gb(struct nfc_llcp_local *local) 467static int nfc_llcp_build_gb(struct nfc_llcp_local *local)
468{ 468{
469 u8 *gb_cur, *version_tlv, version, version_length; 469 u8 *gb_cur, *version_tlv, version, version_length;
470 u8 *lto_tlv, lto, lto_length; 470 u8 *lto_tlv, lto_length;
471 u8 *wks_tlv, wks_length; 471 u8 *wks_tlv, wks_length;
472 u8 *miux_tlv, miux_length; 472 u8 *miux_tlv, miux_length;
473 __be16 miux;
474 u8 gb_len = 0; 473 u8 gb_len = 0;
475 int ret = 0; 474 int ret = 0;
476 475
@@ -479,9 +478,7 @@ static int nfc_llcp_build_gb(struct nfc_llcp_local *local)
479 1, &version_length); 478 1, &version_length);
480 gb_len += version_length; 479 gb_len += version_length;
481 480
482 /* 1500 ms */ 481 lto_tlv = nfc_llcp_build_tlv(LLCP_TLV_LTO, &local->lto, 1, &lto_length);
483 lto = 150;
484 lto_tlv = nfc_llcp_build_tlv(LLCP_TLV_LTO, &lto, 1, &lto_length);
485 gb_len += lto_length; 482 gb_len += lto_length;
486 483
487 pr_debug("Local wks 0x%lx\n", local->local_wks); 484 pr_debug("Local wks 0x%lx\n", local->local_wks);
@@ -489,8 +486,7 @@ static int nfc_llcp_build_gb(struct nfc_llcp_local *local)
489 &wks_length); 486 &wks_length);
490 gb_len += wks_length; 487 gb_len += wks_length;
491 488
492 miux = cpu_to_be16(LLCP_MAX_MIUX); 489 miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&local->miux, 0,
493 miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0,
494 &miux_length); 490 &miux_length);
495 gb_len += miux_length; 491 gb_len += miux_length;
496 492
@@ -1383,6 +1379,10 @@ int nfc_llcp_register_device(struct nfc_dev *ndev)
1383 rwlock_init(&local->connecting_sockets.lock); 1379 rwlock_init(&local->connecting_sockets.lock);
1384 rwlock_init(&local->raw_sockets.lock); 1380 rwlock_init(&local->raw_sockets.lock);
1385 1381
1382 local->lto = 150; /* 1500 ms */
1383 local->rw = LLCP_MAX_RW;
1384 local->miux = cpu_to_be16(LLCP_MAX_MIUX);
1385
1386 nfc_llcp_build_gb(local); 1386 nfc_llcp_build_gb(local);
1387 1387
1388 local->remote_miu = LLCP_DEFAULT_MIU; 1388 local->remote_miu = LLCP_DEFAULT_MIU;
diff --git a/net/nfc/llcp/llcp.h b/net/nfc/llcp/llcp.h
index 276da3a6a589..0d62366f8cc3 100644
--- a/net/nfc/llcp/llcp.h
+++ b/net/nfc/llcp/llcp.h
@@ -64,6 +64,9 @@ struct nfc_llcp_local {
64 u32 target_idx; 64 u32 target_idx;
65 u8 rf_mode; 65 u8 rf_mode;
66 u8 comm_mode; 66 u8 comm_mode;
67 u8 lto;
68 u8 rw;
69 __be16 miux;
67 unsigned long local_wks; /* Well known services */ 70 unsigned long local_wks; /* Well known services */
68 unsigned long local_sdp; /* Local services */ 71 unsigned long local_sdp; /* Local services */
69 unsigned long local_sap; /* Local SAPs, not available for discovery */ 72 unsigned long local_sap; /* Local SAPs, not available for discovery */
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
index 614cfd0470b7..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};
@@ -716,6 +718,146 @@ static int nfc_genl_dep_link_down(struct sk_buff *skb, struct genl_info *info)
716 return rc; 718 return rc;
717} 719}
718 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
719static struct genl_ops nfc_genl_ops[] = { 861static struct genl_ops nfc_genl_ops[] = {
720 { 862 {
721 .cmd = NFC_CMD_GET_DEVICE, 863 .cmd = NFC_CMD_GET_DEVICE,
@@ -760,6 +902,16 @@ static struct genl_ops nfc_genl_ops[] = {
760 .done = nfc_genl_dump_targets_done, 902 .done = nfc_genl_dump_targets_done,
761 .policy = nfc_genl_policy, 903 .policy = nfc_genl_policy,
762 }, 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 },
763}; 915};
764 916
765 917
diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h
index c5e42b79a418..87d914d2876a 100644
--- a/net/nfc/nfc.h
+++ b/net/nfc/nfc.h
@@ -56,6 +56,7 @@ void nfc_llcp_unregister_device(struct nfc_dev *dev);
56int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len); 56int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len);
57u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len); 57u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len);
58int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb); 58int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb);
59struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev);
59int __init nfc_llcp_init(void); 60int __init nfc_llcp_init(void);
60void nfc_llcp_exit(void); 61void nfc_llcp_exit(void);
61 62
@@ -97,6 +98,11 @@ static inline int nfc_llcp_data_received(struct nfc_dev *dev,
97 return 0; 98 return 0;
98} 99}
99 100
101static inline struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev)
102{
103 return NULL;
104}
105
100static inline int nfc_llcp_init(void) 106static inline int nfc_llcp_init(void)
101{ 107{
102 return 0; 108 return 0;