NFC: UI frame sending routine implementation
authorSamuel Ortiz <sameo@linux.intel.com>
Tue, 16 Oct 2012 13:01:40 +0000 (15:01 +0200)
committerSamuel Ortiz <sameo@linux.intel.com>
Fri, 26 Oct 2012 16:26:50 +0000 (18:26 +0200)
UI frames still need to follow the MIU rule, and they need to use the
client passed dsap as the listening socket dsap is stuck on SDP.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
net/nfc/llcp/commands.c
net/nfc/llcp/llcp.h

index 6db280ddc4c83e49128702de6567a432115cbf54..79415353cc28af65177496b6fcce6eca34872534 100644 (file)
@@ -579,6 +579,52 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
        return len;
 }
 
+int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap,
+                          struct msghdr *msg, size_t len)
+{
+       struct sk_buff *pdu;
+       struct nfc_llcp_local *local;
+       size_t frag_len = 0, remaining_len;
+       u8 *msg_ptr;
+       int err;
+
+       pr_debug("Send UI frame len %zd\n", len);
+
+       local = sock->local;
+       if (local == NULL)
+               return -ENODEV;
+
+       remaining_len = len;
+       msg_ptr = (u8 *) msg->msg_iov;
+
+       while (remaining_len > 0) {
+
+               frag_len = min_t(size_t, sock->miu, remaining_len);
+
+               pr_debug("Fragment %zd bytes remaining %zd",
+                        frag_len, remaining_len);
+
+               pdu = nfc_alloc_send_skb(sock->dev, &sock->sk, MSG_DONTWAIT,
+                                        frag_len + LLCP_HEADER_SIZE, &err);
+               if (pdu == NULL) {
+                       pr_err("Could not allocate PDU\n");
+                       continue;
+               }
+
+               pdu = llcp_add_header(pdu, dsap, ssap, LLCP_PDU_UI);
+
+               memcpy(skb_put(pdu, frag_len), msg_ptr, frag_len);
+
+               /* No need to check for the peer RW for UI frames */
+               skb_queue_tail(&local->tx_queue, pdu);
+
+               remaining_len -= frag_len;
+               msg_ptr += frag_len;
+       }
+
+       return len;
+}
+
 int nfc_llcp_send_rr(struct nfc_llcp_sock *sock)
 {
        struct sk_buff *skb;
index e06d03571644d9e18dbb309f2a9222fcf1538c52..276da3a6a589fabbffc402ae1e109f87d00a0eed 100644 (file)
@@ -221,6 +221,8 @@ int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason);
 int nfc_llcp_send_disconnect(struct nfc_llcp_sock *sock);
 int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
                          struct msghdr *msg, size_t len);
+int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap,
+                          struct msghdr *msg, size_t len);
 int nfc_llcp_send_rr(struct nfc_llcp_sock *sock);
 
 /* Socket API */