blob: afb53f65887b284342105926722f326759a3e604 [file] [log] [blame]
The Android Open Source Project5738f832012-12-12 16:00:35 -08001/******************************************************************************
2 *
3 * Copyright (C) 2003-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 * This module contains action functions of the link control state machine.
22 *
23 ******************************************************************************/
24
25#include <string.h>
Chris Manton83e2c342014-09-29 21:37:44 -070026#include "bt_types.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080027#include "bt_target.h"
Mike J. Chen5cd8bff2014-01-31 18:16:59 -080028#include "bt_utils.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080029#include "avct_api.h"
30#include "avct_int.h"
Pavlin Radoslavov258c2532015-09-27 20:59:05 -070031#include "bt_common.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080032#include "btm_api.h"
Myles Watsond7ffd642016-10-27 10:27:36 -070033#include "osi/include/osi.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080034
35/* packet header length lookup table */
Marie Janssend19e0782016-07-15 12:48:27 -070036const uint8_t avct_lcb_pkt_type_len[] = {
The Android Open Source Project5738f832012-12-12 16:00:35 -080037 AVCT_HDR_LEN_SINGLE,
38 AVCT_HDR_LEN_START,
39 AVCT_HDR_LEN_CONT,
40 AVCT_HDR_LEN_END
41};
42
43/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -080044 *
45 * Function avct_lcb_msg_asmbl
46 *
47 * Description Reassemble incoming message.
48 *
49 *
50 * Returns Pointer to reassembled message; NULL if no message
51 * available.
52 *
53 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -080054static BT_HDR *avct_lcb_msg_asmbl(tAVCT_LCB *p_lcb, BT_HDR *p_buf)
55{
Marie Janssend19e0782016-07-15 12:48:27 -070056 uint8_t *p;
57 uint8_t pkt_type;
The Android Open Source Project5738f832012-12-12 16:00:35 -080058 BT_HDR *p_ret;
The Android Open Source Project5738f832012-12-12 16:00:35 -080059
60 /* parse the message header */
Marie Janssend19e0782016-07-15 12:48:27 -070061 p = (uint8_t *)(p_buf + 1) + p_buf->offset;
Avish Shaha408eb72016-06-22 06:47:20 +053062 pkt_type = AVCT_PKT_TYPE(p);
The Android Open Source Project5738f832012-12-12 16:00:35 -080063
64 /* quick sanity check on length */
65 if (p_buf->len < avct_lcb_pkt_type_len[pkt_type])
66 {
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -080067 osi_free(p_buf);
Sharvil Nanavati158084e2014-05-04 09:53:44 -070068 AVCT_TRACE_WARNING("Bad length during reassembly");
The Android Open Source Project5738f832012-12-12 16:00:35 -080069 p_ret = NULL;
70 }
71 /* single packet */
72 else if (pkt_type == AVCT_PKT_TYPE_SINGLE)
73 {
74 /* if reassembly in progress drop message and process new single */
75 if (p_lcb->p_rx_msg != NULL)
Sharvil Nanavati158084e2014-05-04 09:53:44 -070076 AVCT_TRACE_WARNING("Got single during reassembly");
Pavlin Radoslavov0a20dd42016-02-04 18:20:06 -080077
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -080078 osi_free_and_reset((void **)&p_lcb->p_rx_msg);
Pavlin Radoslavov0a20dd42016-02-04 18:20:06 -080079
The Android Open Source Project5738f832012-12-12 16:00:35 -080080 p_ret = p_buf;
81 }
82 /* start packet */
83 else if (pkt_type == AVCT_PKT_TYPE_START)
84 {
85 /* if reassembly in progress drop message and process new start */
86 if (p_lcb->p_rx_msg != NULL)
Sharvil Nanavati158084e2014-05-04 09:53:44 -070087 AVCT_TRACE_WARNING("Got start during reassembly");
Pavlin Radoslavov20524d32016-02-02 18:12:08 -080088
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -080089 osi_free(p_lcb->p_rx_msg);
Pavlin Radoslavov20524d32016-02-02 18:12:08 -080090
Pavlin Radoslavov0a20dd42016-02-04 18:20:06 -080091 /*
92 * Allocate bigger buffer for reassembly. As lower layers are
93 * not aware of possible packet size after reassembly, they
Mallikarjuna GB0d65d4c2013-11-10 13:30:25 +053094 * would have allocated smaller buffer.
95 */
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -080096 p_lcb->p_rx_msg = (BT_HDR *)osi_malloc(BT_DEFAULT_BUFFER_SIZE);
Pavlin Radoslavov0a20dd42016-02-04 18:20:06 -080097 memcpy(p_lcb->p_rx_msg, p_buf,
98 sizeof(BT_HDR) + p_buf->offset + p_buf->len);
The Android Open Source Project5738f832012-12-12 16:00:35 -080099
Pavlin Radoslavov0a20dd42016-02-04 18:20:06 -0800100 /* Free original buffer */
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800101 osi_free(p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800102
Pavlin Radoslavov0a20dd42016-02-04 18:20:06 -0800103 /* update p to point to new buffer */
Marie Janssend19e0782016-07-15 12:48:27 -0700104 p = (uint8_t *)(p_lcb->p_rx_msg + 1) + p_lcb->p_rx_msg->offset;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800105
Pavlin Radoslavov0a20dd42016-02-04 18:20:06 -0800106 /* copy first header byte over nosp */
107 *(p + 1) = *p;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800108
Pavlin Radoslavov0a20dd42016-02-04 18:20:06 -0800109 /* set offset to point to where to copy next */
110 p_lcb->p_rx_msg->offset += p_lcb->p_rx_msg->len;
111
112 /* adjust length for packet header */
113 p_lcb->p_rx_msg->len -= 1;
114
The Android Open Source Project5738f832012-12-12 16:00:35 -0800115 p_ret = NULL;
116 }
117 /* continue or end */
118 else
119 {
120 /* if no reassembly in progress drop message */
121 if (p_lcb->p_rx_msg == NULL)
122 {
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800123 osi_free(p_buf);
Sharvil Nanavati158084e2014-05-04 09:53:44 -0700124 AVCT_TRACE_WARNING("Pkt type=%d out of order", pkt_type);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800125 p_ret = NULL;
126 }
127 else
128 {
129 /* get size of buffer holding assembled message */
Pavlin Radoslavov0a20dd42016-02-04 18:20:06 -0800130 /*
131 * NOTE: The buffer is allocated above at the beginning of the
132 * reassembly, and is always of size BT_DEFAULT_BUFFER_SIZE.
133 */
Marie Janssend19e0782016-07-15 12:48:27 -0700134 uint16_t buf_len = BT_DEFAULT_BUFFER_SIZE - sizeof(BT_HDR);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800135
136 /* adjust offset and len of fragment for header byte */
137 p_buf->offset += AVCT_HDR_LEN_CONT;
138 p_buf->len -= AVCT_HDR_LEN_CONT;
139
140 /* verify length */
Pavlin Radoslavov0a20dd42016-02-04 18:20:06 -0800141 if ((p_lcb->p_rx_msg->offset + p_buf->len) > buf_len) {
The Android Open Source Project5738f832012-12-12 16:00:35 -0800142 /* won't fit; free everything */
Pavlin Radoslavov0a20dd42016-02-04 18:20:06 -0800143 AVCT_TRACE_WARNING("%s: Fragmented message too big!", __func__);
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800144 osi_free_and_reset((void **)&p_lcb->p_rx_msg);
145 osi_free(p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800146 p_ret = NULL;
Pavlin Radoslavov0a20dd42016-02-04 18:20:06 -0800147 } else {
The Android Open Source Project5738f832012-12-12 16:00:35 -0800148 /* copy contents of p_buf to p_rx_msg */
Marie Janssend19e0782016-07-15 12:48:27 -0700149 memcpy((uint8_t *)(p_lcb->p_rx_msg + 1) + p_lcb->p_rx_msg->offset,
150 (uint8_t *)(p_buf + 1) + p_buf->offset, p_buf->len);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800151
152 if (pkt_type == AVCT_PKT_TYPE_END)
153 {
154 p_lcb->p_rx_msg->offset -= p_lcb->p_rx_msg->len;
155 p_lcb->p_rx_msg->len += p_buf->len;
156 p_ret = p_lcb->p_rx_msg;
157 p_lcb->p_rx_msg = NULL;
158 }
159 else
160 {
161 p_lcb->p_rx_msg->offset += p_buf->len;
162 p_lcb->p_rx_msg->len += p_buf->len;
163 p_ret = NULL;
164 }
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800165 osi_free(p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800166 }
167 }
168 }
169 return p_ret;
170}
171
172
173/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800174 *
175 * Function avct_lcb_chnl_open
176 *
177 * Description Open L2CAP channel to peer
178 *
179 *
180 * Returns Nothing.
181 *
182 ******************************************************************************/
Myles Watsond35a6482016-10-27 08:52:16 -0700183void avct_lcb_chnl_open(tAVCT_LCB *p_lcb,
184 UNUSED_ATTR tAVCT_LCB_EVT *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800185{
Marie Janssend19e0782016-07-15 12:48:27 -0700186 uint16_t result = AVCT_RESULT_FAIL;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800187
188 BTM_SetOutService(p_lcb->peer_addr, BTM_SEC_SERVICE_AVCTP, 0);
189 /* call l2cap connect req */
190 p_lcb->ch_state = AVCT_CH_CONN;
Avish Shaha408eb72016-06-22 06:47:20 +0530191 p_lcb->ch_lcid = L2CA_ConnectReq(AVCT_PSM, p_lcb->peer_addr);
192 if (p_lcb->ch_lcid == 0)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800193 {
194 /* if connect req failed, send ourselves close event */
195 avct_lcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, (tAVCT_LCB_EVT *) &result);
196 }
197}
198
199/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800200 *
201 * Function avct_lcb_unbind_disc
202 *
203 * Description Deallocate ccb and call callback with disconnect event.
204 *
205 *
206 * Returns Nothing.
207 *
208 ******************************************************************************/
Myles Watsond35a6482016-10-27 08:52:16 -0700209void avct_lcb_unbind_disc(UNUSED_ATTR tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800210{
211 avct_ccb_dealloc(p_data->p_ccb, AVCT_DISCONNECT_CFM_EVT, 0, NULL);
212}
213
214/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800215 *
216 * Function avct_lcb_open_ind
217 *
218 * Description Handle an LL_OPEN event. For each allocated ccb already
219 * bound to this lcb, send a connect event. For each
220 * unbound ccb with a new PID, bind that ccb to this lcb and
221 * send a connect event.
222 *
223 *
224 * Returns Nothing.
225 *
226 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800227void avct_lcb_open_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
228{
229 tAVCT_CCB *p_ccb = &avct_cb.ccb[0];
230 int i;
Marie Janssend19e0782016-07-15 12:48:27 -0700231 bool bind = false;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800232
233 for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++)
234 {
235 /* if ccb allocated and */
236 if (p_ccb->allocated)
237 {
238 /* if bound to this lcb send connect confirm event */
239 if (p_ccb->p_lcb == p_lcb)
240 {
Marie Janssend19e0782016-07-15 12:48:27 -0700241 bind = true;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800242 L2CA_SetTxPriority(p_lcb->ch_lcid, L2CAP_CHNL_PRIORITY_HIGH);
243 p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_CONNECT_CFM_EVT,
244 0, p_lcb->peer_addr);
245 }
246 /* if unbound acceptor and lcb doesn't already have a ccb for this PID */
247 else if ((p_ccb->p_lcb == NULL) && (p_ccb->cc.role == AVCT_ACP) &&
248 (avct_lcb_has_pid(p_lcb, p_ccb->cc.pid) == NULL))
249 {
250 /* bind ccb to lcb and send connect ind event */
Marie Janssend19e0782016-07-15 12:48:27 -0700251 bind = true;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800252 p_ccb->p_lcb = p_lcb;
253 L2CA_SetTxPriority(p_lcb->ch_lcid, L2CAP_CHNL_PRIORITY_HIGH);
254 p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_CONNECT_IND_EVT,
255 0, p_lcb->peer_addr);
256 }
257 }
258 }
259
260 /* if no ccbs bound to this lcb, disconnect */
Marie Janssend19e0782016-07-15 12:48:27 -0700261 if (bind == false)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800262 {
263 avct_lcb_event(p_lcb, AVCT_LCB_INT_CLOSE_EVT, p_data);
264 }
265}
266
267/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800268 *
269 * Function avct_lcb_open_fail
270 *
271 * Description L2CAP channel open attempt failed. Deallocate any ccbs
272 * on this lcb and send connect confirm event with failure.
273 *
274 *
275 * Returns Nothing.
276 *
277 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800278void avct_lcb_open_fail(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
279{
280 tAVCT_CCB *p_ccb = &avct_cb.ccb[0];
281 int i;
282
283 for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++)
284 {
285 if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb))
286 {
287 avct_ccb_dealloc(p_ccb, AVCT_CONNECT_CFM_EVT,
288 p_data->result, p_lcb->peer_addr);
289 }
290 }
291}
292
293/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800294 *
295 * Function avct_lcb_close_ind
296 *
297 * Description L2CAP channel closed by peer. Deallocate any initiator
298 * ccbs on this lcb and send disconnect ind event.
299 *
300 *
301 * Returns Nothing.
302 *
303 ******************************************************************************/
Myles Watsond35a6482016-10-27 08:52:16 -0700304void avct_lcb_close_ind(tAVCT_LCB *p_lcb,
305 UNUSED_ATTR tAVCT_LCB_EVT *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800306{
307 tAVCT_CCB *p_ccb = &avct_cb.ccb[0];
308 int i;
309
310 for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++)
311 {
312 if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb))
313 {
314 if (p_ccb->cc.role == AVCT_INT)
315 {
316 avct_ccb_dealloc(p_ccb, AVCT_DISCONNECT_IND_EVT,
317 0, p_lcb->peer_addr);
318 }
319 else
320 {
321 p_ccb->p_lcb = NULL;
322 (*p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_ccb), AVCT_DISCONNECT_IND_EVT,
323 0, p_lcb->peer_addr);
324 }
325 }
326 }
327}
328
329/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800330 *
331 * Function avct_lcb_close_cfm
332 *
333 * Description L2CAP channel closed by us. Deallocate any initiator
334 * ccbs on this lcb and send disconnect ind or cfm event.
335 *
336 *
337 * Returns Nothing.
338 *
339 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800340void avct_lcb_close_cfm(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
341{
342 tAVCT_CCB *p_ccb = &avct_cb.ccb[0];
343 int i;
Marie Janssend19e0782016-07-15 12:48:27 -0700344 uint8_t event;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800345
346 for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++)
347 {
348 if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb))
349 {
350 /* if this ccb initiated close send disconnect cfm otherwise ind */
351 if (p_ccb->ch_close)
352 {
Marie Janssend19e0782016-07-15 12:48:27 -0700353 p_ccb->ch_close = false;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800354 event = AVCT_DISCONNECT_CFM_EVT;
355 }
356 else
357 {
358 event = AVCT_DISCONNECT_IND_EVT;
359 }
360
361 if (p_ccb->cc.role == AVCT_INT)
362 {
363 avct_ccb_dealloc(p_ccb, event, p_data->result, p_lcb->peer_addr);
364 }
365 else
366 {
367 p_ccb->p_lcb = NULL;
368 (*p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_ccb), event,
369 p_data->result, p_lcb->peer_addr);
370 }
371 }
372 }
373}
374
375/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800376 *
377 * Function avct_lcb_bind_conn
378 *
379 * Description Bind ccb to lcb and send connect cfm event.
380 *
381 *
382 * Returns Nothing.
383 *
384 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800385void avct_lcb_bind_conn(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
386{
387 p_data->p_ccb->p_lcb = p_lcb;
388 (*p_data->p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_data->p_ccb),
389 AVCT_CONNECT_CFM_EVT, 0, p_lcb->peer_addr);
390}
391
392/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800393 *
394 * Function avct_lcb_chk_disc
395 *
396 * Description A ccb wants to close; if it is the last ccb on this lcb,
397 * close channel. Otherwise just deallocate and call
398 * callback.
399 *
400 *
401 * Returns Nothing.
402 *
403 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800404void avct_lcb_chk_disc(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
405{
Pavlin Radoslavov7aaf7c62016-08-23 12:24:03 -0700406 AVCT_TRACE_WARNING("%s", __func__);
Avish Shaha408eb72016-06-22 06:47:20 +0530407
The Android Open Source Project5738f832012-12-12 16:00:35 -0800408 avct_close_bcb(p_lcb, p_data);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800409 if (avct_lcb_last_ccb(p_lcb, p_data->p_ccb))
410 {
Pavlin Radoslavov7aaf7c62016-08-23 12:24:03 -0700411 AVCT_TRACE_WARNING("%s: closing", __func__);
Marie Janssend19e0782016-07-15 12:48:27 -0700412 p_data->p_ccb->ch_close = true;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800413 avct_lcb_event(p_lcb, AVCT_LCB_INT_CLOSE_EVT, p_data);
414 }
415 else
416 {
Pavlin Radoslavov7aaf7c62016-08-23 12:24:03 -0700417 AVCT_TRACE_WARNING("%s: dealloc ccb", __func__);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800418 avct_lcb_unbind_disc(p_lcb, p_data);
419 }
420}
421
422/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800423 *
424 * Function avct_lcb_chnl_disc
425 *
426 * Description Disconnect L2CAP channel.
427 *
428 *
429 * Returns Nothing.
430 *
431 ******************************************************************************/
Myles Watsond35a6482016-10-27 08:52:16 -0700432void avct_lcb_chnl_disc(tAVCT_LCB *p_lcb,
433 UNUSED_ATTR tAVCT_LCB_EVT *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800434{
435 L2CA_DisconnectReq(p_lcb->ch_lcid);
436}
437
438/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800439 *
440 * Function avct_lcb_bind_fail
441 *
442 * Description Deallocate ccb and call callback with connect event
443 * with failure result.
444 *
445 *
446 * Returns Nothing.
447 *
448 ******************************************************************************/
Myles Watsond35a6482016-10-27 08:52:16 -0700449void avct_lcb_bind_fail(UNUSED_ATTR tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800450{
451 avct_ccb_dealloc(p_data->p_ccb, AVCT_CONNECT_CFM_EVT, AVCT_RESULT_FAIL, NULL);
452}
453
454/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800455 *
456 * Function avct_lcb_cong_ind
457 *
458 * Description Handle congestion indication from L2CAP.
459 *
460 *
461 * Returns Nothing.
462 *
463 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800464void avct_lcb_cong_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
465{
466 tAVCT_CCB *p_ccb = &avct_cb.ccb[0];
467 int i;
Marie Janssend19e0782016-07-15 12:48:27 -0700468 uint8_t event;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800469 BT_HDR *p_buf;
470
471 /* set event */
472 event = (p_data->cong) ? AVCT_CONG_IND_EVT : AVCT_UNCONG_IND_EVT;
473 p_lcb->cong = p_data->cong;
Marie Janssend19e0782016-07-15 12:48:27 -0700474 if (p_lcb->cong == false && !fixed_queue_is_empty(p_lcb->tx_q))
The Android Open Source Project5738f832012-12-12 16:00:35 -0800475 {
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700476 while (!p_lcb->cong &&
477 (p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_lcb->tx_q)) != NULL)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800478 {
479 if (L2CA_DataWrite(p_lcb->ch_lcid, p_buf) == L2CAP_DW_CONGESTED)
480 {
Marie Janssend19e0782016-07-15 12:48:27 -0700481 p_lcb->cong = true;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800482 }
483 }
484 }
485
486 /* send event to all ccbs on this lcb */
487 for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++)
488 {
489 if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb))
490 {
491 (*p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_ccb), event, 0, p_lcb->peer_addr);
492 }
493 }
494}
495
496/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800497 *
498 * Function avct_lcb_discard_msg
499 *
500 * Description Discard a message sent in from the API.
501 *
502 *
503 * Returns Nothing.
504 *
505 ******************************************************************************/
Myles Watsond35a6482016-10-27 08:52:16 -0700506void avct_lcb_discard_msg(UNUSED_ATTR tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800507{
Avish Shaha408eb72016-06-22 06:47:20 +0530508 AVCT_TRACE_WARNING("%s Dropping message", __func__);
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800509 osi_free_and_reset((void **)&p_data->ul_msg.p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800510}
511
512/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800513 *
514 * Function avct_lcb_send_msg
515 *
516 * Description Build and send an AVCTP message.
517 *
518 *
519 * Returns Nothing.
520 *
521 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800522void avct_lcb_send_msg(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
523{
Marie Janssend19e0782016-07-15 12:48:27 -0700524 uint16_t curr_msg_len;
525 uint8_t pkt_type;
526 uint8_t hdr_len;
527 uint8_t *p;
528 uint8_t nosp = 0; /* number of subsequent packets */
529 uint16_t temp;
530 uint16_t buf_size = p_lcb->peer_mtu + L2CAP_MIN_OFFSET + BT_HDR_SIZE;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800531
532
533 /* store msg len */
534 curr_msg_len = p_data->ul_msg.p_buf->len;
535
536 /* initialize packet type and other stuff */
537 if (curr_msg_len <= (p_lcb->peer_mtu - AVCT_HDR_LEN_SINGLE))
538 {
539 pkt_type = AVCT_PKT_TYPE_SINGLE;
540 }
541 else
542 {
543 pkt_type = AVCT_PKT_TYPE_START;
544 temp = (curr_msg_len + AVCT_HDR_LEN_START - p_lcb->peer_mtu);
545 nosp = temp / (p_lcb->peer_mtu - 1) + 1;
546 if ( (temp % (p_lcb->peer_mtu - 1)) != 0)
547 nosp++;
548 }
549
550 /* while we haven't sent all packets */
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800551 while (curr_msg_len != 0) {
552 BT_HDR *p_buf;
553
The Android Open Source Project5738f832012-12-12 16:00:35 -0800554 /* set header len */
555 hdr_len = avct_lcb_pkt_type_len[pkt_type];
556
557 /* if remaining msg must be fragmented */
558 if (p_data->ul_msg.p_buf->len > (p_lcb->peer_mtu - hdr_len))
559 {
560 /* get a new buffer for fragment we are sending */
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800561 p_buf = (BT_HDR *)osi_malloc(buf_size);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800562
563 /* copy portion of data from current message to new buffer */
564 p_buf->offset = L2CAP_MIN_OFFSET + hdr_len;
565 p_buf->len = p_lcb->peer_mtu - hdr_len;
566
Marie Janssend19e0782016-07-15 12:48:27 -0700567 memcpy((uint8_t *)(p_buf + 1) + p_buf->offset,
568 (uint8_t *)(p_data->ul_msg.p_buf + 1) + p_data->ul_msg.p_buf->offset, p_buf->len);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800569
570 p_data->ul_msg.p_buf->offset += p_buf->len;
571 p_data->ul_msg.p_buf->len -= p_buf->len;
572 }
573 else
574 {
575 p_buf = p_data->ul_msg.p_buf;
576 }
577
578 curr_msg_len -= p_buf->len;
579
580 /* set up to build header */
581 p_buf->len += hdr_len;
582 p_buf->offset -= hdr_len;
Marie Janssend19e0782016-07-15 12:48:27 -0700583 p = (uint8_t *)(p_buf + 1) + p_buf->offset;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800584
585 /* build header */
Avish Shaha408eb72016-06-22 06:47:20 +0530586 AVCT_BUILD_HDR(p, p_data->ul_msg.label, pkt_type, p_data->ul_msg.cr);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800587 if (pkt_type == AVCT_PKT_TYPE_START)
588 {
589 UINT8_TO_STREAM(p, nosp);
590 }
591 if ((pkt_type == AVCT_PKT_TYPE_START) || (pkt_type == AVCT_PKT_TYPE_SINGLE))
592 {
593 UINT16_TO_BE_STREAM(p, p_data->ul_msg.p_ccb->cc.pid);
594 }
595
Marie Janssend19e0782016-07-15 12:48:27 -0700596 if (p_lcb->cong == true)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800597 {
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700598 fixed_queue_enqueue(p_lcb->tx_q, p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800599 }
600
601 /* send message to L2CAP */
602 else
603 {
604 if (L2CA_DataWrite(p_lcb->ch_lcid, p_buf) == L2CAP_DW_CONGESTED)
605 {
Marie Janssend19e0782016-07-15 12:48:27 -0700606 p_lcb->cong = true;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800607 }
608 }
609
610 /* update pkt type for next packet */
611 if (curr_msg_len > (p_lcb->peer_mtu - AVCT_HDR_LEN_END))
612 {
613 pkt_type = AVCT_PKT_TYPE_CONT;
614 }
615 else
616 {
617 pkt_type = AVCT_PKT_TYPE_END;
618 }
619 }
Avish Shaha408eb72016-06-22 06:47:20 +0530620 AVCT_TRACE_DEBUG ("%s tx_q_count:%d", __func__,
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700621 fixed_queue_length(p_lcb->tx_q));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800622 return;
623}
624
625/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800626 *
627 * Function avct_lcb_free_msg_ind
628 *
629 * Description Discard an incoming AVCTP message.
630 *
631 *
632 * Returns Nothing.
633 *
634 ******************************************************************************/
Myles Watsond35a6482016-10-27 08:52:16 -0700635void avct_lcb_free_msg_ind(UNUSED_ATTR tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800636{
Pavlin Radoslavov20524d32016-02-02 18:12:08 -0800637 if (p_data == NULL)
638 return;
639
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800640 osi_free_and_reset((void **)&p_data->p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800641}
642
643/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800644 *
645 * Function avct_lcb_msg_ind
646 *
647 * Description Handle an incoming AVCTP message.
648 *
649 *
650 * Returns Nothing.
651 *
652 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800653void avct_lcb_msg_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
654{
Marie Janssend19e0782016-07-15 12:48:27 -0700655 uint8_t *p;
656 uint8_t label, type, cr_ipid;
657 uint16_t pid;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800658 tAVCT_CCB *p_ccb;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800659
660 /* this p_buf is to be reported through p_msg_cback. The layer_specific
661 * needs to be set properly to indicate that it is received through
662 * control channel */
663 p_data->p_buf->layer_specific = AVCT_DATA_CTRL;
664
665 /* reassemble message; if no message available (we received a fragment) return */
Marie Janssenf33b6f42016-11-22 15:01:42 -0800666 p_data->p_buf = avct_lcb_msg_asmbl(p_lcb, p_data->p_buf);
667 if (p_data->p_buf == NULL)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800668 {
669 return;
670 }
671
Marie Janssend19e0782016-07-15 12:48:27 -0700672 p = (uint8_t *)(p_data->p_buf + 1) + p_data->p_buf->offset;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800673
674 /* parse header byte */
Avish Shaha408eb72016-06-22 06:47:20 +0530675 AVCT_PARSE_HDR(p, label, type, cr_ipid);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800676
677 /* check for invalid cr_ipid */
678 if (cr_ipid == AVCT_CR_IPID_INVALID)
679 {
Sharvil Nanavati158084e2014-05-04 09:53:44 -0700680 AVCT_TRACE_WARNING("Invalid cr_ipid", cr_ipid);
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800681 osi_free_and_reset((void **)&p_data->p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800682 return;
683 }
684
685 /* parse and lookup PID */
686 BE_STREAM_TO_UINT16(pid, p);
Avish Shaha408eb72016-06-22 06:47:20 +0530687 p_ccb = avct_lcb_has_pid(p_lcb, pid);
688 if (p_ccb)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800689 {
690 /* PID found; send msg up, adjust bt hdr and call msg callback */
691 p_data->p_buf->offset += AVCT_HDR_LEN_SINGLE;
692 p_data->p_buf->len -= AVCT_HDR_LEN_SINGLE;
693 (*p_ccb->cc.p_msg_cback)(avct_ccb_to_idx(p_ccb), label, cr_ipid, p_data->p_buf);
Avish Shaha408eb72016-06-22 06:47:20 +0530694 return;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800695 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800696
Avish Shaha408eb72016-06-22 06:47:20 +0530697 /* PID not found; drop message */
698 AVCT_TRACE_WARNING("No ccb for PID=%x", pid);
699 osi_free_and_reset((void **)&p_data->p_buf);
700
701 /* if command send reject */
702 if (cr_ipid == AVCT_CMD)
703 {
704 BT_HDR *p_buf = (BT_HDR *)osi_malloc(AVCT_CMD_BUF_SIZE);
705 p_buf->len = AVCT_HDR_LEN_SINGLE;
706 p_buf->offset = AVCT_MSG_OFFSET - AVCT_HDR_LEN_SINGLE;
707 p = (uint8_t *)(p_buf + 1) + p_buf->offset;
708 AVCT_BUILD_HDR(p, label, AVCT_PKT_TYPE_SINGLE, AVCT_REJ);
709 UINT16_TO_BE_STREAM(p, pid);
710 L2CA_DataWrite(p_lcb->ch_lcid, p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800711 }
712}