linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/29] NFC updates for 3.6
@ 2012-06-06 10:16 Samuel Ortiz
  2012-06-06 10:16 ` [PATCH 01/29] NFC: Take a reference on the LLCP local pointer when creating a socket Samuel Ortiz
                   ` (28 more replies)
  0 siblings, 29 replies; 30+ messages in thread
From: Samuel Ortiz @ 2012-06-06 10:16 UTC (permalink / raw)
  To: John W. Linville
  Cc: Lauro Ramos Venancio, Aloisio Almeida Jr, Ilan Elias,
	linux-wireless, linux-nfc, Samuel Ortiz

Hi John,

This is the first NFC patchset for 3.6. With this one we have:

- Peer to peer target mode support. Peer devices can now detect and activate
  us as targets, not only as initiators.
- An LLCP socket handling code simplification. It's simpler and race free now.
- LLCP fixes. Attending the NFC plugfest helped fixed a few LLCP bugs. 
- At the NFC plugfest I also found some issues with the pn533 radio and
  digital settings. This should be improved now.
- The pn533 also gets a few improvements, like a semaphore to mutex conversion
  and a proper polling loop implementation (alternating between target and
  initiator modes).

You can either apply those patches manually, or pull it from here:

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

Thanks in advance for merging this code.

Samuel Ortiz (29):
  NFC: Take a reference on the LLCP local pointer when creating a
    socket
  NFC: Socket linked list
  NFC: Move LLCP receiver window value to socket structure
  NFC: Move LLCP MIU extension value to socket structure
  NFC: LLCP's MIUX is 10 bytes long, not 7
  NFC: Export LLCP general bytes getter
  NFC: Add target mode protocols to the polling loop startup routine
  NFC: Implement pn533 target mode polling loop
  NFC: Add target mode activation netlink event
  NFC: Set the NFC device RF mode appropriately
  NFC: Introduce target mode tx ops
  NFC: Introduce target mode rx data callback
  NFC: Implement the pn533 target mode data fetching routine
  NFC: Implement the pn533 target mode Tx op
  NFC: Don't hold a NULL connecting LLCP socket lock
  NFC: Call the DEP link down ops even when in target mode
  NFC: Reset poll mod list when stopping pn533 poll
  NFC: Unregister device if pn533 initial configuration fails
  NFC: Configure pn533 RF timings
  NFC: Add passive initiator data for pn533
  NFC: Add type A and type F parameters for pn533 target mode
  NFC: Implement pn533 polling loop
  NFC: Requeue lost LLCP frames
  NFC: Send a receiver ready frame only to reply to an I frame
  NFC: Switch to Initiator mode when getting NFC_ATTR_PROTOCOLS
  NFC: Destroy LLCP timout workqueue when releasing the link
  NFC: Set the proper baud rate when trying to activate pn533 targets
  NFC: Convert pn533 from semaphore to mutex
  NFC: Monitor pn533 target mode

 drivers/nfc/pn533.c     |  662 ++++++++++++++++++++++++++++++++++++++---------
 drivers/nfc/pn544_hci.c |   10 +-
 include/linux/nfc.h     |   12 +
 include/net/nfc/hci.h   |    3 +-
 include/net/nfc/nfc.h   |   14 +-
 include/net/nfc/shdlc.h |    3 +-
 net/nfc/core.c          |  119 +++++++---
 net/nfc/hci/core.c      |   13 +-
 net/nfc/hci/shdlc.c     |    6 +-
 net/nfc/llcp/commands.c |   54 +++-
 net/nfc/llcp/llcp.c     |  421 ++++++++++++++++++------------
 net/nfc/llcp/llcp.h     |   26 ++-
 net/nfc/llcp/sock.c     |   47 ++--
 net/nfc/nci/core.c      |   15 +-
 net/nfc/netlink.c       |   81 ++++++-
 net/nfc/nfc.h           |   12 +-
 16 files changed, 1106 insertions(+), 392 deletions(-)

-- 
1.7.9.1


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 01/29] NFC: Take a reference on the LLCP local pointer when creating a socket
  2012-06-06 10:16 [PATCH 00/29] NFC updates for 3.6 Samuel Ortiz
@ 2012-06-06 10:16 ` Samuel Ortiz
  2012-06-06 10:16 ` [PATCH 02/29] NFC: Socket linked list Samuel Ortiz
                   ` (27 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Samuel Ortiz @ 2012-06-06 10:16 UTC (permalink / raw)
  To: John W. Linville
  Cc: Lauro Ramos Venancio, Aloisio Almeida Jr, Ilan Elias,
	linux-wireless, linux-nfc, Samuel Ortiz

LLCP sockets point to their local LLCP service, so they need to take a
reference on it.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 net/nfc/llcp/llcp.c |   46 +++++++++++++++++++++++++++++++---------------
 net/nfc/llcp/llcp.h |    4 ++++
 net/nfc/llcp/sock.c |   14 +++++---------
 3 files changed, 40 insertions(+), 24 deletions(-)

diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c
index 42994fa..0f6dd3a 100644
--- a/net/nfc/llcp/llcp.c
+++ b/net/nfc/llcp/llcp.c
@@ -59,8 +59,6 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local)
 			release_sock(sk);
 
 			sock_orphan(sk);
-
-			s->local = NULL;
 		}
 
 		parent_sk = &parent->sk;
@@ -83,8 +81,6 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local)
 				release_sock(accept_sk);
 
 				sock_orphan(accept_sk);
-
-				lsk->local = NULL;
 			}
 		}
 
@@ -96,13 +92,39 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local)
 		release_sock(parent_sk);
 
 		sock_orphan(parent_sk);
-
-		parent->local = NULL;
 	}
 
 	mutex_unlock(&local->socket_lock);
 }
 
+struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local)
+{
+	kref_get(&local->ref);
+
+	return local;
+}
+
+static void local_release(struct kref *ref)
+{
+	struct nfc_llcp_local *local;
+
+	local = container_of(ref, struct nfc_llcp_local, ref);
+
+	list_del(&local->list);
+	nfc_llcp_socket_release(local);
+	del_timer_sync(&local->link_timer);
+	skb_queue_purge(&local->tx_queue);
+	destroy_workqueue(local->tx_wq);
+	destroy_workqueue(local->rx_wq);
+	kfree_skb(local->rx_pending);
+	kfree(local);
+}
+
+int nfc_llcp_local_put(struct nfc_llcp_local *local)
+{
+	return kref_put(&local->ref, local_release);
+}
+
 static void nfc_llcp_clear_sdp(struct nfc_llcp_local *local)
 {
 	mutex_lock(&local->sdp_lock);
@@ -612,7 +634,7 @@ enqueue:
 
 	new_sock = nfc_llcp_sock(new_sk);
 	new_sock->dev = local->dev;
-	new_sock->local = local;
+	new_sock->local = nfc_llcp_local_get(local);
 	new_sock->nfc_protocol = sock->nfc_protocol;
 	new_sock->ssap = bound_sap;
 	new_sock->dsap = ssap;
@@ -943,6 +965,7 @@ int nfc_llcp_register_device(struct nfc_dev *ndev)
 
 	local->dev = ndev;
 	INIT_LIST_HEAD(&local->list);
+	kref_init(&local->ref);
 	mutex_init(&local->sdp_lock);
 	mutex_init(&local->socket_lock);
 	init_timer(&local->link_timer);
@@ -1015,14 +1038,7 @@ void nfc_llcp_unregister_device(struct nfc_dev *dev)
 		return;
 	}
 
-	list_del(&local->list);
-	nfc_llcp_socket_release(local);
-	del_timer_sync(&local->link_timer);
-	skb_queue_purge(&local->tx_queue);
-	destroy_workqueue(local->tx_wq);
-	destroy_workqueue(local->rx_wq);
-	kfree_skb(local->rx_pending);
-	kfree(local);
+	nfc_llcp_local_put(local);
 }
 
 int __init nfc_llcp_init(void)
diff --git a/net/nfc/llcp/llcp.h b/net/nfc/llcp/llcp.h
index 50680ce..bc61955 100644
--- a/net/nfc/llcp/llcp.h
+++ b/net/nfc/llcp/llcp.h
@@ -44,6 +44,8 @@ struct nfc_llcp_local {
 	struct list_head list;
 	struct nfc_dev *dev;
 
+	struct kref ref;
+
 	struct mutex sdp_lock;
 	struct mutex socket_lock;
 
@@ -165,6 +167,8 @@ struct nfc_llcp_sock {
 
 
 struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev);
+struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local);
+int nfc_llcp_local_put(struct nfc_llcp_local *local);
 u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local,
 			 struct nfc_llcp_sock *sock);
 u8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local);
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c
index 3f339b1..9ac397b 100644
--- a/net/nfc/llcp/sock.c
+++ b/net/nfc/llcp/sock.c
@@ -111,7 +111,7 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
 	}
 
 	llcp_sock->dev = dev;
-	llcp_sock->local = local;
+	llcp_sock->local = nfc_llcp_local_get(local);
 	llcp_sock->nfc_protocol = llcp_addr.nfc_protocol;
 	llcp_sock->service_name_len = min_t(unsigned int,
 					    llcp_addr.service_name_len,
@@ -487,7 +487,7 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
 	}
 
 	llcp_sock->dev = dev;
-	llcp_sock->local = local;
+	llcp_sock->local = nfc_llcp_local_get(local);
 	llcp_sock->ssap = nfc_llcp_get_local_ssap(local);
 	if (llcp_sock->ssap == LLCP_SAP_MAX) {
 		ret = -ENOMEM;
@@ -701,8 +701,6 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp)
 
 void nfc_llcp_sock_free(struct nfc_llcp_sock *sock)
 {
-	struct nfc_llcp_local *local = sock->local;
-
 	kfree(sock->service_name);
 
 	skb_queue_purge(&sock->tx_queue);
@@ -710,13 +708,11 @@ void nfc_llcp_sock_free(struct nfc_llcp_sock *sock)
 	skb_queue_purge(&sock->tx_backlog_queue);
 
 	list_del_init(&sock->accept_queue);
-
-	if (local != NULL && sock == local->sockets[sock->ssap])
-		local->sockets[sock->ssap] = NULL;
-	else
-		list_del_init(&sock->list);
+	list_del_init(&sock->list);
 
 	sock->parent = NULL;
+
+	nfc_llcp_local_put(sock->local);
 }
 
 static int llcp_sock_create(struct net *net, struct socket *sock,
-- 
1.7.9.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 02/29] NFC: Socket linked list
  2012-06-06 10:16 [PATCH 00/29] NFC updates for 3.6 Samuel Ortiz
  2012-06-06 10:16 ` [PATCH 01/29] NFC: Take a reference on the LLCP local pointer when creating a socket Samuel Ortiz
