diff options
author | John W. Linville <linville@tuxdriver.com> | 2012-10-29 14:52:37 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-10-29 14:52:37 -0400 |
commit | e298c79efcf7b88fded994a03375589d8b726ce7 (patch) | |
tree | ca430a7220b7ee30c1a0aa09b5e2c1511c9d0e4c /net | |
parent | d1f10302568221c20628200bc8baa426c55f61c0 (diff) | |
parent | 52feb444a90304eb13c03115bb9758101dbb9254 (diff) |
Merge tag 'nfc-next-3.8-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/nfc-3.0
This is the first NFC pull request for 3.8
With this one we have:
- pn544 p2p support.
- pn544 physical and HCI layers separation. We are getting the pn544 driver
ready to support non i2c physical layers.
- LLCP SNL (Service Name Lookup). This is the NFC p2p service discovery
protocol.
- LLCP datagram sockets (connection less) support.
- IDR library usage for NFC devices indexes assignement.
- NFC netlink extension for setting and getting LLCP link characteristics.
- Various code style fixes and cleanups spread over the pn533, LLCP, HCI and
pn544 code.
Diffstat (limited to 'net')
-rw-r--r-- | net/nfc/Kconfig | 4 | ||||
-rw-r--r-- | net/nfc/core.c | 33 | ||||
-rw-r--r-- | net/nfc/hci/command.c | 24 | ||||
-rw-r--r-- | net/nfc/hci/core.c | 71 | ||||
-rw-r--r-- | net/nfc/hci/llc.c | 2 | ||||
-rw-r--r-- | net/nfc/hci/llc_shdlc.c | 7 | ||||
-rw-r--r-- | net/nfc/llcp/Kconfig | 4 | ||||
-rw-r--r-- | net/nfc/llcp/commands.c | 120 | ||||
-rw-r--r-- | net/nfc/llcp/llcp.c | 226 | ||||
-rw-r--r-- | net/nfc/llcp/llcp.h | 13 | ||||
-rw-r--r-- | net/nfc/llcp/sock.c | 42 | ||||
-rw-r--r-- | net/nfc/nci/Kconfig | 4 | ||||
-rw-r--r-- | net/nfc/nci/core.c | 29 | ||||
-rw-r--r-- | net/nfc/netlink.c | 157 | ||||
-rw-r--r-- | net/nfc/nfc.h | 6 | ||||
-rw-r--r-- | net/nfc/rawsock.c | 1 |
16 files changed, 630 insertions, 113 deletions
diff --git a/net/nfc/Kconfig b/net/nfc/Kconfig index 8d8d9bc4b6ff..60c3bbb63e8e 100644 --- a/net/nfc/Kconfig +++ b/net/nfc/Kconfig | |||
@@ -3,8 +3,8 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | menuconfig NFC | 5 | menuconfig NFC |
6 | depends on NET && EXPERIMENTAL | 6 | depends on NET |
7 | tristate "NFC subsystem support (EXPERIMENTAL)" | 7 | tristate "NFC subsystem support" |
8 | default n | 8 | default n |
9 | help | 9 | help |
10 | Say Y here if you want to build support for NFC (Near field | 10 | Say Y here if you want to build support for NFC (Near field |
diff --git a/net/nfc/core.c b/net/nfc/core.c index 479bee36dc3e..aa64ea441676 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c | |||
@@ -40,6 +40,9 @@ | |||
40 | int nfc_devlist_generation; | 40 | int nfc_devlist_generation; |
41 | DEFINE_MUTEX(nfc_devlist_mutex); | 41 | DEFINE_MUTEX(nfc_devlist_mutex); |
42 | 42 | ||
43 | /* NFC device ID bitmap */ | ||
44 | static DEFINE_IDA(nfc_index_ida); | ||
45 | |||
43 | /** | 46 | /** |
44 | * nfc_dev_up - turn on the NFC device | 47 | * nfc_dev_up - turn on the NFC device |
45 | * | 48 | * |
@@ -181,6 +184,7 @@ int nfc_stop_poll(struct nfc_dev *dev) | |||
181 | 184 | ||
182 | dev->ops->stop_poll(dev); | 185 | dev->ops->stop_poll(dev); |
183 | dev->polling = false; | 186 | dev->polling = false; |
187 | dev->rf_mode = NFC_RF_NONE; | ||
184 | 188 | ||
185 | error: | 189 | error: |
186 | device_unlock(&dev->dev); | 190 | device_unlock(&dev->dev); |
@@ -194,7 +198,7 @@ static struct nfc_target *nfc_find_target(struct nfc_dev *dev, u32 target_idx) | |||
194 | if (dev->n_targets == 0) | 198 | if (dev->n_targets == 0) |
195 | return NULL; | 199 | return NULL; |
196 | 200 | ||
197 | for (i = 0; i < dev->n_targets ; i++) { | 201 | for (i = 0; i < dev->n_targets; i++) { |
198 | if (dev->targets[i].idx == target_idx) | 202 | if (dev->targets[i].idx == target_idx) |
199 | return &dev->targets[i]; | 203 | return &dev->targets[i]; |
200 | } | 204 | } |
@@ -274,12 +278,14 @@ int nfc_dep_link_down(struct nfc_dev *dev) | |||
274 | if (!rc) { | 278 | if (!rc) { |
275 | dev->dep_link_up = false; | 279 | dev->dep_link_up = false; |
276 | dev->active_target = NULL; | 280 | dev->active_target = NULL; |
281 | dev->rf_mode = NFC_RF_NONE; | ||
277 | nfc_llcp_mac_is_down(dev); | 282 | nfc_llcp_mac_is_down(dev); |
278 | nfc_genl_dep_link_down_event(dev); | 283 | nfc_genl_dep_link_down_event(dev); |
279 | } | 284 | } |
280 | 285 | ||
281 | error: | 286 | error: |
282 | device_unlock(&dev->dev); | 287 | device_unlock(&dev->dev); |
288 | |||
283 | return rc; | 289 | return rc; |
284 | } | 290 | } |
285 | 291 | ||
@@ -503,6 +509,7 @@ EXPORT_SYMBOL(nfc_tm_activated); | |||
503 | int nfc_tm_deactivated(struct nfc_dev *dev) | 509 | int nfc_tm_deactivated(struct nfc_dev *dev) |
504 | { | 510 | { |
505 | dev->dep_link_up = false; | 511 | dev->dep_link_up = false; |
512 | dev->rf_mode = NFC_RF_NONE; | ||
506 | 513 | ||
507 | return nfc_genl_tm_deactivated(dev); | 514 | return nfc_genl_tm_deactivated(dev); |
508 | } | 515 | } |
@@ -697,6 +704,8 @@ static void nfc_check_pres_work(struct work_struct *work) | |||
697 | 704 | ||
698 | if (dev->active_target && timer_pending(&dev->check_pres_timer) == 0) { | 705 | if (dev->active_target && timer_pending(&dev->check_pres_timer) == 0) { |
699 | rc = dev->ops->check_presence(dev, dev->active_target); | 706 | rc = dev->ops->check_presence(dev, dev->active_target); |
707 | if (rc == -EOPNOTSUPP) | ||
708 | goto exit; | ||
700 | if (!rc) { | 709 | if (!rc) { |
701 | mod_timer(&dev->check_pres_timer, jiffies + | 710 | mod_timer(&dev->check_pres_timer, jiffies + |
702 | msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); | 711 | msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); |
@@ -708,6 +717,7 @@ static void nfc_check_pres_work(struct work_struct *work) | |||
708 | } | 717 | } |
709 | } | 718 | } |
710 | 719 | ||
720 | exit: | ||
711 | device_unlock(&dev->dev); | 721 | device_unlock(&dev->dev); |
712 | } | 722 | } |
713 | 723 | ||
@@ -753,7 +763,6 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, | |||
753 | u32 supported_protocols, | 763 | u32 supported_protocols, |
754 | int tx_headroom, int tx_tailroom) | 764 | int tx_headroom, int tx_tailroom) |
755 | { | 765 | { |
756 | static atomic_t dev_no = ATOMIC_INIT(0); | ||
757 | struct nfc_dev *dev; | 766 | struct nfc_dev *dev; |
758 | 767 | ||
759 | if (!ops->start_poll || !ops->stop_poll || !ops->activate_target || | 768 | if (!ops->start_poll || !ops->stop_poll || !ops->activate_target || |
@@ -767,11 +776,6 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, | |||
767 | if (!dev) | 776 | if (!dev) |
768 | return NULL; | 777 | return NULL; |
769 | 778 | ||
770 | dev->dev.class = &nfc_class; | ||
771 | dev->idx = atomic_inc_return(&dev_no) - 1; | ||
772 | dev_set_name(&dev->dev, "nfc%d", dev->idx); | ||
773 | device_initialize(&dev->dev); | ||
774 | |||
775 | dev->ops = ops; | 779 | dev->ops = ops; |
776 | dev->supported_protocols = supported_protocols; | 780 | dev->supported_protocols = supported_protocols; |
777 | dev->tx_headroom = tx_headroom; | 781 | dev->tx_headroom = tx_headroom; |
@@ -779,6 +783,7 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, | |||
779 | 783 | ||
780 | nfc_genl_data_init(&dev->genl_data); | 784 | nfc_genl_data_init(&dev->genl_data); |
781 | 785 | ||
786 | dev->rf_mode = NFC_RF_NONE; | ||
782 | 787 | ||
783 | /* first generation must not be 0 */ | 788 | /* first generation must not be 0 */ |
784 | dev->targets_generation = 1; | 789 | dev->targets_generation = 1; |
@@ -806,6 +811,14 @@ int nfc_register_device(struct nfc_dev *dev) | |||
806 | 811 | ||
807 | pr_debug("dev_name=%s\n", dev_name(&dev->dev)); | 812 | pr_debug("dev_name=%s\n", dev_name(&dev->dev)); |
808 | 813 | ||
814 | dev->idx = ida_simple_get(&nfc_index_ida, 0, 0, GFP_KERNEL); | ||
815 | if (dev->idx < 0) | ||
816 | return dev->idx; | ||
817 | |||
818 | dev->dev.class = &nfc_class; | ||
819 | dev_set_name(&dev->dev, "nfc%d", dev->idx); | ||
820 | device_initialize(&dev->dev); | ||
821 | |||
809 | mutex_lock(&nfc_devlist_mutex); | 822 | mutex_lock(&nfc_devlist_mutex); |
810 | nfc_devlist_generation++; | 823 | nfc_devlist_generation++; |
811 | rc = device_add(&dev->dev); | 824 | rc = device_add(&dev->dev); |
@@ -834,10 +847,12 @@ EXPORT_SYMBOL(nfc_register_device); | |||
834 | */ | 847 | */ |
835 | void nfc_unregister_device(struct nfc_dev *dev) | 848 | void nfc_unregister_device(struct nfc_dev *dev) |
836 | { | 849 | { |
837 | int rc; | 850 | int rc, id; |
838 | 851 | ||
839 | pr_debug("dev_name=%s\n", dev_name(&dev->dev)); | 852 | pr_debug("dev_name=%s\n", dev_name(&dev->dev)); |
840 | 853 | ||
854 | id = dev->idx; | ||
855 | |||
841 | mutex_lock(&nfc_devlist_mutex); | 856 | mutex_lock(&nfc_devlist_mutex); |
842 | nfc_devlist_generation++; | 857 | nfc_devlist_generation++; |
843 | 858 | ||
@@ -856,6 +871,8 @@ void nfc_unregister_device(struct nfc_dev *dev) | |||
856 | pr_debug("The userspace won't be notified that the device %s was removed\n", | 871 | pr_debug("The userspace won't be notified that the device %s was removed\n", |
857 | dev_name(&dev->dev)); | 872 | dev_name(&dev->dev)); |
858 | 873 | ||
874 | ida_simple_remove(&nfc_index_ida, id); | ||
875 | |||
859 | } | 876 | } |
860 | EXPORT_SYMBOL(nfc_unregister_device); | 877 | EXPORT_SYMBOL(nfc_unregister_device); |
861 | 878 | ||
diff --git a/net/nfc/hci/command.c b/net/nfc/hci/command.c index 71c6a7086b8f..07659cfd6d7b 100644 --- a/net/nfc/hci/command.c +++ b/net/nfc/hci/command.c | |||
@@ -257,16 +257,16 @@ static u8 nfc_hci_create_pipe(struct nfc_hci_dev *hdev, u8 dest_host, | |||
257 | *result = nfc_hci_execute_cmd(hdev, NFC_HCI_ADMIN_PIPE, | 257 | *result = nfc_hci_execute_cmd(hdev, NFC_HCI_ADMIN_PIPE, |
258 | NFC_HCI_ADM_CREATE_PIPE, | 258 | NFC_HCI_ADM_CREATE_PIPE, |
259 | (u8 *) ¶ms, sizeof(params), &skb); | 259 | (u8 *) ¶ms, sizeof(params), &skb); |
260 | if (*result == 0) { | 260 | if (*result < 0) |
261 | resp = (struct hci_create_pipe_resp *)skb->data; | 261 | return NFC_HCI_INVALID_PIPE; |
262 | pipe = resp->pipe; | ||
263 | kfree_skb(skb); | ||
264 | 262 | ||
265 | pr_debug("pipe created=%d\n", pipe); | 263 | resp = (struct hci_create_pipe_resp *)skb->data; |
264 | pipe = resp->pipe; | ||
265 | kfree_skb(skb); | ||
266 | 266 | ||
267 | return pipe; | 267 | pr_debug("pipe created=%d\n", pipe); |
268 | } else | 268 | |
269 | return NFC_HCI_INVALID_PIPE; | 269 | return pipe; |
270 | } | 270 | } |
271 | 271 | ||
272 | static int nfc_hci_delete_pipe(struct nfc_hci_dev *hdev, u8 pipe) | 272 | static int nfc_hci_delete_pipe(struct nfc_hci_dev *hdev, u8 pipe) |
@@ -279,8 +279,6 @@ static int nfc_hci_delete_pipe(struct nfc_hci_dev *hdev, u8 pipe) | |||
279 | 279 | ||
280 | static int nfc_hci_clear_all_pipes(struct nfc_hci_dev *hdev) | 280 | static int nfc_hci_clear_all_pipes(struct nfc_hci_dev *hdev) |
281 | { | 281 | { |
282 | int r; | ||
283 | |||
284 | u8 param[2]; | 282 | u8 param[2]; |
285 | 283 | ||
286 | /* TODO: Find out what the identity reference data is | 284 | /* TODO: Find out what the identity reference data is |
@@ -288,10 +286,8 @@ static int nfc_hci_clear_all_pipes(struct nfc_hci_dev *hdev) | |||
288 | 286 | ||
289 | pr_debug("\n"); | 287 | pr_debug("\n"); |
290 | 288 | ||
291 | r = nfc_hci_execute_cmd(hdev, NFC_HCI_ADMIN_PIPE, | 289 | return nfc_hci_execute_cmd(hdev, NFC_HCI_ADMIN_PIPE, |
292 | NFC_HCI_ADM_CLEAR_ALL_PIPE, param, 2, NULL); | 290 | NFC_HCI_ADM_CLEAR_ALL_PIPE, param, 2, NULL); |
293 | |||
294 | return 0; | ||
295 | } | 291 | } |
296 | 292 | ||
297 | int nfc_hci_disconnect_gate(struct nfc_hci_dev *hdev, u8 gate) | 293 | int nfc_hci_disconnect_gate(struct nfc_hci_dev *hdev, u8 gate) |
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index 5fbb6e40793e..bc571b0efb92 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c | |||
@@ -65,8 +65,9 @@ static void nfc_hci_msg_tx_work(struct work_struct *work) | |||
65 | -ETIME); | 65 | -ETIME); |
66 | kfree(hdev->cmd_pending_msg); | 66 | kfree(hdev->cmd_pending_msg); |
67 | hdev->cmd_pending_msg = NULL; | 67 | hdev->cmd_pending_msg = NULL; |
68 | } else | 68 | } else { |
69 | goto exit; | 69 | goto exit; |
70 | } | ||
70 | } | 71 | } |
71 | 72 | ||
72 | next_msg: | 73 | next_msg: |
@@ -182,7 +183,7 @@ static u32 nfc_hci_sak_to_protocol(u8 sak) | |||
182 | } | 183 | } |
183 | } | 184 | } |
184 | 185 | ||
185 | static int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate) | 186 | int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate) |
186 | { | 187 | { |
187 | struct nfc_target *targets; | 188 | struct nfc_target *targets; |
188 | struct sk_buff *atqa_skb = NULL; | 189 | struct sk_buff *atqa_skb = NULL; |
@@ -263,7 +264,9 @@ static int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate) | |||
263 | break; | 264 | break; |
264 | } | 265 | } |
265 | 266 | ||
266 | targets->hci_reader_gate = gate; | 267 | /* if driver set the new gate, we will skip the old one */ |
268 | if (targets->hci_reader_gate == 0x00) | ||
269 | targets->hci_reader_gate = gate; | ||
267 | 270 | ||
268 | r = nfc_targets_found(hdev->ndev, targets, 1); | 271 | r = nfc_targets_found(hdev->ndev, targets, 1); |
269 | 272 | ||
@@ -275,6 +278,7 @@ exit: | |||
275 | 278 | ||
276 | return r; | 279 | return r; |
277 | } | 280 | } |
281 | EXPORT_SYMBOL(nfc_hci_target_discovered); | ||
278 | 282 | ||
279 | void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event, | 283 | void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event, |
280 | struct sk_buff *skb) | 284 | struct sk_buff *skb) |
@@ -307,8 +311,13 @@ void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event, | |||
307 | nfc_hci_pipe2gate(hdev, pipe)); | 311 | nfc_hci_pipe2gate(hdev, pipe)); |
308 | break; | 312 | break; |
309 | default: | 313 | default: |
310 | /* TODO: Unknown events are hardware specific | 314 | if (hdev->ops->event_received) { |
311 | * pass them to the driver (needs a new hci_ops) */ | 315 | hdev->ops->event_received(hdev, |
316 | nfc_hci_pipe2gate(hdev, pipe), | ||
317 | event, skb); | ||
318 | return; | ||
319 | } | ||
320 | |||
312 | break; | 321 | break; |
313 | } | 322 | } |
314 | 323 | ||
@@ -527,7 +536,8 @@ static int hci_start_poll(struct nfc_dev *nfc_dev, | |||
527 | return hdev->ops->start_poll(hdev, im_protocols, tm_protocols); | 536 | return hdev->ops->start_poll(hdev, im_protocols, tm_protocols); |
528 | else | 537 | else |
529 | return nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, | 538 | return nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, |
530 | NFC_HCI_EVT_READER_REQUESTED, NULL, 0); | 539 | NFC_HCI_EVT_READER_REQUESTED, |
540 | NULL, 0); | ||
531 | } | 541 | } |
532 | 542 | ||
533 | static void hci_stop_poll(struct nfc_dev *nfc_dev) | 543 | static void hci_stop_poll(struct nfc_dev *nfc_dev) |
@@ -538,6 +548,28 @@ static void hci_stop_poll(struct nfc_dev *nfc_dev) | |||
538 | NFC_HCI_EVT_END_OPERATION, NULL, 0); | 548 | NFC_HCI_EVT_END_OPERATION, NULL, 0); |
539 | } | 549 | } |
540 | 550 | ||
551 | static int hci_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, | ||
552 | __u8 comm_mode, __u8 *gb, size_t gb_len) | ||
553 | { | ||
554 | struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); | ||
555 | |||
556 | if (hdev->ops->dep_link_up) | ||
557 | return hdev->ops->dep_link_up(hdev, target, comm_mode, | ||
558 | gb, gb_len); | ||
559 | |||
560 | return 0; | ||
561 | } | ||
562 | |||
563 | static int hci_dep_link_down(struct nfc_dev *nfc_dev) | ||
564 | { | ||
565 | struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); | ||
566 | |||
567 | if (hdev->ops->dep_link_down) | ||
568 | return hdev->ops->dep_link_down(hdev); | ||
569 | |||
570 | return 0; | ||
571 | } | ||
572 | |||
541 | static int hci_activate_target(struct nfc_dev *nfc_dev, | 573 | static int hci_activate_target(struct nfc_dev *nfc_dev, |
542 | struct nfc_target *target, u32 protocol) | 574 | struct nfc_target *target, u32 protocol) |
543 | { | 575 | { |
@@ -586,8 +618,8 @@ static int hci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target, | |||
586 | switch (target->hci_reader_gate) { | 618 | switch (target->hci_reader_gate) { |
587 | case NFC_HCI_RF_READER_A_GATE: | 619 | case NFC_HCI_RF_READER_A_GATE: |
588 | case NFC_HCI_RF_READER_B_GATE: | 620 | case NFC_HCI_RF_READER_B_GATE: |
589 | if (hdev->ops->data_exchange) { | 621 | if (hdev->ops->im_transceive) { |
590 | r = hdev->ops->data_exchange(hdev, target, skb, cb, | 622 | r = hdev->ops->im_transceive(hdev, target, skb, cb, |
591 | cb_context); | 623 | cb_context); |
592 | if (r <= 0) /* handled */ | 624 | if (r <= 0) /* handled */ |
593 | break; | 625 | break; |
@@ -604,14 +636,14 @@ static int hci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target, | |||
604 | skb->len, hci_transceive_cb, hdev); | 636 | skb->len, hci_transceive_cb, hdev); |
605 | break; | 637 | break; |
606 | default: | 638 | default: |
607 | if (hdev->ops->data_exchange) { | 639 | if (hdev->ops->im_transceive) { |
608 | r = hdev->ops->data_exchange(hdev, target, skb, cb, | 640 | r = hdev->ops->im_transceive(hdev, target, skb, cb, |
609 | cb_context); | 641 | cb_context); |
610 | if (r == 1) | 642 | if (r == 1) |
611 | r = -ENOTSUPP; | 643 | r = -ENOTSUPP; |
612 | } | 644 | } else { |
613 | else | ||
614 | r = -ENOTSUPP; | 645 | r = -ENOTSUPP; |
646 | } | ||
615 | break; | 647 | break; |
616 | } | 648 | } |
617 | 649 | ||
@@ -620,6 +652,16 @@ static int hci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target, | |||
620 | return r; | 652 | return r; |
621 | } | 653 | } |
622 | 654 | ||
655 | static int hci_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) | ||
656 | { | ||
657 | struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); | ||
658 | |||
659 | if (hdev->ops->tm_send) | ||
660 | return hdev->ops->tm_send(hdev, skb); | ||
661 | else | ||
662 | return -ENOTSUPP; | ||
663 | } | ||
664 | |||
623 | static int hci_check_presence(struct nfc_dev *nfc_dev, | 665 | static int hci_check_presence(struct nfc_dev *nfc_dev, |
624 | struct nfc_target *target) | 666 | struct nfc_target *target) |
625 | { | 667 | { |
@@ -723,9 +765,12 @@ static struct nfc_ops hci_nfc_ops = { | |||
723 | .dev_down = hci_dev_down, | 765 | .dev_down = hci_dev_down, |
724 | .start_poll = hci_start_poll, | 766 | .start_poll = hci_start_poll, |
725 | .stop_poll = hci_stop_poll, | 767 | .stop_poll = hci_stop_poll, |
768 | .dep_link_up = hci_dep_link_up, | ||
769 | .dep_link_down = hci_dep_link_down, | ||
726 | .activate_target = hci_activate_target, | 770 | .activate_target = hci_activate_target, |
727 | .deactivate_target = hci_deactivate_target, | 771 | .deactivate_target = hci_deactivate_target, |
728 | .im_transceive = hci_transceive, | 772 | .im_transceive = hci_transceive, |
773 | .tm_send = hci_tm_send, | ||
729 | .check_presence = hci_check_presence, | 774 | .check_presence = hci_check_presence, |
730 | }; | 775 | }; |
731 | 776 | ||
@@ -848,7 +893,7 @@ void nfc_hci_driver_failure(struct nfc_hci_dev *hdev, int err) | |||
848 | } | 893 | } |
849 | EXPORT_SYMBOL(nfc_hci_driver_failure); | 894 | EXPORT_SYMBOL(nfc_hci_driver_failure); |
850 | 895 | ||
851 | void inline nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb) | 896 | void nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb) |
852 | { | 897 | { |
853 | nfc_llc_rcv_from_drv(hdev->llc, skb); | 898 | nfc_llc_rcv_from_drv(hdev->llc, skb); |
854 | } | 899 | } |
diff --git a/net/nfc/hci/llc.c b/net/nfc/hci/llc.c index ae1205ded87f..fe5e966e5b88 100644 --- a/net/nfc/hci/llc.c +++ b/net/nfc/hci/llc.c | |||
@@ -72,7 +72,7 @@ int nfc_llc_register(const char *name, struct nfc_llc_ops *ops) | |||
72 | llc_engine->ops = ops; | 72 | llc_engine->ops = ops; |
73 | 73 | ||
74 | INIT_LIST_HEAD(&llc_engine->entry); | 74 | INIT_LIST_HEAD(&llc_engine->entry); |
75 | list_add_tail (&llc_engine->entry, &llc_engines); | 75 | list_add_tail(&llc_engine->entry, &llc_engines); |
76 | 76 | ||
77 | return 0; | 77 | return 0; |
78 | } | 78 | } |
diff --git a/net/nfc/hci/llc_shdlc.c b/net/nfc/hci/llc_shdlc.c index 01cbc72943cd..27b313befc35 100644 --- a/net/nfc/hci/llc_shdlc.c +++ b/net/nfc/hci/llc_shdlc.c | |||
@@ -634,9 +634,9 @@ static void llc_shdlc_sm_work(struct work_struct *work) | |||
634 | r = llc_shdlc_connect_initiate(shdlc); | 634 | r = llc_shdlc_connect_initiate(shdlc); |
635 | else | 635 | else |
636 | r = -ETIME; | 636 | r = -ETIME; |
637 | if (r < 0) | 637 | if (r < 0) { |
638 | llc_shdlc_connect_complete(shdlc, r); | 638 | llc_shdlc_connect_complete(shdlc, r); |
639 | else { | 639 | } else { |
640 | mod_timer(&shdlc->connect_timer, jiffies + | 640 | mod_timer(&shdlc->connect_timer, jiffies + |
641 | msecs_to_jiffies(SHDLC_CONNECT_VALUE_MS)); | 641 | msecs_to_jiffies(SHDLC_CONNECT_VALUE_MS)); |
642 | 642 | ||
@@ -682,9 +682,8 @@ static void llc_shdlc_sm_work(struct work_struct *work) | |||
682 | llc_shdlc_handle_send_queue(shdlc); | 682 | llc_shdlc_handle_send_queue(shdlc); |
683 | } | 683 | } |
684 | 684 | ||
685 | if (shdlc->hard_fault) { | 685 | if (shdlc->hard_fault) |
686 | shdlc->llc_failure(shdlc->hdev, shdlc->hard_fault); | 686 | shdlc->llc_failure(shdlc->hdev, shdlc->hard_fault); |
687 | } | ||
688 | break; | 687 | break; |
689 | default: | 688 | default: |
690 | break; | 689 | break; |
diff --git a/net/nfc/llcp/Kconfig b/net/nfc/llcp/Kconfig index fbf5e8150908..a1a41cd68255 100644 --- a/net/nfc/llcp/Kconfig +++ b/net/nfc/llcp/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config NFC_LLCP | 1 | config NFC_LLCP |
2 | depends on NFC && EXPERIMENTAL | 2 | depends on NFC |
3 | bool "NFC LLCP support (EXPERIMENTAL)" | 3 | bool "NFC LLCP support" |
4 | default n | 4 | default n |
5 | help | 5 | help |
6 | Say Y here if you want to build support for a kernel NFC LLCP | 6 | Say Y here if you want to build support for a kernel NFC LLCP |
diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c index c45ccd6c094c..ed2d17312d61 100644 --- a/net/nfc/llcp/commands.c +++ b/net/nfc/llcp/commands.c | |||
@@ -261,7 +261,6 @@ int nfc_llcp_disconnect(struct nfc_llcp_sock *sock) | |||
261 | struct sk_buff *skb; | 261 | struct sk_buff *skb; |
262 | struct nfc_dev *dev; | 262 | struct nfc_dev *dev; |
263 | struct nfc_llcp_local *local; | 263 | struct nfc_llcp_local *local; |
264 | u16 size = 0; | ||
265 | 264 | ||
266 | pr_debug("Sending DISC\n"); | 265 | pr_debug("Sending DISC\n"); |
267 | 266 | ||
@@ -273,17 +272,10 @@ int nfc_llcp_disconnect(struct nfc_llcp_sock *sock) | |||
273 | if (dev == NULL) | 272 | if (dev == NULL) |
274 | return -ENODEV; | 273 | return -ENODEV; |
275 | 274 | ||
276 | size += LLCP_HEADER_SIZE; | 275 | skb = llcp_allocate_pdu(sock, LLCP_PDU_DISC, 0); |
277 | size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE; | ||
278 | |||
279 | skb = alloc_skb(size, GFP_ATOMIC); | ||
280 | if (skb == NULL) | 276 | if (skb == NULL) |
281 | return -ENOMEM; | 277 | return -ENOMEM; |
282 | 278 | ||
283 | skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE); | ||
284 | |||
285 | skb = llcp_add_header(skb, sock->dsap, sock->ssap, LLCP_PDU_DISC); | ||
286 | |||
287 | skb_queue_tail(&local->tx_queue, skb); | 279 | skb_queue_tail(&local->tx_queue, skb); |
288 | 280 | ||
289 | return 0; | 281 | return 0; |
@@ -324,8 +316,7 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock) | |||
324 | struct sk_buff *skb; | 316 | struct sk_buff *skb; |
325 | u8 *service_name_tlv = NULL, service_name_tlv_length; | 317 | u8 *service_name_tlv = NULL, service_name_tlv_length; |
326 | u8 *miux_tlv = NULL, miux_tlv_length; | 318 | u8 *miux_tlv = NULL, miux_tlv_length; |
327 | u8 *rw_tlv = NULL, rw_tlv_length, rw; | 319 | u8 *rw_tlv = NULL, rw_tlv_length; |
328 | __be16 miux; | ||
329 | int err; | 320 | int err; |
330 | u16 size = 0; | 321 | u16 size = 0; |
331 | 322 | ||
@@ -343,13 +334,11 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock) | |||
343 | size += service_name_tlv_length; | 334 | size += service_name_tlv_length; |
344 | } | 335 | } |
345 | 336 | ||
346 | miux = cpu_to_be16(LLCP_MAX_MIUX); | 337 | miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&local->miux, 0, |
347 | miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0, | ||
348 | &miux_tlv_length); | 338 | &miux_tlv_length); |
349 | size += miux_tlv_length; | 339 | size += miux_tlv_length; |
350 | 340 | ||
351 | rw = LLCP_MAX_RW; | 341 | rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &local->rw, 0, &rw_tlv_length); |
352 | rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &rw, 0, &rw_tlv_length); | ||
353 | size += rw_tlv_length; | 342 | size += rw_tlv_length; |
354 | 343 | ||
355 | 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); |
@@ -386,8 +375,7 @@ int nfc_llcp_send_cc(struct nfc_llcp_sock *sock) | |||
386 | struct nfc_llcp_local *local; | 375 | struct nfc_llcp_local *local; |
387 | struct sk_buff *skb; | 376 | struct sk_buff *skb; |
388 | u8 *miux_tlv = NULL, miux_tlv_length; | 377 | u8 *miux_tlv = NULL, miux_tlv_length; |
389 | u8 *rw_tlv = NULL, rw_tlv_length, rw; | 378 | u8 *rw_tlv = NULL, rw_tlv_length; |
390 | __be16 miux; | ||
391 | int err; | 379 | int err; |
392 | u16 size = 0; | 380 | u16 size = 0; |
393 | 381 | ||
@@ -397,13 +385,11 @@ int nfc_llcp_send_cc(struct nfc_llcp_sock *sock) | |||
397 | if (local == NULL) | 385 | if (local == NULL) |
398 | return -ENODEV; | 386 | return -ENODEV; |
399 | 387 | ||
400 | miux = cpu_to_be16(LLCP_MAX_MIUX); | 388 | miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&local->miux, 0, |
401 | miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0, | ||
402 | &miux_tlv_length); | 389 | &miux_tlv_length); |
403 | size += miux_tlv_length; | 390 | size += miux_tlv_length; |
404 | 391 | ||
405 | rw = LLCP_MAX_RW; | 392 | rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &local->rw, 0, &rw_tlv_length); |
406 | rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &rw, 0, &rw_tlv_length); | ||
407 | size += rw_tlv_length; | 393 | size += rw_tlv_length; |
408 | 394 | ||
409 | skb = llcp_allocate_pdu(sock, LLCP_PDU_CC, size); | 395 | skb = llcp_allocate_pdu(sock, LLCP_PDU_CC, size); |
@@ -428,6 +414,52 @@ error_tlv: | |||
428 | return err; | 414 | return err; |
429 | } | 415 | } |
430 | 416 | ||
417 | int nfc_llcp_send_snl(struct nfc_llcp_local *local, u8 tid, u8 sap) | ||
418 | { | ||
419 | struct sk_buff *skb; | ||
420 | struct nfc_dev *dev; | ||
421 | u8 *sdres_tlv = NULL, sdres_tlv_length, sdres[2]; | ||
422 | u16 size = 0; | ||
423 | |||
424 | pr_debug("Sending SNL tid 0x%x sap 0x%x\n", tid, sap); | ||
425 | |||
426 | if (local == NULL) | ||
427 | return -ENODEV; | ||
428 | |||
429 | dev = local->dev; | ||
430 | if (dev == NULL) | ||
431 | return -ENODEV; | ||
432 | |||
433 | sdres[0] = tid; | ||
434 | sdres[1] = sap; | ||
435 | sdres_tlv = nfc_llcp_build_tlv(LLCP_TLV_SDRES, sdres, 0, | ||
436 | &sdres_tlv_length); | ||
437 | if (sdres_tlv == NULL) | ||
438 | return -ENOMEM; | ||
439 | |||
440 | size += LLCP_HEADER_SIZE; | ||
441 | size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE; | ||
442 | size += sdres_tlv_length; | ||
443 | |||
444 | skb = alloc_skb(size, GFP_KERNEL); | ||
445 | if (skb == NULL) { | ||
446 | kfree(sdres_tlv); | ||
447 | return -ENOMEM; | ||
448 | } | ||
449 | |||
450 | skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE); | ||
451 | |||
452 | skb = llcp_add_header(skb, LLCP_SAP_SDP, LLCP_SAP_SDP, LLCP_PDU_SNL); | ||
453 | |||
454 | memcpy(skb_put(skb, sdres_tlv_length), sdres_tlv, sdres_tlv_length); | ||
455 | |||
456 | skb_queue_tail(&local->tx_queue, skb); | ||
457 | |||
458 | kfree(sdres_tlv); | ||
459 | |||
460 | return 0; | ||
461 | } | ||
462 | |||
431 | int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason) | 463 | int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason) |
432 | { | 464 | { |
433 | struct sk_buff *skb; | 465 | struct sk_buff *skb; |
@@ -541,6 +573,52 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, | |||
541 | return len; | 573 | return len; |
542 | } | 574 | } |
543 | 575 | ||
576 | int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap, | ||
577 | struct msghdr *msg, size_t len) | ||
578 | { | ||
579 | struct sk_buff *pdu; | ||
580 | struct nfc_llcp_local *local; | ||
581 | size_t frag_len = 0, remaining_len; | ||
582 | u8 *msg_ptr; | ||
583 | int err; | ||
584 | |||
585 | pr_debug("Send UI frame len %zd\n", len); | ||
586 | |||
587 | local = sock->local; | ||
588 | if (local == NULL) | ||
589 | return -ENODEV; | ||
590 | |||
591 | remaining_len = len; | ||
592 | msg_ptr = (u8 *) msg->msg_iov; | ||
593 | |||
594 | while (remaining_len > 0) { | ||
595 | |||
596 | frag_len = min_t(size_t, sock->miu, remaining_len); | ||
597 | |||
598 | pr_debug("Fragment %zd bytes remaining %zd", | ||
599 | frag_len, remaining_len); | ||
600 | |||
601 | pdu = nfc_alloc_send_skb(sock->dev, &sock->sk, MSG_DONTWAIT, | ||
602 | frag_len + LLCP_HEADER_SIZE, &err); | ||
603 | if (pdu == NULL) { | ||
604 | pr_err("Could not allocate PDU\n"); | ||
605 | continue; | ||
606 | } | ||
607 | |||
608 | pdu = llcp_add_header(pdu, dsap, ssap, LLCP_PDU_UI); | ||
609 | |||
610 | memcpy(skb_put(pdu, frag_len), msg_ptr, frag_len); | ||
611 | |||
612 | /* No need to check for the peer RW for UI frames */ | ||
613 | skb_queue_tail(&local->tx_queue, pdu); | ||
614 | |||
615 | remaining_len -= frag_len; | ||
616 | msg_ptr += frag_len; | ||
617 | } | ||
618 | |||
619 | return len; | ||
620 | } | ||
621 | |||
544 | int nfc_llcp_send_rr(struct nfc_llcp_sock *sock) | 622 | int nfc_llcp_send_rr(struct nfc_llcp_sock *sock) |
545 | { | 623 | { |
546 | struct sk_buff *skb; | 624 | struct sk_buff *skb; |
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c index cc10d073c338..f6804532047a 100644 --- a/net/nfc/llcp/llcp.c +++ b/net/nfc/llcp/llcp.c | |||
@@ -45,12 +45,38 @@ void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *sk) | |||
45 | write_unlock(&l->lock); | 45 | write_unlock(&l->lock); |
46 | } | 46 | } |
47 | 47 | ||
48 | static void nfc_llcp_socket_purge(struct nfc_llcp_sock *sock) | ||
49 | { | ||
50 | struct nfc_llcp_local *local = sock->local; | ||
51 | struct sk_buff *s, *tmp; | ||
52 | |||
53 | pr_debug("%p\n", &sock->sk); | ||
54 | |||
55 | skb_queue_purge(&sock->tx_queue); | ||
56 | skb_queue_purge(&sock->tx_pending_queue); | ||
57 | skb_queue_purge(&sock->tx_backlog_queue); | ||
58 | |||
59 | if (local == NULL) | ||
60 | return; | ||
61 | |||
62 | /* Search for local pending SKBs that are related to this socket */ | ||
63 | skb_queue_walk_safe(&local->tx_queue, s, tmp) { | ||
64 | if (s->sk != &sock->sk) | ||
65 | continue; | ||
66 | |||
67 | skb_unlink(s, &local->tx_queue); | ||
68 | kfree_skb(s); | ||
69 | } | ||
70 | } | ||
71 | |||
48 | static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen) | 72 | static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen) |
49 | { | 73 | { |
50 | struct sock *sk; | 74 | struct sock *sk; |
51 | struct hlist_node *node, *tmp; | 75 | struct hlist_node *node, *tmp; |
52 | struct nfc_llcp_sock *llcp_sock; | 76 | struct nfc_llcp_sock *llcp_sock; |
53 | 77 | ||
78 | skb_queue_purge(&local->tx_queue); | ||
79 | |||
54 | write_lock(&local->sockets.lock); | 80 | write_lock(&local->sockets.lock); |
55 | 81 | ||
56 | sk_for_each_safe(sk, node, tmp, &local->sockets.head) { | 82 | sk_for_each_safe(sk, node, tmp, &local->sockets.head) { |
@@ -58,6 +84,8 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen) | |||
58 | 84 | ||
59 | bh_lock_sock(sk); | 85 | bh_lock_sock(sk); |
60 | 86 | ||
87 | nfc_llcp_socket_purge(llcp_sock); | ||
88 | |||
61 | if (sk->sk_state == LLCP_CONNECTED) | 89 | if (sk->sk_state == LLCP_CONNECTED) |
62 | nfc_put_device(llcp_sock->dev); | 90 | nfc_put_device(llcp_sock->dev); |
63 | 91 | ||
@@ -65,7 +93,8 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen) | |||
65 | struct nfc_llcp_sock *lsk, *n; | 93 | struct nfc_llcp_sock *lsk, *n; |
66 | struct sock *accept_sk; | 94 | struct sock *accept_sk; |
67 | 95 | ||
68 | list_for_each_entry_safe(lsk, n, &llcp_sock->accept_queue, | 96 | list_for_each_entry_safe(lsk, n, |
97 | &llcp_sock->accept_queue, | ||
69 | accept_queue) { | 98 | accept_queue) { |
70 | accept_sk = &lsk->sk; | 99 | accept_sk = &lsk->sk; |
71 | bh_lock_sock(accept_sk); | 100 | bh_lock_sock(accept_sk); |
@@ -85,6 +114,16 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen) | |||
85 | } | 114 | } |
86 | } | 115 | } |
87 | 116 | ||
117 | /* | ||
118 | * If we have a connection less socket bound, we keep it alive | ||
119 | * if the device is still present. | ||
120 | */ | ||
121 | if (sk->sk_state == LLCP_BOUND && sk->sk_type == SOCK_DGRAM && | ||
122 | listen == true) { | ||
123 | bh_unlock_sock(sk); | ||
124 | continue; | ||
125 | } | ||
126 | |||
88 | sk->sk_state = LLCP_CLOSED; | 127 | sk->sk_state = LLCP_CLOSED; |
89 | 128 | ||
90 | bh_unlock_sock(sk); | 129 | bh_unlock_sock(sk); |
@@ -134,7 +173,7 @@ static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local, | |||
134 | { | 173 | { |
135 | struct sock *sk; | 174 | struct sock *sk; |
136 | struct hlist_node *node; | 175 | struct hlist_node *node; |
137 | struct nfc_llcp_sock *llcp_sock; | 176 | struct nfc_llcp_sock *llcp_sock, *tmp_sock; |
138 | 177 | ||
139 | pr_debug("ssap dsap %d %d\n", ssap, dsap); | 178 | pr_debug("ssap dsap %d %d\n", ssap, dsap); |
140 | 179 | ||
@@ -146,10 +185,12 @@ static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local, | |||
146 | llcp_sock = NULL; | 185 | llcp_sock = NULL; |
147 | 186 | ||
148 | sk_for_each(sk, node, &local->sockets.head) { | 187 | sk_for_each(sk, node, &local->sockets.head) { |
149 | llcp_sock = nfc_llcp_sock(sk); | 188 | tmp_sock = nfc_llcp_sock(sk); |
150 | 189 | ||
151 | if (llcp_sock->ssap == ssap && llcp_sock->dsap == dsap) | 190 | if (tmp_sock->ssap == ssap && tmp_sock->dsap == dsap) { |
191 | llcp_sock = tmp_sock; | ||
152 | break; | 192 | break; |
193 | } | ||
153 | } | 194 | } |
154 | 195 | ||
155 | read_unlock(&local->sockets.lock); | 196 | read_unlock(&local->sockets.lock); |
@@ -249,7 +290,12 @@ struct nfc_llcp_sock *nfc_llcp_sock_from_sn(struct nfc_llcp_local *local, | |||
249 | 290 | ||
250 | pr_debug("llcp sock %p\n", tmp_sock); | 291 | pr_debug("llcp sock %p\n", tmp_sock); |
251 | 292 | ||
252 | if (tmp_sock->sk.sk_state != LLCP_LISTEN) | 293 | if (tmp_sock->sk.sk_type == SOCK_STREAM && |
294 | tmp_sock->sk.sk_state != LLCP_LISTEN) | ||
295 | continue; | ||
296 | |||
297 | if (tmp_sock->sk.sk_type == SOCK_DGRAM && | ||
298 | tmp_sock->sk.sk_state != LLCP_BOUND) | ||
253 | continue; | 299 | continue; |
254 | 300 | ||
255 | if (tmp_sock->service_name == NULL || | 301 | if (tmp_sock->service_name == NULL || |
@@ -421,10 +467,9 @@ static u8 nfc_llcp_reserve_sdp_ssap(struct nfc_llcp_local *local) | |||
421 | static int nfc_llcp_build_gb(struct nfc_llcp_local *local) | 467 | static int nfc_llcp_build_gb(struct nfc_llcp_local *local) |
422 | { | 468 | { |
423 | u8 *gb_cur, *version_tlv, version, version_length; | 469 | u8 *gb_cur, *version_tlv, version, version_length; |
424 | u8 *lto_tlv, lto, lto_length; | 470 | u8 *lto_tlv, lto_length; |
425 | u8 *wks_tlv, wks_length; | 471 | u8 *wks_tlv, wks_length; |
426 | u8 *miux_tlv, miux_length; | 472 | u8 *miux_tlv, miux_length; |
427 | __be16 miux; | ||
428 | u8 gb_len = 0; | 473 | u8 gb_len = 0; |
429 | int ret = 0; | 474 | int ret = 0; |
430 | 475 | ||
@@ -433,9 +478,7 @@ static int nfc_llcp_build_gb(struct nfc_llcp_local *local) | |||
433 | 1, &version_length); | 478 | 1, &version_length); |
434 | gb_len += version_length; | 479 | gb_len += version_length; |
435 | 480 | ||
436 | /* 1500 ms */ | 481 | lto_tlv = nfc_llcp_build_tlv(LLCP_TLV_LTO, &local->lto, 1, <o_length); |
437 | lto = 150; | ||
438 | lto_tlv = nfc_llcp_build_tlv(LLCP_TLV_LTO, <o, 1, <o_length); | ||
439 | gb_len += lto_length; | 482 | gb_len += lto_length; |
440 | 483 | ||
441 | pr_debug("Local wks 0x%lx\n", local->local_wks); | 484 | pr_debug("Local wks 0x%lx\n", local->local_wks); |
@@ -443,8 +486,7 @@ static int nfc_llcp_build_gb(struct nfc_llcp_local *local) | |||
443 | &wks_length); | 486 | &wks_length); |
444 | gb_len += wks_length; | 487 | gb_len += wks_length; |
445 | 488 | ||
446 | miux = cpu_to_be16(LLCP_MAX_MIUX); | 489 | miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&local->miux, 0, |
447 | miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0, | ||
448 | &miux_length); | 490 | &miux_length); |
449 | gb_len += miux_length; | 491 | gb_len += miux_length; |
450 | 492 | ||
@@ -610,7 +652,10 @@ static void nfc_llcp_tx_work(struct work_struct *work) | |||
610 | if (skb != NULL) { | 652 | if (skb != NULL) { |
611 | sk = skb->sk; | 653 | sk = skb->sk; |
612 | llcp_sock = nfc_llcp_sock(sk); | 654 | llcp_sock = nfc_llcp_sock(sk); |
613 | if (llcp_sock != NULL) { | 655 | |
656 | if (llcp_sock == NULL && nfc_llcp_ptype(skb) == LLCP_PDU_I) { | ||
657 | nfc_llcp_send_symm(local->dev); | ||
658 | } else { | ||
614 | int ret; | 659 | int ret; |
615 | 660 | ||
616 | pr_debug("Sending pending skb\n"); | 661 | pr_debug("Sending pending skb\n"); |
@@ -629,8 +674,6 @@ static void nfc_llcp_tx_work(struct work_struct *work) | |||
629 | skb_queue_tail(&llcp_sock->tx_pending_queue, | 674 | skb_queue_tail(&llcp_sock->tx_pending_queue, |
630 | skb); | 675 | skb); |
631 | } | 676 | } |
632 | } else { | ||
633 | nfc_llcp_send_symm(local->dev); | ||
634 | } | 677 | } |
635 | } else { | 678 | } else { |
636 | nfc_llcp_send_symm(local->dev); | 679 | nfc_llcp_send_symm(local->dev); |
@@ -704,6 +747,39 @@ static u8 *nfc_llcp_connect_sn(struct sk_buff *skb, size_t *sn_len) | |||
704 | return NULL; | 747 | return NULL; |
705 | } | 748 | } |
706 | 749 | ||
750 | static void nfc_llcp_recv_ui(struct nfc_llcp_local *local, | ||
751 | struct sk_buff *skb) | ||
752 | { | ||
753 | struct nfc_llcp_sock *llcp_sock; | ||
754 | struct nfc_llcp_ui_cb *ui_cb; | ||
755 | u8 dsap, ssap; | ||
756 | |||
757 | dsap = nfc_llcp_dsap(skb); | ||
758 | ssap = nfc_llcp_ssap(skb); | ||
759 | |||
760 | ui_cb = nfc_llcp_ui_skb_cb(skb); | ||
761 | ui_cb->dsap = dsap; | ||
762 | ui_cb->ssap = ssap; | ||
763 | |||
764 | printk("%s %d %d\n", __func__, dsap, ssap); | ||
765 | |||
766 | pr_debug("%d %d\n", dsap, ssap); | ||
767 | |||
768 | /* We're looking for a bound socket, not a client one */ | ||
769 | llcp_sock = nfc_llcp_sock_get(local, dsap, LLCP_SAP_SDP); | ||
770 | if (llcp_sock == NULL || llcp_sock->sk.sk_type != SOCK_DGRAM) | ||
771 | return; | ||
772 | |||
773 | /* There is no sequence with UI frames */ | ||
774 | skb_pull(skb, LLCP_HEADER_SIZE); | ||
775 | if (sock_queue_rcv_skb(&llcp_sock->sk, skb)) { | ||
776 | pr_err("receive queue is full\n"); | ||
777 | skb_queue_head(&llcp_sock->tx_backlog_queue, skb); | ||
778 | } | ||
779 | |||
780 | nfc_llcp_sock_put(llcp_sock); | ||
781 | } | ||
782 | |||
707 | static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, | 783 | static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, |
708 | struct sk_buff *skb) | 784 | struct sk_buff *skb) |
709 | { | 785 | { |
@@ -823,9 +899,6 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, | |||
823 | fail: | 899 | fail: |
824 | /* Send DM */ | 900 | /* Send DM */ |
825 | nfc_llcp_send_dm(local, dsap, ssap, reason); | 901 | nfc_llcp_send_dm(local, dsap, ssap, reason); |
826 | |||
827 | return; | ||
828 | |||
829 | } | 902 | } |
830 | 903 | ||
831 | int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock) | 904 | int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock) |
@@ -953,6 +1026,9 @@ static void nfc_llcp_recv_disc(struct nfc_llcp_local *local, | |||
953 | 1026 | ||
954 | sk = &llcp_sock->sk; | 1027 | sk = &llcp_sock->sk; |
955 | lock_sock(sk); | 1028 | lock_sock(sk); |
1029 | |||
1030 | nfc_llcp_socket_purge(llcp_sock); | ||
1031 | |||
956 | if (sk->sk_state == LLCP_CLOSED) { | 1032 | if (sk->sk_state == LLCP_CLOSED) { |
957 | release_sock(sk); | 1033 | release_sock(sk); |
958 | nfc_llcp_sock_put(llcp_sock); | 1034 | nfc_llcp_sock_put(llcp_sock); |
@@ -1027,7 +1103,7 @@ static void nfc_llcp_recv_dm(struct nfc_llcp_local *local, struct sk_buff *skb) | |||
1027 | } | 1103 | } |
1028 | 1104 | ||
1029 | if (llcp_sock == NULL) { | 1105 | if (llcp_sock == NULL) { |
1030 | pr_err("Invalid DM\n"); | 1106 | pr_debug("Already closed\n"); |
1031 | return; | 1107 | return; |
1032 | } | 1108 | } |
1033 | 1109 | ||
@@ -1038,8 +1114,100 @@ static void nfc_llcp_recv_dm(struct nfc_llcp_local *local, struct sk_buff *skb) | |||
1038 | sk->sk_state_change(sk); | 1114 | sk->sk_state_change(sk); |
1039 | 1115 | ||
1040 | nfc_llcp_sock_put(llcp_sock); | 1116 | nfc_llcp_sock_put(llcp_sock); |
1117 | } | ||
1041 | 1118 | ||
1042 | return; | 1119 | static void nfc_llcp_recv_snl(struct nfc_llcp_local *local, |
1120 | struct sk_buff *skb) | ||
1121 | { | ||
1122 | struct nfc_llcp_sock *llcp_sock; | ||
1123 | u8 dsap, ssap, *tlv, type, length, tid, sap; | ||
1124 | u16 tlv_len, offset; | ||
1125 | char *service_name; | ||
1126 | size_t service_name_len; | ||
1127 | |||
1128 | dsap = nfc_llcp_dsap(skb); | ||
1129 | ssap = nfc_llcp_ssap(skb); | ||
1130 | |||
1131 | pr_debug("%d %d\n", dsap, ssap); | ||
1132 | |||
1133 | if (dsap != LLCP_SAP_SDP || ssap != LLCP_SAP_SDP) { | ||
1134 | pr_err("Wrong SNL SAP\n"); | ||
1135 | return; | ||
1136 | } | ||
1137 | |||
1138 | tlv = &skb->data[LLCP_HEADER_SIZE]; | ||
1139 | tlv_len = skb->len - LLCP_HEADER_SIZE; | ||
1140 | offset = 0; | ||
1141 | |||
1142 | while (offset < tlv_len) { | ||
1143 | type = tlv[0]; | ||
1144 | length = tlv[1]; | ||
1145 | |||
1146 | switch (type) { | ||
1147 | case LLCP_TLV_SDREQ: | ||
1148 | tid = tlv[2]; | ||
1149 | service_name = (char *) &tlv[3]; | ||
1150 | service_name_len = length - 1; | ||
1151 | |||
1152 | pr_debug("Looking for %.16s\n", service_name); | ||
1153 | |||
1154 | if (service_name_len == strlen("urn:nfc:sn:sdp") && | ||
1155 | !strncmp(service_name, "urn:nfc:sn:sdp", | ||
1156 | service_name_len)) { | ||
1157 | sap = 1; | ||
1158 | goto send_snl; | ||
1159 | } | ||
1160 | |||
1161 | llcp_sock = nfc_llcp_sock_from_sn(local, service_name, | ||
1162 | service_name_len); | ||
1163 | if (!llcp_sock) { | ||
1164 | sap = 0; | ||
1165 | goto send_snl; | ||
1166 | } | ||
1167 | |||
1168 | /* | ||
1169 | * We found a socket but its ssap has not been reserved | ||
1170 | * yet. We need to assign it for good and send a reply. | ||
1171 | * The ssap will be freed when the socket is closed. | ||
1172 | */ | ||
1173 | if (llcp_sock->ssap == LLCP_SDP_UNBOUND) { | ||
1174 | atomic_t *client_count; | ||
1175 | |||
1176 | sap = nfc_llcp_reserve_sdp_ssap(local); | ||
1177 | |||
1178 | pr_debug("Reserving %d\n", sap); | ||
1179 | |||
1180 | if (sap == LLCP_SAP_MAX) { | ||
1181 | sap = 0; | ||
1182 | goto send_snl; | ||
1183 | } | ||
1184 | |||
1185 | client_count = | ||
1186 | &local->local_sdp_cnt[sap - | ||
1187 | LLCP_WKS_NUM_SAP]; | ||
1188 | |||
1189 | atomic_inc(client_count); | ||
1190 | |||
1191 | llcp_sock->ssap = sap; | ||
1192 | llcp_sock->reserved_ssap = sap; | ||
1193 | } else { | ||
1194 | sap = llcp_sock->ssap; | ||
1195 | } | ||
1196 | |||
1197 | pr_debug("%p %d\n", llcp_sock, sap); | ||
1198 | |||
1199 | send_snl: | ||
1200 | nfc_llcp_send_snl(local, tid, sap); | ||
1201 | break; | ||
1202 | |||
1203 | default: | ||
1204 | pr_err("Invalid SNL tlv value 0x%x\n", type); | ||
1205 | break; | ||
1206 | } | ||
1207 | |||
1208 | offset += length + 2; | ||
1209 | tlv += length + 2; | ||
1210 | } | ||
1043 | } | 1211 | } |
1044 | 1212 | ||
1045 | static void nfc_llcp_rx_work(struct work_struct *work) | 1213 | static void nfc_llcp_rx_work(struct work_struct *work) |
@@ -1072,6 +1240,11 @@ static void nfc_llcp_rx_work(struct work_struct *work) | |||
1072 | pr_debug("SYMM\n"); | 1240 | pr_debug("SYMM\n"); |
1073 | break; | 1241 | break; |
1074 | 1242 | ||
1243 | case LLCP_PDU_UI: | ||
1244 | pr_debug("UI\n"); | ||
1245 | nfc_llcp_recv_ui(local, skb); | ||
1246 | break; | ||
1247 | |||
1075 | case LLCP_PDU_CONNECT: | 1248 | case LLCP_PDU_CONNECT: |
1076 | pr_debug("CONNECT\n"); | 1249 | pr_debug("CONNECT\n"); |
1077 | nfc_llcp_recv_connect(local, skb); | 1250 | nfc_llcp_recv_connect(local, skb); |
@@ -1092,6 +1265,11 @@ static void nfc_llcp_rx_work(struct work_struct *work) | |||
1092 | nfc_llcp_recv_dm(local, skb); | 1265 | nfc_llcp_recv_dm(local, skb); |
1093 | break; | 1266 | break; |
1094 | 1267 | ||
1268 | case LLCP_PDU_SNL: | ||
1269 | pr_debug("SNL\n"); | ||
1270 | nfc_llcp_recv_snl(local, skb); | ||
1271 | break; | ||
1272 | |||
1095 | case LLCP_PDU_I: | 1273 | case LLCP_PDU_I: |
1096 | case LLCP_PDU_RR: | 1274 | case LLCP_PDU_RR: |
1097 | case LLCP_PDU_RNR: | 1275 | case LLCP_PDU_RNR: |
@@ -1104,8 +1282,6 @@ static void nfc_llcp_rx_work(struct work_struct *work) | |||
1104 | schedule_work(&local->tx_work); | 1282 | schedule_work(&local->tx_work); |
1105 | kfree_skb(local->rx_pending); | 1283 | kfree_skb(local->rx_pending); |
1106 | local->rx_pending = NULL; | 1284 | local->rx_pending = NULL; |
1107 | |||
1108 | return; | ||
1109 | } | 1285 | } |
1110 | 1286 | ||
1111 | void nfc_llcp_recv(void *data, struct sk_buff *skb, int err) | 1287 | void nfc_llcp_recv(void *data, struct sk_buff *skb, int err) |
@@ -1121,8 +1297,6 @@ void nfc_llcp_recv(void *data, struct sk_buff *skb, int err) | |||
1121 | local->rx_pending = skb_get(skb); | 1297 | local->rx_pending = skb_get(skb); |
1122 | del_timer(&local->link_timer); | 1298 | del_timer(&local->link_timer); |
1123 | schedule_work(&local->rx_work); | 1299 | schedule_work(&local->rx_work); |
1124 | |||
1125 | return; | ||
1126 | } | 1300 | } |
1127 | 1301 | ||
1128 | int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb) | 1302 | int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb) |
@@ -1205,6 +1379,10 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) | |||
1205 | rwlock_init(&local->connecting_sockets.lock); | 1379 | rwlock_init(&local->connecting_sockets.lock); |
1206 | rwlock_init(&local->raw_sockets.lock); | 1380 | rwlock_init(&local->raw_sockets.lock); |
1207 | 1381 | ||
1382 | local->lto = 150; /* 1500 ms */ | ||
1383 | local->rw = LLCP_MAX_RW; | ||
1384 | local->miux = cpu_to_be16(LLCP_MAX_MIUX); | ||
1385 | |||
1208 | nfc_llcp_build_gb(local); | 1386 | nfc_llcp_build_gb(local); |
1209 | 1387 | ||
1210 | 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 fdb2d24e60bd..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 */ |
@@ -124,6 +127,13 @@ struct nfc_llcp_sock { | |||
124 | struct sock *parent; | 127 | struct sock *parent; |
125 | }; | 128 | }; |
126 | 129 | ||
130 | struct nfc_llcp_ui_cb { | ||
131 | __u8 dsap; | ||
132 | __u8 ssap; | ||
133 | }; | ||
134 | |||
135 | #define nfc_llcp_ui_skb_cb(__skb) ((struct nfc_llcp_ui_cb *)&((__skb)->cb[0])) | ||
136 | |||
127 | #define nfc_llcp_sock(sk) ((struct nfc_llcp_sock *) (sk)) | 137 | #define nfc_llcp_sock(sk) ((struct nfc_llcp_sock *) (sk)) |
128 | #define nfc_llcp_dev(sk) (nfc_llcp_sock((sk))->dev) | 138 | #define nfc_llcp_dev(sk) (nfc_llcp_sock((sk))->dev) |
129 | 139 | ||
@@ -209,10 +219,13 @@ int nfc_llcp_disconnect(struct nfc_llcp_sock *sock); | |||
209 | int nfc_llcp_send_symm(struct nfc_dev *dev); | 219 | int nfc_llcp_send_symm(struct nfc_dev *dev); |
210 | int nfc_llcp_send_connect(struct nfc_llcp_sock *sock); | 220 | int nfc_llcp_send_connect(struct nfc_llcp_sock *sock); |
211 | int nfc_llcp_send_cc(struct nfc_llcp_sock *sock); | 221 | int nfc_llcp_send_cc(struct nfc_llcp_sock *sock); |
222 | int nfc_llcp_send_snl(struct nfc_llcp_local *local, u8 tid, u8 sap); | ||
212 | int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason); | 223 | int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason); |
213 | int nfc_llcp_send_disconnect(struct nfc_llcp_sock *sock); | 224 | int nfc_llcp_send_disconnect(struct nfc_llcp_sock *sock); |
214 | int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, | 225 | int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, |
215 | struct msghdr *msg, size_t len); | 226 | struct msghdr *msg, size_t len); |
227 | int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap, | ||
228 | struct msghdr *msg, size_t len); | ||
216 | int nfc_llcp_send_rr(struct nfc_llcp_sock *sock); | 229 | int nfc_llcp_send_rr(struct nfc_llcp_sock *sock); |
217 | 230 | ||
218 | /* Socket API */ | 231 | /* Socket API */ |
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c index 63e4cdc92376..0fa1e92ceac8 100644 --- a/net/nfc/llcp/sock.c +++ b/net/nfc/llcp/sock.c | |||
@@ -205,8 +205,8 @@ static int llcp_sock_listen(struct socket *sock, int backlog) | |||
205 | 205 | ||
206 | lock_sock(sk); | 206 | lock_sock(sk); |
207 | 207 | ||
208 | if ((sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM) | 208 | if ((sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM) || |
209 | || sk->sk_state != LLCP_BOUND) { | 209 | sk->sk_state != LLCP_BOUND) { |
210 | ret = -EBADFD; | 210 | ret = -EBADFD; |
211 | goto error; | 211 | goto error; |
212 | } | 212 | } |
@@ -608,6 +608,25 @@ static int llcp_sock_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
608 | 608 | ||
609 | lock_sock(sk); | 609 | lock_sock(sk); |
610 | 610 | ||
611 | if (sk->sk_type == SOCK_DGRAM) { | ||
612 | struct sockaddr_nfc_llcp *addr = | ||
613 | (struct sockaddr_nfc_llcp *)msg->msg_name; | ||
614 | |||
615 | if (msg->msg_namelen < sizeof(*addr)) { | ||
616 | release_sock(sk); | ||
617 | |||
618 | pr_err("Invalid socket address length %d\n", | ||
619 | msg->msg_namelen); | ||
620 | |||
621 | return -EINVAL; | ||
622 | } | ||
623 | |||
624 | release_sock(sk); | ||
625 | |||
626 | return nfc_llcp_send_ui_frame(llcp_sock, addr->dsap, addr->ssap, | ||
627 | msg, len); | ||
628 | } | ||
629 | |||
611 | if (sk->sk_state != LLCP_CONNECTED) { | 630 | if (sk->sk_state != LLCP_CONNECTED) { |
612 | release_sock(sk); | 631 | release_sock(sk); |
613 | return -ENOTCONN; | 632 | return -ENOTCONN; |
@@ -663,11 +682,28 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
663 | return -EFAULT; | 682 | return -EFAULT; |
664 | } | 683 | } |
665 | 684 | ||
685 | if (sk->sk_type == SOCK_DGRAM && msg->msg_name) { | ||
686 | struct nfc_llcp_ui_cb *ui_cb = nfc_llcp_ui_skb_cb(skb); | ||
687 | struct sockaddr_nfc_llcp sockaddr; | ||
688 | |||
689 | pr_debug("Datagram socket %d %d\n", ui_cb->dsap, ui_cb->ssap); | ||
690 | |||
691 | sockaddr.sa_family = AF_NFC; | ||
692 | sockaddr.nfc_protocol = NFC_PROTO_NFC_DEP; | ||
693 | sockaddr.dsap = ui_cb->dsap; | ||
694 | sockaddr.ssap = ui_cb->ssap; | ||
695 | |||
696 | memcpy(msg->msg_name, &sockaddr, sizeof(sockaddr)); | ||
697 | msg->msg_namelen = sizeof(sockaddr); | ||
698 | } | ||
699 | |||
666 | /* Mark read part of skb as used */ | 700 | /* Mark read part of skb as used */ |
667 | if (!(flags & MSG_PEEK)) { | 701 | if (!(flags & MSG_PEEK)) { |
668 | 702 | ||
669 | /* SOCK_STREAM: re-queue skb if it contains unreceived data */ | 703 | /* SOCK_STREAM: re-queue skb if it contains unreceived data */ |
670 | if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_RAW) { | 704 | if (sk->sk_type == SOCK_STREAM || |
705 | sk->sk_type == SOCK_DGRAM || | ||
706 | sk->sk_type == SOCK_RAW) { | ||
671 | skb_pull(skb, copied); | 707 | skb_pull(skb, copied); |
672 | if (skb->len) { | 708 | if (skb->len) { |
673 | skb_queue_head(&sk->sk_receive_queue, skb); | 709 | skb_queue_head(&sk->sk_receive_queue, skb); |
diff --git a/net/nfc/nci/Kconfig b/net/nfc/nci/Kconfig index decdc49b26d8..6d69b5f0f19b 100644 --- a/net/nfc/nci/Kconfig +++ b/net/nfc/nci/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config NFC_NCI | 1 | config NFC_NCI |
2 | depends on NFC && EXPERIMENTAL | 2 | depends on NFC |
3 | tristate "NCI protocol support (EXPERIMENTAL)" | 3 | tristate "NCI protocol support" |
4 | default n | 4 | default n |
5 | help | 5 | help |
6 | NCI (NFC Controller Interface) is a communication protocol between | 6 | NCI (NFC Controller Interface) is a communication protocol between |
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c index acf9abb7d99b..5f98dc1bf039 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c | |||
@@ -205,10 +205,10 @@ static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt) | |||
205 | cmd.num_disc_configs = 0; | 205 | cmd.num_disc_configs = 0; |
206 | 206 | ||
207 | if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) && | 207 | if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) && |
208 | (protocols & NFC_PROTO_JEWEL_MASK | 208 | (protocols & NFC_PROTO_JEWEL_MASK || |
209 | || protocols & NFC_PROTO_MIFARE_MASK | 209 | protocols & NFC_PROTO_MIFARE_MASK || |
210 | || protocols & NFC_PROTO_ISO14443_MASK | 210 | protocols & NFC_PROTO_ISO14443_MASK || |
211 | || protocols & NFC_PROTO_NFC_DEP_MASK)) { | 211 | protocols & NFC_PROTO_NFC_DEP_MASK)) { |
212 | cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode = | 212 | cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode = |
213 | NCI_NFC_A_PASSIVE_POLL_MODE; | 213 | NCI_NFC_A_PASSIVE_POLL_MODE; |
214 | cmd.disc_configs[cmd.num_disc_configs].frequency = 1; | 214 | cmd.disc_configs[cmd.num_disc_configs].frequency = 1; |
@@ -224,8 +224,8 @@ static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt) | |||
224 | } | 224 | } |
225 | 225 | ||
226 | if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) && | 226 | if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) && |
227 | (protocols & NFC_PROTO_FELICA_MASK | 227 | (protocols & NFC_PROTO_FELICA_MASK || |
228 | || protocols & NFC_PROTO_NFC_DEP_MASK)) { | 228 | protocols & NFC_PROTO_NFC_DEP_MASK)) { |
229 | cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode = | 229 | cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode = |
230 | NCI_NFC_F_PASSIVE_POLL_MODE; | 230 | NCI_NFC_F_PASSIVE_POLL_MODE; |
231 | cmd.disc_configs[cmd.num_disc_configs].frequency = 1; | 231 | cmd.disc_configs[cmd.num_disc_configs].frequency = 1; |
@@ -414,13 +414,13 @@ static int nci_set_local_general_bytes(struct nfc_dev *nfc_dev) | |||
414 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); | 414 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); |
415 | struct nci_set_config_param param; | 415 | struct nci_set_config_param param; |
416 | __u8 local_gb[NFC_MAX_GT_LEN]; | 416 | __u8 local_gb[NFC_MAX_GT_LEN]; |
417 | int i, rc = 0; | 417 | int i; |
418 | 418 | ||
419 | param.val = nfc_get_local_general_bytes(nfc_dev, ¶m.len); | 419 | param.val = nfc_get_local_general_bytes(nfc_dev, ¶m.len); |
420 | if ((param.val == NULL) || (param.len == 0)) | 420 | if ((param.val == NULL) || (param.len == 0)) |
421 | return rc; | 421 | return 0; |
422 | 422 | ||
423 | if (param.len > NCI_MAX_PARAM_LEN) | 423 | if (param.len > NFC_MAX_GT_LEN) |
424 | return -EINVAL; | 424 | return -EINVAL; |
425 | 425 | ||
426 | for (i = 0; i < param.len; i++) | 426 | for (i = 0; i < param.len; i++) |
@@ -429,10 +429,8 @@ static int nci_set_local_general_bytes(struct nfc_dev *nfc_dev) | |||
429 | param.id = NCI_PN_ATR_REQ_GEN_BYTES; | 429 | param.id = NCI_PN_ATR_REQ_GEN_BYTES; |
430 | param.val = local_gb; | 430 | param.val = local_gb; |
431 | 431 | ||
432 | rc = nci_request(ndev, nci_set_config_req, (unsigned long)¶m, | 432 | return nci_request(ndev, nci_set_config_req, (unsigned long)¶m, |
433 | msecs_to_jiffies(NCI_SET_CONFIG_TIMEOUT)); | 433 | msecs_to_jiffies(NCI_SET_CONFIG_TIMEOUT)); |
434 | |||
435 | return rc; | ||
436 | } | 434 | } |
437 | 435 | ||
438 | static int nci_start_poll(struct nfc_dev *nfc_dev, | 436 | static int nci_start_poll(struct nfc_dev *nfc_dev, |
@@ -579,7 +577,6 @@ static void nci_deactivate_target(struct nfc_dev *nfc_dev, | |||
579 | } | 577 | } |
580 | } | 578 | } |
581 | 579 | ||
582 | |||
583 | static int nci_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, | 580 | static int nci_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, |
584 | __u8 comm_mode, __u8 *gb, size_t gb_len) | 581 | __u8 comm_mode, __u8 *gb, size_t gb_len) |
585 | { | 582 | { |
@@ -806,8 +803,8 @@ int nci_recv_frame(struct sk_buff *skb) | |||
806 | 803 | ||
807 | pr_debug("len %d\n", skb->len); | 804 | pr_debug("len %d\n", skb->len); |
808 | 805 | ||
809 | if (!ndev || (!test_bit(NCI_UP, &ndev->flags) | 806 | if (!ndev || (!test_bit(NCI_UP, &ndev->flags) && |
810 | && !test_bit(NCI_INIT, &ndev->flags))) { | 807 | !test_bit(NCI_INIT, &ndev->flags))) { |
811 | kfree_skb(skb); | 808 | kfree_skb(skb); |
812 | return -ENXIO; | 809 | return -ENXIO; |
813 | } | 810 | } |
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 | ||
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); | |||
56 | int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len); | 56 | int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len); |
57 | u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len); | 57 | u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len); |
58 | int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb); | 58 | int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb); |
59 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev); | ||
59 | int __init nfc_llcp_init(void); | 60 | int __init nfc_llcp_init(void); |
60 | void nfc_llcp_exit(void); | 61 | void 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 | ||
101 | static inline struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev) | ||
102 | { | ||
103 | return NULL; | ||
104 | } | ||
105 | |||
100 | static inline int nfc_llcp_init(void) | 106 | static inline int nfc_llcp_init(void) |
101 | { | 107 | { |
102 | return 0; | 108 | return 0; |
diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c index 8b8a6a2b2bad..313bf1bc848a 100644 --- a/net/nfc/rawsock.c +++ b/net/nfc/rawsock.c | |||
@@ -256,7 +256,6 @@ static int rawsock_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
256 | return rc ? : copied; | 256 | return rc ? : copied; |
257 | } | 257 | } |
258 | 258 | ||
259 | |||
260 | static const struct proto_ops rawsock_ops = { | 259 | static const struct proto_ops rawsock_ops = { |
261 | .family = PF_NFC, | 260 | .family = PF_NFC, |
262 | .owner = THIS_MODULE, | 261 | .owner = THIS_MODULE, |