diff options
-rw-r--r-- | drivers/nfc/pn533.c | 2 | ||||
-rw-r--r-- | include/linux/nfc.h | 6 | ||||
-rw-r--r-- | include/net/nfc.h | 4 | ||||
-rw-r--r-- | net/nfc/core.c | 77 | ||||
-rw-r--r-- | net/nfc/netlink.c | 56 | ||||
-rw-r--r-- | net/nfc/nfc.h | 4 |
6 files changed, 149 insertions, 0 deletions
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index f81a93e5b59d..c78eb6afd0cb 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c | |||
@@ -1432,6 +1432,8 @@ static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata, | |||
1432 | } | 1432 | } |
1433 | 1433 | ||
1434 | struct nfc_ops pn533_nfc_ops = { | 1434 | struct nfc_ops pn533_nfc_ops = { |
1435 | .dev_up = NULL, | ||
1436 | .dev_down = NULL, | ||
1435 | .start_poll = pn533_start_poll, | 1437 | .start_poll = pn533_start_poll, |
1436 | .stop_poll = pn533_stop_poll, | 1438 | .stop_poll = pn533_stop_poll, |
1437 | .activate_target = pn533_activate_target, | 1439 | .activate_target = pn533_activate_target, |
diff --git a/include/linux/nfc.h b/include/linux/nfc.h index c525e0b5876b..36cb955b05cc 100644 --- a/include/linux/nfc.h +++ b/include/linux/nfc.h | |||
@@ -39,6 +39,10 @@ | |||
39 | * | 39 | * |
40 | * @NFC_CMD_GET_DEVICE: request information about a device (requires | 40 | * @NFC_CMD_GET_DEVICE: request information about a device (requires |
41 | * %NFC_ATTR_DEVICE_INDEX) or dump request to get a list of all nfc devices | 41 | * %NFC_ATTR_DEVICE_INDEX) or dump request to get a list of all nfc devices |
42 | * @NFC_CMD_DEV_UP: turn on the nfc device | ||
43 | * (requires %NFC_ATTR_DEVICE_INDEX) | ||
44 | * @NFC_CMD_DEV_DOWN: turn off the nfc device | ||
45 | * (requires %NFC_ATTR_DEVICE_INDEX) | ||
42 | * @NFC_CMD_START_POLL: start polling for targets using the given protocols | 46 | * @NFC_CMD_START_POLL: start polling for targets using the given protocols |
43 | * (requires %NFC_ATTR_DEVICE_INDEX and %NFC_ATTR_PROTOCOLS) | 47 | * (requires %NFC_ATTR_DEVICE_INDEX and %NFC_ATTR_PROTOCOLS) |
44 | * @NFC_CMD_STOP_POLL: stop polling for targets (requires | 48 | * @NFC_CMD_STOP_POLL: stop polling for targets (requires |
@@ -56,6 +60,8 @@ | |||
56 | enum nfc_commands { | 60 | enum nfc_commands { |
57 | NFC_CMD_UNSPEC, | 61 | NFC_CMD_UNSPEC, |
58 | NFC_CMD_GET_DEVICE, | 62 | NFC_CMD_GET_DEVICE, |
63 | NFC_CMD_DEV_UP, | ||
64 | NFC_CMD_DEV_DOWN, | ||
59 | NFC_CMD_START_POLL, | 65 | NFC_CMD_START_POLL, |
60 | NFC_CMD_STOP_POLL, | 66 | NFC_CMD_STOP_POLL, |
61 | NFC_CMD_GET_TARGET, | 67 | NFC_CMD_GET_TARGET, |
diff --git a/include/net/nfc.h b/include/net/nfc.h index 87b51fe15b70..6a7f602aa841 100644 --- a/include/net/nfc.h +++ b/include/net/nfc.h | |||
@@ -48,6 +48,8 @@ typedef void (*data_exchange_cb_t)(void *context, struct sk_buff *skb, | |||
48 | int err); | 48 | int err); |
49 | 49 | ||
50 | struct nfc_ops { | 50 | struct nfc_ops { |
51 | int (*dev_up)(struct nfc_dev *dev); | ||
52 | int (*dev_down)(struct nfc_dev *dev); | ||
51 | int (*start_poll)(struct nfc_dev *dev, u32 protocols); | 53 | int (*start_poll)(struct nfc_dev *dev, u32 protocols); |
52 | void (*stop_poll)(struct nfc_dev *dev); | 54 | void (*stop_poll)(struct nfc_dev *dev); |
53 | int (*activate_target)(struct nfc_dev *dev, u32 target_idx, | 55 | int (*activate_target)(struct nfc_dev *dev, u32 target_idx, |
@@ -78,7 +80,9 @@ struct nfc_dev { | |||
78 | int targets_generation; | 80 | int targets_generation; |
79 | spinlock_t targets_lock; | 81 | spinlock_t targets_lock; |
80 | struct device dev; | 82 | struct device dev; |
83 | bool dev_up; | ||
81 | bool polling; | 84 | bool polling; |
85 | bool remote_activated; | ||
82 | struct nfc_genl_data genl_data; | 86 | struct nfc_genl_data genl_data; |
83 | u32 supported_protocols; | 87 | u32 supported_protocols; |
84 | 88 | ||
diff --git a/net/nfc/core.c b/net/nfc/core.c index 284e2f6a14ff..47e02c1b8c02 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c | |||
@@ -53,6 +53,80 @@ int nfc_printk(const char *level, const char *format, ...) | |||
53 | EXPORT_SYMBOL(nfc_printk); | 53 | EXPORT_SYMBOL(nfc_printk); |
54 | 54 | ||
55 | /** | 55 | /** |
56 | * nfc_dev_up - turn on the NFC device | ||
57 | * | ||
58 | * @dev: The nfc device to be turned on | ||
59 | * | ||
60 | * The device remains up until the nfc_dev_down function is called. | ||
61 | */ | ||
62 | int nfc_dev_up(struct nfc_dev *dev) | ||
63 | { | ||
64 | int rc = 0; | ||
65 | |||
66 | nfc_dbg("dev_name=%s", dev_name(&dev->dev)); | ||
67 | |||
68 | device_lock(&dev->dev); | ||
69 | |||
70 | if (!device_is_registered(&dev->dev)) { | ||
71 | rc = -ENODEV; | ||
72 | goto error; | ||
73 | } | ||
74 | |||
75 | if (dev->dev_up) { | ||
76 | rc = -EALREADY; | ||
77 | goto error; | ||
78 | } | ||
79 | |||
80 | if (dev->ops->dev_up) | ||
81 | rc = dev->ops->dev_up(dev); | ||
82 | |||
83 | if (!rc) | ||
84 | dev->dev_up = true; | ||
85 | |||
86 | error: | ||
87 | device_unlock(&dev->dev); | ||
88 | return rc; | ||
89 | } | ||
90 | |||
91 | /** | ||
92 | * nfc_dev_down - turn off the NFC device | ||
93 | * | ||
94 | * @dev: The nfc device to be turned off | ||
95 | */ | ||
96 | int nfc_dev_down(struct nfc_dev *dev) | ||
97 | { | ||
98 | int rc = 0; | ||
99 | |||
100 | nfc_dbg("dev_name=%s", dev_name(&dev->dev)); | ||
101 | |||
102 | device_lock(&dev->dev); | ||
103 | |||
104 | if (!device_is_registered(&dev->dev)) { | ||
105 | rc = -ENODEV; | ||
106 | goto error; | ||
107 | } | ||
108 | |||
109 | if (!dev->dev_up) { | ||
110 | rc = -EALREADY; | ||
111 | goto error; | ||
112 | } | ||
113 | |||
114 | if (dev->polling || dev->remote_activated) { | ||
115 | rc = -EBUSY; | ||
116 | goto error; | ||
117 | } | ||
118 | |||
119 | if (dev->ops->dev_down) | ||
120 | dev->ops->dev_down(dev); | ||
121 | |||
122 | dev->dev_up = false; | ||
123 | |||
124 | error: | ||
125 | device_unlock(&dev->dev); | ||
126 | return rc; | ||
127 | } | ||
128 | |||
129 | /** | ||
56 | * nfc_start_poll - start polling for nfc targets | 130 | * nfc_start_poll - start polling for nfc targets |
57 | * | 131 | * |
58 | * @dev: The nfc device that must start polling | 132 | * @dev: The nfc device that must start polling |
@@ -144,6 +218,8 @@ int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol) | |||
144 | } | 218 | } |
145 | 219 | ||
146 | rc = dev->ops->activate_target(dev, target_idx, protocol); | 220 | rc = dev->ops->activate_target(dev, target_idx, protocol); |
221 | if (!rc) | ||
222 | dev->remote_activated = true; | ||
147 | 223 | ||
148 | error: | 224 | error: |
149 | device_unlock(&dev->dev); | 225 | device_unlock(&dev->dev); |
@@ -170,6 +246,7 @@ int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx) | |||
170 | } | 246 | } |
171 | 247 | ||
172 | dev->ops->deactivate_target(dev, target_idx); | 248 | dev->ops->deactivate_target(dev, target_idx); |
249 | dev->remote_activated = false; | ||
173 | 250 | ||
174 | error: | 251 | error: |
175 | device_unlock(&dev->dev); | 252 | device_unlock(&dev->dev); |
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index ccdff7953f7d..03f8818e1f16 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c | |||
@@ -367,6 +367,52 @@ out_putdev: | |||
367 | return rc; | 367 | return rc; |
368 | } | 368 | } |
369 | 369 | ||
370 | static int nfc_genl_dev_up(struct sk_buff *skb, struct genl_info *info) | ||
371 | { | ||
372 | struct nfc_dev *dev; | ||
373 | int rc; | ||
374 | u32 idx; | ||
375 | |||
376 | nfc_dbg("entry"); | ||
377 | |||
378 | if (!info->attrs[NFC_ATTR_DEVICE_INDEX]) | ||
379 | return -EINVAL; | ||
380 | |||
381 | idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); | ||
382 | |||
383 | dev = nfc_get_device(idx); | ||
384 | if (!dev) | ||
385 | return -ENODEV; | ||
386 | |||
387 | rc = nfc_dev_up(dev); | ||
388 | |||
389 | nfc_put_device(dev); | ||
390 | return rc; | ||
391 | } | ||
392 | |||
393 | static int nfc_genl_dev_down(struct sk_buff *skb, struct genl_info *info) | ||
394 | { | ||
395 | struct nfc_dev *dev; | ||
396 | int rc; | ||
397 | u32 idx; | ||
398 | |||
399 | nfc_dbg("entry"); | ||
400 | |||
401 | if (!info->attrs[NFC_ATTR_DEVICE_INDEX]) | ||
402 | return -EINVAL; | ||
403 | |||
404 | idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); | ||
405 | |||
406 | dev = nfc_get_device(idx); | ||
407 | if (!dev) | ||
408 | return -ENODEV; | ||
409 | |||
410 | rc = nfc_dev_down(dev); | ||
411 | |||
412 | nfc_put_device(dev); | ||
413 | return rc; | ||
414 | } | ||
415 | |||
370 | static int nfc_genl_start_poll(struct sk_buff *skb, struct genl_info *info) | 416 | static int nfc_genl_start_poll(struct sk_buff *skb, struct genl_info *info) |
371 | { | 417 | { |
372 | struct nfc_dev *dev; | 418 | struct nfc_dev *dev; |
@@ -441,6 +487,16 @@ static struct genl_ops nfc_genl_ops[] = { | |||
441 | .policy = nfc_genl_policy, | 487 | .policy = nfc_genl_policy, |
442 | }, | 488 | }, |
443 | { | 489 | { |
490 | .cmd = NFC_CMD_DEV_UP, | ||
491 | .doit = nfc_genl_dev_up, | ||
492 | .policy = nfc_genl_policy, | ||
493 | }, | ||
494 | { | ||
495 | .cmd = NFC_CMD_DEV_DOWN, | ||
496 | .doit = nfc_genl_dev_down, | ||
497 | .policy = nfc_genl_policy, | ||
498 | }, | ||
499 | { | ||
444 | .cmd = NFC_CMD_START_POLL, | 500 | .cmd = NFC_CMD_START_POLL, |
445 | .doit = nfc_genl_start_poll, | 501 | .doit = nfc_genl_start_poll, |
446 | .policy = nfc_genl_policy, | 502 | .policy = nfc_genl_policy, |
diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h index aaf9832298f3..1a877de8e230 100644 --- a/net/nfc/nfc.h +++ b/net/nfc/nfc.h | |||
@@ -101,6 +101,10 @@ static inline void nfc_device_iter_exit(struct class_dev_iter *iter) | |||
101 | class_dev_iter_exit(iter); | 101 | class_dev_iter_exit(iter); |
102 | } | 102 | } |
103 | 103 | ||
104 | int nfc_dev_up(struct nfc_dev *dev); | ||
105 | |||
106 | int nfc_dev_down(struct nfc_dev *dev); | ||
107 | |||
104 | int nfc_start_poll(struct nfc_dev *dev, u32 protocols); | 108 | int nfc_start_poll(struct nfc_dev *dev, u32 protocols); |
105 | 109 | ||
106 | int nfc_stop_poll(struct nfc_dev *dev); | 110 | int nfc_stop_poll(struct nfc_dev *dev); |