@ 2012-06-06 10:16 ` Samuel Ortiz
  2012-06-06 10:16 ` [PATCH 03/29] NFC: Move LLCP receiver window value to socket structure Samuel Ortiz
                   ` (26 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Samuel Ortiz @ 2012-06-06 10:16 UTC (permalink / raw)
  To: John W. Linville
  Cc: Lauro Ramos Venancio, Aloisio Almeida Jr, Ilan Elias,
	linux-wireless, linux-nfc, Samuel Ortiz

Simplify the LLCP sockets structure by putting all the connected ones
into a single linked list.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 net/nfc/llcp/llcp.c |  249 ++++++++++++++++++++++++++++-----------------------
 net/nfc/llcp/llcp.h |   12 ++-
 net/nfc/llcp/sock.c |   32 +++----
 3 files changed, 158 insertions(+), 135 deletions(-)

diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c
index 0f6dd3a..262aa82 100644
--- a/net/nfc/llcp/llcp.c
+++ b/net/nfc/llcp/llcp.c
@@ -31,45 +31,41 @@ static u8 llcp_magic[3] = {0x46, 0x66, 0x6d};
 
 static struct list_head llcp_devices;
 
-static void nfc_llcp_socket_release(struct nfc_llcp_local *local)
+void nfc_llcp_sock_link(struct llcp_sock_list *l, struct sock *sk)
 {
-	struct nfc_llcp_sock *parent, *s, *n;
-	struct sock *sk, *parent_sk;
-	int i;
-
-	mutex_lock(&local->socket_lock);
-
-	for (i = 0; i < LLCP_MAX_SAP; i++) {
-		parent = local->sockets[i];
-		if (parent == NULL)
-			continue;
-
-		/* Release all child sockets */
-		list_for_each_entry_safe(s, n, &parent->list, list) {
-			list_del_init(&s->list);
-			sk = &s->sk;
-
-			lock_sock(sk);
+	write_lock(&l->lock);
+	sk_add_node(sk, &l->head);
+	write_unlock(&l->lock);
+}
 
-			if (sk->sk_state == LLCP_CONNECTED)
-				nfc_put_device(s->dev);
+void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *sk)
+{
+	write_lock(&l->lock);
+	sk_del_node_init(sk);
+	write_unlock(&l->lock);
+}
 
-			sk->sk_state = LLCP_CLOSED;
+static void nfc_llcp_socket_release(struct nfc_llcp_local *local)
+{
+	struct sock *sk;
+	struct hlist_node *node, *tmp;
+	struct nfc_llcp_sock *llcp_sock;
 
-			release_sock(sk);
+	write_lock(&local->sockets.lock);
 
-			sock_orphan(sk);
-		}
+	sk_for_each_safe(sk, node, tmp, &local->sockets.head) {
+		llcp_sock = nfc_llcp_sock(sk);
 
-		parent_sk = &parent->sk;
+		lock_sock(sk);
 
-		lock_sock(parent_sk);
+		if (sk->sk_state == LLCP_CONNECTED)
+			nfc_put_device(llcp_sock->dev);
 
-		if (parent_sk->sk_state == LLCP_LISTEN) {
+		if (sk->sk_state == LLCP_LISTEN) {
 			struct nfc_llcp_sock *lsk, *n;
 			struct sock *accept_sk;
 
-			list_for_each_entry_safe(lsk, n, &parent->accept_queue,
+			list_for_each_entry_safe(lsk, n, &llcp_sock->accept_queue,
 						 accept_queue) {
 				accept_sk = &lsk->sk;
 				lock_sock(accept_sk);
@@ -84,17 +80,16 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local)
 			}
 		}
 
-		if (parent_sk->sk_state == LLCP_CONNECTED)
-			nfc_put_device(parent->dev);
+		sk->sk_state = LLCP_CLOSED;
 
-		parent_sk->sk_state = LLCP_CLOSED;
+		release_sock(sk);
 
-		release_sock(parent_sk);
+		sock_orphan(sk);
 
-		sock_orphan(parent_sk);
+		sk_del_node_init(sk);
 	}
 
-	mutex_unlock(&local->socket_lock);
+	write_unlock(&local->sockets.lock);
 }
 
 struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local)
@@ -122,6 +117,11 @@ static void local_release(struct kref *ref)
 
 int nfc_llcp_local_put(struct nfc_llcp_local *local)
 {
+	WARN_ON(local == NULL);
+
+	if (local == NULL)
+		return 0;
+
 	return kref_put(&local->ref, local_release);
 }
 
@@ -465,46 +465,107 @@ static void nfc_llcp_set_nrns(struct nfc_llcp_sock *sock, struct sk_buff *pdu)
 	sock->recv_ack_n = (sock->recv_n - 1) % 16;
 }
 
+static struct nfc_llcp_sock *nfc_llcp_connecting_sock_get(struct nfc_llcp_local *local,
+							  u8 ssap)
+{
+	struct sock *sk;
+	struct nfc_llcp_sock *llcp_sock;
+	struct hlist_node *node;
+
+	read_lock(&local->connecting_sockets.lock);
+
+	sk_for_each(sk, node, &local->connecting_sockets.head) {
+		llcp_sock = nfc_llcp_sock(sk);
+
+		if (llcp_sock->ssap == ssap)
+			goto out;
+	}
+
+	llcp_sock = NULL;
+
+out:
+	read_unlock(&local->connecting_sockets.lock);
+
+	sock_hold(&llcp_sock->sk);
+
+	return llcp_sock;
+}
+
 static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local,
 					       u8 ssap, u8 dsap)
 {
-	struct nfc_llcp_sock *sock, *llcp_sock, *n;
+	struct sock *sk;
+	struct hlist_node *node;
+	struct nfc_llcp_sock *llcp_sock;
 
 	pr_debug("ssap dsap %d %d\n", ssap, dsap);
 
 	if (ssap == 0 && dsap == 0)
 		return NULL;
 
-	mutex_lock(&local->socket_lock);
-	sock = local->sockets[ssap];
-	if (sock == NULL) {
-		mutex_unlock(&local->socket_lock);
-		return NULL;
-	}
+	read_lock(&local->sockets.lock);
+
+	llcp_sock = NULL;
 
-	pr_debug("root dsap %d (%d)\n", sock->dsap, dsap);
+	sk_for_each(sk, node, &local->sockets.head) {
+		llcp_sock = nfc_llcp_sock(sk);
 
-	if (sock->dsap == dsap) {
-		sock_hold(&sock->sk);
-		mutex_unlock(&local->socket_lock);
-		return sock;
+		if (llcp_sock->ssap == ssap &&
+		    llcp_sock->dsap == dsap)
+			break;
 	}
 
-	list_for_each_entry_safe(llcp_sock, n, &sock->list, list) {
-		pr_debug("llcp_sock %p sk %p dsap %d\n", llcp_sock,
-			 &llcp_sock->sk, llcp_sock->dsap);
-		if (llcp_sock->dsap == dsap) {
-			sock_hold(&llcp_sock->sk);
-			mutex_unlock(&local->socket_lock);
-			return llcp_sock;
-		}
+	read_unlock(&local->sockets.lock);
+
+	if (llcp_sock == NULL)
+		return NULL;
+
+	sock_hold(&llcp_sock->sk);
+
+	return llcp_sock;
+}
+
+static struct nfc_llcp_sock *nfc_llcp_sock_get_sn(struct nfc_llcp_local *local,
+						  u8 *sn, size_t sn_len)
+{
+	struct sock *sk;
+	struct hlist_node *node;
+	struct nfc_llcp_sock *llcp_sock;
+
+	pr_debug("sn %zd\n", sn_len);
+
+	if (sn == NULL || sn_len == 0)
+		return NULL;
+
+	read_lock(&local->sockets.lock);
+
+	llcp_sock = NULL;
+
+	sk_for_each(sk, node, &local->sockets.head) {
+		llcp_sock = nfc_llcp_sock(sk);
+
+		if (llcp_sock->sk.sk_state != LLCP_LISTEN)
+			continue;
+
+		if (llcp_sock->service_name == NULL ||
+		    llcp_sock->service_name_len == 0)
+			continue;
+
+		if (llcp_sock->service_name_len != sn_len)
+			continue;
+
+		if (memcmp(sn, llcp_sock->service_name, sn_len) == 0)
+			break;
 	}
 
-	pr_err("Could not find socket for %d %d\n", ssap, dsap);
+	read_unlock(&local->sockets.lock);
 
-	mutex_unlock(&local->socket_lock);
+	if (llcp_sock == NULL)
+		return NULL;
 
-	return NULL;
+	sock_hold(&llcp_sock->sk);
+
+	return llcp_sock;
 }
 
 static void nfc_llcp_sock_put(struct nfc_llcp_sock *sock)
@@ -540,7 +601,7 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local,
 {
 	struct sock *new_sk, *parent;
 	struct nfc_llcp_sock *sock, *new_sock;
-	u8 dsap, ssap, bound_sap, reason;
+	u8 dsap, ssap, reason;
 
 	dsap = nfc_llcp_dsap(skb);
 	ssap = nfc_llcp_ssap(skb);
@@ -551,24 +612,11 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local,
 			   skb->len - LLCP_HEADER_SIZE);
 
 	if (dsap != LLCP_SAP_SDP) {
-		bound_sap = dsap;
-
-		mutex_lock(&local->socket_lock);
-		sock = local->sockets[dsap];
-		if (sock == NULL) {
-			mutex_unlock(&local->socket_lock);
+		sock = nfc_llcp_sock_get(local, dsap, LLCP_SAP_SDP);
+		if (sock == NULL || sock->sk.sk_state != LLCP_LISTEN) {
 			reason = LLCP_DM_NOBOUND;
 			goto fail;
 		}
-
-		sock_hold(&sock->sk);
-		mutex_unlock(&local->socket_lock);
-
-		lock_sock(&sock->sk);
-
-		if (sock->dsap == LLCP_SAP_SDP &&
-		    sock->sk.sk_state == LLCP_LISTEN)
-			goto enqueue;
 	} else {
 		u8 *sn;
 		size_t sn_len;
@@ -581,40 +629,15 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local,
 
 		pr_debug("Service name length %zu\n", sn_len);
 
-		mutex_lock(&local->socket_lock);
-		for (bound_sap = 0; bound_sap < LLCP_LOCAL_SAP_OFFSET;
-		     bound_sap++) {
-			sock = local->sockets[bound_sap];
-			if (sock == NULL)
-				continue;
-
-			if (sock->service_name == NULL ||
-			    sock->service_name_len == 0)
-					continue;
-
-			if (sock->service_name_len != sn_len)
-				continue;
-
-			if (sock->dsap == LLCP_SAP_SDP &&
-			    sock->sk.sk_state == LLCP_LISTEN &&
-			    !memcmp(sn, sock->service_name, sn_len)) {
-				pr_debug("Found service name at SAP %d\n",
-					 bound_sap);
-				sock_hold(&sock->sk);
-				mutex_unlock(&local->socket_lock);
-
-				lock_sock(&sock->sk);
-
-				goto enqueue;
-			}
+		sock = nfc_llcp_sock_get_sn(local, sn, sn_len);
+		if (sock == NULL) {
+			reason = LLCP_DM_NOBOUND;
+			goto fail;
 		}
-		mutex_unlock(&local->socket_lock);
 	}
 
-	reason = LLCP_DM_NOBOUND;
-	goto fail;
+	lock_sock(&sock->sk);
 
-enqueue:
 	parent = &sock->sk;
 
 	if (sk_acceptq_is_full(parent)) {
@@ -636,13 +659,13 @@ enqueue:
 	new_sock->dev = local->dev;
 	new_sock->local = nfc_llcp_local_get(local);
 	new_sock->nfc_protocol = sock->nfc_protocol;
-	new_sock->ssap = bound_sap;
+	new_sock->ssap = sock->ssap;
 	new_sock->dsap = ssap;
 	new_sock->parent = parent;
 
 	pr_debug("new sock %p sk %p\n", new_sock, &new_sock->sk);
 
-	list_add_tail(&new_sock->list, &sock->list);
+	nfc_llcp_sock_link(&local->sockets, new_sk);
 
 	nfc_llcp_accept_enqueue(&sock->sk, new_sk);
 
@@ -813,11 +836,7 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb)
 	dsap = nfc_llcp_dsap(skb);
 	ssap = nfc_llcp_ssap(skb);
 
-	llcp_sock = nfc_llcp_sock_get(local, dsap, ssap);
-
-	if (llcp_sock == NULL)
-		llcp_sock = nfc_llcp_sock_get(local, dsap, LLCP_SAP_SDP);
-
+	llcp_sock = nfc_llcp_connecting_sock_get(local, dsap);
 	if (llcp_sock == NULL) {
 		pr_err("Invalid CC\n");
 		nfc_llcp_send_dm(local, dsap, ssap, LLCP_DM_NOCONN);
@@ -825,9 +844,13 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb)
 		return;
 	}
 
-	llcp_sock->dsap = ssap;
 	sk = &llcp_sock->sk;
 
+	/* Unlink from connecting and link to the client array */
+	nfc_llcp_sock_unlink(&local->connecting_sockets, sk);
+	nfc_llcp_sock_link(&local->sockets, sk);
+	llcp_sock->dsap = ssap;
+
 	nfc_llcp_parse_tlv(local, &skb->data[LLCP_HEADER_SIZE],
 			   skb->len - LLCP_HEADER_SIZE);
 
@@ -967,7 +990,6 @@ int nfc_llcp_register_device(struct nfc_dev *ndev)
 	INIT_LIST_HEAD(&local->list);
 	kref_init(&local->ref);
 	mutex_init(&local->sdp_lock);
-	mutex_init(&local->socket_lock);
 	init_timer(&local->link_timer);
 	local->link_timer.data = (unsigned long) local;
 	local->link_timer.function = nfc_llcp_symm_timer;
@@ -1007,6 +1029,9 @@ int nfc_llcp_register_device(struct nfc_dev *ndev)
 		goto err_rx_wq;
 	}
 
+	local->sockets.lock = __RW_LOCK_UNLOCKED(local->sockets.lock);
+	local->connecting_sockets.lock = __RW_LOCK_UNLOCKED(local->connecting_sockets.lock);
+
 	nfc_llcp_build_gb(local);
 
 	local->remote_miu = LLCP_DEFAULT_MIU;
diff --git a/net/nfc/llcp/llcp.h b/net/nfc/llcp/llcp.h
index bc61955..7053304 100644
--- a/net/nfc/llcp/llcp.h
+++ b/net/nfc/llcp/llcp.h
@@ -40,6 +40,11 @@ enum llcp_state {
 
 struct nfc_llcp_sock;
 
+struct llcp_sock_list {
+	struct hlist_head head;
+	rwlock_t          lock;
+};
+
 struct nfc_llcp_local {
 	struct list_head list;
 	struct nfc_dev *dev;
@@ -47,7 +52,6 @@ struct nfc_llcp_local {
 	struct kref ref;
 
 	struct mutex sdp_lock;
-	struct mutex socket_lock;
 
 	struct timer_list link_timer;
 	struct sk_buff_head tx_queue;
@@ -82,12 +86,12 @@ struct nfc_llcp_local {
 	u8  remote_rw;
 
 	/* sockets array */
-	struct nfc_llcp_sock *sockets[LLCP_MAX_SAP];
+	struct llcp_sock_list sockets;
+	struct llcp_sock_list connecting_sockets;
 };
 
 struct nfc_llcp_sock {
 	struct sock sk;
-	struct list_head list;
 	struct nfc_dev *dev;
 	struct nfc_llcp_local *local;
 	u32 target_idx;
@@ -166,6 +170,8 @@ struct nfc_llcp_sock {
 #define LLCP_DM_REJ     0x03
 
 
+void nfc_llcp_sock_link(struct llcp_sock_list *l, struct sock *s);
+void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *s);
 struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev);
 struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local);
 int nfc_llcp_local_put(struct nfc_llcp_local *local);
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c
index 9ac397b..8a60b53 100644
--- a/net/nfc/llcp/sock.c
+++ b/net/nfc/llcp/sock.c
@@ -124,7 +124,7 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
 	if (llcp_sock->ssap == LLCP_MAX_SAP)
 		goto put_dev;
 
-	local->sockets[llcp_sock->ssap] = llcp_sock;
+	nfc_llcp_sock_link(&local->sockets, sk);
 
 	pr_debug("Socket bound to SAP %d\n", llcp_sock->ssap);
 
@@ -379,15 +379,6 @@ static int llcp_sock_release(struct socket *sock)
 		goto out;
 	}
 
-	mutex_lock(&local->socket_lock);
-
-	if (llcp_sock == local->sockets[llcp_sock->ssap])
-		local->sockets[llcp_sock->ssap] = NULL;
-	else
-		list_del_init(&llcp_sock->list);
-
-	mutex_unlock(&local->socket_lock);
-
 	lock_sock(sk);
 
 	/* Send a DISC */
@@ -412,14 +403,12 @@ static int llcp_sock_release(struct socket *sock)
 		}
 	}
 
-	/* Freeing the SAP */
-	if ((sk->sk_state == LLCP_CONNECTED
-	     && llcp_sock->ssap > LLCP_LOCAL_SAP_OFFSET) ||
-	    sk->sk_state == LLCP_BOUND || sk->sk_state == LLCP_LISTEN)
-		nfc_llcp_put_ssap(llcp_sock->local, llcp_sock->ssap);
+	nfc_llcp_put_ssap(llcp_sock->local, llcp_sock->ssap);
 
 	release_sock(sk);
 
+	nfc_llcp_sock_unlink(&local->sockets, sk);
+
 out:
 	sock_orphan(sk);
 	sock_put(sk);
@@ -505,21 +494,26 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
 					  llcp_sock->service_name_len,
 					  GFP_KERNEL);
 
-	local->sockets[llcp_sock->ssap] = llcp_sock;
+	nfc_llcp_sock_link(&local->connecting_sockets, sk);
 
 	ret = nfc_llcp_send_connect(llcp_sock);
 	if (ret)
-		goto put_dev;
+		goto sock_unlink;
 
 	ret = sock_wait_state(sk, LLCP_CONNECTED,
 			      sock_sndtimeo(sk, flags & O_NONBLOCK));
 	if (ret)
-		goto put_dev;
+		goto sock_unlink;
 
 	release_sock(sk);
 
 	return 0;
 
+sock_unlink:
+	nfc_llcp_put_ssap(local, llcp_sock->ssap);
+
+	nfc_llcp_sock_unlink(&local->connecting_sockets, sk);
+
 put_dev:
 	nfc_put_device(dev);
 
@@ -690,7 +684,6 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp)
 	skb_queue_head_init(&llcp_sock->tx_queue);
 	skb_queue_head_init(&llcp_sock->tx_pending_queue);
 	skb_queue_head_init(&llcp_sock->tx_backlog_queue);
-	INIT_LIST_HEAD(&llcp_sock->list);
 	INIT_LIST_HEAD(&llcp_sock->accept_queue);
 
 	if (sock != NULL)
@@ -708,7 +701,6 @@ void nfc_llcp_sock_free(struct nfc_llcp_sock *sock)
 	skb_queue_purge(&sock->tx_backlog_queue);
 
 	list_del_init(&sock->accept_queue);
-	list_del_init(&sock->list);
 
 	sock->parent = NULL;
 
-- 
1.7.9.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 03/29] NFC: Move LLCP receiver window value to socket structure
  2012-06-06 10:16 [PATCH 00/29] NFC updates for 3.6 Samuel Ortiz
  2012-06-06 10:16 ` [PATCH 01/29] NFC: Take a reference on the LLCP local pointer when creating a socket Samuel Ortiz
  2012-06-06 10:16 ` [PATCH 02/29] NFC: Socket linked list Samuel Ortiz
@ 2012-06-06 10:16 ` Samuel Ortiz
  2012-06-06 10:16 ` [PATCH 04/29] NFC: Move LLCP MIU extension " Samuel Ortiz
                   ` (25 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Samuel Ortiz @ 2012-06-06 10:16 UTC (permalink / raw)
  To: John W. Linville
  Cc: Lauro Ramos Venancio, Aloisio Almeida Jr, Ilan Elias,
	linux-wireless, linux-nfc, Samuel Ortiz

RW can only be fetched from a CONNECT or a CC frame thus making it an
end points specific value, not a link one.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 net/nfc/llcp/commands.c |   45 ++++++++++++++++++++++++++++++++++++++-------
 net/nfc/llcp/llcp.c     |   21 ++++++++++-----------
 net/nfc/llcp/llcp.h     |    9 ++++++---
 net/nfc/llcp/sock.c     |    1 +
 4 files changed, 55 insertions(+), 21 deletions(-)

diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c
index bf8ae4f..eb51864 100644
--- a/net/nfc/llcp/commands.c
+++ b/net/nfc/llcp/commands.c
@@ -117,8 +117,8 @@ u8 *nfc_llcp_build_tlv(u8 type, u8 *value, u8 value_length, u8 *tlv_length)
 	return tlv;
 }
 
-int nfc_llcp_parse_tlv(struct nfc_llcp_local *local,
-		       u8 *tlv_array, u16 tlv_array_len)
+int nfc_llcp_parse_gb_tlv(struct nfc_llcp_local *local,
+			  u8 *tlv_array, u16 tlv_array_len)
 {
 	u8 *tlv = tlv_array, type, length, offset = 0;
 
@@ -149,8 +149,42 @@ int nfc_llcp_parse_tlv(struct nfc_llcp_local *local,
 		case LLCP_TLV_OPT:
 			local->remote_opt = llcp_tlv_opt(tlv);
 			break;
+		default:
+			pr_err("Invalid gt tlv value 0x%x\n", type);
+			break;
+		}
+
+		offset += length + 2;
+		tlv += length + 2;
+	}
+
+	pr_debug("version 0x%x miu %d lto %d opt 0x%x wks 0x%x\n",
+		 local->remote_version, local->remote_miu,
+		 local->remote_lto, local->remote_opt,
+		 local->remote_wks);
+
+	return 0;
+}
+
+int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock,
+				  u8 *tlv_array, u16 tlv_array_len)
+{
+	u8 *tlv = tlv_array, type, length, offset = 0;
+
+	pr_debug("TLV array length %d\n", tlv_array_len);
+
+	if (sock == NULL)
+		return -ENOTCONN;
+
+	while (offset < tlv_array_len) {
+		type = tlv[0];
+		length = tlv[1];
+
+		pr_debug("type 0x%x length %d\n", type, length);
+
+		switch (type) {
 		case LLCP_TLV_RW:
-			local->remote_rw = llcp_tlv_rw(tlv);
+			sock->rw = llcp_tlv_rw(tlv);
 			break;
 		case LLCP_TLV_SN:
 			break;
@@ -163,10 +197,7 @@ int nfc_llcp_parse_tlv(struct nfc_llcp_local *local,
 		tlv += length + 2;
 	}
 
-	pr_debug("version 0x%x miu %d lto %d opt 0x%x wks 0x%x rw %d\n",
-		 local->remote_version, local->remote_miu,
-		 local->remote_lto, local->remote_opt,
-		 local->remote_wks, local->remote_rw);
+	pr_debug("sock %p rw %d\n", sock, sock->rw);
 
 	return 0;
 }
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c
index 262aa82..d3efc5b 100644
--- a/net/nfc/llcp/llcp.c
+++ b/net/nfc/llcp/llcp.c
@@ -406,9 +406,9 @@ int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len)
 		return -EINVAL;
 	}
 
-	return nfc_llcp_parse_tlv(local,
-				  &local->remote_gb[3],
-				  local->remote_gb_len - 3);
+	return nfc_llcp_parse_gb_tlv(local,
+				     &local->remote_gb[3],
+				     local->remote_gb_len - 3);
 }
 
 static void nfc_llcp_tx_work(struct work_struct *work)
@@ -608,9 +608,6 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local,
 
 	pr_debug("%d %d\n", dsap, ssap);
 
-	nfc_llcp_parse_tlv(local, &skb->data[LLCP_HEADER_SIZE],
-			   skb->len - LLCP_HEADER_SIZE);
-
 	if (dsap != LLCP_SAP_SDP) {
 		sock = nfc_llcp_sock_get(local, dsap, LLCP_SAP_SDP);
 		if (sock == NULL || sock->sk.sk_state != LLCP_LISTEN) {
@@ -663,6 +660,9 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local,
 	new_sock->dsap = ssap;
 	new_sock->parent = parent;
 
+	nfc_llcp_parse_connection_tlv(new_sock, &skb->data[LLCP_HEADER_SIZE],
+				      skb->len - LLCP_HEADER_SIZE);
+
 	pr_debug("new sock %p sk %p\n", new_sock, &new_sock->sk);
 
 	nfc_llcp_sock_link(&local->sockets, new_sk);
@@ -699,11 +699,11 @@ int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock)
 
 	pr_debug("Remote ready %d tx queue len %d remote rw %d",
 		 sock->remote_ready, skb_queue_len(&sock->tx_pending_queue),
-		 local->remote_rw);
+		 sock->rw);
 
 	/* Try to queue some I frames for transmission */
 	while (sock->remote_ready &&
-	       skb_queue_len(&sock->tx_pending_queue) < local->remote_rw) {
+	       skb_queue_len(&sock->tx_pending_queue) < sock->rw) {
 		struct sk_buff *pdu, *pending_pdu;
 
 		pdu = skb_dequeue(&sock->tx_queue);
@@ -851,8 +851,8 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb)
 	nfc_llcp_sock_link(&local->sockets, sk);
 	llcp_sock->dsap = ssap;
 
-	nfc_llcp_parse_tlv(local, &skb->data[LLCP_HEADER_SIZE],
-			   skb->len - LLCP_HEADER_SIZE);
+	nfc_llcp_parse_connection_tlv(llcp_sock, &skb->data[LLCP_HEADER_SIZE],
+				      skb->len - LLCP_HEADER_SIZE);
 
 	sk->sk_state = LLCP_CONNECTED;
 	sk->sk_state_change(sk);
@@ -1036,7 +1036,6 @@ int nfc_llcp_register_device(struct nfc_dev *ndev)
 
 	local->remote_miu = LLCP_DEFAULT_MIU;
 	local->remote_lto = LLCP_DEFAULT_LTO;
-	local->remote_rw = LLCP_DEFAULT_RW;
 
 	list_add(&llcp_devices, &local->list);
 
diff --git a/net/nfc/llcp/llcp.h b/net/nfc/llcp/llcp.h
index 7053304..add03e7 100644
--- a/net/nfc/llcp/llcp.h
+++ b/net/nfc/llcp/llcp.h
@@ -83,7 +83,6 @@ struct nfc_llcp_local {
 	u16 remote_lto;
 	u8  remote_opt;
 	u16 remote_wks;
-	u8  remote_rw;
 
 	/* sockets array */
 	struct llcp_sock_list sockets;
@@ -97,10 +96,12 @@ struct nfc_llcp_sock {
 	u32 target_idx;
 	u32 nfc_protocol;
 
+	/* Link parameters */
 	u8 ssap;
 	u8 dsap;
 	char *service_name;
 	size_t service_name_len;
+	u8 rw;
 
 	/* Link variables */
 	u8 send_n;
@@ -189,8 +190,10 @@ void nfc_llcp_accept_enqueue(struct sock *parent, struct sock *sk);
 struct sock *nfc_llcp_accept_dequeue(struct sock *sk, struct socket *newsock);
 
 /* TLV API */
-int nfc_llcp_parse_tlv(struct nfc_llcp_local *local,
-		       u8 *tlv_array, u16 tlv_array_len);
+int nfc_llcp_parse_gb_tlv(struct nfc_llcp_local *local,
+			  u8 *tlv_array, u16 tlv_array_len);
+int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock,
+				  u8 *tlv_array, u16 tlv_array_len);
 
 /* Commands API */
 void nfc_llcp_recv(void *data, struct sk_buff *skb, int err);
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c
index 8a60b53..aab077e 100644
--- a/net/nfc/llcp/sock.c
+++ b/net/nfc/llcp/sock.c
@@ -678,6 +678,7 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp)
 
 	llcp_sock->ssap = 0;
 	llcp_sock->dsap = LLCP_SAP_SDP;
+	llcp_sock->rw = LLCP_DEFAULT_RW;
 	llcp_sock->send_n = llcp_sock->send_ack_n = 0;
 	llcp_sock->recv_n = llcp_sock->recv_ack_n = 0;
 	llcp_sock->remote_ready = 1;
-- 
1.7.9.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 04/29] NFC: Move LLCP MIU extension value to socket structure
  2012-06-06 10:16 [PATCH 00/29] NFC updates for 3.6 Samuel Ortiz
                   ` (2 preceding siblings ...)
  2012-06-06 10:16 ` [PATCH 03/29] NFC: Move LLCP receiver window value to socket structure Samuel Ortiz
