Commit 74ea1f45 authored by John W. Linville's avatar John W. Linville

Merge tag 'nfc-next-3.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/nfc-next

Samuel Ortiz <sameo@linux.intel.com> says:

"This is the first NFC pull request for the 3.12 release.

With this one we have:

- A few pn533 improvements and minor fixes. Testing our pn533 driver
  against Google's NCI stack triggered a few issues that we fixed now.
  We also added Tx fragmentation support to this driver.

- More NFC secure element handling. We added a GET_SE netlink command
  for getting all the discovered secure elements, and we defined 2
  additional secure element netlink event (transaction and connectivity).
  We also fixed a couple of typos and copy-paste bugs from the secure
  element handling code.

- Firmware download support for the pn544 driver. This chipset can enter a
  special mode where it's waiting for firmware blobs to replace the
  already flashed one. We now support that mode."
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parents 946951e1 39525ee1
......@@ -5791,7 +5791,7 @@ M: Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
M: Samuel Ortiz <sameo@linux.intel.com>
L: linux-wireless@vger.kernel.org
L: linux-nfc@lists.01.org (moderated for non-subscribers)
S: Maintained
S: Supported
F: net/nfc/
F: include/net/nfc/
F: include/uapi/linux/nfc.h
......
......@@ -60,7 +60,7 @@ struct nfcsim {
static struct nfcsim *dev0;
static struct nfcsim *dev1;
struct workqueue_struct *wq;
static struct workqueue_struct *wq;
static void nfcsim_cleanup_dev(struct nfcsim *dev, u8 shutdown)
{
......@@ -481,7 +481,7 @@ static void nfcsim_free_device(struct nfcsim *dev)
kfree(dev);
}
int __init nfcsim_init(void)
static int __init nfcsim_init(void)
{
int rc;
......@@ -522,7 +522,7 @@ int __init nfcsim_init(void)
return rc;
}
void __exit nfcsim_exit(void)
static void __exit nfcsim_exit(void)
{
nfcsim_cleanup_dev(dev0, 1);
nfcsim_cleanup_dev(dev1, 1);
......
This diff is collapsed.
This diff is collapsed.
......@@ -45,7 +45,7 @@ static int pn544_mei_probe(struct mei_cl_device *device,
r = pn544_hci_probe(phy, &mei_phy_ops, LLC_NOP_NAME,
MEI_NFC_HEADER_SIZE, 0, MEI_NFC_MAX_HCI_PAYLOAD,
&phy->hdev);
NULL, &phy->hdev);
if (r < 0) {
nfc_mei_phy_free(phy);
......
......@@ -31,9 +31,6 @@
/* Timing restrictions (ms) */
#define PN544_HCI_RESETVEN_TIME 30
#define HCI_MODE 0
#define FW_MODE 1
enum pn544_state {
PN544_ST_COLD,
PN544_ST_FW_READY,
......@@ -130,6 +127,8 @@ struct pn544_hci_info {
int async_cb_type;
data_exchange_cb_t async_cb;
void *async_cb_context;
fw_download_t fw_download;
};
static int pn544_hci_open(struct nfc_hci_dev *hdev)
......@@ -782,6 +781,17 @@ static int pn544_hci_event_received(struct nfc_hci_dev *hdev, u8 gate, u8 event,
return r;
}
static int pn544_hci_fw_download(struct nfc_hci_dev *hdev,
const char *firmware_name)
{
struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev);
if (info->fw_download == NULL)
return -ENOTSUPP;
return info->fw_download(info->phy_id, firmware_name);
}
static struct nfc_hci_ops pn544_hci_ops = {
.open = pn544_hci_open,
.close = pn544_hci_close,
......@@ -796,11 +806,12 @@ static struct nfc_hci_ops pn544_hci_ops = {
.tm_send = pn544_hci_tm_send,
.check_presence = pn544_hci_check_presence,
.event_received = pn544_hci_event_received,
.fw_download = pn544_hci_fw_download,
};
int pn544_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name,
int phy_headroom, int phy_tailroom, int phy_payload,
struct nfc_hci_dev **hdev)
fw_download_t fw_download, struct nfc_hci_dev **hdev)
{
struct pn544_hci_info *info;
u32 protocols;
......@@ -816,6 +827,7 @@ int pn544_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name,
info->phy_ops = phy_ops;
info->phy_id = phy_id;
info->fw_download = fw_download;
info->state = PN544_ST_COLD;
mutex_init(&info->info_lock);
......
......@@ -24,9 +24,14 @@
#define DRIVER_DESC "HCI NFC driver for PN544"
#define PN544_HCI_MODE 0
#define PN544_FW_MODE 1
typedef int (*fw_download_t)(void *context, const char *firmware_name);
int pn544_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name,
int phy_headroom, int phy_tailroom, int phy_payload,
struct nfc_hci_dev **hdev);
fw_download_t fw_download, struct nfc_hci_dev **hdev);
void pn544_hci_remove(struct nfc_hci_dev *hdev);
#endif /* __LOCAL_PN544_H_ */
......@@ -224,6 +224,9 @@ int nfc_set_remote_general_bytes(struct nfc_dev *dev,
u8 *gt, u8 gt_len);
u8 *nfc_get_local_general_bytes(struct nfc_dev *dev, size_t *gb_len);
int nfc_fw_download_done(struct nfc_dev *dev, const char *firmware_name,
u32 result);
int nfc_targets_found(struct nfc_dev *dev,
struct nfc_target *targets, int ntargets);
int nfc_target_lost(struct nfc_dev *dev, u32 target_idx);
......
......@@ -71,6 +71,20 @@
* @NFC_CMD_DISABLE_SE: Disable the physical link to a specific secure element.
* @NFC_CMD_FW_DOWNLOAD: Request to Load/flash firmware, or event to inform
* that some firmware was loaded
* @NFC_EVENT_SE_ADDED: Event emitted when a new secure element is discovered.
* This typically will be sent whenever a new NFC controller with either
* an embedded SE or an UICC one connected to it through SWP.
* @NFC_EVENT_SE_REMOVED: Event emitted when a secure element is removed from
* the system, as a consequence of e.g. an NFC controller being unplugged.
* @NFC_EVENT_SE_CONNECTIVITY: This event is emitted whenever a secure element
* is requesting connectivity access. For example a UICC SE may need to
* talk with a sleeping modem and will notify this need by sending this
* event. It is then up to userspace to decide if it will wake the modem
* up or not.
* @NFC_EVENT_SE_TRANSACTION: This event is sent when an application running on
* a specific SE notifies us about the end of a transaction. The parameter
* for this event is the application ID (AID).
* @NFC_CMD_GET_SE: Dump all discovered secure elements from an NFC controller.
*/
enum nfc_commands {
NFC_CMD_UNSPEC,
......@@ -97,6 +111,9 @@ enum nfc_commands {
NFC_CMD_FW_DOWNLOAD,
NFC_EVENT_SE_ADDED,
NFC_EVENT_SE_REMOVED,
NFC_EVENT_SE_CONNECTIVITY,
NFC_EVENT_SE_TRANSACTION,
NFC_CMD_GET_SE,
/* private: internal use only */
__NFC_CMD_AFTER_LAST
};
......@@ -129,6 +146,7 @@ enum nfc_commands {
* @NFC_ATTR_FIRMWARE_NAME: Free format firmware version
* @NFC_ATTR_SE_INDEX: Secure element index
* @NFC_ATTR_SE_TYPE: Secure element type (UICC or EMBEDDED)
* @NFC_ATTR_FIRMWARE_DOWNLOAD_STATUS: Firmware download operation status
*/
enum nfc_attrs {
NFC_ATTR_UNSPEC,
......@@ -154,6 +172,8 @@ enum nfc_attrs {
NFC_ATTR_FIRMWARE_NAME,
NFC_ATTR_SE_INDEX,
NFC_ATTR_SE_TYPE,
NFC_ATTR_SE_AID,
NFC_ATTR_FIRMWARE_DOWNLOAD_STATUS,
/* private: internal use only */
__NFC_ATTR_AFTER_LAST
};
......
......@@ -77,11 +77,19 @@ int nfc_fw_download(struct nfc_dev *dev, const char *firmware_name)
return rc;
}
int nfc_fw_download_done(struct nfc_dev *dev, const char *firmware_name)
/**
* nfc_fw_download_done - inform that a firmware download was completed
*
* @dev: The nfc device to which firmware was downloaded
* @firmware_name: The firmware filename
* @result: The positive value of a standard errno value
*/
int nfc_fw_download_done(struct nfc_dev *dev, const char *firmware_name,
u32 result)
{
dev->fw_download_in_progress = false;
return nfc_genl_fw_download_done(dev, firmware_name);
return nfc_genl_fw_download_done(dev, firmware_name, result);
}
EXPORT_SYMBOL(nfc_fw_download_done);
......@@ -129,7 +137,7 @@ int nfc_dev_up(struct nfc_dev *dev)
/* We have to enable the device before discovering SEs */
if (dev->ops->discover_se) {
rc = dev->ops->discover_se(dev);
if (!rc)
if (rc)
pr_warn("SE discovery failed\n");
}
......@@ -575,12 +583,14 @@ int nfc_enable_se(struct nfc_dev *dev, u32 se_idx)
goto error;
}
if (se->type == NFC_SE_ENABLED) {
if (se->state == NFC_SE_ENABLED) {
rc = -EALREADY;
goto error;
}
rc = dev->ops->enable_se(dev, se_idx);
if (rc >= 0)
se->state = NFC_SE_ENABLED;
error:
device_unlock(&dev->dev);
......@@ -618,12 +628,14 @@ int nfc_disable_se(struct nfc_dev *dev, u32 se_idx)
goto error;
}
if (se->type == NFC_SE_DISABLED) {
if (se->state == NFC_SE_DISABLED) {
rc = -EALREADY;
goto error;
}
rc = dev->ops->disable_se(dev, se_idx);
if (rc >= 0)
se->state = NFC_SE_DISABLED;
error:
device_unlock(&dev->dev);
......
......@@ -717,7 +717,7 @@ static int hci_disable_se(struct nfc_dev *nfc_dev, u32 se_idx)
struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev);
if (hdev->ops->disable_se)
return hdev->ops->enable_se(hdev, se_idx);
return hdev->ops->disable_se(hdev, se_idx);
return 0;
}
......
......@@ -1114,7 +1114,8 @@ static int nfc_genl_fw_download(struct sk_buff *skb, struct genl_info *info)
return rc;
}
int nfc_genl_fw_download_done(struct nfc_dev *dev, const char *firmware_name)
int nfc_genl_fw_download_done(struct nfc_dev *dev, const char *firmware_name,
u32 result)
{
struct sk_buff *msg;
void *hdr;
......@@ -1129,6 +1130,7 @@ int nfc_genl_fw_download_done(struct nfc_dev *dev, const char *firmware_name)
goto free_msg;
if (nla_put_string(msg, NFC_ATTR_FIRMWARE_NAME, firmware_name) ||
nla_put_u32(msg, NFC_ATTR_FIRMWARE_DOWNLOAD_STATUS, result) ||
nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx))
goto nla_put_failure;
......@@ -1191,6 +1193,91 @@ static int nfc_genl_disable_se(struct sk_buff *skb, struct genl_info *info)
return rc;
}
static int nfc_genl_send_se(struct sk_buff *msg, struct nfc_dev *dev,
u32 portid, u32 seq,
struct netlink_callback *cb,
int flags)
{
void *hdr;
struct nfc_se *se, *n;
list_for_each_entry_safe(se, n, &dev->secure_elements, list) {
hdr = genlmsg_put(msg, portid, seq, &nfc_genl_family, flags,
NFC_CMD_GET_SE);
if (!hdr)
goto nla_put_failure;
if (cb)
genl_dump_check_consistent(cb, hdr, &nfc_genl_family);
if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx) ||
nla_put_u32(msg, NFC_ATTR_SE_INDEX, se->idx) ||
nla_put_u8(msg, NFC_ATTR_SE_TYPE, se->type))
goto nla_put_failure;
if (genlmsg_end(msg, hdr) < 0)
goto nla_put_failure;
}
return 0;
nla_put_failure:
genlmsg_cancel(msg, hdr);
return -EMSGSIZE;
}
static int nfc_genl_dump_ses(struct sk_buff *skb,
struct netlink_callback *cb)
{
struct class_dev_iter *iter = (struct class_dev_iter *) cb->args[0];
struct nfc_dev *dev = (struct nfc_dev *) cb->args[1];
bool first_call = false;
if (!iter) {
first_call = true;
iter = kmalloc(sizeof(struct class_dev_iter), GFP_KERNEL);
if (!iter)
return -ENOMEM;
cb->args[0] = (long) iter;
}
mutex_lock(&nfc_devlist_mutex);
cb->seq = nfc_devlist_generation;
if (first_call) {
nfc_device_iter_init(iter);
dev = nfc_device_iter_next(iter);
}
while (dev) {
int rc;
rc = nfc_genl_send_se(skb, dev, NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, cb, NLM_F_MULTI);
if (rc < 0)
break;
dev = nfc_device_iter_next(iter);
}
mutex_unlock(&nfc_devlist_mutex);
cb->args[1] = (long) dev;
return skb->len;
}
static int nfc_genl_dump_ses_done(struct netlink_callback *cb)
{
struct class_dev_iter *iter = (struct class_dev_iter *) cb->args[0];
nfc_device_iter_exit(iter);
kfree(iter);
return 0;
}
static struct genl_ops nfc_genl_ops[] = {
{
.cmd = NFC_CMD_GET_DEVICE,
......@@ -1265,6 +1352,12 @@ static struct genl_ops nfc_genl_ops[] = {
.doit = nfc_genl_disable_se,
.policy = nfc_genl_policy,
},
{
.cmd = NFC_CMD_GET_SE,
.dumpit = nfc_genl_dump_ses,
.done = nfc_genl_dump_ses_done,
.policy = nfc_genl_policy,
},
};
......
......@@ -124,9 +124,8 @@ static inline void nfc_device_iter_exit(struct class_dev_iter *iter)
}
int nfc_fw_download(struct nfc_dev *dev, const char *firmware_name);
int nfc_genl_fw_download_done(struct nfc_dev *dev, const char *firmware_name);
int nfc_fw_download_done(struct nfc_dev *dev, const char *firmware_name);
int nfc_genl_fw_download_done(struct nfc_dev *dev, const char *firmware_name,
u32 result);
int nfc_dev_up(struct nfc_dev *dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment