2012-05-07 10:31:51

by Samuel Ortiz

[permalink] [raw]
Subject: [PATCH 00/20] NFC updates for 3.5

Hi John,

Here comes my 2nd NFC batch for the next 3.5 merge window.

Besides the sparse, warning and LLCP fixes, we have a new pn544 driver based
on the existing NFC HCI APIs. We will be living with 2 pn544 drivers for a
while as I wanted to keep a transition period for whoever is using the
existing driver. I'm planning to remove it for 3.6, but this could be extended
if someone screams about it.

You can also pull those patches from:

git://git.kernel.org/pub/scm/linux/kernel/git/sameo/nfc-3.0.git nfc-next

They should apply cleanly on top of your wireless-next tree.

Dan Carpenter (1):
NFC: Remove unneeded pn533 dev NULL check

Eric Lapuyade (7):
NFC: Cache the core NFC active target pointer instead of its index
NFC: Remove useless HCI private nfc target table
NFC: Specify usage for targets found and target lost events
NFC: Add HCI/SHDLC support to let driver check for tag presence
NFC: Update Documentation/nfc-hci.txt
NFC: HCI based pn544 driver
NFC: HCI drivers don't have to keep track of polling state

H Hartley Sweeten (5):
NFC: Quiet nci/data.c sparse noise about plain integer as NULL
pointer
NFC: Include nci_core.h to nci/lib.c
NFC: Quiet nci/ntf.c sparse noise about plain integer as NULL pointer
NFC: HCI ops should not be exposed globally
NFC: The NFC genl family structure should not be exposed globally

Samuel Ortiz (5):
NFC: LLCP connect must wait for a CC frame
NFC: Update the LLCP poll mask
NFC: Return the amount of LLCP bytes queued to sock_sendmsg
NFC: Send device index instead of its name when target is lost
feature-removal: Remove pn544 raw driver

Stephen Rothwell (1):
NFC: Fix up for NLA_PUT_ api changes

joseph daniel (1):
NFC: Fix LLCP compilation warning

Documentation/feature-removal-schedule.txt | 12 +
Documentation/nfc/nfc-hci.txt | 45 +-
drivers/nfc/Kconfig | 13 +
drivers/nfc/Makefile | 1 +
drivers/nfc/pn533.c | 19 +-
drivers/nfc/pn544_hci.c | 947 ++++++++++++++++++++++++++++
include/linux/nfc/pn544.h | 7 +
include/net/nfc/hci.h | 6 +-
include/net/nfc/nfc.h | 19 +-
include/net/nfc/shdlc.h | 2 +
net/nfc/core.c | 112 +++-
net/nfc/hci/core.c | 78 +--
net/nfc/hci/shdlc.c | 12 +
net/nfc/llcp/commands.c | 2 +-
net/nfc/llcp/llcp.c | 7 +
net/nfc/llcp/sock.c | 57 ++-
net/nfc/nci/core.c | 27 +-
net/nfc/nci/data.c | 8 +-
net/nfc/nci/lib.c | 1 +
net/nfc/nci/ntf.c | 2 +-
net/nfc/netlink.c | 12 +-
net/nfc/nfc.h | 2 +-
22 files changed, 1248 insertions(+), 143 deletions(-)
create mode 100644 drivers/nfc/pn544_hci.c

--
1.7.9.1



2012-05-07 10:32:21

by Samuel Ortiz

[permalink] [raw]
Subject: [PATCH 07/20] NFC: Remove unneeded pn533 dev NULL check

From: Dan Carpenter <[email protected]>

container_of() works by subtracting the offset of the member. The math
can't really return a zero here. Sometimes people check it when they
actually meant to check something else but in this case we can just
remove the check.

Signed-off-by: Dan Carpenter <[email protected]>
Signed-off-by: Samuel Ortiz <[email protected]>
---
drivers/nfc/pn533.c | 3 ---
1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index 766e0bb..19110f0 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -394,9 +394,6 @@ static void pn533_wq_cmd_complete(struct work_struct *work)
struct pn533_frame *in_frame;
int rc;

- if (dev == NULL)
- return;
-
in_frame = dev->wq_in_frame;

if (dev->wq_in_error)
--
1.7.9.1


2012-05-07 10:32:34

by Samuel Ortiz

[permalink] [raw]
Subject: [PATCH 12/20] NFC: Fix LLCP compilation warning

From: joseph daniel <[email protected]>

nfc_llcp_general_bytes is defined in nfc/core.c as:
nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *gb_len).

as in nfc/nfc.h:
nfc_llcp_general_bytes(struct nfc_dev *dev, u8 *gb_len), if CONFIG_NFC_LLCP
is not defined.

so we got some warnings,
net/nfc/core.c:207:2: warning: passing argument 2 of ‘nfc_llcp_general_bytes’ from incompatible pointer type [enabled by default]
net/nfc/nfc.h:87:19: note: expected ‘u8 *’ but argument is of type ‘size_t *’

Signed-off-by: joseph daniel <[email protected]>
Signed-off-by: Samuel Ortiz <[email protected]>
---
net/nfc/nfc.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h
index 2c868d2..4dd8fab 100644
--- a/net/nfc/nfc.h
+++ b/net/nfc/nfc.h
@@ -84,7 +84,7 @@ static inline int nfc_llcp_set_remote_gb(struct nfc_dev *dev,
return 0;
}

-static inline u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, u8 *gb_len)
+static inline u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *gb_len)
{
*gb_len = 0;
return NULL;
--
1.7.9.1


2012-05-07 10:32:21

by Samuel Ortiz

[permalink] [raw]
Subject: [PATCH 08/20] NFC: LLCP connect must wait for a CC frame

Blocking sockets should sleep on a CC (Connection Complete) reception
from the connect() call.

Signed-off-by: Samuel Ortiz <[email protected]>
---
net/nfc/llcp/llcp.c | 7 +++++++
net/nfc/llcp/sock.c | 42 +++++++++++++++++++++++++++++++++++++++++-
2 files changed, 48 insertions(+), 1 deletions(-)

diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c
index 92988aa..42994fa 100644
--- a/net/nfc/llcp/llcp.c
+++ b/net/nfc/llcp/llcp.c
@@ -448,6 +448,8 @@ static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local,
{
struct nfc_llcp_sock *sock, *llcp_sock, *n;

+ pr_debug("ssap dsap %d %d\n", ssap, dsap);
+
if (ssap == 0 && dsap == 0)
return NULL;

@@ -783,6 +785,7 @@ static void nfc_llcp_recv_disc(struct nfc_llcp_local *local,
static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb)
{
struct nfc_llcp_sock *llcp_sock;
+ struct sock *sk;
u8 dsap, ssap;

dsap = nfc_llcp_dsap(skb);
@@ -801,10 +804,14 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb)
}

llcp_sock->dsap = ssap;
+ sk = &llcp_sock->sk;

nfc_llcp_parse_tlv(local, &skb->data[LLCP_HEADER_SIZE],
skb->len - LLCP_HEADER_SIZE);

+ sk->sk_state = LLCP_CONNECTED;
+ sk->sk_state_change(sk);
+
nfc_llcp_sock_put(llcp_sock);
}

diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c
index c13e02e..99196d3 100644
--- a/net/nfc/llcp/sock.c
+++ b/net/nfc/llcp/sock.c
@@ -27,6 +27,42 @@
#include "../nfc.h"
#include "llcp.h"

+static int sock_wait_state(struct sock *sk, int state, unsigned long timeo)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ int err = 0;
+
+ pr_debug("sk %p", sk);
+
+ add_wait_queue(sk_sleep(sk), &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ while (sk->sk_state != state) {
+ if (!timeo) {
+ err = -EINPROGRESS;
+ break;
+ }
+
+ if (signal_pending(current)) {
+ err = sock_intr_errno(timeo);
+ break;
+ }
+
+ release_sock(sk);
+ timeo = schedule_timeout(timeo);
+ lock_sock(sk);
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ err = sock_error(sk);
+ if (err)
+ break;
+ }
+
+ __set_current_state(TASK_RUNNING);
+ remove_wait_queue(sk_sleep(sk), &wait);
+ return err;
+}
+
static struct proto llcp_sock_proto = {
.name = "NFC_LLCP",
.owner = THIS_MODULE,
@@ -462,9 +498,13 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
if (ret)
goto put_dev;

- sk->sk_state = LLCP_CONNECTED;
+ ret = sock_wait_state(sk, LLCP_CONNECTED,
+ sock_sndtimeo(sk, flags & O_NONBLOCK));
+ if (ret)
+ goto put_dev;

release_sock(sk);
+
return 0;

put_dev:
--
1.7.9.1


2012-05-07 10:33:12

by Samuel Ortiz

[permalink] [raw]
Subject: [PATCH 20/20] NFC: HCI drivers don't have to keep track of polling state

From: Eric Lapuyade <[email protected]>

The NFC core code already does that for them.

Signed-off-by: Eric Lapuyade <[email protected]>
Signed-off-by: Samuel Ortiz <[email protected]>
---
include/net/nfc/hci.h | 2 --
net/nfc/hci/core.c | 21 ++++-----------------
2 files changed, 4 insertions(+), 19 deletions(-)

diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h
index ae04200..4467c94 100644
--- a/include/net/nfc/hci.h
+++ b/include/net/nfc/hci.h
@@ -84,8 +84,6 @@ struct nfc_hci_dev {

u8 gate2pipe[NFC_HCI_MAX_GATES];

- bool poll_started;
-
u8 sw_romlib;
u8 sw_patch;
u8 sw_flashlib_major;
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c
index 0fdb96f..e1a640d 100644
--- a/net/nfc/hci/core.c
+++ b/net/nfc/hci/core.c
@@ -251,11 +251,6 @@ void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event,

switch (event) {
case NFC_HCI_EVT_TARGET_DISCOVERED:
- if (hdev->poll_started == false) {
- r = -EPROTO;
- goto exit;
- }
-
if (skb->len < 1) { /* no status data? */
r = -EPROTO;
goto exit;
@@ -489,28 +484,20 @@ static int hci_dev_down(struct nfc_dev *nfc_dev)
static int hci_start_poll(struct nfc_dev *nfc_dev, u32 protocols)
{
struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev);
- int r;

if (hdev->ops->start_poll)
- r = hdev->ops->start_poll(hdev, protocols);
+ return hdev->ops->start_poll(hdev, protocols);
else
- r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,
+ return nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,
NFC_HCI_EVT_READER_REQUESTED, NULL, 0);
- if (r == 0)
- hdev->poll_started = true;
-
- return r;
}

static void hci_stop_poll(struct nfc_dev *nfc_dev)
{
struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev);

- if (hdev->poll_started) {
- nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,
- NFC_HCI_EVT_END_OPERATION, NULL, 0);
- hdev->poll_started = false;
- }
+ nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,
+ NFC_HCI_EVT_END_OPERATION, NULL, 0);
}

static int hci_activate_target(struct nfc_dev *nfc_dev,
--
1.7.9.1


2012-05-07 10:32:20

by Samuel Ortiz

[permalink] [raw]
Subject: [PATCH 04/20] NFC: Specify usage for targets found and target lost events

From: Eric Lapuyade <[email protected]>

It is now specified that nfc_target_found() and nfc_target_lost() core
functions must not be called from an atomic context. This allow us to
serialize calls and protect the targets table using the nfc device lock
instead of a spinlock.

Signed-off-by: Eric Lapuyade <[email protected]>
Signed-off-by: Samuel Ortiz <[email protected]>
---
include/net/nfc/nfc.h | 1 -
net/nfc/core.c | 35 ++++++++++++++++++++++++++---------
net/nfc/netlink.c | 4 ++--
3 files changed, 28 insertions(+), 12 deletions(-)

diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h
index 8ba1747..cee20aa 100644
--- a/include/net/nfc/nfc.h
+++ b/include/net/nfc/nfc.h
@@ -97,7 +97,6 @@ struct nfc_dev {
struct nfc_target *targets;
int n_targets;
int targets_generation;
- spinlock_t targets_lock;
struct device dev;
bool dev_up;
bool polling;
diff --git a/net/nfc/core.c b/net/nfc/core.c
index 5d86f6c..02e1fda 100644
--- a/net/nfc/core.c
+++ b/net/nfc/core.c
@@ -501,6 +501,9 @@ EXPORT_SYMBOL(nfc_alloc_recv_skb);
* 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.
+ * IMPORTANT: this function must not be called from an atomic context.
+ * In addition, it must also not be called from a context that would prevent
+ * the NFC Core to call other nfc ops entry point concurrently.
*/
int nfc_targets_found(struct nfc_dev *dev,
struct nfc_target *targets, int n_targets)
@@ -514,7 +517,7 @@ int nfc_targets_found(struct nfc_dev *dev,
for (i = 0; i < n_targets; i++)
targets[i].idx = dev->target_next_idx++;

- spin_lock_bh(&dev->targets_lock);
+ device_lock(&dev->dev);

dev->targets_generation++;

@@ -524,12 +527,12 @@ int nfc_targets_found(struct nfc_dev *dev,

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

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

nfc_genl_targets_found(dev);

@@ -537,6 +540,18 @@ int nfc_targets_found(struct nfc_dev *dev,
}
EXPORT_SYMBOL(nfc_targets_found);

+/**
+ * nfc_target_lost - inform that an activated target went out of field
+ *
+ * @dev: The nfc device that had the activated target in field
+ * @target_idx: the nfc index of the target
+ *
+ * The device driver must call this function when the activated target
+ * goes out of the field.
+ * IMPORTANT: this function must not be called from an atomic context.
+ * In addition, it must also not be called from a context that would prevent
+ * the NFC Core to call other nfc ops entry point concurrently.
+ */
int nfc_target_lost(struct nfc_dev *dev, u32 target_idx)
{
struct nfc_target *tg;
@@ -544,7 +559,7 @@ int nfc_target_lost(struct nfc_dev *dev, u32 target_idx)

pr_debug("dev_name %s n_target %d\n", dev_name(&dev->dev), target_idx);

- spin_lock_bh(&dev->targets_lock);
+ device_lock(&dev->dev);

for (i = 0; i < dev->n_targets; i++) {
tg = &dev->targets[i];
@@ -553,7 +568,7 @@ int nfc_target_lost(struct nfc_dev *dev, u32 target_idx)
}

if (i == dev->n_targets) {
- spin_unlock_bh(&dev->targets_lock);
+ device_unlock(&dev->dev);
return -EINVAL;
}

@@ -569,7 +584,7 @@ int nfc_target_lost(struct nfc_dev *dev, u32 target_idx)
dev->targets = NULL;
}

- spin_unlock_bh(&dev->targets_lock);
+ device_unlock(&dev->dev);

nfc_genl_target_lost(dev, target_idx);

@@ -607,8 +622,10 @@ static void nfc_check_pres_work(struct work_struct *work)
mod_timer(&dev->check_pres_timer, jiffies +
msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS));
} else {
- nfc_target_lost(dev, dev->active_target->idx);
- dev->active_target = NULL;
+ u32 active_target_idx = dev->active_target->idx;
+ device_unlock(&dev->dev);
+ nfc_target_lost(dev, active_target_idx);
+ return;
}
}

@@ -681,9 +698,9 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
dev->tx_headroom = tx_headroom;
dev->tx_tailroom = tx_tailroom;

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

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

diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
index 6c558bc..cc89e4f 100644
--- a/net/nfc/netlink.c
+++ b/net/nfc/netlink.c
@@ -124,7 +124,7 @@ static int nfc_genl_dump_targets(struct sk_buff *skb,
cb->args[1] = (long) dev;
}

- spin_lock_bh(&dev->targets_lock);
+ device_lock(&dev->dev);

cb->seq = dev->targets_generation;

@@ -137,7 +137,7 @@ static int nfc_genl_dump_targets(struct sk_buff *skb,
i++;
}

- spin_unlock_bh(&dev->targets_lock);
+ device_unlock(&dev->dev);

cb->args[0] = i;

--
1.7.9.1


2012-05-07 10:32:47

by Samuel Ortiz

[permalink] [raw]
Subject: [PATCH 15/20] NFC: Quiet nci/ntf.c sparse noise about plain integer as NULL pointer

From: H Hartley Sweeten <[email protected]>

Pointers should be cleared with NULL, not 0.

Quiets a couple sparse warnings of the type:

warning: Using plain integer as NULL pointer

Signed-off-by: H Hartley Sweeten <[email protected]>
Cc: Lauro Ramos Venancio <[email protected]>
Cc: Aloisio Almeida Jr <[email protected]>
Cc: Samuel Ortiz <[email protected]>
Cc: "David S. Miller" <[email protected]>
Signed-off-by: Samuel Ortiz <[email protected]>
---
net/nfc/nci/ntf.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c
index 99e1632..cb26461 100644
--- a/net/nfc/nci/ntf.c
+++ b/net/nfc/nci/ntf.c
@@ -497,7 +497,7 @@ static void nci_rf_deactivate_ntf_packet(struct nci_dev *ndev,
/* drop partial rx data packet */
if (ndev->rx_data_reassembly) {
kfree_skb(ndev->rx_data_reassembly);
- ndev->rx_data_reassembly = 0;
+ ndev->rx_data_reassembly = NULL;
}

/* complete the data exchange transaction, if exists */
--
1.7.9.1


2012-05-07 10:32:43

by Samuel Ortiz

[permalink] [raw]
Subject: [PATCH 14/20] NFC: Include nci_core.h to nci/lib.c

From: H Hartley Sweeten <[email protected]>

Include the header to pickup the exported symbol prototype.

Quites the sparse warning:

warning: symbol 'nci_to_errno' was not declared. Should it be static?

Signed-off-by: H Hartley Sweeten <[email protected]>
Cc: Lauro Ramos Venancio <[email protected]>
Cc: Aloisio Almeida Jr <[email protected]>
CC: Samuel Ortiz <[email protected]>
CC: "David S. Miller" <[email protected]>
Signed-off-by: Samuel Ortiz <[email protected]>
---
net/nfc/nci/lib.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/net/nfc/nci/lib.c b/net/nfc/nci/lib.c
index 6a63e5e..6b7fd26 100644
--- a/net/nfc/nci/lib.c
+++ b/net/nfc/nci/lib.c
@@ -31,6 +31,7 @@
#include <linux/errno.h>

#include <net/nfc/nci.h>
+#include <net/nfc/nci_core.h>

/* NCI status codes to Unix errno mapping */
int nci_to_errno(__u8 code)
--
1.7.9.1


2012-05-07 10:31:58

by Samuel Ortiz

[permalink] [raw]
Subject: [PATCH 02/20] NFC: Cache the core NFC active target pointer instead of its index

From: Eric Lapuyade <[email protected]>

The NFC Core now caches the active nfc target pointer, thereby avoiding
the need to lookup the target table for each invocation of a driver ops.
Consequently, pn533, HCI and NCI now directly receive an nfc_target
pointer instead of a target index.

Cc: Ilan Elias <[email protected]>
Signed-off-by: Eric Lapuyade <[email protected]>
Signed-off-by: Samuel Ortiz <[email protected]>
---
drivers/nfc/pn533.c | 16 +++++-----
include/net/nfc/nfc.h | 18 ++++++-----
net/nfc/core.c | 81 +++++++++++++++++++++++++++++++++++++------------
net/nfc/hci/core.c | 36 ++++------------------
net/nfc/nci/core.c | 27 ++++++++--------
5 files changed, 99 insertions(+), 79 deletions(-)

diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index e6ec16d..766e0bb 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -1194,8 +1194,8 @@ static int pn533_activate_target_nfcdep(struct pn533 *dev)
return rc;
}

-static int pn533_activate_target(struct nfc_dev *nfc_dev, u32 target_idx,
- u32 protocol)
+static int pn533_activate_target(struct nfc_dev *nfc_dev,
+ struct nfc_target *target, u32 protocol)
{
struct pn533 *dev = nfc_get_drvdata(nfc_dev);
int rc;
@@ -1243,7 +1243,8 @@ static int pn533_activate_target(struct nfc_dev *nfc_dev, u32 target_idx,
return 0;
}

-static void pn533_deactivate_target(struct nfc_dev *nfc_dev, u32 target_idx)
+static void pn533_deactivate_target(struct nfc_dev *nfc_dev,
+ struct nfc_target *target)
{
struct pn533 *dev = nfc_get_drvdata(nfc_dev);
u8 tg;
@@ -1351,7 +1352,7 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg,
return 0;
}

-static int pn533_dep_link_up(struct nfc_dev *nfc_dev, int target_idx,
+static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target,
u8 comm_mode, u8* gb, size_t gb_len)
{
struct pn533 *dev = nfc_get_drvdata(nfc_dev);
@@ -1552,10 +1553,9 @@ error:
return 0;
}

-static int pn533_data_exchange(struct nfc_dev *nfc_dev, u32 target_idx,
- struct sk_buff *skb,
- data_exchange_cb_t cb,
- void *cb_context)
+static int pn533_data_exchange(struct nfc_dev *nfc_dev,
+ struct nfc_target *target, struct sk_buff *skb,
+ data_exchange_cb_t cb, void *cb_context)
{
struct pn533 *dev = nfc_get_drvdata(nfc_dev);
struct pn533_frame *out_frame, *in_frame;
diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h
index 313d00f..8ba1747 100644
--- a/include/net/nfc/nfc.h
+++ b/include/net/nfc/nfc.h
@@ -48,26 +48,28 @@ struct nfc_dev;
typedef void (*data_exchange_cb_t)(void *context, struct sk_buff *skb,
int err);

+struct nfc_target;
+
struct nfc_ops {
int (*dev_up)(struct nfc_dev *dev);
int (*dev_down)(struct nfc_dev *dev);
int (*start_poll)(struct nfc_dev *dev, u32 protocols);
void (*stop_poll)(struct nfc_dev *dev);
- int (*dep_link_up)(struct nfc_dev *dev, int target_idx, u8 comm_mode,
- u8 *gb, size_t gb_len);
+ int (*dep_link_up)(struct nfc_dev *dev, struct nfc_target *target,
+ u8 comm_mode, u8 *gb, size_t gb_len);
int (*dep_link_down)(struct nfc_dev *dev);
- int (*activate_target)(struct nfc_dev *dev, u32 target_idx,
+ int (*activate_target)(struct nfc_dev *dev, struct nfc_target *target,
u32 protocol);
- void (*deactivate_target)(struct nfc_dev *dev, u32 target_idx);
- int (*data_exchange)(struct nfc_dev *dev, u32 target_idx,
+ void (*deactivate_target)(struct nfc_dev *dev,
+ struct nfc_target *target);
+ int (*data_exchange)(struct nfc_dev *dev, struct nfc_target *target,
struct sk_buff *skb, data_exchange_cb_t cb,
void *cb_context);
- int (*check_presence)(struct nfc_dev *dev, u32 target_idx);
+ int (*check_presence)(struct nfc_dev *dev, struct nfc_target *target);
};

#define NFC_TARGET_IDX_ANY -1
#define NFC_MAX_GT_LEN 48
-#define NFC_TARGET_IDX_NONE 0xffffffff

struct nfc_target {
u32 idx;
@@ -99,7 +101,7 @@ struct nfc_dev {
struct device dev;
bool dev_up;
bool polling;
- u32 activated_target_idx;
+ struct nfc_target *active_target;
bool dep_link_up;
u32 dep_rf_mode;
struct nfc_genl_data genl_data;
diff --git a/net/nfc/core.c b/net/nfc/core.c
index da35327..5d86f6c 100644
--- a/net/nfc/core.c
+++ b/net/nfc/core.c
@@ -97,7 +97,7 @@ int nfc_dev_down(struct nfc_dev *dev)
goto error;
}

- if (dev->polling || dev->activated_target_idx != NFC_TARGET_IDX_NONE) {
+ if (dev->polling || dev->active_target) {
rc = -EBUSY;
goto error;
}
@@ -183,11 +183,27 @@ error:
return rc;
}

+static struct nfc_target *nfc_find_target(struct nfc_dev *dev, u32 target_idx)
+{
+ int i;
+
+ if (dev->n_targets == 0)
+ return NULL;
+
+ for (i = 0; i < dev->n_targets ; i++) {
+ if (dev->targets[i].idx == target_idx)
+ return &dev->targets[i];
+ }
+
+ return NULL;
+}
+
int nfc_dep_link_up(struct nfc_dev *dev, int target_index, u8 comm_mode)
{
int rc = 0;
u8 *gb;
size_t gb_len;
+ struct nfc_target *target;

pr_debug("dev_name=%s comm %d\n", dev_name(&dev->dev), comm_mode);

@@ -212,9 +228,15 @@ int nfc_dep_link_up(struct nfc_dev *dev, int target_index, u8 comm_mode)
goto error;
}

- rc = dev->ops->dep_link_up(dev, target_index, comm_mode, gb, gb_len);
+ target = nfc_find_target(dev, target_index);
+ if (target == NULL) {
+ rc = -ENOTCONN;
+ goto error;
+ }
+
+ rc = dev->ops->dep_link_up(dev, target, comm_mode, gb, gb_len);
if (!rc)
- dev->activated_target_idx = target_index;
+ dev->active_target = target;

error:
device_unlock(&dev->dev);
@@ -250,7 +272,7 @@ int nfc_dep_link_down(struct nfc_dev *dev)
rc = dev->ops->dep_link_down(dev);
if (!rc) {
dev->dep_link_up = false;
- dev->activated_target_idx = NFC_TARGET_IDX_NONE;
+ dev->active_target = NULL;
nfc_llcp_mac_is_down(dev);
nfc_genl_dep_link_down_event(dev);
}
@@ -282,6 +304,7 @@ EXPORT_SYMBOL(nfc_dep_link_is_up);
int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol)
{
int rc;
+ struct nfc_target *target;

pr_debug("dev_name=%s target_idx=%u protocol=%u\n",
dev_name(&dev->dev), target_idx, protocol);
@@ -293,9 +316,20 @@ int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol)
goto error;
}

- rc = dev->ops->activate_target(dev, target_idx, protocol);
+ if (dev->active_target) {
+ rc = -EBUSY;
+ goto error;
+ }
+
+ target = nfc_find_target(dev, target_idx);
+ if (target == NULL) {
+ rc = -ENOTCONN;
+ goto error;
+ }
+
+ rc = dev->ops->activate_target(dev, target, protocol);
if (!rc) {
- dev->activated_target_idx = target_idx;
+ dev->active_target = target;

if (dev->ops->check_presence)
mod_timer(&dev->check_pres_timer, jiffies +
@@ -327,11 +361,21 @@ int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx)
goto error;
}

+ if (dev->active_target == NULL) {
+ rc = -ENOTCONN;
+ goto error;
+ }
+
+ if (dev->active_target->idx != target_idx) {
+ rc = -ENOTCONN;
+ goto error;
+ }
+
if (dev->ops->check_presence)
del_timer_sync(&dev->check_pres_timer);

- dev->ops->deactivate_target(dev, target_idx);
- dev->activated_target_idx = NFC_TARGET_IDX_NONE;
+ dev->ops->deactivate_target(dev, dev->active_target);
+ dev->active_target = NULL;

error:
device_unlock(&dev->dev);
@@ -365,13 +409,13 @@ int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, struct sk_buff *skb,
goto error;
}

- if (dev->activated_target_idx == NFC_TARGET_IDX_NONE) {
+ if (dev->active_target == NULL) {
rc = -ENOTCONN;
kfree_skb(skb);
goto error;
}

- if (target_idx != dev->activated_target_idx) {
+ if (dev->active_target->idx != target_idx) {
rc = -EADDRNOTAVAIL;
kfree_skb(skb);
goto error;
@@ -380,7 +424,8 @@ int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, struct sk_buff *skb,
if (dev->ops->check_presence)
del_timer_sync(&dev->check_pres_timer);

- rc = dev->ops->data_exchange(dev, target_idx, skb, cb, cb_context);
+ rc = dev->ops->data_exchange(dev, dev->active_target, skb, cb,
+ cb_context);

if (!rc && dev->ops->check_presence)
mod_timer(&dev->check_pres_timer, jiffies +
@@ -514,7 +559,7 @@ int nfc_target_lost(struct nfc_dev *dev, u32 target_idx)

dev->targets_generation++;
dev->n_targets--;
- dev->activated_target_idx = NFC_TARGET_IDX_NONE;
+ dev->active_target = NULL;

if (dev->n_targets) {
memcpy(&dev->targets[i], &dev->targets[i + 1],
@@ -556,15 +601,14 @@ static void nfc_check_pres_work(struct work_struct *work)

device_lock(&dev->dev);

- if (dev->activated_target_idx != NFC_TARGET_IDX_NONE &&
- timer_pending(&dev->check_pres_timer) == 0) {
- rc = dev->ops->check_presence(dev, dev->activated_target_idx);
+ if (dev->active_target && timer_pending(&dev->check_pres_timer) == 0) {
+ rc = dev->ops->check_presence(dev, dev->active_target);
if (!rc) {
mod_timer(&dev->check_pres_timer, jiffies +
msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS));
} else {
- nfc_target_lost(dev, dev->activated_target_idx);
- dev->activated_target_idx = NFC_TARGET_IDX_NONE;
+ nfc_target_lost(dev, dev->active_target->idx);
+ dev->active_target = NULL;
}
}

@@ -643,8 +687,6 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
/* first generation must not be 0 */
dev->targets_generation = 1;

- dev->activated_target_idx = NFC_TARGET_IDX_NONE;
-
if (ops->check_presence) {
char name[32];
init_timer(&dev->check_pres_timer);
@@ -662,7 +704,6 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
}
}

-
return dev;
}
EXPORT_SYMBOL(nfc_allocate_device);
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c
index 86fd00d..545c19f 100644
--- a/net/nfc/hci/core.c
+++ b/net/nfc/hci/core.c
@@ -520,50 +520,26 @@ static void hci_stop_poll(struct nfc_dev *nfc_dev)
}
}

-static struct nfc_target *hci_find_target(struct nfc_hci_dev *hdev,
- u32 target_idx)
+static int hci_activate_target(struct nfc_dev *nfc_dev,
+ struct nfc_target *target, u32 protocol)
{
- int i;
- if (hdev->poll_started == false || hdev->targets == NULL)
- return NULL;
-
- for (i = 0; i < hdev->target_count; i++) {
- if (hdev->targets[i].idx == target_idx)
- return &hdev->targets[i];
- }
-
- return NULL;
-}
-
-static int hci_activate_target(struct nfc_dev *nfc_dev, u32 target_idx,
- u32 protocol)
-{
- struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev);
-
- if (hci_find_target(hdev, target_idx) == NULL)
- return -ENOMEDIUM;
-
return 0;
}

-static void hci_deactivate_target(struct nfc_dev *nfc_dev, u32 target_idx)
+static void hci_deactivate_target(struct nfc_dev *nfc_dev,
+ struct nfc_target *target)
{
}

-static int hci_data_exchange(struct nfc_dev *nfc_dev, u32 target_idx,
+static int hci_data_exchange(struct nfc_dev *nfc_dev, struct nfc_target *target,
struct sk_buff *skb, data_exchange_cb_t cb,
void *cb_context)
{
struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev);
int r;
- struct nfc_target *target;
struct sk_buff *res_skb = NULL;

- pr_debug("target_idx=%d\n", target_idx);
-
- target = hci_find_target(hdev, target_idx);
- if (target == NULL)
- return -ENOMEDIUM;
+ pr_debug("target_idx=%d\n", target->idx);

switch (target->hci_reader_gate) {
case NFC_HCI_RF_READER_A_GATE:
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
index 8737c20..d560e6f 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -436,16 +436,16 @@ static void nci_stop_poll(struct nfc_dev *nfc_dev)
msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT));
}

-static int nci_activate_target(struct nfc_dev *nfc_dev, __u32 target_idx,
- __u32 protocol)
+static int nci_activate_target(struct nfc_dev *nfc_dev,
+ struct nfc_target *target, __u32 protocol)
{
struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
struct nci_rf_discover_select_param param;
- struct nfc_target *target = NULL;
+ struct nfc_target *nci_target = NULL;
int i;
int rc = 0;

- pr_debug("target_idx %d, protocol 0x%x\n", target_idx, protocol);
+ pr_debug("target_idx %d, protocol 0x%x\n", target->idx, protocol);

if ((atomic_read(&ndev->state) != NCI_W4_HOST_SELECT) &&
(atomic_read(&ndev->state) != NCI_POLL_ACTIVE)) {
@@ -459,25 +459,25 @@ static int nci_activate_target(struct nfc_dev *nfc_dev, __u32 target_idx,
}

for (i = 0; i < ndev->n_targets; i++) {
- if (ndev->targets[i].idx == target_idx) {
- target = &ndev->targets[i];
+ if (ndev->targets[i].idx == target->idx) {
+ nci_target = &ndev->targets[i];
break;
}
}

- if (!target) {
+ if (!nci_target) {
pr_err("unable to find the selected target\n");
return -EINVAL;
}

- if (!(target->supported_protocols & (1 << protocol))) {
+ if (!(nci_target->supported_protocols & (1 << protocol))) {
pr_err("target does not support the requested protocol 0x%x\n",
protocol);
return -EINVAL;
}

if (atomic_read(&ndev->state) == NCI_W4_HOST_SELECT) {
- param.rf_discovery_id = target->logical_idx;
+ param.rf_discovery_id = nci_target->logical_idx;

if (protocol == NFC_PROTO_JEWEL)
param.rf_protocol = NCI_RF_PROTOCOL_T1T;
@@ -501,11 +501,12 @@ static int nci_activate_target(struct nfc_dev *nfc_dev, __u32 target_idx,
return rc;
}

-static void nci_deactivate_target(struct nfc_dev *nfc_dev, __u32 target_idx)
+static void nci_deactivate_target(struct nfc_dev *nfc_dev,
+ struct nfc_target *target)
{
struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);

- pr_debug("target_idx %d\n", target_idx);
+ pr_debug("target_idx %d\n", target->idx);

if (!ndev->target_active_prot) {
pr_err("unable to deactivate target, no active target\n");
@@ -520,14 +521,14 @@ static void nci_deactivate_target(struct nfc_dev *nfc_dev, __u32 target_idx)
}
}

-static int nci_data_exchange(struct nfc_dev *nfc_dev, __u32 target_idx,
+static int nci_data_exchange(struct nfc_dev *nfc_dev, struct nfc_target *target,
struct sk_buff *skb,
data_exchange_cb_t cb, void *cb_context)
{
struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
int rc;

- pr_debug("target_idx %d, len %d\n", target_idx, skb->len);
+ pr_debug("target_idx %d, len %d\n", target->idx, skb->len);

if (!ndev->target_active_prot) {
pr_err("unable to exchange data, no active target\n");
--
1.7.9.1


2012-05-07 10:33:24

by Samuel Ortiz

[permalink] [raw]
Subject: [PATCH 18/20] NFC: HCI based pn544 driver

From: Eric Lapuyade <[email protected]>

This is an NFC driver for NXP pn544.
Unlike pn544.c, this one is based on the NFC HCI and SHDLC kernel layers.

Signed-off-by: Eric Lapuyade <[email protected]>
Signed-off-by: Samuel Ortiz <[email protected]>
---
drivers/nfc/Kconfig | 13 +
drivers/nfc/Makefile | 1 +
drivers/nfc/pn544_hci.c | 947 +++++++++++++++++++++++++++++++++++++++++++++
include/linux/nfc/pn544.h | 7 +
4 files changed, 968 insertions(+), 0 deletions(-)
create mode 100644 drivers/nfc/pn544_hci.c

diff --git a/drivers/nfc/Kconfig b/drivers/nfc/Kconfig
index 5af95927..3b20b73 100644
--- a/drivers/nfc/Kconfig
+++ b/drivers/nfc/Kconfig
@@ -17,6 +17,19 @@ config PN544_NFC
To compile this driver as a module, choose m here. The module will
be called pn544.

+config PN544_HCI_NFC
+ tristate "HCI PN544 NFC driver"
+ depends on I2C && NFC_SHDLC
+ select CRC_CCITT
+ default n
+ ---help---
+ NXP PN544 i2c driver.
+ This is a driver based on the SHDLC and HCI NFC kernel layers and
+ will thus not work with NXP libnfc library.
+
+ To compile this driver as a module, choose m here. The module will
+ be called pn544_hci.
+
config NFC_PN533
tristate "NXP PN533 USB driver"
depends on USB
diff --git a/drivers/nfc/Makefile b/drivers/nfc/Makefile
index ab99e85..473e44c 100644
--- a/drivers/nfc/Makefile
+++ b/drivers/nfc/Makefile
@@ -3,6 +3,7 @@
#

obj-$(CONFIG_PN544_NFC) += pn544.o
+obj-$(CONFIG_PN544_HCI_NFC) += pn544_hci.o
obj-$(CONFIG_NFC_PN533) += pn533.o
obj-$(CONFIG_NFC_WILINK) += nfcwilink.o

diff --git a/drivers/nfc/pn544_hci.c b/drivers/nfc/pn544_hci.c
new file mode 100644
index 0000000..46f4a9f
--- /dev/null
+++ b/drivers/nfc/pn544_hci.c
@@ -0,0 +1,947 @@
+/*
+ * HCI based Driver for NXP PN544 NFC Chip
+ *
+ * Copyright (C) 2012 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include <linux/crc-ccitt.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/miscdevice.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+
+#include <linux/nfc.h>
+#include <net/nfc/hci.h>
+#include <net/nfc/shdlc.h>
+
+#include <linux/nfc/pn544.h>
+
+#define DRIVER_DESC "HCI NFC driver for PN544"
+
+#define PN544_HCI_DRIVER_NAME "pn544_hci"
+
+/* Timing restrictions (ms) */
+#define PN544_HCI_RESETVEN_TIME 30
+
+static struct i2c_device_id pn544_hci_id_table[] = {
+ {"pn544", 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, pn544_hci_id_table);
+
+#define HCI_MODE 0
+#define FW_MODE 1
+
+/* framing in HCI mode */
+#define PN544_HCI_LLC_LEN 1
+#define PN544_HCI_LLC_CRC 2
+#define PN544_HCI_LLC_LEN_CRC (PN544_HCI_LLC_LEN + PN544_HCI_LLC_CRC)
+#define PN544_HCI_LLC_MIN_SIZE (1 + PN544_HCI_LLC_LEN_CRC)
+#define PN544_HCI_LLC_MAX_PAYLOAD 29
+#define PN544_HCI_LLC_MAX_SIZE (PN544_HCI_LLC_LEN_CRC + 1 + \
+ PN544_HCI_LLC_MAX_PAYLOAD)
+
+enum pn544_state {
+ PN544_ST_COLD,
+ PN544_ST_FW_READY,
+ PN544_ST_READY,
+};
+
+#define FULL_VERSION_LEN 11
+
+/* Proprietary commands */
+#define PN544_WRITE 0x3f
+
+/* Proprietary gates, events, commands and registers */
+
+/* NFC_HCI_RF_READER_A_GATE additional registers and commands */
+#define PN544_RF_READER_A_AUTO_ACTIVATION 0x10
+#define PN544_RF_READER_A_CMD_CONTINUE_ACTIVATION 0x12
+#define PN544_MIFARE_CMD 0x21
+
+/* Commands that apply to all RF readers */
+#define PN544_RF_READER_CMD_PRESENCE_CHECK 0x30
+#define PN544_RF_READER_CMD_ACTIVATE_NEXT 0x32
+
+/* NFC_HCI_ID_MGMT_GATE additional registers */
+#define PN544_ID_MGMT_FULL_VERSION_SW 0x10
+
+#define PN544_RF_READER_ISO15693_GATE 0x12
+
+#define PN544_RF_READER_F_GATE 0x14
+#define PN544_FELICA_ID 0x04
+#define PN544_FELICA_RAW 0x20
+
+#define PN544_RF_READER_JEWEL_GATE 0x15
+#define PN544_JEWEL_RAW_CMD 0x23
+
+#define PN544_RF_READER_NFCIP1_INITIATOR_GATE 0x30
+#define PN544_RF_READER_NFCIP1_TARGET_GATE 0x31
+
+#define PN544_SYS_MGMT_GATE 0x90
+#define PN544_SYS_MGMT_INFO_NOTIFICATION 0x02
+
+#define PN544_POLLING_LOOP_MGMT_GATE 0x94
+#define PN544_PL_RDPHASES 0x06
+#define PN544_PL_EMULATION 0x07
+#define PN544_PL_NFCT_DEACTIVATED 0x09
+
+#define PN544_SWP_MGMT_GATE 0xA0
+
+#define PN544_NFC_WI_MGMT_GATE 0xA1
+
+static u8 pn544_custom_gates[] = {
+ PN544_SYS_MGMT_GATE,
+ PN544_SWP_MGMT_GATE,
+ PN544_POLLING_LOOP_MGMT_GATE,
+ PN544_NFC_WI_MGMT_GATE,
+ PN544_RF_READER_F_GATE,
+ PN544_RF_READER_JEWEL_GATE,
+ PN544_RF_READER_ISO15693_GATE,
+ PN544_RF_READER_NFCIP1_INITIATOR_GATE,
+ PN544_RF_READER_NFCIP1_TARGET_GATE
+};
+
+/* Largest headroom needed for outgoing custom commands */
+#define PN544_CMDS_HEADROOM 2
+
+struct pn544_hci_info {
+ struct i2c_client *i2c_dev;
+ struct nfc_shdlc *shdlc;
+
+ enum pn544_state state;
+
+ struct mutex info_lock;
+
+ unsigned int gpio_en;
+ unsigned int gpio_irq;
+ unsigned int gpio_fw;
+ unsigned int en_polarity;
+
+ int hard_fault; /*
+ * < 0 if hardware error occured (e.g. i2c err)
+ * and prevents normal operation.
+ */
+};
+
+static void pn544_hci_platform_init(struct pn544_hci_info *info)
+{
+ int polarity, retry, ret;
+ char rset_cmd[] = { 0x05, 0xF9, 0x04, 0x00, 0xC3, 0xE5 };
+ int count = sizeof(rset_cmd);
+
+ pr_info(DRIVER_DESC ": %s\n", __func__);
+ dev_info(&info->i2c_dev->dev, "Detecting nfc_en polarity\n");
+
+ /* Disable fw download */
+ gpio_set_value(info->gpio_fw, 0);
+
+ for (polarity = 0; polarity < 2; polarity++) {
+ info->en_polarity = polarity;
+ retry = 3;
+ while (retry--) {
+ /* power off */
+ gpio_set_value(info->gpio_en, !info->en_polarity);
+ usleep_range(10000, 15000);
+
+ /* power on */
+ gpio_set_value(info->gpio_en, info->en_polarity);
+ usleep_range(10000, 15000);
+
+ /* send reset */
+ dev_dbg(&info->i2c_dev->dev, "Sending reset cmd\n");
+ ret = i2c_master_send(info->i2c_dev, rset_cmd, count);
+ if (ret == count) {
+ dev_info(&info->i2c_dev->dev,
+ "nfc_en polarity : active %s\n",
+ (polarity == 0 ? "low" : "high"));
+ goto out;
+ }
+ }
+ }
+
+ dev_err(&info->i2c_dev->dev,
+ "Could not detect nfc_en polarity, fallback to active high\n");
+
+out:
+ gpio_set_value(info->gpio_en, !info->en_polarity);
+}
+
+static int pn544_hci_enable(struct pn544_hci_info *info, int mode)
+{
+ pr_info(DRIVER_DESC ": %s\n", __func__);
+
+ gpio_set_value(info->gpio_fw, 0);
+ gpio_set_value(info->gpio_en, info->en_polarity);
+ usleep_range(10000, 15000);
+
+ return 0;
+}
+
+static void pn544_hci_disable(struct pn544_hci_info *info)
+{
+ pr_info(DRIVER_DESC ": %s\n", __func__);
+
+ gpio_set_value(info->gpio_fw, 0);
+ gpio_set_value(info->gpio_en, !info->en_polarity);
+ usleep_range(10000, 15000);
+
+ gpio_set_value(info->gpio_en, info->en_polarity);
+ usleep_range(10000, 15000);
+
+ gpio_set_value(info->gpio_en, !info->en_polarity);
+ usleep_range(10000, 15000);
+}
+
+static int pn544_hci_i2c_write(struct i2c_client *client, u8 *buf, int len)
+{
+ int r;
+
+ usleep_range(3000, 6000);
+
+ r = i2c_master_send(client, buf, len);
+
+ if (r == -EREMOTEIO) { /* Retry, chip was in standby */
+ usleep_range(6000, 10000);
+ r = i2c_master_send(client, buf, len);
+ }
+
+ if (r >= 0 && r != len)
+ r = -EREMOTEIO;
+
+ return r;
+}
+
+static int check_crc(u8 *buf, int buflen)
+{
+ u8 len;
+ u16 crc;
+
+ len = buf[0] + 1;
+ crc = crc_ccitt(0xffff, buf, len - 2);
+ crc = ~crc;
+
+ if (buf[len - 2] != (crc & 0xff) || buf[len - 1] != (crc >> 8)) {
+ pr_err(PN544_HCI_DRIVER_NAME ": CRC error 0x%x != 0x%x 0x%x\n",
+ crc, buf[len - 1], buf[len - 2]);
+
+ pr_info(DRIVER_DESC ": %s : BAD CRC\n", __func__);
+ print_hex_dump(KERN_DEBUG, "crc: ", DUMP_PREFIX_NONE,
+ 16, 2, buf, buflen, false);
+ return -EPERM;
+ }
+ return 0;
+}
+
+/*
+ * Reads an shdlc frame and returns it in a newly allocated sk_buff. Guarantees
+ * that i2c bus will be flushed and that next read will start on a new frame.
+ * returned skb contains only LLC header and payload.
+ * returns:
+ * -EREMOTEIO : i2c read error (fatal)
+ * -EBADMSG : frame was incorrect and discarded
+ * -ENOMEM : cannot allocate skb, frame dropped
+ */
+static int pn544_hci_i2c_read(struct i2c_client *client, struct sk_buff **skb)
+{
+ int r;
+ u8 len;
+ u8 tmp[PN544_HCI_LLC_MAX_SIZE - 1];
+
+ r = i2c_master_recv(client, &len, 1);
+ if (r != 1) {
+ dev_err(&client->dev, "cannot read len byte\n");
+ return -EREMOTEIO;
+ }
+
+ if ((len < (PN544_HCI_LLC_MIN_SIZE - 1)) ||
+ (len > (PN544_HCI_LLC_MAX_SIZE - 1))) {
+ dev_err(&client->dev, "invalid len byte\n");
+ r = -EBADMSG;
+ goto flush;
+ }
+
+ *skb = alloc_skb(1 + len, GFP_KERNEL);
+ if (*skb == NULL) {
+ r = -ENOMEM;
+ goto flush;
+ }
+
+ *skb_put(*skb, 1) = len;
+
+ r = i2c_master_recv(client, skb_put(*skb, len), len);
+ if (r != len) {
+ kfree_skb(*skb);
+ return -EREMOTEIO;
+ }
+
+ r = check_crc((*skb)->data, (*skb)->len);
+ if (r != 0) {
+ kfree_skb(*skb);
+ r = -EBADMSG;
+ goto flush;
+ }
+
+ skb_pull(*skb, 1);
+ skb_trim(*skb, (*skb)->len - 2);
+
+ usleep_range(3000, 6000);
+
+ return 0;
+
+flush:
+ if (i2c_master_recv(client, tmp, sizeof(tmp)) < 0)
+ r = -EREMOTEIO;
+
+ usleep_range(3000, 6000);
+
+ return r;
+}
+
+/*
+ * Reads an shdlc frame from the chip. This is not as straightforward as it
+ * seems. There are cases where we could loose the frame start synchronization.
+ * The frame format is len-data-crc, and corruption can occur anywhere while
+ * transiting on i2c bus, such that we could read an invalid len.
+ * In order to recover synchronization with the next frame, we must be sure
+ * to read the real amount of data without using the len byte. We do this by
+ * assuming the following:
+ * - the chip will always present only one single complete frame on the bus
+ * before triggering the interrupt
+ * - the chip will not present a new frame until we have completely read
+ * the previous one (or until we have handled the interrupt).
+ * The tricky case is when we read a corrupted len that is less than the real
+ * len. We must detect this here in order to determine that we need to flush
+ * the bus. This is the reason why we check the crc here.
+ */
+static irqreturn_t pn544_hci_irq_thread_fn(int irq, void *dev_id)
+{
+ struct pn544_hci_info *info = dev_id;
+ struct i2c_client *client = info->i2c_dev;
+ struct sk_buff *skb = NULL;
+ int r;
+
+ BUG_ON(!info);
+ BUG_ON(irq != info->i2c_dev->irq);
+
+ dev_dbg(&client->dev, "IRQ\n");
+
+ if (info->hard_fault != 0)
+ return IRQ_HANDLED;
+
+ r = pn544_hci_i2c_read(client, &skb);
+ if (r == -EREMOTEIO) {
+ info->hard_fault = r;
+
+ nfc_shdlc_recv_frame(info->shdlc, NULL);
+
+ return IRQ_HANDLED;
+ } else if ((r == -ENOMEM) || (r == -EBADMSG)) {
+ return IRQ_HANDLED;
+ }
+
+ nfc_shdlc_recv_frame(info->shdlc, skb);
+
+ return IRQ_HANDLED;
+}
+
+static int pn544_hci_open(struct nfc_shdlc *shdlc)
+{
+ struct pn544_hci_info *info = nfc_shdlc_get_clientdata(shdlc);
+ int r = 0;
+
+ mutex_lock(&info->info_lock);
+
+ if (info->state != PN544_ST_COLD) {
+ r = -EBUSY;
+ goto out;
+ }
+
+ r = pn544_hci_enable(info, HCI_MODE);
+
+out:
+ mutex_unlock(&info->info_lock);
+ return r;
+}
+
+static void pn544_hci_close(struct nfc_shdlc *shdlc)
+{
+ struct pn544_hci_info *info = nfc_shdlc_get_clientdata(shdlc);
+
+ mutex_lock(&info->info_lock);
+
+ if (info->state == PN544_ST_COLD)
+ goto out;
+
+ pn544_hci_disable(info);
+
+out:
+ mutex_unlock(&info->info_lock);
+}
+
+static int pn544_hci_ready(struct nfc_shdlc *shdlc)
+{
+ struct nfc_hci_dev *hdev = nfc_shdlc_get_hci_dev(shdlc);
+ struct sk_buff *skb;
+ static struct hw_config {
+ u8 adr[2];
+ u8 value;
+ } hw_config[] = {
+ {{0x9f, 0x9a}, 0x00},
+
+ {{0x98, 0x10}, 0xbc},
+
+ {{0x9e, 0x71}, 0x00},
+
+ {{0x98, 0x09}, 0x00},
+
+ {{0x9e, 0xb4}, 0x00},
+
+ {{0x9e, 0xd9}, 0xff},
+ {{0x9e, 0xda}, 0xff},
+ {{0x9e, 0xdb}, 0x23},
+ {{0x9e, 0xdc}, 0x21},
+ {{0x9e, 0xdd}, 0x22},
+ {{0x9e, 0xde}, 0x24},
+
+ {{0x9c, 0x01}, 0x08},
+
+ {{0x9e, 0xaa}, 0x01},
+
+ {{0x9b, 0xd1}, 0x0d},
+ {{0x9b, 0xd2}, 0x24},
+ {{0x9b, 0xd3}, 0x0a},
+ {{0x9b, 0xd4}, 0x22},
+ {{0x9b, 0xd5}, 0x08},
+ {{0x9b, 0xd6}, 0x1e},
+ {{0x9b, 0xdd}, 0x1c},
+
+ {{0x9b, 0x84}, 0x13},
+ {{0x99, 0x81}, 0x7f},
+ {{0x99, 0x31}, 0x70},
+
+ {{0x98, 0x00}, 0x3f},
+
+ {{0x9f, 0x09}, 0x00},
+
+ {{0x9f, 0x0a}, 0x05},
+
+ {{0x9e, 0xd1}, 0xa1},
+ {{0x99, 0x23}, 0x00},
+
+ {{0x9e, 0x74}, 0x80},
+
+ {{0x9f, 0x28}, 0x10},
+
+ {{0x9f, 0x35}, 0x14},
+
+ {{0x9f, 0x36}, 0x60},
+
+ {{0x9c, 0x31}, 0x00},
+
+ {{0x9c, 0x32}, 0xc8},
+
+ {{0x9c, 0x19}, 0x40},
+
+ {{0x9c, 0x1a}, 0x40},
+
+ {{0x9c, 0x0c}, 0x00},
+
+ {{0x9c, 0x0d}, 0x00},
+
+ {{0x9c, 0x12}, 0x00},
+
+ {{0x9c, 0x13}, 0x00},
+
+ {{0x98, 0xa2}, 0x0e},
+
+ {{0x98, 0x93}, 0x40},
+
+ {{0x98, 0x7d}, 0x02},
+ {{0x98, 0x7e}, 0x00},
+ {{0x9f, 0xc8}, 0x01},
+ };
+ struct hw_config *p = hw_config;
+ int count = ARRAY_SIZE(hw_config);
+ struct sk_buff *res_skb;
+ u8 param[4];
+ int r;
+
+ param[0] = 0;
+ while (count--) {
+ param[1] = p->adr[0];
+ param[2] = p->adr[1];
+ param[3] = p->value;
+
+ r = nfc_hci_send_cmd(hdev, PN544_SYS_MGMT_GATE, PN544_WRITE,
+ param, 4, &res_skb);
+ if (r < 0)
+ return r;
+
+ if (res_skb->len != 1) {
+ kfree_skb(res_skb);
+ return -EPROTO;
+ }
+
+ if (res_skb->data[0] != p->value) {
+ kfree_skb(res_skb);
+ return -EIO;
+ }
+
+ kfree_skb(res_skb);
+
+ p++;
+ }
+
+ param[0] = NFC_HCI_UICC_HOST_ID;
+ r = nfc_hci_set_param(hdev, NFC_HCI_ADMIN_GATE,
+ NFC_HCI_ADMIN_WHITELIST, param, 1);
+ if (r < 0)
+ return r;
+
+ param[0] = 0x3d;
+ r = nfc_hci_set_param(hdev, PN544_SYS_MGMT_GATE,
+ PN544_SYS_MGMT_INFO_NOTIFICATION, param, 1);
+ if (r < 0)
+ return r;
+
+ param[0] = 0x0;
+ r = nfc_hci_set_param(hdev, NFC_HCI_RF_READER_A_GATE,
+ PN544_RF_READER_A_AUTO_ACTIVATION, param, 1);
+ if (r < 0)
+ return r;
+
+ r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,
+ NFC_HCI_EVT_END_OPERATION, NULL, 0);
+ if (r < 0)
+ return r;
+
+ param[0] = 0x1;
+ r = nfc_hci_set_param(hdev, PN544_POLLING_LOOP_MGMT_GATE,
+ PN544_PL_NFCT_DEACTIVATED, param, 1);
+ if (r < 0)
+ return r;
+
+ param[0] = 0x0;
+ r = nfc_hci_set_param(hdev, PN544_POLLING_LOOP_MGMT_GATE,
+ PN544_PL_RDPHASES, param, 1);
+ if (r < 0)
+ return r;
+
+ r = nfc_hci_get_param(hdev, NFC_HCI_ID_MGMT_GATE,
+ PN544_ID_MGMT_FULL_VERSION_SW, &skb);
+ if (r < 0)
+ return r;
+
+ if (skb->len != FULL_VERSION_LEN) {
+ kfree_skb(skb);
+ return -EINVAL;
+ }
+
+ print_hex_dump(KERN_DEBUG, "FULL VERSION SOFTWARE INFO: ",
+ DUMP_PREFIX_NONE, 16, 1,
+ skb->data, FULL_VERSION_LEN, false);
+
+ kfree_skb(skb);
+
+ return 0;
+}
+
+static int pn544_hci_xmit(struct nfc_shdlc *shdlc, struct sk_buff *skb)
+{
+ struct pn544_hci_info *info = nfc_shdlc_get_clientdata(shdlc);
+ struct i2c_client *client = info->i2c_dev;
+
+ if (info->hard_fault != 0)
+ return info->hard_fault;
+
+ return pn544_hci_i2c_write(client, skb->data, skb->len);
+}
+
+static int pn544_hci_start_poll(struct nfc_shdlc *shdlc, u32 protocols)
+{
+ struct nfc_hci_dev *hdev = nfc_shdlc_get_hci_dev(shdlc);
+ u8 phases = 0;
+ int r;
+ u8 duration[2];
+ u8 activated;
+
+ pr_info(DRIVER_DESC ": %s protocols = %d\n", __func__, protocols);
+
+ r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,
+ NFC_HCI_EVT_END_OPERATION, NULL, 0);
+ if (r < 0)
+ return r;
+
+ duration[0] = 0x18;
+ duration[1] = 0x6a;
+ r = nfc_hci_set_param(hdev, PN544_POLLING_LOOP_MGMT_GATE,
+ PN544_PL_EMULATION, duration, 2);
+ if (r < 0)
+ return r;
+
+ activated = 0;
+ r = nfc_hci_set_param(hdev, PN544_POLLING_LOOP_MGMT_GATE,
+ PN544_PL_NFCT_DEACTIVATED, &activated, 1);
+ if (r < 0)
+ return r;
+
+ if (protocols & (NFC_PROTO_ISO14443_MASK | NFC_PROTO_MIFARE_MASK |
+ NFC_PROTO_JEWEL_MASK))
+ phases |= 1; /* Type A */
+ if (protocols & NFC_PROTO_FELICA_MASK) {
+ phases |= (1 << 2); /* Type F 212 */
+ phases |= (1 << 3); /* Type F 424 */
+ }
+
+ phases |= (1 << 5); /* NFC active */
+
+ r = nfc_hci_set_param(hdev, PN544_POLLING_LOOP_MGMT_GATE,
+ PN544_PL_RDPHASES, &phases, 1);
+ if (r < 0)
+ return r;
+
+ r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,
+ NFC_HCI_EVT_READER_REQUESTED, NULL, 0);
+ if (r < 0)
+ nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,
+ NFC_HCI_EVT_END_OPERATION, NULL, 0);
+
+ return r;
+}
+
+static int pn544_hci_target_from_gate(struct nfc_shdlc *shdlc, u8 gate,
+ struct nfc_target *target)
+{
+ switch (gate) {
+ case PN544_RF_READER_F_GATE:
+ target->supported_protocols = NFC_PROTO_FELICA_MASK;
+ break;
+ case PN544_RF_READER_JEWEL_GATE:
+ target->supported_protocols = NFC_PROTO_JEWEL_MASK;
+ target->sens_res = 0x0c00;
+ break;
+ default:
+ return -EPROTO;
+ }
+
+ return 0;
+}
+
+static int pn544_hci_complete_target_discovered(struct nfc_shdlc *shdlc,
+ u8 gate,
+ struct nfc_target *target)
+{
+ struct nfc_hci_dev *hdev = nfc_shdlc_get_hci_dev(shdlc);
+ struct sk_buff *uid_skb;
+ int r = 0;
+
+ if (target->supported_protocols & NFC_PROTO_MIFARE_MASK) {
+ if (target->nfcid1_len != 4 && target->nfcid1_len != 7 &&
+ target->nfcid1_len != 10)
+ return -EPROTO;
+
+ r = nfc_hci_send_cmd(hdev, NFC_HCI_RF_READER_A_GATE,
+ PN544_RF_READER_CMD_ACTIVATE_NEXT,
+ target->nfcid1, target->nfcid1_len, NULL);
+ } else if (target->supported_protocols & NFC_PROTO_FELICA_MASK) {
+ r = nfc_hci_get_param(hdev, PN544_RF_READER_F_GATE,
+ PN544_FELICA_ID, &uid_skb);
+ if (r < 0)
+ return r;
+
+ if (uid_skb->len != 8) {
+ kfree_skb(uid_skb);
+ return -EPROTO;
+ }
+
+ r = nfc_hci_send_cmd(hdev, PN544_RF_READER_F_GATE,
+ PN544_RF_READER_CMD_ACTIVATE_NEXT,
+ uid_skb->data, uid_skb->len, NULL);
+ kfree_skb(uid_skb);
+ } else if (target->supported_protocols & NFC_PROTO_ISO14443_MASK) {
+ /*
+ * TODO: maybe other ISO 14443 require some kind of continue
+ * activation, but for now we've seen only this one below.
+ */
+ if (target->sens_res == 0x4403) /* Type 4 Mifare DESFire */
+ r = nfc_hci_send_cmd(hdev, NFC_HCI_RF_READER_A_GATE,
+ PN544_RF_READER_A_CMD_CONTINUE_ACTIVATION,
+ NULL, 0, NULL);
+ }
+
+ return r;
+}
+
+#define MIFARE_CMD_AUTH_KEY_A 0x60
+#define MIFARE_CMD_AUTH_KEY_B 0x61
+#define MIFARE_CMD_HEADER 2
+#define MIFARE_UID_LEN 4
+#define MIFARE_KEY_LEN 6
+#define MIFARE_CMD_LEN 12
+/*
+ * Returns:
+ * <= 0: driver handled the data exchange
+ * 1: driver doesn't especially handle, please do standard processing
+ */
+static int pn544_hci_data_exchange(struct nfc_shdlc *shdlc,
+ struct nfc_target *target,
+ struct sk_buff *skb,
+ struct sk_buff **res_skb)
+{
+ struct nfc_hci_dev *hdev = nfc_shdlc_get_hci_dev(shdlc);
+ int r;
+
+ pr_info(DRIVER_DESC ": %s for gate=%d\n", __func__,
+ target->hci_reader_gate);
+
+ switch (target->hci_reader_gate) {
+ case NFC_HCI_RF_READER_A_GATE:
+ if (target->supported_protocols & NFC_PROTO_MIFARE_MASK) {
+ /*
+ * It seems that pn544 is inverting key and UID for
+ * MIFARE authentication commands.
+ */
+ if (skb->len == MIFARE_CMD_LEN &&
+ (skb->data[0] == MIFARE_CMD_AUTH_KEY_A ||
+ skb->data[0] == MIFARE_CMD_AUTH_KEY_B)) {
+ u8 uid[MIFARE_UID_LEN];
+ u8 *data = skb->data + MIFARE_CMD_HEADER;
+
+ memcpy(uid, data + MIFARE_KEY_LEN,
+ MIFARE_UID_LEN);
+ memmove(data + MIFARE_UID_LEN, data,
+ MIFARE_KEY_LEN);
+ memcpy(data, uid, MIFARE_UID_LEN);
+ }
+
+ return nfc_hci_send_cmd(hdev, target->hci_reader_gate,
+ PN544_MIFARE_CMD,
+ skb->data, skb->len, res_skb);
+ } else
+ return 1;
+ case PN544_RF_READER_F_GATE:
+ *skb_push(skb, 1) = 0;
+ *skb_push(skb, 1) = 0;
+
+ r = nfc_hci_send_cmd(hdev, target->hci_reader_gate,
+ PN544_FELICA_RAW,
+ skb->data, skb->len, res_skb);
+ if (r == 0)
+ skb_pull(*res_skb, 1);
+ return r;
+ case PN544_RF_READER_JEWEL_GATE:
+ return nfc_hci_send_cmd(hdev, target->hci_reader_gate,
+ PN544_JEWEL_RAW_CMD,
+ skb->data, skb->len, res_skb);
+ default:
+ return 1;
+ }
+}
+
+static int pn544_hci_check_presence(struct nfc_shdlc *shdlc,
+ struct nfc_target *target)
+{
+ struct nfc_hci_dev *hdev = nfc_shdlc_get_hci_dev(shdlc);
+
+ return nfc_hci_send_cmd(hdev, target->hci_reader_gate,
+ PN544_RF_READER_CMD_PRESENCE_CHECK,
+ NULL, 0, NULL);
+}
+
+static struct nfc_shdlc_ops pn544_shdlc_ops = {
+ .open = pn544_hci_open,
+ .close = pn544_hci_close,
+ .hci_ready = pn544_hci_ready,
+ .xmit = pn544_hci_xmit,
+ .start_poll = pn544_hci_start_poll,
+ .target_from_gate = pn544_hci_target_from_gate,
+ .complete_target_discovered = pn544_hci_complete_target_discovered,
+ .data_exchange = pn544_hci_data_exchange,
+ .check_presence = pn544_hci_check_presence,
+};
+
+static int __devinit pn544_hci_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct pn544_hci_info *info;
+ struct pn544_nfc_platform_data *pdata;
+ int r = 0;
+ u32 protocols;
+ struct nfc_hci_init_data init_data;
+
+ dev_dbg(&client->dev, "%s\n", __func__);
+ dev_dbg(&client->dev, "IRQ: %d\n", client->irq);
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ dev_err(&client->dev, "Need I2C_FUNC_I2C\n");
+ return -ENODEV;
+ }
+
+ info = kzalloc(sizeof(struct pn544_hci_info), GFP_KERNEL);
+ if (!info) {
+ dev_err(&client->dev,
+ "Cannot allocate memory for pn544_hci_info.\n");
+ r = -ENOMEM;
+ goto err_info_alloc;
+ }
+
+ info->i2c_dev = client;
+ info->state = PN544_ST_COLD;
+ mutex_init(&info->info_lock);
+ i2c_set_clientdata(client, info);
+
+ pdata = client->dev.platform_data;
+ if (pdata == NULL) {
+ dev_err(&client->dev, "No platform data\n");
+ r = -EINVAL;
+ goto err_pdata;
+ }
+
+ if (pdata->request_resources == NULL) {
+ dev_err(&client->dev, "request_resources() missing\n");
+ r = -EINVAL;
+ goto err_pdata;
+ }
+
+ r = pdata->request_resources(client);
+ if (r) {
+ dev_err(&client->dev, "Cannot get platform resources\n");
+ goto err_pdata;
+ }
+
+ info->gpio_en = pdata->get_gpio(NFC_GPIO_ENABLE);
+ info->gpio_fw = pdata->get_gpio(NFC_GPIO_FW_RESET);
+ info->gpio_irq = pdata->get_gpio(NFC_GPIO_IRQ);
+
+ pn544_hci_platform_init(info);
+
+ r = request_threaded_irq(client->irq, NULL, pn544_hci_irq_thread_fn,
+ IRQF_TRIGGER_RISING, PN544_HCI_DRIVER_NAME,
+ info);
+ if (r < 0) {
+ dev_err(&client->dev, "Unable to register IRQ handler\n");
+ goto err_rti;
+ }
+
+ init_data.gate_count = ARRAY_SIZE(pn544_custom_gates);
+
+ memcpy(init_data.gates, pn544_custom_gates,
+ ARRAY_SIZE(pn544_custom_gates));
+
+ /*
+ * TODO: Session id must include the driver name + some bus addr
+ * persistent info to discriminate 2 identical chips
+ */
+ strcpy(init_data.session_id, "ID544HCI");
+
+ protocols = NFC_PROTO_JEWEL_MASK |
+ NFC_PROTO_MIFARE_MASK |
+ NFC_PROTO_FELICA_MASK |
+ NFC_PROTO_ISO14443_MASK |
+ NFC_PROTO_NFC_DEP_MASK;
+
+ info->shdlc = nfc_shdlc_allocate(&pn544_shdlc_ops,
+ &init_data, protocols,
+ PN544_CMDS_HEADROOM, 0,
+ PN544_HCI_LLC_MAX_PAYLOAD,
+ dev_name(&client->dev));
+ if (!info->shdlc) {
+ dev_err(&client->dev, "Cannot allocate nfc shdlc.\n");
+ r = -ENOMEM;
+ goto err_allocshdlc;
+ }
+
+ nfc_shdlc_set_clientdata(info->shdlc, info);
+
+ return 0;
+
+err_allocshdlc:
+ free_irq(client->irq, info);
+
+err_rti:
+ if (pdata->free_resources != NULL)
+ pdata->free_resources();
+
+err_pdata:
+ kfree(info);
+
+err_info_alloc:
+ return r;
+}
+
+static __devexit int pn544_hci_remove(struct i2c_client *client)
+{
+ struct pn544_hci_info *info = i2c_get_clientdata(client);
+ struct pn544_nfc_platform_data *pdata = client->dev.platform_data;
+
+ dev_dbg(&client->dev, "%s\n", __func__);
+
+ nfc_shdlc_free(info->shdlc);
+
+ if (info->state != PN544_ST_COLD) {
+ if (pdata->disable)
+ pdata->disable();
+ }
+
+ free_irq(client->irq, info);
+ if (pdata->free_resources)
+ pdata->free_resources();
+
+ kfree(info);
+
+ return 0;
+}
+
+static struct i2c_driver pn544_hci_driver = {
+ .driver = {
+ .name = PN544_HCI_DRIVER_NAME,
+ },
+ .probe = pn544_hci_probe,
+ .id_table = pn544_hci_id_table,
+ .remove = __devexit_p(pn544_hci_remove),
+};
+
+static int __init pn544_hci_init(void)
+{
+ int r;
+
+ pr_debug(DRIVER_DESC ": %s\n", __func__);
+
+ r = i2c_add_driver(&pn544_hci_driver);
+ if (r) {
+ pr_err(PN544_HCI_DRIVER_NAME ": driver registration failed\n");
+ return r;
+ }
+
+ return 0;
+}
+
+static void __exit pn544_hci_exit(void)
+{
+ i2c_del_driver(&pn544_hci_driver);
+}
+
+module_init(pn544_hci_init);
+module_exit(pn544_hci_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/include/linux/nfc/pn544.h b/include/linux/nfc/pn544.h
index 7ab8521..9890bba 100644
--- a/include/linux/nfc/pn544.h
+++ b/include/linux/nfc/pn544.h
@@ -84,6 +84,12 @@ struct pn544_fw_packet {
};

#ifdef __KERNEL__
+enum {
+ NFC_GPIO_ENABLE,
+ NFC_GPIO_FW_RESET,
+ NFC_GPIO_IRQ
+};
+
/* board config */
struct pn544_nfc_platform_data {
int (*request_resources) (struct i2c_client *client);
@@ -91,6 +97,7 @@ struct pn544_nfc_platform_data {
void (*enable) (int fw);
int (*test) (void);
void (*disable) (void);
+ int (*get_gpio)(int type);
};
#endif /* __KERNEL__ */

--
1.7.9.1


2012-05-07 10:32:31

by Samuel Ortiz

[permalink] [raw]
Subject: [PATCH 11/20] NFC: Send device index instead of its name when target is lost

Signed-off-by: Samuel Ortiz <[email protected]>
---
net/nfc/netlink.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
index cc89e4f..747c6b3 100644
--- a/net/nfc/netlink.c
+++ b/net/nfc/netlink.c
@@ -197,7 +197,7 @@ int nfc_genl_target_lost(struct nfc_dev *dev, u32 target_idx)
if (!hdr)
goto free_msg;

- if (nla_put_string(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev)))
+ if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx))
goto nla_put_failure;
if (nla_put_u32(msg, NFC_ATTR_TARGET_INDEX, target_idx))
goto nla_put_failure;
--
1.7.9.1


2012-05-07 10:32:28

by Samuel Ortiz

[permalink] [raw]
Subject: [PATCH 10/20] NFC: Return the amount of LLCP bytes queued to sock_sendmsg

Otherwise an LLCP send() always returns 0.

Signed-off-by: Samuel Ortiz <[email protected]>
---
net/nfc/llcp/commands.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c
index 11a3b7d..c4c100d 100644
--- a/net/nfc/llcp/commands.c
+++ b/net/nfc/llcp/commands.c
@@ -502,7 +502,7 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,

kfree(msg_data);

- return 0;
+ return len;
}

int nfc_llcp_send_rr(struct nfc_llcp_sock *sock)
--
1.7.9.1


2012-05-07 10:32:10

by Samuel Ortiz

[permalink] [raw]
Subject: [PATCH 05/20] NFC: Add HCI/SHDLC support to let driver check for tag presence

From: Eric Lapuyade <[email protected]>

Signed-off-by: Eric Lapuyade <[email protected]>
Signed-off-by: Samuel Ortiz <[email protected]>
---
include/net/nfc/hci.h | 2 ++
include/net/nfc/shdlc.h | 2 ++
net/nfc/hci/core.c | 12 ++++++++++++
net/nfc/hci/shdlc.c | 12 ++++++++++++
4 files changed, 28 insertions(+), 0 deletions(-)

diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h
index 95fc0c2..ae04200 100644
--- a/include/net/nfc/hci.h
+++ b/include/net/nfc/hci.h
@@ -39,6 +39,8 @@ struct nfc_hci_ops {
int (*data_exchange) (struct nfc_hci_dev *hdev,
struct nfc_target *target,
struct sk_buff *skb, struct sk_buff **res_skb);
+ int (*check_presence)(struct nfc_hci_dev *hdev,
+ struct nfc_target *target);
};

#define NFC_HCI_MAX_CUSTOM_GATES 15
diff --git a/include/net/nfc/shdlc.h b/include/net/nfc/shdlc.h
index 1071987..ab06afd 100644
--- a/include/net/nfc/shdlc.h
+++ b/include/net/nfc/shdlc.h
@@ -35,6 +35,8 @@ struct nfc_shdlc_ops {
int (*data_exchange) (struct nfc_shdlc *shdlc,
struct nfc_target *target,
struct sk_buff *skb, struct sk_buff **res_skb);
+ int (*check_presence)(struct nfc_shdlc *shdlc,
+ struct nfc_target *target);
};

enum shdlc_state {
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c
index ef5cd5c9..f7e4f5a 100644
--- a/net/nfc/hci/core.c
+++ b/net/nfc/hci/core.c
@@ -574,6 +574,17 @@ static int hci_data_exchange(struct nfc_dev *nfc_dev, struct nfc_target *target,
return 0;
}

+static int hci_check_presence(struct nfc_dev *nfc_dev,
+ struct nfc_target *target)
+{
+ struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev);
+
+ if (hdev->ops->check_presence)
+ return hdev->ops->check_presence(hdev, target);
+
+ return 0;
+}
+
struct nfc_ops hci_nfc_ops = {
.dev_up = hci_dev_up,
.dev_down = hci_dev_down,
@@ -582,6 +593,7 @@ struct nfc_ops hci_nfc_ops = {
.activate_target = hci_activate_target,
.deactivate_target = hci_deactivate_target,
.data_exchange = hci_data_exchange,
+ .check_presence = hci_check_presence,
};

struct nfc_hci_dev *nfc_hci_allocate_device(struct nfc_hci_ops *ops,
diff --git a/net/nfc/hci/shdlc.c b/net/nfc/hci/shdlc.c
index 923bdf7..5665dc6 100644
--- a/net/nfc/hci/shdlc.c
+++ b/net/nfc/hci/shdlc.c
@@ -816,6 +816,17 @@ static int nfc_shdlc_data_exchange(struct nfc_hci_dev *hdev,
return -EPERM;
}

+static int nfc_shdlc_check_presence(struct nfc_hci_dev *hdev,
+ struct nfc_target *target)
+{
+ struct nfc_shdlc *shdlc = nfc_hci_get_clientdata(hdev);
+
+ if (shdlc->ops->check_presence)
+ return shdlc->ops->check_presence(shdlc, target);
+
+ return 0;
+}
+
static struct nfc_hci_ops shdlc_ops = {
.open = nfc_shdlc_open,
.close = nfc_shdlc_close,
@@ -825,6 +836,7 @@ static struct nfc_hci_ops shdlc_ops = {
.target_from_gate = nfc_shdlc_target_from_gate,
.complete_target_discovered = nfc_shdlc_complete_target_discovered,
.data_exchange = nfc_shdlc_data_exchange,
+ .check_presence = nfc_shdlc_check_presence,
};

struct nfc_shdlc *nfc_shdlc_allocate(struct nfc_shdlc_ops *ops,
--
1.7.9.1


2012-05-07 10:33:08

by Samuel Ortiz

[permalink] [raw]
Subject: [PATCH 19/20] feature-removal: Remove pn544 raw driver

The pn544_hci driver uses the kernel NFC APIs while pn544 does not.
Moreover pn544 is outdated and not maintained.

Signed-off-by: Samuel Ortiz <[email protected]>
---
Documentation/feature-removal-schedule.txt | 12 ++++++++++++
1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 709e08e..dfb8b50 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -531,3 +531,15 @@ Why: There appear to be no production users of the get_robust_list syscall,
of ASLR. It was only ever intended for debugging, so it should be
removed.
Who: Kees Cook <[email protected]>
+
+----------------------------
+
+What: Removing the pn544 raw driver.
+When: 3.6
+Why: With the introduction of the NFC HCI and SHDL kernel layers, pn544.c
+ is being replaced by pn544_hci.c which is accessible through the netlink
+ and socket NFC APIs. Moreover, pn544.c is outdated and does not seem to
+ work properly with the latest Android stacks.
+ Having 2 drivers for the same hardware is confusing and as such we
+ should only keep the one following the kernel NFC APIs.
+Who: Samuel Ortiz <[email protected]>
--
1.7.9.1


2012-05-07 10:31:54

by Samuel Ortiz

[permalink] [raw]
Subject: [PATCH 01/20] NFC: Fix up for NLA_PUT_ api changes

From: Stephen Rothwell <[email protected]>

Signed-off-by: Stephen Rothwell <[email protected]>
Signed-off-by: Samuel Ortiz <[email protected]>
---
net/nfc/netlink.c | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
index ebdb605..6c558bc 100644
--- a/net/nfc/netlink.c
+++ b/net/nfc/netlink.c
@@ -197,8 +197,10 @@ int nfc_genl_target_lost(struct nfc_dev *dev, u32 target_idx)
if (!hdr)
goto free_msg;

- NLA_PUT_STRING(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev));
- NLA_PUT_U32(msg, NFC_ATTR_TARGET_INDEX, target_idx);
+ if (nla_put_string(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev)))
+ goto nla_put_failure;
+ if (nla_put_u32(msg, NFC_ATTR_TARGET_INDEX, target_idx))
+ goto nla_put_failure;

genlmsg_end(msg, hdr);

--
1.7.9.1


2012-05-07 10:32:40

by Samuel Ortiz

[permalink] [raw]
Subject: [PATCH 13/20] NFC: Quiet nci/data.c sparse noise about plain integer as NULL pointer

From: H Hartley Sweeten <[email protected]>

Pointers should be cleared with NULL, not 0.

Quiets a couple sparse warnings of the type:

warning: Using plain integer as NULL pointer

Signed-off-by: H Hartley Sweeten <[email protected]>
Cc: Lauro Ramos Venancio <[email protected]>
Cc: Aloisio Almeida Jr <[email protected]>
Cc: Samuel Ortiz <[email protected]>
Cc: "David S. Miller" <[email protected]>
Signed-off-by: Samuel Ortiz <[email protected]>
---
net/nfc/nci/data.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/net/nfc/nci/data.c b/net/nfc/nci/data.c
index a0bc326..76c48c5 100644
--- a/net/nfc/nci/data.c
+++ b/net/nfc/nci/data.c
@@ -49,7 +49,7 @@ void nci_data_exchange_complete(struct nci_dev *ndev, struct sk_buff *skb,

if (cb) {
ndev->data_exchange_cb = NULL;
- ndev->data_exchange_cb_context = 0;
+ ndev->data_exchange_cb_context = NULL;

/* forward skb to nfc core */
cb(cb_context, skb, err);
@@ -200,10 +200,10 @@ static void nci_add_rx_data_frag(struct nci_dev *ndev,
pr_err("error adding room for accumulated rx data\n");

kfree_skb(skb);
- skb = 0;
+ skb = NULL;

kfree_skb(ndev->rx_data_reassembly);
- ndev->rx_data_reassembly = 0;
+ ndev->rx_data_reassembly = NULL;

err = -ENOMEM;
goto exit;
@@ -216,7 +216,7 @@ static void nci_add_rx_data_frag(struct nci_dev *ndev,

/* third, free old reassembly */
kfree_skb(ndev->rx_data_reassembly);
- ndev->rx_data_reassembly = 0;
+ ndev->rx_data_reassembly = NULL;
}

if (pbf == NCI_PBF_CONT) {
--
1.7.9.1


2012-05-07 10:33:00

by Samuel Ortiz

[permalink] [raw]
Subject: [PATCH 17/20] NFC: The NFC genl family structure should not be exposed globally

From: H Hartley Sweeten <[email protected]>

The variable 'nfc_genl_family' is only referenced in this file and
should be marked static to prevent it from being exposed globally.

Quites the sparse warning:

warning: symbol 'nfc_genl_family' was not declared. Should it be static?

Signed-off-by: H Hartley Sweeten <[email protected]>
Cc: Lauro Ramos Venancio <[email protected]>
Cc: Aloisio Almeida Jr <[email protected]>
Cc: Samuel Ortiz <[email protected]>
Cc: "David S. Miller" <[email protected]>
Signed-off-by: Samuel Ortiz <[email protected]>
---
net/nfc/netlink.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
index 747c6b3..23b75c1 100644
--- a/net/nfc/netlink.c
+++ b/net/nfc/netlink.c
@@ -33,7 +33,7 @@ static struct genl_multicast_group nfc_genl_event_mcgrp = {
.name = NFC_GENL_MCAST_EVENT_NAME,
};

-struct genl_family nfc_genl_family = {
+static struct genl_family nfc_genl_family = {
.id = GENL_ID_GENERATE,
.hdrsize = 0,
.name = NFC_GENL_NAME,
--
1.7.9.1


2012-05-07 10:32:02

by Samuel Ortiz

[permalink] [raw]
Subject: [PATCH 03/20] NFC: Remove useless HCI private nfc target table

From: Eric Lapuyade <[email protected]>

Signed-off-by: Eric Lapuyade <[email protected]>
Signed-off-by: Samuel Ortiz <[email protected]>
---
include/net/nfc/hci.h | 2 --
net/nfc/hci/core.c | 7 -------
2 files changed, 0 insertions(+), 9 deletions(-)

diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h
index aca65a5..95fc0c2 100644
--- a/include/net/nfc/hci.h
+++ b/include/net/nfc/hci.h
@@ -83,8 +83,6 @@ struct nfc_hci_dev {
u8 gate2pipe[NFC_HCI_MAX_GATES];

bool poll_started;
- struct nfc_target *targets;
- int target_count;

u8 sw_romlib;
u8 sw_patch;
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c
index 545c19f..ef5cd5c9 100644
--- a/net/nfc/hci/core.c
+++ b/net/nfc/hci/core.c
@@ -235,13 +235,6 @@ static int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate)
targets->hci_reader_gate = gate;

r = nfc_targets_found(hdev->ndev, targets, 1);
- if (r < 0)
- goto exit;
-
- kfree(hdev->targets);
- hdev->targets = targets;
- targets = NULL;
- hdev->target_count = 1;

exit:
kfree(targets);
--
1.7.9.1


2012-05-07 13:01:54

by Stephen Rothwell

[permalink] [raw]
Subject: Re: [PATCH 01/20] NFC: Fix up for NLA_PUT_ api changes

Hi Samuel,

On Mon, 7 May 2012 12:31:12 +0200 Samuel Ortiz <[email protected]> wrote:
>
> From: Stephen Rothwell <[email protected]>
>
> Signed-off-by: Stephen Rothwell <[email protected]>
> Signed-off-by: Samuel Ortiz <[email protected]>
> ---
> net/nfc/netlink.c | 6 ++++--
> 1 files changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
> index ebdb605..6c558bc 100644
> --- a/net/nfc/netlink.c
> +++ b/net/nfc/netlink.c
> @@ -197,8 +197,10 @@ int nfc_genl_target_lost(struct nfc_dev *dev, u32 target_idx)
> if (!hdr)
> goto free_msg;
>
> - NLA_PUT_STRING(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev));
> - NLA_PUT_U32(msg, NFC_ATTR_TARGET_INDEX, target_idx);
> + if (nla_put_string(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev)))
> + goto nla_put_failure;
> + if (nla_put_u32(msg, NFC_ATTR_TARGET_INDEX, target_idx))
> + goto nla_put_failure;
>
> genlmsg_end(msg, hdr);

This has been superceded by the merge fix Dave Miller did when he merged
the wireless-next tree into the net-next tree.

--
Cheers,
Stephen Rothwell [email protected]


Attachments:
(No filename) (1.12 kB)
(No filename) (836.00 B)
Download all attachments

2012-05-07 10:32:15

by Samuel Ortiz

[permalink] [raw]
Subject: [PATCH 06/20] NFC: Update Documentation/nfc-hci.txt

From: Eric Lapuyade <[email protected]>

Document the new HCI ops and fix a few typos and spelling mistakes.

Signed-off-by: Eric Lapuyade <[email protected]>
Signed-off-by: Samuel Ortiz <[email protected]>
---
Documentation/nfc/nfc-hci.txt | 45 +++++++++++++++++++++++++++++++---------
1 files changed, 35 insertions(+), 10 deletions(-)

diff --git a/Documentation/nfc/nfc-hci.txt b/Documentation/nfc/nfc-hci.txt
index 216b725..320f933 100644
--- a/Documentation/nfc/nfc-hci.txt
+++ b/Documentation/nfc/nfc-hci.txt
@@ -22,9 +22,9 @@ response to arrive.
HCI events can also be received from the host controller. They will be handled
and a translation will be forwarded to NFC Core as needed.
HCI uses 2 execution contexts:
-- one if for executing commands : nfc_hci_msg_tx_work(). Only one command
+- one for executing commands : nfc_hci_msg_tx_work(). Only one command
can be executing at any given moment.
-- one if for dispatching received events and responses : nfc_hci_msg_rx_work()
+- one for dispatching received events and commands : nfc_hci_msg_rx_work().

HCI Session initialization:
---------------------------
@@ -52,18 +52,42 @@ entry points:
struct nfc_hci_ops {
int (*open)(struct nfc_hci_dev *hdev);
void (*close)(struct nfc_hci_dev *hdev);
+ int (*hci_ready) (struct nfc_hci_dev *hdev);
int (*xmit)(struct nfc_hci_dev *hdev, struct sk_buff *skb);
int (*start_poll)(struct nfc_hci_dev *hdev, u32 protocols);
int (*target_from_gate)(struct nfc_hci_dev *hdev, u8 gate,
struct nfc_target *target);
+ int (*complete_target_discovered) (struct nfc_hci_dev *hdev, u8 gate,
+ struct nfc_target *target);
+ int (*data_exchange) (struct nfc_hci_dev *hdev,
+ struct nfc_target *target,
+ struct sk_buff *skb, struct sk_buff **res_skb);
+ int (*check_presence)(struct nfc_hci_dev *hdev,
+ struct nfc_target *target);
};

-open() and close() shall turn the hardware on and off. xmit() shall simply
-write a frame to the chip. start_poll() is an optional entrypoint that shall
-set the hardware in polling mode. This must be implemented only if the hardware
-uses proprietary gates or a mechanism slightly different from the HCI standard.
-target_from_gate() is another optional entrypoint to return the protocols
+- open() and close() shall turn the hardware on and off.
+- hci_ready() is an optional entry point that is called right after the hci
+session has been set up. The driver can use it to do additional initialization
+that must be performed using HCI commands.
+- xmit() shall simply write a frame to the chip.
+- start_poll() is an optional entrypoint that shall set the hardware in polling
+mode. This must be implemented only if the hardware uses proprietary gates or a
+mechanism slightly different from the HCI standard.
+- target_from_gate() is an optional entrypoint to return the nfc protocols
corresponding to a proprietary gate.
+- complete_target_discovered() is an optional entry point to let the driver
+perform additional proprietary processing necessary to auto activate the
+discovered target.
+- data_exchange() must be implemented by the driver if proprietary HCI commands
+are required to send data to the tag. Some tag types will require custom
+commands, others can be written to using the standard HCI commands. The driver
+can check the tag type and either do proprietary processing, or return 1 to ask
+for standard processing.
+- check_presence() is an optional entry point that will be called regularly
+by the core to check that an activated tag is still in the field. If this is
+not implemented, the core will not be able to push tag_lost events to the user
+space

On the rx path, the driver is responsible to push incoming HCP frames to HCI
using nfc_hci_recv_frame(). HCI will take care of re-aggregation and handling
@@ -99,7 +123,8 @@ fast, cannot sleep. stores incoming frames into an shdlc rx queue
handles shdlc rx & tx queues. Dispatches HCI cmd responses.

- HCI Tx Cmd worker (MSGTXWQ)
-Serialize execution of HCI commands. Complete execution in case of resp timeout.
+Serializes execution of HCI commands. Completes execution in case of response
+timeout.

- HCI Rx worker (MSGRXWQ)
Dispatches incoming HCI commands or events.
@@ -133,11 +158,11 @@ able to complete the command with a timeout error if no response arrive.
SMW context gets scheduled and invokes nfc_shdlc_sm_work(). This function
handles shdlc framing in and out. It uses the driver xmit to send frames and
receives incoming frames in an skb queue filled from the driver IRQ handler.
-SHDLC I(nformation) frames payload are HCP fragments. They are agregated to
+SHDLC I(nformation) frames payload are HCP fragments. They are aggregated to
form complete HCI frames, which can be a response, command, or event.

HCI Responses are dispatched immediately from this context to unblock
-waiting command execution. Reponse processing involves invoking the completion
+waiting command execution. Response processing involves invoking the completion
callback that was provided by nfc_hci_msg_tx_work() when it sent the command.
The completion callback will then wake the syscall context.

--
1.7.9.1


2012-05-07 10:32:25

by Samuel Ortiz

[permalink] [raw]
Subject: [PATCH 09/20] NFC: Update the LLCP poll mask

Fix the poll mask depending on the socket state. POLLOUT was missing
for example.

Signed-off-by: Samuel Ortiz <[email protected]>
---
net/nfc/llcp/sock.c | 15 ++++++++++++++-
1 files changed, 14 insertions(+), 1 deletions(-)

diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c
index 99196d3..3f339b1 100644
--- a/net/nfc/llcp/sock.c
+++ b/net/nfc/llcp/sock.c
@@ -340,11 +340,24 @@ static unsigned int llcp_sock_poll(struct file *file, struct socket *sock,
mask |= POLLERR;

if (!skb_queue_empty(&sk->sk_receive_queue))
- mask |= POLLIN;
+ mask |= POLLIN | POLLRDNORM;

if (sk->sk_state == LLCP_CLOSED)
mask |= POLLHUP;

+ if (sk->sk_shutdown & RCV_SHUTDOWN)
+ mask |= POLLRDHUP | POLLIN | POLLRDNORM;
+
+ if (sk->sk_shutdown == SHUTDOWN_MASK)
+ mask |= POLLHUP;
+
+ if (sock_writeable(sk))
+ mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
+ else
+ set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
+
+ pr_debug("mask 0x%x\n", mask);
+
return mask;
}

--
1.7.9.1


2012-05-07 10:32:55

by Samuel Ortiz

[permalink] [raw]
Subject: [PATCH 16/20] NFC: HCI ops should not be exposed globally

From: H Hartley Sweeten <[email protected]>

The variable 'hci_nfc_ops' is only referenced in this file and
should be marked static to prevent it from being exposed globally.

Quites the sparse warning:

warning: symbol 'hci_nfc_ops' was not declared. Should it be static?

Signed-off-by: H Hartley Sweeten <[email protected]>
Cc: Lauro Ramos Venancio <[email protected]>
Cc: Aloisio Almeida Jr <[email protected]>
Cc: Samuel Ortiz <[email protected]>
Cc: "David S. Miller" <[email protected]>
Signed-off-by: Samuel Ortiz <[email protected]>
---
net/nfc/hci/core.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c
index f7e4f5a..0fdb96f 100644
--- a/net/nfc/hci/core.c
+++ b/net/nfc/hci/core.c
@@ -585,7 +585,7 @@ static int hci_check_presence(struct nfc_dev *nfc_dev,
return 0;
}

-struct nfc_ops hci_nfc_ops = {
+static struct nfc_ops hci_nfc_ops = {
.dev_up = hci_dev_up,
.dev_down = hci_dev_down,
.start_poll = hci_start_poll,
--
1.7.9.1