@ 2012-06-06 10:16 ` Samuel Ortiz
  2012-06-06 10:16 ` [PATCH 05/29] NFC: LLCP's MIUX is 10 bytes long, not 7 Samuel Ortiz
                   ` (24 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Samuel Ortiz @ 2012-06-06 10:16 UTC (permalink / raw)
  To: John W. Linville
  Cc: Lauro Ramos Venancio, Aloisio Almeida Jr, Ilan Elias,
	linux-wireless, linux-nfc, Samuel Ortiz

The MIU extension value can be received during the PAX or during the
connection establishment process. It's definitely a connection related value
rather than a link one.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 net/nfc/llcp/commands.c |    7 +++++--
 net/nfc/llcp/llcp.c     |    1 +
 net/nfc/llcp/llcp.h     |    1 +
 net/nfc/llcp/sock.c     |    2 ++
 4 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c
index eb51864..850e5cf 100644
--- a/net/nfc/llcp/commands.c
+++ b/net/nfc/llcp/commands.c
@@ -183,6 +183,9 @@ int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock,
 		pr_debug("type 0x%x length %d\n", type, length);
 
 		switch (type) {
+		case LLCP_TLV_MIUX:
+			sock->miu = llcp_tlv_miux(tlv) + 128;
+			break;
 		case LLCP_TLV_RW:
 			sock->rw = llcp_tlv_rw(tlv);
 			break;
@@ -197,7 +200,7 @@ int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock,
 		tlv += length + 2;
 	}
 
-	pr_debug("sock %p rw %d\n", sock, sock->rw);
+	pr_debug("sock %p rw %d miu %d\n", sock, sock->rw, sock->miu);
 
 	return 0;
 }
@@ -505,7 +508,7 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
 
 	while (remaining_len > 0) {
 
-		frag_len = min_t(size_t, local->remote_miu, remaining_len);
+		frag_len = min_t(size_t, sock->miu, remaining_len);
 
 		pr_debug("Fragment %zd bytes remaining %zd",
 			 frag_len, remaining_len);
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c
index d3efc5b..5f7aa3f 100644
--- a/net/nfc/llcp/llcp.c
+++ b/net/nfc/llcp/llcp.c
@@ -655,6 +655,7 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local,
 	new_sock = nfc_llcp_sock(new_sk);
 	new_sock->dev = local->dev;
 	new_sock->local = nfc_llcp_local_get(local);
+	new_sock->miu = local->remote_miu;
 	new_sock->nfc_protocol = sock->nfc_protocol;
 	new_sock->ssap = sock->ssap;
 	new_sock->dsap = ssap;
diff --git a/net/nfc/llcp/llcp.h b/net/nfc/llcp/llcp.h
index add03e7..7286c86 100644
--- a/net/nfc/llcp/llcp.h
+++ b/net/nfc/llcp/llcp.h
@@ -102,6 +102,7 @@ struct nfc_llcp_sock {
 	char *service_name;
 	size_t service_name_len;
 	u8 rw;
+	u16 miu;
 
 	/* Link variables */
 	u8 send_n;
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c
index aab077e..30e3cc7 100644
--- a/net/nfc/llcp/sock.c
+++ b/net/nfc/llcp/sock.c
@@ -477,6 +477,7 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
 
 	llcp_sock->dev = dev;
 	llcp_sock->local = nfc_llcp_local_get(local);
+	llcp_sock->miu = llcp_sock->local->remote_miu;
 	llcp_sock->ssap = nfc_llcp_get_local_ssap(local);
 	if (llcp_sock->ssap == LLCP_SAP_MAX) {
 		ret = -ENOMEM;
@@ -679,6 +680,7 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp)
 	llcp_sock->ssap = 0;
 	llcp_sock->dsap = LLCP_SAP_SDP;
 	llcp_sock->rw = LLCP_DEFAULT_RW;
+	llcp_sock->miu = LLCP_DEFAULT_MIU;
 	llcp_sock->send_n = llcp_sock->send_ack_n = 0;
 	llcp_sock->recv_n = llcp_sock->recv_ack_n = 0;
 	llcp_sock->remote_ready = 1;
-- 
1.7.9.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 05/29] NFC: LLCP's MIUX is 10 bytes long, not 7
  2012-06-06 10:16 [PATCH 00/29] NFC updates for 3.6 Samuel Ortiz
                   ` (3 preceding siblings ...)
  2012-06-06 10:16 ` [PATCH 04/29] NFC: Move LLCP MIU extension " Samuel Ortiz
@ 2012-06-06 10:16 ` Samuel Ortiz
  2012-06-06 10:16 ` [PATCH 06/29] NFC: Export LLCP general bytes getter Samuel Ortiz
                   ` (23 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Samuel Ortiz @ 2012-06-06 10:16 UTC (permalink / raw)
  To: John W. Linville
  Cc: Lauro Ramos Venancio, Aloisio Almeida Jr, Ilan Elias,
	linux-wireless, linux-nfc, Samuel Ortiz

The mask is 0x7ff and not 0x7f and the return value is an u16.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 net/nfc/llcp/commands.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c
index 850e5cf..b982b5b 100644
--- a/net/nfc/llcp/commands.c
+++ b/net/nfc/llcp/commands.c
@@ -51,7 +51,7 @@ static u8 llcp_tlv8(u8 *tlv, u8 type)
 	return tlv[2];
 }
 
-static u8 llcp_tlv16(u8 *tlv, u8 type)
+static u16 llcp_tlv16(u8 *tlv, u8 type)
 {
 	if (tlv[0] != type || tlv[1] != llcp_tlv_length[tlv[0]])
 		return 0;
@@ -67,7 +67,7 @@ static u8 llcp_tlv_version(u8 *tlv)
 
 static u16 llcp_tlv_miux(u8 *tlv)
 {
-	return llcp_tlv16(tlv, LLCP_TLV_MIUX) & 0x7f;
+	return llcp_tlv16(tlv, LLCP_TLV_MIUX) & 0x7ff;
 }
 
 static u16 llcp_tlv_wks(u8 *tlv)
-- 
1.7.9.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 06/29] NFC: Export LLCP general bytes getter
  2012-06-06 10:16 [PATCH 00/29] NFC updates for 3.6 Samuel Ortiz
                   ` (4 preceding siblings ...)
  2012-06-06 10:16 ` [PATCH 05/29] NFC: LLCP's MIUX is 10 bytes long, not 7 Samuel Ortiz
@ 2012-06-06 10:16 ` Samuel Ortiz
  2012-06-06 10:16 ` [PATCH 07/29] NFC: Add target mode protocols to the polling loop startup routine Samuel Ortiz
                   ` (22 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Samuel Ortiz @ 2012-06-06 10:16 UTC (permalink / raw)
  To: John W. Linville
  Cc: Lauro Ramos Venancio, Aloisio Almeida Jr, Ilan Elias,
	linux-wireless, linux-nfc, Samuel Ortiz

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 include/net/nfc/nfc.h |    1 +
 net/nfc/core.c        |    8 ++++++++
 2 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h
index b7ca4a2..3116f92 100644
--- a/include/net/nfc/nfc.h
+++ b/include/net/nfc/nfc.h
@@ -188,6 +188,7 @@ struct sk_buff *nfc_alloc_recv_skb(unsigned int size, gfp_t gfp);
 
 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_targets_found(struct nfc_dev *dev,
 		      struct nfc_target *targets, int ntargets);
diff --git a/net/nfc/core.c b/net/nfc/core.c
index 9f6ce01..f5a43f7 100644
--- a/net/nfc/core.c
+++ b/net/nfc/core.c
@@ -447,6 +447,14 @@ int nfc_set_remote_general_bytes(struct nfc_dev *dev, u8 *gb, u8 gb_len)
 }
 EXPORT_SYMBOL(nfc_set_remote_general_bytes);
 
+u8 *nfc_get_local_general_bytes(struct nfc_dev *dev, size_t *gb_len)
+{
+	pr_debug("dev_name=%s\n", dev_name(&dev->dev));
+
+	return nfc_llcp_general_bytes(dev, gb_len);
+}
+EXPORT_SYMBOL(nfc_get_local_general_bytes);
+
 /**
  * nfc_alloc_send_skb - allocate a skb for data exchange responses
  *
-- 
1.7.9.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 07/29] NFC: Add target mode protocols to the polling loop startup routine
  2012-06-06 10:16 [PATCH 00/29] NFC updates for 3.6 Samuel Ortiz
                   ` (5 preceding siblings ...)
  2012-06-06 10:16 ` [PATCH 06/29] NFC: Export LLCP general bytes getter Samuel Ortiz
@ 2012-06-06 10:16 ` Samuel Ortiz
  2012-06-06 10:16 ` [PATCH 08/29] NFC: Implement pn533 target mode polling loop Samuel Ortiz
                   ` (21 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Samuel Ortiz @ 2012-06-06 10:16 UTC (permalink / raw)
  To: John W. Linville
  Cc: Lauro Ramos Venancio, Aloisio Almeida Jr, Ilan Elias,
	linux-wireless, linux-nfc, Samuel Ortiz

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 drivers/nfc/pn533.c     |   39 +++++++++++++++++++++++++++++----------
 drivers/nfc/pn544_hci.c |   10 ++++++----
 include/linux/nfc.h     |    4 ++++
 include/net/nfc/hci.h   |    3 ++-
 include/net/nfc/nfc.h   |    3 ++-
 include/net/nfc/shdlc.h |    3 ++-
 net/nfc/core.c          |   10 +++++-----
 net/nfc/hci/core.c      |    5 +++--
 net/nfc/hci/shdlc.c     |    6 ++++--
 net/nfc/nci/core.c      |    7 ++++---
 net/nfc/netlink.c       |   19 +++++++++++++++----
 net/nfc/nfc.h           |    2 +-
 12 files changed, 77 insertions(+), 34 deletions(-)

diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index 19110f0..38a523c 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -1078,27 +1078,23 @@ stop_poll:
 	return 0;
 }
 
