Skip to content

Commit 1ed28f6

Browse files
Samuel Ortizlinvjw
authored andcommitted
NFC: Add a DEP link control netlink command
NFC-DEP (Data Exchange Protocol) is an NFC MAC layer. This command allows to enable and disable the DEP link on to which e.g. LLCP can run. Signed-off-by: Samuel Ortiz <sameo@linux.intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
1 parent db81a62 commit 1ed28f6

File tree

5 files changed

+255
-0
lines changed

5 files changed

+255
-0
lines changed

include/linux/nfc.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ enum nfc_commands {
6262
NFC_CMD_GET_DEVICE,
6363
NFC_CMD_DEV_UP,
6464
NFC_CMD_DEV_DOWN,
65+
NFC_CMD_DEP_LINK_UP,
66+
NFC_CMD_DEP_LINK_DOWN,
6567
NFC_CMD_START_POLL,
6668
NFC_CMD_STOP_POLL,
6769
NFC_CMD_GET_TARGET,
@@ -86,6 +88,8 @@ enum nfc_commands {
8688
* @NFC_ATTR_TARGET_SENS_RES: NFC-A targets extra information such as NFCID
8789
* @NFC_ATTR_TARGET_SEL_RES: NFC-A targets extra information (useful if the
8890
* target is not NFC-Forum compliant)
91+
* @NFC_ATTR_COMM_MODE: Passive or active mode
92+
* @NFC_ATTR_RF_MODE: Initiator or target
8993
*/
9094
enum nfc_attrs {
9195
NFC_ATTR_UNSPEC,
@@ -95,6 +99,8 @@ enum nfc_attrs {
9599
NFC_ATTR_TARGET_INDEX,
96100
NFC_ATTR_TARGET_SENS_RES,
97101
NFC_ATTR_TARGET_SEL_RES,
102+
NFC_ATTR_COMM_MODE,
103+
NFC_ATTR_RF_MODE,
98104
/* private: internal use only */
99105
__NFC_ATTR_AFTER_LAST
100106
};
@@ -111,6 +117,14 @@ enum nfc_attrs {
111117

112118
#define NFC_PROTO_MAX 6
113119

120+
/* NFC communication modes */
121+
#define NFC_COMM_ACTIVE 0
122+
#define NFC_COMM_PASSIVE 1
123+
124+
/* NFC RF modes */
125+
#define NFC_RF_INITIATOR 0
126+
#define NFC_RF_TARGET 1
127+
114128
/* NFC protocols masks used in bitsets */
115129
#define NFC_PROTO_JEWEL_MASK (1 << NFC_PROTO_JEWEL)
116130
#define NFC_PROTO_MIFARE_MASK (1 << NFC_PROTO_MIFARE)

include/net/nfc/nfc.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ struct nfc_ops {
5252
int (*dev_down)(struct nfc_dev *dev);
5353
int (*start_poll)(struct nfc_dev *dev, u32 protocols);
5454
void (*stop_poll)(struct nfc_dev *dev);
55+
int (*dep_link_up)(struct nfc_dev *dev, int target_idx,
56+
u8 comm_mode, u8 rf_mode);
57+
int (*dep_link_down)(struct nfc_dev *dev);
5558
int (*activate_target)(struct nfc_dev *dev, u32 target_idx,
5659
u32 protocol);
5760
void (*deactivate_target)(struct nfc_dev *dev, u32 target_idx);
@@ -60,6 +63,9 @@ struct nfc_ops {
6063
void *cb_context);
6164
};
6265

66+
#define NFC_TARGET_IDX_ANY -1
67+
#define NFC_MAX_GT_LEN 48
68+
6369
struct nfc_target {
6470
u32 idx;
6571
u32 supported_protocols;
@@ -83,6 +89,8 @@ struct nfc_dev {
8389
bool dev_up;
8490
bool polling;
8591
bool remote_activated;
92+
bool dep_link_up;
93+
u32 dep_rf_mode;
8694
struct nfc_genl_data genl_data;
8795
u32 supported_protocols;
8896

@@ -165,4 +173,7 @@ struct sk_buff *nfc_alloc_recv_skb(unsigned int size, gfp_t gfp);
165173
int nfc_targets_found(struct nfc_dev *dev, struct nfc_target *targets,
166174
int ntargets);
167175

176+
int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx,
177+
u8 comm_mode, u8 rf_mode);
178+
168179
#endif /* __NET_NFC_H */

net/nfc/core.c

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,83 @@ int nfc_stop_poll(struct nfc_dev *dev)
181181
return rc;
182182
}
183183

184+
int nfc_dep_link_up(struct nfc_dev *dev, int target_index,
185+
u8 comm_mode, u8 rf_mode)
186+
{
187+
int rc = 0;
188+
189+
pr_debug("dev_name=%s comm:%d rf:%d\n",
190+
dev_name(&dev->dev), comm_mode, rf_mode);
191+
192+
if (!dev->ops->dep_link_up)
193+
return -EOPNOTSUPP;
194+
195+
device_lock(&dev->dev);
196+
197+
if (!device_is_registered(&dev->dev)) {
198+
rc = -ENODEV;
199+
goto error;
200+
}
201+
202+
if (dev->dep_link_up == true) {
203+
rc = -EALREADY;
204+
goto error;
205+
}
206+
207+
rc = dev->ops->dep_link_up(dev, target_index, comm_mode, rf_mode);
208+
209+
error:
210+
device_unlock(&dev->dev);
211+
return rc;
212+
}
213+
214+
int nfc_dep_link_down(struct nfc_dev *dev)
215+
{
216+
int rc = 0;
217+
218+
pr_debug("dev_name=%s\n", dev_name(&dev->dev));
219+
220+
if (!dev->ops->dep_link_down)
221+
return -EOPNOTSUPP;
222+
223+
device_lock(&dev->dev);
224+
225+
if (!device_is_registered(&dev->dev)) {
226+
rc = -ENODEV;
227+
goto error;
228+
}
229+
230+
if (dev->dep_link_up == false) {
231+
rc = -EALREADY;
232+
goto error;
233+
}
234+
235+
if (dev->dep_rf_mode == NFC_RF_TARGET) {
236+
rc = -EOPNOTSUPP;
237+
goto error;
238+
}
239+
240+
rc = dev->ops->dep_link_down(dev);
241+
if (!rc) {
242+
dev->dep_link_up = false;
243+
nfc_genl_dep_link_down_event(dev);
244+
}
245+
246+
error:
247+
device_unlock(&dev->dev);
248+
return rc;
249+
}
250+
251+
int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx,
252+
u8 comm_mode, u8 rf_mode)
253+
{
254+
dev->dep_link_up = true;
255+
dev->dep_rf_mode = rf_mode;
256+
257+
return nfc_genl_dep_link_up_event(dev, target_idx, comm_mode, rf_mode);
258+
}
259+
EXPORT_SYMBOL(nfc_dep_link_is_up);
260+
184261
/**
185262
* nfc_activate_target - prepare the target for data exchange
186263
*

net/nfc/netlink.c

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ static const struct nla_policy nfc_genl_policy[NFC_ATTR_MAX + 1] = {
4646
[NFC_ATTR_DEVICE_NAME] = { .type = NLA_STRING,
4747
.len = NFC_DEVICE_NAME_MAXSIZE },
4848
[NFC_ATTR_PROTOCOLS] = { .type = NLA_U32 },
49+
[NFC_ATTR_COMM_MODE] = { .type = NLA_U8 },
50+
[NFC_ATTR_RF_MODE] = { .type = NLA_U8 },
4951
};
5052

5153
static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target,
@@ -311,6 +313,75 @@ static int nfc_genl_dump_devices_done(struct netlink_callback *cb)
311313
return 0;
312314
}
313315

316+
int nfc_genl_dep_link_up_event(struct nfc_dev *dev, u32 target_idx,
317+
u8 comm_mode, u8 rf_mode)
318+
{
319+
struct sk_buff *msg;
320+
void *hdr;
321+
322+
pr_debug("DEP link is up\n");
323+
324+
msg = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC);
325+
if (!msg)
326+
return -ENOMEM;
327+
328+
hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0,
329+
NFC_CMD_DEP_LINK_UP);
330+
if (!hdr)
331+
goto free_msg;
332+
333+
NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx);
334+
if (rf_mode == NFC_RF_INITIATOR)
335+
NLA_PUT_U32(msg, NFC_ATTR_TARGET_INDEX, target_idx);
336+
NLA_PUT_U8(msg, NFC_ATTR_COMM_MODE, comm_mode);
337+
NLA_PUT_U8(msg, NFC_ATTR_RF_MODE, rf_mode);
338+
339+
genlmsg_end(msg, hdr);
340+
341+
dev->dep_link_up = true;
342+
343+
genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_ATOMIC);
344+
345+
return 0;
346+
347+
nla_put_failure:
348+
genlmsg_cancel(msg, hdr);
349+
free_msg:
350+
nlmsg_free(msg);
351+
return -EMSGSIZE;
352+
}
353+
354+
int nfc_genl_dep_link_down_event(struct nfc_dev *dev)
355+
{
356+
struct sk_buff *msg;
357+
void *hdr;
358+
359+
pr_debug("DEP link is down\n");
360+
361+
msg = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC);
362+
if (!msg)
363+
return -ENOMEM;
364+
365+
hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0,
366+
NFC_CMD_DEP_LINK_DOWN);
367+
if (!hdr)
368+
goto free_msg;
369+
370+
NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx);
371+
372+
genlmsg_end(msg, hdr);
373+
374+
genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_ATOMIC);
375+
376+
return 0;
377+
378+
nla_put_failure:
379+
genlmsg_cancel(msg, hdr);
380+
free_msg:
381+
nlmsg_free(msg);
382+
return -EMSGSIZE;
383+
}
384+
314385
static int nfc_genl_get_device(struct sk_buff *skb, struct genl_info *info)
315386
{
316387
struct sk_buff *msg;
@@ -398,6 +469,8 @@ static int nfc_genl_start_poll(struct sk_buff *skb, struct genl_info *info)
398469
u32 idx;
399470
u32 protocols;
400471

472+
pr_debug("Poll start\n");
473+
401474
if (!info->attrs[NFC_ATTR_DEVICE_INDEX] ||
402475
!info->attrs[NFC_ATTR_PROTOCOLS])
403476
return -EINVAL;
@@ -452,6 +525,67 @@ static int nfc_genl_stop_poll(struct sk_buff *skb, struct genl_info *info)
452525
return rc;
453526
}
454527

528+
static int nfc_genl_dep_link_up(struct sk_buff *skb, struct genl_info *info)
529+
{
530+
struct nfc_dev *dev;
531+
int rc, tgt_idx;
532+
u32 idx;
533+
u8 comm, rf;
534+
535+
pr_debug("DEP link up\n");
536+
537+
if (!info->attrs[NFC_ATTR_DEVICE_INDEX] ||
538+
!info->attrs[NFC_ATTR_COMM_MODE] ||
539+
!info->attrs[NFC_ATTR_RF_MODE])
540+
return -EINVAL;
541+
542+
idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
543+
if (!info->attrs[NFC_ATTR_TARGET_INDEX])
544+
tgt_idx = NFC_TARGET_IDX_ANY;
545+
else
546+
tgt_idx = nla_get_u32(info->attrs[NFC_ATTR_TARGET_INDEX]);
547+
548+
comm = nla_get_u8(info->attrs[NFC_ATTR_COMM_MODE]);
549+
rf = nla_get_u8(info->attrs[NFC_ATTR_RF_MODE]);
550+
551+
if (comm != NFC_COMM_ACTIVE && comm != NFC_COMM_PASSIVE)
552+
return -EINVAL;
553+
554+
if (rf != NFC_RF_INITIATOR && comm != NFC_RF_TARGET)
555+
return -EINVAL;
556+
557+
dev = nfc_get_device(idx);
558+
if (!dev)
559+
return -ENODEV;
560+
561+
rc = nfc_dep_link_up(dev, tgt_idx, comm, rf);
562+
563+
nfc_put_device(dev);
564+
565+
return rc;
566+
}
567+
568+
static int nfc_genl_dep_link_down(struct sk_buff *skb, struct genl_info *info)
569+
{
570+
struct nfc_dev *dev;
571+
int rc;
572+
u32 idx;
573+
574+
if (!info->attrs[NFC_ATTR_DEVICE_INDEX])
575+
return -EINVAL;
576+
577+
idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
578+
579+
dev = nfc_get_device(idx);
580+
if (!dev)
581+
return -ENODEV;
582+
583+
rc = nfc_dep_link_down(dev);
584+
585+
nfc_put_device(dev);
586+
return rc;
587+
}
588+
455589
static struct genl_ops nfc_genl_ops[] = {
456590
{
457591
.cmd = NFC_CMD_GET_DEVICE,
@@ -480,6 +614,16 @@ static struct genl_ops nfc_genl_ops[] = {
480614
.doit = nfc_genl_stop_poll,
481615
.policy = nfc_genl_policy,
482616
},
617+
{
618+
.cmd = NFC_CMD_DEP_LINK_UP,
619+
.doit = nfc_genl_dep_link_up,
620+
.policy = nfc_genl_policy,
621+
},
622+
{
623+
.cmd = NFC_CMD_DEP_LINK_DOWN,
624+
.doit = nfc_genl_dep_link_down,
625+
.policy = nfc_genl_policy,
626+
},
483627
{
484628
.cmd = NFC_CMD_GET_TARGET,
485629
.dumpit = nfc_genl_dump_targets,

net/nfc/nfc.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ int nfc_genl_targets_found(struct nfc_dev *dev);
6868
int nfc_genl_device_added(struct nfc_dev *dev);
6969
int nfc_genl_device_removed(struct nfc_dev *dev);
7070

71+
int nfc_genl_dep_link_up_event(struct nfc_dev *dev, u32 target_idx,
72+
u8 comm_mode, u8 rf_mode);
73+
int nfc_genl_dep_link_down_event(struct nfc_dev *dev);
74+
7175
struct nfc_dev *nfc_get_device(unsigned idx);
7276

7377
static inline void nfc_put_device(struct nfc_dev *dev)
@@ -102,6 +106,11 @@ int nfc_start_poll(struct nfc_dev *dev, u32 protocols);
102106

103107
int nfc_stop_poll(struct nfc_dev *dev);
104108

109+
int nfc_dep_link_up(struct nfc_dev *dev, int target_idx,
110+
u8 comm_mode, u8 rf_mode);
111+
112+
int nfc_dep_link_down(struct nfc_dev *dev);
113+
105114
int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol);
106115

107116
int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx);

0 commit comments

Comments
 (0)