aboutsummaryrefslogtreecommitdiffstats
path: root/net/nfc/llcp/commands.c
diff options
context:
space:
mode:
authorThierry Escande <thierry.escande@linux.intel.com>2013-02-15 04:43:06 -0500
committerSamuel Ortiz <sameo@linux.intel.com>2013-03-10 18:14:54 -0400
commitd9b8d8e19b073096d3609bbd60f82148d128b555 (patch)
tree0888a7ff7367bc5efd1b5e1388bc59aab308451c /net/nfc/llcp/commands.c
parente0ae7bac06ccb90bb0cf7a3362730b48c7d7f1a8 (diff)
NFC: llcp: Service Name Lookup netlink interface
This adds a netlink interface for service name lookup support. Multiple URIs can be passed nested into the NFC_ATTR_LLC_SDP attribute using the NFC_CMD_LLC_SDREQ netlink command. When the SNL reply is received, a NFC_EVENT_LLC_SDRES event is sent to the user space. URI and SAP tuples are passed back, nested into NFC_ATTR_LLC_SDP attribute. Signed-off-by: Thierry Escande <thierry.escande@linux.intel.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'net/nfc/llcp/commands.c')
-rw-r--r--net/nfc/llcp/commands.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c
index 59f7ffca783e..c943edb07b72 100644
--- a/net/nfc/llcp/commands.c
+++ b/net/nfc/llcp/commands.c
@@ -144,12 +144,59 @@ struct nfc_llcp_sdp_tlv *nfc_llcp_build_sdres_tlv(u8 tid, u8 sap)
144 return sdres; 144 return sdres;
145} 145}
146 146
147struct nfc_llcp_sdp_tlv *nfc_llcp_build_sdreq_tlv(u8 tid, char *uri,
148 size_t uri_len)
149{
150 struct nfc_llcp_sdp_tlv *sdreq;
151
152 pr_debug("uri: %s, len: %zu\n", uri, uri_len);
153
154 sdreq = kzalloc(sizeof(struct nfc_llcp_sdp_tlv), GFP_KERNEL);
155 if (sdreq == NULL)
156 return NULL;
157
158 sdreq->tlv_len = uri_len + 3;
159
160 if (uri[uri_len - 1] == 0)
161 sdreq->tlv_len--;
162
163 sdreq->tlv = kzalloc(sdreq->tlv_len + 1, GFP_KERNEL);
164 if (sdreq->tlv == NULL) {
165 kfree(sdreq);
166 return NULL;
167 }
168
169 sdreq->tlv[0] = LLCP_TLV_SDREQ;
170 sdreq->tlv[1] = sdreq->tlv_len - 2;
171 sdreq->tlv[2] = tid;
172
173 sdreq->tid = tid;
174 sdreq->uri = sdreq->tlv + 3;
175 memcpy(sdreq->uri, uri, uri_len);
176
177 INIT_HLIST_NODE(&sdreq->node);
178
179 return sdreq;
180}
181
147void nfc_llcp_free_sdp_tlv(struct nfc_llcp_sdp_tlv *sdp) 182void nfc_llcp_free_sdp_tlv(struct nfc_llcp_sdp_tlv *sdp)
148{ 183{
149 kfree(sdp->tlv); 184 kfree(sdp->tlv);
150 kfree(sdp); 185 kfree(sdp);
151} 186}
152 187
188void nfc_llcp_free_sdp_tlv_list(struct hlist_head *head)
189{
190 struct nfc_llcp_sdp_tlv *sdp;
191 struct hlist_node *n;
192
193 hlist_for_each_entry_safe(sdp, n, head, node) {
194 hlist_del(&sdp->node);
195
196 nfc_llcp_free_sdp_tlv(sdp);
197 }
198}
199
153int nfc_llcp_parse_gb_tlv(struct nfc_llcp_local *local, 200int nfc_llcp_parse_gb_tlv(struct nfc_llcp_local *local,
154 u8 *tlv_array, u16 tlv_array_len) 201 u8 *tlv_array, u16 tlv_array_len)
155{ 202{
@@ -511,6 +558,37 @@ int nfc_llcp_send_snl_sdres(struct nfc_llcp_local *local,
511 return 0; 558 return 0;
512} 559}
513 560
561int nfc_llcp_send_snl_sdreq(struct nfc_llcp_local *local,
562 struct hlist_head *tlv_list, size_t tlvs_len)
563{
564 struct nfc_llcp_sdp_tlv *sdreq;
565 struct hlist_node *n;
566 struct sk_buff *skb;
567
568 skb = nfc_llcp_allocate_snl(local, tlvs_len);
569 if (IS_ERR(skb))
570 return PTR_ERR(skb);
571
572 mutex_lock(&local->sdreq_lock);
573
574 hlist_for_each_entry_safe(sdreq, n, tlv_list, node) {
575 pr_debug("tid %d for %s\n", sdreq->tid, sdreq->uri);
576
577 memcpy(skb_put(skb, sdreq->tlv_len), sdreq->tlv,
578 sdreq->tlv_len);
579
580 hlist_del(&sdreq->node);
581
582 hlist_add_head(&sdreq->node, &local->pending_sdreqs);
583 }
584
585 mutex_unlock(&local->sdreq_lock);
586
587 skb_queue_tail(&local->tx_queue, skb);
588
589 return 0;
590}
591
514int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason) 592int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason)
515{ 593{
516 struct sk_buff *skb; 594 struct sk_buff *skb;