-static int pn533_start_poll(struct nfc_dev *nfc_dev, u32 protocols)
+static int pn533_init_target(struct nfc_dev *nfc_dev, u32 protocols)
+{
+	return 0;
+}
+
+static int pn533_start_im_poll(struct nfc_dev *nfc_dev, u32 protocols)
 {
 	struct pn533 *dev = nfc_get_drvdata(nfc_dev);
 	struct pn533_poll_modulations *start_mod;
 	int rc;
 
-	nfc_dev_dbg(&dev->interface->dev, "%s - protocols=0x%x", __func__,
-								protocols);
-
 	if (dev->poll_mod_count) {
 		nfc_dev_err(&dev->interface->dev, "Polling operation already"
 								" active");
 		return -EBUSY;
 	}
 
-	if (dev->tgt_active_prot) {
-		nfc_dev_err(&dev->interface->dev, "Cannot poll with a target"
-							" already activated");
-		return -EBUSY;
-	}
-
 	pn533_poll_create_mod_list(dev, protocols);
 
 	if (!dev->poll_mod_count) {
@@ -1135,6 +1131,29 @@ error:
 	return rc;
 }
 
+static int pn533_start_poll(struct nfc_dev *nfc_dev,
+			    u32 im_protocols, u32 tm_protocols)
+{
+	struct pn533 *dev = nfc_get_drvdata(nfc_dev);
+
+	nfc_dev_dbg(&dev->interface->dev,
+		    "%s: im protocols 0x%x tm protocols 0x%x",
+		    __func__, im_protocols, tm_protocols);
+
+	if (dev->tgt_active_prot) {
+		nfc_dev_err(&dev->interface->dev,
+			    "Cannot poll with a target already activated");
+		return -EBUSY;
+	}
+
+	if (!tm_protocols)
+		return pn533_start_im_poll(nfc_dev, im_protocols);
+	else if (!im_protocols)
+		return pn533_init_target(nfc_dev, tm_protocols);
+	else
+		return -EINVAL;
+}
+
 static void pn533_stop_poll(struct nfc_dev *nfc_dev)
 {
 	struct pn533 *dev = nfc_get_drvdata(nfc_dev);
diff --git a/drivers/nfc/pn544_hci.c b/drivers/nfc/pn544_hci.c
index 281f18c..457eac3 100644
--- a/drivers/nfc/pn544_hci.c
+++ b/drivers/nfc/pn544_hci.c
@@ -576,7 +576,8 @@ static int pn544_hci_xmit(struct nfc_shdlc *shdlc, struct sk_buff *skb)
 	return pn544_hci_i2c_write(client, skb->data, skb->len);
 }
 
-static int pn544_hci_start_poll(struct nfc_shdlc *shdlc, u32 protocols)
+static int pn544_hci_start_poll(struct nfc_shdlc *shdlc,
+				u32 im_protocols, u32 tm_protocols)
 {
 	struct nfc_hci_dev *hdev = nfc_shdlc_get_hci_dev(shdlc);
 	u8 phases = 0;
@@ -584,7 +585,8 @@ static int pn544_hci_start_poll(struct nfc_shdlc *shdlc, u32 protocols)
 	u8 duration[2];
 	u8 activated;
 
-	pr_info(DRIVER_DESC ": %s protocols = %d\n", __func__, protocols);
+	pr_info(DRIVER_DESC ": %s protocols 0x%x 0x%x\n",
+		__func__, im_protocols, tm_protocols);
 
 	r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,
 			       NFC_HCI_EVT_END_OPERATION, NULL, 0);
@@ -604,10 +606,10 @@ static int pn544_hci_start_poll(struct nfc_shdlc *shdlc, u32 protocols)
 	if (r < 0)
 		return r;
 
-	if (protocols & (NFC_PROTO_ISO14443_MASK | NFC_PROTO_MIFARE_MASK |
+	if (im_protocols & (NFC_PROTO_ISO14443_MASK | NFC_PROTO_MIFARE_MASK |
 			 NFC_PROTO_JEWEL_MASK))
 		phases |= 1;		/* Type A */
-	if (protocols & NFC_PROTO_FELICA_MASK) {
+	if (im_protocols & NFC_PROTO_FELICA_MASK) {
 		phases |= (1 << 2);	/* Type F 212 */
 		phases |= (1 << 3);	/* Type F 424 */
 	}
diff --git a/include/linux/nfc.h b/include/linux/nfc.h
index 0ae9b58..5487158 100644
--- a/include/linux/nfc.h
+++ b/include/linux/nfc.h
@@ -94,6 +94,8 @@ enum nfc_commands {
  * @NFC_ATTR_TARGET_SENSF_RES: NFC-F targets extra information, max 18 bytes
  * @NFC_ATTR_COMM_MODE: Passive or active mode
  * @NFC_ATTR_RF_MODE: Initiator or target
+ * @NFC_ATTR_IM_PROTOCOLS: Initiator mode protocols to poll for
+ * @NFC_ATTR_TM_PROTOCOLS: Target mode protocols to listen for
  */
 enum nfc_attrs {
 	NFC_ATTR_UNSPEC,
@@ -109,6 +111,8 @@ enum nfc_attrs {
 	NFC_ATTR_COMM_MODE,
 	NFC_ATTR_RF_MODE,
 	NFC_ATTR_DEVICE_POWERED,
+	NFC_ATTR_IM_PROTOCOLS,
+	NFC_ATTR_TM_PROTOCOLS,
 /* private: internal use only */
 	__NFC_ATTR_AFTER_LAST
 };
diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h
index 4467c94..e30e6a8 100644
--- a/include/net/nfc/hci.h
+++ b/include/net/nfc/hci.h
@@ -31,7 +31,8 @@ struct nfc_hci_ops {
 	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 (*start_poll) (struct nfc_hci_dev *hdev,
+			   u32 im_protocols, u32 tm_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,
diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h
index 3116f92..97aa0e8 100644
--- a/include/net/nfc/nfc.h
+++ b/include/net/nfc/nfc.h
@@ -53,7 +53,8 @@ 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);
+	int (*start_poll)(struct nfc_dev *dev,
+			  u32 im_protocols, u32 tm_protocols);
 	void (*stop_poll)(struct nfc_dev *dev);
 	int (*dep_link_up)(struct nfc_dev *dev, struct nfc_target *target,
 			   u8 comm_mode, u8 *gb, size_t gb_len);
diff --git a/include/net/nfc/shdlc.h b/include/net/nfc/shdlc.h
index ab06afd..35e930d 100644
--- a/include/net/nfc/shdlc.h
+++ b/include/net/nfc/shdlc.h
@@ -27,7 +27,8 @@ struct nfc_shdlc_ops {
 	void (*close) (struct nfc_shdlc *shdlc);
 	int (*hci_ready) (struct nfc_shdlc *shdlc);
 	int (*xmit) (struct nfc_shdlc *shdlc, struct sk_buff *skb);
-	int (*start_poll) (struct nfc_shdlc *shdlc, u32 protocols);
+	int (*start_poll) (struct nfc_shdlc *shdlc,
+			   u32 im_protocols, u32 tm_protocols);
 	int (*target_from_gate) (struct nfc_shdlc *shdlc, u8 gate,
 				 struct nfc_target *target);
 	int (*complete_target_discovered) (struct nfc_shdlc *shdlc, u8 gate,
diff --git a/net/nfc/core.c b/net/nfc/core.c
index f5a43f7..c83717b 100644
--- a/net/nfc/core.c
+++ b/net/nfc/core.c
@@ -121,14 +121,14 @@ error:
  * The device remains polling for targets until a target is found or
  * the nfc_stop_poll function is called.
  */
-int nfc_start_poll(struct nfc_dev *dev, u32 protocols)
+int nfc_start_poll(struct nfc_dev *dev, u32 im_protocols, u32 tm_protocols)
 {
 	int rc;
 
-	pr_debug("dev_name=%s protocols=0x%x\n",
-		 dev_name(&dev->dev), protocols);
+	pr_debug("dev_name %s initiator protocols 0x%x target protocols 0x%x\n",
+		 dev_name(&dev->dev), im_protocols, tm_protocols);
 
-	if (!protocols)
+	if (!im_protocols && !tm_protocols)
 		return -EINVAL;
 
 	device_lock(&dev->dev);
@@ -143,7 +143,7 @@ int nfc_start_poll(struct nfc_dev *dev, u32 protocols)
 		goto error;
 	}
 
-	rc = dev->ops->start_poll(dev, protocols);
+	rc = dev->ops->start_poll(dev, im_protocols, tm_protocols);
 	if (!rc)
 		dev->polling = true;
 
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c
index e1a640d..281f3a3 100644
--- a/net/nfc/hci/core.c
+++ b/net/nfc/hci/core.c
@@ -481,12 +481,13 @@ static int hci_dev_down(struct nfc_dev *nfc_dev)
 	return 0;
 }
 
-static int hci_start_poll(struct nfc_dev *nfc_dev, u32 protocols)
+static int hci_start_poll(struct nfc_dev *nfc_dev,
+			  u32 im_protocols, u32 tm_protocols)
 {
 	struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev);
 
 	if (hdev->ops->start_poll)
-		return hdev->ops->start_poll(hdev, protocols);
+		return hdev->ops->start_poll(hdev, im_protocols, tm_protocols);
 	else
 		return nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,
 				       NFC_HCI_EVT_READER_REQUESTED, NULL, 0);
diff --git a/net/nfc/hci/shdlc.c b/net/nfc/hci/shdlc.c
index 5665dc6..6b836e6 100644
--- a/net/nfc/hci/shdlc.c
+++ b/net/nfc/hci/shdlc.c
@@ -765,14 +765,16 @@ static int nfc_shdlc_xmit(struct nfc_hci_dev *hdev, struct sk_buff *skb)
 	return 0;
 }
 
-static int nfc_shdlc_start_poll(struct nfc_hci_dev *hdev, u32 protocols)
+static int nfc_shdlc_start_poll(struct nfc_hci_dev *hdev,
+				u32 im_protocols, u32 tm_protocols)
 {
 	struct nfc_shdlc *shdlc = nfc_hci_get_clientdata(hdev);
 
 	pr_debug("\n");
 
 	if (shdlc->ops->start_poll)
-		return shdlc->ops->start_poll(shdlc, protocols);
+		return shdlc->ops->start_poll(shdlc,
+					      im_protocols, tm_protocols);
 
 	return 0;
 }
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
index d560e6f..0f71898 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -387,7 +387,8 @@ static int nci_dev_down(struct nfc_dev *nfc_dev)
 	return nci_close_device(ndev);
 }
 
-static int nci_start_poll(struct nfc_dev *nfc_dev, __u32 protocols)
+static int nci_start_poll(struct nfc_dev *nfc_dev,
+			  __u32 im_protocols, __u32 tm_protocols)
 {
 	struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
 	int rc;
@@ -413,11 +414,11 @@ static int nci_start_poll(struct nfc_dev *nfc_dev, __u32 protocols)
 			return -EBUSY;
 	}
 
-	rc = nci_request(ndev, nci_rf_discover_req, protocols,
+	rc = nci_request(ndev, nci_rf_discover_req, im_protocols,
 			 msecs_to_jiffies(NCI_RF_DISC_TIMEOUT));
 
 	if (!rc)
-		ndev->poll_prots = protocols;
+		ndev->poll_prots = im_protocols;
 
 	return rc;
 }
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
index 581d419..a18fd56 100644
--- a/net/nfc/netlink.c
+++ b/net/nfc/netlink.c
@@ -49,6 +49,8 @@ static const struct nla_policy nfc_genl_policy[NFC_ATTR_MAX + 1] = {
 	[NFC_ATTR_COMM_MODE] = { .type = NLA_U8 },
 	[NFC_ATTR_RF_MODE] = { .type = NLA_U8 },
 	[NFC_ATTR_DEVICE_POWERED] = { .type = NLA_U8 },
+	[NFC_ATTR_IM_PROTOCOLS] = { .type = NLA_U32 },
+	[NFC_ATTR_TM_PROTOCOLS] = { .type = NLA_U32 },
 };
 
 static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target,
@@ -519,16 +521,25 @@ static int nfc_genl_start_poll(struct sk_buff *skb, struct genl_info *info)
 	struct nfc_dev *dev;
 	int rc;
 	u32 idx;
-	u32 protocols;
+	u32 im_protocols = 0, tm_protocols = 0;
 
 	pr_debug("Poll start\n");
 
 	if (!info->attrs[NFC_ATTR_DEVICE_INDEX] ||
-	    !info->attrs[NFC_ATTR_PROTOCOLS])
+	    ((!info->attrs[NFC_ATTR_IM_PROTOCOLS] &&
+	      !info->attrs[NFC_ATTR_PROTOCOLS]) &&
+	     !info->attrs[NFC_ATTR_TM_PROTOCOLS]))
 		return -EINVAL;
 
 	idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
-	protocols = nla_get_u32(info->attrs[NFC_ATTR_PROTOCOLS]);
+
+	if (info->attrs[NFC_ATTR_TM_PROTOCOLS])
+		tm_protocols = nla_get_u32(info->attrs[NFC_ATTR_TM_PROTOCOLS]);
+	else if (info->attrs[NFC_ATTR_PROTOCOLS])
+		tm_protocols = nla_get_u32(info->attrs[NFC_ATTR_PROTOCOLS]);
+
+	if (info->attrs[NFC_ATTR_IM_PROTOCOLS])
+		im_protocols = nla_get_u32(info->attrs[NFC_ATTR_IM_PROTOCOLS]);
 
 	dev = nfc_get_device(idx);
 	if (!dev)
@@ -536,7 +547,7 @@ static int nfc_genl_start_poll(struct sk_buff *skb, struct genl_info *info)
 
 	mutex_lock(&dev->genl_data.genl_data_mutex);
 
-	rc = nfc_start_poll(dev, protocols);
+	rc = nfc_start_poll(dev, im_protocols, tm_protocols);
 	if (!rc)
 		dev->genl_data.poll_req_pid = info->snd_pid;
 
diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h
index 3dd4232..7d9708f 100644
--- a/net/nfc/nfc.h
+++ b/net/nfc/nfc.h
@@ -158,7 +158,7 @@ int nfc_dev_up(struct nfc_dev *dev);
 
 int nfc_dev_down(struct nfc_dev *dev);
 
-int nfc_start_poll(struct nfc_dev *dev, u32 protocols);
+int nfc_start_poll(struct nfc_dev *dev, u32 im_protocols, u32 tm_protocols);
 
 int nfc_stop_poll(struct nfc_dev *dev);
 
-- 
1.7.9.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 08/29] NFC: Implement pn533 target mode polling loop
  2012-06-06 10:16 [PATCH 00/29] NFC updates for 3.6 Samuel Ortiz
                   ` (6 preceding siblings ...)
  2012-06-06 10:16 ` [PATCH 07/29] NFC: Add target mode protocols to the polling loop startup routine Samuel Ortiz
@ 2012-06-06 10:16 ` Samuel Ortiz
  2012-06-06 10:16 ` [PATCH 09/29] NFC: Add target mode activation netlink event Samuel Ortiz
                   ` (20 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Samuel Ortiz @ 2012-06-06 10:16 UTC (permalink / raw)
  To: John W. Linville
  Cc: Lauro Ramos Venancio, Aloisio Almeida Jr, Ilan Elias,
	linux-wireless, linux-nfc, Samuel Ortiz

We only want to support p2p target mode for now, no host card emulation.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 drivers/nfc/pn533.c |  109 ++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 104 insertions(+), 5 deletions(-)

diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index 38a523c..605a08a 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -74,6 +74,8 @@ MODULE_DEVICE_TABLE(usb, pn533_table);
 #define PN533_CMD_IN_RELEASE 0x52
 #define PN533_CMD_IN_JUMP_FOR_DEP 0x56
 
+#define PN533_CMD_TG_INIT_AS_TARGET 0x8c
+
 #define PN533_CMD_RESPONSE(cmd) (cmd + 1)
 
 /* PN533 Return codes */
@@ -253,6 +255,25 @@ struct pn533_cmd_jump_dep_response {
 	u8 gt[];
 } __packed;
 
+
+/* PN533_TG_INIT_AS_TARGET */
+#define PN533_INIT_TARGET_PASSIVE 0x1
+#define PN533_INIT_TARGET_DEP 0x2
+
+struct pn533_cmd_init_target {
+	u8 mode;
+	u8 mifare[6];
+	u8 felica[18];
+	u8 nfcid3[10];
+	u8 gb_len;
+	u8 gb[];
+} __packed;
+
+struct pn533_cmd_init_target_response {
+	u8 mode;
+	u8 cmd[];
+} __packed;
+
 struct pn533 {
 	struct usb_device *udev;
 	struct usb_interface *interface;
@@ -1078,11 +1099,88 @@ stop_poll:
 	return 0;
 }
 
-static int pn533_init_target(struct nfc_dev *nfc_dev, u32 protocols)
+static int pn533_init_target_frame(struct pn533_frame *frame,
+				   u8 *gb, size_t gb_len)
 {
+	struct pn533_cmd_init_target *cmd;
+	size_t cmd_len;
+
+	cmd_len = sizeof(struct pn533_cmd_init_target) + gb_len + 1;
+	cmd = kzalloc(cmd_len, GFP_KERNEL);
+	if (cmd == NULL)
+		return -ENOMEM;
+
+	pn533_tx_frame_init(frame, PN533_CMD_TG_INIT_AS_TARGET);
+
+	/* DEP support only */
+	cmd->mode |= PN533_INIT_TARGET_DEP;
+	get_random_bytes(cmd->nfcid3, 10);
+	cmd->gb_len = gb_len;
+	memcpy(cmd->gb, gb, gb_len);
+	/* Len Tk */
+	cmd->gb[gb_len] = 0;
+
+	memcpy(PN533_FRAME_CMD_PARAMS_PTR(frame), cmd, cmd_len);
+	frame->datalen += cmd_len;
+
+	pn533_tx_frame_finish(frame);
+
 	return 0;
 }
 
+static int pn533_init_target_complete(struct pn533 *dev, void *arg,
+				      u8 *params, int params_len)
+{
+	struct pn533_cmd_init_target_response *resp;
+
+	nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+
+	if (params_len < 0) {
+		nfc_dev_err(&dev->interface->dev,
+			    "Error %d when starting as a target",
+			    params_len);
+
+		return params_len;
+	}
+
+	resp = (struct pn533_cmd_init_target_response *) params;
+
+	nfc_dev_dbg(&dev->interface->dev, "Target mode 0x%x\n", resp->mode);
+
+	return 0;
+}
+
+static int pn533_init_target(struct nfc_dev *nfc_dev, u32 protocols)
+{
+	struct pn533 *dev = nfc_get_drvdata(nfc_dev);
+	u8 *gb;
+	size_t gb_len;
+	int rc;
+
+	pn533_poll_reset_mod_list(dev);
+
+	gb = nfc_get_local_general_bytes(nfc_dev, &gb_len);
+	if (gb == NULL)
+		return -ENOMEM;
+
+	rc = pn533_init_target_frame(dev->out_frame, gb, gb_len);
+	if (rc < 0)
+		return rc;
+
+	rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame,
+					dev->in_maxlen,
+					pn533_init_target_complete,
+					NULL, GFP_KERNEL);
+
+	if (rc)
+		nfc_dev_err(&dev->interface->dev,
+			    "Error %d when trying to initiate as a target", rc);
+
+	dev->poll_mod_count++;
+
+	return rc;
+}
+
 static int pn533_start_im_poll(struct nfc_dev *nfc_dev, u32 protocols)
 {
 	struct pn533 *dev = nfc_get_drvdata(nfc_dev);
@@ -1146,12 +1244,13 @@ static int pn533_start_poll(struct nfc_dev *nfc_dev,
 		return -EBUSY;
 	}
 
-	if (!tm_protocols)
+	if (im_protocols)
 		return pn533_start_im_poll(nfc_dev, im_protocols);
-	else if (!im_protocols)
+
+	if (tm_protocols)
 		return pn533_init_target(nfc_dev, tm_protocols);
-	else
-		return -EINVAL;
+
+	return -EINVAL;
 }
 
 static void pn533_stop_poll(struct nfc_dev *nfc_dev)
-- 
1.7.9.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 09/29] NFC: Add target mode activation netlink event
  2012-06-06 10:16 [PATCH 00/29] NFC updates for 3.6 Samuel Ortiz
                   ` (7 preceding siblings ...)
  2012-06-06 10:16 ` [PATCH 08/29] NFC: Implement pn533 target mode polling loop Samuel Ortiz
@ 2012-06-06 10:16 ` Samuel Ortiz
  2012-06-06 10:16 ` [PATCH 10/29] NFC: Set the NFC device RF mode appropriately Samuel Ortiz
                   ` (19 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Samuel Ortiz @ 2012-06-06 10:16 UTC (permalink / raw)
  To: John W. Linville
  Cc: Lauro Ramos Venancio, Aloisio Almeida Jr, Ilan Elias,
	linux-wireless, linux-nfc, Samuel Ortiz

Userspace gets a netlink event upon target mode activation.
The LLCP layer is also signaled when we get an ATR_REQ in order to get
the remote general bytes.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 drivers/nfc/pn533.c   |   27 +++++++++++++++++++-
 include/linux/nfc.h   |    7 +++++
 include/net/nfc/nfc.h |    4 +++
 net/nfc/core.c        |   35 +++++++++++++++++++++++++++
 net/nfc/netlink.c     |   62 +++++++++++++++++++++++++++++++++++++++++++++++++
 net/nfc/nfc.h         |    3 ++
 6 files changed, 136 insertions(+), 2 deletions(-)

diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index 605a08a..c6b9bc5 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -260,6 +260,10 @@ struct pn533_cmd_jump_dep_response {
 #define PN533_INIT_TARGET_PASSIVE 0x1
 #define PN533_INIT_TARGET_DEP 0x2
 
+#define PN533_INIT_TARGET_RESP_FRAME_MASK 0x3
+#define PN533_INIT_TARGET_RESP_ACTIVE     0x1
+#define PN533_INIT_TARGET_RESP_DEP        0x4
+
 struct pn533_cmd_init_target {
 	u8 mode;
 	u8 mifare[6];
@@ -1128,10 +1132,13 @@ static int pn533_init_target_frame(struct pn533_frame *frame,
 	return 0;
 }
 
+#define ATR_REQ_GB_OFFSET 17
 static int pn533_init_target_complete(struct pn533 *dev, void *arg,
 				      u8 *params, int params_len)
 {
 	struct pn533_cmd_init_target_response *resp;
+	u8 frame, comm_mode = NFC_COMM_PASSIVE, *gb;
+	size_t gb_len;
 
 	nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
 
@@ -1143,11 +1150,27 @@ static int pn533_init_target_complete(struct pn533 *dev, void *arg,
 		return params_len;
 	}
 
+	if (params_len < ATR_REQ_GB_OFFSET + 1)
+		return -EINVAL;
+
 	resp = (struct pn533_cmd_init_target_response *) params;
 
-	nfc_dev_dbg(&dev->interface->dev, "Target mode 0x%x\n", resp->mode);
+	nfc_dev_dbg(&dev->interface->dev, "Target mode 0x%x param len %d\n",
+		    resp->mode, params_len);
 
-	return 0;
+	frame = resp->mode & PN533_INIT_TARGET_RESP_FRAME_MASK;
+	if (frame == PN533_INIT_TARGET_RESP_ACTIVE)
+		comm_mode = NFC_COMM_ACTIVE;
+
+	/* Again, only DEP */
+	if ((resp->mode & PN533_INIT_TARGET_RESP_DEP) == 0)
+		return -EOPNOTSUPP;
+
+	gb = resp->cmd + ATR_REQ_GB_OFFSET;
+	gb_len = params_len - (ATR_REQ_GB_OFFSET + 1);
+
+	return nfc_tm_activated(dev->nfc_dev, NFC_PROTO_NFC_DEP_MASK,
+				comm_mode, gb, gb_len);
 }
 
 static int pn533_init_target(struct nfc_dev *nfc_dev, u32 protocols)
diff --git a/include/linux/nfc.h b/include/linux/nfc.h
index 5487158..d124e92 100644
--- a/include/linux/nfc.h
+++ b/include/linux/nfc.h
@@ -56,6 +56,10 @@
  *	%NFC_ATTR_PROTOCOLS)
  * @NFC_EVENT_DEVICE_REMOVED: event emitted when a device is removed
  *	(it sends %NFC_ATTR_DEVICE_INDEX)
+ * @NFC_EVENT_TM_ACTIVATED: event emitted when the adapter is activated in
+ *      target mode.
+ * @NFC_EVENT_DEVICE_DEACTIVATED: event emitted when the adapter is deactivated
+ *      from target mode.
  */
 enum nfc_commands {
 	NFC_CMD_UNSPEC,
@@ -71,6 +75,8 @@ enum nfc_commands {
 	NFC_EVENT_DEVICE_ADDED,
 	NFC_EVENT_DEVICE_REMOVED,
 	NFC_EVENT_TARGET_LOST,
+	NFC_EVENT_TM_ACTIVATED,
+	NFC_EVENT_TM_DEACTIVATED,
 /* private: internal use only */
 	__NFC_CMD_AFTER_LAST
 };
@@ -122,6 +128,7 @@ enum nfc_attrs {
 #define NFC_NFCID1_MAXSIZE 10
 #define NFC_SENSB_RES_MAXSIZE 12
 #define NFC_SENSF_RES_MAXSIZE 18
+#define NFC_GB_MAXSIZE        48
 
 /* NFC protocols */
 #define NFC_PROTO_JEWEL		1
diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h
index 97aa0e8..41573b4b 100644
--- a/include/net/nfc/nfc.h
+++ b/include/net/nfc/nfc.h
@@ -198,4 +198,8 @@ int nfc_target_lost(struct nfc_dev *dev, u32 target_idx);
 int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx,
 		       u8 comm_mode, u8 rf_mode);
 
+int nfc_tm_activated(struct nfc_dev *dev, u32 protocol, u8 comm_mode,
+		     u8 *gb, size_t gb_len);
+int nfc_tm_deactivated(struct nfc_dev *dev);
+
 #endif /* __NET_NFC_H */
diff --git a/net/nfc/core.c b/net/nfc/core.c
index c83717b..17f1474 100644
--- a/net/nfc/core.c
+++ b/net/nfc/core.c
@@ -455,6 +455,41 @@ u8 *nfc_get_local_general_bytes(struct nfc_dev *dev, size_t *gb_len)
 }
 EXPORT_SYMBOL(nfc_get_local_general_bytes);
 
+int nfc_tm_activated(struct nfc_dev *dev, u32 protocol, u8 comm_mode,
+		     u8 *gb, size_t gb_len)
+{
+	int rc;
+
+	device_lock(&dev->dev);
+
+	dev->polling = false;
+
+	if (gb != NULL) {
+		rc = nfc_set_remote_general_bytes(dev, gb, gb_len);
+		if (rc < 0)
+			goto out;
+	}
+
+	if (protocol == NFC_PROTO_NFC_DEP_MASK)
+		nfc_dep_link_is_up(dev, 0, comm_mode, NFC_RF_TARGET);
+
+	rc = nfc_genl_tm_activated(dev, protocol);
+
+out:
+	device_unlock(&dev->dev);
+
+	return rc;
+}
+EXPORT_SYMBOL(nfc_tm_activated);
+
+int nfc_tm_deactivated(struct nfc_dev *dev)
+{
+	dev->dep_link_up = false;
+
+	return nfc_genl_tm_deactivated(dev);
+}
+EXPORT_SYMBOL(nfc_tm_deactivated);
+
 /**
  * nfc_alloc_send_skb - allocate a skb for data exchange responses
  *
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
index a18fd56..21eaa9b 100644
--- a/net/nfc/netlink.c
+++ b/net/nfc/netlink.c
@@ -221,6 +221,68 @@ free_msg:
 	return -EMSGSIZE;
 }
 
+int nfc_genl_tm_activated(struct nfc_dev *dev, u32 protocol)
+{
+	struct sk_buff *msg;
+	void *hdr;
+
+	msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
+
+	hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0,
+			  NFC_EVENT_TM_ACTIVATED);
+	if (!hdr)
+		goto free_msg;
+
+	if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx))
+		goto nla_put_failure;
+	if (nla_put_u32(msg, NFC_ATTR_TM_PROTOCOLS, protocol))
+		goto nla_put_failure;
+
+	genlmsg_end(msg, hdr);
+
+	genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL);
+
+	return 0;
+
+nla_put_failure:
+	genlmsg_cancel(msg, hdr);
+free_msg:
+	nlmsg_free(msg);
+	return -EMSGSIZE;
+}
+
+int nfc_genl_tm_deactivated(struct nfc_dev *dev)
+{
+	struct sk_buff *msg;
+	void *hdr;
+
+	msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
+
+	hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0,
+			  NFC_EVENT_TM_DEACTIVATED);
+	if (!hdr)
+		goto free_msg;
+
+	if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx))
+		goto nla_put_failure;
+
+	genlmsg_end(msg, hdr);
+
+	genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL);
+
+	return 0;
+
+nla_put_failure:
+	genlmsg_cancel(msg, hdr);
+free_msg:
+	nlmsg_free(msg);
+	return -EMSGSIZE;
+}
+
 int nfc_genl_device_added(struct nfc_dev *dev)
 {
 	struct sk_buff *msg;
diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h
index 7d9708f..cd9fcbe 100644
--- a/net/nfc/nfc.h
+++ b/net/nfc/nfc.h
@@ -128,6 +128,9 @@ int nfc_genl_dep_link_up_event(struct nfc_dev *dev, u32 target_idx,
 			       u8 comm_mode, u8 rf_mode);
 int nfc_genl_dep_link_down_event(struct nfc_dev *dev);
 
+int nfc_genl_tm_activated(struct nfc_dev *dev, u32 protocol);
+int nfc_genl_tm_deactivated(struct nfc_dev *dev);
+
 struct nfc_dev *nfc_get_device(unsigned int idx);
 
 static inline void nfc_put_device(struct nfc_dev *dev)
-- 
1.7.9.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 10/29] NFC: Set the NFC device RF mode appropriately
  2012-06-06 10:16 [PATCH 00/29] NFC updates for 3.6 Samuel Ortiz
                   ` (8 preceding siblings ...)
  2012-06-06 10:16 ` [PATCH 09/29] NFC: Add target mode activation netlink event Samuel Ortiz
@ 2012-06-06 10:16 ` Samuel Ortiz
  2012-06-06 10:16 ` [PATCH 11/29] NFC: Introduce target mode tx ops Samuel Ortiz
                   ` (18 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Samuel Ortiz @ 2012-06-06 10:16 UTC (permalink / raw)
  To: John W. Linville
  Cc: Lauro Ramos Venancio, Aloisio Almeida Jr, Ilan Elias,
	linux-wireless, linux-nfc, Samuel Ortiz

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 include/linux/nfc.h   |    1 +
 include/net/nfc/nfc.h |    2 +-
 net/nfc/core.c        |   14 ++++++++++----
 3 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/include/linux/nfc.h b/include/linux/nfc.h
index d124e92..f4e6dd9 100644
--- a/include/linux/nfc.h
+++ b/include/linux/nfc.h
@@ -146,6 +146,7 @@ enum nfc_attrs {
 /* NFC RF modes */
 #define NFC_RF_INITIATOR 0
 #define NFC_RF_TARGET    1
+#define NFC_RF_NONE      2
 
 /* NFC protocols masks used in bitsets */
 #define NFC_PROTO_JEWEL_MASK	(1 << NFC_PROTO_JEWEL)
diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h
index 41573b4b..a6a7b49 100644
--- a/include/net/nfc/nfc.h
+++ b/include/net/nfc/nfc.h
@@ -100,10 +100,10 @@ struct nfc_dev {
 	int targets_generation;
 	struct device dev;
 	bool dev_up;
+	u8 rf_mode;
 	bool polling;
 	struct nfc_target *active_target;
 	bool dep_link_up;
-	u32 dep_rf_mode;
 	struct nfc_genl_data genl_data;
 	u32 supported_protocols;
 
diff --git a/net/nfc/core.c b/net/nfc/core.c
index 17f1474..722a0c7 100644
--- a/net/nfc/core.c
+++ b/net/nfc/core.c
@@ -144,8 +144,10 @@ int nfc_start_poll(struct nfc_dev *dev, u32 im_protocols, u32 tm_protocols)
 	}
 
 	rc = dev->ops->start_poll(dev, im_protocols, tm_protocols);
-	if (!rc)
+	if (!rc) {
 		dev->polling = true;
+		dev->rf_mode = NFC_RF_NONE;
+	}
 
 error:
 	device_unlock(&dev->dev);
@@ -235,8 +237,10 @@ int nfc_dep_link_up(struct nfc_dev *dev, int target_index, u8 comm_mode)
 	}
 
 	rc = dev->ops->dep_link_up(dev, target, comm_mode, gb, gb_len);
-	if (!rc)
+	if (!rc) {
 		dev->active_target = target;
+		dev->rf_mode = NFC_RF_INITIATOR;
+	}
 
 error:
 	device_unlock(&dev->dev);
@@ -264,7 +268,7 @@ int nfc_dep_link_down(struct nfc_dev *dev)
 		goto error;
 	}
 
-	if (dev->dep_rf_mode == NFC_RF_TARGET) {
+	if (dev->rf_mode == NFC_RF_TARGET) {
 		rc = -EOPNOTSUPP;
 		goto error;
 	}
@@ -286,7 +290,6 @@ int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx,
 		       u8 comm_mode, u8 rf_mode)
 {
 	dev->dep_link_up = true;
-	dev->dep_rf_mode = rf_mode;
 
 	nfc_llcp_mac_is_up(dev, target_idx, comm_mode, rf_mode);
 
@@ -330,6 +333,7 @@ int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol)
 	rc = dev->ops->activate_target(dev, target, protocol);
 	if (!rc) {
 		dev->active_target = target;
+		dev->rf_mode = NFC_RF_INITIATOR;
 
 		if (dev->ops->check_presence)
 			mod_timer(&dev->check_pres_timer, jiffies +
@@ -470,6 +474,8 @@ int nfc_tm_activated(struct nfc_dev *dev, u32 protocol, u8 comm_mode,
 			goto out;
 	}
 
+	dev->rf_mode = NFC_RF_TARGET;
+
 	if (protocol == NFC_PROTO_NFC_DEP_MASK)
 		nfc_dep_link_is_up(dev, 0, comm_mode, NFC_RF_TARGET);
 
-- 
1.7.9.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 11/29] NFC: Introduce target mode tx ops
  2012-06-06 10:16 [PATCH 00/29] NFC updates for 3.6 Samuel Ortiz
                   ` (9 preceding siblings ...)
  2012-06-06 10:16 ` [PATCH 10/29] NFC: Set the NFC device RF mode appropriately Samuel Ortiz
@ 2012-06-06 10:16 ` Samuel Ortiz
  2012-06-06 10:16 ` [PATCH 12/29] NFC: Introduce target mode rx data callback Samuel Ortiz
                   ` (17 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Samuel Ortiz @ 2012-06-06 10:16 UTC (permalink / raw)
  To: John W. Linville
  Cc: Lauro Ramos Venancio, Aloisio Almeida Jr, Ilan Elias,
	linux-wireless, linux-nfc, Samuel Ortiz

And rename the initiator mode data exchange ops for consistency sake.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 drivers/nfc/pn533.c   |    8 ++++----
 include/net/nfc/nfc.h |    3 ++-
 net/nfc/core.c        |   37 ++++++++++++++++++++-----------------
 net/nfc/hci/core.c    |    8 ++++----
 net/nfc/nci/core.c    |    8 ++++----
 5 files changed, 34 insertions(+), 30 deletions(-)

diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index c6b9bc5..fd94c6f 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -1691,9 +1691,9 @@ error:
 	return 0;
 }
 
-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)
+static int pn533_transceive(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;
@@ -1853,7 +1853,7 @@ struct nfc_ops pn533_nfc_ops = {
 	.stop_poll = pn533_stop_poll,
 	.activate_target = pn533_activate_target,
 	.deactivate_target = pn533_deactivate_target,
-	.data_exchange = pn533_data_exchange,
+	.im_transceive = pn533_transceive,
 };
 
 static int pn533_probe(struct usb_interface *interface,
diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h
index a6a7b49..45c4c97 100644
--- a/include/net/nfc/nfc.h
+++ b/include/net/nfc/nfc.h
@@ -63,9 +63,10 @@ struct nfc_ops {
 			       u32 protocol);
 	void (*deactivate_target)(struct nfc_dev *dev,
 				  struct nfc_target *target);
-	int (*data_exchange)(struct nfc_dev *dev, struct nfc_target *target,
+	int (*im_transceive)(struct nfc_dev *dev, struct nfc_target *target,
 			     struct sk_buff *skb, data_exchange_cb_t cb,
 			     void *cb_context);
+	int (*tm_send)(struct nfc_dev *dev, struct sk_buff *skb);
 	int (*check_presence)(struct nfc_dev *dev, struct nfc_target *target);
 };
 
diff --git a/net/nfc/core.c b/net/nfc/core.c
index 722a0c7..76c1e20 100644
--- a/net/nfc/core.c
+++ b/net/nfc/core.c
@@ -413,27 +413,30 @@ int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, struct sk_buff *skb,
 		goto error;
 	}
 
-	if (dev->active_target == NULL) {
-		rc = -ENOTCONN;
-		kfree_skb(skb);
-		goto error;
-	}
+	if (dev->rf_mode == NFC_RF_INITIATOR && dev->active_target != NULL) {
+		if (dev->active_target->idx != target_idx) {
+			rc = -EADDRNOTAVAIL;
+			kfree_skb(skb);
+			goto error;
+		}
 
-	if (dev->active_target->idx != target_idx) {
-		rc = -EADDRNOTAVAIL;
+		if (dev->ops->check_presence)
+			del_timer_sync(&dev->check_pres_timer);
+
+		rc = dev->ops->im_transceive(dev, dev->active_target, skb, cb,
+					     cb_context);
+
+		if (!rc && dev->ops->check_presence)
+			mod_timer(&dev->check_pres_timer, jiffies +
+				  msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS));
+	} else if (dev->rf_mode == NFC_RF_TARGET && dev->ops->tm_send != NULL) {
+		rc = dev->ops->tm_send(dev, skb);
+	} else {
+		rc = -ENOTCONN;
 		kfree_skb(skb);
 		goto error;
 	}
 
-	if (dev->ops->check_presence)
-		del_timer_sync(&dev->check_pres_timer);
-
-	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 +
-			  msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS));
 
 error:
 	device_unlock(&dev->dev);
@@ -727,7 +730,7 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
 	struct nfc_dev *dev;
 
 	if (!ops->start_poll || !ops->stop_poll || !ops->activate_target ||
-	    !ops->deactivate_target || !ops->data_exchange)
+	    !ops->deactivate_target || !ops->im_transceive)
 		return NULL;
 
 	if (!supported_protocols)
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c
index 281f3a3..a8b0b71 100644
--- a/net/nfc/hci/core.c
+++ b/net/nfc/hci/core.c
@@ -512,9 +512,9 @@ static void hci_deactivate_target(struct nfc_dev *nfc_dev,
 {
 }
 
-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)
+static int hci_transceive(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;
@@ -580,7 +580,7 @@ static struct nfc_ops hci_nfc_ops = {
 	.stop_poll = hci_stop_poll,
 	.activate_target = hci_activate_target,
 	.deactivate_target = hci_deactivate_target,
-	.data_exchange = hci_data_exchange,
+	.im_transceive = hci_transceive,
 	.check_presence = hci_check_presence,
 };
 
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
index 0f71898..766a02b 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -522,9 +522,9 @@ static void nci_deactivate_target(struct nfc_dev *nfc_dev,
 	}
 }
 
-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)
+static int nci_transceive(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;
@@ -557,7 +557,7 @@ static struct nfc_ops nci_nfc_ops = {
 	.stop_poll = nci_stop_poll,
 	.activate_target = nci_activate_target,
 	.deactivate_target = nci_deactivate_target,
-	.data_exchange = nci_data_exchange,
+	.im_transceive = nci_transceive,
 };
 
 /* ---- Interface to NCI drivers ---- */
-- 
1.7.9.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 12/29] NFC: Introduce target mode rx data callback
  2012-06-06 10:16 [PATCH 00/29] NFC updates for 3.6 Samuel Ortiz
                   ` (10 preceding siblings ...)
  2012-06-06 10:16 ` [PATCH 11/29] NFC: Introduce target mode tx ops Samuel Ortiz
@ 2012-06-06 10:16 ` Samuel Ortiz
  2012-06-06 10:16 ` [PATCH 13/29] NFC: Implement the pn533 target mode data fetching routine Samuel Ortiz
                   ` (16 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Samuel Ortiz @ 2012-06-06 10:16 UTC (permalink / raw)
  To: John W. Linville
  Cc: Lauro Ramos Venancio, Aloisio Almeida Jr, Ilan Elias,
	linux-wireless, linux-nfc, Samuel Ortiz

This routine will be called by drivers whenever they receive data in target
mode. This should be unexpected events and as such should be handled by a
standalone API (i.e. not as a callback pointer from an existing API).

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 include/net/nfc/nfc.h |    1 +
 net/nfc/core.c        |   12 ++++++++++++
 net/nfc/llcp/llcp.c   |   15 +++++++++++++++
 net/nfc/nfc.h         |    7 +++++++
 4 files changed, 35 insertions(+), 0 deletions(-)

diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h
index 45c4c97..180964b 100644
--- a/include/net/nfc/nfc.h
+++ b/include/net/nfc/nfc.h
@@ -202,5 +202,6 @@ int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx,
 int nfc_tm_activated(struct nfc_dev *dev, u32 protocol, u8 comm_mode,
 		     u8 *gb, size_t gb_len);
 int nfc_tm_deactivated(struct nfc_dev *dev);
+int nfc_tm_data_received(struct nfc_dev *dev, struct sk_buff *skb);
 
 #endif /* __NET_NFC_H */
diff --git a/net/nfc/core.c b/net/nfc/core.c
index 76c1e20..6a3799e 100644
--- a/net/nfc/core.c
+++ b/net/nfc/core.c
@@ -462,6 +462,18 @@ u8 *nfc_get_local_general_bytes(struct nfc_dev *dev, size_t *gb_len)
 }
 EXPORT_SYMBOL(nfc_get_local_general_bytes);
 
+int nfc_tm_data_received(struct nfc_dev *dev, struct sk_buff *skb)
+{
+	/* Only LLCP target mode for now */
+	if (dev->dep_link_up == false) {
+		kfree_skb(skb);
+		return -ENOLINK;
+	}
+
+	return nfc_llcp_data_received(dev, skb);
+}
+EXPORT_SYMBOL(nfc_tm_data_received);
+
 int nfc_tm_activated(struct nfc_dev *dev, u32 protocol, u8 comm_mode,
 		     u8 *gb, size_t gb_len)
 {
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c
index 5f7aa3f..5705e6d 100644
--- a/net/nfc/llcp/llcp.c
+++ b/net/nfc/llcp/llcp.c
@@ -937,6 +937,21 @@ void nfc_llcp_recv(void *data, struct sk_buff *skb, int err)
 	return;
 }
 
+int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb)
+{
+	struct nfc_llcp_local *local;
+
+	local = nfc_llcp_find_local(dev);
+	if (local == NULL)
+		return -ENODEV;
+
+	local->rx_pending = skb_get(skb);
+	del_timer(&local->link_timer);
+	queue_work(local->rx_wq, &local->rx_work);
+
+	return 0;
+}
+
 void nfc_llcp_mac_is_down(struct nfc_dev *dev)
 {
 	struct nfc_llcp_local *local;
diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h
index cd9fcbe..c5e42b7 100644
--- a/net/nfc/nfc.h
+++ b/net/nfc/nfc.h
@@ -55,6 +55,7 @@ int nfc_llcp_register_device(struct nfc_dev *dev);
 void nfc_llcp_unregister_device(struct nfc_dev *dev);
 int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len);
 u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len);
+int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb);
 int __init nfc_llcp_init(void);
 void nfc_llcp_exit(void);
 
@@ -90,6 +91,12 @@ static inline u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *gb_len)
 	return NULL;
 }
 
