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