• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (C) 2010-2013 Broadcom Corporation
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 
20 /******************************************************************************
21  *
22  *  This file contains the LLCP Service Discovery
23  *
24  ******************************************************************************/
25 
26 #include <string.h>
27 #include "gki.h"
28 #include "nfc_target.h"
29 #include "bt_types.h"
30 #include "llcp_api.h"
31 #include "llcp_int.h"
32 #include "llcp_defs.h"
33 
34 /*******************************************************************************
35 **
36 ** Function         llcp_sdp_proc_data
37 **
38 ** Description      Do nothing
39 **
40 **
41 ** Returns          void
42 **
43 *******************************************************************************/
llcp_sdp_proc_data(tLLCP_SAP_CBACK_DATA * p_data)44 void llcp_sdp_proc_data (tLLCP_SAP_CBACK_DATA *p_data)
45 {
46     /*
47     ** Do nothing
48     ** llcp_sdp_proc_SNL () is called by link layer
49     */
50 }
51 
52 /*******************************************************************************
53 **
54 ** Function         llcp_sdp_check_send_snl
55 **
56 ** Description      Enqueue Service Name Lookup PDU into sig_xmit_q for transmitting
57 **
58 **
59 ** Returns          void
60 **
61 *******************************************************************************/
llcp_sdp_check_send_snl(void)62 void llcp_sdp_check_send_snl (void)
63 {
64     UINT8 *p;
65 
66     if (llcp_cb.sdp_cb.p_snl)
67     {
68         LLCP_TRACE_DEBUG0 ("SDP: llcp_sdp_check_send_snl ()");
69 
70         llcp_cb.sdp_cb.p_snl->len     += LLCP_PDU_HEADER_SIZE;
71         llcp_cb.sdp_cb.p_snl->offset  -= LLCP_PDU_HEADER_SIZE;
72 
73         p = (UINT8 *) (llcp_cb.sdp_cb.p_snl + 1) + llcp_cb.sdp_cb.p_snl->offset;
74         UINT16_TO_BE_STREAM (p, LLCP_GET_PDU_HEADER (LLCP_SAP_SDP, LLCP_PDU_SNL_TYPE, LLCP_SAP_SDP ));
75 
76         GKI_enqueue (&llcp_cb.lcb.sig_xmit_q, llcp_cb.sdp_cb.p_snl);
77         llcp_cb.sdp_cb.p_snl = NULL;
78     }
79     else
80     {
81         /* Notify DTA after sending out SNL with SDRES not to send SNLs in AGF PDU */
82         if ((llcp_cb.p_dta_cback) && (llcp_cb.dta_snl_resp))
83         {
84             llcp_cb.dta_snl_resp = FALSE;
85             (*llcp_cb.p_dta_cback) ();
86         }
87     }
88 }
89 
90 /*******************************************************************************
91 **
92 ** Function         llcp_sdp_add_sdreq
93 **
94 ** Description      Add Service Discovery Request into SNL PDU
95 **
96 **
97 ** Returns          void
98 **
99 *******************************************************************************/
llcp_sdp_add_sdreq(UINT8 tid,char * p_name)100 static void llcp_sdp_add_sdreq (UINT8 tid, char *p_name)
101 {
102     UINT8  *p;
103     UINT16 name_len = (UINT16) strlen (p_name);
104 
105     p = (UINT8 *) (llcp_cb.sdp_cb.p_snl + 1) + llcp_cb.sdp_cb.p_snl->offset + llcp_cb.sdp_cb.p_snl->len;
106 
107     UINT8_TO_BE_STREAM (p, LLCP_SDREQ_TYPE);
108     UINT8_TO_BE_STREAM (p, (1 + name_len));
109     UINT8_TO_BE_STREAM (p, tid);
110     ARRAY_TO_BE_STREAM (p, p_name, name_len);
111 
112     llcp_cb.sdp_cb.p_snl->len += LLCP_SDREQ_MIN_LEN + name_len;
113 }
114 
115 /*******************************************************************************
116 **
117 ** Function         llcp_sdp_send_sdreq
118 **
119 ** Description      Send Service Discovery Request
120 **
121 **
122 ** Returns          LLCP_STATUS
123 **
124 *******************************************************************************/
llcp_sdp_send_sdreq(UINT8 tid,char * p_name)125 tLLCP_STATUS llcp_sdp_send_sdreq (UINT8 tid, char *p_name)
126 {
127     tLLCP_STATUS status;
128     UINT16       name_len;
129     UINT16       available_bytes;
130 
131     LLCP_TRACE_DEBUG2 ("llcp_sdp_send_sdreq (): tid=0x%x, ServiceName=%s", tid, p_name);
132 
133     /* if there is no pending SNL */
134     if (!llcp_cb.sdp_cb.p_snl)
135     {
136         llcp_cb.sdp_cb.p_snl = (BT_HDR*) GKI_getpoolbuf (LLCP_POOL_ID);
137 
138         if (llcp_cb.sdp_cb.p_snl)
139         {
140             llcp_cb.sdp_cb.p_snl->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE + LLCP_PDU_HEADER_SIZE;
141             llcp_cb.sdp_cb.p_snl->len    = 0;
142         }
143     }
144 
145     if (llcp_cb.sdp_cb.p_snl)
146     {
147         available_bytes = GKI_get_buf_size (llcp_cb.sdp_cb.p_snl)
148                           - BT_HDR_SIZE - llcp_cb.sdp_cb.p_snl->offset
149                           - llcp_cb.sdp_cb.p_snl->len;
150 
151         name_len = (UINT16) strlen (p_name);
152 
153         /* if SDREQ parameter can be added in SNL */
154         if (  (available_bytes >= LLCP_SDREQ_MIN_LEN + name_len)
155             &&(llcp_cb.sdp_cb.p_snl->len + LLCP_SDREQ_MIN_LEN + name_len <= llcp_cb.lcb.effective_miu)  )
156         {
157             llcp_sdp_add_sdreq (tid, p_name);
158             status = LLCP_STATUS_SUCCESS;
159         }
160         else
161         {
162             /* send pending SNL PDU to LM */
163             llcp_sdp_check_send_snl ();
164 
165             llcp_cb.sdp_cb.p_snl = (BT_HDR*) GKI_getpoolbuf (LLCP_POOL_ID);
166 
167             if (llcp_cb.sdp_cb.p_snl)
168             {
169                 llcp_cb.sdp_cb.p_snl->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE + LLCP_PDU_HEADER_SIZE;
170                 llcp_cb.sdp_cb.p_snl->len    = 0;
171 
172                 llcp_sdp_add_sdreq (tid, p_name);
173 
174                 status = LLCP_STATUS_SUCCESS;
175             }
176             else
177             {
178                 status = LLCP_STATUS_FAIL;
179             }
180         }
181     }
182     else
183     {
184         status = LLCP_STATUS_FAIL;
185     }
186 
187     /* if LM is waiting for PDUs from upper layer */
188     if (  (status == LLCP_STATUS_SUCCESS)
189         &&(llcp_cb.lcb.symm_state == LLCP_LINK_SYMM_LOCAL_XMIT_NEXT)  )
190     {
191         llcp_link_check_send_data ();
192     }
193 
194     return status;
195 }
196 
197 /*******************************************************************************
198 **
199 ** Function         llcp_sdp_add_sdres
200 **
201 ** Description      Add Service Discovery Response into SNL PDU
202 **
203 **
204 ** Returns          void
205 **
206 *******************************************************************************/
llcp_sdp_add_sdres(UINT8 tid,UINT8 sap)207 static void llcp_sdp_add_sdres (UINT8 tid, UINT8 sap)
208 {
209     UINT8  *p;
210 
211     p = (UINT8 *) (llcp_cb.sdp_cb.p_snl + 1) + llcp_cb.sdp_cb.p_snl->offset + llcp_cb.sdp_cb.p_snl->len;
212 
213     UINT8_TO_BE_STREAM (p, LLCP_SDRES_TYPE);
214     UINT8_TO_BE_STREAM (p, LLCP_SDRES_LEN);
215     UINT8_TO_BE_STREAM (p, tid);
216     UINT8_TO_BE_STREAM (p, sap);
217 
218     llcp_cb.sdp_cb.p_snl->len += 2 + LLCP_SDRES_LEN;   /* type and length */
219 }
220 
221 /*******************************************************************************
222 **
223 ** Function         llcp_sdp_send_sdres
224 **
225 ** Description      Send Service Discovery Response
226 **
227 **
228 ** Returns          LLCP_STATUS
229 **
230 *******************************************************************************/
llcp_sdp_send_sdres(UINT8 tid,UINT8 sap)231 static tLLCP_STATUS llcp_sdp_send_sdres (UINT8 tid, UINT8 sap)
232 {
233     tLLCP_STATUS status;
234     UINT16       available_bytes;
235 
236     LLCP_TRACE_DEBUG2 ("llcp_sdp_send_sdres (): tid=0x%x, SAP=0x%x", tid, sap);
237 
238     /* if there is no pending SNL */
239     if (!llcp_cb.sdp_cb.p_snl)
240     {
241         llcp_cb.sdp_cb.p_snl = (BT_HDR*) GKI_getpoolbuf (LLCP_POOL_ID);
242 
243         if (llcp_cb.sdp_cb.p_snl)
244         {
245             llcp_cb.sdp_cb.p_snl->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE + LLCP_PDU_HEADER_SIZE;
246             llcp_cb.sdp_cb.p_snl->len    = 0;
247         }
248     }
249 
250     if (llcp_cb.sdp_cb.p_snl)
251     {
252         available_bytes = GKI_get_buf_size (llcp_cb.sdp_cb.p_snl)
253                           - BT_HDR_SIZE - llcp_cb.sdp_cb.p_snl->offset
254                           - llcp_cb.sdp_cb.p_snl->len;
255 
256         /* if SDRES parameter can be added in SNL */
257         if (  (available_bytes >= 2 + LLCP_SDRES_LEN)
258             &&(llcp_cb.sdp_cb.p_snl->len + 2 + LLCP_SDRES_LEN <= llcp_cb.lcb.effective_miu)  )
259         {
260             llcp_sdp_add_sdres (tid, sap);
261             status = LLCP_STATUS_SUCCESS;
262         }
263         else
264         {
265             /* send pending SNL PDU to LM */
266             llcp_sdp_check_send_snl ();
267 
268             llcp_cb.sdp_cb.p_snl = (BT_HDR*) GKI_getpoolbuf (LLCP_POOL_ID);
269 
270             if (llcp_cb.sdp_cb.p_snl)
271             {
272                 llcp_cb.sdp_cb.p_snl->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE + LLCP_PDU_HEADER_SIZE;
273                 llcp_cb.sdp_cb.p_snl->len    = 0;
274 
275                 llcp_sdp_add_sdres (tid, sap);
276 
277                 status = LLCP_STATUS_SUCCESS;
278             }
279             else
280             {
281                 status = LLCP_STATUS_FAIL;
282             }
283         }
284     }
285     else
286     {
287         status = LLCP_STATUS_FAIL;
288     }
289 
290     /* if LM is waiting for PDUs from upper layer */
291     if (  (status == LLCP_STATUS_SUCCESS)
292         &&(llcp_cb.lcb.symm_state == LLCP_LINK_SYMM_LOCAL_XMIT_NEXT)  )
293     {
294         llcp_link_check_send_data ();
295     }
296 
297     return status;
298 }
299 
300 /*******************************************************************************
301 **
302 ** Function         llcp_sdp_get_sap_by_name
303 **
304 ** Description      Search SAP by service name
305 **
306 **
307 ** Returns          SAP if success
308 **
309 *******************************************************************************/
llcp_sdp_get_sap_by_name(char * p_name,UINT8 length)310 UINT8 llcp_sdp_get_sap_by_name (char *p_name, UINT8 length)
311 {
312     UINT8        sap;
313     tLLCP_APP_CB *p_app_cb;
314 
315     for (sap = LLCP_SAP_SDP; sap <= LLCP_UPPER_BOUND_SDP_SAP; sap++)
316     {
317         p_app_cb = llcp_util_get_app_cb (sap);
318 
319         if (  (p_app_cb)
320             &&(p_app_cb->p_app_cback)
321             &&(strlen((char*)p_app_cb->p_service_name) == length)
322             &&(!strncmp((char*)p_app_cb->p_service_name, p_name, length))  )
323         {
324             /* if device is under LLCP DTA testing */
325             if (  (llcp_cb.p_dta_cback)
326                 &&(!strncmp((char*)p_app_cb->p_service_name, "urn:nfc:sn:cl-echo-in", length))  )
327             {
328                 llcp_cb.dta_snl_resp = TRUE;
329             }
330             return (sap);
331         }
332     }
333     return 0;
334 }
335 
336 /*******************************************************************************
337 **
338 ** Function         llcp_sdp_return_sap
339 **
340 ** Description      Report TID and SAP to requester
341 **
342 **
343 ** Returns          void
344 **
345 *******************************************************************************/
llcp_sdp_return_sap(UINT8 tid,UINT8 sap)346 static void llcp_sdp_return_sap (UINT8 tid, UINT8 sap)
347 {
348     UINT8 i;
349 
350     LLCP_TRACE_DEBUG2 ("llcp_sdp_return_sap (): tid=0x%x, SAP=0x%x", tid, sap);
351 
352     for (i = 0; i < LLCP_MAX_SDP_TRANSAC; i++)
353     {
354         if (  (llcp_cb.sdp_cb.transac[i].p_cback)
355             &&(llcp_cb.sdp_cb.transac[i].tid == tid)  )
356         {
357             (*llcp_cb.sdp_cb.transac[i].p_cback) (tid, sap);
358 
359             llcp_cb.sdp_cb.transac[i].p_cback = NULL;
360         }
361     }
362 }
363 
364 /*******************************************************************************
365 **
366 ** Function         llcp_sdp_proc_deactivation
367 **
368 ** Description      Report SDP failure for any pending request because of deactivation
369 **
370 **
371 ** Returns          void
372 **
373 *******************************************************************************/
llcp_sdp_proc_deactivation(void)374 void llcp_sdp_proc_deactivation (void)
375 {
376     UINT8 i;
377 
378     LLCP_TRACE_DEBUG0 ("llcp_sdp_proc_deactivation ()");
379 
380     for (i = 0; i < LLCP_MAX_SDP_TRANSAC; i++)
381     {
382         if (llcp_cb.sdp_cb.transac[i].p_cback)
383         {
384             (*llcp_cb.sdp_cb.transac[i].p_cback) (llcp_cb.sdp_cb.transac[i].tid, 0x00);
385 
386             llcp_cb.sdp_cb.transac[i].p_cback = NULL;
387         }
388     }
389 
390     /* free any pending SNL PDU */
391     if (llcp_cb.sdp_cb.p_snl)
392     {
393         GKI_freebuf (llcp_cb.sdp_cb.p_snl);
394         llcp_cb.sdp_cb.p_snl = NULL;
395     }
396 
397     llcp_cb.sdp_cb.next_tid = 0;
398     llcp_cb.dta_snl_resp = FALSE;
399 }
400 
401 /*******************************************************************************
402 **
403 ** Function         llcp_sdp_proc_snl
404 **
405 ** Description      Process SDREQ and SDRES in SNL
406 **
407 **
408 ** Returns          LLCP_STATUS
409 **
410 *******************************************************************************/
llcp_sdp_proc_snl(UINT16 sdu_length,UINT8 * p)411 tLLCP_STATUS llcp_sdp_proc_snl (UINT16 sdu_length, UINT8 *p)
412 {
413     UINT8  type, length, tid, sap, *p_value;
414 
415     LLCP_TRACE_DEBUG0 ("llcp_sdp_proc_snl ()");
416 
417     if ((llcp_cb.lcb.agreed_major_version < LLCP_MIN_SNL_MAJOR_VERSION)||
418        ((llcp_cb.lcb.agreed_major_version == LLCP_MIN_SNL_MAJOR_VERSION)&&(llcp_cb.lcb.agreed_minor_version < LLCP_MIN_SNL_MINOR_VERSION)))
419     {
420         LLCP_TRACE_DEBUG0 ("llcp_sdp_proc_snl(): version number less than 1.1, SNL not supported.");
421         return LLCP_STATUS_FAIL;
422     }
423     while (sdu_length >= 2) /* at least type and length */
424     {
425         BE_STREAM_TO_UINT8 (type, p);
426         BE_STREAM_TO_UINT8 (length, p);
427 
428         switch (type)
429         {
430         case LLCP_SDREQ_TYPE:
431             if (  (length > 1)                /* TID and sevice name */
432                 &&(sdu_length >= 2 + length)  ) /* type, length, TID and service name */
433             {
434                 p_value = p;
435                 BE_STREAM_TO_UINT8 (tid, p_value);
436                 sap = llcp_sdp_get_sap_by_name ((char*) p_value, (UINT8) (length - 1));
437                 llcp_sdp_send_sdres (tid, sap);
438             }
439             else
440             {
441                 LLCP_TRACE_ERROR1 ("llcp_sdp_proc_snl (): bad length (%d) in LLCP_SDREQ_TYPE", length);
442             }
443             break;
444 
445         case LLCP_SDRES_TYPE:
446             if (  (length == LLCP_SDRES_LEN)  /* TID and SAP */
447                 &&(sdu_length >= 2 + length)  ) /* type, length, TID and SAP */
448             {
449                 p_value = p;
450                 BE_STREAM_TO_UINT8 (tid, p_value);
451                 BE_STREAM_TO_UINT8 (sap, p_value);
452                 llcp_sdp_return_sap (tid, sap);
453             }
454             else
455             {
456                 LLCP_TRACE_ERROR1 ("llcp_sdp_proc_snl (): bad length (%d) in LLCP_SDRES_TYPE", length);
457             }
458             break;
459 
460         default:
461             LLCP_TRACE_WARNING1 ("llcp_sdp_proc_snl (): Unknown type (0x%x) is ignored", type);
462             break;
463         }
464 
465         if (sdu_length >= 2 + length)   /* type, length, value */
466         {
467             sdu_length -= 2 + length;
468             p += length;
469         }
470         else
471         {
472             break;
473         }
474     }
475 
476     if (sdu_length)
477     {
478         LLCP_TRACE_ERROR0 ("llcp_sdp_proc_snl (): Bad format of SNL");
479         return LLCP_STATUS_FAIL;
480     }
481     else
482     {
483         return LLCP_STATUS_SUCCESS;
484     }
485 }
486