+static inline int nfc_llcp_data_received(struct nfc_dev *dev,
+					 struct sk_buff *skb)
+{
+	return 0;
+}
+
 static inline int nfc_llcp_init(void)
 {
 	return 0;
-- 
1.7.9.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 13/29] NFC: Implement the pn533 target mode data fetching routine
  2012-06-06 10:16 [PATCH 00/29] NFC updates for 3.6 Samuel Ortiz
                   ` (11 preceding siblings ...)
  2012-06-06 10:16 ` [PATCH 12/29] NFC: Introduce target mode rx data callback Samuel Ortiz
@ 2012-06-06 10:16 ` Samuel Ortiz
  2012-06-06 10:16 ` [PATCH 14/29] NFC: Implement the pn533 target mode Tx op Samuel Ortiz
                   ` (15 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Samuel Ortiz @ 2012-06-06 10:16 UTC (permalink / raw)
  To: John W. Linville
  Cc: Lauro Ramos Venancio, Aloisio Almeida Jr, Ilan Elias,
	linux-wireless, linux-nfc, Samuel Ortiz

This one needs to be called as soon as we are activated as a target, for
the pn533 to receive the first SYMM and keep the LLCP link alive.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 drivers/nfc/pn533.c |   85 ++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 80 insertions(+), 5 deletions(-)

diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index fd94c6f..6a506e2 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -75,6 +75,7 @@ MODULE_DEVICE_TABLE(usb, pn533_table);
 #define PN533_CMD_IN_JUMP_FOR_DEP 0x56
 
 #define PN533_CMD_TG_INIT_AS_TARGET 0x8c
+#define PN533_CMD_TG_GET_DATA 0x86
 
 #define PN533_CMD_RESPONSE(cmd) (cmd + 1)
 
@@ -83,6 +84,9 @@ MODULE_DEVICE_TABLE(usb, pn533_table);
 #define PN533_CMD_MI_MASK 0x40
 #define PN533_CMD_RET_SUCCESS 0x00
 
+/* PN533 status codes */
+#define PN533_STATUS_TARGET_RELEASED 0x29
+
 struct pn533;
 
 typedef int (*pn533_cmd_complete_t) (struct pn533 *dev, void *arg,
@@ -296,6 +300,7 @@ struct pn533 {
 	struct workqueue_struct	*wq;
 	struct work_struct cmd_work;
 	struct work_struct mi_work;
+	struct work_struct tg_work;
 	struct pn533_frame *wq_in_frame;
 	int wq_in_error;
 
@@ -1132,6 +1137,68 @@ static int pn533_init_target_frame(struct pn533_frame *frame,
 	return 0;
 }
 
+#define PN533_CMD_DATAEXCH_HEAD_LEN (sizeof(struct pn533_frame) + 3)
+#define PN533_CMD_DATAEXCH_DATA_MAXLEN 262
+static int pn533_tm_get_data_complete(struct pn533 *dev, void *arg,
+				      u8 *params, int params_len)
+{
+	struct sk_buff *skb_resp = arg;
+	struct pn533_frame *in_frame = (struct pn533_frame *) skb_resp->data;
+
+	nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+
+	if (params_len < 0) {
+		nfc_dev_err(&dev->interface->dev,
+			    "Error %d when starting as a target",
+			    params_len);
+
+		return params_len;
+	}
+
+	if (params_len > 0 && params[0] != 0) {
+		nfc_tm_deactivated(dev->nfc_dev);
+
+		kfree_skb(skb_resp);
+		return 0;
+	}
+
+	skb_put(skb_resp, PN533_FRAME_SIZE(in_frame));
+	skb_pull(skb_resp, PN533_CMD_DATAEXCH_HEAD_LEN);
+	skb_trim(skb_resp, skb_resp->len - PN533_FRAME_TAIL_SIZE);
+
+	return nfc_tm_data_received(dev->nfc_dev, skb_resp);
+}
+
+static void pn533_wq_tg_get_data(struct work_struct *work)
+{
+	struct pn533 *dev = container_of(work, struct pn533, tg_work);
+	struct pn533_frame *in_frame;
+	struct sk_buff *skb_resp;
+	size_t skb_resp_len;
+
+	nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+
+	skb_resp_len = PN533_CMD_DATAEXCH_HEAD_LEN +
+		PN533_CMD_DATAEXCH_DATA_MAXLEN +
+		PN533_FRAME_TAIL_SIZE;
+
+	skb_resp = nfc_alloc_recv_skb(skb_resp_len, GFP_KERNEL);
+	if (!skb_resp)
+		return;
+
+	in_frame = (struct pn533_frame *)skb_resp->data;
+
+	pn533_tx_frame_init(dev->out_frame, PN533_CMD_TG_GET_DATA);
+	pn533_tx_frame_finish(dev->out_frame);
+
+	pn533_send_cmd_frame_async(dev, dev->out_frame, in_frame,
+				   skb_resp_len,
+				   pn533_tm_get_data_complete,
+				   skb_resp, GFP_KERNEL);
+
+	return;
+}
+
 #define ATR_REQ_GB_OFFSET 17
 static int pn533_init_target_complete(struct pn533 *dev, void *arg,
 				      u8 *params, int params_len)
@@ -1139,6 +1206,7 @@ static int pn533_init_target_complete(struct pn533 *dev, void *arg,
 	struct pn533_cmd_init_target_response *resp;
 	u8 frame, comm_mode = NFC_COMM_PASSIVE, *gb;
 	size_t gb_len;
+	int rc;
 
 	nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
 
@@ -1169,8 +1237,17 @@ static int pn533_init_target_complete(struct pn533 *dev, void *arg,
 	gb = resp->cmd + ATR_REQ_GB_OFFSET;
 	gb_len = params_len - (ATR_REQ_GB_OFFSET + 1);
 
-	return nfc_tm_activated(dev->nfc_dev, NFC_PROTO_NFC_DEP_MASK,
-				comm_mode, gb, gb_len);
+	rc = nfc_tm_activated(dev->nfc_dev, NFC_PROTO_NFC_DEP_MASK,
+			      comm_mode, gb, gb_len);
+	if (rc < 0) {
+		nfc_dev_err(&dev->interface->dev,
+			    "Error when signaling target activation");
+		return rc;
+	}
+
+	queue_work(dev->wq, &dev->tg_work);
+
+	return 0;
 }
 
 static int pn533_init_target(struct nfc_dev *nfc_dev, u32 protocols)
@@ -1553,9 +1630,6 @@ static int pn533_dep_link_down(struct nfc_dev *nfc_dev)
 	return 0;
 }
 
-#define PN533_CMD_DATAEXCH_HEAD_LEN (sizeof(struct pn533_frame) + 3)
-#define PN533_CMD_DATAEXCH_DATA_MAXLEN 262
-
 static int pn533_data_exchange_tx_frame(struct pn533 *dev, struct sk_buff *skb)
 {
 	int payload_len = skb->len;
@@ -1920,6 +1994,7 @@ static int pn533_probe(struct usb_interface *interface,
 
 	INIT_WORK(&dev->cmd_work, pn533_wq_cmd_complete);
 	INIT_WORK(&dev->mi_work, pn533_wq_mi_recv);
+	INIT_WORK(&dev->tg_work, pn533_wq_tg_get_data);
 	dev->wq = alloc_workqueue("pn533",
 				  WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM,
 				  1);
-- 
1.7.9.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 14/29] NFC: Implement the pn533 target mode Tx op
  2012-06-06 10:16 [PATCH 00/29] NFC updates for 3.6 Samuel Ortiz
                   ` (12 preceding siblings ...)
  2012-06-06 10:16 ` [PATCH 13/29] NFC: Implement the pn533 target mode data fetching routine Samuel Ortiz
@ 2012-06-06 10:16 ` Samuel Ortiz
  2012-06-06 10:16 ` [PATCH 15/29] NFC: Don't hold a NULL connecting LLCP socket lock Samuel Ortiz
                   ` (14 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Samuel Ortiz @ 2012-06-06 10:16 UTC (permalink / raw)
  To: John W. Linville
  Cc: Lauro Ramos Venancio, Aloisio Almeida Jr, Ilan Elias,
	linux-wireless, linux-nfc, Samuel Ortiz

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 drivers/nfc/pn533.c |   82 +++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 73 insertions(+), 9 deletions(-)

diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index 6a506e2..db40787 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -76,6 +76,7 @@ MODULE_DEVICE_TABLE(usb, pn533_table);
 
 #define PN533_CMD_TG_INIT_AS_TARGET 0x8c
 #define PN533_CMD_TG_GET_DATA 0x86
+#define PN533_CMD_TG_SET_DATA 0x8e
 
 #define PN533_CMD_RESPONSE(cmd) (cmd + 1)
 
@@ -1630,7 +1631,8 @@ static int pn533_dep_link_down(struct nfc_dev *nfc_dev)
 	return 0;
 }
 
-static int pn533_data_exchange_tx_frame(struct pn533 *dev, struct sk_buff *skb)
+static int pn533_build_tx_frame(struct pn533 *dev, struct sk_buff *skb,
+				bool target)
 {
 	int payload_len = skb->len;
 	struct pn533_frame *out_frame;
@@ -1647,14 +1649,20 @@ static int pn533_data_exchange_tx_frame(struct pn533 *dev, struct sk_buff *skb)
 		return -ENOSYS;
 	}
 
