nfa_cho_api.c revision 45faad0ff5deeb0c676356345d99398cc4ab695a
1/*****************************************************************************
2**
3**  Name:           nfa_cho_api.c
4**
5**  Description:    NFA interface for connection handover
6**
7**  Copyright (c) 2010, Broadcom Corp., All Rights Reserved.
8**  Broadcom Bluetooth Core. Proprietary and confidential.
9**
10*****************************************************************************/
11#include <string.h>
12#include "nfc_api.h"
13#include "nfa_sys.h"
14#include "nfa_sys_int.h"
15#include "nfa_p2p_api.h"
16#include "nfa_cho_api.h"
17#include "nfa_cho_int.h"
18#include "nfa_mem_co.h"
19
20/*****************************************************************************
21**  Constants
22*****************************************************************************/
23
24/*******************************************************************************
25**
26** Function         NFA_ChoRegister
27**
28** Description      This function is called to register callback function to receive
29**                  connection handover events.
30**
31**                  On this registration, "urn:nfc:sn:handover" server will be
32**                  registered on LLCP if enable_server is TRUE.
33**
34**                  The result of the registration is reported with NFA_CHO_REG_EVT.
35**
36** Note:            If RF discovery is started, NFA_StopRfDiscovery()/NFA_RF_DISCOVERY_STOPPED_EVT
37**                  should happen before calling this function
38**
39** Returns          NFA_STATUS_OK if successfully initiated
40**                  NFA_STATUS_FAILED otherwise
41**
42*******************************************************************************/
43tNFA_STATUS NFA_ChoRegister (BOOLEAN        enable_server,
44                             tNFA_CHO_CBACK *p_cback)
45{
46    tNFA_CHO_API_REG *p_msg;
47
48    CHO_TRACE_API1 ("NFA_ChoRegister (): enable_server=%d", enable_server);
49
50    if (  (nfa_cho_cb.state != NFA_CHO_ST_DISABLED)
51        ||(nfa_cho_cb.p_cback != NULL)  )
52    {
53        CHO_TRACE_ERROR0 ("NFA_ChoRegister (): Already registered or callback is not provided");
54        return (NFA_STATUS_FAILED);
55    }
56
57    if ((p_msg = (tNFA_CHO_API_REG *) GKI_getbuf (sizeof (tNFA_CHO_API_REG))) != NULL)
58    {
59        p_msg->hdr.event = NFA_CHO_API_REG_EVT;
60
61        p_msg->enable_server = enable_server;
62        p_msg->p_cback       = p_cback;
63
64        nfa_sys_sendmsg (p_msg);
65
66        return (NFA_STATUS_OK);
67    }
68
69    return (NFA_STATUS_FAILED);
70}
71
72/*******************************************************************************
73**
74** Function         NFA_ChoDeregister
75**
76** Description      This function is called to deregister callback function from NFA
77**                  Connection Handover Application.
78**
79**                  If this is the valid deregistration, NFA Connection Handover
80**                  Application will close the service with "urn:nfc:sn:handover"
81**                  on LLCP and deregister NDEF type handler if any.
82**
83** Note:            If RF discovery is started, NFA_StopRfDiscovery()/NFA_RF_DISCOVERY_STOPPED_EVT
84**                  should happen before calling this function
85**
86** Returns          NFA_STATUS_OK if successfully initiated
87**                  NFA_STATUS_FAILED otherwise
88**
89*******************************************************************************/
90tNFA_STATUS NFA_ChoDeregister (void)
91{
92    tNFA_CHO_API_DEREG *p_msg;
93
94    CHO_TRACE_API0 ("NFA_ChoDeregister ()");
95
96    if (nfa_cho_cb.state == NFA_CHO_ST_DISABLED)
97    {
98        CHO_TRACE_ERROR0 ("NFA_ChoDeregister (): Not registered");
99        return (NFA_STATUS_FAILED);
100    }
101
102    if ((p_msg = (tNFA_CHO_API_DEREG *) GKI_getbuf (sizeof (tNFA_CHO_API_DEREG))) != NULL)
103    {
104        p_msg->event = NFA_CHO_API_DEREG_EVT;
105
106        nfa_sys_sendmsg (p_msg);
107
108        return (NFA_STATUS_OK);
109    }
110
111    return (NFA_STATUS_FAILED);
112}
113
114/*******************************************************************************
115**
116** Function         NFA_ChoConnect
117**
118** Description      This function is called to create data link connection to
119**                  Connection Handover server on peer device.
120**
121**                  It must be called after receiving NFA_CHO_ACTIVATED_EVT.
122**                  NFA_CHO_CONNECTED_EVT will be returned if successful.
123**                  Otherwise, NFA_CHO_DISCONNECTED_EVT will be returned.
124**
125**                  If NFA_CHO_ROLE_REQUESTER is returned in NFA_CHO_CONNECTED_EVT,
126**                  Handover Request Message can be sent.
127**                  If NFA_CHO_ROLE_SELECTOR is returned in NFA_CHO_CONNECTED_EVT
128**                  because of collision, application must wait for Handover
129**                  Request Message.
130**
131** Returns          NFA_STATUS_OK if successfully initiated
132**                  NFA_STATUS_FAILED otherwise
133**
134*******************************************************************************/
135tNFA_STATUS NFA_ChoConnect (void)
136{
137    tNFA_CHO_API_CONNECT *p_msg;
138
139    CHO_TRACE_API0 ("NFA_ChoConnect ()");
140
141    if (nfa_cho_cb.state == NFA_CHO_ST_DISABLED)
142    {
143        CHO_TRACE_ERROR0 ("NFA_ChoConnect (): Not registered");
144        return (NFA_STATUS_FAILED);
145    }
146    else if (nfa_cho_cb.state == NFA_CHO_ST_CONNECTED)
147    {
148        CHO_TRACE_ERROR0 ("NFA_ChoConnect (): Already connected");
149        return (NFA_STATUS_FAILED);
150    }
151
152    if ((p_msg = (tNFA_CHO_API_CONNECT *) GKI_getbuf (sizeof (tNFA_CHO_API_CONNECT))) != NULL)
153    {
154        p_msg->event = NFA_CHO_API_CONNECT_EVT;
155
156        nfa_sys_sendmsg (p_msg);
157
158        return (NFA_STATUS_OK);
159    }
160
161    return (NFA_STATUS_FAILED);
162}
163
164/*******************************************************************************
165**
166** Function         NFA_ChoDisconnect
167**
168** Description      This function is called to disconnect data link connection with
169**                  Connection Handover server on peer device.
170**
171**                  NFA_CHO_DISCONNECTED_EVT will be returned.
172**
173** Returns          NFA_STATUS_OK if successfully initiated
174**                  NFA_STATUS_FAILED otherwise
175**
176*******************************************************************************/
177tNFA_STATUS NFA_ChoDisconnect (void)
178{
179    tNFA_CHO_API_DISCONNECT *p_msg;
180
181    CHO_TRACE_API0 ("NFA_ChoDisconnect ()");
182
183    if (nfa_cho_cb.state == NFA_CHO_ST_DISABLED)
184    {
185        CHO_TRACE_ERROR0 ("NFA_ChoDisconnect (): Not registered");
186        return (NFA_STATUS_FAILED);
187    }
188
189    if ((p_msg = (tNFA_CHO_API_DISCONNECT *) GKI_getbuf (sizeof (tNFA_CHO_API_DISCONNECT))) != NULL)
190    {
191        p_msg->event = NFA_CHO_API_DISCONNECT_EVT;
192
193        nfa_sys_sendmsg (p_msg);
194
195        return (NFA_STATUS_OK);
196    }
197
198    return (NFA_STATUS_FAILED);
199}
200
201/*******************************************************************************
202**
203** Function         NFA_ChoSendHr
204**
205** Description      This function is called to send Handover Request Message with
206**                  Handover Carrier records or Alternative Carrier records.
207**
208**                  It must be called after receiving NFA_CHO_CONNECTED_EVT.
209**
210**                  NDEF may include one or more Handover Carrier records or Alternative
211**                  Carrier records with auxiliary data.
212**                  The records in NDEF must be matched with tNFA_CHO_AC_INFO in order.
213**                  Payload ID must be unique and Payload ID length must be less than
214**                  or equal to NFA_CHO_MAX_REF_NAME_LEN.
215**
216**                  The alternative carrier information of Handover Select record
217**                  will be sent to application by NFA_HO_SELECT_EVT. Application
218**                  may receive NFA_CHO_REQUEST_EVT because of handover collision.
219**
220** Returns          NFA_STATUS_OK if successfully initiated
221**                  NFA_STATUS_FAILED otherwise
222**
223*******************************************************************************/
224tNFA_STATUS NFA_ChoSendHr (UINT8             num_ac_info,
225                           tNFA_CHO_AC_INFO *p_ac_info,
226                           UINT8            *p_ndef,
227                           UINT32            ndef_len)
228{
229    tNFA_CHO_API_SEND_HR *p_msg;
230    UINT16               msg_size;
231    UINT8                *p_ndef_buf;
232
233    CHO_TRACE_API2 ("NFA_ChoSendHr (): num_ac_info=%d, ndef_len=%d", num_ac_info, ndef_len);
234
235    if (nfa_cho_cb.state != NFA_CHO_ST_CONNECTED)
236    {
237        CHO_TRACE_ERROR0 ("NFA_ChoSendHr (): Not connected");
238        return (NFA_STATUS_FAILED);
239    }
240
241    if (num_ac_info > NFA_CHO_MAX_AC_INFO)
242    {
243        CHO_TRACE_ERROR0 ("NFA_ChoSendHr (): Too many AC information");
244        return (NFA_STATUS_FAILED);
245    }
246
247    p_ndef_buf = (UINT8 *) GKI_getpoolbuf (LLCP_POOL_ID);
248
249    if (!p_ndef_buf)
250    {
251        CHO_TRACE_ERROR0 ("NFA_ChoSendHr (): Failed to allocate buffer for NDEF");
252        return NFA_STATUS_FAILED;
253    }
254    else if (ndef_len > LLCP_POOL_BUF_SIZE)
255    {
256        CHO_TRACE_ERROR1 ("NFA_ChoSendHr (): Failed to allocate buffer for %d bytes", ndef_len);
257        GKI_freebuf (p_ndef_buf);
258        return NFA_STATUS_FAILED;
259    }
260
261    msg_size = sizeof (tNFA_CHO_API_SEND_HR) + num_ac_info * sizeof (tNFA_CHO_AC_INFO);
262
263    if ((p_msg = (tNFA_CHO_API_SEND_HR *) GKI_getbuf (msg_size)) != NULL)
264    {
265        p_msg->hdr.event = NFA_CHO_API_SEND_HR_EVT;
266
267        memcpy (p_ndef_buf, p_ndef, ndef_len);
268        p_msg->p_ndef        = p_ndef_buf;
269        p_msg->max_ndef_size = LLCP_POOL_BUF_SIZE;
270        p_msg->cur_ndef_size = ndef_len;
271
272        p_msg->num_ac_info   = num_ac_info;
273        p_msg->p_ac_info     = (tNFA_CHO_AC_INFO *) (p_msg + 1);
274        memcpy (p_msg->p_ac_info, p_ac_info, num_ac_info * sizeof (tNFA_CHO_AC_INFO));
275
276        nfa_sys_sendmsg (p_msg);
277        return (NFA_STATUS_OK);
278    }
279    else
280    {
281        GKI_freebuf (p_ndef_buf);
282        return (NFA_STATUS_FAILED);
283    }
284}
285
286/*******************************************************************************
287**
288** Function         NFA_ChoSendHs
289**
290** Description      This function is called to send Handover Select message with
291**                  Alternative Carrier records as response to Handover Request
292**                  message.
293**
294**                  NDEF may include one or more Alternative Carrier records with
295**                  auxiliary data.
296**                  The records in NDEF must be matched with tNFA_CHO_AC_INFO in order.
297**                  Payload ID must be unique and Payload ID length must be less than
298**                  or equal to NFA_CHO_MAX_REF_NAME_LEN.
299**
300** Returns          NFA_STATUS_OK if successfully initiated
301**                  NFA_STATUS_FAILED otherwise
302**
303*******************************************************************************/
304tNFA_STATUS NFA_ChoSendHs (UINT8             num_ac_info,
305                           tNFA_CHO_AC_INFO *p_ac_info,
306                           UINT8            *p_ndef,
307                           UINT32            ndef_len)
308{
309    tNFA_CHO_API_SEND_HS *p_msg;
310    UINT16               msg_size;
311    UINT8                *p_ndef_buf;
312
313    CHO_TRACE_API2 ("NFA_ChoSendHs(): num_ac_info=%d, ndef_len=%d",
314                    num_ac_info, ndef_len);
315
316    if (nfa_cho_cb.state != NFA_CHO_ST_CONNECTED)
317    {
318        CHO_TRACE_ERROR0 ("NFA_ChoSendHs (): Not connected");
319        return (NFA_STATUS_FAILED);
320    }
321
322    if (num_ac_info > NFA_CHO_MAX_AC_INFO)
323    {
324        CHO_TRACE_ERROR0 ("NFA_ChoSendHs (): Too many AC information");
325        return (NFA_STATUS_FAILED);
326    }
327
328    p_ndef_buf = (UINT8 *) GKI_getpoolbuf (LLCP_POOL_ID);
329    if (!p_ndef_buf)
330    {
331        CHO_TRACE_ERROR0 ("NFA_ChoSendHs (): Failed to allocate buffer for NDEF");
332        return NFA_STATUS_FAILED;
333    }
334    else if (ndef_len > LLCP_POOL_BUF_SIZE)
335    {
336        CHO_TRACE_ERROR1 ("NFA_ChoSendHs (): Failed to allocate buffer for %d bytes", ndef_len);
337        GKI_freebuf (p_ndef_buf);
338        return NFA_STATUS_FAILED;
339    }
340
341    msg_size = sizeof (tNFA_CHO_API_SEND_HS) + num_ac_info * sizeof (tNFA_CHO_AC_INFO);
342
343    if ((p_msg = (tNFA_CHO_API_SEND_HS *) GKI_getbuf (msg_size)) != NULL)
344    {
345        p_msg->hdr.event = NFA_CHO_API_SEND_HS_EVT;
346
347        memcpy (p_ndef_buf, p_ndef, ndef_len);
348        p_msg->p_ndef        = p_ndef_buf;
349        p_msg->max_ndef_size = LLCP_POOL_BUF_SIZE;
350        p_msg->cur_ndef_size = ndef_len;
351
352        p_msg->num_ac_info   = num_ac_info;
353        p_msg->p_ac_info     = (tNFA_CHO_AC_INFO *) (p_msg + 1);
354        memcpy (p_msg->p_ac_info, p_ac_info, num_ac_info * sizeof (tNFA_CHO_AC_INFO));
355
356        nfa_sys_sendmsg (p_msg);
357        return (NFA_STATUS_OK);
358    }
359    else
360    {
361        GKI_freebuf (p_ndef_buf);
362        return (NFA_STATUS_FAILED);
363    }
364}
365
366/*******************************************************************************
367**
368** Function         NFA_ChoSendSelectError
369**
370** Description      This function is called to send Error record to indicate failure
371**                  to process the most recently received Handover Request message.
372**
373**                  error_reason : NFA_CHO_ERROR_TEMP_MEM
374**                                 NFA_CHO_ERROR_PERM_MEM
375**                                 NFA_CHO_ERROR_CARRIER
376**
377** Returns          NFA_STATUS_OK if successfully initiated
378**                  NFA_STATUS_FAILED otherwise
379**
380*******************************************************************************/
381tNFA_STATUS NFA_ChoSendSelectError (UINT8  error_reason,
382                                    UINT32 error_data)
383{
384    tNFA_CHO_API_SEL_ERR *p_msg;
385
386    CHO_TRACE_API2 ("NFA_ChoSendSelectError (): error_reason=0x%x, error_data=0x%x",
387                     error_reason, error_data);
388
389    if (nfa_cho_cb.state == NFA_CHO_ST_DISABLED)
390    {
391        CHO_TRACE_ERROR0 ("NFA_ChoSendSelectError (): Not registered");
392        return (NFA_STATUS_FAILED);
393    }
394
395    if ((p_msg = (tNFA_CHO_API_SEL_ERR *) GKI_getbuf (sizeof (tNFA_CHO_API_SEL_ERR))) != NULL)
396    {
397        p_msg->hdr.event = NFA_CHO_API_SEL_ERR_EVT;
398
399        p_msg->error_reason = error_reason;
400        p_msg->error_data   = error_data;
401
402        nfa_sys_sendmsg (p_msg);
403
404        return (NFA_STATUS_OK);
405    }
406
407    return (NFA_STATUS_FAILED);
408}
409
410/*******************************************************************************
411**
412** Function         NFA_ChoSetTraceLevel
413**
414** Description      This function sets the trace level for CHO.  If called with
415**                  a value of 0xFF, it simply returns the current trace level.
416**
417** Returns          The new or current trace level
418**
419*******************************************************************************/
420UINT8 NFA_ChoSetTraceLevel (UINT8 new_level)
421{
422    if (new_level != 0xFF)
423        nfa_cho_cb.trace_level = new_level;
424
425    return (nfa_cho_cb.trace_level);
426}
427
428#if (defined (NFA_CHO_TEST_INCLUDED) && (NFA_CHO_TEST_INCLUDED == TRUE))
429/*******************************************************************************
430**
431** Function         NFA_ChoSetTestParam
432**
433** Description      This function is called to set test parameters.
434**
435*******************************************************************************/
436void NFA_ChoSetTestParam (UINT8        test_enable,
437                          UINT8        test_version,
438                          UINT16       test_random_number)
439{
440    nfa_cho_cb.test_enabled         = test_enable;
441    nfa_cho_cb.test_version         = test_version;
442    nfa_cho_cb.test_random_number   = test_random_number;
443}
444#endif
445