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 *******************************************************************************/
rfc_send_sabme(tRFC_MCB * p_mcb,UINT8 dlci)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 *******************************************************************************/
rfc_send_ua(tRFC_MCB * p_mcb,UINT8 dlci)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 *******************************************************************************/
rfc_send_dm(tRFC_MCB * p_mcb,UINT8 dlci,BOOLEAN pf)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 *******************************************************************************/
rfc_send_disc(tRFC_MCB * p_mcb,UINT8 dlci)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 *******************************************************************************/
rfc_send_buf_uih(tRFC_MCB * p_mcb,UINT8 dlci,BT_HDR * p_buf)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 *******************************************************************************/
rfc_send_pn(tRFC_MCB * p_mcb,UINT8 dlci,BOOLEAN is_command,UINT16 mtu,UINT8 cl,UINT8 k)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 *******************************************************************************/
rfc_send_fcon(tRFC_MCB * p_mcb,BOOLEAN is_command)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 *******************************************************************************/
rfc_send_fcoff(tRFC_MCB * p_mcb,BOOLEAN is_command)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 *******************************************************************************/
rfc_send_msc(tRFC_MCB * p_mcb,UINT8 dlci,BOOLEAN is_command,tPORT_CTRL * p_pars)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 *******************************************************************************/
rfc_send_rls(tRFC_MCB * p_mcb,UINT8 dlci,BOOLEAN is_command,UINT8 status)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 *******************************************************************************/
rfc_send_nsc(tRFC_MCB * p_mcb)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 *******************************************************************************/
rfc_send_rpn(tRFC_MCB * p_mcb,UINT8 dlci,BOOLEAN is_command,tPORT_STATE * p_pars,UINT16 mask)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 *******************************************************************************/
rfc_send_test(tRFC_MCB * p_mcb,BOOLEAN is_command,BT_HDR * p_buf)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 *******************************************************************************/
rfc_send_credit(tRFC_MCB * p_mcb,UINT8 dlci,UINT8 credit)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 *******************************************************************************/
rfc_parse_data(tRFC_MCB * p_mcb,MX_FRAME * p_frame,BT_HDR * p_buf)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 *******************************************************************************/
rfc_process_mx_message(tRFC_MCB * p_mcb,BT_HDR * p_buf)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
877