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 * Port Emulation entity utilities 22 * 23 ******************************************************************************/ 24#include <string.h> 25 26#include "osi/include/mutex.h" 27 28#include "bt_target.h" 29#include "bt_common.h" 30#include "btm_int.h" 31#include "btu.h" 32#include "l2cdefs.h" 33#include "port_api.h" 34#include "port_int.h" 35#include "rfc_int.h" 36#include "rfcdefs.h" 37 38static const tPORT_STATE default_port_pars = 39{ 40 PORT_BAUD_RATE_9600, 41 PORT_8_BITS, 42 PORT_ONESTOPBIT, 43 PORT_PARITY_NO, 44 PORT_ODD_PARITY, 45 PORT_FC_OFF, 46 0, /* No rx_char */ 47 PORT_XON_DC1, 48 PORT_XOFF_DC3, 49}; 50 51 52 53/******************************************************************************* 54** 55** Function port_allocate_port 56** 57** Description Look through the Port Control Blocks for a free one. Note 58** that one server can open several ports with the same SCN 59** if it can support simulteneous requests from different 60** clients. 61** 62** Returns Pointer to the PORT or NULL if not found 63** 64*******************************************************************************/ 65tPORT *port_allocate_port (UINT8 dlci, BD_ADDR bd_addr) 66{ 67 tPORT *p_port = &rfc_cb.port.port[0]; 68 UINT8 xx, yy; 69 70 for (xx = 0, yy = rfc_cb.rfc.last_port + 1; xx < MAX_RFC_PORTS; xx++, yy++) 71 { 72 if (yy >= MAX_RFC_PORTS) 73 yy = 0; 74 75 p_port = &rfc_cb.port.port[yy]; 76 if (!p_port->in_use) 77 { 78 memset(p_port, 0, sizeof (tPORT)); 79 80 p_port->in_use = TRUE; 81 p_port->inx = yy + 1; 82 83 /* During the open set default state for the port connection */ 84 port_set_defaults (p_port); 85 86 p_port->rfc.port_timer = alarm_new("rfcomm_port.port_timer"); 87 rfc_cb.rfc.last_port = yy; 88 89 p_port->dlci = dlci; 90 memcpy (p_port->bd_addr, bd_addr, BD_ADDR_LEN); 91 92 RFCOMM_TRACE_DEBUG("rfc_cb.port.port[%d]:%p allocated, last_port:%d", yy, p_port, rfc_cb.rfc.last_port); 93 RFCOMM_TRACE_DEBUG("port_allocate_port:bd_addr:%02x:%02x:%02x:%02x:%02x:%02x", 94 bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]); 95 return (p_port); 96 } 97 } 98 99 /* If here, no free PORT found */ 100 return (NULL); 101} 102 103 104/******************************************************************************* 105** 106** Function port_set_defaults 107** 108** Description Set defualt port parameters 109** 110** 111*******************************************************************************/ 112void port_set_defaults (tPORT *p_port) 113{ 114 p_port->ev_mask = 0; 115 p_port->p_callback = NULL; 116 p_port->port_ctrl = 0; 117 p_port->error = 0; 118 p_port->line_status = 0; 119 p_port->rx_flag_ev_pending = FALSE; 120 p_port->peer_mtu = RFCOMM_DEFAULT_MTU; 121 122 p_port->user_port_pars = default_port_pars; 123 p_port->peer_port_pars = default_port_pars; 124 125 p_port->credit_tx = 0; 126 p_port->credit_rx = 0; 127 128 memset (&p_port->local_ctrl, 0, sizeof (p_port->local_ctrl)); 129 memset (&p_port->peer_ctrl, 0, sizeof (p_port->peer_ctrl)); 130 memset (&p_port->rx, 0, sizeof (p_port->rx)); 131 memset (&p_port->tx, 0, sizeof (p_port->tx)); 132 133 p_port->tx.queue = fixed_queue_new(SIZE_MAX); 134 p_port->rx.queue = fixed_queue_new(SIZE_MAX); 135} 136 137/******************************************************************************* 138** 139** Function port_select_mtu 140** 141** Description Select MTU which will best serve connection from our 142** point of view. 143** If our device is 1.2 or lower we calculate how many DH5s 144** fit into 1 RFCOMM buffer. 145** 146** 147*******************************************************************************/ 148void port_select_mtu (tPORT *p_port) 149{ 150 UINT16 packet_size; 151 152 /* Will select MTU only if application did not setup something */ 153 if (p_port->mtu == 0) 154 { 155 /* find packet size which connection supports */ 156 packet_size = btm_get_max_packet_size (p_port->bd_addr); 157 if (packet_size == 0) 158 { 159 /* something is very wrong */ 160 RFCOMM_TRACE_WARNING ("port_select_mtu bad packet size"); 161 p_port->mtu = RFCOMM_DEFAULT_MTU; 162 } 163 else 164 { 165 /* We try to negotiate MTU that each packet can be split into whole 166 number of max packets. For example if link is 1.2 max packet size is 339 bytes. 167 At first calculate how many whole packets it is. MAX L2CAP is 1691 + 4 overhead. 168 1695, that will be 5 Dh5 packets. Now maximum RFCOMM packet is 169 5 * 339 = 1695. Minus 4 bytes L2CAP header 1691. Minus RFCOMM 6 bytes header overhead 1685 170 171 For EDR 2.0 packet size is 1027. So we better send RFCOMM packet as 1 3DH5 packet 172 1 * 1027 = 1027. Minus 4 bytes L2CAP header 1023. Minus RFCOMM 6 bytes header overhead 1017 */ 173 if ((L2CAP_MTU_SIZE + L2CAP_PKT_OVERHEAD) >= packet_size) 174 { 175 p_port->mtu = ((L2CAP_MTU_SIZE + L2CAP_PKT_OVERHEAD) / packet_size * packet_size) - RFCOMM_DATA_OVERHEAD - L2CAP_PKT_OVERHEAD; 176 RFCOMM_TRACE_DEBUG ("port_select_mtu selected %d based on connection speed", p_port->mtu); 177 } 178 else 179 { 180 p_port->mtu = L2CAP_MTU_SIZE - RFCOMM_DATA_OVERHEAD; 181 RFCOMM_TRACE_DEBUG ("port_select_mtu selected %d based on l2cap PDU size", p_port->mtu); 182 } 183 } 184 } 185 else 186 { 187 RFCOMM_TRACE_DEBUG ("port_select_mtu application selected %d", p_port->mtu); 188 } 189 p_port->credit_rx_max = (PORT_RX_HIGH_WM / p_port->mtu); 190 if( p_port->credit_rx_max > PORT_RX_BUF_HIGH_WM ) 191 p_port->credit_rx_max = PORT_RX_BUF_HIGH_WM; 192 p_port->credit_rx_low = (PORT_RX_LOW_WM / p_port->mtu); 193 if( p_port->credit_rx_low > PORT_RX_BUF_LOW_WM ) 194 p_port->credit_rx_low = PORT_RX_BUF_LOW_WM; 195 p_port->rx_buf_critical = (PORT_RX_CRITICAL_WM / p_port->mtu); 196 if( p_port->rx_buf_critical > PORT_RX_BUF_CRITICAL_WM ) 197 p_port->rx_buf_critical = PORT_RX_BUF_CRITICAL_WM; 198 RFCOMM_TRACE_DEBUG ("port_select_mtu credit_rx_max %d, credit_rx_low %d, rx_buf_critical %d", 199 p_port->credit_rx_max, p_port->credit_rx_low, p_port->rx_buf_critical); 200} 201 202/******************************************************************************* 203** 204** Function port_release_port 205** 206** Description Release port control block. 207** 208** Returns Pointer to the PORT or NULL if not found 209** 210*******************************************************************************/ 211void port_release_port(tPORT *p_port) 212{ 213 RFCOMM_TRACE_DEBUG("%s p_port: %p state: %d keep_handle: %d", __func__, 214 p_port, p_port->rfc.state, p_port->keep_port_handle); 215 216 mutex_global_lock(); 217 BT_HDR *p_buf; 218 while ((p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_port->rx.queue)) != NULL) 219 osi_free(p_buf); 220 p_port->rx.queue_size = 0; 221 222 while ((p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_port->tx.queue)) != NULL) 223 osi_free(p_buf); 224 p_port->tx.queue_size = 0; 225 mutex_global_unlock(); 226 227 alarm_cancel(p_port->rfc.port_timer); 228 229 p_port->state = PORT_STATE_CLOSED; 230 231 if (p_port->rfc.state == RFC_STATE_CLOSED) 232 { 233 if (p_port->rfc.p_mcb) 234 { 235 p_port->rfc.p_mcb->port_inx[p_port->dlci] = 0; 236 237 /* If there are no more ports opened on this MCB release it */ 238 rfc_check_mcb_active(p_port->rfc.p_mcb); 239 } 240 241 rfc_port_timer_stop (p_port); 242 fixed_queue_free(p_port->tx.queue, NULL); 243 p_port->tx.queue = NULL; 244 fixed_queue_free(p_port->rx.queue, NULL); 245 p_port->rx.queue = NULL; 246 247 if (p_port->keep_port_handle) 248 { 249 RFCOMM_TRACE_DEBUG("%s Re-initialize handle: %d", __func__, p_port->inx); 250 251 /* save event mask and callback */ 252 UINT32 mask = p_port->ev_mask; 253 tPORT_CALLBACK *p_port_cb = p_port->p_callback; 254 tPORT_STATE user_port_pars = p_port->user_port_pars; 255 256 port_set_defaults(p_port); 257 258 /* restore */ 259 p_port->ev_mask = mask; 260 p_port->p_callback = p_port_cb; 261 p_port->user_port_pars = user_port_pars; 262 p_port->mtu = p_port->keep_mtu; 263 264 p_port->state = PORT_STATE_OPENING; 265 p_port->rfc.p_mcb = NULL; 266 if (p_port->is_server) 267 p_port->dlci &= 0xfe; 268 269 p_port->local_ctrl.modem_signal = p_port->default_signal_state; 270 memcpy (p_port->bd_addr, BT_BD_ANY, BD_ADDR_LEN); 271 } else { 272 RFCOMM_TRACE_DEBUG("%s Clean-up handle: %d", __func__, p_port->inx); 273 alarm_free(p_port->rfc.port_timer); 274 memset (p_port, 0, sizeof (tPORT)); 275 } 276 } 277} 278 279/******************************************************************************* 280** 281** Function port_find_mcb 282** 283** Description This function checks if connection exists to device with 284** the BD_ADDR. 285** 286*******************************************************************************/ 287tRFC_MCB *port_find_mcb (BD_ADDR bd_addr) 288{ 289 int i; 290 291 for (i = 0; i < MAX_BD_CONNECTIONS; i++) 292 { 293 if ((rfc_cb.port.rfc_mcb[i].state != RFC_MX_STATE_IDLE) 294 && !memcmp (rfc_cb.port.rfc_mcb[i].bd_addr, bd_addr, BD_ADDR_LEN)) 295 { 296 /* Multiplexer channel found do not change anything */ 297 RFCOMM_TRACE_DEBUG("port_find_mcb: found bd_addr:%02x:%02x:%02x:%02x:%02x:%02x", 298 bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]); 299 RFCOMM_TRACE_DEBUG("port_find_mcb: rfc_cb.port.rfc_mcb:index:%d, %p, lcid:%d", 300 i, &rfc_cb.port.rfc_mcb[i], rfc_cb.port.rfc_mcb[i].lcid); 301 return (&rfc_cb.port.rfc_mcb[i]); 302 } 303 } 304 RFCOMM_TRACE_DEBUG("port_find_mcb: not found, bd_addr:%02x:%02x:%02x:%02x:%02x:%02x", 305 bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]); 306 return (NULL); 307} 308 309 310/******************************************************************************* 311** 312** Function port_find_mcb_dlci_port 313** 314** Description Find port on the multiplexer channel based on DLCI. If 315** this port with DLCI not found try to use even DLCI. This 316** is for the case when client is establishing connection on 317** none-initiator MCB. 318** 319** Returns Pointer to the PORT or NULL if not found 320** 321*******************************************************************************/ 322tPORT *port_find_mcb_dlci_port (tRFC_MCB *p_mcb, UINT8 dlci) 323{ 324 UINT8 inx; 325 326 if (!p_mcb) 327 return (NULL); 328 329 if (dlci > RFCOMM_MAX_DLCI) 330 return (NULL); 331 332 inx = p_mcb->port_inx[dlci]; 333 if (inx == 0) 334 { 335 RFCOMM_TRACE_DEBUG("port_find_mcb_dlci_port: p_mcb:%p, port_inx[dlci:%d] is 0", p_mcb, dlci); 336 return (NULL); 337 } 338 else 339 return (&rfc_cb.port.port[inx - 1]); 340} 341 342 343/******************************************************************************* 344** 345** Function port_find_dlci_port 346** 347** Description Find port with DLCI not assigned to multiplexer channel 348** 349** Returns Pointer to the PORT or NULL if not found 350** 351*******************************************************************************/ 352tPORT *port_find_dlci_port (UINT8 dlci) 353{ 354 UINT16 i; 355 tPORT *p_port; 356 357 for (i = 0; i < MAX_RFC_PORTS; i++) 358 { 359 p_port = &rfc_cb.port.port[i]; 360 361 if (p_port->in_use && (p_port->rfc.p_mcb == NULL)) 362 { 363 if (p_port->dlci == dlci) 364 { 365 return (p_port); 366 } 367 else if ((dlci & 0x01) && (p_port->dlci == (dlci - 1))) 368 { 369 p_port->dlci++; 370 return (p_port); 371 } 372 } 373 } 374 return (NULL); 375} 376 377 378/******************************************************************************* 379** 380** Function port_find_port 381** 382** Description Find port with DLCI, BD_ADDR 383** 384** Returns Pointer to the PORT or NULL if not found 385** 386*******************************************************************************/ 387tPORT *port_find_port (UINT8 dlci, BD_ADDR bd_addr) 388{ 389 UINT16 i; 390 tPORT *p_port; 391 392 for (i = 0; i < MAX_RFC_PORTS; i++) 393 { 394 p_port = &rfc_cb.port.port[i]; 395 if (p_port->in_use 396 && (p_port->dlci == dlci) 397 && !memcmp (p_port->bd_addr, bd_addr, BD_ADDR_LEN)) 398 { 399 return (p_port); 400 } 401 } 402 return (NULL); 403} 404 405 406/******************************************************************************* 407** 408** Function port_flow_control_user 409** 410** Description Check the current user flow control and if necessary return 411** events to be send to the user based on the user's specified 412** flow control type. 413** 414** Returns event mask to be returned to the application 415** 416*******************************************************************************/ 417UINT32 port_flow_control_user (tPORT *p_port) 418{ 419 UINT32 event = 0; 420 421 /* Flow control to the user can be caused by flow controlling by the peer */ 422 /* (FlowInd, or flow control by the peer RFCOMM (Fcon) or internally if */ 423 /* tx_queue is full */ 424 BOOLEAN fc = p_port->tx.peer_fc 425 || !p_port->rfc.p_mcb 426 || !p_port->rfc.p_mcb->peer_ready 427 || (p_port->tx.queue_size > PORT_TX_HIGH_WM) 428 || (fixed_queue_length(p_port->tx.queue) > PORT_TX_BUF_HIGH_WM); 429 430 if (p_port->tx.user_fc == fc) 431 return (0); 432 433 p_port->tx.user_fc = fc; 434 435 if (fc) 436 event = PORT_EV_FC; 437 else 438 event = PORT_EV_FC | PORT_EV_FCS; 439 440 return (event); 441} 442 443 444/******************************************************************************* 445** 446** Function port_get_signal_changes 447** 448** Description Check modem signals that has been changed 449** 450** Returns event mask to be returned to the application 451** 452*******************************************************************************/ 453UINT32 port_get_signal_changes (tPORT *p_port, UINT8 old_signals, UINT8 signal) 454{ 455 UINT8 changed_signals = (signal ^ old_signals); 456 UINT32 events = 0; 457 458 if (changed_signals & PORT_DTRDSR_ON) 459 { 460 events |= PORT_EV_DSR; 461 462 if (signal & PORT_DTRDSR_ON) 463 events |= PORT_EV_DSRS; 464 } 465 466 if (changed_signals & PORT_CTSRTS_ON) 467 { 468 events |= PORT_EV_CTS; 469 470 if (signal & PORT_CTSRTS_ON) 471 events |= PORT_EV_CTSS; 472 } 473 474 if (changed_signals & PORT_RING_ON) 475 events |= PORT_EV_RING; 476 477 if (changed_signals & PORT_DCD_ON) 478 { 479 events |= PORT_EV_RLSD; 480 481 if (signal & PORT_DCD_ON) 482 events |= PORT_EV_RLSDS; 483 } 484 485 return (p_port->ev_mask & events); 486} 487 488/******************************************************************************* 489** 490** Function port_flow_control_peer 491** 492** Description Send flow control messages to the peer for both enabling 493** and disabling flow control, for both credit-based and 494** TS 07.10 flow control mechanisms. 495** 496** Returns nothing 497** 498*******************************************************************************/ 499void port_flow_control_peer(tPORT *p_port, BOOLEAN enable, UINT16 count) 500{ 501 if (!p_port->rfc.p_mcb) 502 return; 503 504 /* If using credit based flow control */ 505 if (p_port->rfc.p_mcb->flow == PORT_FC_CREDIT) 506 { 507 /* if want to enable flow from peer */ 508 if (enable) 509 { 510 /* update rx credits */ 511 if (count > p_port->credit_rx) 512 { 513 p_port->credit_rx = 0; 514 } 515 else 516 { 517 p_port->credit_rx -= count; 518 } 519 520 /* If credit count is less than low credit watermark, and user */ 521 /* did not force flow control, send a credit update */ 522 /* There might be a special case when we just adjusted rx_max */ 523 if ((p_port->credit_rx <= p_port->credit_rx_low) 524 && !p_port->rx.user_fc 525 && (p_port->credit_rx_max > p_port->credit_rx)) 526 { 527 rfc_send_credit(p_port->rfc.p_mcb, p_port->dlci, 528 (UINT8) (p_port->credit_rx_max - p_port->credit_rx)); 529 530 p_port->credit_rx = p_port->credit_rx_max; 531 532 p_port->rx.peer_fc = FALSE; 533 } 534 } 535 /* else want to disable flow from peer */ 536 else 537 { 538 /* if client registered data callback, just do what they want */ 539 if (p_port->p_data_callback || p_port->p_data_co_callback) 540 { 541 p_port->rx.peer_fc = TRUE; 542 } 543 /* if queue count reached credit rx max, set peer fc */ 544 else if (fixed_queue_length(p_port->rx.queue) >= p_port->credit_rx_max) 545 { 546 p_port->rx.peer_fc = TRUE; 547 } 548 } 549 } 550 /* else using TS 07.10 flow control */ 551 else 552 { 553 /* if want to enable flow from peer */ 554 if (enable) 555 { 556 /* If rfcomm suspended traffic from the peer based on the rx_queue_size */ 557 /* check if it can be resumed now */ 558 if (p_port->rx.peer_fc 559 && (p_port->rx.queue_size < PORT_RX_LOW_WM) 560 && (fixed_queue_length(p_port->rx.queue) < PORT_RX_BUF_LOW_WM)) 561 { 562 p_port->rx.peer_fc = FALSE; 563 564 /* If user did not force flow control allow traffic now */ 565 if (!p_port->rx.user_fc) 566 RFCOMM_FlowReq (p_port->rfc.p_mcb, p_port->dlci, TRUE); 567 } 568 } 569 /* else want to disable flow from peer */ 570 else 571 { 572 /* if client registered data callback, just do what they want */ 573 if (p_port->p_data_callback || p_port->p_data_co_callback) 574 { 575 p_port->rx.peer_fc = TRUE; 576 RFCOMM_FlowReq (p_port->rfc.p_mcb, p_port->dlci, FALSE); 577 } 578 /* Check the size of the rx queue. If it exceeds certain */ 579 /* level and flow control has not been sent to the peer do it now */ 580 else if ( ((p_port->rx.queue_size > PORT_RX_HIGH_WM) 581 || (fixed_queue_length(p_port->rx.queue) > PORT_RX_BUF_HIGH_WM)) 582 && !p_port->rx.peer_fc) 583 { 584 RFCOMM_TRACE_EVENT ("PORT_DataInd Data reached HW. Sending FC set."); 585 586 p_port->rx.peer_fc = TRUE; 587 RFCOMM_FlowReq (p_port->rfc.p_mcb, p_port->dlci, FALSE); 588 } 589 } 590 } 591} 592 593