NFC: Add target mode activation netlink event
Userspace gets a netlink event upon target mode activation. The LLCP layer is also signaled when we get an ATR_REQ in order to get the remote general bytes. Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
This commit is contained in:
Родитель
ad3823cef6
Коммит
fc40a8c1a0
|
@ -260,6 +260,10 @@ struct pn533_cmd_jump_dep_response {
|
|||
#define PN533_INIT_TARGET_PASSIVE 0x1
|
||||
#define PN533_INIT_TARGET_DEP 0x2
|
||||
|
||||
#define PN533_INIT_TARGET_RESP_FRAME_MASK 0x3
|
||||
#define PN533_INIT_TARGET_RESP_ACTIVE 0x1
|
||||
#define PN533_INIT_TARGET_RESP_DEP 0x4
|
||||
|
||||
struct pn533_cmd_init_target {
|
||||
u8 mode;
|
||||
u8 mifare[6];
|
||||
|
@ -1128,10 +1132,13 @@ static int pn533_init_target_frame(struct pn533_frame *frame,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define ATR_REQ_GB_OFFSET 17
|
||||
static int pn533_init_target_complete(struct pn533 *dev, void *arg,
|
||||
u8 *params, int params_len)
|
||||
{
|
||||
struct pn533_cmd_init_target_response *resp;
|
||||
u8 frame, comm_mode = NFC_COMM_PASSIVE, *gb;
|
||||
size_t gb_len;
|
||||
|
||||
nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
|
||||
|
||||
|
@ -1143,11 +1150,27 @@ static int pn533_init_target_complete(struct pn533 *dev, void *arg,
|
|||
return params_len;
|
||||
}
|
||||
|
||||
if (params_len < ATR_REQ_GB_OFFSET + 1)
|
||||
return -EINVAL;
|
||||
|
||||
resp = (struct pn533_cmd_init_target_response *) params;
|
||||
|
||||
nfc_dev_dbg(&dev->interface->dev, "Target mode 0x%x\n", resp->mode);
|
||||
nfc_dev_dbg(&dev->interface->dev, "Target mode 0x%x param len %d\n",
|
||||
resp->mode, params_len);
|
||||
|
||||
return 0;
|
||||
frame = resp->mode & PN533_INIT_TARGET_RESP_FRAME_MASK;
|
||||
if (frame == PN533_INIT_TARGET_RESP_ACTIVE)
|
||||
comm_mode = NFC_COMM_ACTIVE;
|
||||
|
||||
/* Again, only DEP */
|
||||
if ((resp->mode & PN533_INIT_TARGET_RESP_DEP) == 0)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
gb = resp->cmd + ATR_REQ_GB_OFFSET;
|
||||
gb_len = params_len - (ATR_REQ_GB_OFFSET + 1);
|
||||
|
||||
return nfc_tm_activated(dev->nfc_dev, NFC_PROTO_NFC_DEP_MASK,
|
||||
comm_mode, gb, gb_len);
|
||||
}
|
||||
|
||||
static int pn533_init_target(struct nfc_dev *nfc_dev, u32 protocols)
|
||||
|
|
|
@ -56,6 +56,10 @@
|
|||
* %NFC_ATTR_PROTOCOLS)
|
||||
* @NFC_EVENT_DEVICE_REMOVED: event emitted when a device is removed
|
||||
* (it sends %NFC_ATTR_DEVICE_INDEX)
|
||||
* @NFC_EVENT_TM_ACTIVATED: event emitted when the adapter is activated in
|
||||
* target mode.
|
||||
* @NFC_EVENT_DEVICE_DEACTIVATED: event emitted when the adapter is deactivated
|
||||
* from target mode.
|
||||
*/
|
||||
enum nfc_commands {
|
||||
NFC_CMD_UNSPEC,
|
||||
|
@ -71,6 +75,8 @@ enum nfc_commands {
|
|||
NFC_EVENT_DEVICE_ADDED,
|
||||
NFC_EVENT_DEVICE_REMOVED,
|
||||
NFC_EVENT_TARGET_LOST,
|
||||
NFC_EVENT_TM_ACTIVATED,
|
||||
NFC_EVENT_TM_DEACTIVATED,
|
||||
/* private: internal use only */
|
||||
__NFC_CMD_AFTER_LAST
|
||||
};
|
||||
|
@ -122,6 +128,7 @@ enum nfc_attrs {
|
|||
#define NFC_NFCID1_MAXSIZE 10
|
||||
#define NFC_SENSB_RES_MAXSIZE 12
|
||||
#define NFC_SENSF_RES_MAXSIZE 18
|
||||
#define NFC_GB_MAXSIZE 48
|
||||
|
||||
/* NFC protocols */
|
||||
#define NFC_PROTO_JEWEL 1
|
||||
|
|
|
@ -198,4 +198,8 @@ int nfc_target_lost(struct nfc_dev *dev, u32 target_idx);
|
|||
int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx,
|
||||
u8 comm_mode, u8 rf_mode);
|
||||
|
||||
int nfc_tm_activated(struct nfc_dev *dev, u32 protocol, u8 comm_mode,
|
||||
u8 *gb, size_t gb_len);
|
||||
int nfc_tm_deactivated(struct nfc_dev *dev);
|
||||
|
||||
#endif /* __NET_NFC_H */
|
||||
|
|
|
@ -455,6 +455,41 @@ u8 *nfc_get_local_general_bytes(struct nfc_dev *dev, size_t *gb_len)
|
|||
}
|
||||
EXPORT_SYMBOL(nfc_get_local_general_bytes);
|
||||
|
||||
int nfc_tm_activated(struct nfc_dev *dev, u32 protocol, u8 comm_mode,
|
||||
u8 *gb, size_t gb_len)
|
||||
{
|
||||
int rc;
|
||||
|
||||
device_lock(&dev->dev);
|
||||
|
||||
dev->polling = false;
|
||||
|
||||
if (gb != NULL) {
|
||||
rc = nfc_set_remote_general_bytes(dev, gb, gb_len);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (protocol == NFC_PROTO_NFC_DEP_MASK)
|
||||
nfc_dep_link_is_up(dev, 0, comm_mode, NFC_RF_TARGET);
|
||||
|
||||
rc = nfc_genl_tm_activated(dev, protocol);
|
||||
|
||||
out:
|
||||
device_unlock(&dev->dev);
|
||||
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(nfc_tm_activated);
|
||||
|
||||
int nfc_tm_deactivated(struct nfc_dev *dev)
|
||||
{
|
||||
dev->dep_link_up = false;
|
||||
|
||||
return nfc_genl_tm_deactivated(dev);
|
||||
}
|
||||
EXPORT_SYMBOL(nfc_tm_deactivated);
|
||||
|
||||
/**
|
||||
* nfc_alloc_send_skb - allocate a skb for data exchange responses
|
||||
*
|
||||
|
|
|
@ -221,6 +221,68 @@ free_msg:
|
|||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
int nfc_genl_tm_activated(struct nfc_dev *dev, u32 protocol)
|
||||
{
|
||||
struct sk_buff *msg;
|
||||
void *hdr;
|
||||
|
||||
msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
|
||||
if (!msg)
|
||||
return -ENOMEM;
|
||||
|
||||
hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0,
|
||||
NFC_EVENT_TM_ACTIVATED);
|
||||
if (!hdr)
|
||||
goto free_msg;
|
||||
|
||||
if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx))
|
||||
goto nla_put_failure;
|
||||
if (nla_put_u32(msg, NFC_ATTR_TM_PROTOCOLS, protocol))
|
||||
goto nla_put_failure;
|
||||
|
||||
genlmsg_end(msg, hdr);
|
||||
|
||||
genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL);
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
genlmsg_cancel(msg, hdr);
|
||||
free_msg:
|
||||
nlmsg_free(msg);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
int nfc_genl_tm_deactivated(struct nfc_dev *dev)
|
||||
{
|
||||
struct sk_buff *msg;
|
||||
void *hdr;
|
||||
|
||||
msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
|
||||
if (!msg)
|
||||
return -ENOMEM;
|
||||
|
||||
hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0,
|
||||
NFC_EVENT_TM_DEACTIVATED);
|
||||
if (!hdr)
|
||||
goto free_msg;
|
||||
|
||||
if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx))
|
||||
goto nla_put_failure;
|
||||
|
||||
genlmsg_end(msg, hdr);
|
||||
|
||||
genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL);
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
genlmsg_cancel(msg, hdr);
|
||||
free_msg:
|
||||
nlmsg_free(msg);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
int nfc_genl_device_added(struct nfc_dev *dev)
|
||||
{
|
||||
struct sk_buff *msg;
|
||||
|
|
|
@ -128,6 +128,9 @@ int nfc_genl_dep_link_up_event(struct nfc_dev *dev, u32 target_idx,
|
|||
u8 comm_mode, u8 rf_mode);
|
||||
int nfc_genl_dep_link_down_event(struct nfc_dev *dev);
|
||||
|
||||
int nfc_genl_tm_activated(struct nfc_dev *dev, u32 protocol);
|
||||
int nfc_genl_tm_deactivated(struct nfc_dev *dev);
|
||||
|
||||
struct nfc_dev *nfc_get_device(unsigned int idx);
|
||||
|
||||
static inline void nfc_put_device(struct nfc_dev *dev)
|
||||
|
|
Загрузка…
Ссылка в новой задаче