port_utils.cc 18 KB

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