diff options
author | Thierry Escande <thierry.escande@linux.intel.com> | 2013-02-15 04:43:06 -0500 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2013-03-10 18:14:54 -0400 |
commit | d9b8d8e19b073096d3609bbd60f82148d128b555 (patch) | |
tree | 0888a7ff7367bc5efd1b5e1388bc59aab308451c /net/nfc/llcp/commands.c | |
parent | e0ae7bac06ccb90bb0cf7a3362730b48c7d7f1a8 (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.c | 78 |
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 | ||
147 | struct 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 | |||
147 | void nfc_llcp_free_sdp_tlv(struct nfc_llcp_sdp_tlv *sdp) | 182 | void 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 | ||
188 | void 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 | |||
153 | int nfc_llcp_parse_gb_tlv(struct nfc_llcp_local *local, | 200 | int 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 | ||
561 | int 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 | |||
514 | int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason) | 592 | int 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; |