diff options
Diffstat (limited to 'net/nfc')
-rw-r--r-- | net/nfc/core.c | 119 | ||||
-rw-r--r-- | net/nfc/hci/core.c | 13 | ||||
-rw-r--r-- | net/nfc/hci/shdlc.c | 6 | ||||
-rw-r--r-- | net/nfc/llcp/commands.c | 54 | ||||
-rw-r--r-- | net/nfc/llcp/llcp.c | 421 | ||||
-rw-r--r-- | net/nfc/llcp/llcp.h | 26 | ||||
-rw-r--r-- | net/nfc/llcp/sock.c | 47 | ||||
-rw-r--r-- | net/nfc/nci/core.c | 15 | ||||
-rw-r--r-- | net/nfc/netlink.c | 81 | ||||
-rw-r--r-- | net/nfc/nfc.h | 12 |
10 files changed, 530 insertions, 264 deletions
diff --git a/net/nfc/core.c b/net/nfc/core.c index 9f6ce011d35d..4177bb5104b9 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c | |||
@@ -121,14 +121,14 @@ error: | |||
121 | * The device remains polling for targets until a target is found or | 121 | * The device remains polling for targets until a target is found or |
122 | * the nfc_stop_poll function is called. | 122 | * the nfc_stop_poll function is called. |
123 | */ | 123 | */ |
124 | int nfc_start_poll(struct nfc_dev *dev, u32 protocols) | 124 | int nfc_start_poll(struct nfc_dev *dev, u32 im_protocols, u32 tm_protocols) |
125 | { | 125 | { |
126 | int rc; | 126 | int rc; |
127 | 127 | ||
128 | pr_debug("dev_name=%s protocols=0x%x\n", | 128 | pr_debug("dev_name %s initiator protocols 0x%x target protocols 0x%x\n", |
129 | dev_name(&dev->dev), protocols); | 129 | dev_name(&dev->dev), im_protocols, tm_protocols); |
130 | 130 | ||
131 | if (!protocols) | 131 | if (!im_protocols && !tm_protocols) |
132 | return -EINVAL; | 132 | return -EINVAL; |
133 | 133 | ||
134 | device_lock(&dev->dev); | 134 | device_lock(&dev->dev); |
@@ -143,9 +143,11 @@ int nfc_start_poll(struct nfc_dev *dev, u32 protocols) | |||
143 | goto error; | 143 | goto error; |
144 | } | 144 | } |
145 | 145 | ||
146 | rc = dev->ops->start_poll(dev, protocols); | 146 | rc = dev->ops->start_poll(dev, im_protocols, tm_protocols); |
147 | if (!rc) | 147 | if (!rc) { |
148 | dev->polling = true; | 148 | dev->polling = true; |
149 | dev->rf_mode = NFC_RF_NONE; | ||
150 | } | ||
149 | 151 | ||
150 | error: | 152 | error: |
151 | device_unlock(&dev->dev); | 153 | device_unlock(&dev->dev); |
@@ -235,8 +237,10 @@ int nfc_dep_link_up(struct nfc_dev *dev, int target_index, u8 comm_mode) | |||
235 | } | 237 | } |
236 | 238 | ||
237 | rc = dev->ops->dep_link_up(dev, target, comm_mode, gb, gb_len); | 239 | rc = dev->ops->dep_link_up(dev, target, comm_mode, gb, gb_len); |
238 | if (!rc) | 240 | if (!rc) { |
239 | dev->active_target = target; | 241 | dev->active_target = target; |
242 | dev->rf_mode = NFC_RF_INITIATOR; | ||
243 | } | ||
240 | 244 | ||
241 | error: | 245 | error: |
242 | device_unlock(&dev->dev); | 246 | device_unlock(&dev->dev); |
@@ -264,11 +268,6 @@ int nfc_dep_link_down(struct nfc_dev *dev) | |||
264 | goto error; | 268 | goto error; |
265 | } | 269 | } |
266 | 270 | ||
267 | if (dev->dep_rf_mode == NFC_RF_TARGET) { | ||
268 | rc = -EOPNOTSUPP; | ||
269 | goto error; | ||
270 | } | ||
271 | |||
272 | rc = dev->ops->dep_link_down(dev); | 271 | rc = dev->ops->dep_link_down(dev); |
273 | if (!rc) { | 272 | if (!rc) { |
274 | dev->dep_link_up = false; | 273 | dev->dep_link_up = false; |
@@ -286,7 +285,6 @@ int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx, | |||
286 | u8 comm_mode, u8 rf_mode) | 285 | u8 comm_mode, u8 rf_mode) |
287 | { | 286 | { |
288 | dev->dep_link_up = true; | 287 | dev->dep_link_up = true; |
289 | dev->dep_rf_mode = rf_mode; | ||
290 | 288 | ||
291 | nfc_llcp_mac_is_up(dev, target_idx, comm_mode, rf_mode); | 289 | nfc_llcp_mac_is_up(dev, target_idx, comm_mode, rf_mode); |
292 | 290 | ||
@@ -330,6 +328,7 @@ int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol) | |||
330 | rc = dev->ops->activate_target(dev, target, protocol); | 328 | rc = dev->ops->activate_target(dev, target, protocol); |
331 | if (!rc) { | 329 | if (!rc) { |
332 | dev->active_target = target; | 330 | dev->active_target = target; |
331 | dev->rf_mode = NFC_RF_INITIATOR; | ||
333 | 332 | ||
334 | if (dev->ops->check_presence) | 333 | if (dev->ops->check_presence) |
335 | mod_timer(&dev->check_pres_timer, jiffies + | 334 | mod_timer(&dev->check_pres_timer, jiffies + |
@@ -409,27 +408,30 @@ int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, struct sk_buff *skb, | |||
409 | goto error; | 408 | goto error; |
410 | } | 409 | } |
411 | 410 | ||
412 | if (dev->active_target == NULL) { | 411 | if (dev->rf_mode == NFC_RF_INITIATOR && dev->active_target != NULL) { |
413 | rc = -ENOTCONN; | 412 | if (dev->active_target->idx != target_idx) { |
414 | kfree_skb(skb); | 413 | rc = -EADDRNOTAVAIL; |
415 | goto error; | 414 | kfree_skb(skb); |
416 | } | 415 | goto error; |
416 | } | ||
417 | 417 | ||
418 | if (dev->active_target->idx != target_idx) { | 418 | if (dev->ops->check_presence) |
419 | rc = -EADDRNOTAVAIL; | 419 | del_timer_sync(&dev->check_pres_timer); |
420 | |||
421 | rc = dev->ops->im_transceive(dev, dev->active_target, skb, cb, | ||
422 | cb_context); | ||
423 | |||
424 | if (!rc && dev->ops->check_presence) | ||
425 | mod_timer(&dev->check_pres_timer, jiffies + | ||
426 | msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); | ||
427 | } else if (dev->rf_mode == NFC_RF_TARGET && dev->ops->tm_send != NULL) { | ||
428 | rc = dev->ops->tm_send(dev, skb); | ||
429 | } else { | ||
430 | rc = -ENOTCONN; | ||
420 | kfree_skb(skb); | 431 | kfree_skb(skb); |
421 | goto error; | 432 | goto error; |
422 | } | 433 | } |
423 | 434 | ||
424 | if (dev->ops->check_presence) | ||
425 | del_timer_sync(&dev->check_pres_timer); | ||
426 | |||
427 | rc = dev->ops->data_exchange(dev, dev->active_target, skb, cb, | ||
428 | cb_context); | ||
429 | |||
430 | if (!rc && dev->ops->check_presence) | ||
431 | mod_timer(&dev->check_pres_timer, jiffies + | ||
432 | msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); | ||
433 | 435 | ||
434 | error: | 436 | error: |
435 | device_unlock(&dev->dev); | 437 | device_unlock(&dev->dev); |
@@ -447,6 +449,63 @@ int nfc_set_remote_general_bytes(struct nfc_dev *dev, u8 *gb, u8 gb_len) | |||
447 | } | 449 | } |
448 | EXPORT_SYMBOL(nfc_set_remote_general_bytes); | 450 | EXPORT_SYMBOL(nfc_set_remote_general_bytes); |
449 | 451 | ||
452 | u8 *nfc_get_local_general_bytes(struct nfc_dev *dev, size_t *gb_len) | ||
453 | { | ||
454 | pr_debug("dev_name=%s\n", dev_name(&dev->dev)); | ||
455 | |||
456 | return nfc_llcp_general_bytes(dev, gb_len); | ||
457 | } | ||
458 | EXPORT_SYMBOL(nfc_get_local_general_bytes); | ||
459 | |||
460 | int nfc_tm_data_received(struct nfc_dev *dev, struct sk_buff *skb) | ||
461 | { | ||
462 | /* Only LLCP target mode for now */ | ||
463 | if (dev->dep_link_up == false) { | ||
464 | kfree_skb(skb); | ||
465 | return -ENOLINK; | ||
466 | } | ||
467 | |||
468 | return nfc_llcp_data_received(dev, skb); | ||
469 | } | ||
470 | EXPORT_SYMBOL(nfc_tm_data_received); | ||
471 | |||
472 | int nfc_tm_activated(struct nfc_dev *dev, u32 protocol, u8 comm_mode, | ||
473 | u8 *gb, size_t gb_len) | ||
474 | { | ||
475 | int rc; | ||
476 | |||
477 | device_lock(&dev->dev); | ||
478 | |||
479 | dev->polling = false; | ||
480 | |||
481 | if (gb != NULL) { | ||
482 | rc = nfc_set_remote_general_bytes(dev, gb, gb_len); | ||
483 | if (rc < 0) | ||
484 | goto out; | ||
485 | } | ||
486 | |||
487 | dev->rf_mode = NFC_RF_TARGET; | ||
488 | |||
489 | if (protocol == NFC_PROTO_NFC_DEP_MASK) | ||
490 | nfc_dep_link_is_up(dev, 0, comm_mode, NFC_RF_TARGET); | ||
491 | |||
492 | rc = nfc_genl_tm_activated(dev, protocol); | ||
493 | |||
494 | out: | ||
495 | device_unlock(&dev->dev); | ||
496 | |||
497 | return rc; | ||
498 | } | ||
499 | EXPORT_SYMBOL(nfc_tm_activated); | ||
500 | |||
501 | int nfc_tm_deactivated(struct nfc_dev *dev) | ||
502 | { | ||
503 | dev->dep_link_up = false; | ||
504 | |||
505 | return nfc_genl_tm_deactivated(dev); | ||
506 | } | ||
507 | EXPORT_SYMBOL(nfc_tm_deactivated); | ||
508 | |||
450 | /** | 509 | /** |
451 | * nfc_alloc_send_skb - allocate a skb for data exchange responses | 510 | * nfc_alloc_send_skb - allocate a skb for data exchange responses |
452 | * | 511 | * |
@@ -678,7 +737,7 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, | |||
678 | struct nfc_dev *dev; | 737 | struct nfc_dev *dev; |
679 | 738 | ||
680 | if (!ops->start_poll || !ops->stop_poll || !ops->activate_target || | 739 | if (!ops->start_poll || !ops->stop_poll || !ops->activate_target || |
681 | !ops->deactivate_target || !ops->data_exchange) | 740 | !ops->deactivate_target || !ops->im_transceive) |
682 | return NULL; | 741 | return NULL; |
683 | 742 | ||
684 | if (!supported_protocols) | 743 | if (!supported_protocols) |
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index e1a640d2b588..a8b0b71e8f86 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c | |||
@@ -481,12 +481,13 @@ static int hci_dev_down(struct nfc_dev *nfc_dev) | |||
481 | return 0; | 481 | return 0; |
482 | } | 482 | } |
483 | 483 | ||
484 | static int hci_start_poll(struct nfc_dev *nfc_dev, u32 protocols) | 484 | static int hci_start_poll(struct nfc_dev *nfc_dev, |
485 | u32 im_protocols, u32 tm_protocols) | ||
485 | { | 486 | { |
486 | struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); | 487 | struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); |
487 | 488 | ||
488 | if (hdev->ops->start_poll) | 489 | if (hdev->ops->start_poll) |
489 | return hdev->ops->start_poll(hdev, protocols); | 490 | return hdev->ops->start_poll(hdev, im_protocols, tm_protocols); |
490 | else | 491 | else |
491 | return nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, | 492 | return nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, |
492 | NFC_HCI_EVT_READER_REQUESTED, NULL, 0); | 493 | NFC_HCI_EVT_READER_REQUESTED, NULL, 0); |
@@ -511,9 +512,9 @@ static void hci_deactivate_target(struct nfc_dev *nfc_dev, | |||
511 | { | 512 | { |
512 | } | 513 | } |
513 | 514 | ||
514 | static int hci_data_exchange(struct nfc_dev *nfc_dev, struct nfc_target *target, | 515 | static int hci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target, |
515 | struct sk_buff *skb, data_exchange_cb_t cb, | 516 | struct sk_buff *skb, data_exchange_cb_t cb, |
516 | void *cb_context) | 517 | void *cb_context) |
517 | { | 518 | { |
518 | struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); | 519 | struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); |
519 | int r; | 520 | int r; |
@@ -579,7 +580,7 @@ static struct nfc_ops hci_nfc_ops = { | |||
579 | .stop_poll = hci_stop_poll, | 580 | .stop_poll = hci_stop_poll, |
580 | .activate_target = hci_activate_target, | 581 | .activate_target = hci_activate_target, |
581 | .deactivate_target = hci_deactivate_target, | 582 | .deactivate_target = hci_deactivate_target, |
582 | .data_exchange = hci_data_exchange, | 583 | .im_transceive = hci_transceive, |
583 | .check_presence = hci_check_presence, | 584 | .check_presence = hci_check_presence, |
584 | }; | 585 | }; |
585 | 586 | ||
diff --git a/net/nfc/hci/shdlc.c b/net/nfc/hci/shdlc.c index 5665dc6d893a..6b836e6242b7 100644 --- a/net/nfc/hci/shdlc.c +++ b/net/nfc/hci/shdlc.c | |||
@@ -765,14 +765,16 @@ static int nfc_shdlc_xmit(struct nfc_hci_dev *hdev, struct sk_buff *skb) | |||
765 | return 0; | 765 | return 0; |
766 | } | 766 | } |
767 | 767 | ||
768 | static int nfc_shdlc_start_poll(struct nfc_hci_dev *hdev, u32 protocols) | 768 | static int nfc_shdlc_start_poll(struct nfc_hci_dev *hdev, |
769 | u32 im_protocols, u32 tm_protocols) | ||
769 | { | 770 | { |
770 | struct nfc_shdlc *shdlc = nfc_hci_get_clientdata(hdev); | 771 | struct nfc_shdlc *shdlc = nfc_hci_get_clientdata(hdev); |
771 | 772 | ||
772 | pr_debug("\n"); | 773 | pr_debug("\n"); |
773 | 774 | ||
774 | if (shdlc->ops->start_poll) | 775 | if (shdlc->ops->start_poll) |
775 | return shdlc->ops->start_poll(shdlc, protocols); | 776 | return shdlc->ops->start_poll(shdlc, |
777 | im_protocols, tm_protocols); | ||
776 | 778 | ||
777 | return 0; | 779 | return 0; |
778 | } | 780 | } |
diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c index bf8ae4f0b90c..b982b5b890d7 100644 --- a/net/nfc/llcp/commands.c +++ b/net/nfc/llcp/commands.c | |||
@@ -51,7 +51,7 @@ static u8 llcp_tlv8(u8 *tlv, u8 type) | |||
51 | return tlv[2]; | 51 | return tlv[2]; |
52 | } | 52 | } |
53 | 53 | ||
54 | static u8 llcp_tlv16(u8 *tlv, u8 type) | 54 | static u16 llcp_tlv16(u8 *tlv, u8 type) |
55 | { | 55 | { |
56 | if (tlv[0] != type || tlv[1] != llcp_tlv_length[tlv[0]]) | 56 | if (tlv[0] != type || tlv[1] != llcp_tlv_length[tlv[0]]) |
57 | return 0; | 57 | return 0; |
@@ -67,7 +67,7 @@ static u8 llcp_tlv_version(u8 *tlv) | |||
67 | 67 | ||
68 | static u16 llcp_tlv_miux(u8 *tlv) | 68 | static u16 llcp_tlv_miux(u8 *tlv) |
69 | { | 69 | { |
70 | return llcp_tlv16(tlv, LLCP_TLV_MIUX) & 0x7f; | 70 | return llcp_tlv16(tlv, LLCP_TLV_MIUX) & 0x7ff; |
71 | } | 71 | } |
72 | 72 | ||
73 | static u16 llcp_tlv_wks(u8 *tlv) | 73 | static u16 llcp_tlv_wks(u8 *tlv) |
@@ -117,8 +117,8 @@ u8 *nfc_llcp_build_tlv(u8 type, u8 *value, u8 value_length, u8 *tlv_length) | |||
117 | return tlv; | 117 | return tlv; |
118 | } | 118 | } |
119 | 119 | ||
120 | int nfc_llcp_parse_tlv(struct nfc_llcp_local *local, | 120 | int nfc_llcp_parse_gb_tlv(struct nfc_llcp_local *local, |
121 | u8 *tlv_array, u16 tlv_array_len) | 121 | u8 *tlv_array, u16 tlv_array_len) |
122 | { | 122 | { |
123 | u8 *tlv = tlv_array, type, length, offset = 0; | 123 | u8 *tlv = tlv_array, type, length, offset = 0; |
124 | 124 | ||
@@ -149,8 +149,45 @@ int nfc_llcp_parse_tlv(struct nfc_llcp_local *local, | |||
149 | case LLCP_TLV_OPT: | 149 | case LLCP_TLV_OPT: |
150 | local->remote_opt = llcp_tlv_opt(tlv); | 150 | local->remote_opt = llcp_tlv_opt(tlv); |
151 | break; | 151 | break; |
152 | default: | ||
153 | pr_err("Invalid gt tlv value 0x%x\n", type); | ||
154 | break; | ||
155 | } | ||
156 | |||
157 | offset += length + 2; | ||
158 | tlv += length + 2; | ||
159 | } | ||
160 | |||
161 | pr_debug("version 0x%x miu %d lto %d opt 0x%x wks 0x%x\n", | ||
162 | local->remote_version, local->remote_miu, | ||
163 | local->remote_lto, local->remote_opt, | ||
164 | local->remote_wks); | ||
165 | |||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock, | ||
170 | u8 *tlv_array, u16 tlv_array_len) | ||
171 | { | ||
172 | u8 *tlv = tlv_array, type, length, offset = 0; | ||
173 | |||
174 | pr_debug("TLV array length %d\n", tlv_array_len); | ||
175 | |||
176 | if (sock == NULL) | ||
177 | return -ENOTCONN; | ||
178 | |||
179 | while (offset < tlv_array_len) { | ||
180 | type = tlv[0]; | ||
181 | length = tlv[1]; | ||
182 | |||
183 | pr_debug("type 0x%x length %d\n", type, length); | ||
184 | |||
185 | switch (type) { | ||
186 | case LLCP_TLV_MIUX: | ||
187 | sock->miu = llcp_tlv_miux(tlv) + 128; | ||
188 | break; | ||
152 | case LLCP_TLV_RW: | 189 | case LLCP_TLV_RW: |
153 | local->remote_rw = llcp_tlv_rw(tlv); | 190 | sock->rw = llcp_tlv_rw(tlv); |
154 | break; | 191 | break; |
155 | case LLCP_TLV_SN: | 192 | case LLCP_TLV_SN: |
156 | break; | 193 | break; |
@@ -163,10 +200,7 @@ int nfc_llcp_parse_tlv(struct nfc_llcp_local *local, | |||
163 | tlv += length + 2; | 200 | tlv += length + 2; |
164 | } | 201 | } |
165 | 202 | ||
166 | pr_debug("version 0x%x miu %d lto %d opt 0x%x wks 0x%x rw %d\n", | 203 | pr_debug("sock %p rw %d miu %d\n", sock, sock->rw, sock->miu); |
167 | local->remote_version, local->remote_miu, | ||
168 | local->remote_lto, local->remote_opt, | ||
169 | local->remote_wks, local->remote_rw); | ||
170 | 204 | ||
171 | return 0; | 205 | return 0; |
172 | } | 206 | } |
@@ -474,7 +508,7 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, | |||
474 | 508 | ||
475 | while (remaining_len > 0) { | 509 | while (remaining_len > 0) { |
476 | 510 | ||
477 | frag_len = min_t(size_t, local->remote_miu, remaining_len); | 511 | frag_len = min_t(size_t, sock->miu, remaining_len); |
478 | 512 | ||
479 | pr_debug("Fragment %zd bytes remaining %zd", | 513 | pr_debug("Fragment %zd bytes remaining %zd", |
480 | frag_len, remaining_len); | 514 | frag_len, remaining_len); |
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c index 42994fac26d6..5d503eeb15a1 100644 --- a/net/nfc/llcp/llcp.c +++ b/net/nfc/llcp/llcp.c | |||
@@ -31,47 +31,41 @@ static u8 llcp_magic[3] = {0x46, 0x66, 0x6d}; | |||
31 | 31 | ||
32 | static struct list_head llcp_devices; | 32 | static struct list_head llcp_devices; |
33 | 33 | ||
34 | static void nfc_llcp_socket_release(struct nfc_llcp_local *local) | 34 | void nfc_llcp_sock_link(struct llcp_sock_list *l, struct sock *sk) |
35 | { | 35 | { |
36 | struct nfc_llcp_sock *parent, *s, *n; | 36 | write_lock(&l->lock); |
37 | struct sock *sk, *parent_sk; | 37 | sk_add_node(sk, &l->head); |
38 | int i; | 38 | write_unlock(&l->lock); |
39 | 39 | } | |
40 | mutex_lock(&local->socket_lock); | ||
41 | |||
42 | for (i = 0; i < LLCP_MAX_SAP; i++) { | ||
43 | parent = local->sockets[i]; | ||
44 | if (parent == NULL) | ||
45 | continue; | ||
46 | |||
47 | /* Release all child sockets */ | ||
48 | list_for_each_entry_safe(s, n, &parent->list, list) { | ||
49 | list_del_init(&s->list); | ||
50 | sk = &s->sk; | ||
51 | |||
52 | lock_sock(sk); | ||
53 | |||
54 | if (sk->sk_state == LLCP_CONNECTED) | ||
55 | nfc_put_device(s->dev); | ||
56 | 40 | ||
57 | sk->sk_state = LLCP_CLOSED; | 41 | void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *sk) |
42 | { | ||
43 | write_lock(&l->lock); | ||
44 | sk_del_node_init(sk); | ||
45 | write_unlock(&l->lock); | ||
46 | } | ||
58 | 47 | ||
59 | release_sock(sk); | 48 | static void nfc_llcp_socket_release(struct nfc_llcp_local *local) |
49 | { | ||
50 | struct sock *sk; | ||
51 | struct hlist_node *node, *tmp; | ||
52 | struct nfc_llcp_sock *llcp_sock; | ||
60 | 53 | ||
61 | sock_orphan(sk); | 54 | write_lock(&local->sockets.lock); |
62 | 55 | ||
63 | s->local = NULL; | 56 | sk_for_each_safe(sk, node, tmp, &local->sockets.head) { |
64 | } | 57 | llcp_sock = nfc_llcp_sock(sk); |
65 | 58 | ||
66 | parent_sk = &parent->sk; | 59 | lock_sock(sk); |
67 | 60 | ||
68 | lock_sock(parent_sk); | 61 | if (sk->sk_state == LLCP_CONNECTED) |
62 | nfc_put_device(llcp_sock->dev); | ||
69 | 63 | ||
70 | if (parent_sk->sk_state == LLCP_LISTEN) { | 64 | if (sk->sk_state == LLCP_LISTEN) { |
71 | struct nfc_llcp_sock *lsk, *n; | 65 | struct nfc_llcp_sock *lsk, *n; |
72 | struct sock *accept_sk; | 66 | struct sock *accept_sk; |
73 | 67 | ||
74 | list_for_each_entry_safe(lsk, n, &parent->accept_queue, | 68 | list_for_each_entry_safe(lsk, n, &llcp_sock->accept_queue, |
75 | accept_queue) { | 69 | accept_queue) { |
76 | accept_sk = &lsk->sk; | 70 | accept_sk = &lsk->sk; |
77 | lock_sock(accept_sk); | 71 | lock_sock(accept_sk); |
@@ -83,24 +77,53 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local) | |||
83 | release_sock(accept_sk); | 77 | release_sock(accept_sk); |
84 | 78 | ||
85 | sock_orphan(accept_sk); | 79 | sock_orphan(accept_sk); |
86 | |||
87 | lsk->local = NULL; | ||
88 | } | 80 | } |
89 | } | 81 | } |
90 | 82 | ||
91 | if (parent_sk->sk_state == LLCP_CONNECTED) | 83 | sk->sk_state = LLCP_CLOSED; |
92 | nfc_put_device(parent->dev); | ||
93 | |||
94 | parent_sk->sk_state = LLCP_CLOSED; | ||
95 | 84 | ||
96 | release_sock(parent_sk); | 85 | release_sock(sk); |
97 | 86 | ||
98 | sock_orphan(parent_sk); | 87 | sock_orphan(sk); |
99 | 88 | ||
100 | parent->local = NULL; | 89 | sk_del_node_init(sk); |
101 | } | 90 | } |
102 | 91 | ||
103 | mutex_unlock(&local->socket_lock); | 92 | write_unlock(&local->sockets.lock); |
93 | } | ||
94 | |||
95 | struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local) | ||
96 | { | ||
97 | kref_get(&local->ref); | ||
98 | |||
99 | return local; | ||
100 | } | ||
101 | |||
102 | static void local_release(struct kref *ref) | ||
103 | { | ||
104 | struct nfc_llcp_local *local; | ||
105 | |||
106 | local = container_of(ref, struct nfc_llcp_local, ref); | ||
107 | |||
108 | list_del(&local->list); | ||
109 | nfc_llcp_socket_release(local); | ||
110 | del_timer_sync(&local->link_timer); | ||
111 | skb_queue_purge(&local->tx_queue); | ||
112 | destroy_workqueue(local->tx_wq); | ||
113 | destroy_workqueue(local->rx_wq); | ||
114 | destroy_workqueue(local->timeout_wq); | ||
115 | kfree_skb(local->rx_pending); | ||
116 | kfree(local); | ||
117 | } | ||
118 | |||
119 | int nfc_llcp_local_put(struct nfc_llcp_local *local) | ||
120 | { | ||
121 | WARN_ON(local == NULL); | ||
122 | |||
123 | if (local == NULL) | ||
124 | return 0; | ||
125 | |||
126 | return kref_put(&local->ref, local_release); | ||
104 | } | 127 | } |
105 | 128 | ||
106 | static void nfc_llcp_clear_sdp(struct nfc_llcp_local *local) | 129 | static void nfc_llcp_clear_sdp(struct nfc_llcp_local *local) |
@@ -384,31 +407,9 @@ int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len) | |||
384 | return -EINVAL; | 407 | return -EINVAL; |
385 | } | 408 | } |
386 | 409 | ||
387 | return nfc_llcp_parse_tlv(local, | 410 | return nfc_llcp_parse_gb_tlv(local, |
388 | &local->remote_gb[3], | 411 | &local->remote_gb[3], |
389 | local->remote_gb_len - 3); | 412 | local->remote_gb_len - 3); |
390 | } | ||
391 | |||
392 | static void nfc_llcp_tx_work(struct work_struct *work) | ||
393 | { | ||
394 | struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, | ||
395 | tx_work); | ||
396 | struct sk_buff *skb; | ||
397 | |||
398 | skb = skb_dequeue(&local->tx_queue); | ||
399 | if (skb != NULL) { | ||
400 | pr_debug("Sending pending skb\n"); | ||
401 | print_hex_dump(KERN_DEBUG, "LLCP Tx: ", DUMP_PREFIX_OFFSET, | ||
402 | 16, 1, skb->data, skb->len, true); | ||
403 | |||
404 | nfc_data_exchange(local->dev, local->target_idx, | ||
405 | skb, nfc_llcp_recv, local); | ||
406 | } else { | ||
407 | nfc_llcp_send_symm(local->dev); | ||
408 | } | ||
409 | |||
410 | mod_timer(&local->link_timer, | ||
411 | jiffies + msecs_to_jiffies(local->remote_lto)); | ||
412 | } | 413 | } |
413 | 414 | ||
414 | static u8 nfc_llcp_dsap(struct sk_buff *pdu) | 415 | static u8 nfc_llcp_dsap(struct sk_buff *pdu) |
@@ -443,46 +444,146 @@ static void nfc_llcp_set_nrns(struct nfc_llcp_sock *sock, struct sk_buff *pdu) | |||
443 | sock->recv_ack_n = (sock->recv_n - 1) % 16; | 444 | sock->recv_ack_n = (sock->recv_n - 1) % 16; |
444 | } | 445 | } |
445 | 446 | ||
447 | static void nfc_llcp_tx_work(struct work_struct *work) | ||
448 | { | ||
449 | struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, | ||
450 | tx_work); | ||
451 | struct sk_buff *skb; | ||
452 | struct sock *sk; | ||
453 | struct nfc_llcp_sock *llcp_sock; | ||
454 | |||
455 | skb = skb_dequeue(&local->tx_queue); | ||
456 | if (skb != NULL) { | ||
457 | sk = skb->sk; | ||
458 | llcp_sock = nfc_llcp_sock(sk); | ||
459 | if (llcp_sock != NULL) { | ||
460 | int ret; | ||
461 | |||
462 | pr_debug("Sending pending skb\n"); | ||
463 | print_hex_dump(KERN_DEBUG, "LLCP Tx: ", | ||
464 | DUMP_PREFIX_OFFSET, 16, 1, | ||
465 | skb->data, skb->len, true); | ||
466 | |||
467 | ret = nfc_data_exchange(local->dev, local->target_idx, | ||
468 | skb, nfc_llcp_recv, local); | ||
469 | |||
470 | if (!ret && nfc_llcp_ptype(skb) == LLCP_PDU_I) { | ||
471 | skb = skb_get(skb); | ||
472 | skb_queue_tail(&llcp_sock->tx_pending_queue, | ||
473 | skb); | ||
474 | } | ||
475 | } else { | ||
476 | nfc_llcp_send_symm(local->dev); | ||
477 | } | ||
478 | } else { | ||
479 | nfc_llcp_send_symm(local->dev); | ||
480 | } | ||
481 | |||
482 | mod_timer(&local->link_timer, | ||
483 | jiffies + msecs_to_jiffies(2 * local->remote_lto)); | ||
484 | } | ||
485 | |||
486 | static struct nfc_llcp_sock *nfc_llcp_connecting_sock_get(struct nfc_llcp_local *local, | ||
487 | u8 ssap) | ||
488 | { | ||
489 | struct sock *sk; | ||
490 | struct nfc_llcp_sock *llcp_sock; | ||
491 | struct hlist_node *node; | ||
492 | |||
493 | read_lock(&local->connecting_sockets.lock); | ||
494 | |||
495 | sk_for_each(sk, node, &local->connecting_sockets.head) { | ||
496 | llcp_sock = nfc_llcp_sock(sk); | ||
497 | |||
498 | if (llcp_sock->ssap == ssap) { | ||
499 | sock_hold(&llcp_sock->sk); | ||
500 | goto out; | ||
501 | } | ||
502 | } | ||
503 | |||
504 | llcp_sock = NULL; | ||
505 | |||
506 | out: | ||
507 | read_unlock(&local->connecting_sockets.lock); | ||
508 | |||
509 | return llcp_sock; | ||
510 | } | ||
511 | |||
446 | static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local, | 512 | static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local, |
447 | u8 ssap, u8 dsap) | 513 | u8 ssap, u8 dsap) |
448 | { | 514 | { |
449 | struct nfc_llcp_sock *sock, *llcp_sock, *n; | 515 | struct sock *sk; |
516 | struct hlist_node *node; | ||
517 | struct nfc_llcp_sock *llcp_sock; | ||
450 | 518 | ||
451 | pr_debug("ssap dsap %d %d\n", ssap, dsap); | 519 | pr_debug("ssap dsap %d %d\n", ssap, dsap); |
452 | 520 | ||
453 | if (ssap == 0 && dsap == 0) | 521 | if (ssap == 0 && dsap == 0) |
454 | return NULL; | 522 | return NULL; |
455 | 523 | ||
456 | mutex_lock(&local->socket_lock); | 524 | read_lock(&local->sockets.lock); |
457 | sock = local->sockets[ssap]; | ||
458 | if (sock == NULL) { | ||
459 | mutex_unlock(&local->socket_lock); | ||
460 | return NULL; | ||
461 | } | ||
462 | 525 | ||
463 | pr_debug("root dsap %d (%d)\n", sock->dsap, dsap); | 526 | llcp_sock = NULL; |
464 | 527 | ||
465 | if (sock->dsap == dsap) { | 528 | sk_for_each(sk, node, &local->sockets.head) { |
466 | sock_hold(&sock->sk); | 529 | llcp_sock = nfc_llcp_sock(sk); |
467 | mutex_unlock(&local->socket_lock); | 530 | |
468 | return sock; | 531 | if (llcp_sock->ssap == ssap && |
532 | llcp_sock->dsap == dsap) | ||
533 | break; | ||
469 | } | 534 | } |
470 | 535 | ||
471 | list_for_each_entry_safe(llcp_sock, n, &sock->list, list) { | 536 | read_unlock(&local->sockets.lock); |
472 | pr_debug("llcp_sock %p sk %p dsap %d\n", llcp_sock, | 537 | |
473 | &llcp_sock->sk, llcp_sock->dsap); | 538 | if (llcp_sock == NULL) |
474 | if (llcp_sock->dsap == dsap) { | 539 | return NULL; |
475 | sock_hold(&llcp_sock->sk); | 540 | |
476 | mutex_unlock(&local->socket_lock); | 541 | sock_hold(&llcp_sock->sk); |
477 | return llcp_sock; | 542 | |
478 | } | 543 | return llcp_sock; |
544 | } | ||
545 | |||
546 | static struct nfc_llcp_sock *nfc_llcp_sock_get_sn(struct nfc_llcp_local *local, | ||
547 | u8 *sn, size_t sn_len) | ||
548 | { | ||
549 | struct sock *sk; | ||
550 | struct hlist_node *node; | ||
551 | struct nfc_llcp_sock *llcp_sock; | ||
552 | |||
553 | pr_debug("sn %zd\n", sn_len); | ||
554 | |||
555 | if (sn == NULL || sn_len == 0) | ||
556 | return NULL; | ||
557 | |||
558 | read_lock(&local->sockets.lock); | ||
559 | |||
560 | llcp_sock = NULL; | ||
561 | |||
562 | sk_for_each(sk, node, &local->sockets.head) { | ||
563 | llcp_sock = nfc_llcp_sock(sk); | ||
564 | |||
565 | if (llcp_sock->sk.sk_state != LLCP_LISTEN) | ||
566 | continue; | ||
567 | |||
568 | if (llcp_sock->service_name == NULL || | ||
569 | llcp_sock->service_name_len == 0) | ||
570 | continue; | ||
571 | |||
572 | if (llcp_sock->service_name_len != sn_len) | ||
573 | continue; | ||
574 | |||
575 | if (memcmp(sn, llcp_sock->service_name, sn_len) == 0) | ||
576 | break; | ||
479 | } | 577 | } |
480 | 578 | ||
481 | pr_err("Could not find socket for %d %d\n", ssap, dsap); | 579 | read_unlock(&local->sockets.lock); |
482 | 580 | ||
483 | mutex_unlock(&local->socket_lock); | 581 | if (llcp_sock == NULL) |
582 | return NULL; | ||
484 | 583 | ||
485 | return NULL; | 584 | sock_hold(&llcp_sock->sk); |
585 | |||
586 | return llcp_sock; | ||
486 | } | 587 | } |
487 | 588 | ||
488 | static void nfc_llcp_sock_put(struct nfc_llcp_sock *sock) | 589 | static void nfc_llcp_sock_put(struct nfc_llcp_sock *sock) |
@@ -518,35 +619,19 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, | |||
518 | { | 619 | { |
519 | struct sock *new_sk, *parent; | 620 | struct sock *new_sk, *parent; |
520 | struct nfc_llcp_sock *sock, *new_sock; | 621 | struct nfc_llcp_sock *sock, *new_sock; |
521 | u8 dsap, ssap, bound_sap, reason; | 622 | u8 dsap, ssap, reason; |
522 | 623 | ||
523 | dsap = nfc_llcp_dsap(skb); | 624 | dsap = nfc_llcp_dsap(skb); |
524 | ssap = nfc_llcp_ssap(skb); | 625 | ssap = nfc_llcp_ssap(skb); |
525 | 626 | ||
526 | pr_debug("%d %d\n", dsap, ssap); | 627 | pr_debug("%d %d\n", dsap, ssap); |
527 | 628 | ||
528 | nfc_llcp_parse_tlv(local, &skb->data[LLCP_HEADER_SIZE], | ||
529 | skb->len - LLCP_HEADER_SIZE); | ||
530 | |||
531 | if (dsap != LLCP_SAP_SDP) { | 629 | if (dsap != LLCP_SAP_SDP) { |
532 | bound_sap = dsap; | 630 | sock = nfc_llcp_sock_get(local, dsap, LLCP_SAP_SDP); |
533 | 631 | if (sock == NULL || sock->sk.sk_state != LLCP_LISTEN) { | |
534 | mutex_lock(&local->socket_lock); | ||
535 | sock = local->sockets[dsap]; | ||
536 | if (sock == NULL) { | ||
537 | mutex_unlock(&local->socket_lock); | ||
538 | reason = LLCP_DM_NOBOUND; | 632 | reason = LLCP_DM_NOBOUND; |
539 | goto fail; | 633 | goto fail; |
540 | } | 634 | } |
541 | |||
542 | sock_hold(&sock->sk); | ||
543 | mutex_unlock(&local->socket_lock); | ||
544 | |||
545 | lock_sock(&sock->sk); | ||
546 | |||
547 | if (sock->dsap == LLCP_SAP_SDP && | ||
548 | sock->sk.sk_state == LLCP_LISTEN) | ||
549 | goto enqueue; | ||
550 | } else { | 635 | } else { |
551 | u8 *sn; | 636 | u8 *sn; |
552 | size_t sn_len; | 637 | size_t sn_len; |
@@ -559,40 +644,15 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, | |||
559 | 644 | ||
560 | pr_debug("Service name length %zu\n", sn_len); | 645 | pr_debug("Service name length %zu\n", sn_len); |
561 | 646 | ||
562 | mutex_lock(&local->socket_lock); | 647 | sock = nfc_llcp_sock_get_sn(local, sn, sn_len); |
563 | for (bound_sap = 0; bound_sap < LLCP_LOCAL_SAP_OFFSET; | 648 | if (sock == NULL) { |
564 | bound_sap++) { | 649 | reason = LLCP_DM_NOBOUND; |
565 | sock = local->sockets[bound_sap]; | 650 | goto fail; |
566 | if (sock == NULL) | ||
567 | continue; | ||
568 | |||
569 | if (sock->service_name == NULL || | ||
570 | sock->service_name_len == 0) | ||
571 | continue; | ||
572 | |||
573 | if (sock->service_name_len != sn_len) | ||
574 | continue; | ||
575 | |||
576 | if (sock->dsap == LLCP_SAP_SDP && | ||
577 | sock->sk.sk_state == LLCP_LISTEN && | ||
578 | !memcmp(sn, sock->service_name, sn_len)) { | ||
579 | pr_debug("Found service name at SAP %d\n", | ||
580 | bound_sap); | ||
581 | sock_hold(&sock->sk); | ||
582 | mutex_unlock(&local->socket_lock); | ||
583 | |||
584 | lock_sock(&sock->sk); | ||
585 | |||
586 | goto enqueue; | ||
587 | } | ||
588 | } | 651 | } |
589 | mutex_unlock(&local->socket_lock); | ||
590 | } | 652 | } |
591 | 653 | ||
592 | reason = LLCP_DM_NOBOUND; | 654 | lock_sock(&sock->sk); |
593 | goto fail; | ||
594 | 655 | ||
595 | enqueue: | ||
596 | parent = &sock->sk; | 656 | parent = &sock->sk; |
597 | 657 | ||
598 | if (sk_acceptq_is_full(parent)) { | 658 | if (sk_acceptq_is_full(parent)) { |
@@ -612,15 +672,19 @@ enqueue: | |||
612 | 672 | ||
613 | new_sock = nfc_llcp_sock(new_sk); | 673 | new_sock = nfc_llcp_sock(new_sk); |
614 | new_sock->dev = local->dev; | 674 | new_sock->dev = local->dev; |
615 | new_sock->local = local; | 675 | new_sock->local = nfc_llcp_local_get(local); |
676 | new_sock->miu = local->remote_miu; | ||
616 | new_sock->nfc_protocol = sock->nfc_protocol; | 677 | new_sock->nfc_protocol = sock->nfc_protocol; |
617 | new_sock->ssap = bound_sap; | 678 | new_sock->ssap = sock->ssap; |
618 | new_sock->dsap = ssap; | 679 | new_sock->dsap = ssap; |
619 | new_sock->parent = parent; | 680 | new_sock->parent = parent; |
620 | 681 | ||
682 | nfc_llcp_parse_connection_tlv(new_sock, &skb->data[LLCP_HEADER_SIZE], | ||
683 | skb->len - LLCP_HEADER_SIZE); | ||
684 | |||
621 | pr_debug("new sock %p sk %p\n", new_sock, &new_sock->sk); | 685 | pr_debug("new sock %p sk %p\n", new_sock, &new_sock->sk); |
622 | 686 | ||
623 | list_add_tail(&new_sock->list, &sock->list); | 687 | nfc_llcp_sock_link(&local->sockets, new_sk); |
624 | 688 | ||
625 | nfc_llcp_accept_enqueue(&sock->sk, new_sk); | 689 | nfc_llcp_accept_enqueue(&sock->sk, new_sk); |
626 | 690 | ||
@@ -654,12 +718,12 @@ int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock) | |||
654 | 718 | ||
655 | pr_debug("Remote ready %d tx queue len %d remote rw %d", | 719 | pr_debug("Remote ready %d tx queue len %d remote rw %d", |
656 | sock->remote_ready, skb_queue_len(&sock->tx_pending_queue), | 720 | sock->remote_ready, skb_queue_len(&sock->tx_pending_queue), |
657 | local->remote_rw); | 721 | sock->rw); |
658 | 722 | ||
659 | /* Try to queue some I frames for transmission */ | 723 | /* Try to queue some I frames for transmission */ |
660 | while (sock->remote_ready && | 724 | while (sock->remote_ready && |
661 | skb_queue_len(&sock->tx_pending_queue) < local->remote_rw) { | 725 | skb_queue_len(&sock->tx_pending_queue) < sock->rw) { |
662 | struct sk_buff *pdu, *pending_pdu; | 726 | struct sk_buff *pdu; |
663 | 727 | ||
664 | pdu = skb_dequeue(&sock->tx_queue); | 728 | pdu = skb_dequeue(&sock->tx_queue); |
665 | if (pdu == NULL) | 729 | if (pdu == NULL) |
@@ -668,10 +732,7 @@ int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock) | |||
668 | /* Update N(S)/N(R) */ | 732 | /* Update N(S)/N(R) */ |
669 | nfc_llcp_set_nrns(sock, pdu); | 733 | nfc_llcp_set_nrns(sock, pdu); |
670 | 734 | ||
671 | pending_pdu = skb_clone(pdu, GFP_KERNEL); | ||
672 | |||
673 | skb_queue_tail(&local->tx_queue, pdu); | 735 | skb_queue_tail(&local->tx_queue, pdu); |
674 | skb_queue_tail(&sock->tx_pending_queue, pending_pdu); | ||
675 | nr_frames++; | 736 | nr_frames++; |
676 | } | 737 | } |
677 | 738 | ||
@@ -728,11 +789,21 @@ static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local, | |||
728 | 789 | ||
729 | llcp_sock->send_ack_n = nr; | 790 | llcp_sock->send_ack_n = nr; |
730 | 791 | ||
731 | skb_queue_walk_safe(&llcp_sock->tx_pending_queue, s, tmp) | 792 | /* Remove and free all skbs until ns == nr */ |
732 | if (nfc_llcp_ns(s) <= nr) { | 793 | skb_queue_walk_safe(&llcp_sock->tx_pending_queue, s, tmp) { |
733 | skb_unlink(s, &llcp_sock->tx_pending_queue); | 794 | skb_unlink(s, &llcp_sock->tx_pending_queue); |
734 | kfree_skb(s); | 795 | kfree_skb(s); |
735 | } | 796 | |
797 | if (nfc_llcp_ns(s) == nr) | ||
798 | break; | ||
799 | } | ||
800 | |||
801 | /* Re-queue the remaining skbs for transmission */ | ||
802 | skb_queue_reverse_walk_safe(&llcp_sock->tx_pending_queue, | ||
803 | s, tmp) { | ||
804 | skb_unlink(s, &llcp_sock->tx_pending_queue); | ||
805 | skb_queue_head(&local->tx_queue, s); | ||
806 | } | ||
736 | } | 807 | } |
737 | 808 | ||
738 | if (ptype == LLCP_PDU_RR) | 809 | if (ptype == LLCP_PDU_RR) |
@@ -740,7 +811,7 @@ static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local, | |||
740 | else if (ptype == LLCP_PDU_RNR) | 811 | else if (ptype == LLCP_PDU_RNR) |
741 | llcp_sock->remote_ready = false; | 812 | llcp_sock->remote_ready = false; |
742 | 813 | ||
743 | if (nfc_llcp_queue_i_frames(llcp_sock) == 0) | 814 | if (nfc_llcp_queue_i_frames(llcp_sock) == 0 && ptype == LLCP_PDU_I) |
744 | nfc_llcp_send_rr(llcp_sock); | 815 | nfc_llcp_send_rr(llcp_sock); |
745 | 816 | ||
746 | release_sock(sk); | 817 | release_sock(sk); |
@@ -791,11 +862,7 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb) | |||
791 | dsap = nfc_llcp_dsap(skb); | 862 | dsap = nfc_llcp_dsap(skb); |
792 | ssap = nfc_llcp_ssap(skb); | 863 | ssap = nfc_llcp_ssap(skb); |
793 | 864 | ||
794 | llcp_sock = nfc_llcp_sock_get(local, dsap, ssap); | 865 | llcp_sock = nfc_llcp_connecting_sock_get(local, dsap); |
795 | |||
796 | if (llcp_sock == NULL) | ||
797 | llcp_sock = nfc_llcp_sock_get(local, dsap, LLCP_SAP_SDP); | ||
798 | |||
799 | if (llcp_sock == NULL) { | 866 | if (llcp_sock == NULL) { |
800 | pr_err("Invalid CC\n"); | 867 | pr_err("Invalid CC\n"); |
801 | nfc_llcp_send_dm(local, dsap, ssap, LLCP_DM_NOCONN); | 868 | nfc_llcp_send_dm(local, dsap, ssap, LLCP_DM_NOCONN); |
@@ -803,11 +870,15 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb) | |||
803 | return; | 870 | return; |
804 | } | 871 | } |
805 | 872 | ||
806 | llcp_sock->dsap = ssap; | ||
807 | sk = &llcp_sock->sk; | 873 | sk = &llcp_sock->sk; |
808 | 874 | ||
809 | nfc_llcp_parse_tlv(local, &skb->data[LLCP_HEADER_SIZE], | 875 | /* Unlink from connecting and link to the client array */ |
810 | skb->len - LLCP_HEADER_SIZE); | 876 | nfc_llcp_sock_unlink(&local->connecting_sockets, sk); |
877 | nfc_llcp_sock_link(&local->sockets, sk); | ||
878 | llcp_sock->dsap = ssap; | ||
879 | |||
880 | nfc_llcp_parse_connection_tlv(llcp_sock, &skb->data[LLCP_HEADER_SIZE], | ||
881 | skb->len - LLCP_HEADER_SIZE); | ||
811 | 882 | ||
812 | sk->sk_state = LLCP_CONNECTED; | 883 | sk->sk_state = LLCP_CONNECTED; |
813 | sk->sk_state_change(sk); | 884 | sk->sk_state_change(sk); |
@@ -891,6 +962,21 @@ void nfc_llcp_recv(void *data, struct sk_buff *skb, int err) | |||
891 | return; | 962 | return; |
892 | } | 963 | } |
893 | 964 | ||
965 | int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb) | ||
966 | { | ||
967 | struct nfc_llcp_local *local; | ||
968 | |||
969 | local = nfc_llcp_find_local(dev); | ||
970 | if (local == NULL) | ||
971 | return -ENODEV; | ||
972 | |||
973 | local->rx_pending = skb_get(skb); | ||
974 | del_timer(&local->link_timer); | ||
975 | queue_work(local->rx_wq, &local->rx_work); | ||
976 | |||
977 | return 0; | ||
978 | } | ||
979 | |||
894 | void nfc_llcp_mac_is_down(struct nfc_dev *dev) | 980 | void nfc_llcp_mac_is_down(struct nfc_dev *dev) |
895 | { | 981 | { |
896 | struct nfc_llcp_local *local; | 982 | struct nfc_llcp_local *local; |
@@ -943,8 +1029,8 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) | |||
943 | 1029 | ||
944 | local->dev = ndev; | 1030 | local->dev = ndev; |
945 | INIT_LIST_HEAD(&local->list); | 1031 | INIT_LIST_HEAD(&local->list); |
1032 | kref_init(&local->ref); | ||
946 | mutex_init(&local->sdp_lock); | 1033 | mutex_init(&local->sdp_lock); |
947 | mutex_init(&local->socket_lock); | ||
948 | init_timer(&local->link_timer); | 1034 | init_timer(&local->link_timer); |
949 | local->link_timer.data = (unsigned long) local; | 1035 | local->link_timer.data = (unsigned long) local; |
950 | local->link_timer.function = nfc_llcp_symm_timer; | 1036 | local->link_timer.function = nfc_llcp_symm_timer; |
@@ -984,11 +1070,13 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) | |||
984 | goto err_rx_wq; | 1070 | goto err_rx_wq; |
985 | } | 1071 | } |
986 | 1072 | ||
1073 | local->sockets.lock = __RW_LOCK_UNLOCKED(local->sockets.lock); | ||
1074 | local->connecting_sockets.lock = __RW_LOCK_UNLOCKED(local->connecting_sockets.lock); | ||
1075 | |||
987 | nfc_llcp_build_gb(local); | 1076 | nfc_llcp_build_gb(local); |
988 | 1077 | ||
989 | local->remote_miu = LLCP_DEFAULT_MIU; | 1078 | local->remote_miu = LLCP_DEFAULT_MIU; |
990 | local->remote_lto = LLCP_DEFAULT_LTO; | 1079 | local->remote_lto = LLCP_DEFAULT_LTO; |
991 | local->remote_rw = LLCP_DEFAULT_RW; | ||
992 | 1080 | ||
993 | list_add(&llcp_devices, &local->list); | 1081 | list_add(&llcp_devices, &local->list); |
994 | 1082 | ||
@@ -1015,14 +1103,7 @@ void nfc_llcp_unregister_device(struct nfc_dev *dev) | |||
1015 | return; | 1103 | return; |
1016 | } | 1104 | } |
1017 | 1105 | ||
1018 | list_del(&local->list); | 1106 | nfc_llcp_local_put(local); |
1019 | nfc_llcp_socket_release(local); | ||
1020 | del_timer_sync(&local->link_timer); | ||
1021 | skb_queue_purge(&local->tx_queue); | ||
1022 | destroy_workqueue(local->tx_wq); | ||
1023 | destroy_workqueue(local->rx_wq); | ||
1024 | kfree_skb(local->rx_pending); | ||
1025 | kfree(local); | ||
1026 | } | 1107 | } |
1027 | 1108 | ||
1028 | int __init nfc_llcp_init(void) | 1109 | int __init nfc_llcp_init(void) |
diff --git a/net/nfc/llcp/llcp.h b/net/nfc/llcp/llcp.h index 50680ce5ae43..7286c86982ff 100644 --- a/net/nfc/llcp/llcp.h +++ b/net/nfc/llcp/llcp.h | |||
@@ -40,12 +40,18 @@ enum llcp_state { | |||
40 | 40 | ||
41 | struct nfc_llcp_sock; | 41 | struct nfc_llcp_sock; |
42 | 42 | ||
43 | struct llcp_sock_list { | ||
44 | struct hlist_head head; | ||
45 | rwlock_t lock; | ||
46 | }; | ||
47 | |||
43 | struct nfc_llcp_local { | 48 | struct nfc_llcp_local { |
44 | struct list_head list; | 49 | struct list_head list; |
45 | struct nfc_dev *dev; | 50 | struct nfc_dev *dev; |
46 | 51 | ||
52 | struct kref ref; | ||
53 | |||
47 | struct mutex sdp_lock; | 54 | struct mutex sdp_lock; |
48 | struct mutex socket_lock; | ||
49 | 55 | ||
50 | struct timer_list link_timer; | 56 | struct timer_list link_timer; |
51 | struct sk_buff_head tx_queue; | 57 | struct sk_buff_head tx_queue; |
@@ -77,24 +83,26 @@ struct nfc_llcp_local { | |||
77 | u16 remote_lto; | 83 | u16 remote_lto; |
78 | u8 remote_opt; | 84 | u8 remote_opt; |
79 | u16 remote_wks; | 85 | u16 remote_wks; |
80 | u8 remote_rw; | ||
81 | 86 | ||
82 | /* sockets array */ | 87 | /* sockets array */ |
83 | struct nfc_llcp_sock *sockets[LLCP_MAX_SAP]; | 88 | struct llcp_sock_list sockets; |
89 | struct llcp_sock_list connecting_sockets; | ||
84 | }; | 90 | }; |
85 | 91 | ||
86 | struct nfc_llcp_sock { | 92 | struct nfc_llcp_sock { |
87 | struct sock sk; | 93 | struct sock sk; |
88 | struct list_head list; | ||
89 | struct nfc_dev *dev; | 94 | struct nfc_dev *dev; |
90 | struct nfc_llcp_local *local; | 95 | struct nfc_llcp_local *local; |
91 | u32 target_idx; | 96 | u32 target_idx; |
92 | u32 nfc_protocol; | 97 | u32 nfc_protocol; |
93 | 98 | ||
99 | /* Link parameters */ | ||
94 | u8 ssap; | 100 | u8 ssap; |
95 | u8 dsap; | 101 | u8 dsap; |
96 | char *service_name; | 102 | char *service_name; |
97 | size_t service_name_len; | 103 | size_t service_name_len; |
104 | u8 rw; | ||
105 | u16 miu; | ||
98 | 106 | ||
99 | /* Link variables */ | 107 | /* Link variables */ |
100 | u8 send_n; | 108 | u8 send_n; |
@@ -164,7 +172,11 @@ struct nfc_llcp_sock { | |||
164 | #define LLCP_DM_REJ 0x03 | 172 | #define LLCP_DM_REJ 0x03 |
165 | 173 | ||
166 | 174 | ||
175 | void nfc_llcp_sock_link(struct llcp_sock_list *l, struct sock *s); | ||
176 | void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *s); | ||
167 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev); | 177 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev); |
178 | struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local); | ||
179 | int nfc_llcp_local_put(struct nfc_llcp_local *local); | ||
168 | u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local, | 180 | u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local, |
169 | struct nfc_llcp_sock *sock); | 181 | struct nfc_llcp_sock *sock); |
170 | u8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local); | 182 | u8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local); |
@@ -179,8 +191,10 @@ void nfc_llcp_accept_enqueue(struct sock *parent, struct sock *sk); | |||
179 | struct sock *nfc_llcp_accept_dequeue(struct sock *sk, struct socket *newsock); | 191 | struct sock *nfc_llcp_accept_dequeue(struct sock *sk, struct socket *newsock); |
180 | 192 | ||
181 | /* TLV API */ | 193 | /* TLV API */ |
182 | int nfc_llcp_parse_tlv(struct nfc_llcp_local *local, | 194 | int nfc_llcp_parse_gb_tlv(struct nfc_llcp_local *local, |
183 | u8 *tlv_array, u16 tlv_array_len); | 195 | u8 *tlv_array, u16 tlv_array_len); |
196 | int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock, | ||
197 | u8 *tlv_array, u16 tlv_array_len); | ||
184 | 198 | ||
185 | /* Commands API */ | 199 | /* Commands API */ |
186 | void nfc_llcp_recv(void *data, struct sk_buff *skb, int err); | 200 | void nfc_llcp_recv(void *data, struct sk_buff *skb, int err); |
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c index 3f339b19d140..30e3cc71be7a 100644 --- a/net/nfc/llcp/sock.c +++ b/net/nfc/llcp/sock.c | |||
@@ -111,7 +111,7 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) | |||
111 | } | 111 | } |
112 | 112 | ||
113 | llcp_sock->dev = dev; | 113 | llcp_sock->dev = dev; |
114 | llcp_sock->local = local; | 114 | llcp_sock->local = nfc_llcp_local_get(local); |
115 | llcp_sock->nfc_protocol = llcp_addr.nfc_protocol; | 115 | llcp_sock->nfc_protocol = llcp_addr.nfc_protocol; |
116 | llcp_sock->service_name_len = min_t(unsigned int, | 116 | llcp_sock->service_name_len = min_t(unsigned int, |
117 | llcp_addr.service_name_len, | 117 | llcp_addr.service_name_len, |
@@ -124,7 +124,7 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) | |||
124 | if (llcp_sock->ssap == LLCP_MAX_SAP) | 124 | if (llcp_sock->ssap == LLCP_MAX_SAP) |
125 | goto put_dev; | 125 | goto put_dev; |
126 | 126 | ||
127 | local->sockets[llcp_sock->ssap] = llcp_sock; | 127 | nfc_llcp_sock_link(&local->sockets, sk); |
128 | 128 | ||
129 | pr_debug("Socket bound to SAP %d\n", llcp_sock->ssap); | 129 | pr_debug("Socket bound to SAP %d\n", llcp_sock->ssap); |
130 | 130 | ||
@@ -379,15 +379,6 @@ static int llcp_sock_release(struct socket *sock) | |||
379 | goto out; | 379 | goto out; |
380 | } | 380 | } |
381 | 381 | ||
382 | mutex_lock(&local->socket_lock); | ||
383 | |||
384 | if (llcp_sock == local->sockets[llcp_sock->ssap]) | ||
385 | local->sockets[llcp_sock->ssap] = NULL; | ||
386 | else | ||
387 | list_del_init(&llcp_sock->list); | ||
388 | |||
389 | mutex_unlock(&local->socket_lock); | ||
390 | |||
391 | lock_sock(sk); | 382 | lock_sock(sk); |
392 | 383 | ||
393 | /* Send a DISC */ | 384 | /* Send a DISC */ |
@@ -412,14 +403,12 @@ static int llcp_sock_release(struct socket *sock) | |||
412 | } | 403 | } |
413 | } | 404 | } |
414 | 405 | ||
415 | /* Freeing the SAP */ | 406 | nfc_llcp_put_ssap(llcp_sock->local, llcp_sock->ssap); |
416 | if ((sk->sk_state == LLCP_CONNECTED | ||
417 | && llcp_sock->ssap > LLCP_LOCAL_SAP_OFFSET) || | ||
418 | sk->sk_state == LLCP_BOUND || sk->sk_state == LLCP_LISTEN) | ||
419 | nfc_llcp_put_ssap(llcp_sock->local, llcp_sock->ssap); | ||
420 | 407 | ||
421 | release_sock(sk); | 408 | release_sock(sk); |
422 | 409 | ||
410 | nfc_llcp_sock_unlink(&local->sockets, sk); | ||
411 | |||
423 | out: | 412 | out: |
424 | sock_orphan(sk); | 413 | sock_orphan(sk); |
425 | sock_put(sk); | 414 | sock_put(sk); |
@@ -487,7 +476,8 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, | |||
487 | } | 476 | } |
488 | 477 | ||
489 | llcp_sock->dev = dev; | 478 | llcp_sock->dev = dev; |
490 | llcp_sock->local = local; | 479 | llcp_sock->local = nfc_llcp_local_get(local); |
480 | llcp_sock->miu = llcp_sock->local->remote_miu; | ||
491 | llcp_sock->ssap = nfc_llcp_get_local_ssap(local); | 481 | llcp_sock->ssap = nfc_llcp_get_local_ssap(local); |
492 | if (llcp_sock->ssap == LLCP_SAP_MAX) { | 482 | if (llcp_sock->ssap == LLCP_SAP_MAX) { |
493 | ret = -ENOMEM; | 483 | ret = -ENOMEM; |
@@ -505,21 +495,26 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, | |||
505 | llcp_sock->service_name_len, | 495 | llcp_sock->service_name_len, |
506 | GFP_KERNEL); | 496 | GFP_KERNEL); |
507 | 497 | ||
508 | local->sockets[llcp_sock->ssap] = llcp_sock; | 498 | nfc_llcp_sock_link(&local->connecting_sockets, sk); |
509 | 499 | ||
510 | ret = nfc_llcp_send_connect(llcp_sock); | 500 | ret = nfc_llcp_send_connect(llcp_sock); |
511 | if (ret) | 501 | if (ret) |
512 | goto put_dev; | 502 | goto sock_unlink; |
513 | 503 | ||
514 | ret = sock_wait_state(sk, LLCP_CONNECTED, | 504 | ret = sock_wait_state(sk, LLCP_CONNECTED, |
515 | sock_sndtimeo(sk, flags & O_NONBLOCK)); | 505 | sock_sndtimeo(sk, flags & O_NONBLOCK)); |
516 | if (ret) | 506 | if (ret) |
517 | goto put_dev; | 507 | goto sock_unlink; |
518 | 508 | ||
519 | release_sock(sk); | 509 | release_sock(sk); |
520 | 510 | ||
521 | return 0; | 511 | return 0; |
522 | 512 | ||
513 | sock_unlink: | ||
514 | nfc_llcp_put_ssap(local, llcp_sock->ssap); | ||
515 | |||
516 | nfc_llcp_sock_unlink(&local->connecting_sockets, sk); | ||
517 | |||
523 | put_dev: | 518 | put_dev: |
524 | nfc_put_device(dev); | 519 | nfc_put_device(dev); |
525 | 520 | ||
@@ -684,13 +679,14 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp) | |||
684 | 679 | ||
685 | llcp_sock->ssap = 0; | 680 | llcp_sock->ssap = 0; |
686 | llcp_sock->dsap = LLCP_SAP_SDP; | 681 | llcp_sock->dsap = LLCP_SAP_SDP; |
682 | llcp_sock->rw = LLCP_DEFAULT_RW; | ||
683 | llcp_sock->miu = LLCP_DEFAULT_MIU; | ||
687 | llcp_sock->send_n = llcp_sock->send_ack_n = 0; | 684 | llcp_sock->send_n = llcp_sock->send_ack_n = 0; |
688 | llcp_sock->recv_n = llcp_sock->recv_ack_n = 0; | 685 | llcp_sock->recv_n = llcp_sock->recv_ack_n = 0; |
689 | llcp_sock->remote_ready = 1; | 686 | llcp_sock->remote_ready = 1; |
690 | skb_queue_head_init(&llcp_sock->tx_queue); | 687 | skb_queue_head_init(&llcp_sock->tx_queue); |
691 | skb_queue_head_init(&llcp_sock->tx_pending_queue); | 688 | skb_queue_head_init(&llcp_sock->tx_pending_queue); |
692 | skb_queue_head_init(&llcp_sock->tx_backlog_queue); | 689 | skb_queue_head_init(&llcp_sock->tx_backlog_queue); |
693 | INIT_LIST_HEAD(&llcp_sock->list); | ||
694 | INIT_LIST_HEAD(&llcp_sock->accept_queue); | 690 | INIT_LIST_HEAD(&llcp_sock->accept_queue); |
695 | 691 | ||
696 | if (sock != NULL) | 692 | if (sock != NULL) |
@@ -701,8 +697,6 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp) | |||
701 | 697 | ||
702 | void nfc_llcp_sock_free(struct nfc_llcp_sock *sock) | 698 | void nfc_llcp_sock_free(struct nfc_llcp_sock *sock) |
703 | { | 699 | { |
704 | struct nfc_llcp_local *local = sock->local; | ||
705 | |||
706 | kfree(sock->service_name); | 700 | kfree(sock->service_name); |
707 | 701 | ||
708 | skb_queue_purge(&sock->tx_queue); | 702 | skb_queue_purge(&sock->tx_queue); |
@@ -711,12 +705,9 @@ void nfc_llcp_sock_free(struct nfc_llcp_sock *sock) | |||
711 | 705 | ||
712 | list_del_init(&sock->accept_queue); | 706 | list_del_init(&sock->accept_queue); |
713 | 707 | ||
714 | if (local != NULL && sock == local->sockets[sock->ssap]) | ||
715 | local->sockets[sock->ssap] = NULL; | ||
716 | else | ||
717 | list_del_init(&sock->list); | ||
718 | |||
719 | sock->parent = NULL; | 708 | sock->parent = NULL; |
709 | |||
710 | nfc_llcp_local_put(sock->local); | ||
720 | } | 711 | } |
721 | 712 | ||
722 | static int llcp_sock_create(struct net *net, struct socket *sock, | 713 | static int llcp_sock_create(struct net *net, struct socket *sock, |
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c index d560e6f13072..766a02b1dfa1 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c | |||
@@ -387,7 +387,8 @@ static int nci_dev_down(struct nfc_dev *nfc_dev) | |||
387 | return nci_close_device(ndev); | 387 | return nci_close_device(ndev); |
388 | } | 388 | } |
389 | 389 | ||
390 | static int nci_start_poll(struct nfc_dev *nfc_dev, __u32 protocols) | 390 | static int nci_start_poll(struct nfc_dev *nfc_dev, |
391 | __u32 im_protocols, __u32 tm_protocols) | ||
391 | { | 392 | { |
392 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); | 393 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); |
393 | int rc; | 394 | int rc; |
@@ -413,11 +414,11 @@ static int nci_start_poll(struct nfc_dev *nfc_dev, __u32 protocols) | |||
413 | return -EBUSY; | 414 | return -EBUSY; |
414 | } | 415 | } |
415 | 416 | ||
416 | rc = nci_request(ndev, nci_rf_discover_req, protocols, | 417 | rc = nci_request(ndev, nci_rf_discover_req, im_protocols, |
417 | msecs_to_jiffies(NCI_RF_DISC_TIMEOUT)); | 418 | msecs_to_jiffies(NCI_RF_DISC_TIMEOUT)); |
418 | 419 | ||
419 | if (!rc) | 420 | if (!rc) |
420 | ndev->poll_prots = protocols; | 421 | ndev->poll_prots = im_protocols; |
421 | 422 | ||
422 | return rc; | 423 | return rc; |
423 | } | 424 | } |
@@ -521,9 +522,9 @@ static void nci_deactivate_target(struct nfc_dev *nfc_dev, | |||
521 | } | 522 | } |
522 | } | 523 | } |
523 | 524 | ||
524 | static int nci_data_exchange(struct nfc_dev *nfc_dev, struct nfc_target *target, | 525 | static int nci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target, |
525 | struct sk_buff *skb, | 526 | struct sk_buff *skb, |
526 | data_exchange_cb_t cb, void *cb_context) | 527 | data_exchange_cb_t cb, void *cb_context) |
527 | { | 528 | { |
528 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); | 529 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); |
529 | int rc; | 530 | int rc; |
@@ -556,7 +557,7 @@ static struct nfc_ops nci_nfc_ops = { | |||
556 | .stop_poll = nci_stop_poll, | 557 | .stop_poll = nci_stop_poll, |
557 | .activate_target = nci_activate_target, | 558 | .activate_target = nci_activate_target, |
558 | .deactivate_target = nci_deactivate_target, | 559 | .deactivate_target = nci_deactivate_target, |
559 | .data_exchange = nci_data_exchange, | 560 | .im_transceive = nci_transceive, |
560 | }; | 561 | }; |
561 | 562 | ||
562 | /* ---- Interface to NCI drivers ---- */ | 563 | /* ---- Interface to NCI drivers ---- */ |
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index 581d419083aa..03c31db38f12 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c | |||
@@ -49,6 +49,8 @@ static const struct nla_policy nfc_genl_policy[NFC_ATTR_MAX + 1] = { | |||
49 | [NFC_ATTR_COMM_MODE] = { .type = NLA_U8 }, | 49 | [NFC_ATTR_COMM_MODE] = { .type = NLA_U8 }, |
50 | [NFC_ATTR_RF_MODE] = { .type = NLA_U8 }, | 50 | [NFC_ATTR_RF_MODE] = { .type = NLA_U8 }, |
51 | [NFC_ATTR_DEVICE_POWERED] = { .type = NLA_U8 }, | 51 | [NFC_ATTR_DEVICE_POWERED] = { .type = NLA_U8 }, |
52 | [NFC_ATTR_IM_PROTOCOLS] = { .type = NLA_U32 }, | ||
53 | [NFC_ATTR_TM_PROTOCOLS] = { .type = NLA_U32 }, | ||
52 | }; | 54 | }; |
53 | 55 | ||
54 | static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target, | 56 | static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target, |
@@ -219,6 +221,68 @@ free_msg: | |||
219 | return -EMSGSIZE; | 221 | return -EMSGSIZE; |
220 | } | 222 | } |
221 | 223 | ||
224 | int nfc_genl_tm_activated(struct nfc_dev *dev, u32 protocol) | ||
225 | { | ||
226 | struct sk_buff *msg; | ||
227 | void *hdr; | ||
228 | |||
229 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | ||
230 | if (!msg) | ||
231 | return -ENOMEM; | ||
232 | |||
233 | hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, | ||
234 | NFC_EVENT_TM_ACTIVATED); | ||
235 | if (!hdr) | ||
236 | goto free_msg; | ||
237 | |||
238 | if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx)) | ||
239 | goto nla_put_failure; | ||
240 | if (nla_put_u32(msg, NFC_ATTR_TM_PROTOCOLS, protocol)) | ||
241 | goto nla_put_failure; | ||
242 | |||
243 | genlmsg_end(msg, hdr); | ||
244 | |||
245 | genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL); | ||
246 | |||
247 | return 0; | ||
248 | |||
249 | nla_put_failure: | ||
250 | genlmsg_cancel(msg, hdr); | ||
251 | free_msg: | ||
252 | nlmsg_free(msg); | ||
253 | return -EMSGSIZE; | ||
254 | } | ||
255 | |||
256 | int nfc_genl_tm_deactivated(struct nfc_dev *dev) | ||
257 | { | ||
258 | struct sk_buff *msg; | ||
259 | void *hdr; | ||
260 | |||
261 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | ||
262 | if (!msg) | ||
263 | return -ENOMEM; | ||
264 | |||
265 | hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, | ||
266 | NFC_EVENT_TM_DEACTIVATED); | ||
267 | if (!hdr) | ||
268 | goto free_msg; | ||
269 | |||
270 | if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx)) | ||
271 | goto nla_put_failure; | ||
272 | |||
273 | genlmsg_end(msg, hdr); | ||
274 | |||
275 | genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL); | ||
276 | |||
277 | return 0; | ||
278 | |||
279 | nla_put_failure: | ||
280 | genlmsg_cancel(msg, hdr); | ||
281 | free_msg: | ||
282 | nlmsg_free(msg); | ||
283 | return -EMSGSIZE; | ||
284 | } | ||
285 | |||
222 | int nfc_genl_device_added(struct nfc_dev *dev) | 286 | int nfc_genl_device_added(struct nfc_dev *dev) |
223 | { | 287 | { |
224 | struct sk_buff *msg; | 288 | struct sk_buff *msg; |
@@ -519,16 +583,25 @@ static int nfc_genl_start_poll(struct sk_buff *skb, struct genl_info *info) | |||
519 | struct nfc_dev *dev; | 583 | struct nfc_dev *dev; |
520 | int rc; | 584 | int rc; |
521 | u32 idx; | 585 | u32 idx; |
522 | u32 protocols; | 586 | u32 im_protocols = 0, tm_protocols = 0; |
523 | 587 | ||
524 | pr_debug("Poll start\n"); | 588 | pr_debug("Poll start\n"); |
525 | 589 | ||
526 | if (!info->attrs[NFC_ATTR_DEVICE_INDEX] || | 590 | if (!info->attrs[NFC_ATTR_DEVICE_INDEX] || |
527 | !info->attrs[NFC_ATTR_PROTOCOLS]) | 591 | ((!info->attrs[NFC_ATTR_IM_PROTOCOLS] && |
592 | !info->attrs[NFC_ATTR_PROTOCOLS]) && | ||
593 | !info->attrs[NFC_ATTR_TM_PROTOCOLS])) | ||
528 | return -EINVAL; | 594 | return -EINVAL; |
529 | 595 | ||
530 | idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); | 596 | idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); |
531 | protocols = nla_get_u32(info->attrs[NFC_ATTR_PROTOCOLS]); | 597 | |
598 | if (info->attrs[NFC_ATTR_TM_PROTOCOLS]) | ||
599 | tm_protocols = nla_get_u32(info->attrs[NFC_ATTR_TM_PROTOCOLS]); | ||
600 | |||
601 | if (info->attrs[NFC_ATTR_IM_PROTOCOLS]) | ||
602 | im_protocols = nla_get_u32(info->attrs[NFC_ATTR_IM_PROTOCOLS]); | ||
603 | else if (info->attrs[NFC_ATTR_PROTOCOLS]) | ||
604 | im_protocols = nla_get_u32(info->attrs[NFC_ATTR_PROTOCOLS]); | ||
532 | 605 | ||
533 | dev = nfc_get_device(idx); | 606 | dev = nfc_get_device(idx); |
534 | if (!dev) | 607 | if (!dev) |
@@ -536,7 +609,7 @@ static int nfc_genl_start_poll(struct sk_buff *skb, struct genl_info *info) | |||
536 | 609 | ||
537 | mutex_lock(&dev->genl_data.genl_data_mutex); | 610 | mutex_lock(&dev->genl_data.genl_data_mutex); |
538 | 611 | ||
539 | rc = nfc_start_poll(dev, protocols); | 612 | rc = nfc_start_poll(dev, im_protocols, tm_protocols); |
540 | if (!rc) | 613 | if (!rc) |
541 | dev->genl_data.poll_req_pid = info->snd_pid; | 614 | dev->genl_data.poll_req_pid = info->snd_pid; |
542 | 615 | ||
diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h index 3dd4232ae664..c5e42b79a418 100644 --- a/net/nfc/nfc.h +++ b/net/nfc/nfc.h | |||
@@ -55,6 +55,7 @@ int nfc_llcp_register_device(struct nfc_dev *dev); | |||
55 | void nfc_llcp_unregister_device(struct nfc_dev *dev); | 55 | 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 __init nfc_llcp_init(void); | 59 | int __init nfc_llcp_init(void); |
59 | void nfc_llcp_exit(void); | 60 | void nfc_llcp_exit(void); |
60 | 61 | ||
@@ -90,6 +91,12 @@ static inline u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *gb_len) | |||
90 | return NULL; | 91 | return NULL; |
91 | } | 92 | } |
92 | 93 | ||
94 | static inline int nfc_llcp_data_received(struct nfc_dev *dev, | ||
95 | struct sk_buff *skb) | ||
96 | { | ||
97 | return 0; | ||
98 | } | ||
99 | |||
93 | static inline int nfc_llcp_init(void) | 100 | static inline int nfc_llcp_init(void) |
94 | { | 101 | { |
95 | return 0; | 102 | return 0; |
@@ -128,6 +135,9 @@ int nfc_genl_dep_link_up_event(struct nfc_dev *dev, u32 target_idx, | |||
128 | u8 comm_mode, u8 rf_mode); | 135 | u8 comm_mode, u8 rf_mode); |
129 | int nfc_genl_dep_link_down_event(struct nfc_dev *dev); | 136 | int nfc_genl_dep_link_down_event(struct nfc_dev *dev); |
130 | 137 | ||
138 | int nfc_genl_tm_activated(struct nfc_dev *dev, u32 protocol); | ||
139 | int nfc_genl_tm_deactivated(struct nfc_dev *dev); | ||
140 | |||
131 | struct nfc_dev *nfc_get_device(unsigned int idx); | 141 | struct nfc_dev *nfc_get_device(unsigned int idx); |
132 | 142 | ||
133 | static inline void nfc_put_device(struct nfc_dev *dev) | 143 | static inline void nfc_put_device(struct nfc_dev *dev) |
@@ -158,7 +168,7 @@ int nfc_dev_up(struct nfc_dev *dev); | |||
158 | 168 | ||
159 | int nfc_dev_down(struct nfc_dev *dev); | 169 | int nfc_dev_down(struct nfc_dev *dev); |
160 | 170 | ||
161 | int nfc_start_poll(struct nfc_dev *dev, u32 protocols); | 171 | int nfc_start_poll(struct nfc_dev *dev, u32 im_protocols, u32 tm_protocols); |
162 | 172 | ||
163 | int nfc_stop_poll(struct nfc_dev *dev); | 173 | int nfc_stop_poll(struct nfc_dev *dev); |
164 | 174 | ||