blob: 6b158314ffa63ba2a04076aa1d199c4f5798aa7d [file] [log] [blame]
The Android Open Source Project5738f832012-12-12 16:00:35 -08001/******************************************************************************
2 *
3 * Copyright (C) 1999-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 file contains functions to send TS 07.10 frames
22 *
23 ******************************************************************************/
24#include "bt_target.h"
25#include "gki.h"
26#include "rfcdefs.h"
27#include "port_api.h"
28#include "l2c_api.h"
29#include "port_int.h"
30#include "rfc_int.h"
31
32/*******************************************************************************
33**
34** Function rfc_send_sabme
35**
36** Description This function sends SABME frame.
37**
38*******************************************************************************/
39void rfc_send_sabme (tRFC_MCB *p_mcb, UINT8 dlci)
40{
41 BT_HDR *p_buf;
42 UINT8 *p_data;
43 UINT8 cr = RFCOMM_CR(p_mcb->is_initiator, TRUE);
44
45 if ((p_buf = (BT_HDR *)GKI_getpoolbuf (RFCOMM_CMD_POOL_ID)) == NULL)
46 return;
47
48 p_buf->offset = L2CAP_MIN_OFFSET;
49 p_data = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
50
51 /* SABME frame, command, PF = 1, dlci */
52 *p_data++ = RFCOMM_EA | cr | (dlci << RFCOMM_SHIFT_DLCI);
53 *p_data++ = RFCOMM_SABME | RFCOMM_PF;
54 *p_data++ = RFCOMM_EA | 0;
55
56 *p_data = RFCOMM_SABME_FCS ((UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET, cr, dlci);
57
58 p_buf->len = 4;
59
60 rfc_check_send_cmd(p_mcb, p_buf);
61}
62
63
64/*******************************************************************************
65**
66** Function rfc_send_ua
67**
68** Description This function sends UA frame.
69**
70*******************************************************************************/
71void rfc_send_ua (tRFC_MCB *p_mcb, UINT8 dlci)
72{
73 BT_HDR *p_buf;
74 UINT8 *p_data;
75 UINT8 cr = RFCOMM_CR(p_mcb->is_initiator, FALSE);
76
77 if ((p_buf = (BT_HDR *)GKI_getpoolbuf (RFCOMM_CMD_POOL_ID)) == NULL)
78 return;
79
80 p_buf->offset = L2CAP_MIN_OFFSET;
81 p_data = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
82
83 /* ua frame, response, PF = 1, dlci */
84 *p_data++ = RFCOMM_EA | cr | (dlci << RFCOMM_SHIFT_DLCI);
85 *p_data++ = RFCOMM_UA | RFCOMM_PF;
86 *p_data++ = RFCOMM_EA | 0;
87
88 *p_data = RFCOMM_UA_FCS ((UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET, cr, dlci);
89
90 p_buf->len = 4;
91
92 rfc_check_send_cmd(p_mcb, p_buf);
93}
94
95
96/*******************************************************************************
97**
98** Function rfc_send_dm
99**
100** Description This function sends DM frame.
101**
102*******************************************************************************/
103void rfc_send_dm (tRFC_MCB *p_mcb, UINT8 dlci, BOOLEAN pf)
104{
105 BT_HDR *p_buf;
106 UINT8 *p_data;
107 UINT8 cr = RFCOMM_CR(p_mcb->is_initiator, FALSE);
108
109 if ((p_buf = (BT_HDR *)GKI_getpoolbuf (RFCOMM_CMD_POOL_ID)) == NULL)
110 return;
111
112 p_buf->offset = L2CAP_MIN_OFFSET;
113 p_data = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
114
115 /* DM frame, response, PF = 1, dlci */
116 *p_data++ = RFCOMM_EA | cr | (dlci << RFCOMM_SHIFT_DLCI);
117 *p_data++ = RFCOMM_DM | ((pf) ? RFCOMM_PF : 0);
118 *p_data++ = RFCOMM_EA | 0;
119
120 *p_data = RFCOMM_DM_FCS ((UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET, cr, dlci);
121
122 p_buf->len = 4;
123
124 rfc_check_send_cmd(p_mcb, p_buf);
125}
126
127
128/*******************************************************************************
129**
130** Function rfc_send_disc
131**
132** Description This function sends DISC frame.
133**
134*******************************************************************************/
135void rfc_send_disc (tRFC_MCB *p_mcb, UINT8 dlci)
136{
137 BT_HDR *p_buf;
138 UINT8 *p_data;
139 UINT8 cr = RFCOMM_CR(p_mcb->is_initiator, TRUE);
140
141 if ((p_buf = (BT_HDR *)GKI_getpoolbuf (RFCOMM_CMD_POOL_ID)) == NULL)
142 return;
143
144 p_buf->offset = L2CAP_MIN_OFFSET;
145 p_data = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
146
147 /* DISC frame, command, PF = 1, dlci */
148 *p_data++ = RFCOMM_EA | cr | (dlci << RFCOMM_SHIFT_DLCI);
149 *p_data++ = RFCOMM_DISC | RFCOMM_PF;
150 *p_data++ = RFCOMM_EA | 0;
151
152 *p_data = RFCOMM_DISC_FCS ((UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET, cr, dlci);
153
154 p_buf->len = 4;
155
156 rfc_check_send_cmd(p_mcb, p_buf);
157}
158
159
160/*******************************************************************************
161**
162** Function rfc_send_buf_uih
163**
164** Description This function sends UIH frame.
165**
166*******************************************************************************/
167void rfc_send_buf_uih (tRFC_MCB *p_mcb, UINT8 dlci, BT_HDR *p_buf)
168{
169 UINT8 *p_data;
170 UINT8 cr = RFCOMM_CR(p_mcb->is_initiator, TRUE);
171 UINT8 credits;
172
173 p_buf->offset -= RFCOMM_CTRL_FRAME_LEN;
174 if (p_buf->len > 127)
175 p_buf->offset--;
176
177 if (dlci)
178 credits = (UINT8)p_buf->layer_specific;
179 else
180 credits = 0;
181
182 if (credits)
183 p_buf->offset--;
184
185 p_data = (UINT8 *)(p_buf + 1) + p_buf->offset;
186
187 /* UIH frame, command, PF = 0, dlci */
188 *p_data++ = RFCOMM_EA | cr | (dlci << RFCOMM_SHIFT_DLCI);
189 *p_data++ = RFCOMM_UIH | ((credits) ? RFCOMM_PF : 0);
190 if (p_buf->len <= 127)
191 {
192 *p_data++ = RFCOMM_EA | (p_buf->len << 1);
193 p_buf->len += 3;
194 }
195 else
196 {
197 *p_data++ = (p_buf->len & 0x7f) << 1;
198 *p_data++ = p_buf->len >> RFCOMM_SHIFT_LENGTH2;
199 p_buf->len += 4;
200 }
201
202 if (credits)
203 {
204 *p_data++ = credits;
205 p_buf->len++;
206 }
207
208 p_data = (UINT8 *)(p_buf + 1) + p_buf->offset + p_buf->len++;
209
210 *p_data = RFCOMM_UIH_FCS ((UINT8 *)(p_buf + 1) + p_buf->offset, dlci);
211
212 if (dlci == RFCOMM_MX_DLCI)
213 {
214 rfc_check_send_cmd(p_mcb, p_buf);
215 }
216 else
217 {
218
219 L2CA_DataWrite (p_mcb->lcid, p_buf);
220 }
221}
222
223
224/*******************************************************************************
225**
226** Function rfc_send_pn
227**
228** Description This function sends DLC Parameters Negotiation Frame.
229**
230*******************************************************************************/
231void rfc_send_pn (tRFC_MCB *p_mcb, UINT8 dlci, BOOLEAN is_command, UINT16 mtu, UINT8 cl, UINT8 k)
232{
233 BT_HDR *p_buf;
234 UINT8 *p_data;
235
236 if ((p_buf = (BT_HDR *)GKI_getpoolbuf (RFCOMM_CMD_POOL_ID)) == NULL)
237 return;
238
239 p_buf->offset = L2CAP_MIN_OFFSET + RFCOMM_CTRL_FRAME_LEN;
240 p_data = (UINT8 *)(p_buf + 1) + p_buf->offset;
241
242 *p_data++ = RFCOMM_EA | RFCOMM_I_CR(is_command) | RFCOMM_MX_PN;
243 *p_data++ = RFCOMM_EA | (RFCOMM_MX_PN_LEN << 1);
244
245 *p_data++ = dlci;
246 *p_data++ = RFCOMM_PN_FRAM_TYPE_UIH | cl;
247
248 /* It appeared that we need to reply with the same priority bits as we received.
249 ** We will use the fact that we reply in the same context so rx_frame can still be used.
250 */
251 if (is_command)
252 *p_data++ = RFCOMM_PN_PRIORITY_0;
253 else
254 *p_data++ = rfc_cb.rfc.rx_frame.u.pn.priority;
255
256 *p_data++ = RFCOMM_T1_DSEC;
257 *p_data++ = mtu & 0xFF;
258 *p_data++ = mtu >> 8;
259 *p_data++ = RFCOMM_N2;
260 *p_data = k;
261
262 /* Total length is sizeof PN data + mx header 2 */
263 p_buf->len = RFCOMM_MX_PN_LEN + 2;
264
265 rfc_send_buf_uih (p_mcb, RFCOMM_MX_DLCI, p_buf);
266}
267
268
269/*******************************************************************************
270**
271** Function rfc_send_fcon
272**
273** Description This function sends Flow Control On Command.
274**
275*******************************************************************************/
276void rfc_send_fcon (tRFC_MCB *p_mcb, BOOLEAN is_command)
277{
278 BT_HDR *p_buf;
279 UINT8 *p_data;
280
281 if ((p_buf = (BT_HDR *)GKI_getpoolbuf (RFCOMM_CMD_POOL_ID)) == NULL)
282 return;
283
284 p_buf->offset = L2CAP_MIN_OFFSET + RFCOMM_CTRL_FRAME_LEN;
285 p_data = (UINT8 *)(p_buf + 1) + p_buf->offset;
286
287 *p_data++ = RFCOMM_EA | RFCOMM_I_CR(is_command) | RFCOMM_MX_FCON;
288 *p_data++ = RFCOMM_EA | (RFCOMM_MX_FCON_LEN << 1);
289
290 /* Total length is sizeof FCON data + mx header 2 */
291 p_buf->len = RFCOMM_MX_FCON_LEN + 2;
292
293 rfc_send_buf_uih (p_mcb, RFCOMM_MX_DLCI, p_buf);
294}
295
296
297/*******************************************************************************
298**
299** Function rfc_send_fcoff
300**
301** Description This function sends Flow Control Off Command.
302**
303*******************************************************************************/
304void rfc_send_fcoff (tRFC_MCB *p_mcb, BOOLEAN is_command)
305{
306 BT_HDR *p_buf;
307 UINT8 *p_data;
308
309 if ((p_buf = (BT_HDR *)GKI_getpoolbuf (RFCOMM_CMD_POOL_ID)) == NULL)
310 return;
311
312 p_buf->offset = L2CAP_MIN_OFFSET + RFCOMM_CTRL_FRAME_LEN;
313 p_data = (UINT8 *)(p_buf + 1) + p_buf->offset;
314
315 *p_data++ = RFCOMM_EA | RFCOMM_I_CR(is_command) | RFCOMM_MX_FCOFF;
316 *p_data++ = RFCOMM_EA | (RFCOMM_MX_FCOFF_LEN << 1);
317
318 /* Total length is sizeof FCOFF data + mx header 2 */
319 p_buf->len = RFCOMM_MX_FCOFF_LEN + 2;
320
321 rfc_send_buf_uih (p_mcb, RFCOMM_MX_DLCI, p_buf);
322}
323
324
325/*******************************************************************************
326**
327** Function rfc_send_msc
328**
329** Description This function sends Modem Status Command Frame.
330**
331*******************************************************************************/
332void rfc_send_msc (tRFC_MCB *p_mcb, UINT8 dlci, BOOLEAN is_command,
333 tPORT_CTRL *p_pars)
334{
335 BT_HDR *p_buf;
336 UINT8 *p_data;
337 UINT8 signals;
338 UINT8 break_duration;
339 UINT8 len;
340
341 signals = p_pars->modem_signal;
342 break_duration = p_pars->break_signal;
343
344 if ((p_buf = (BT_HDR *)GKI_getpoolbuf (RFCOMM_CMD_POOL_ID)) == NULL)
345 return;
346
347 p_buf->offset = L2CAP_MIN_OFFSET + RFCOMM_CTRL_FRAME_LEN;
348 p_data = (UINT8 *)(p_buf + 1) + p_buf->offset;
349
350 if (break_duration)
351 len = RFCOMM_MX_MSC_LEN_WITH_BREAK;
352 else
353 len = RFCOMM_MX_MSC_LEN_NO_BREAK;
354
355 *p_data++ = RFCOMM_EA | RFCOMM_I_CR(is_command) | RFCOMM_MX_MSC;
356 *p_data++ = RFCOMM_EA | (len << 1);
357
358 *p_data++ = RFCOMM_EA | RFCOMM_CR_MASK | (dlci << RFCOMM_SHIFT_DLCI);
359 *p_data++ = RFCOMM_EA |
360 ((p_pars->fc) ? RFCOMM_MSC_FC : 0) |
361 ((signals & MODEM_SIGNAL_DTRDSR) ? RFCOMM_MSC_RTC : 0) |
362 ((signals & MODEM_SIGNAL_RTSCTS) ? RFCOMM_MSC_RTR : 0) |
363 ((signals & MODEM_SIGNAL_RI) ? RFCOMM_MSC_IC : 0) |
364 ((signals & MODEM_SIGNAL_DCD) ? RFCOMM_MSC_DV : 0);
365
366 if (break_duration)
367 {
368 *p_data++ = RFCOMM_EA | RFCOMM_MSC_BREAK_PRESENT_MASK |
369 (break_duration << RFCOMM_MSC_SHIFT_BREAK);
370 }
371
372 /* Total length is sizeof MSC data + mx header 2 */
373 p_buf->len = len + 2;
374
375 rfc_send_buf_uih (p_mcb, RFCOMM_MX_DLCI, p_buf);
376}
377
378
379/*******************************************************************************
380**
381** Function rfc_send_rls
382**
383** Description This function sends Remote Line Status Command Frame.
384**
385*******************************************************************************/
386void rfc_send_rls (tRFC_MCB *p_mcb, UINT8 dlci, BOOLEAN is_command, UINT8 status)
387{
388 BT_HDR *p_buf;
389 UINT8 *p_data;
390
391 if ((p_buf = (BT_HDR *)GKI_getpoolbuf (RFCOMM_CMD_POOL_ID)) == NULL)
392 return;
393
394 p_buf->offset = L2CAP_MIN_OFFSET + RFCOMM_CTRL_FRAME_LEN;
395 p_data = (UINT8 *)(p_buf + 1) + p_buf->offset;
396
397 *p_data++ = RFCOMM_EA | RFCOMM_I_CR(is_command) | RFCOMM_MX_RLS;
398 *p_data++ = RFCOMM_EA | (RFCOMM_MX_RLS_LEN << 1);
399
400 *p_data++ = RFCOMM_EA | RFCOMM_CR_MASK | (dlci << RFCOMM_SHIFT_DLCI);
401 *p_data++ = RFCOMM_RLS_ERROR | status;
402
403 /* Total length is sizeof RLS data + mx header 2 */
404 p_buf->len = RFCOMM_MX_RLS_LEN + 2;
405
406 rfc_send_buf_uih (p_mcb, RFCOMM_MX_DLCI, p_buf);
407}
408
409
410/*******************************************************************************
411**
412** Function rfc_send_nsc
413**
414** Description This function sends Non Supported Command Response.
415**
416*******************************************************************************/
417void rfc_send_nsc (tRFC_MCB *p_mcb)
418{
419 BT_HDR *p_buf;
420 UINT8 *p_data;
421
422 if ((p_buf = (BT_HDR *)GKI_getpoolbuf (RFCOMM_CMD_POOL_ID)) == NULL)
423 return;
424
425 p_buf->offset = L2CAP_MIN_OFFSET + RFCOMM_CTRL_FRAME_LEN;
426 p_data = (UINT8 *)(p_buf + 1) + p_buf->offset;
427
428 *p_data++ = RFCOMM_EA | RFCOMM_I_CR(FALSE) | RFCOMM_MX_NSC;
429 *p_data++ = RFCOMM_EA | (RFCOMM_MX_NSC_LEN << 1);
430
431 *p_data++ = rfc_cb.rfc.rx_frame.ea |
432 (rfc_cb.rfc.rx_frame.cr << RFCOMM_SHIFT_CR) |
433 rfc_cb.rfc.rx_frame.type;
434
435 /* Total length is sizeof NSC data + mx header 2 */
436 p_buf->len = RFCOMM_MX_NSC_LEN + 2;
437
438 rfc_send_buf_uih (p_mcb, RFCOMM_MX_DLCI, p_buf);
439}
440
441
442/*******************************************************************************
443**
444** Function rfc_send_rpn
445**
446** Description This function sends Remote Port Negotiation Command
447**
448*******************************************************************************/
449void rfc_send_rpn (tRFC_MCB *p_mcb, UINT8 dlci, BOOLEAN is_command,
450 tPORT_STATE *p_pars, UINT16 mask)
451{
452 BT_HDR *p_buf;
453 UINT8 *p_data;
454
455 if ((p_buf = (BT_HDR *)GKI_getpoolbuf (RFCOMM_CMD_POOL_ID)) == NULL)
456 return;
457
458 p_buf->offset = L2CAP_MIN_OFFSET + RFCOMM_CTRL_FRAME_LEN;
459 p_data = (UINT8 *)(p_buf + 1) + p_buf->offset;
460
461 *p_data++ = RFCOMM_EA | RFCOMM_I_CR(is_command) | RFCOMM_MX_RPN;
462
463 if (!p_pars)
464 {
465 *p_data++ = RFCOMM_EA | (RFCOMM_MX_RPN_REQ_LEN << 1);
466
467 *p_data++ = RFCOMM_EA | RFCOMM_CR_MASK | (dlci << RFCOMM_SHIFT_DLCI);
468
469 p_buf->len = RFCOMM_MX_RPN_REQ_LEN + 2;
470 }
471 else
472 {
473 *p_data++ = RFCOMM_EA | (RFCOMM_MX_RPN_LEN << 1);
474
475 *p_data++ = RFCOMM_EA | RFCOMM_CR_MASK | (dlci << RFCOMM_SHIFT_DLCI);
476 *p_data++ = p_pars->baud_rate;
477 *p_data++ = (p_pars->byte_size << RFCOMM_RPN_BITS_SHIFT)
478 | (p_pars->stop_bits << RFCOMM_RPN_STOP_BITS_SHIFT)
479 | (p_pars->parity << RFCOMM_RPN_PARITY_SHIFT)
480 | (p_pars->parity_type << RFCOMM_RPN_PARITY_TYPE_SHIFT);
481 *p_data++ = p_pars->fc_type;
482 *p_data++ = p_pars->xon_char;
483 *p_data++ = p_pars->xoff_char;
484 *p_data++ = (mask & 0xFF);
485 *p_data++ = (mask >> 8);
486
487 /* Total length is sizeof RPN data + mx header 2 */
488 p_buf->len = RFCOMM_MX_RPN_LEN + 2;
489 }
490
491 rfc_send_buf_uih (p_mcb, RFCOMM_MX_DLCI, p_buf);
492}
493
494
495/*******************************************************************************
496**
497** Function rfc_send_test
498**
499** Description This function sends Test frame.
500**
501*******************************************************************************/
502void rfc_send_test (tRFC_MCB *p_mcb, BOOLEAN is_command, BT_HDR *p_buf)
503{
504 UINT8 *p_data;
505 UINT16 xx;
506 UINT8 *p_src, *p_dest;
507
508 /* Shift buffer to give space for header */
509 if (p_buf->offset < (L2CAP_MIN_OFFSET + RFCOMM_MIN_OFFSET + 2))
510 {
511 p_src = (UINT8 *) (p_buf + 1) + p_buf->offset + p_buf->len - 1;
512 p_dest = (UINT8 *) (p_buf + 1) + L2CAP_MIN_OFFSET + RFCOMM_MIN_OFFSET + 2 + p_buf->len - 1;
513
514 for (xx = 0; xx < p_buf->len; xx++)
515 *p_dest-- = *p_src--;
516
517 p_buf->offset = L2CAP_MIN_OFFSET + RFCOMM_MIN_OFFSET + 2;
518 }
519
520 /* Adjust offset by number of bytes we are going to fill */
521 p_buf->offset -= 2;
522 p_data = (UINT8 *)(p_buf + 1) + p_buf->offset;
523
524 *p_data++ = RFCOMM_EA | RFCOMM_I_CR(is_command) | RFCOMM_MX_TEST;
525 *p_data++ = RFCOMM_EA | (p_buf->len << 1);
526
527 p_buf->len += 2;
528
529 rfc_send_buf_uih (p_mcb, RFCOMM_MX_DLCI, p_buf);
530}
531
532/*******************************************************************************
533**
534** Function rfc_send_credit
535**
536** Description This function sends a flow control credit in UIH frame.
537**
538*******************************************************************************/
539void rfc_send_credit(tRFC_MCB *p_mcb, UINT8 dlci, UINT8 credit)
540{
541 BT_HDR *p_buf;
542 UINT8 *p_data;
543 UINT8 cr = RFCOMM_CR(p_mcb->is_initiator, TRUE);
544
545 if ((p_buf = (BT_HDR *)GKI_getpoolbuf (RFCOMM_CMD_POOL_ID)) == NULL)
546 return;
547
548 p_buf->offset = L2CAP_MIN_OFFSET;
549 p_data = (UINT8 *)(p_buf + 1) + p_buf->offset;
550
551 *p_data++ = RFCOMM_EA | cr | (dlci << RFCOMM_SHIFT_DLCI);
552 *p_data++ = RFCOMM_UIH | RFCOMM_PF;
553 *p_data++ = RFCOMM_EA | 0;
554 *p_data++ = credit;
555 *p_data = RFCOMM_UIH_FCS ((UINT8 *)(p_buf + 1) + p_buf->offset, dlci);
556
557 p_buf->len = 5;
558
559 rfc_check_send_cmd(p_mcb, p_buf);
560}
561
562
563/*******************************************************************************
564**
565** Function rfc_parse_data
566**
567** Description This function processes data packet received from L2CAP
568**
569*******************************************************************************/
570UINT8 rfc_parse_data (tRFC_MCB *p_mcb, MX_FRAME *p_frame, BT_HDR *p_buf)
571{
572 UINT8 ead, eal, fcs;
573 UINT8 *p_data = (UINT8 *)(p_buf + 1) + p_buf->offset;
574 UINT8 *p_start = p_data;
575 UINT16 len;
576
577 if (p_buf->len < RFCOMM_CTRL_FRAME_LEN)
578 {
Sharvil Nanavatid5bba902014-05-04 01:33:15 -0700579 RFCOMM_TRACE_ERROR ("Bad Length1: %d", p_buf->len);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800580 return (RFC_EVENT_BAD_FRAME);
581 }
582
583 RFCOMM_PARSE_CTRL_FIELD (ead, p_frame->cr, p_frame->dlci, p_data);
584 if( !ead )
585 {
Sharvil Nanavatid5bba902014-05-04 01:33:15 -0700586 RFCOMM_TRACE_ERROR ("Bad Address(EA must be 1)");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800587 return (RFC_EVENT_BAD_FRAME);
588 }
589 RFCOMM_PARSE_TYPE_FIELD (p_frame->type, p_frame->pf, p_data);
590 RFCOMM_PARSE_LEN_FIELD (eal, len, p_data);
591
592 p_buf->len -= (3 + !ead + !eal + 1); /* Additional 1 for FCS */
593 p_buf->offset += (3 + !ead + !eal);
594
595 /* handle credit if credit based flow control */
596 if ((p_mcb->flow == PORT_FC_CREDIT) && (p_frame->type == RFCOMM_UIH) &&
597 (p_frame->dlci != RFCOMM_MX_DLCI) && (p_frame->pf == 1))
598 {
599 p_frame->credit = *p_data++;
600 p_buf->len--;
601 p_buf->offset++;
602 }
603 else
604 p_frame->credit = 0;
605
606 if (p_buf->len != len)
607 {
Sharvil Nanavatid5bba902014-05-04 01:33:15 -0700608 RFCOMM_TRACE_ERROR ("Bad Length2 %d %d", p_buf->len, len);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800609 return (RFC_EVENT_BAD_FRAME);
610 }
611
612 fcs = *(p_data + len);
613
614 /* All control frames that we are sending are sent with P=1, expect */
615 /* reply with F=1 */
616 /* According to TS 07.10 spec ivalid frames are discarded without */
617 /* notification to the sender */
618 switch (p_frame->type)
619 {
620 case RFCOMM_SABME:
621 if (RFCOMM_FRAME_IS_RSP(p_mcb->is_initiator, p_frame->cr)
622 || !p_frame->pf || len || !RFCOMM_VALID_DLCI (p_frame->dlci)
623 || !rfc_check_fcs (RFCOMM_CTRL_FRAME_LEN, p_start, fcs))
624 {
Sharvil Nanavatid5bba902014-05-04 01:33:15 -0700625 RFCOMM_TRACE_ERROR ("Bad SABME");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800626 return (RFC_EVENT_BAD_FRAME);
627 }
628 else
629 return (RFC_EVENT_SABME);
630
631 case RFCOMM_UA:
632 if (RFCOMM_FRAME_IS_CMD(p_mcb->is_initiator, p_frame->cr)
633 || !p_frame->pf || len || !RFCOMM_VALID_DLCI (p_frame->dlci)
634 || !rfc_check_fcs (RFCOMM_CTRL_FRAME_LEN, p_start, fcs))
635 {
Sharvil Nanavatid5bba902014-05-04 01:33:15 -0700636 RFCOMM_TRACE_ERROR ("Bad UA");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800637 return (RFC_EVENT_BAD_FRAME);
638 }
639 else
640 return (RFC_EVENT_UA);
641
642 case RFCOMM_DM:
643 if (RFCOMM_FRAME_IS_CMD(p_mcb->is_initiator, p_frame->cr)
644 || len || !RFCOMM_VALID_DLCI(p_frame->dlci)
645 || !rfc_check_fcs (RFCOMM_CTRL_FRAME_LEN, p_start, fcs))
646 {
Sharvil Nanavatid5bba902014-05-04 01:33:15 -0700647 RFCOMM_TRACE_ERROR ("Bad DM");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800648 return (RFC_EVENT_BAD_FRAME);
649 }
650 else
651 return (RFC_EVENT_DM);
652
653 case RFCOMM_DISC:
654 if (RFCOMM_FRAME_IS_RSP(p_mcb->is_initiator, p_frame->cr)
655 || !p_frame->pf || len || !RFCOMM_VALID_DLCI(p_frame->dlci)
656 || !rfc_check_fcs (RFCOMM_CTRL_FRAME_LEN, p_start, fcs))
657 {
Sharvil Nanavatid5bba902014-05-04 01:33:15 -0700658 RFCOMM_TRACE_ERROR ("Bad DISC");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800659 return (RFC_EVENT_BAD_FRAME);
660 }
661 else
662 return (RFC_EVENT_DISC);
663
664 case RFCOMM_UIH:
665 if (!RFCOMM_VALID_DLCI(p_frame->dlci))
666 {
Sharvil Nanavatid5bba902014-05-04 01:33:15 -0700667 RFCOMM_TRACE_ERROR ("Bad UIH - invalid DLCI");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800668 return (RFC_EVENT_BAD_FRAME);
669 }
670 else if (!rfc_check_fcs (2, p_start, fcs))
671 {
Sharvil Nanavatid5bba902014-05-04 01:33:15 -0700672 RFCOMM_TRACE_ERROR ("Bad UIH - FCS");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800673 return (RFC_EVENT_BAD_FRAME);
674 }
675 else if (RFCOMM_FRAME_IS_RSP(p_mcb->is_initiator, p_frame->cr))
676 {
677 /* we assume that this is ok to allow bad implementations to work */
Sharvil Nanavatid5bba902014-05-04 01:33:15 -0700678 RFCOMM_TRACE_ERROR ("Bad UIH - response");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800679 return (RFC_EVENT_UIH);
680 }
681 else
682 return (RFC_EVENT_UIH);
683 }
684
685 return (RFC_EVENT_BAD_FRAME);
686}
687
688
689/*******************************************************************************
690**
691** Function rfc_process_mx_message
692**
693** Description This function processes UIH frames received on the
694** multiplexer control channel.
695**
696*******************************************************************************/
697void rfc_process_mx_message (tRFC_MCB *p_mcb, BT_HDR *p_buf)
698{
699 UINT8 *p_data = (UINT8 *)(p_buf + 1) + p_buf->offset;
700 MX_FRAME *p_rx_frame = &rfc_cb.rfc.rx_frame;
701 UINT16 length = p_buf->len;
702 UINT8 ea, cr, mx_len;
703 BOOLEAN is_command;
704
705 p_rx_frame->ea = *p_data & RFCOMM_EA;
706 p_rx_frame->cr = (*p_data & RFCOMM_CR_MASK) >> RFCOMM_SHIFT_CR;
707 p_rx_frame->type = *p_data++ & ~(RFCOMM_CR_MASK | RFCOMM_EA_MASK);
708
709 if (!p_rx_frame->ea || !length)
710 {
Sharvil Nanavatid5bba902014-05-04 01:33:15 -0700711 RFCOMM_TRACE_ERROR ("Illegal MX Frame ea:%d len:%d", p_rx_frame->ea, length);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800712 GKI_freebuf (p_buf);
713 return;
714 }
715
716 length--;
717
718 is_command = p_rx_frame->cr;
719
720 ea = *p_data & RFCOMM_EA;
721
722 mx_len = *p_data++ >> RFCOMM_SHIFT_LENGTH1;
723 length--;
724
725 if (!ea)
726 {
727 mx_len += *p_data++ << RFCOMM_SHIFT_LENGTH2;
728 length --;
729 }
730
731 if (mx_len != length)
732 {
Sharvil Nanavatid5bba902014-05-04 01:33:15 -0700733 RFCOMM_TRACE_ERROR ("Bad MX frame");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800734 GKI_freebuf (p_buf);
735 return;
736 }
737
738 switch (p_rx_frame->type)
739 {
740 case RFCOMM_MX_PN:
741 if (length != RFCOMM_MX_PN_LEN)
742 break;
743
744 p_rx_frame->dlci = *p_data++ & RFCOMM_PN_DLCI_MASK;
745 p_rx_frame->u.pn.frame_type = *p_data & RFCOMM_PN_FRAME_TYPE_MASK;
746 p_rx_frame->u.pn.conv_layer = *p_data++ & RFCOMM_PN_CONV_LAYER_MASK;
747 p_rx_frame->u.pn.priority = *p_data++ & RFCOMM_PN_PRIORITY_MASK;
748 p_rx_frame->u.pn.t1 = *p_data++;
749 p_rx_frame->u.pn.mtu = *p_data + (*(p_data + 1) << 8);
750 p_data += 2;
751 p_rx_frame->u.pn.n2 = *p_data++;
752 p_rx_frame->u.pn.k = *p_data++ & RFCOMM_PN_K_MASK;
753
754 if (!p_rx_frame->dlci
755 || !RFCOMM_VALID_DLCI (p_rx_frame->dlci)
756 || (p_rx_frame->u.pn.mtu < RFCOMM_MIN_MTU)
757 || (p_rx_frame->u.pn.mtu > RFCOMM_MAX_MTU))
758 {
Sharvil Nanavatid5bba902014-05-04 01:33:15 -0700759 RFCOMM_TRACE_ERROR ("Bad PN frame");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800760 break;
761 }
762
763 GKI_freebuf (p_buf);
764
765 rfc_process_pn (p_mcb, is_command, p_rx_frame);
766 return;
767
768 case RFCOMM_MX_TEST:
769 if (!length)
770 break;
771
772 p_rx_frame->u.test.p_data = p_data;
773 p_rx_frame->u.test.data_len = length;
774
775 p_buf->offset += 2;
776 p_buf->len -= 2;
777
778 if (is_command)
779 rfc_send_test (p_mcb, FALSE, p_buf);
780 else
781 rfc_process_test_rsp (p_mcb, p_buf);
782 return;
783
784 case RFCOMM_MX_FCON:
785 if (length != RFCOMM_MX_FCON_LEN)
786 break;
787
788 GKI_freebuf (p_buf);
789
790 rfc_process_fcon (p_mcb, is_command);
791 return;
792
793 case RFCOMM_MX_FCOFF:
794 if (length != RFCOMM_MX_FCOFF_LEN)
795 break;
796
797 GKI_freebuf (p_buf);
798
799 rfc_process_fcoff (p_mcb, is_command);
800 return;
801
802 case RFCOMM_MX_MSC:
803
804 ea = *p_data & RFCOMM_EA;
805 cr = (*p_data & RFCOMM_CR_MASK) >> RFCOMM_SHIFT_CR;
806 p_rx_frame->dlci = *p_data++ >> RFCOMM_SHIFT_DLCI;
807
808 if (!ea || !cr || !p_rx_frame->dlci
809 || !RFCOMM_VALID_DLCI (p_rx_frame->dlci))
810 {
Sharvil Nanavatid5bba902014-05-04 01:33:15 -0700811 RFCOMM_TRACE_ERROR ("Bad MSC frame");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800812 break;
813 }
814
815 p_rx_frame->u.msc.signals = *p_data++;
816
817 if (mx_len == RFCOMM_MX_MSC_LEN_WITH_BREAK)
818 {
819 p_rx_frame->u.msc.break_present = *p_data & RFCOMM_MSC_BREAK_PRESENT_MASK;
820 p_rx_frame->u.msc.break_duration = (*p_data & RFCOMM_MSC_BREAK_MASK) >> RFCOMM_MSC_SHIFT_BREAK;
821 }
822 else
823 {
824 p_rx_frame->u.msc.break_present = FALSE;
825 p_rx_frame->u.msc.break_duration = 0;
826 }
827 GKI_freebuf (p_buf);
828
829 rfc_process_msc (p_mcb, is_command, p_rx_frame);
830 return;
831
832 case RFCOMM_MX_NSC:
833 if ((length != RFCOMM_MX_NSC_LEN) || !is_command)
834 break;
835
836 p_rx_frame->u.nsc.ea = *p_data & RFCOMM_EA;
837 p_rx_frame->u.nsc.cr = (*p_data & RFCOMM_CR_MASK) >> RFCOMM_SHIFT_CR;
838 p_rx_frame->u.nsc.type = *p_data++ >> RFCOMM_SHIFT_DLCI;
839
840 GKI_freebuf (p_buf);
841
842 rfc_process_nsc (p_mcb, p_rx_frame);
843 return;
844
845 case RFCOMM_MX_RPN:
846 if ((length != RFCOMM_MX_RPN_REQ_LEN) && (length != RFCOMM_MX_RPN_LEN))
847 break;
848
849 ea = *p_data & RFCOMM_EA;
850 cr = (*p_data & RFCOMM_CR_MASK) >> RFCOMM_SHIFT_CR;
851 p_rx_frame->dlci = *p_data++ >> RFCOMM_SHIFT_DLCI;
852
853 if (!ea || !cr || !p_rx_frame->dlci
854 || !RFCOMM_VALID_DLCI (p_rx_frame->dlci))
855 {
Sharvil Nanavatid5bba902014-05-04 01:33:15 -0700856 RFCOMM_TRACE_ERROR ("Bad RPN frame");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800857 break;
858 }
859
860 p_rx_frame->u.rpn.is_request = (length == RFCOMM_MX_RPN_REQ_LEN);
861
862 if (!p_rx_frame->u.rpn.is_request)
863 {
864 p_rx_frame->u.rpn.baud_rate = *p_data++;
865 p_rx_frame->u.rpn.byte_size = (*p_data >> RFCOMM_RPN_BITS_SHIFT) & RFCOMM_RPN_BITS_MASK;
866 p_rx_frame->u.rpn.stop_bits = (*p_data >> RFCOMM_RPN_STOP_BITS_SHIFT) & RFCOMM_RPN_STOP_BITS_MASK;
867 p_rx_frame->u.rpn.parity = (*p_data >> RFCOMM_RPN_PARITY_SHIFT) & RFCOMM_RPN_PARITY_MASK;
868 p_rx_frame->u.rpn.parity_type = (*p_data++ >> RFCOMM_RPN_PARITY_TYPE_SHIFT) & RFCOMM_RPN_PARITY_TYPE_MASK;
869
870 p_rx_frame->u.rpn.fc_type = *p_data++ & RFCOMM_FC_MASK;
871 p_rx_frame->u.rpn.xon_char = *p_data++;
872 p_rx_frame->u.rpn.xoff_char = *p_data++;
873 p_rx_frame->u.rpn.param_mask = (*p_data + (*(p_data + 1) << 8)) & RFCOMM_RPN_PM_MASK;
874 }
875 GKI_freebuf (p_buf);
876
877 rfc_process_rpn (p_mcb, is_command, p_rx_frame->u.rpn.is_request, p_rx_frame);
878 return;
879
880 case RFCOMM_MX_RLS:
881 if (length != RFCOMM_MX_RLS_LEN)
882 break;
883
884 ea = *p_data & RFCOMM_EA;
885 cr = (*p_data & RFCOMM_CR_MASK) >> RFCOMM_SHIFT_CR;
886
887 p_rx_frame->dlci = *p_data++ >> RFCOMM_SHIFT_DLCI;
888 p_rx_frame->u.rls.line_status = (*p_data & ~0x01);
889
890 if (!ea || !cr || !p_rx_frame->dlci
891 || !RFCOMM_VALID_DLCI (p_rx_frame->dlci))
892 {
Sharvil Nanavatid5bba902014-05-04 01:33:15 -0700893 RFCOMM_TRACE_ERROR ("Bad RPN frame");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800894 break;
895 }
896
897 GKI_freebuf (p_buf);
898
899 rfc_process_rls (p_mcb, is_command, p_rx_frame);
900 return;
901 }
902
903 GKI_freebuf (p_buf);
904
905 if (is_command)
906 rfc_send_nsc (p_mcb);
907}
908