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 877