-	skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN);
-	out_frame = (struct pn533_frame *) skb->data;
+	if (target == true) {
+		skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN);
+		out_frame = (struct pn533_frame *) skb->data;
 
-	pn533_tx_frame_init(out_frame, PN533_CMD_IN_DATA_EXCHANGE);
+		pn533_tx_frame_init(out_frame, PN533_CMD_IN_DATA_EXCHANGE);
+		tg = 1;
+		memcpy(PN533_FRAME_CMD_PARAMS_PTR(out_frame), &tg, sizeof(u8));
+		out_frame->datalen += sizeof(u8);
+	} else {
+		skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN - 1);
+		out_frame = (struct pn533_frame *) skb->data;
+		pn533_tx_frame_init(out_frame, PN533_CMD_TG_SET_DATA);
+	}
 
-	tg = 1;
-	memcpy(PN533_FRAME_CMD_PARAMS_PTR(out_frame), &tg, sizeof(u8));
-	out_frame->datalen += sizeof(u8);
 
 	/* The data is already in the out_frame, just update the datalen */
 	out_frame->datalen += payload_len;
@@ -1785,7 +1793,7 @@ static int pn533_transceive(struct nfc_dev *nfc_dev,
 		goto error;
 	}
 
-	rc = pn533_data_exchange_tx_frame(dev, skb);
+	rc = pn533_build_tx_frame(dev, skb, true);
 	if (rc)
 		goto error;
 
@@ -1833,6 +1841,61 @@ error:
 	return rc;
 }
 
+static int pn533_tm_send_complete(struct pn533 *dev, void *arg,
+				  u8 *params, int params_len)
+{
+	nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+
+	if (params_len < 0) {
+		nfc_dev_err(&dev->interface->dev,
+			    "Error %d when sending data",
+			    params_len);
+
+		return params_len;
+	}
+
+	if (params_len > 0 && params[0] != 0) {
+		nfc_tm_deactivated(dev->nfc_dev);
+
+		return 0;
+	}
+
+	queue_work(dev->wq, &dev->tg_work);
+
+	return 0;
+}
+
+static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb)
+{
+	struct pn533 *dev = nfc_get_drvdata(nfc_dev);
+	struct pn533_frame *out_frame;
+	int rc;
+
+	nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
+
+	rc = pn533_build_tx_frame(dev, skb, false);
+	if (rc)
+		goto error;
+
+	out_frame = (struct pn533_frame *) skb->data;
+
+	rc = pn533_send_cmd_frame_async(dev, out_frame, dev->in_frame,
+					dev->in_maxlen, pn533_tm_send_complete,
+					NULL, GFP_KERNEL);
+	if (rc) {
+		nfc_dev_err(&dev->interface->dev,
+			    "Error %d when trying to send data", rc);
+		goto error;
+	}
+
+	return 0;
+
+error:
+	kfree_skb(skb);
+
+	return rc;
+}
+
 static void pn533_wq_mi_recv(struct work_struct *work)
 {
 	struct pn533 *dev = container_of(work, struct pn533, mi_work);
@@ -1853,7 +1916,7 @@ static void pn533_wq_mi_recv(struct work_struct *work)
 
 	skb_reserve(skb_cmd, PN533_CMD_DATAEXCH_HEAD_LEN);
 
-	rc = pn533_data_exchange_tx_frame(dev, skb_cmd);
+	rc = pn533_build_tx_frame(dev, skb_cmd, true);
 	if (rc)
 		goto error_frame;
 
@@ -1928,6 +1991,7 @@ struct nfc_ops pn533_nfc_ops = {
 	.activate_target = pn533_activate_target,
 	.deactivate_target = pn533_deactivate_target,
 	.im_transceive = pn533_transceive,
+	.tm_send = pn533_tm_send,
 };
 
 static int pn533_probe(struct usb_interface *interface,
-- 
1.7.9.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 15/29] NFC: Don't hold a NULL connecting LLCP socket lock
  2012-06-06 10:16 [PATCH 00/29] NFC updates for 3.6 Samuel Ortiz
                   ` (13 preceding siblings ...)
  2012-06-06 10:16 ` [PATCH 14/29] NFC: Implement the pn533 target mode Tx op Samuel Ortiz
@ 2012-06-06 10:16 ` Samuel Ortiz
  2012-06-06 10:16 ` [PATCH 16/29] NFC: Call the DEP link down ops even when in target mode Samuel Ortiz
                   ` (13 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Samuel Ortiz @ 2012-06-06 10:16 UTC (permalink / raw)
  To: John W. Linville
  Cc: Lauro Ramos Venancio, Aloisio Almeida Jr, Ilan Elias,
	linux-wireless, linux-nfc, Samuel Ortiz

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 net/nfc/llcp/llcp.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c
index 5705e6d..b694313 100644
--- a/net/nfc/llcp/llcp.c
+++ b/net/nfc/llcp/llcp.c
@@ -477,8 +477,10 @@ static struct nfc_llcp_sock *nfc_llcp_connecting_sock_get(struct nfc_llcp_local
 	sk_for_each(sk, node, &local->connecting_sockets.head) {
 		llcp_sock = nfc_llcp_sock(sk);
 
-		if (llcp_sock->ssap == ssap)
+		if (llcp_sock->ssap == ssap) {
+			sock_hold(&llcp_sock->sk);
 			goto out;
+		}
 	}
 
 	llcp_sock = NULL;
@@ -486,8 +488,6 @@ static struct nfc_llcp_sock *nfc_llcp_connecting_sock_get(struct nfc_llcp_local
 out:
 	read_unlock(&local->connecting_sockets.lock);
 
-	sock_hold(&llcp_sock->sk);
-
 	return llcp_sock;
 }
 
-- 
1.7.9.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 16/29] NFC: Call the DEP link down ops even when in target mode
  2012-06-06 10:16 [PATCH 00/29] NFC updates for 3.6 Samuel Ortiz
                   ` (14 preceding siblings ...)
  2012-06-06 10:16 ` [PATCH 15/29] NFC: Don't hold a NULL connecting LLCP socket lock Samuel Ortiz
@ 2012-06-06 10:16 ` Samuel Ortiz
  2012-06-06 10:16 ` [PATCH 17/29] NFC: Reset poll mod list when stopping pn533 poll Samuel Ortiz
                   ` (12 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Samuel Ortiz @ 2012-06-06 10:16 UTC (permalink / raw)
  To: John W. Linville
  Cc: Lauro Ramos Venancio, Aloisio Almeida Jr, Ilan Elias,
	linux-wireless, linux-nfc, Samuel Ortiz

Even in target mode we need to let the driver know that we want to
bring the DEP link down.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 net/nfc/core.c |    5 -----
 1 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/net/nfc/core.c b/net/nfc/core.c
index 6a3799e..4177bb5 100644
--- a/net/nfc/core.c
+++ b/net/nfc/core.c
@@ -268,11 +268,6 @@ int nfc_dep_link_down(struct nfc_dev *dev)
 		goto error;
 	}
 
-	if (dev->rf_mode == NFC_RF_TARGET) {
-		rc = -EOPNOTSUPP;
-		goto error;
-	}
-
 	rc = dev->ops->dep_link_down(dev);
 	if (!rc) {
 		dev->dep_link_up = false;
-- 
1.7.9.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 17/29] NFC: Reset poll mod list when stopping pn533 poll
  2012-06-06 10:16 [PATCH 00/29] NFC updates for 3.6 Samuel Ortiz
                   ` (15 preceding siblings ...)
  2012-06-06 10:16 ` [PATCH 16/29] NFC: Call the DEP link down ops even when in target mode Samuel Ortiz
@ 2012-06-06 10:16 ` Samuel Ortiz
  2012-06-06 10:16 ` [PATCH 18/29] NFC: Unregister device if pn533 initial configuration fails Samuel Ortiz
                   ` (11 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Samuel Ortiz @ 2012-06-06 10:16 UTC (permalink / raw)
  To: John W. Linville
  Cc: Lauro Ramos Venancio, Aloisio Almeida Jr, Ilan Elias,
	linux-wireless, linux-nfc, Samuel Ortiz

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 drivers/nfc/pn533.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index db40787..6b8a65c 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -1371,6 +1371,8 @@ static void pn533_stop_poll(struct nfc_dev *nfc_dev)
 
 	/* prevent pn533_start_poll_complete to issue a new poll meanwhile */
 	usb_kill_urb(dev->in_urb);
+
+	pn533_poll_reset_mod_list(dev);
 }
 
 static int pn533_activate_target_nfcdep(struct pn533 *dev)
-- 
1.7.9.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 18/29] NFC: Unregister device if pn533 initial configuration fails
  2012-06-06 10:16 [PATCH 00/29] NFC updates for 3.6 Samuel Ortiz
                   ` (16 preceding siblings ...)
  2012-06-06 10:16 ` [PATCH 17/29] NFC: Reset poll mod list when stopping pn533 poll Samuel Ortiz
@ 2012-06-06 10:16 ` Samuel Ortiz
  2012-06-06 10:16 ` [PATCH 19/29] NFC: Configure pn533 RF timings Samuel Ortiz
                   ` (10 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Samuel Ortiz @ 2012-06-06 10:16 UTC (permalink / raw)
  To: John W. Linville
  Cc: Lauro Ramos Venancio, Aloisio Almeida Jr, Ilan Elias,
	linux-wireless, linux-nfc, Samuel Ortiz

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 drivers/nfc/pn533.c |    6 +++++-
 1 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index 6b8a65c..2a7e4e8 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -2112,13 +2112,17 @@ static int pn533_probe(struct usb_interface *interface,
 	if (rc) {
 		nfc_dev_err(&dev->interface->dev, "Error on setting MAX_RETRIES"
 								" config");
-		goto free_nfc_dev;
+		goto unregister_nfc_dev;
 	}
 
 	return 0;
 
+unregister_nfc_dev:
+	nfc_unregister_device(dev->nfc_dev);
+
 free_nfc_dev:
 	nfc_free_device(dev->nfc_dev);
+
 destroy_wq:
 	destroy_workqueue(dev->wq);
 error:
-- 
1.7.9.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 19/29] NFC: Configure pn533 RF timings
  2012-06-06 10:16 [PATCH 00/29] NFC updates for 3.6 Samuel Ortiz
                   ` (17 preceding siblings ...)
  2012-06-06 10:16 ` [PATCH 18/29] NFC: Unregister device if pn533 initial configuration fails Samuel Ortiz
@ 2012-06-06 10:16 ` Samuel Ortiz
  2012-06-06 10:16 ` [PATCH 20/29] NFC: Add passive initiator data for pn533 Samuel Ortiz
                   ` (9 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Samuel Ortiz @ 2012-06-06 10:16 UTC (permalink / raw)
  To: John W. Linville
  Cc: Lauro Ramos Venancio, Aloisio Almeida Jr, Ilan Elias,
	linux-wireless, linux-nfc, Samuel Ortiz

Those define the ATR_RES response timeout after which the pn533 considers the
target to be mute.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 drivers/nfc/pn533.c |   25 +++++++++++++++++++++++++
 1 files changed, 25 insertions(+), 0 deletions(-)

diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index 2a7e4e8..d976344 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -104,8 +104,14 @@ struct pn533_fw_version {
 };
 
 /* PN533_CMD_RF_CONFIGURATION */
+#define PN533_CFGITEM_TIMING 0x02
 #define PN533_CFGITEM_MAX_RETRIES 0x05
 
+#define PN533_CONFIG_TIMING_102 0xb
+#define PN533_CONFIG_TIMING_204 0xc
+#define PN533_CONFIG_TIMING_409 0xd
+#define PN533_CONFIG_TIMING_819 0xe
+
 #define PN533_CONFIG_MAX_RETRIES_NO_RETRY 0x00
 #define PN533_CONFIG_MAX_RETRIES_ENDLESS 0xFF
 
@@ -115,6 +121,12 @@ struct pn533_config_max_retries {
 	u8 mx_rty_passive_act;
 } __packed;
 
+struct pn533_config_timing {
+	u8 rfu;
+	u8 atr_res_timeout;
+	u8 dep_timeout;
+} __packed;
+
 /* PN533_CMD_IN_LIST_PASSIVE_TARGET */
 
 /* felica commands opcode */
@@ -2004,6 +2016,7 @@ static int pn533_probe(struct usb_interface *interface,
 	struct usb_host_interface *iface_desc;
 	struct usb_endpoint_descriptor *endpoint;
 	struct pn533_config_max_retries max_retries;
+	struct pn533_config_timing timing;
 	int in_endpoint = 0;
 	int out_endpoint = 0;
 	int rc = -ENOMEM;
@@ -2115,6 +2128,18 @@ static int pn533_probe(struct usb_interface *interface,
 		goto unregister_nfc_dev;
 	}
 
+	timing.rfu = PN533_CONFIG_TIMING_102;
+	timing.atr_res_timeout = PN533_CONFIG_TIMING_204;
+	timing.dep_timeout = PN533_CONFIG_TIMING_409;
+
+	rc = pn533_set_configuration(dev, PN533_CFGITEM_TIMING,
+				(u8 *) &timing, sizeof(timing));
+	if (rc) {
+		nfc_dev_err(&dev->interface->dev,
+			    "Error on setting RF timings");
+		goto unregister_nfc_dev;
+	}
+
 	return 0;
 
 unregister_nfc_dev:
-- 
1.7.9.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 20/29] NFC: Add passive initiator data for pn533
  2012-06-06 10:16 [PATCH 00/29] NFC updates for 3.6 Samuel Ortiz
                   ` (18 preceding siblings ...)
  2012-06-06 10:16 ` [PATCH 19/29] NFC: Configure pn533 RF timings Samuel Ortiz
@ 2012-06-06 10:16 ` Samuel Ortiz
  2012-06-06 10:16 ` [PATCH 21/29] NFC: Add type A and type F parameters for pn533 target mode Samuel Ortiz
                   ` (8 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Samuel Ortiz @ 2012-06-06 10:16 UTC (permalink / raw)
  To: John W. Linville
  Cc: Lauro Ramos Venancio, Aloisio Almeida Jr, Ilan Elias,
	linux-wireless, linux-nfc, Samuel Ortiz

When trying to enable a DEP link as a passive initiator, pn533 needs to
provide the polling request command payload.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 drivers/nfc/pn533.c |   23 ++++++++++++++++++-----
 1 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index d976344..806ab3d 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -256,7 +256,7 @@ struct pn533_cmd_jump_dep {
 	u8 active;
 	u8 baud;
 	u8 next;
-	u8 gt[];
+	u8 data[];
 } __packed;
 
 struct pn533_cmd_jump_dep_response {
@@ -1582,12 +1582,14 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg,
 	return 0;
 }
 
+#define PASSIVE_DATA_LEN 5
 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);
 	struct pn533_cmd_jump_dep *cmd;
-	u8 cmd_len;
+	u8 cmd_len, *data_ptr;
+	u8 passive_data[PASSIVE_DATA_LEN] = {0x00, 0xff, 0xff, 0x00, 0x3};
 	int rc;
 
 	nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
@@ -1605,6 +1607,9 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target,
 	}
 
 	cmd_len = sizeof(struct pn533_cmd_jump_dep) + gb_len;
+	if (comm_mode == NFC_COMM_PASSIVE)
+		cmd_len += PASSIVE_DATA_LEN;
+
 	cmd = kzalloc(cmd_len, GFP_KERNEL);
 	if (cmd == NULL)
 		return -ENOMEM;
@@ -1612,10 +1617,18 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target,
 	pn533_tx_frame_init(dev->out_frame, PN533_CMD_IN_JUMP_FOR_DEP);
 
 	cmd->active = !comm_mode;
-	cmd->baud = 0;
+	cmd->next = 0;
+	cmd->baud = 2;
+	data_ptr = cmd->data;
+	if (comm_mode == NFC_COMM_PASSIVE && cmd->baud > 0) {
+		memcpy(data_ptr, passive_data, PASSIVE_DATA_LEN);
+		cmd->next |= 1;
+		data_ptr += PASSIVE_DATA_LEN;
+	}
+
 	if (gb != NULL && gb_len > 0) {
-		cmd->next = 4; /* We have some Gi */
-		memcpy(cmd->gt, gb, gb_len);
+		cmd->next |= 4; /* We have some Gi */
+		memcpy(data_ptr, gb, gb_len);
 	} else {
 		cmd->next = 0;
 	}
-- 
1.7.9.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 21/29] NFC: Add type A and type F parameters for pn533 target mode
  2012-06-06 10:16 [PATCH 00/29] NFC updates for 3.6 Samuel Ortiz
                   ` (19 preceding siblings ...)
  2012-06-06 10:16 ` [PATCH 20/29] NFC: Add passive initiator data for pn533 Samuel Ortiz
@ 2012-06-06 10:16 ` Samuel Ortiz
  2012-06-06 10:16 ` [PATCH 22/29] NFC: Implement pn533 polling loop Samuel Ortiz
                   ` (7 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Samuel Ortiz @ 2012-06-06 10:16 UTC (permalink / raw)
  To: John W. Linville
  Cc: Lauro Ramos Venancio, Aloisio Almeida Jr, Ilan Elias,
	linux-wireless, linux-nfc, Samuel Ortiz

Without those settings several devices will not activate pn533 as a target.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 drivers/nfc/pn533.c |   25 ++++++++++++++++++++++++-
 1 files changed, 24 insertions(+), 1 deletions(-)

diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index 806ab3d..6e4b228 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -1126,6 +1126,13 @@ static int pn533_init_target_frame(struct pn533_frame *frame,
 {
 	struct pn533_cmd_init_target *cmd;
 	size_t cmd_len;
+	u8 felica_params[18] = {0x1, 0xfe, /* DEP */
+				0x0, 0x0, 0x0, 0x0, 0x0, 0x0, /* random */
+				0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+				0xff, 0xff}; /* System code */
+	u8 mifare_params[6] = {0x1, 0x1, /* SENS_RES */
+			       0x0, 0x0, 0x0,
+			       0x40}; /* SEL_RES for DEP */
 
 	cmd_len = sizeof(struct pn533_cmd_init_target) + gb_len + 1;
 	cmd = kzalloc(cmd_len, GFP_KERNEL);
@@ -1136,17 +1143,33 @@ static int pn533_init_target_frame(struct pn533_frame *frame,
 
 	/* DEP support only */
 	cmd->mode |= PN533_INIT_TARGET_DEP;
-	get_random_bytes(cmd->nfcid3, 10);
+
+	/* Felica params */
+	memcpy(cmd->felica, felica_params, 18);
+	get_random_bytes(cmd->felica + 2, 6);
+
+	/* NFCID3 */
+	memset(cmd->nfcid3, 0, 10);
+	memcpy(cmd->nfcid3, cmd->felica, 8);
+
+	/* MIFARE params */
+	memcpy(cmd->mifare, mifare_params, 6);
+
+	/* General bytes */
 	cmd->gb_len = gb_len;
 	memcpy(cmd->gb, gb, gb_len);
+
 	/* Len Tk */
 	cmd->gb[gb_len] = 0;
 
 	memcpy(PN533_FRAME_CMD_PARAMS_PTR(frame), cmd, cmd_len);
+
 	frame->datalen += cmd_len;
 
 	pn533_tx_frame_finish(frame);
 
+	kfree(cmd);
+
 	return 0;
 }
 
-- 
1.7.9.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 22/29] NFC: Implement pn533 polling loop
  2012-06-06 10:16 [PATCH 00/29] NFC updates for 3.6 Samuel Ortiz
                   ` (20 preceding siblings ...)
  2012-06-06 10:16 ` [PATCH 21/29] NFC: Add type A and type F parameters for pn533 target mode Samuel Ortiz
@ 2012-06-06 10:16 ` Samuel Ortiz
  2012-06-06 10:16 ` [PATCH 23/29] NFC: Requeue lost LLCP frames Samuel Ortiz
                   ` (6 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Samuel Ortiz @ 2012-06-06 10:16 UTC (permalink / raw)
  To: John W. Linville
  Cc: Lauro Ramos Venancio, Aloisio Almeida Jr, Ilan Elias,
	linux-wireless, linux-nfc, Samuel Ortiz

After going through all the modulations, the pn533 driver spends 2
seconds listening for targets.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 drivers/nfc/pn533.c |  287 ++++++++++++++++++++++++++++----------------------
 1 files changed, 161 insertions(+), 126 deletions(-)

diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index 6e4b228..c9ba96c 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -45,6 +45,9 @@ static const struct usb_device_id pn533_table[] = {
 };
 MODULE_DEVICE_TABLE(usb, pn533_table);
 
+/* How much time we spend listening for initiators */
+#define PN533_LISTEN_TIME 2
+
 /* frame definitions */
 #define PN533_FRAME_TAIL_SIZE 2
 #define PN533_FRAME_SIZE(f) (sizeof(struct pn533_frame) + f->datalen + \
@@ -163,6 +166,7 @@ enum {
 	PN533_POLL_MOD_424KBPS_FELICA,
 	PN533_POLL_MOD_106KBPS_JEWEL,
 	PN533_POLL_MOD_847KBPS_B,
+	PN533_LISTEN_MOD,
 
 	__PN533_POLL_MOD_AFTER_LAST,
 };
@@ -230,6 +234,9 @@ const struct pn533_poll_modulations poll_mod[] = {
 		},
 		.len = 3,
 	},
