1/******************************************************************************
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    {
579        RFCOMM_TRACE_ERROR ("Bad Length1: %d", p_buf->len);
580        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    {
586        RFCOMM_TRACE_ERROR ("Bad Address(EA must be 1)");
587        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    {
608        RFCOMM_TRACE_ERROR ("Bad Length2 %d %d", p_buf->len, len);
609        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        {
625            RFCOMM_TRACE_ERROR ("Bad SABME");
626            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        {
636            RFCOMM_TRACE_ERROR ("Bad UA");
637            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        {
647            RFCOMM_TRACE_ERROR ("Bad DM");
648            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        {
658            RFCOMM_TRACE_ERROR ("Bad DISC");
659            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        {
667            RFCOMM_TRACE_ERROR ("Bad UIH - invalid DLCI");
668            return (RFC_EVENT_BAD_FRAME);
669        }
670        else if (!rfc_check_fcs (2, p_start, fcs))
671        {
672            RFCOMM_TRACE_ERROR ("Bad UIH - FCS");
673            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 */
678            RFCOMM_TRACE_ERROR ("Bad UIH - response");
679            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    {
711        RFCOMM_TRACE_ERROR ("Illegal MX Frame ea:%d len:%d", p_rx_frame->ea, length);
712        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    {
733        RFCOMM_TRACE_ERROR ("Bad MX frame");
734        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        {
759            RFCOMM_TRACE_ERROR ("Bad PN frame");
760            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        {
811            RFCOMM_TRACE_ERROR ("Bad MSC frame");
812            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        {
856            RFCOMM_TRACE_ERROR ("Bad RPN frame");
857            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        {
893            RFCOMM_TRACE_ERROR ("Bad RPN frame");
894            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
909