diff options
Diffstat (limited to 'net/nfc/core.c')
-rw-r--r-- | net/nfc/core.c | 81 |
1 files changed, 61 insertions, 20 deletions
diff --git a/net/nfc/core.c b/net/nfc/core.c index 3192c3f589ee..7df28ad4727f 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c | |||
@@ -97,7 +97,7 @@ int nfc_dev_down(struct nfc_dev *dev) | |||
97 | goto error; | 97 | goto error; |
98 | } | 98 | } |
99 | 99 | ||
100 | if (dev->polling || dev->activated_target_idx != NFC_TARGET_IDX_NONE) { | 100 | if (dev->polling || dev->active_target) { |
101 | rc = -EBUSY; | 101 | rc = -EBUSY; |
102 | goto error; | 102 | goto error; |
103 | } | 103 | } |
@@ -183,11 +183,27 @@ error: | |||
183 | return rc; | 183 | return rc; |
184 | } | 184 | } |
185 | 185 | ||
186 | static struct nfc_target *nfc_find_target(struct nfc_dev *dev, u32 target_idx) | ||
187 | { | ||
188 | int i; | ||
189 | |||
190 | if (dev->n_targets == 0) | ||
191 | return NULL; | ||
192 | |||
193 | for (i = 0; i < dev->n_targets ; i++) { | ||
194 | if (dev->targets[i].idx == target_idx) | ||
195 | return &dev->targets[i]; | ||
196 | } | ||
197 | |||
198 | return NULL; | ||
199 | } | ||
200 | |||
186 | int nfc_dep_link_up(struct nfc_dev *dev, int target_index, u8 comm_mode) | 201 | int nfc_dep_link_up(struct nfc_dev *dev, int target_index, u8 comm_mode) |
187 | { | 202 | { |
188 | int rc = 0; | 203 | int rc = 0; |
189 | u8 *gb; | 204 | u8 *gb; |
190 | size_t gb_len; | 205 | size_t gb_len; |
206 | struct nfc_target *target; | ||
191 | 207 | ||
192 | pr_debug("dev_name=%s comm %d\n", dev_name(&dev->dev), comm_mode); | 208 | pr_debug("dev_name=%s comm %d\n", dev_name(&dev->dev), comm_mode); |
193 | 209 | ||
@@ -212,9 +228,15 @@ int nfc_dep_link_up(struct nfc_dev *dev, int target_index, u8 comm_mode) | |||
212 | goto error; | 228 | goto error; |
213 | } | 229 | } |
214 | 230 | ||
215 | rc = dev->ops->dep_link_up(dev, target_index, comm_mode, gb, gb_len); | 231 | target = nfc_find_target(dev, target_index); |
232 | if (target == NULL) { | ||
233 | rc = -ENOTCONN; | ||
234 | goto error; | ||
235 | } | ||
236 | |||
237 | rc = dev->ops->dep_link_up(dev, target, comm_mode, gb, gb_len); | ||
216 | if (!rc) | 238 | if (!rc) |
217 | dev->activated_target_idx = target_index; | 239 | dev->active_target = target; |
218 | 240 | ||
219 | error: | 241 | error: |
220 | device_unlock(&dev->dev); | 242 | device_unlock(&dev->dev); |
@@ -250,7 +272,7 @@ int nfc_dep_link_down(struct nfc_dev *dev) | |||
250 | rc = dev->ops->dep_link_down(dev); | 272 | rc = dev->ops->dep_link_down(dev); |
251 | if (!rc) { | 273 | if (!rc) { |
252 | dev->dep_link_up = false; | 274 | dev->dep_link_up = false; |
253 | dev->activated_target_idx = NFC_TARGET_IDX_NONE; | 275 | dev->active_target = NULL; |
254 | nfc_llcp_mac_is_down(dev); | 276 | nfc_llcp_mac_is_down(dev); |
255 | nfc_genl_dep_link_down_event(dev); | 277 | nfc_genl_dep_link_down_event(dev); |
256 | } | 278 | } |
@@ -282,6 +304,7 @@ EXPORT_SYMBOL(nfc_dep_link_is_up); | |||
282 | int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol) | 304 | int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol) |
283 | { | 305 | { |
284 | int rc; | 306 | int rc; |
307 | struct nfc_target *target; | ||
285 | 308 | ||
286 | pr_debug("dev_name=%s target_idx=%u protocol=%u\n", | 309 | pr_debug("dev_name=%s target_idx=%u protocol=%u\n", |
287 | dev_name(&dev->dev), target_idx, protocol); | 310 | dev_name(&dev->dev), target_idx, protocol); |
@@ -293,9 +316,20 @@ int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol) | |||
293 | goto error; | 316 | goto error; |
294 | } | 317 | } |
295 | 318 | ||
296 | rc = dev->ops->activate_target(dev, target_idx, protocol); | 319 | if (dev->active_target) { |
320 | rc = -EBUSY; | ||
321 | goto error; | ||
322 | } | ||
323 | |||
324 | target = nfc_find_target(dev, target_idx); | ||
325 | if (target == NULL) { | ||
326 | rc = -ENOTCONN; | ||
327 | goto error; | ||
328 | } | ||
329 | |||
330 | rc = dev->ops->activate_target(dev, target, protocol); | ||
297 | if (!rc) { | 331 | if (!rc) { |
298 | dev->activated_target_idx = target_idx; | 332 | dev->active_target = target; |
299 | 333 | ||
300 | if (dev->ops->check_presence) | 334 | if (dev->ops->check_presence) |
301 | mod_timer(&dev->check_pres_timer, jiffies + | 335 | mod_timer(&dev->check_pres_timer, jiffies + |
@@ -327,11 +361,21 @@ int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx) | |||
327 | goto error; | 361 | goto error; |
328 | } | 362 | } |
329 | 363 | ||
364 | if (dev->active_target == NULL) { | ||
365 | rc = -ENOTCONN; | ||
366 | goto error; | ||
367 | } | ||
368 | |||
369 | if (dev->active_target->idx != target_idx) { | ||
370 | rc = -ENOTCONN; | ||
371 | goto error; | ||
372 | } | ||
373 | |||
330 | if (dev->ops->check_presence) | 374 | if (dev->ops->check_presence) |
331 | del_timer_sync(&dev->check_pres_timer); | 375 | del_timer_sync(&dev->check_pres_timer); |
332 | 376 | ||
333 | dev->ops->deactivate_target(dev, target_idx); | 377 | dev->ops->deactivate_target(dev, dev->active_target); |
334 | dev->activated_target_idx = NFC_TARGET_IDX_NONE; | 378 | dev->active_target = NULL; |
335 | 379 | ||
336 | error: | 380 | error: |
337 | device_unlock(&dev->dev); | 381 | device_unlock(&dev->dev); |
@@ -365,13 +409,13 @@ int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, struct sk_buff *skb, | |||
365 | goto error; | 409 | goto error; |
366 | } | 410 | } |
367 | 411 | ||
368 | if (dev->activated_target_idx == NFC_TARGET_IDX_NONE) { | 412 | if (dev->active_target == NULL) { |
369 | rc = -ENOTCONN; | 413 | rc = -ENOTCONN; |
370 | kfree_skb(skb); | 414 | kfree_skb(skb); |
371 | goto error; | 415 | goto error; |
372 | } | 416 | } |
373 | 417 | ||
374 | if (target_idx != dev->activated_target_idx) { | 418 | if (dev->active_target->idx != target_idx) { |
375 | rc = -EADDRNOTAVAIL; | 419 | rc = -EADDRNOTAVAIL; |
376 | kfree_skb(skb); | 420 | kfree_skb(skb); |
377 | goto error; | 421 | goto error; |
@@ -380,7 +424,8 @@ int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, struct sk_buff *skb, | |||
380 | if (dev->ops->check_presence) | 424 | if (dev->ops->check_presence) |
381 | del_timer_sync(&dev->check_pres_timer); | 425 | del_timer_sync(&dev->check_pres_timer); |
382 | 426 | ||
383 | rc = dev->ops->data_exchange(dev, target_idx, skb, cb, cb_context); | 427 | rc = dev->ops->data_exchange(dev, dev->active_target, skb, cb, |
428 | cb_context); | ||
384 | 429 | ||
385 | if (!rc && dev->ops->check_presence) | 430 | if (!rc && dev->ops->check_presence) |
386 | mod_timer(&dev->check_pres_timer, jiffies + | 431 | mod_timer(&dev->check_pres_timer, jiffies + |
@@ -514,7 +559,7 @@ int nfc_target_lost(struct nfc_dev *dev, u32 target_idx) | |||
514 | 559 | ||
515 | dev->targets_generation++; | 560 | dev->targets_generation++; |
516 | dev->n_targets--; | 561 | dev->n_targets--; |
517 | dev->activated_target_idx = NFC_TARGET_IDX_NONE; | 562 | dev->active_target = NULL; |
518 | 563 | ||
519 | if (dev->n_targets) { | 564 | if (dev->n_targets) { |
520 | memcpy(&dev->targets[i], &dev->targets[i + 1], | 565 | memcpy(&dev->targets[i], &dev->targets[i + 1], |
@@ -556,15 +601,14 @@ static void nfc_check_pres_work(struct work_struct *work) | |||
556 | 601 | ||
557 | device_lock(&dev->dev); | 602 | device_lock(&dev->dev); |
558 | 603 | ||
559 | if (dev->activated_target_idx != NFC_TARGET_IDX_NONE && | 604 | if (dev->active_target && timer_pending(&dev->check_pres_timer) == 0) { |
560 | timer_pending(&dev->check_pres_timer) == 0) { | 605 | rc = dev->ops->check_presence(dev, dev->active_target); |
561 | rc = dev->ops->check_presence(dev, dev->activated_target_idx); | ||
562 | if (!rc) { | 606 | if (!rc) { |
563 | mod_timer(&dev->check_pres_timer, jiffies + | 607 | mod_timer(&dev->check_pres_timer, jiffies + |
564 | msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); | 608 | msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); |
565 | } else { | 609 | } else { |
566 | nfc_target_lost(dev, dev->activated_target_idx); | 610 | nfc_target_lost(dev, dev->active_target->idx); |
567 | dev->activated_target_idx = NFC_TARGET_IDX_NONE; | 611 | dev->active_target = NULL; |
568 | } | 612 | } |
569 | } | 613 | } |
570 | 614 | ||
@@ -643,8 +687,6 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, | |||
643 | /* first generation must not be 0 */ | 687 | /* first generation must not be 0 */ |
644 | dev->targets_generation = 1; | 688 | dev->targets_generation = 1; |
645 | 689 | ||
646 | dev->activated_target_idx = NFC_TARGET_IDX_NONE; | ||
647 | |||
648 | if (ops->check_presence) { | 690 | if (ops->check_presence) { |
649 | char name[32]; | 691 | char name[32]; |
650 | init_timer(&dev->check_pres_timer); | 692 | init_timer(&dev->check_pres_timer); |
@@ -662,7 +704,6 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, | |||
662 | } | 704 | } |
663 | } | 705 | } |
664 | 706 | ||
665 | |||
666 | return dev; | 707 | return dev; |
667 | } | 708 | } |
668 | EXPORT_SYMBOL(nfc_allocate_device); | 709 | EXPORT_SYMBOL(nfc_allocate_device); |