+	[PN533_LISTEN_MOD] = {
+		.len = 0,
+	},
 };
 
 /* PN533_CMD_IN_ATR */
@@ -312,10 +319,13 @@ struct pn533 {
 
 	struct workqueue_struct	*wq;
 	struct work_struct cmd_work;
+	struct work_struct poll_work;
 	struct work_struct mi_work;
 	struct work_struct tg_work;
+	struct timer_list listen_timer;
 	struct pn533_frame *wq_in_frame;
 	int wq_in_error;
+	int cancel_listen;
 
 	pn533_cmd_complete_t cmd_complete;
 	void *cmd_complete_arg;
@@ -326,6 +336,10 @@ struct pn533 {
 	u8 poll_mod_count;
 	u8 poll_mod_curr;
 	u32 poll_protocols;
+	u32 listen_protocols;
+
+	u8 *gb;
+	size_t gb_len;
 
 	u8 tgt_available_prots;
 	u8 tgt_active_prot;
@@ -1006,6 +1020,11 @@ static int pn533_target_found(struct pn533 *dev,
 	return 0;
 }
 
+static inline void pn533_poll_next_mod(struct pn533 *dev)
+{
+	dev->poll_mod_curr = (dev->poll_mod_curr + 1) % dev->poll_mod_count;
+}
+
 static void pn533_poll_reset_mod_list(struct pn533 *dev)
 {
 	dev->poll_mod_count = 0;
@@ -1018,107 +1037,52 @@ static void pn533_poll_add_mod(struct pn533 *dev, u8 mod_index)
 	dev->poll_mod_count++;
 }
 
-static void pn533_poll_create_mod_list(struct pn533 *dev, u32 protocols)
+static void pn533_poll_create_mod_list(struct pn533 *dev,
+				       u32 im_protocols, u32 tm_protocols)
 {
 	pn533_poll_reset_mod_list(dev);
 
-	if (protocols & NFC_PROTO_MIFARE_MASK
-					|| protocols & NFC_PROTO_ISO14443_MASK
-					|| protocols & NFC_PROTO_NFC_DEP_MASK)
+	if (im_protocols & NFC_PROTO_MIFARE_MASK
+	    || im_protocols & NFC_PROTO_ISO14443_MASK
+	    || im_protocols & NFC_PROTO_NFC_DEP_MASK)
 		pn533_poll_add_mod(dev, PN533_POLL_MOD_106KBPS_A);
 
-	if (protocols & NFC_PROTO_FELICA_MASK
-					|| protocols & NFC_PROTO_NFC_DEP_MASK) {
+	if (im_protocols & NFC_PROTO_FELICA_MASK
+	    || im_protocols & NFC_PROTO_NFC_DEP_MASK) {
 		pn533_poll_add_mod(dev, PN533_POLL_MOD_212KBPS_FELICA);
 		pn533_poll_add_mod(dev, PN533_POLL_MOD_424KBPS_FELICA);
 	}
 
-	if (protocols & NFC_PROTO_JEWEL_MASK)
+	if (im_protocols & NFC_PROTO_JEWEL_MASK)
 		pn533_poll_add_mod(dev, PN533_POLL_MOD_106KBPS_JEWEL);
 
-	if (protocols & NFC_PROTO_ISO14443_MASK)
+	if (im_protocols & NFC_PROTO_ISO14443_MASK)
 		pn533_poll_add_mod(dev, PN533_POLL_MOD_847KBPS_B);
-}
-
-static void pn533_start_poll_frame(struct pn533_frame *frame,
-					struct pn533_poll_modulations *mod)
-{
-
-	pn533_tx_frame_init(frame, PN533_CMD_IN_LIST_PASSIVE_TARGET);
 
-	memcpy(PN533_FRAME_CMD_PARAMS_PTR(frame), &mod->data, mod->len);
-	frame->datalen += mod->len;
-
-	pn533_tx_frame_finish(frame);
+	if (tm_protocols)
+		pn533_poll_add_mod(dev, PN533_LISTEN_MOD);
 }
 
 static int pn533_start_poll_complete(struct pn533 *dev, void *arg,
-						u8 *params, int params_len)
+				     u8 *params, int params_len)
 {
 	struct pn533_poll_response *resp;
-	struct pn533_poll_modulations *next_mod;
 	int rc;
 
 	nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
 
-	if (params_len == -ENOENT) {
-		nfc_dev_dbg(&dev->interface->dev, "Polling operation has been"
-								" stopped");
-		goto stop_poll;
-	}
-
-	if (params_len < 0) {
-		nfc_dev_err(&dev->interface->dev, "Error %d when running poll",
-								params_len);
-		goto stop_poll;
-	}
-
 	resp = (struct pn533_poll_response *) params;
 	if (resp->nbtg) {
 		rc = pn533_target_found(dev, resp, params_len);
 
 		/* We must stop the poll after a valid target found */
-		if (rc == 0)
-			goto stop_poll;
-
-		if (rc != -EAGAIN)
-			nfc_dev_err(&dev->interface->dev, "The target found is"
-					" not valid - continuing to poll");
-	}
-
-	dev->poll_mod_curr = (dev->poll_mod_curr + 1) % dev->poll_mod_count;
-
-	next_mod = dev->poll_mod_active[dev->poll_mod_curr];
-
-	nfc_dev_dbg(&dev->interface->dev, "Polling next modulation (0x%x)",
-							dev->poll_mod_curr);
-
-	pn533_start_poll_frame(dev->out_frame, next_mod);
-
-	/* Don't need to down the semaphore again */
-	rc = __pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame,
-				dev->in_maxlen, pn533_start_poll_complete,
-				NULL, GFP_ATOMIC);
-
-	if (rc == -EPERM) {
-		nfc_dev_dbg(&dev->interface->dev, "Cannot poll next modulation"
-					" because poll has been stopped");
-		goto stop_poll;
-	}
-
-	if (rc) {
-		nfc_dev_err(&dev->interface->dev, "Error %d when trying to poll"
-							" next modulation", rc);
-		goto stop_poll;
+		if (rc == 0) {
+			pn533_poll_reset_mod_list(dev);
+			return 0;
+		}
 	}
 
-	/* Inform caller function to do not up the semaphore */
-	return -EINPROGRESS;
-
-stop_poll:
-	pn533_poll_reset_mod_list(dev);
-	dev->poll_protocols = 0;
-	return 0;
+	return -EAGAIN;
 }
 
 static int pn533_init_target_frame(struct pn533_frame *frame,
@@ -1286,83 +1250,136 @@ static int pn533_init_target_complete(struct pn533 *dev, void *arg,
 	return 0;
 }
 
-static int pn533_init_target(struct nfc_dev *nfc_dev, u32 protocols)
+static void pn533_listen_mode_timer(unsigned long data)
 {
-	struct pn533 *dev = nfc_get_drvdata(nfc_dev);
-	u8 *gb;
-	size_t gb_len;
+	struct pn533 *dev = (struct pn533 *) data;
+
+	nfc_dev_dbg(&dev->interface->dev, "Listen mode timeout");
+
+	/* An ack will cancel the last issued command (poll) */
+	pn533_send_ack(dev, GFP_ATOMIC);
+
+	dev->cancel_listen = 1;
+
+	up(&dev->cmd_lock);
+
+	pn533_poll_next_mod(dev);
+
+	queue_work(dev->wq, &dev->poll_work);
+}
+
+static int pn533_poll_complete(struct pn533 *dev, void *arg,
+			       u8 *params, int params_len)
+{
+	struct pn533_poll_modulations *cur_mod;
 	int rc;
 
-	pn533_poll_reset_mod_list(dev);
+	nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
 
-	gb = nfc_get_local_general_bytes(nfc_dev, &gb_len);
-	if (gb == NULL)
-		return -ENOMEM;
+	if (params_len == -ENOENT) {
+		if (dev->poll_mod_count != 0)
+			return 0;
 
-	rc = pn533_init_target_frame(dev->out_frame, gb, gb_len);
-	if (rc < 0)
-		return rc;
+		nfc_dev_err(&dev->interface->dev,
+			    "Polling operation has been stopped");
 
-	rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame,
-					dev->in_maxlen,
-					pn533_init_target_complete,
-					NULL, GFP_KERNEL);
+		goto stop_poll;
+	}
 
-	if (rc)
+	if (params_len < 0) {
 		nfc_dev_err(&dev->interface->dev,
-			    "Error %d when trying to initiate as a target", rc);
+			    "Error %d when running poll", params_len);
 
-	dev->poll_mod_count++;
+		goto stop_poll;
+	}
 
-	return rc;
+	cur_mod = dev->poll_mod_active[dev->poll_mod_curr];
+
+	if (cur_mod->len == 0) {
+		del_timer(&dev->listen_timer);
+
+		return pn533_init_target_complete(dev, arg, params, params_len);
+	} else {
+		rc = pn533_start_poll_complete(dev, arg, params, params_len);
+		if (!rc)
+			return rc;
+	}
+
+	pn533_poll_next_mod(dev);
+
+	queue_work(dev->wq, &dev->poll_work);
+
+	return 0;
+
+stop_poll:
+	pn533_poll_reset_mod_list(dev);
+	dev->poll_protocols = 0;
+	return 0;
 }
 
