Skip to content

Commit

Permalink
NFC: add nfc generic netlink interface
Browse files Browse the repository at this point in the history
The NFC generic netlink interface exports the NFC control operations
to the user space.

Signed-off-by: Lauro Ramos Venancio <lauro.venancio@openbossa.org>
Signed-off-by: Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Reviewed-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Lauro Ramos Venancio authored and John W. Linville committed Jul 5, 2011
1 parent 3e256b8 commit 4d12b8b
Show file tree
Hide file tree
Showing 6 changed files with 773 additions and 3 deletions.
112 changes: 112 additions & 0 deletions include/linux/nfc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
* Copyright (C) 2011 Instituto Nokia de Tecnologia
*
* Authors:
* Lauro Ramos Venancio <lauro.venancio@openbossa.org>
* Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/

#ifndef __LINUX_NFC_H
#define __LINUX_NFC_H

#define NFC_GENL_NAME "nfc"
#define NFC_GENL_VERSION 1

#define NFC_GENL_MCAST_EVENT_NAME "events"

/**
* enum nfc_commands - supported nfc commands
*
* @NFC_CMD_UNSPEC: unspecified command
*
* @NFC_CMD_GET_DEVICE: request information about a device (requires
* %NFC_ATTR_DEVICE_INDEX) or dump request to get a list of all nfc devices
* @NFC_CMD_START_POLL: start polling for targets using the given protocols
* (requires %NFC_ATTR_DEVICE_INDEX and %NFC_ATTR_PROTOCOLS)
* @NFC_CMD_STOP_POLL: stop polling for targets (requires
* %NFC_ATTR_DEVICE_INDEX)
* @NFC_CMD_GET_TARGET: dump all targets found by the previous poll (requires
* %NFC_ATTR_DEVICE_INDEX)
* @NFC_EVENT_TARGETS_FOUND: event emitted when a new target is found
* (it sends %NFC_ATTR_DEVICE_INDEX)
* @NFC_EVENT_DEVICE_ADDED: event emitted when a new device is registred
* (it sends %NFC_ATTR_DEVICE_NAME, %NFC_ATTR_DEVICE_INDEX and
* %NFC_ATTR_PROTOCOLS)
* @NFC_EVENT_DEVICE_REMOVED: event emitted when a device is removed
* (it sends %NFC_ATTR_DEVICE_INDEX)
*/
enum nfc_commands {
NFC_CMD_UNSPEC,
NFC_CMD_GET_DEVICE,
NFC_CMD_START_POLL,
NFC_CMD_STOP_POLL,
NFC_CMD_GET_TARGET,
NFC_EVENT_TARGETS_FOUND,
NFC_EVENT_DEVICE_ADDED,
NFC_EVENT_DEVICE_REMOVED,
/* private: internal use only */
__NFC_CMD_AFTER_LAST
};
#define NFC_CMD_MAX (__NFC_CMD_AFTER_LAST - 1)

/**
* enum nfc_attrs - supported nfc attributes
*
* @NFC_ATTR_UNSPEC: unspecified attribute
*
* @NFC_ATTR_DEVICE_INDEX: index of nfc device
* @NFC_ATTR_DEVICE_NAME: device name, max 8 chars
* @NFC_ATTR_PROTOCOLS: nfc protocols - bitwise or-ed combination from
* NFC_PROTO_*_MASK constants
* @NFC_ATTR_TARGET_INDEX: index of the nfc target
* @NFC_ATTR_TARGET_SENS_RES: NFC-A targets extra information such as NFCID
* @NFC_ATTR_TARGET_SEL_RES: NFC-A targets extra information (useful if the
* target is not NFC-Forum compliant)
*/
enum nfc_attrs {
NFC_ATTR_UNSPEC,
NFC_ATTR_DEVICE_INDEX,
NFC_ATTR_DEVICE_NAME,
NFC_ATTR_PROTOCOLS,
NFC_ATTR_TARGET_INDEX,
NFC_ATTR_TARGET_SENS_RES,
NFC_ATTR_TARGET_SEL_RES,
/* private: internal use only */
__NFC_ATTR_AFTER_LAST
};
#define NFC_ATTR_MAX (__NFC_ATTR_AFTER_LAST - 1)

#define NFC_DEVICE_NAME_MAXSIZE 8

/* NFC protocols */
#define NFC_PROTO_JEWEL 1
#define NFC_PROTO_MIFARE 2
#define NFC_PROTO_FELICA 3
#define NFC_PROTO_ISO14443 4
#define NFC_PROTO_NFC_DEP 5

#define NFC_PROTO_MAX 6

/* NFC protocols masks used in bitsets */
#define NFC_PROTO_JEWEL_MASK (1 << NFC_PROTO_JEWEL)
#define NFC_PROTO_MIFARE_MASK (1 << NFC_PROTO_MIFARE)
#define NFC_PROTO_FELICA_MASK (1 << NFC_PROTO_FELICA)
#define NFC_PROTO_ISO14443_MASK (1 << NFC_PROTO_ISO14443)
#define NFC_PROTO_NFC_DEP_MASK (1 << NFC_PROTO_NFC_DEP)

