aboutsummaryrefslogtreecommitdiffstats
path: root/net/nfc
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2013-04-24 10:54:20 -0400
committerJohn W. Linville <linville@tuxdriver.com>2013-04-24 10:54:20 -0400
commit6ed0e321a0aef14a894e26658108bf7e895c36a6 (patch)
treef49428d68ebcb1beb757296ea1559079210babbe /net/nfc
parent3dec2246c2ff11beb24ca1950f074b2bcbc85953 (diff)
parentb006ed545cbadf1ebd4683719554742d20dbcede (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Diffstat (limited to 'net/nfc')
-rw-r--r--net/nfc/core.c43
-rw-r--r--net/nfc/llcp/commands.c30
-rw-r--r--net/nfc/llcp/llcp.c127
-rw-r--r--net/nfc/llcp/llcp.h5
-rw-r--r--net/nfc/llcp/sock.c43
5 files changed, 194 insertions, 54 deletions
diff --git a/net/nfc/core.c b/net/nfc/core.c
index 6ceee8e181ca..40d2527693da 100644
--- a/net/nfc/core.c
+++ b/net/nfc/core.c
@@ -27,6 +27,7 @@
27#include <linux/kernel.h> 27#include <linux/kernel.h>
28#include <linux/module.h> 28#include <linux/module.h>
29#include <linux/slab.h> 29#include <linux/slab.h>
30#include <linux/rfkill.h>
30#include <linux/nfc.h> 31#include <linux/nfc.h>
31 32
32#include <net/genetlink.h> 33#include <net/genetlink.h>
@@ -58,6 +59,11 @@ int nfc_dev_up(struct nfc_dev *dev)
58 59
59 device_lock(&dev->dev); 60 device_lock(&dev->dev);
60 61
62 if (dev->rfkill && rfkill_blocked(dev->rfkill)) {
63 rc = -ERFKILL;
64 goto error;
65 }
66
61 if (!device_is_registered(&dev->dev)) { 67 if (!device_is_registered(&dev->dev)) {
62 rc = -ENODEV; 68 rc = -ENODEV;
63 goto error; 69 goto error;
@@ -117,6 +123,24 @@ error:
117 return rc; 123 return rc;
118} 124}
119 125
126static int nfc_rfkill_set_block(void *data, bool blocked)
127{
128 struct nfc_dev *dev = data;
129
130 pr_debug("%s blocked %d", dev_name(&dev->dev), blocked);
131
132 if (!blocked)
133 return 0;
134
135 nfc_dev_down(dev);
136
137 return 0;
138}
139
140static const struct rfkill_ops nfc_rfkill_ops = {
141 .set_block = nfc_rfkill_set_block,
142};
143
120/** 144/**
121 * nfc_start_poll - start polling for nfc targets 145 * nfc_start_poll - start polling for nfc targets
122 * 146 *
@@ -143,6 +167,11 @@ int nfc_start_poll(struct nfc_dev *dev, u32 im_protocols, u32 tm_protocols)
143 goto error; 167 goto error;
144 } 168 }
145 169
170 if (!dev->dev_up) {
171 rc = -ENODEV;
172 goto error;
173 }
174
146 if (dev->polling) { 175 if (dev->polling) {
147 rc = -EBUSY; 176 rc = -EBUSY;
148 goto error; 177 goto error;
@@ -835,6 +864,15 @@ int nfc_register_device(struct nfc_dev *dev)
835 pr_debug("The userspace won't be notified that the device %s was added\n", 864 pr_debug("The userspace won't be notified that the device %s was added\n",
836 dev_name(&dev->dev)); 865 dev_name(&dev->dev));
837 866
867 dev->rfkill = rfkill_alloc(dev_name(&dev->dev), &dev->dev,
868 RFKILL_TYPE_NFC, &nfc_rfkill_ops, dev);
869 if (dev->rfkill) {
870 if (rfkill_register(dev->rfkill) < 0) {
871 rfkill_destroy(dev->rfkill);
872 dev->rfkill = NULL;
873 }
874 }
875
838 return 0; 876 return 0;
839} 877}
840EXPORT_SYMBOL(nfc_register_device); 878EXPORT_SYMBOL(nfc_register_device);
@@ -852,6 +890,11 @@ void nfc_unregister_device(struct nfc_dev *dev)
852 890
853 id = dev->idx; 891 id = dev->idx;
854 892
893 if (dev->rfkill) {
894 rfkill_unregister(dev->rfkill);
895 rfkill_destroy(dev->rfkill);
896 }
897
855 if (dev->ops->check_presence) { 898 if (dev->ops->check_presence) {
856 device_lock(&dev->dev); 899 device_lock(&dev->dev);
857 dev->shutting_down = true; 900 dev->shutting_down = true;
diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c
index b75a9b3f9e89..094f7e27e910 100644
--- a/net/nfc/llcp/commands.c
+++ b/net/nfc/llcp/commands.c
@@ -420,7 +420,8 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock)
420 } 420 }
421 421
422 /* If the socket parameters are not set, use the local ones */ 422 /* If the socket parameters are not set, use the local ones */
423 miux = sock->miux > LLCP_MAX_MIUX ? local->miux : sock->miux; 423 miux = be16_to_cpu(sock->miux) > LLCP_MAX_MIUX ?
424 local->miux : sock->miux;
424 rw = sock->rw > LLCP_MAX_RW ? local->rw : sock->rw; 425 rw = sock->rw > LLCP_MAX_RW ? local->rw : sock->rw;
425 426
426 miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0, 427 miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0,
@@ -475,7 +476,8 @@ int nfc_llcp_send_cc(struct nfc_llcp_sock *sock)
475 return -ENODEV; 476 return -ENODEV;
476 477
477 /* If the socket parameters are not set, use the local ones */ 478 /* If the socket parameters are not set, use the local ones */
478 miux = sock->miux > LLCP_MAX_MIUX ? local->miux : sock->miux; 479 miux = be16_to_cpu(sock->miux) > LLCP_MAX_MIUX ?
480 local->miux : sock->miux;
479 rw = sock->rw > LLCP_MAX_RW ? local->rw : sock->rw; 481 rw = sock->rw > LLCP_MAX_RW ? local->rw : sock->rw;
480 482
481 miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0, 483 miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0,
@@ -656,6 +658,7 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
656 struct nfc_llcp_local *local; 658 struct nfc_llcp_local *local;
657 size_t frag_len = 0, remaining_len; 659 size_t frag_len = 0, remaining_len;
658 u8 *msg_data, *msg_ptr; 660 u8 *msg_data, *msg_ptr;
661 u16 remote_miu;
659 662
660 pr_debug("Send I frame len %zd\n", len); 663 pr_debug("Send I frame len %zd\n", len);
661 664
@@ -692,9 +695,11 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
692 remaining_len = len; 695 remaining_len = len;
693 msg_ptr = msg_data; 696 msg_ptr = msg_data;
694 697
695 while (remaining_len > 0) { 698 do {
699 remote_miu = sock->remote_miu > LLCP_MAX_MIU ?
700 local->remote_miu : sock->remote_miu;
696 701
697 frag_len = min_t(size_t, sock->remote_miu, remaining_len); 702 frag_len = min_t(size_t, remote_miu, remaining_len);
698 703
699 pr_debug("Fragment %zd bytes remaining %zd", 704 pr_debug("Fragment %zd bytes remaining %zd",
700 frag_len, remaining_len); 705 frag_len, remaining_len);
@@ -706,7 +711,8 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
706 711
707 skb_put(pdu, LLCP_SEQUENCE_SIZE); 712 skb_put(pdu, LLCP_SEQUENCE_SIZE);
708 713
709 memcpy(skb_put(pdu, frag_len), msg_ptr, frag_len); 714 if (likely(frag_len > 0))
715 memcpy(skb_put(pdu, frag_len), msg_ptr, frag_len);
710 716
711 skb_queue_tail(&sock->tx_queue, pdu); 717 skb_queue_tail(&sock->tx_queue, pdu);
712 718
@@ -718,7 +724,7 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
718 724
719 remaining_len -= frag_len; 725 remaining_len -= frag_len;
720 msg_ptr += frag_len; 726 msg_ptr += frag_len;
721 } 727 } while (remaining_len > 0);
722 728
723 kfree(msg_data); 729 kfree(msg_data);
724 730
@@ -732,6 +738,7 @@ int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap,
732 struct nfc_llcp_local *local; 738 struct nfc_llcp_local *local;
733 size_t frag_len = 0, remaining_len; 739 size_t frag_len = 0, remaining_len;
734 u8 *msg_ptr, *msg_data; 740 u8 *msg_ptr, *msg_data;
741 u16 remote_miu;
735 int err; 742 int err;
736 743
737 pr_debug("Send UI frame len %zd\n", len); 744 pr_debug("Send UI frame len %zd\n", len);
@@ -752,9 +759,11 @@ int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap,
752 remaining_len = len; 759 remaining_len = len;
753 msg_ptr = msg_data; 760 msg_ptr = msg_data;
754 761
755 while (remaining_len > 0) { 762 do {
763 remote_miu = sock->remote_miu > LLCP_MAX_MIU ?
764 local->remote_miu : sock->remote_miu;
756 765
757 frag_len = min_t(size_t, sock->remote_miu, remaining_len); 766 frag_len = min_t(size_t, remote_miu, remaining_len);
758 767
759 pr_debug("Fragment %zd bytes remaining %zd", 768 pr_debug("Fragment %zd bytes remaining %zd",
760 frag_len, remaining_len); 769 frag_len, remaining_len);
@@ -768,14 +777,15 @@ int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap,
768 777
769 pdu = llcp_add_header(pdu, dsap, ssap, LLCP_PDU_UI); 778 pdu = llcp_add_header(pdu, dsap, ssap, LLCP_PDU_UI);
770 779
771 memcpy(skb_put(pdu, frag_len), msg_ptr, frag_len); 780 if (likely(frag_len > 0))
781 memcpy(skb_put(pdu, frag_len), msg_ptr, frag_len);
772 782
773 /* No need to check for the peer RW for UI frames */ 783 /* No need to check for the peer RW for UI frames */
774 skb_queue_tail(&local->tx_queue, pdu); 784 skb_queue_tail(&local->tx_queue, pdu);
775 785
776 remaining_len -= frag_len; 786 remaining_len -= frag_len;
777 msg_ptr += frag_len; 787 msg_ptr += frag_len;
778 } 788 } while (remaining_len > 0);
779 789
780 kfree(msg_data); 790 kfree(msg_data);
781 791
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c
index 7de0368aff0c..9e483c8e52f8 100644
--- a/net/nfc/llcp/llcp.c
+++ b/net/nfc/llcp/llcp.c
@@ -31,6 +31,8 @@ static u8 llcp_magic[3] = {0x46, 0x66, 0x6d};
31 31
32static struct list_head llcp_devices; 32static struct list_head llcp_devices;
33 33
34static void nfc_llcp_rx_skb(struct nfc_llcp_local *local, struct sk_buff *skb);
35
34void nfc_llcp_sock_link(struct llcp_sock_list *l, struct sock *sk) 36void nfc_llcp_sock_link(struct llcp_sock_list *l, struct sock *sk)
35{ 37{
36 write_lock(&l->lock); 38 write_lock(&l->lock);
@@ -45,6 +47,12 @@ void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *sk)
45 write_unlock(&l->lock); 47 write_unlock(&l->lock);
46} 48}
47 49
50void nfc_llcp_socket_remote_param_init(struct nfc_llcp_sock *sock)
51{
52 sock->remote_rw = LLCP_DEFAULT_RW;
53 sock->remote_miu = LLCP_MAX_MIU + 1;
54}
55
48static void nfc_llcp_socket_purge(struct nfc_llcp_sock *sock) 56static void nfc_llcp_socket_purge(struct nfc_llcp_sock *sock)
49{ 57{
50 struct nfc_llcp_local *local = sock->local; 58 struct nfc_llcp_local *local = sock->local;
@@ -68,7 +76,7 @@ static void nfc_llcp_socket_purge(struct nfc_llcp_sock *sock)
68 } 76 }
69} 77}
70 78
71static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen, 79static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool device,
72 int err) 80 int err)
73{ 81{
74 struct sock *sk; 82 struct sock *sk;
@@ -108,21 +116,6 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen,
108 116
109 bh_unlock_sock(accept_sk); 117 bh_unlock_sock(accept_sk);
110 } 118 }
111
112 if (listen == true) {
113 bh_unlock_sock(sk);
114 continue;
115 }
116 }
117
118 /*
119 * If we have a connection less socket bound, we keep it alive
120 * if the device is still present.
121 */
122 if (sk->sk_state == LLCP_BOUND && sk->sk_type == SOCK_DGRAM &&
123 listen == true) {
124 bh_unlock_sock(sk);
125 continue;
126 } 119 }
127 120
128 if (err) 121 if (err)
@@ -137,11 +130,8 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen,
137 130
138 write_unlock(&local->sockets.lock); 131 write_unlock(&local->sockets.lock);
139 132
140 /* 133 /* If we still have a device, we keep the RAW sockets alive */
141 * If we want to keep the listening sockets alive, 134 if (device == true)
142 * we don't touch the RAW ones.
143 */
144 if (listen == true)
145 return; 135 return;
146 136
147 write_lock(&local->raw_sockets.lock); 137 write_lock(&local->raw_sockets.lock);
@@ -173,9 +163,9 @@ struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local)
173 return local; 163 return local;
174} 164}
175 165
176static void local_cleanup(struct nfc_llcp_local *local, bool listen) 166static void local_cleanup(struct nfc_llcp_local *local)
177{ 167{
178 nfc_llcp_socket_release(local, listen, ENXIO); 168 nfc_llcp_socket_release(local, false, ENXIO);
179 del_timer_sync(&local->link_timer); 169 del_timer_sync(&local->link_timer);
180 skb_queue_purge(&local->tx_queue); 170 skb_queue_purge(&local->tx_queue);
181 cancel_work_sync(&local->tx_work); 171 cancel_work_sync(&local->tx_work);
@@ -194,7 +184,7 @@ static void local_release(struct kref *ref)
194 local = container_of(ref, struct nfc_llcp_local, ref); 184 local = container_of(ref, struct nfc_llcp_local, ref);
195 185
196 list_del(&local->list); 186 list_del(&local->list);
197 local_cleanup(local, false); 187 local_cleanup(local);
198 kfree(local); 188 kfree(local);
199} 189}
200 190
@@ -1116,6 +1106,12 @@ static void nfc_llcp_recv_disc(struct nfc_llcp_local *local,
1116 dsap = nfc_llcp_dsap(skb); 1106 dsap = nfc_llcp_dsap(skb);
1117 ssap = nfc_llcp_ssap(skb); 1107 ssap = nfc_llcp_ssap(skb);
1118 1108
1109 if ((dsap == 0) && (ssap == 0)) {
1110 pr_debug("Connection termination");
1111 nfc_dep_link_down(local->dev);
1112 return;
1113 }
1114
1119 llcp_sock = nfc_llcp_sock_get(local, dsap, ssap); 1115 llcp_sock = nfc_llcp_sock_get(local, dsap, ssap);
1120 if (llcp_sock == NULL) { 1116 if (llcp_sock == NULL) {
1121 nfc_llcp_send_dm(local, dsap, ssap, LLCP_DM_NOCONN); 1117 nfc_llcp_send_dm(local, dsap, ssap, LLCP_DM_NOCONN);
@@ -1349,19 +1345,54 @@ exit:
1349 nfc_llcp_send_snl_sdres(local, &llc_sdres_list, sdres_tlvs_len); 1345 nfc_llcp_send_snl_sdres(local, &llc_sdres_list, sdres_tlvs_len);
1350} 1346}
1351 1347
1352static void nfc_llcp_rx_work(struct work_struct *work) 1348static void nfc_llcp_recv_agf(struct nfc_llcp_local *local, struct sk_buff *skb)
1353{ 1349{
1354 struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, 1350 u8 ptype;
1355 rx_work); 1351 u16 pdu_len;
1356 u8 dsap, ssap, ptype; 1352 struct sk_buff *new_skb;
1357 struct sk_buff *skb;
1358 1353
1359 skb = local->rx_pending; 1354 if (skb->len <= LLCP_HEADER_SIZE) {
1360 if (skb == NULL) { 1355 pr_err("Malformed AGF PDU\n");
1361 pr_debug("No pending SKB\n");
1362 return; 1356 return;
1363 } 1357 }
1364 1358
1359 skb_pull(skb, LLCP_HEADER_SIZE);
1360
1361 while (skb->len > LLCP_AGF_PDU_HEADER_SIZE) {
1362 pdu_len = skb->data[0] << 8 | skb->data[1];
1363
1364 skb_pull(skb, LLCP_AGF_PDU_HEADER_SIZE);
1365
1366 if (pdu_len < LLCP_HEADER_SIZE || pdu_len > skb->len) {
1367 pr_err("Malformed AGF PDU\n");
1368 return;
1369 }
1370
1371 ptype = nfc_llcp_ptype(skb);
1372
1373 if (ptype == LLCP_PDU_SYMM || ptype == LLCP_PDU_AGF)
1374 goto next;
1375
1376 new_skb = nfc_alloc_recv_skb(pdu_len, GFP_KERNEL);
1377 if (new_skb == NULL) {
1378 pr_err("Could not allocate PDU\n");
1379 return;
1380 }
1381
1382 memcpy(skb_put(new_skb, pdu_len), skb->data, pdu_len);
1383
1384 nfc_llcp_rx_skb(local, new_skb);
1385
1386 kfree_skb(new_skb);
1387next:
1388 skb_pull(skb, pdu_len);
1389 }
1390}
1391
1392static void nfc_llcp_rx_skb(struct nfc_llcp_local *local, struct sk_buff *skb)
1393{
1394 u8 dsap, ssap, ptype;
1395
1365 ptype = nfc_llcp_ptype(skb); 1396 ptype = nfc_llcp_ptype(skb);
1366 dsap = nfc_llcp_dsap(skb); 1397 dsap = nfc_llcp_dsap(skb);
1367 ssap = nfc_llcp_ssap(skb); 1398 ssap = nfc_llcp_ssap(skb);
@@ -1372,10 +1403,6 @@ static void nfc_llcp_rx_work(struct work_struct *work)
1372 print_hex_dump(KERN_DEBUG, "LLCP Rx: ", DUMP_PREFIX_OFFSET, 1403 print_hex_dump(KERN_DEBUG, "LLCP Rx: ", DUMP_PREFIX_OFFSET,
1373 16, 1, skb->data, skb->len, true); 1404 16, 1, skb->data, skb->len, true);
1374 1405
1375 __net_timestamp(skb);
1376
1377 nfc_llcp_send_to_raw_sock(local, skb, NFC_LLCP_DIRECTION_RX);
1378
1379 switch (ptype) { 1406 switch (ptype) {
1380 case LLCP_PDU_SYMM: 1407 case LLCP_PDU_SYMM:
1381 pr_debug("SYMM\n"); 1408 pr_debug("SYMM\n");
@@ -1418,7 +1445,30 @@ static void nfc_llcp_rx_work(struct work_struct *work)
1418 nfc_llcp_recv_hdlc(local, skb); 1445 nfc_llcp_recv_hdlc(local, skb);
1419 break; 1446 break;
1420 1447
1448 case LLCP_PDU_AGF:
1449 pr_debug("AGF frame\n");
1450 nfc_llcp_recv_agf(local, skb);
1451 break;
1421 } 1452 }
1453}
1454
1455static void nfc_llcp_rx_work(struct work_struct *work)
1456{
1457 struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local,
1458 rx_work);
1459 struct sk_buff *skb;
1460
1461 skb = local->rx_pending;
1462 if (skb == NULL) {
1463 pr_debug("No pending SKB\n");
1464 return;
1465 }
1466
1467 __net_timestamp(skb);
1468
1469 nfc_llcp_send_to_raw_sock(local, skb, NFC_LLCP_DIRECTION_RX);
1470
1471 nfc_llcp_rx_skb(local, skb);
1422 1472
1423 schedule_work(&local->tx_work); 1473 schedule_work(&local->tx_work);
1424 kfree_skb(local->rx_pending); 1474 kfree_skb(local->rx_pending);
@@ -1466,6 +1516,9 @@ void nfc_llcp_mac_is_down(struct nfc_dev *dev)
1466 if (local == NULL) 1516 if (local == NULL)
1467 return; 1517 return;
1468 1518
1519 local->remote_miu = LLCP_DEFAULT_MIU;
1520 local->remote_lto = LLCP_DEFAULT_LTO;
1521
1469 /* Close and purge all existing sockets */ 1522 /* Close and purge all existing sockets */
1470 nfc_llcp_socket_release(local, true, 0); 1523 nfc_llcp_socket_release(local, true, 0);
1471} 1524}
@@ -1553,7 +1606,7 @@ void nfc_llcp_unregister_device(struct nfc_dev *dev)
1553 return; 1606 return;
1554 } 1607 }
1555 1608
1556 local_cleanup(local, false); 1609 local_cleanup(local);
1557 1610
1558 nfc_llcp_local_put(local); 1611 nfc_llcp_local_put(local);
1559} 1612}
diff --git a/net/nfc/llcp/llcp.h b/net/nfc/llcp/llcp.h
index 7e87a66b02ec..ff8c434f7df8 100644
--- a/net/nfc/llcp/llcp.h
+++ b/net/nfc/llcp/llcp.h
@@ -31,6 +31,7 @@ enum llcp_state {
31#define LLCP_MAX_LTO 0xff 31#define LLCP_MAX_LTO 0xff
32#define LLCP_MAX_RW 15 32#define LLCP_MAX_RW 15
33#define LLCP_MAX_MIUX 0x7ff 33#define LLCP_MAX_MIUX 0x7ff
34#define LLCP_MAX_MIU (LLCP_MAX_MIUX + 128)
34 35
35#define LLCP_WKS_NUM_SAP 16 36#define LLCP_WKS_NUM_SAP 16
36#define LLCP_SDP_NUM_SAP 16 37#define LLCP_SDP_NUM_SAP 16
@@ -124,7 +125,7 @@ struct nfc_llcp_sock {
124 char *service_name; 125 char *service_name;
125 size_t service_name_len; 126 size_t service_name_len;
126 u8 rw; 127 u8 rw;
127 u16 miux; 128 __be16 miux;
128 129
129 130
130 /* Remote link parameters */ 131 /* Remote link parameters */
@@ -162,6 +163,7 @@ struct nfc_llcp_ui_cb {
162 163
163#define LLCP_HEADER_SIZE 2 164#define LLCP_HEADER_SIZE 2
164#define LLCP_SEQUENCE_SIZE 1 165#define LLCP_SEQUENCE_SIZE 1
166#define LLCP_AGF_PDU_HEADER_SIZE 2
165 167
166/* LLCP versions: 1.1 is 1.0 plus SDP */ 168/* LLCP versions: 1.1 is 1.0 plus SDP */
167#define LLCP_VERSION_10 0x10 169#define LLCP_VERSION_10 0x10
@@ -210,6 +212,7 @@ struct nfc_llcp_ui_cb {
210 212
211void nfc_llcp_sock_link(struct llcp_sock_list *l, struct sock *s); 213void nfc_llcp_sock_link(struct llcp_sock_list *l, struct sock *s);
212void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *s); 214void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *s);
215void nfc_llcp_socket_remote_param_init(struct nfc_llcp_sock *sock);
213struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev); 216struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev);
214struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local); 217struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local);
215int nfc_llcp_local_put(struct nfc_llcp_local *local); 218int nfc_llcp_local_put(struct nfc_llcp_local *local);
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c
index c1101e6de170..d6faa47c9bba 100644
--- a/net/nfc/llcp/sock.c
+++ b/net/nfc/llcp/sock.c
@@ -279,7 +279,7 @@ static int nfc_llcp_setsockopt(struct socket *sock, int level, int optname,
279 break; 279 break;
280 } 280 }
281 281
282 llcp_sock->miux = (u16) opt; 282 llcp_sock->miux = cpu_to_be16((u16) opt);
283 283
284 break; 284 break;
285 285
@@ -299,9 +299,12 @@ static int nfc_llcp_setsockopt(struct socket *sock, int level, int optname,
299static int nfc_llcp_getsockopt(struct socket *sock, int level, int optname, 299static int nfc_llcp_getsockopt(struct socket *sock, int level, int optname,
300 char __user *optval, int __user *optlen) 300 char __user *optval, int __user *optlen)
301{ 301{
302 struct nfc_llcp_local *local;
302 struct sock *sk = sock->sk; 303 struct sock *sk = sock->sk;
303 struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); 304 struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
304 int len, err = 0; 305 int len, err = 0;
306 u16 miux, remote_miu;
307 u8 rw;
305 308
306 pr_debug("%p optname %d\n", sk, optname); 309 pr_debug("%p optname %d\n", sk, optname);
307 310
@@ -311,19 +314,48 @@ static int nfc_llcp_getsockopt(struct socket *sock, int level, int optname,
311 if (get_user(len, optlen)) 314 if (get_user(len, optlen))
312 return -EFAULT; 315 return -EFAULT;
313 316
317 local = llcp_sock->local;
318 if (!local)
319 return -ENODEV;
320
314 len = min_t(u32, len, sizeof(u32)); 321 len = min_t(u32, len, sizeof(u32));
315 322
316 lock_sock(sk); 323 lock_sock(sk);
317 324
318 switch (optname) { 325 switch (optname) {
319 case NFC_LLCP_RW: 326 case NFC_LLCP_RW:
320 if (put_user(llcp_sock->rw, (u32 __user *) optval)) 327 rw = llcp_sock->rw > LLCP_MAX_RW ? local->rw : llcp_sock->rw;
328 if (put_user(rw, (u32 __user *) optval))
321 err = -EFAULT; 329 err = -EFAULT;
322 330
323 break; 331 break;
324 332
325 case NFC_LLCP_MIUX: 333 case NFC_LLCP_MIUX:
326 if (put_user(llcp_sock->miux, (u32 __user *) optval)) 334 miux = be16_to_cpu(llcp_sock->miux) > LLCP_MAX_MIUX ?
335 be16_to_cpu(local->miux) : be16_to_cpu(llcp_sock->miux);
336
337 if (put_user(miux, (u32 __user *) optval))
338 err = -EFAULT;
339
340 break;
341
342 case NFC_LLCP_REMOTE_MIU:
343 remote_miu = llcp_sock->remote_miu > LLCP_MAX_MIU ?
344 local->remote_miu : llcp_sock->remote_miu;
345
346 if (put_user(remote_miu, (u32 __user *) optval))
347 err = -EFAULT;
348
349 break;
350
351 case NFC_LLCP_REMOTE_LTO:
352 if (put_user(local->remote_lto / 10, (u32 __user *) optval))
353 err = -EFAULT;
354
355 break;
356
357 case NFC_LLCP_REMOTE_RW:
358 if (put_user(llcp_sock->remote_rw, (u32 __user *) optval))
327 err = -EFAULT; 359 err = -EFAULT;
328 360
329 break; 361 break;
@@ -925,13 +957,12 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp)
925 llcp_sock->ssap = 0; 957 llcp_sock->ssap = 0;
926 llcp_sock->dsap = LLCP_SAP_SDP; 958 llcp_sock->dsap = LLCP_SAP_SDP;
927 llcp_sock->rw = LLCP_MAX_RW + 1; 959 llcp_sock->rw = LLCP_MAX_RW + 1;
928 llcp_sock->miux = LLCP_MAX_MIUX + 1; 960 llcp_sock->miux = cpu_to_be16(LLCP_MAX_MIUX + 1);
929 llcp_sock->remote_rw = LLCP_DEFAULT_RW;
930 llcp_sock->remote_miu = LLCP_DEFAULT_MIU;
931 llcp_sock->send_n = llcp_sock->send_ack_n = 0; 961 llcp_sock->send_n = llcp_sock->send_ack_n = 0;
932 llcp_sock->recv_n = llcp_sock->recv_ack_n = 0; 962 llcp_sock->recv_n = llcp_sock->recv_ack_n = 0;
933 llcp_sock->remote_ready = 1; 963 llcp_sock->remote_ready = 1;
934 llcp_sock->reserved_ssap = LLCP_SAP_MAX; 964 llcp_sock->reserved_ssap = LLCP_SAP_MAX;
965 nfc_llcp_socket_remote_param_init(llcp_sock);
935 skb_queue_head_init(&llcp_sock->tx_queue); 966 skb_queue_head_init(&llcp_sock->tx_queue);
936 skb_queue_head_init(&llcp_sock->tx_pending_queue); 967 skb_queue_head_init(&llcp_sock->tx_pending_queue);
937 INIT_LIST_HEAD(&llcp_sock->accept_queue); 968 INIT_LIST_HEAD(&llcp_sock->accept_queue);