-static int pn533_start_im_poll(struct nfc_dev *nfc_dev, u32 protocols)
+static void pn533_build_poll_frame(struct pn533 *dev,
+				   struct pn533_frame *frame,
+				   struct pn533_poll_modulations *mod)
 {
-	struct pn533 *dev = nfc_get_drvdata(nfc_dev);
-	struct pn533_poll_modulations *start_mod;
-	int rc;
+	nfc_dev_dbg(&dev->interface->dev, "mod len %d\n", mod->len);
 
-	if (dev->poll_mod_count) {
-		nfc_dev_err(&dev->interface->dev, "Polling operation already"
-								" active");
-		return -EBUSY;
-	}
+	if (mod->len == 0) {
+		/* Listen mode */
+		pn533_init_target_frame(frame, dev->gb, dev->gb_len);
+	} else {
+		/* Polling mode */
+		pn533_tx_frame_init(frame, PN533_CMD_IN_LIST_PASSIVE_TARGET);
 
-	pn533_poll_create_mod_list(dev, protocols);
+		memcpy(PN533_FRAME_CMD_PARAMS_PTR(frame), &mod->data, mod->len);
+		frame->datalen += mod->len;
 
-	if (!dev->poll_mod_count) {
-		nfc_dev_err(&dev->interface->dev, "No valid protocols"
-								" specified");
-		rc = -EINVAL;
-		goto error;
+		pn533_tx_frame_finish(frame);
 	}
+}
 
-	nfc_dev_dbg(&dev->interface->dev, "It will poll %d modulations types",
-							dev->poll_mod_count);
+static int pn533_send_poll_frame(struct pn533 *dev)
+{
+	struct pn533_poll_modulations *cur_mod;
+	int rc;
 
-	dev->poll_mod_curr = 0;
-	start_mod = dev->poll_mod_active[dev->poll_mod_curr];
+	cur_mod = dev->poll_mod_active[dev->poll_mod_curr];
 
-	pn533_start_poll_frame(dev->out_frame, start_mod);
+	pn533_build_poll_frame(dev, dev->out_frame, cur_mod);
 
 	rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame,
-				dev->in_maxlen,	pn533_start_poll_complete,
+				dev->in_maxlen,	pn533_poll_complete,
 				NULL, GFP_KERNEL);
+	if (rc)
+		nfc_dev_err(&dev->interface->dev, "Polling loop error %d", rc);
 
-	if (rc) {
-		nfc_dev_err(&dev->interface->dev, "Error %d when trying to"
-							" start poll", rc);
-		goto error;
+	return rc;
+}
+
+static void pn533_wq_poll(struct work_struct *work)
+{
+	struct pn533 *dev = container_of(work, struct pn533, poll_work);
+	struct pn533_poll_modulations *cur_mod;
+	int rc;
+
+	cur_mod = dev->poll_mod_active[dev->poll_mod_curr];
+
+	nfc_dev_dbg(&dev->interface->dev,
+		    "%s cancel_listen %d modulation len %d",
+		    __func__, dev->cancel_listen, cur_mod->len);
+
+	if (dev->cancel_listen == 1) {
+		dev->cancel_listen = 0;
+		usb_kill_urb(dev->in_urb);
 	}
 
-	dev->poll_protocols = protocols;
+	rc = pn533_send_poll_frame(dev);
+	if (rc)
+		return;
 
-	return 0;
+	if (cur_mod->len == 0 && dev->poll_mod_count > 1)
+		mod_timer(&dev->listen_timer, jiffies + PN533_LISTEN_TIME * HZ);
 
-error:
-	pn533_poll_reset_mod_list(dev);
-	return rc;
+	return;
 }
 
 static int pn533_start_poll(struct nfc_dev *nfc_dev,
@@ -1380,13 +1397,18 @@ static int pn533_start_poll(struct nfc_dev *nfc_dev,
 		return -EBUSY;
 	}
 
-	if (im_protocols)
-		return pn533_start_im_poll(nfc_dev, im_protocols);
+	if (tm_protocols) {
+		dev->gb = nfc_get_local_general_bytes(nfc_dev, &dev->gb_len);
+		if (dev->gb == NULL)
+			tm_protocols = 0;
+	}
 
-	if (tm_protocols)
-		return pn533_init_target(nfc_dev, tm_protocols);
+	dev->poll_mod_curr = 0;
+	pn533_poll_create_mod_list(dev, im_protocols, tm_protocols);
+	dev->poll_protocols = im_protocols;
+	dev->listen_protocols = tm_protocols;
 
-	return -EINVAL;
+	return pn533_send_poll_frame(dev);
 }
 
 static void pn533_stop_poll(struct nfc_dev *nfc_dev)
@@ -1395,6 +1417,8 @@ static void pn533_stop_poll(struct nfc_dev *nfc_dev)
 
 	nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
 
+	del_timer(&dev->listen_timer);
+
 	if (!dev->poll_mod_count) {
 		nfc_dev_dbg(&dev->interface->dev, "Polling operation was not"
 								" running");
@@ -1676,6 +1700,10 @@ out:
 
 static int pn533_dep_link_down(struct nfc_dev *nfc_dev)
 {
+	struct pn533 *dev = nfc_get_drvdata(nfc_dev);
+
+	pn533_poll_reset_mod_list(dev);
+
 	pn533_deactivate_target(nfc_dev, 0);
 
 	return 0;
@@ -2110,12 +2138,17 @@ static int pn533_probe(struct usb_interface *interface,
 	INIT_WORK(&dev->cmd_work, pn533_wq_cmd_complete);
 	INIT_WORK(&dev->mi_work, pn533_wq_mi_recv);
 	INIT_WORK(&dev->tg_work, pn533_wq_tg_get_data);
+	INIT_WORK(&dev->poll_work, pn533_wq_poll);
 	dev->wq = alloc_workqueue("pn533",
 				  WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM,
 				  1);
 	if (dev->wq == NULL)
 		goto error;
 
+	init_timer(&dev->listen_timer);
+	dev->listen_timer.data = (unsigned long) dev;
+	dev->listen_timer.function = pn533_listen_mode_timer;
+
 	skb_queue_head_init(&dev->resp_q);
 
 	usb_set_intfdata(interface, dev);
@@ -2212,6 +2245,8 @@ static void pn533_disconnect(struct usb_interface *interface)
 
 	skb_queue_purge(&dev->resp_q);
 
+	del_timer(&dev->listen_timer);
+
 	kfree(dev->in_frame);
 	usb_free_urb(dev->in_urb);
 	kfree(dev->out_frame);
-- 
1.7.9.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 23/29] NFC: Requeue lost LLCP frames
  2012-06-06 10:16 [PATCH 00/29] NFC updates for 3.6 Samuel Ortiz
                   ` (21 preceding siblings ...)
  2012-06-06 10:16 ` [PATCH 22/29] NFC: Implement pn533 polling loop Samuel Ortiz
@ 2012-06-06 10:16 ` Samuel Ortiz
  2012-06-06 10:16 ` [PATCH 24/29] NFC: Send a receiver ready frame only to reply to an I frame Samuel Ortiz
                   ` (5 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Samuel Ortiz @ 2012-06-06 10:16 UTC (permalink / raw)
  To: John W. Linville
  Cc: Lauro Ramos Venancio, Aloisio Almeida Jr, Ilan Elias,
	linux-wireless, linux-nfc, Samuel Ortiz

When receiving an I or RR frame telling us that some of the pending queues
were not received, we should requeue them before the currently pending ones.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 net/nfc/llcp/llcp.c |   86 ++++++++++++++++++++++++++++++++------------------
 1 files changed, 55 insertions(+), 31 deletions(-)

diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c
index b694313..0fc60da 100644
--- a/net/nfc/llcp/llcp.c
+++ b/net/nfc/llcp/llcp.c
@@ -411,28 +411,6 @@ int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len)
 				     local->remote_gb_len - 3);
 }
 
-static void nfc_llcp_tx_work(struct work_struct *work)
-{
-	struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local,
-						    tx_work);
-	struct sk_buff *skb;
-
-	skb = skb_dequeue(&local->tx_queue);
-	if (skb != NULL) {
-		pr_debug("Sending pending skb\n");
-		print_hex_dump(KERN_DEBUG, "LLCP Tx: ", DUMP_PREFIX_OFFSET,
-			       16, 1, skb->data, skb->len, true);
-
-		nfc_data_exchange(local->dev, local->target_idx,
-				  skb, nfc_llcp_recv, local);
-	} else {
-		nfc_llcp_send_symm(local->dev);
-	}
-
-	mod_timer(&local->link_timer,
-		  jiffies + msecs_to_jiffies(local->remote_lto));
-}
-
 static u8 nfc_llcp_dsap(struct sk_buff *pdu)
 {
 	return (pdu->data[0] & 0xfc) >> 2;
@@ -465,6 +443,45 @@ static void nfc_llcp_set_nrns(struct nfc_llcp_sock *sock, struct sk_buff *pdu)
 	sock->recv_ack_n = (sock->recv_n - 1) % 16;
 }
 
+static void nfc_llcp_tx_work(struct work_struct *work)
+{
+	struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local,
+						    tx_work);
+	struct sk_buff *skb;
+	struct sock *sk;
+	struct nfc_llcp_sock *llcp_sock;
+
+	skb = skb_dequeue(&local->tx_queue);
+	if (skb != NULL) {
+		sk = skb->sk;
+		llcp_sock = nfc_llcp_sock(sk);
+		if (llcp_sock != NULL) {
+			int ret;
+
+			pr_debug("Sending pending skb\n");
+			print_hex_dump(KERN_DEBUG, "LLCP Tx: ",
+				       DUMP_PREFIX_OFFSET, 16, 1,
+				       skb->data, skb->len, true);
+
+			ret = nfc_data_exchange(local->dev, local->target_idx,
+						skb, nfc_llcp_recv, local);
+
+			if (!ret && nfc_llcp_ptype(skb) == LLCP_PDU_I) {
+				skb = skb_get(skb);
+				skb_queue_tail(&llcp_sock->tx_pending_queue,
+					       skb);
+			}
+		} else {
+			nfc_llcp_send_symm(local->dev);
+		}
+	} else {
+		nfc_llcp_send_symm(local->dev);
+	}
+
+	mod_timer(&local->link_timer,
+		  jiffies + msecs_to_jiffies(2 * local->remote_lto));
+}
+
 static struct nfc_llcp_sock *nfc_llcp_connecting_sock_get(struct nfc_llcp_local *local,
 							  u8 ssap)
 {
@@ -705,7 +722,7 @@ int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock)
 	/* Try to queue some I frames for transmission */
 	while (sock->remote_ready &&
 	       skb_queue_len(&sock->tx_pending_queue) < sock->rw) {
-		struct sk_buff *pdu, *pending_pdu;
+		struct sk_buff *pdu;
 
 		pdu = skb_dequeue(&sock->tx_queue);
 		if (pdu == NULL)
@@ -714,10 +731,7 @@ int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock)
 		/* Update N(S)/N(R) */
 		nfc_llcp_set_nrns(sock, pdu);
 
-		pending_pdu = skb_clone(pdu, GFP_KERNEL);
-
 		skb_queue_tail(&local->tx_queue, pdu);
-		skb_queue_tail(&sock->tx_pending_queue, pending_pdu);
 		nr_frames++;
 	}
 
@@ -774,11 +788,21 @@ static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local,
 
 		llcp_sock->send_ack_n = nr;
 
-		skb_queue_walk_safe(&llcp_sock->tx_pending_queue, s, tmp)
-			if (nfc_llcp_ns(s) <= nr) {
-				skb_unlink(s, &llcp_sock->tx_pending_queue);
-				kfree_skb(s);
-			}
+		/* Remove and free all skbs until ns == nr */
+		skb_queue_walk_safe(&llcp_sock->tx_pending_queue, s, tmp) {
+			skb_unlink(s, &llcp_sock->tx_pending_queue);
+			kfree_skb(s);
+
+			if (nfc_llcp_ns(s) == nr)
+				break;
+		}
+
+		/* Re-queue the remaining skbs for transmission */
+		skb_queue_reverse_walk_safe(&llcp_sock->tx_pending_queue,
+					    s, tmp) {
+			skb_unlink(s, &llcp_sock->tx_pending_queue);
+			skb_queue_head(&local->tx_queue, s);
+		}
 	}
 
 	if (ptype == LLCP_PDU_RR)
-- 
1.7.9.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 24/29] NFC: Send a receiver ready frame only to reply to an I frame
  2012-06-06 10:16 [PATCH 00/29] NFC updates for 3.6 Samuel Ortiz
                   ` (22 preceding siblings ...)
  2012-06-06 10:16 ` [PATCH 23/29] NFC: Requeue lost LLCP frames Samuel Ortiz
@ 2012-06-06 10:16 ` Samuel Ortiz
  2012-06-06 10:16 ` [PATCH 25/29] NFC: Switch to Initiator mode when getting NFC_ATTR_PROTOCOLS Samuel Ortiz
                   ` (4 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Samuel Ortiz @ 2012-06-06 10:16 UTC (permalink / raw)
  To: John W. Linville
  Cc: Lauro Ramos Venancio, Aloisio Almeida Jr, Ilan Elias,
	linux-wireless, linux-nfc, Samuel Ortiz

Sending an RR as a reply to another RR is fine but not quite logical.
We should send RRs only as a reply to I frames.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 net/nfc/llcp/llcp.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c
index 0fc60da..3fe68e1 100644
--- a/net/nfc/llcp/llcp.c
+++ b/net/nfc/llcp/llcp.c
@@ -810,7 +810,7 @@ static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local,
 	else if (ptype == LLCP_PDU_RNR)
 		llcp_sock->remote_ready = false;
 
-	if (nfc_llcp_queue_i_frames(llcp_sock) == 0)
+	if (nfc_llcp_queue_i_frames(llcp_sock) == 0 && ptype == LLCP_PDU_I)
 		nfc_llcp_send_rr(llcp_sock);
 
 	release_sock(sk);
-- 
1.7.9.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 25/29] NFC: Switch to Initiator mode when getting NFC_ATTR_PROTOCOLS
  2012-06-06 10:16 [PATCH 00/29] NFC updates for 3.6 Samuel Ortiz
                   ` (23 preceding siblings ...)
  2012-06-06 10:16 ` [PATCH 24/29] NFC: Send a receiver ready frame only to reply to an I frame Samuel Ortiz
@ 2012-06-06 10:16 ` Samuel Ortiz
  2012-06-06 10:16 ` [PATCH 26/29] NFC: Destroy LLCP timout workqueue when releasing the link Samuel Ortiz
                   ` (3 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Samuel Ortiz @ 2012-06-06 10:16 UTC (permalink / raw)
  To: John W. Linville
  Cc: Lauro Ramos Venancio, Aloisio Almeida Jr, Ilan Elias,
	linux-wireless, linux-nfc, Samuel Ortiz

That is needed for keeping backward compatibility with apps using the old
netlink polling API (NFC_ATTR_PROTOCOLS instead of NFC_ATTR_IM_PROTOCOLS).

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 net/nfc/netlink.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
index 21eaa9b..03c31db 100644
--- a/net/nfc/netlink.c
+++ b/net/nfc/netlink.c
@@ -597,11 +597,11 @@ static int nfc_genl_start_poll(struct sk_buff *skb, struct genl_info *info)
 
 	if (info->attrs[NFC_ATTR_TM_PROTOCOLS])
 		tm_protocols = nla_get_u32(info->attrs[NFC_ATTR_TM_PROTOCOLS]);
-	else if (info->attrs[NFC_ATTR_PROTOCOLS])
-		tm_protocols = nla_get_u32(info->attrs[NFC_ATTR_PROTOCOLS]);
 
 	if (info->attrs[NFC_ATTR_IM_PROTOCOLS])
 		im_protocols = nla_get_u32(info->attrs[NFC_ATTR_IM_PROTOCOLS]);
+	else if (info->attrs[NFC_ATTR_PROTOCOLS])
+		im_protocols = nla_get_u32(info->attrs[NFC_ATTR_PROTOCOLS]);
 
 	dev = nfc_get_device(idx);
 	if (!dev)
-- 
1.7.9.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 26/29] NFC: Destroy LLCP timout workqueue when releasing the link
  2012-06-06 10:16 [PATCH 00/29] NFC updates for 3.6 Samuel Ortiz
                   ` (24 preceding siblings ...)
  2012-06-06 10:16 ` [PATCH 25/29] NFC: Switch to Initiator mode when getting NFC_ATTR_PROTOCOLS Samuel Ortiz
@ 2012-06-06 10:16 ` Samuel Ortiz
  2012-06-06 10:16 ` [PATCH 27/29] NFC: Set the proper baud rate when trying to activate pn533 targets Samuel Ortiz
                   ` (2 subsequent siblings)
  28 siblings, 0 replies; 30+ messages in thread
From: Samuel Ortiz @ 2012-06-06 10:16 UTC (permalink / raw)
  To: John W. Linville
  Cc: Lauro Ramos Venancio, Aloisio Almeida Jr, Ilan Elias,
	linux-wireless, linux-nfc, Samuel Ortiz

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 net/nfc/llcp/llcp.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c
index 3fe68e1..5d503ee 100644
--- a/net/nfc/llcp/llcp.c
+++ b/net/nfc/llcp/llcp.c
@@ -111,6 +111,7 @@ static void local_release(struct kref *ref)
 	skb_queue_purge(&local->tx_queue);
 	destroy_workqueue(local->tx_wq);
 	destroy_workqueue(local->rx_wq);
+	destroy_workqueue(local->timeout_wq);
 	kfree_skb(local->rx_pending);
 	kfree(local);
 }
-- 
1.7.9.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 27/29] NFC: Set the proper baud rate when trying to activate pn533 targets
  2012-06-06 10:16 [PATCH 00/29] NFC updates for 3.6 Samuel Ortiz
                   ` (25 preceding siblings ...)
  2012-06-06 10:16 ` [PATCH 26/29] NFC: Destroy LLCP timout workqueue when releasing the link Samuel Ortiz
@ 2012-06-06 10:16 ` Samuel Ortiz
  2012-06-06 10:16 ` [PATCH 28/29] NFC: Convert pn533 from semaphore to mutex Samuel Ortiz
  2012-06-06 10:16 ` [PATCH 29/29] NFC: Monitor pn533 target mode Samuel Ortiz
  28 siblings, 0 replies; 30+ messages in thread
From: Samuel Ortiz @ 2012-06-06 10:16 UTC (permalink / raw)
  To: John W. Linville
  Cc: Lauro Ramos Venancio, Aloisio Almeida Jr, Ilan Elias,
	linux-wireless, linux-nfc, Samuel Ortiz

We get the right baud rate from the last polled modulation.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 drivers/nfc/pn533.c |   25 +++++++++++++++++++++++--
 1 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index c9ba96c..b97e3c8 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -1629,6 +1629,20 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg,
 	return 0;
 }
 
+static int pn533_mod_to_baud(struct pn533 *dev)
+{
+	switch (dev->poll_mod_curr) {
+	case PN533_POLL_MOD_106KBPS_A:
+		return 0;
+	case PN533_POLL_MOD_212KBPS_FELICA:
+		return 1;
+	case PN533_POLL_MOD_424KBPS_FELICA:
+		return 2;
+	default:
+		return -EINVAL;
+	}
+}
+
 #define PASSIVE_DATA_LEN 5
 static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target,
 			     u8 comm_mode, u8* gb, size_t gb_len)
@@ -1637,7 +1651,7 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target,
 	struct pn533_cmd_jump_dep *cmd;
 	u8 cmd_len, *data_ptr;
 	u8 passive_data[PASSIVE_DATA_LEN] = {0x00, 0xff, 0xff, 0x00, 0x3};
-	int rc;
+	int rc, baud;
 
 	nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
 
@@ -1653,6 +1667,13 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target,
 		return -EBUSY;
 	}
 
+	baud = pn533_mod_to_baud(dev);
+	if (baud < 0) {
+		nfc_dev_err(&dev->interface->dev,
+			    "Invalid curr modulation %d", dev->poll_mod_curr);
+		return baud;
+	}
+
 	cmd_len = sizeof(struct pn533_cmd_jump_dep) + gb_len;
 	if (comm_mode == NFC_COMM_PASSIVE)
 		cmd_len += PASSIVE_DATA_LEN;
@@ -1665,7 +1686,7 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target,
 
 	cmd->active = !comm_mode;
 	cmd->next = 0;
-	cmd->baud = 2;
+	cmd->baud = baud;
 	data_ptr = cmd->data;
 	if (comm_mode == NFC_COMM_PASSIVE && cmd->baud > 0) {
 		memcpy(data_ptr, passive_data, PASSIVE_DATA_LEN);
-- 
1.7.9.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 28/29] NFC: Convert pn533 from semaphore to mutex
  2012-06-06 10:16 [PATCH 00/29] NFC updates for 3.6 Samuel Ortiz
                   ` (26 preceding siblings ...)
  2012-06-06 10:16 ` [PATCH 27/29] NFC: Set the proper baud rate when trying to activate pn533 targets Samuel Ortiz
@ 2012-06-06 10:16 ` Samuel Ortiz
  2012-06-06 10:16 ` [PATCH 29/29] NFC: Monitor pn533 target mode Samuel Ortiz
  28 siblings, 0 replies; 30+ messages in thread
From: Samuel Ortiz @ 2012-06-06 10:16 UTC (permalink / raw)
  To: John W. Linville
  Cc: Lauro Ramos Venancio, Aloisio Almeida Jr, Ilan Elias,
	linux-wireless, linux-nfc, Samuel Ortiz

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 drivers/nfc/pn533.c |   14 +++++++-------
 1 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index b97e3c8..58c1641 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -329,7 +329,7 @@ struct pn533 {
 
 	pn533_cmd_complete_t cmd_complete;
 	void *cmd_complete_arg;
-	struct semaphore cmd_lock;
+	struct mutex cmd_lock;
 	u8 cmd;
 
 	struct pn533_poll_modulations *poll_mod_active[PN533_POLL_MOD_MAX + 1];
@@ -462,7 +462,7 @@ static void pn533_wq_cmd_complete(struct work_struct *work)
 					PN533_FRAME_CMD_PARAMS_LEN(in_frame));
 
 	if (rc != -EINPROGRESS)
-		up(&dev->cmd_lock);
+		mutex_unlock(&dev->cmd_lock);
 }
 
 static void pn533_recv_response(struct urb *urb)
@@ -640,7 +640,7 @@ static int pn533_send_cmd_frame_async(struct pn533 *dev,
 
 	nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
 
-	if (down_trylock(&dev->cmd_lock))
+	if (!mutex_trylock(&dev->cmd_lock))
 		return -EBUSY;
 
 	rc = __pn533_send_cmd_frame_async(dev, out_frame, in_frame,
@@ -650,7 +650,7 @@ static int pn533_send_cmd_frame_async(struct pn533 *dev,
 
 	return 0;
 error:
-	up(&dev->cmd_lock);
+	mutex_unlock(&dev->cmd_lock);
 	return rc;
 }
 
@@ -1261,7 +1261,7 @@ static void pn533_listen_mode_timer(unsigned long data)
 
 	dev->cancel_listen = 1;
 
-	up(&dev->cmd_lock);
+	mutex_unlock(&dev->cmd_lock);
 
 	pn533_poll_next_mod(dev);
 
@@ -2054,7 +2054,7 @@ error_cmd:
 
 	kfree(arg);
 
-	up(&dev->cmd_lock);
+	mutex_unlock(&dev->cmd_lock);
 }
 
 static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata,
@@ -2114,7 +2114,7 @@ static int pn533_probe(struct usb_interface *interface,
 
 	dev->udev = usb_get_dev(interface_to_usbdev(interface));
 	dev->interface = interface;
-	sema_init(&dev->cmd_lock, 1);
+	mutex_init(&dev->cmd_lock);
 
 	iface_desc = interface->cur_altsetting;
 	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
-- 
1.7.9.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 29/29] NFC: Monitor pn533 target mode
  2012-06-06 10:16 [PATCH 00/29] NFC updates for 3.6 Samuel Ortiz
                   ` (27 preceding siblings ...)
  2012-06-06 10:16 ` [PATCH 28/29] NFC: Convert pn533 from semaphore to mutex Samuel Ortiz
@ 2012-06-06 10:16 ` Samuel Ortiz
  28 siblings, 0 replies; 30+ messages in thread
From: Samuel Ortiz @ 2012-06-06 10:16 UTC (permalink / raw)
  To: John W. Linville
  Cc: Lauro Ramos Venancio, Aloisio Almeida Jr, Ilan Elias,
	linux-wireless, linux-nfc, Samuel Ortiz

When receiving a DEP link down event, we should cancel all pending URBs
if we're activated as a target or if we're an initiator.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
---
 drivers/nfc/pn533.c |   23 ++++++++++++++++++++++-
 1 files changed, 22 insertions(+), 1 deletions(-)

diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index 58c1641..9ac829e 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -343,6 +343,7 @@ struct pn533 {
 
 	u8 tgt_available_prots;
 	u8 tgt_active_prot;
+	u8 tgt_mode;
 };
 
 struct pn533_frame {
@@ -1158,6 +1159,8 @@ static int pn533_tm_get_data_complete(struct pn533 *dev, void *arg,
 	if (params_len > 0 && params[0] != 0) {
 		nfc_tm_deactivated(dev->nfc_dev);
 
+		dev->tgt_mode = 0;
+
 		kfree_skb(skb_resp);
 		return 0;
 	}
@@ -1245,6 +1248,8 @@ static int pn533_init_target_complete(struct pn533 *dev, void *arg,
 		return rc;
 	}
 
+	dev->tgt_mode = 1;
+
 	queue_work(dev->wq, &dev->tg_work);
 
 	return 0;
@@ -1397,6 +1402,12 @@ static int pn533_start_poll(struct nfc_dev *nfc_dev,
 		return -EBUSY;
 	}
 
+	if (dev->tgt_mode) {
+		nfc_dev_err(&dev->interface->dev,
+			    "Cannot poll while already being activated");
+		return -EBUSY;
+	}
+
 	if (tm_protocols) {
 		dev->gb = nfc_get_local_general_bytes(nfc_dev, &dev->gb_len);
 		if (dev->gb == NULL)
@@ -1725,7 +1736,15 @@ static int pn533_dep_link_down(struct nfc_dev *nfc_dev)
 
 	pn533_poll_reset_mod_list(dev);
 
-	pn533_deactivate_target(nfc_dev, 0);
+	if (dev->tgt_mode || dev->tgt_active_prot) {
+		pn533_send_ack(dev, GFP_KERNEL);
+		usb_kill_urb(dev->in_urb);
+	}
+
+	dev->tgt_active_prot = 0;
+	dev->tgt_mode = 0;
+
+	skb_queue_purge(&dev->resp_q);
 
 	return 0;
 }
@@ -1956,6 +1975,8 @@ static int pn533_tm_send_complete(struct pn533 *dev, void *arg,
 	if (params_len > 0 && params[0] != 0) {
 		nfc_tm_deactivated(dev->nfc_dev);
 
+		dev->tgt_mode = 0;
+
 		return 0;
 	}
 
-- 
1.7.9.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

end of thread, other threads:[~2012-06-06 10:08 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-06-06 10:16 [PATCH 00/29] NFC updates for 3.6 Samuel Ortiz
2012-06-06 10:16 ` [PATCH 01/29] NFC: Take a reference on the LLCP local pointer when creating a socket Samuel Ortiz
2012-06-06 10:16 ` [PATCH 02/29] NFC: Socket linked list Samuel Ortiz
2012-06-06 10:16 ` [PATCH 03/29] NFC: Move LLCP receiver window value to socket structure Samuel Ortiz
2012-06-06 10:16 ` [PATCH 04/29] NFC: Move LLCP MIU extension " Samuel Ortiz
2012-06-06 10:16 ` [PATCH 05/29] NFC: LLCP's MIUX is 10 bytes long, not 7 Samuel Ortiz
2012-06-06 10:16 ` [PATCH 06/29] NFC: Export LLCP general bytes getter Samuel Ortiz
2012-06-06 10:16 ` [PATCH 07/29] NFC: Add target mode protocols to the polling loop startup routine Samuel Ortiz
2012-06-06 10:16 ` [PATCH 08/29] NFC: Implement pn533 target mode polling loop Samuel Ortiz
2012-06-06 10:16 ` [PATCH 09/29] NFC: Add target mode activation netlink event Samuel Ortiz
2012-06-06 10:16 ` [PATCH 10/29] NFC: Set the NFC device RF mode appropriately Samuel Ortiz
2012-06-06 10:16 ` [PATCH 11/29] NFC: Introduce target mode tx ops Samuel Ortiz
2012-06-06 10:16 ` [PATCH 12/29] NFC: Introduce target mode rx data callback Samuel Ortiz
2012-06-06 10:16 ` [PATCH 13/29] NFC: Implement the pn533 target mode data fetching routine Samuel Ortiz
2012-06-06 10:16 ` [PATCH 14/29] NFC: Implement the pn533 target mode Tx op Samuel Ortiz
2012-06-06 10:16 ` [PATCH 15/29] NFC: Don't hold a NULL connecting LLCP socket lock Samuel Ortiz
2012-06-06 10:16 ` [PATCH 16/29] NFC: Call the DEP link down ops even when in target mode Samuel Ortiz
2012-06-06 10:16 ` [PATCH 17/29] NFC: Reset poll mod list when stopping pn533 poll Samuel Ortiz
2012-06-06 10:16 ` [PATCH 18/29] NFC: Unregister device if pn533 initial configuration fails Samuel Ortiz
2012-06-06 10:16 ` [PATCH 19/29] NFC: Configure pn533 RF timings Samuel Ortiz
2012-06-06 10:16 ` [PATCH 20/29] NFC: Add passive initiator data for pn533 Samuel Ortiz
2012-06-06 10:16 ` [PATCH 21/29] NFC: Add type A and type F parameters for pn533 target mode Samuel Ortiz
2012-06-06 10:16 ` [PATCH 22/29] NFC: Implement pn533 polling loop Samuel Ortiz
2012-06-06 10:16 ` [PATCH 23/29] NFC: Requeue lost LLCP frames Samuel Ortiz
2012-06-06 10:16 ` [PATCH 24/29] NFC: Send a receiver ready frame only to reply to an I frame Samuel Ortiz
2012-06-06 10:16 ` [PATCH 25/29] NFC: Switch to Initiator mode when getting NFC_ATTR_PROTOCOLS Samuel Ortiz
2012-06-06 10:16 ` [PATCH 26/29] NFC: Destroy LLCP timout workqueue when releasing the link Samuel Ortiz
2012-06-06 10:16 ` [PATCH 27/29] NFC: Set the proper baud rate when trying to activate pn533 targets Samuel Ortiz
2012-06-06 10:16 ` [PATCH 28/29] NFC: Convert pn533 from semaphore to mutex Samuel Ortiz
2012-06-06 10:16 ` [PATCH 29/29] NFC: Monitor pn533 target mode Samuel Ortiz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).