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