1/******************************************************************************
2 *
3 *  Copyright (C) 2010-2014 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 *  NFA interface to LLCP
23 *
24 ******************************************************************************/
25#include <string.h>
26#include "nfc_api.h"
27#include "nfa_sys.h"
28#include "nfa_sys_int.h"
29#include "llcp_defs.h"
30#include "llcp_api.h"
31#include "nfa_p2p_api.h"
32#include "nfa_p2p_int.h"
33
34/*****************************************************************************
35**  Constants
36*****************************************************************************/
37
38/*******************************************************************************
39**
40** Function         NFA_P2pRegisterServer
41**
42** Description      This function is called to listen to a SAP as server on LLCP.
43**
44**                  NFA_P2P_REG_SERVER_EVT will be returned with status and handle.
45**
46**                  If server_sap is set to NFA_P2P_ANY_SAP, then NFA will allocate
47**                  a SAP between LLCP_LOWER_BOUND_SDP_SAP and LLCP_UPPER_BOUND_SDP_SAP
48**                  Otherwise, server_sap must be between (LLCP_SDP_SAP + 1) and
49**                  LLCP_UPPER_BOUND_SDP_SAP
50**
51**                  link_type : NFA_P2P_LLINK_TYPE and/or NFA_P2P_DLINK_TYPE
52**
53** Note:            If RF discovery is started, NFA_StopRfDiscovery()/NFA_RF_DISCOVERY_STOPPED_EVT
54**                  should happen before calling this function
55**
56** Returns          NFA_STATUS_OK if successfully initiated
57**                  NFA_STATUS_FAILED otherwise
58**
59*******************************************************************************/
60tNFA_STATUS NFA_P2pRegisterServer (UINT8              server_sap,
61                                   tNFA_P2P_LINK_TYPE link_type,
62                                   char               *p_service_name,
63                                   tNFA_P2P_CBACK     *p_cback)
64{
65    tNFA_P2P_API_REG_SERVER *p_msg;
66
67    P2P_TRACE_API3 ("NFA_P2pRegisterServer (): server_sap:0x%02x, link_type:0x%x, SN:<%s>",
68                     server_sap, link_type, p_service_name);
69
70    if (  (server_sap != NFA_P2P_ANY_SAP)
71        &&((server_sap <= LLCP_SAP_SDP) ||(server_sap > LLCP_UPPER_BOUND_SDP_SAP))  )
72    {
73        P2P_TRACE_ERROR2 ("NFA_P2pRegisterServer (): server_sap must be between %d and %d",
74                          LLCP_SAP_SDP + 1, LLCP_UPPER_BOUND_SDP_SAP);
75        return (NFA_STATUS_FAILED);
76    }
77    else if (  ((link_type & NFA_P2P_LLINK_TYPE) == 0x00)
78             &&((link_type & NFA_P2P_DLINK_TYPE) == 0x00)  )
79    {
80        P2P_TRACE_ERROR1 ("NFA_P2pRegisterServer(): link type (0x%x) must be specified", link_type);
81        return (NFA_STATUS_FAILED);
82    }
83
84    if ((p_msg = (tNFA_P2P_API_REG_SERVER *) GKI_getbuf (sizeof (tNFA_P2P_API_REG_SERVER))) != NULL)
85    {
86        p_msg->hdr.event = NFA_P2P_API_REG_SERVER_EVT;
87
88        p_msg->server_sap = server_sap;
89        p_msg->link_type  = link_type;
90
91        BCM_STRNCPY_S (p_msg->service_name, sizeof (p_msg->service_name), p_service_name, LLCP_MAX_SN_LEN);
92        p_msg->service_name[LLCP_MAX_SN_LEN] = 0;
93
94        p_msg->p_cback = p_cback;
95
96        nfa_sys_sendmsg (p_msg);
97
98        return (NFA_STATUS_OK);
99    }
100
101    return (NFA_STATUS_FAILED);
102}
103
104/*******************************************************************************
105**
106** Function         NFA_P2pRegisterClient
107**
108** Description      This function is called to register a client service on LLCP.
109**
110**                  NFA_P2P_REG_CLIENT_EVT will be returned with status and handle.
111**
112**                  link_type : NFA_P2P_LLINK_TYPE and/or NFA_P2P_DLINK_TYPE
113**
114** Returns          NFA_STATUS_OK if successfully initiated
115**                  NFA_STATUS_FAILED otherwise
116**
117*******************************************************************************/
118tNFA_STATUS NFA_P2pRegisterClient (tNFA_P2P_LINK_TYPE link_type,
119                                   tNFA_P2P_CBACK     *p_cback)
120{
121    tNFA_P2P_API_REG_CLIENT *p_msg;
122
123    P2P_TRACE_API1 ("NFA_P2pRegisterClient (): link_type:0x%x", link_type);
124
125    if (  ((link_type & NFA_P2P_LLINK_TYPE) == 0x00)
126        &&((link_type & NFA_P2P_DLINK_TYPE) == 0x00)  )
127    {
128        P2P_TRACE_ERROR1 ("NFA_P2pRegisterClient (): link type (0x%x) must be specified", link_type);
129        return (NFA_STATUS_FAILED);
130    }
131
132    if ((p_msg = (tNFA_P2P_API_REG_CLIENT *) GKI_getbuf (sizeof (tNFA_P2P_API_REG_CLIENT))) != NULL)
133    {
134        p_msg->hdr.event = NFA_P2P_API_REG_CLIENT_EVT;
135
136        p_msg->p_cback   = p_cback;
137        p_msg->link_type = link_type;
138
139        nfa_sys_sendmsg (p_msg);
140
141        return (NFA_STATUS_OK);
142    }
143
144    return (NFA_STATUS_FAILED);
145}
146
147/*******************************************************************************
148**
149** Function         NFA_P2pDeregister
150**
151** Description      This function is called to stop listening to a SAP as server
152**                  or stop client service on LLCP.
153**
154** Note:            If this function is called to de-register a server and RF discovery
155**                  is started, NFA_StopRfDiscovery()/NFA_RF_DISCOVERY_STOPPED_EVT
156**                  should happen before calling this function
157**
158** Returns          NFA_STATUS_OK if successfully initiated
159**                  NFA_STATUS_BAD_HANDLE if handle is not valid
160**                  NFA_STATUS_FAILED otherwise
161**
162*******************************************************************************/
163tNFA_STATUS NFA_P2pDeregister (tNFA_HANDLE handle)
164{
165    tNFA_P2P_API_DEREG *p_msg;
166    tNFA_HANDLE         xx;
167
168    P2P_TRACE_API1 ("NFA_P2pDeregister (): handle:0x%02X", handle);
169
170    xx = handle & NFA_HANDLE_MASK;
171
172    if (  (xx >= NFA_P2P_NUM_SAP)
173        ||(nfa_p2p_cb.sap_cb[xx].p_cback == NULL)  )
174    {
175        P2P_TRACE_ERROR0 ("NFA_P2pDeregister (): Handle is invalid or not registered");
176        return (NFA_STATUS_BAD_HANDLE);
177    }
178
179    if ((p_msg = (tNFA_P2P_API_DEREG *) GKI_getbuf (sizeof (tNFA_P2P_API_DEREG))) != NULL)
180    {
181        p_msg->hdr.event = NFA_P2P_API_DEREG_EVT;
182
183        p_msg->handle    = handle;
184
185        nfa_sys_sendmsg (p_msg);
186
187        return (NFA_STATUS_OK);
188    }
189
190    return (NFA_STATUS_FAILED);
191}
192
193/*******************************************************************************
194**
195** Function         NFA_P2pAcceptConn
196**
197** Description      This function is called to accept a request of data link
198**                  connection to a listening SAP on LLCP after receiving
199**                  NFA_P2P_CONN_REQ_EVT.
200**
201** Returns          NFA_STATUS_OK if successfully initiated
202**                  NFA_STATUS_BAD_HANDLE if handle is not valid
203**                  NFA_STATUS_FAILED otherwise
204**
205*******************************************************************************/
206tNFA_STATUS NFA_P2pAcceptConn (tNFA_HANDLE handle,
207                               UINT16      miu,
208                               UINT8       rw)
209{
210    tNFA_P2P_API_ACCEPT_CONN *p_msg;
211    tNFA_HANDLE               xx;
212
213    P2P_TRACE_API3 ("NFA_P2pAcceptConn (): handle:0x%02X, MIU:%d, RW:%d", handle, miu, rw);
214
215    xx = handle & NFA_HANDLE_MASK;
216
217    if (!(xx & NFA_P2P_HANDLE_FLAG_CONN))
218    {
219        P2P_TRACE_ERROR0 ("NFA_P2pAcceptConn (): Connection Handle is not valid");
220        return (NFA_STATUS_BAD_HANDLE);
221    }
222    else
223    {
224        xx &= ~NFA_P2P_HANDLE_FLAG_CONN;
225    }
226
227    if (  (xx >= LLCP_MAX_DATA_LINK)
228        ||(nfa_p2p_cb.conn_cb[xx].flags == 0)  )
229    {
230        P2P_TRACE_ERROR0 ("NFA_P2pAcceptConn (): Connection Handle is not valid");
231        return (NFA_STATUS_BAD_HANDLE);
232    }
233
234    if ((miu < LLCP_DEFAULT_MIU) || (nfa_p2p_cb.local_link_miu < miu))
235    {
236        P2P_TRACE_ERROR3 ("NFA_P2pAcceptConn (): MIU(%d) must be between %d and %d",
237                            miu, LLCP_DEFAULT_MIU, nfa_p2p_cb.local_link_miu);
238    }
239    else if ((p_msg = (tNFA_P2P_API_ACCEPT_CONN *) GKI_getbuf (sizeof (tNFA_P2P_API_ACCEPT_CONN))) != NULL)
240    {
241        p_msg->hdr.event = NFA_P2P_API_ACCEPT_CONN_EVT;
242
243        p_msg->conn_handle  = handle;
244        p_msg->miu          = miu;
245        p_msg->rw           = rw;
246
247        nfa_sys_sendmsg (p_msg);
248
249        return (NFA_STATUS_OK);
250    }
251
252    return (NFA_STATUS_FAILED);
253}
254
255/*******************************************************************************
256**
257** Function         NFA_P2pRejectConn
258**
259** Description      This function is called to reject a request of data link
260**                  connection to a listening SAP on LLCP after receiving
261**                  NFA_P2P_CONN_REQ_EVT.
262**
263** Returns          NFA_STATUS_OK if successfully initiated
264**                  NFA_STATUS_BAD_HANDLE if handle is not valid
265**                  NFA_STATUS_FAILED otherwise
266**
267*******************************************************************************/
268tNFA_STATUS NFA_P2pRejectConn (tNFA_HANDLE handle)
269{
270    tNFA_P2P_API_REJECT_CONN *p_msg;
271    tNFA_HANDLE               xx;
272
273    P2P_TRACE_API1 ("NFA_P2pRejectConn (): handle:0x%02X", handle);
274
275    xx = handle & NFA_HANDLE_MASK;
276
277    if (!(xx & NFA_P2P_HANDLE_FLAG_CONN))
278    {
279        P2P_TRACE_ERROR0 ("NFA_P2pRejectConn (): Connection Handle is not valid");
280        return (NFA_STATUS_BAD_HANDLE);
281    }
282    else
283    {
284        xx &= ~NFA_P2P_HANDLE_FLAG_CONN;
285    }
286
287    if (  (xx >= LLCP_MAX_DATA_LINK)
288        ||(nfa_p2p_cb.conn_cb[xx].flags == 0)  )
289    {
290        P2P_TRACE_ERROR0 ("NFA_P2pRejectConn (): Connection Handle is not valid");
291        return (NFA_STATUS_BAD_HANDLE);
292    }
293
294    if ((p_msg = (tNFA_P2P_API_REJECT_CONN *) GKI_getbuf (sizeof (tNFA_P2P_API_REJECT_CONN))) != NULL)
295    {
296        p_msg->hdr.event = NFA_P2P_API_REJECT_CONN_EVT;
297
298        p_msg->conn_handle  = handle;
299
300        nfa_sys_sendmsg (p_msg);
301
302        return (NFA_STATUS_OK);
303    }
304
305    return (NFA_STATUS_FAILED);
306}
307
308/*******************************************************************************
309**
310** Function         NFA_P2pDisconnect
311**
312** Description      This function is called to disconnect an existing or
313**                  connecting data link connection.
314**
315**                  discard any pending data on data link connection if flush is set to TRUE
316**
317**                  NFA_P2P_DISC_EVT will be returned after data link connection is disconnected
318**
319** Returns          NFA_STATUS_OK if successfully initiated
320**                  NFA_STATUS_BAD_HANDLE if handle is not valid
321**                  NFA_STATUS_FAILED otherwise
322**
323*******************************************************************************/
324tNFA_STATUS NFA_P2pDisconnect (tNFA_HANDLE handle, BOOLEAN flush)
325{
326    tNFA_P2P_API_DISCONNECT *p_msg;
327    tNFA_HANDLE              xx;
328
329    P2P_TRACE_API2 ("NFA_P2pDisconnect (): handle:0x%02X, flush=%d", handle, flush);
330
331    xx = handle & NFA_HANDLE_MASK;
332
333    if (xx & NFA_P2P_HANDLE_FLAG_CONN)
334    {
335        xx &= ~NFA_P2P_HANDLE_FLAG_CONN;
336
337        if (  (xx >= LLCP_MAX_DATA_LINK)
338            ||(nfa_p2p_cb.conn_cb[xx].flags == 0)  )
339        {
340            P2P_TRACE_ERROR0 ("NFA_P2pDisconnect (): Connection Handle is not valid");
341            return (NFA_STATUS_BAD_HANDLE);
342        }
343    }
344    else
345    {
346        P2P_TRACE_ERROR0 ("NFA_P2pDisconnect (): Handle is not valid");
347        return (NFA_STATUS_BAD_HANDLE);
348    }
349
350    if ((p_msg = (tNFA_P2P_API_DISCONNECT *) GKI_getbuf (sizeof (tNFA_P2P_API_DISCONNECT))) != NULL)
351    {
352        p_msg->hdr.event = NFA_P2P_API_DISCONNECT_EVT;
353
354        p_msg->conn_handle  = handle;
355        p_msg->flush        = flush;
356
357        nfa_sys_sendmsg (p_msg);
358
359        return (NFA_STATUS_OK);
360    }
361
362    return (NFA_STATUS_FAILED);
363}
364
365/*******************************************************************************
366**
367** Function         NFA_P2pConnectByName
368**
369** Description      This function is called to create a connection-oriented transport
370**                  by a service name.
371**                  NFA_P2P_CONNECTED_EVT if success
372**                  NFA_P2P_DISC_EVT if failed
373**
374** Returns          NFA_STATUS_OK if successfully initiated
375**                  NFA_STATUS_BAD_HANDLE if client is not registered
376**                  NFA_STATUS_FAILED otherwise
377**
378*******************************************************************************/
379tNFA_STATUS NFA_P2pConnectByName (tNFA_HANDLE client_handle,
380                                  char        *p_service_name,
381                                  UINT16      miu,
382                                  UINT8       rw)
383{
384    tNFA_P2P_API_CONNECT *p_msg;
385    tNFA_HANDLE           xx;
386
387    P2P_TRACE_API4 ("NFA_P2pConnectByName (): client_handle:0x%x, SN:<%s>, MIU:%d, RW:%d",
388                    client_handle, p_service_name, miu, rw);
389
390    xx = client_handle & NFA_HANDLE_MASK;
391
392    if (  (xx >= NFA_P2P_NUM_SAP)
393        ||(nfa_p2p_cb.sap_cb[xx].p_cback == NULL)  )
394    {
395        P2P_TRACE_ERROR0 ("NFA_P2pConnectByName (): Client Handle is not valid");
396        return (NFA_STATUS_BAD_HANDLE);
397    }
398
399    if (  (miu < LLCP_DEFAULT_MIU)
400        ||(nfa_p2p_cb.llcp_state != NFA_P2P_LLCP_STATE_ACTIVATED)
401        ||(nfa_p2p_cb.local_link_miu < miu)  )
402    {
403        P2P_TRACE_ERROR3 ("NFA_P2pConnectByName (): MIU(%d) must be between %d and %d or LLCP link is not activated",
404                            miu, LLCP_DEFAULT_MIU, nfa_p2p_cb.local_link_miu);
405    }
406    else if ((p_msg = (tNFA_P2P_API_CONNECT *) GKI_getbuf (sizeof (tNFA_P2P_API_CONNECT))) != NULL)
407    {
408        p_msg->hdr.event = NFA_P2P_API_CONNECT_EVT;
409
410        BCM_STRNCPY_S (p_msg->service_name, sizeof (p_msg->service_name), p_service_name, LLCP_MAX_SN_LEN);
411        p_msg->service_name[LLCP_MAX_SN_LEN] = 0;
412
413        p_msg->dsap    = LLCP_INVALID_SAP;
414        p_msg->miu     = miu;
415        p_msg->rw      = rw;
416        p_msg->client_handle = client_handle;
417
418        nfa_sys_sendmsg (p_msg);
419
420        return (NFA_STATUS_OK);
421    }
422
423    return (NFA_STATUS_FAILED);
424}
425
426/*******************************************************************************
427**
428** Function         NFA_P2pConnectBySap
429**
430** Description      This function is called to create a connection-oriented transport
431**                  by a SAP.
432**                  NFA_P2P_CONNECTED_EVT if success
433**                  NFA_P2P_DISC_EVT if failed
434**
435** Returns          NFA_STATUS_OK if successfully initiated
436**                  NFA_STATUS_BAD_HANDLE if client is not registered
437**                  NFA_STATUS_FAILED otherwise
438**
439*******************************************************************************/
440tNFA_STATUS NFA_P2pConnectBySap (tNFA_HANDLE client_handle,
441                                 UINT8       dsap,
442                                 UINT16      miu,
443                                 UINT8       rw)
444{
445    tNFA_P2P_API_CONNECT *p_msg;
446    tNFA_HANDLE           xx;
447
448    P2P_TRACE_API4 ("NFA_P2pConnectBySap (): client_handle:0x%x, DSAP:0x%02X, MIU:%d, RW:%d",
449                    client_handle, dsap, miu, rw);
450
451    xx = client_handle & NFA_HANDLE_MASK;
452
453    if (  (xx >= NFA_P2P_NUM_SAP)
454        ||(nfa_p2p_cb.sap_cb[xx].p_cback == NULL)  )
455    {
456        P2P_TRACE_ERROR0 ("NFA_P2pConnectBySap (): Client Handle is not valid");
457        return (NFA_STATUS_BAD_HANDLE);
458    }
459
460    if (  (miu < LLCP_DEFAULT_MIU)
461        ||(nfa_p2p_cb.llcp_state != NFA_P2P_LLCP_STATE_ACTIVATED)
462        ||(nfa_p2p_cb.local_link_miu < miu)  )
463    {
464        P2P_TRACE_ERROR3 ("NFA_P2pConnectBySap (): MIU(%d) must be between %d and %d, or LLCP link is not activated",
465                            miu, LLCP_DEFAULT_MIU, nfa_p2p_cb.local_link_miu);
466    }
467    else if ((p_msg = (tNFA_P2P_API_CONNECT *) GKI_getbuf (sizeof (tNFA_P2P_API_CONNECT))) != NULL)
468    {
469        p_msg->hdr.event = NFA_P2P_API_CONNECT_EVT;
470
471        p_msg->service_name[LLCP_MAX_SN_LEN] = 0;
472
473        p_msg->dsap    = dsap;
474        p_msg->miu     = miu;
475        p_msg->rw      = rw;
476        p_msg->client_handle = client_handle;
477
478        nfa_sys_sendmsg (p_msg);
479
480        return (NFA_STATUS_OK);
481    }
482
483    return (NFA_STATUS_FAILED);
484}
485
486/*******************************************************************************
487**
488** Function         NFA_P2pSendUI
489**
490** Description      This function is called to send data on connectionless
491**                  transport.
492**
493** Returns          NFA_STATUS_OK if successfully initiated
494**                  NFA_STATUS_BAD_HANDLE if handle is not valid
495**                  NFA_STATUS_BAD_LENGTH if data length is more than remote link MIU
496**                  NFA_STATUS_CONGESTED  if congested
497**                  NFA_STATUS_FAILED otherwise
498**
499*******************************************************************************/
500tNFA_STATUS NFA_P2pSendUI (tNFA_HANDLE handle,
501                           UINT8       dsap,
502                           UINT16      length,
503                           UINT8      *p_data)
504{
505    tNFA_P2P_API_SEND_UI *p_msg;
506    tNFA_STATUS           ret_status = NFA_STATUS_FAILED;
507    tNFA_HANDLE           xx;
508
509    P2P_TRACE_API3 ("NFA_P2pSendUI (): handle:0x%X, DSAP:0x%02X, length:%d", handle, dsap, length);
510
511    GKI_sched_lock ();
512
513    xx = handle & NFA_HANDLE_MASK;
514
515    if (  (xx >= NFA_P2P_NUM_SAP)
516        ||(nfa_p2p_cb.sap_cb[xx].p_cback == NULL))
517    {
518        P2P_TRACE_ERROR1 ("NFA_P2pSendUI (): Handle (0x%X) is not valid", handle);
519        ret_status = NFA_STATUS_BAD_HANDLE;
520    }
521    else if (length > nfa_p2p_cb.remote_link_miu)
522    {
523        P2P_TRACE_ERROR3 ("NFA_P2pSendUI (): handle:0x%X, length(%d) must be less than remote link MIU(%d)",
524                           handle, length, nfa_p2p_cb.remote_link_miu);
525        ret_status = NFA_STATUS_BAD_LENGTH;
526    }
527    else if (nfa_p2p_cb.sap_cb[xx].flags & NFA_P2P_SAP_FLAG_LLINK_CONGESTED)
528    {
529        P2P_TRACE_WARNING1 ("NFA_P2pSendUI (): handle:0x%X, logical data link is already congested",
530                             handle);
531        ret_status = NFA_STATUS_CONGESTED;
532    }
533    else if (LLCP_IsLogicalLinkCongested ((UINT8)xx,
534                                          nfa_p2p_cb.sap_cb[xx].num_pending_ui_pdu,
535                                          nfa_p2p_cb.total_pending_ui_pdu,
536                                          nfa_p2p_cb.total_pending_i_pdu))
537    {
538        nfa_p2p_cb.sap_cb[xx].flags |= NFA_P2P_SAP_FLAG_LLINK_CONGESTED;
539
540        P2P_TRACE_WARNING1 ("NFA_P2pSendUI(): handle:0x%X, logical data link is congested",
541                             handle);
542        ret_status = NFA_STATUS_CONGESTED;
543    }
544    else if ((p_msg = (tNFA_P2P_API_SEND_UI *) GKI_getbuf (sizeof(tNFA_P2P_API_SEND_UI))) != NULL)
545    {
546        p_msg->hdr.event = NFA_P2P_API_SEND_UI_EVT;
547
548        p_msg->handle  = handle;
549        p_msg->dsap    = dsap;
550
551        if ((p_msg->p_msg = (BT_HDR *) GKI_getpoolbuf (LLCP_POOL_ID)) != NULL)
552        {
553            p_msg->p_msg->len    = length;
554            p_msg->p_msg->offset = LLCP_MIN_OFFSET;
555            memcpy (((UINT8*) (p_msg->p_msg + 1) + p_msg->p_msg->offset), p_data, length);
556
557            /* increase number of tx UI PDU which is not processed by NFA for congestion control */
558            nfa_p2p_cb.sap_cb[xx].num_pending_ui_pdu++;
559            nfa_p2p_cb.total_pending_ui_pdu++;
560            nfa_sys_sendmsg (p_msg);
561
562            ret_status = NFA_STATUS_OK;
563        }
564        else
565        {
566            GKI_freebuf (p_msg);
567
568            nfa_p2p_cb.sap_cb[xx].flags |= NFA_P2P_SAP_FLAG_LLINK_CONGESTED;
569            ret_status = NFA_STATUS_CONGESTED;
570        }
571    }
572
573    GKI_sched_unlock ();
574
575    return (ret_status);
576}
577
578/*******************************************************************************
579**
580** Function         NFA_P2pReadUI
581**
582** Description      This function is called to read data on connectionless
583**                  transport when receiving NFA_P2P_DATA_EVT with NFA_P2P_LLINK_TYPE.
584**
585**                  - Remote SAP who sent UI PDU is returned.
586**                  - Information of UI PDU up to max_data_len is copied into p_data.
587**                  - If more information of UI PDU or more UI PDU in queue then more
588**                    is returned to TRUE.
589**                  - Information of next UI PDU is not concatenated.
590**
591** Returns          NFA_STATUS_OK if successfully initiated
592**                  NFA_STATUS_BAD_HANDLE if handle is not valid
593**
594*******************************************************************************/
595tNFA_STATUS NFA_P2pReadUI (tNFA_HANDLE handle,
596                           UINT32      max_data_len,
597                           UINT8       *p_remote_sap,
598                           UINT32      *p_data_len,
599                           UINT8       *p_data,
600                           BOOLEAN     *p_more)
601{
602    tNFA_STATUS ret_status;
603    tNFA_HANDLE xx;
604
605    P2P_TRACE_API1 ("NFA_P2pReadUI (): handle:0x%X", handle);
606
607    GKI_sched_lock ();
608
609    xx = handle & NFA_HANDLE_MASK;
610
611    if (  (xx >= NFA_P2P_NUM_SAP)
612        ||(nfa_p2p_cb.sap_cb[xx].p_cback == NULL)  )
613    {
614        P2P_TRACE_ERROR1 ("NFA_P2pReadUI (): Handle (0x%X) is not valid", handle);
615        ret_status = NFA_STATUS_BAD_HANDLE;
616    }
617    else
618    {
619        *p_more = LLCP_ReadLogicalLinkData ((UINT8)xx,
620                                            max_data_len,
621                                            p_remote_sap,
622                                            p_data_len,
623                                            p_data);
624        ret_status = NFA_STATUS_OK;
625    }
626
627    GKI_sched_unlock ();
628
629    return (ret_status);
630}
631
632/*******************************************************************************
633**
634** Function         NFA_P2pFlushUI
635**
636** Description      This function is called to flush data on connectionless
637**                  transport.
638**
639** Returns          NFA_STATUS_OK if successfully initiated
640**                  NFA_STATUS_BAD_HANDLE if handle is not valid
641**
642*******************************************************************************/
643tNFA_STATUS NFA_P2pFlushUI (tNFA_HANDLE handle,
644                            UINT32      *p_length)
645{
646    tNFA_STATUS ret_status;
647    tNFA_HANDLE xx;
648
649    P2P_TRACE_API1 ("NFA_P2pReadUI (): handle:0x%X", handle);
650
651    GKI_sched_lock ();
652
653    xx = handle & NFA_HANDLE_MASK;
654
655    if (  (xx >= NFA_P2P_NUM_SAP)
656        ||(nfa_p2p_cb.sap_cb[xx].p_cback == NULL)  )
657    {
658        P2P_TRACE_ERROR1 ("NFA_P2pFlushUI (): Handle (0x%X) is not valid", handle);
659        ret_status = NFA_STATUS_BAD_HANDLE;
660        *p_length  = 0;
661    }
662    else
663    {
664        *p_length  = LLCP_FlushLogicalLinkRxData ((UINT8)xx);
665        ret_status = NFA_STATUS_OK;
666    }
667
668    GKI_sched_unlock ();
669
670    return (ret_status);
671}
672
673/*******************************************************************************
674**
675** Function         NFA_P2pSendData
676**
677** Description      This function is called to send data on connection-oriented
678**                  transport.
679**
680** Returns          NFA_STATUS_OK if successfully initiated
681**                  NFA_STATUS_BAD_HANDLE if handle is not valid
682**                  NFA_STATUS_BAD_LENGTH if data length is more than remote MIU
683**                  NFA_STATUS_CONGESTED  if congested
684**                  NFA_STATUS_FAILED otherwise
685**
686*******************************************************************************/
687tNFA_STATUS NFA_P2pSendData (tNFA_HANDLE handle,
688                             UINT16      length,
689                             UINT8      *p_data)
690{
691    tNFA_P2P_API_SEND_DATA *p_msg;
692    tNFA_STATUS            ret_status = NFA_STATUS_FAILED;
693    tNFA_HANDLE            xx;
694
695    P2P_TRACE_API2 ("NFA_P2pSendData (): handle:0x%X, length:%d", handle, length);
696
697    GKI_sched_lock ();
698
699    xx = handle & NFA_HANDLE_MASK;
700    xx &= ~NFA_P2P_HANDLE_FLAG_CONN;
701
702    if (  (!(handle & NFA_P2P_HANDLE_FLAG_CONN))
703        ||(xx >= LLCP_MAX_DATA_LINK)
704        ||(nfa_p2p_cb.conn_cb[xx].flags == 0)  )
705    {
706        P2P_TRACE_ERROR1 ("NFA_P2pSendData (): Handle(0x%X) is not valid", handle);
707        ret_status = NFA_STATUS_BAD_HANDLE;
708    }
709    else if (nfa_p2p_cb.conn_cb[xx].flags & NFA_P2P_CONN_FLAG_REMOTE_RW_ZERO)
710    {
711        P2P_TRACE_ERROR1 ("NFA_P2pSendData (): handle:0x%X, Remote set RW to 0 (flow off)", handle);
712        ret_status = NFA_STATUS_FAILED;
713    }
714    else if (nfa_p2p_cb.conn_cb[xx].remote_miu < length)
715    {
716        P2P_TRACE_ERROR2 ("NFA_P2pSendData (): handle:0x%X, Data more than remote MIU(%d)",
717                           handle, nfa_p2p_cb.conn_cb[xx].remote_miu);
718        ret_status = NFA_STATUS_BAD_LENGTH;
719    }
720    else if (nfa_p2p_cb.conn_cb[xx].flags & NFA_P2P_CONN_FLAG_CONGESTED)
721    {
722        P2P_TRACE_WARNING1 ("NFA_P2pSendData (): handle:0x%X, data link connection is already congested",
723                            handle);
724        ret_status = NFA_STATUS_CONGESTED;
725    }
726    else if (LLCP_IsDataLinkCongested (nfa_p2p_cb.conn_cb[xx].local_sap,
727                                       nfa_p2p_cb.conn_cb[xx].remote_sap,
728                                       nfa_p2p_cb.conn_cb[xx].num_pending_i_pdu,
729                                       nfa_p2p_cb.total_pending_ui_pdu,
730                                       nfa_p2p_cb.total_pending_i_pdu))
731    {
732        nfa_p2p_cb.conn_cb[xx].flags |= NFA_P2P_CONN_FLAG_CONGESTED;
733
734        P2P_TRACE_WARNING1 ("NFA_P2pSendData (): handle:0x%X, data link connection is congested",
735                            handle);
736        ret_status = NFA_STATUS_CONGESTED;
737    }
738    else if ((p_msg = (tNFA_P2P_API_SEND_DATA *) GKI_getbuf (sizeof(tNFA_P2P_API_SEND_DATA))) != NULL)
739    {
740        p_msg->hdr.event = NFA_P2P_API_SEND_DATA_EVT;
741
742        p_msg->conn_handle  = handle;
743
744        if ((p_msg->p_msg = (BT_HDR *) GKI_getpoolbuf (LLCP_POOL_ID)) != NULL)
745        {
746            p_msg->p_msg->len    = length;
747            p_msg->p_msg->offset = LLCP_MIN_OFFSET;
748            memcpy (((UINT8*) (p_msg->p_msg + 1) + p_msg->p_msg->offset), p_data, length);
749
750            /* increase number of tx I PDU which is not processed by NFA for congestion control */
751            nfa_p2p_cb.conn_cb[xx].num_pending_i_pdu++;
752            nfa_p2p_cb.total_pending_i_pdu++;
753            nfa_sys_sendmsg (p_msg);
754
755            ret_status = NFA_STATUS_OK;
756        }
757        else
758        {
759            GKI_freebuf (p_msg);
760            nfa_p2p_cb.conn_cb[xx].flags |= NFA_P2P_CONN_FLAG_CONGESTED;
761            ret_status = NFA_STATUS_CONGESTED;
762        }
763    }
764
765    GKI_sched_unlock ();
766
767    return (ret_status);
768}
769
770/*******************************************************************************
771**
772** Function         NFA_P2pReadData
773**
774** Description      This function is called to read data on connection-oriented
775**                  transport when receiving NFA_P2P_DATA_EVT with NFA_P2P_DLINK_TYPE.
776**
777**                  - Information of I PDU is copied into p_data up to max_data_len.
778**                  - If more information of I PDU or more I PDU in queue, then more
779**                    is returned to TRUE.
780**                  - Information of next I PDU is not concatenated.
781**
782** Returns          NFA_STATUS_OK if successfully initiated
783**                  NFA_STATUS_BAD_HANDLE if handle is not valid
784**
785*******************************************************************************/
786tNFA_STATUS NFA_P2pReadData (tNFA_HANDLE handle,
787                             UINT32      max_data_len,
788                             UINT32      *p_data_len,
789                             UINT8       *p_data,
790                             BOOLEAN     *p_more)
791{
792    tNFA_STATUS ret_status;
793    tNFA_HANDLE xx;
794
795    P2P_TRACE_API1 ("NFA_P2pReadData (): handle:0x%X", handle);
796
797    GKI_sched_lock ();
798
799    xx = handle & NFA_HANDLE_MASK;
800    xx &= ~NFA_P2P_HANDLE_FLAG_CONN;
801
802    if (  (!(handle & NFA_P2P_HANDLE_FLAG_CONN))
803        ||(xx >= LLCP_MAX_DATA_LINK)
804        ||(nfa_p2p_cb.conn_cb[xx].flags == 0)  )
805    {
806        P2P_TRACE_ERROR1 ("NFA_P2pReadData (): Handle(0x%X) is not valid", handle);
807        ret_status = NFA_STATUS_BAD_HANDLE;
808    }
809    else
810    {
811        *p_more = LLCP_ReadDataLinkData (nfa_p2p_cb.conn_cb[xx].local_sap,
812                                         nfa_p2p_cb.conn_cb[xx].remote_sap,
813                                         max_data_len,
814                                         p_data_len,
815                                         p_data);
816        ret_status = NFA_STATUS_OK;
817    }
818
819    GKI_sched_unlock ();
820
821    return (ret_status);
822}
823
824/*******************************************************************************
825**
826** Function         NFA_P2pFlushData
827**
828** Description      This function is called to flush data on connection-oriented
829**                  transport.
830**
831** Returns          NFA_STATUS_OK if successfully initiated
832**                  NFA_STATUS_BAD_HANDLE if handle is not valid
833**
834*******************************************************************************/
835tNFA_STATUS NFA_P2pFlushData (tNFA_HANDLE handle,
836                              UINT32      *p_length)
837{
838    tNFA_STATUS ret_status;
839    tNFA_HANDLE xx;
840
841    P2P_TRACE_API1 ("NFA_P2pFlushData (): handle:0x%X", handle);
842
843    GKI_sched_lock ();
844
845    xx = handle & NFA_HANDLE_MASK;
846    xx &= ~NFA_P2P_HANDLE_FLAG_CONN;
847
848    if (  (!(handle & NFA_P2P_HANDLE_FLAG_CONN))
849        ||(xx >= LLCP_MAX_DATA_LINK)
850        ||(nfa_p2p_cb.conn_cb[xx].flags == 0)  )
851    {
852        P2P_TRACE_ERROR1 ("NFA_P2pFlushData (): Handle(0x%X) is not valid", handle);
853        ret_status = NFA_STATUS_BAD_HANDLE;
854    }
855    else
856    {
857        *p_length = LLCP_FlushDataLinkRxData (nfa_p2p_cb.conn_cb[xx].local_sap,
858                                              nfa_p2p_cb.conn_cb[xx].remote_sap);
859        ret_status = NFA_STATUS_OK;
860    }
861
862    GKI_sched_unlock ();
863
864    return (ret_status);
865}
866
867/*******************************************************************************
868**
869** Function         NFA_P2pSetLocalBusy
870**
871** Description      This function is called to stop or resume incoming data on
872**                  connection-oriented transport.
873**
874** Returns          NFA_STATUS_OK if successfully initiated
875**                  NFA_STATUS_BAD_HANDLE if handle is not valid
876**                  NFA_STATUS_FAILED otherwise
877**
878*******************************************************************************/
879tNFA_STATUS NFA_P2pSetLocalBusy (tNFA_HANDLE conn_handle,
880                                 BOOLEAN     is_busy)
881{
882    tNFA_P2P_API_SET_LOCAL_BUSY *p_msg;
883    tNFA_HANDLE                  xx;
884
885    P2P_TRACE_API2 ("NFA_P2pSetLocalBusy (): conn_handle:0x%02X, is_busy:%d", conn_handle, is_busy);
886
887    xx = conn_handle & NFA_HANDLE_MASK;
888
889    if (!(xx & NFA_P2P_HANDLE_FLAG_CONN))
890    {
891        P2P_TRACE_ERROR0 ("NFA_P2pSetLocalBusy (): Connection Handle is not valid");
892        return (NFA_STATUS_BAD_HANDLE);
893    }
894    else
895    {
896        xx &= ~NFA_P2P_HANDLE_FLAG_CONN;
897    }
898
899    if (  (xx >= LLCP_MAX_DATA_LINK)
900        ||(nfa_p2p_cb.conn_cb[xx].flags == 0)  )
901    {
902        P2P_TRACE_ERROR0 ("NFA_P2pSetLocalBusy (): Connection Handle is not valid");
903        return (NFA_STATUS_BAD_HANDLE);
904    }
905
906    if ((p_msg = (tNFA_P2P_API_SET_LOCAL_BUSY *) GKI_getbuf (sizeof (tNFA_P2P_API_SET_LOCAL_BUSY))) != NULL)
907    {
908        p_msg->hdr.event = NFA_P2P_API_SET_LOCAL_BUSY_EVT;
909
910        p_msg->conn_handle = conn_handle;
911        p_msg->is_busy     = is_busy;
912
913        nfa_sys_sendmsg (p_msg);
914
915        return (NFA_STATUS_OK);
916    }
917
918    return (NFA_STATUS_FAILED);
919}
920
921/*******************************************************************************
922**
923** Function         NFA_P2pGetLinkInfo
924**
925** Description      This function is called to get local/remote link MIU and
926**                  Well-Known Service list encoded as a 16-bit field of connected LLCP.
927**                  NFA_P2P_LINK_INFO_EVT will be returned.
928**
929** Returns          NFA_STATUS_OK if successfully initiated
930**                  NFA_STATUS_BAD_HANDLE if server or client is not registered
931**                  NFA_STATUS_FAILED otherwise
932**
933*******************************************************************************/
934tNFA_STATUS NFA_P2pGetLinkInfo (tNFA_HANDLE handle)
935{
936    tNFA_P2P_API_GET_LINK_INFO *p_msg;
937    tNFA_HANDLE                 xx;
938
939    P2P_TRACE_API1 ("NFA_P2pGetLinkInfo (): handle:0x%x", handle);
940
941    if (nfa_p2p_cb.llcp_state != NFA_P2P_LLCP_STATE_ACTIVATED)
942    {
943        P2P_TRACE_ERROR0 ("NFA_P2pGetLinkInfo (): LLCP link is not activated");
944        return (NFA_STATUS_FAILED);
945    }
946
947    xx = handle & NFA_HANDLE_MASK;
948
949    if (  (xx >= NFA_P2P_NUM_SAP)
950        ||(nfa_p2p_cb.sap_cb[xx].p_cback == NULL)  )
951    {
952        P2P_TRACE_ERROR0 ("NFA_P2pGetLinkInfo (): Handle is invalid or not registered");
953        return (NFA_STATUS_BAD_HANDLE);
954    }
955
956    if ((p_msg = (tNFA_P2P_API_GET_LINK_INFO *) GKI_getbuf (sizeof (tNFA_P2P_API_GET_LINK_INFO))) != NULL)
957    {
958        p_msg->hdr.event = NFA_P2P_API_GET_LINK_INFO_EVT;
959
960        p_msg->handle = handle;
961
962        nfa_sys_sendmsg (p_msg);
963
964        return (NFA_STATUS_OK);
965    }
966
967    return (NFA_STATUS_FAILED);
968}
969
970/*******************************************************************************
971**
972** Function         NFA_P2pGetRemoteSap
973**
974** Description      This function is called to get SAP associated by service name
975**                  on connected remote LLCP.
976**                  NFA_P2P_SDP_EVT will be returned.
977**
978** Returns          NFA_STATUS_OK if successfully initiated
979**                  NFA_STATUS_BAD_HANDLE if server or client is not registered
980**                  NFA_STATUS_FAILED otherwise
981**
982*******************************************************************************/
983tNFA_STATUS NFA_P2pGetRemoteSap (tNFA_HANDLE handle,
984                                 char        *p_service_name)
985{
986    tNFA_P2P_API_GET_REMOTE_SAP *p_msg;
987    tNFA_HANDLE                  xx;
988
989    P2P_TRACE_API2 ("NFA_P2pGetRemoteSap(): handle:0x%x, SN:<%s>", handle, p_service_name);
990
991    if (nfa_p2p_cb.llcp_state != NFA_P2P_LLCP_STATE_ACTIVATED)
992    {
993        P2P_TRACE_ERROR0 ("NFA_P2pGetRemoteSap(): LLCP link is not activated");
994        return (NFA_STATUS_FAILED);
995    }
996
997    xx = handle & NFA_HANDLE_MASK;
998
999    if (  (xx >= NFA_P2P_NUM_SAP)
1000        ||(nfa_p2p_cb.sap_cb[xx].p_cback == NULL)  )
1001    {
1002        P2P_TRACE_ERROR0 ("NFA_P2pGetRemoteSap (): Handle is invalid or not registered");
1003        return (NFA_STATUS_BAD_HANDLE);
1004    }
1005
1006    if ((p_msg = (tNFA_P2P_API_GET_REMOTE_SAP *) GKI_getbuf (sizeof (tNFA_P2P_API_GET_REMOTE_SAP))) != NULL)
1007    {
1008        p_msg->hdr.event = NFA_P2P_API_GET_REMOTE_SAP_EVT;
1009
1010        p_msg->handle = handle;
1011
1012        BCM_STRNCPY_S (p_msg->service_name, sizeof (p_msg->service_name), p_service_name, LLCP_MAX_SN_LEN);
1013        p_msg->service_name[LLCP_MAX_SN_LEN] = 0;
1014
1015        nfa_sys_sendmsg (p_msg);
1016
1017        return (NFA_STATUS_OK);
1018    }
1019
1020    return (NFA_STATUS_FAILED);
1021}
1022
1023/*******************************************************************************
1024**
1025** Function         NFA_P2pSetLLCPConfig
1026**
1027** Description      This function is called to change LLCP config parameters.
1028**                  Application must call while LLCP is not activated.
1029**
1030**                  Parameters descriptions (default value)
1031**                  - Local Link MIU (LLCP_MIU)
1032**                  - Option parameter (LLCP_OPT_VALUE)
1033**                  - Response Waiting Time Index (LLCP_WAITING_TIME)
1034**                  - Local Link Timeout (LLCP_LTO_VALUE)
1035**                  - Inactivity Timeout as initiator role (LLCP_INIT_INACTIVITY_TIMEOUT)
1036**                  - Inactivity Timeout as target role (LLCP_TARGET_INACTIVITY_TIMEOUT)
1037**                  - Delay SYMM response (LLCP_DELAY_RESP_TIME)
1038**                  - Data link connection timeout (LLCP_DATA_LINK_CONNECTION_TOUT)
1039**                  - Delay timeout to send first PDU as initiator (LLCP_DELAY_TIME_TO_SEND_FIRST_PDU)
1040**
1041** Returns          NFA_STATUS_OK if successfully initiated
1042**                  NFA_STATUS_FAILED otherwise
1043**
1044*******************************************************************************/
1045tNFA_STATUS NFA_P2pSetLLCPConfig (UINT16 link_miu,
1046                                  UINT8  opt,
1047                                  UINT8  wt,
1048                                  UINT16 link_timeout,
1049                                  UINT16 inact_timeout_init,
1050                                  UINT16 inact_timeout_target,
1051                                  UINT16 symm_delay,
1052                                  UINT16 data_link_timeout,
1053                                  UINT16 delay_first_pdu_timeout)
1054{
1055    tNFA_P2P_API_SET_LLCP_CFG *p_msg;
1056
1057    P2P_TRACE_API4 ("NFA_P2pSetLLCPConfig ():link_miu:%d, opt:0x%02X, wt:%d, link_timeout:%d",
1058                     link_miu, opt, wt, link_timeout);
1059    P2P_TRACE_API4 ("                       inact_timeout(init:%d, target:%d), symm_delay:%d, data_link_timeout:%d",
1060                     inact_timeout_init, inact_timeout_target, symm_delay, data_link_timeout);
1061    P2P_TRACE_API1 ("                       delay_first_pdu_timeout:%d", delay_first_pdu_timeout);
1062
1063    if (nfa_p2p_cb.llcp_state == NFA_P2P_LLCP_STATE_ACTIVATED)
1064    {
1065        P2P_TRACE_ERROR0 ("NFA_P2pSetLLCPConfig (): LLCP link is activated");
1066        return (NFA_STATUS_FAILED);
1067    }
1068
1069    if ((p_msg = (tNFA_P2P_API_SET_LLCP_CFG *) GKI_getbuf (sizeof (tNFA_P2P_API_SET_LLCP_CFG))) != NULL)
1070    {
1071        p_msg->hdr.event = NFA_P2P_API_SET_LLCP_CFG_EVT;
1072
1073        p_msg->link_miu             = link_miu;
1074        p_msg->opt                  = opt;
1075        p_msg->wt                   = wt;
1076        p_msg->link_timeout         = link_timeout;
1077        p_msg->inact_timeout_init   = inact_timeout_init;
1078        p_msg->inact_timeout_target = inact_timeout_target;
1079        p_msg->symm_delay           = symm_delay;
1080        p_msg->data_link_timeout    = data_link_timeout;
1081        p_msg->delay_first_pdu_timeout = delay_first_pdu_timeout;
1082
1083        nfa_sys_sendmsg (p_msg);
1084
1085        return (NFA_STATUS_OK);
1086    }
1087
1088    return (NFA_STATUS_FAILED);
1089}
1090
1091/*******************************************************************************
1092**
1093** Function         NFA_P2pGetLLCPConfig
1094**
1095** Description      This function is called to read LLCP config parameters.
1096**
1097**                  Parameters descriptions
1098**                  - Local Link MIU
1099**                  - Option parameter
1100**                  - Response Waiting Time Index
1101**                  - Local Link Timeout
1102**                  - Inactivity Timeout as initiator role
1103**                  - Inactivity Timeout as target role
1104**                  - Delay SYMM response
1105**                  - Data link connection timeout
1106**                  - Delay timeout to send first PDU as initiator
1107**
1108** Returns          None
1109**
1110*******************************************************************************/
1111void NFA_P2pGetLLCPConfig (UINT16 *p_link_miu,
1112                           UINT8  *p_opt,
1113                           UINT8  *p_wt,
1114                           UINT16 *p_link_timeout,
1115                           UINT16 *p_inact_timeout_init,
1116                           UINT16 *p_inact_timeout_target,
1117                           UINT16 *p_symm_delay,
1118                           UINT16 *p_data_link_timeout,
1119                           UINT16 *p_delay_first_pdu_timeout)
1120{
1121    LLCP_GetConfig (p_link_miu,
1122                    p_opt,
1123                    p_wt,
1124                    p_link_timeout,
1125                    p_inact_timeout_init,
1126                    p_inact_timeout_target,
1127                    p_symm_delay,
1128                    p_data_link_timeout,
1129                    p_delay_first_pdu_timeout);
1130
1131    P2P_TRACE_API4 ("NFA_P2pGetLLCPConfig () link_miu:%d, opt:0x%02X, wt:%d, link_timeout:%d",
1132                     *p_link_miu, *p_opt, *p_wt, *p_link_timeout);
1133    P2P_TRACE_API4 ("                       inact_timeout(init:%d, target:%d), symm_delay:%d, data_link_timeout:%d",
1134                     *p_inact_timeout_init, *p_inact_timeout_target, *p_symm_delay, *p_data_link_timeout);
1135    P2P_TRACE_API1 ("                       delay_first_pdu_timeout:%d", *p_delay_first_pdu_timeout);
1136
1137}
1138
1139/*******************************************************************************
1140**
1141** Function         NFA_P2pSetTraceLevel
1142**
1143** Description      This function sets the trace level for P2P.  If called with
1144**                  a value of 0xFF, it simply returns the current trace level.
1145**
1146** Returns          The new or current trace level
1147**
1148*******************************************************************************/
1149UINT8 NFA_P2pSetTraceLevel (UINT8 new_level)
1150{
1151    if (new_level != 0xFF)
1152        nfa_p2p_cb.trace_level = new_level;
1153
1154    return (nfa_p2p_cb.trace_level);
1155}
1156
1157