#endif /*__LINUX_NFC_H */
21 changes: 21 additions & 0 deletions include/net/nfc.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,28 @@ struct nfc_ops {
void *cb_context);
};

struct nfc_target {
u32 idx;
u32 supported_protocols;
u16 sens_res;
u8 sel_res;
};

struct nfc_genl_data {
u32 poll_req_pid;
struct mutex genl_data_mutex;
};

struct nfc_dev {
unsigned idx;
unsigned target_idx;
struct nfc_target *targets;
int n_targets;
int targets_generation;
spinlock_t targets_lock;
struct device dev;
bool polling;
struct nfc_genl_data genl_data;
u32 supported_protocols;

struct nfc_ops *ops;
Expand Down Expand Up @@ -132,4 +150,7 @@ static inline const char *nfc_device_name(struct nfc_dev *dev)

struct sk_buff *nfc_alloc_skb(unsigned int size, gfp_t gfp);

int nfc_targets_found(struct nfc_dev *dev, struct nfc_target *targets,
int ntargets);

#endif /* __NET_NFC_H */
2 changes: 1 addition & 1 deletion net/nfc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@

obj-$(CONFIG_NFC) += nfc.o

nfc-objs := core.o
nfc-objs := core.o netlink.o
93 changes: 91 additions & 2 deletions net/nfc/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -233,12 +233,60 @@ struct sk_buff *nfc_alloc_skb(unsigned int size, gfp_t gfp)
}
EXPORT_SYMBOL(nfc_alloc_skb);

/**
* nfc_targets_found - inform that targets were found
*
* @dev: The nfc device that found the targets
* @targets: array of nfc targets found
* @ntargets: targets array size
*
* The device driver must call this function when one or many nfc targets
* are found. After calling this function, the device driver must stop
* polling for targets.
*/
int nfc_targets_found(struct nfc_dev *dev, struct nfc_target *targets,
int n_targets)
{
int i;

nfc_dbg("dev_name=%s n_targets=%d", dev_name(&dev->dev), n_targets);

dev->polling = false;

for (i = 0; i < n_targets; i++)
targets[i].idx = dev->target_idx++;

spin_lock_bh(&dev->targets_lock);

dev->targets_generation++;

kfree(dev->targets);
dev->targets = kmemdup(targets, n_targets * sizeof(struct nfc_target),
GFP_ATOMIC);

if (!dev->targets) {
dev->n_targets = 0;
spin_unlock_bh(&dev->targets_lock);
return -ENOMEM;
}

dev->n_targets = n_targets;
spin_unlock_bh(&dev->targets_lock);

nfc_genl_targets_found(dev);

return 0;
}
EXPORT_SYMBOL(nfc_targets_found);

static void nfc_release(struct device *d)
{
struct nfc_dev *dev = to_nfc_dev(d);

nfc_dbg("dev_name=%s", dev_name(&dev->dev));

nfc_genl_data_exit(&dev->genl_data);
kfree(dev->targets);
kfree(dev);
}

Expand Down Expand Up @@ -298,6 +346,12 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
dev->ops = ops;
dev->supported_protocols = supported_protocols;

spin_lock_init(&dev->targets_lock);
nfc_genl_data_init(&dev->genl_data);

/* first generation must not be 0 */
dev->targets_generation = 1;

return dev;
}
EXPORT_SYMBOL(nfc_allocate_device);
Expand All @@ -318,7 +372,16 @@ int nfc_register_device(struct nfc_dev *dev)
rc = device_add(&dev->dev);
mutex_unlock(&nfc_devlist_mutex);

return rc;
if (rc < 0)
return rc;

rc = nfc_genl_device_added(dev);
if (rc)
nfc_dbg("The userspace won't be notified that the device %s was"
" added", dev_name(&dev->dev));


return 0;
}
EXPORT_SYMBOL(nfc_register_device);

Expand All @@ -329,6 +392,8 @@ EXPORT_SYMBOL(nfc_register_device);
*/
void nfc_unregister_device(struct nfc_dev *dev)
{
int rc;

nfc_dbg("dev_name=%s", dev_name(&dev->dev));

mutex_lock(&nfc_devlist_mutex);
Expand All @@ -341,18 +406,42 @@ void nfc_unregister_device(struct nfc_dev *dev)
device_unlock(&dev->dev);

mutex_unlock(&nfc_devlist_mutex);

rc = nfc_genl_device_removed(dev);
if (rc)
nfc_dbg("The userspace won't be notified that the device %s"
" was removed", dev_name(&dev->dev));

}
EXPORT_SYMBOL(nfc_unregister_device);

static int __init nfc_init(void)
{
int rc;

nfc_info("NFC Core ver %s", VERSION);

return class_register(&nfc_class);
rc = class_register(&nfc_class);
if (rc)
return rc;

rc = nfc_genl_init();
if (rc)
goto err_genl;

/* the first generation must not be 0 */
nfc_devlist_generation = 1;

return 0;

err_genl:
class_unregister(&nfc_class);
return rc;
}

static void __exit nfc_exit(void)
{
nfc_genl_exit();
class_unregister(&nfc_class);
}

Expand Down
Loading

0 comments on commit 4d12b8b

Please sign in to comment.