OSDN Git Service

739469f6433ecda7c8473ad2fd90ede61d904b02
[android-x86/system-bt.git] / stack / rfcomm / rfc_ts_frames.c
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 *******************************************************************************/
41 void 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 *******************************************************************************/
70 void 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 *******************************************************************************/
99 void 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 *******************************************************************************/
128 void 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 *******************************************************************************/
157 void 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 *******************************************************************************/
220 void 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 *******************************************************************************/
262 void 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 *******************************************************************************/
287 void 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 *******************************************************************************/
312 void 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 *******************************************************************************/
363 void 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 *******************************************************************************/
391 void 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 *******************************************************************************/
420 void 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 *******************************************************************************/
470 void 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 *******************************************************************************/
510 void 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 *******************************************************************************/
538 UINT8 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 *******************************************************************************/
665 void 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