All of lore.kernel.org
 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.