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