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  *
21  * This file contains functions callable by an application
22  * running on top of RFCOMM
23  *
24  *****************************************************************************/
25 
26 #include <cstring>
27 #include "bt_common.h"
28 #include "bt_target.h"
29 #include "bt_utils.h"
30 #include "l2c_api.h"
31 #include "osi/include/osi.h"
32 #include "port_api.h"
33 #include "port_int.h"
34 #include "rfc_int.h"
35 #include "rfcdefs.h"
36 
37 tRFC_CB rfc_cb;
38 std::unordered_map<uint32_t, uint16_t> rfcomm_security_records;
39 std::unordered_map<uint16_t /* sci */, tRFC_MCB*> rfc_lcid_mcb;
40 
41 /*******************************************************************************
42  *
43  * Function         RFCOMM_StartReq
44  *
45  * Description      This function handles Start Request from the upper layer.
46  *                  If RFCOMM multiplexer channel can not be allocated
47  *                  send start not accepted confirmation.  Otherwise dispatch
48  *                  start event to the state machine.
49  *
50  ******************************************************************************/
RFCOMM_StartReq(tRFC_MCB * p_mcb)51 void RFCOMM_StartReq(tRFC_MCB* p_mcb) {
52   rfc_mx_sm_execute(p_mcb, RFC_MX_EVENT_START_REQ, nullptr);
53 }
54 
55 /*******************************************************************************
56  *
57  * Function         RFCOMM_StartRsp
58  *
59  * Description      This function handles Start Response from the upper layer.
60  *                  Save upper layer handle and result of the Start Indication
61  *                  in the control block and dispatch event to the FSM.
62  *
63  ******************************************************************************/
RFCOMM_StartRsp(tRFC_MCB * p_mcb,uint16_t result)64 void RFCOMM_StartRsp(tRFC_MCB* p_mcb, uint16_t result) {
65   rfc_mx_sm_execute(p_mcb, RFC_MX_EVENT_START_RSP, &result);
66 }
67 
68 /*******************************************************************************
69  *
70  * Function         RFCOMM_DlcEstablishReq
71  *
72  * Description      This function is called by the user app to establish
73  *                  connection with the specific dlci on a specific bd device.
74  *                  It will allocate RFCOMM connection control block if not
75  *                  allocated before and dispatch open event to the state
76  *                  machine.
77  *
78  ******************************************************************************/
RFCOMM_DlcEstablishReq(tRFC_MCB * p_mcb,uint8_t dlci,UNUSED_ATTR uint16_t mtu)79 void RFCOMM_DlcEstablishReq(tRFC_MCB* p_mcb, uint8_t dlci,
80                             UNUSED_ATTR uint16_t mtu) {
81   if (p_mcb->state != RFC_MX_STATE_CONNECTED) {
82     PORT_DlcEstablishCnf(p_mcb, dlci, 0, RFCOMM_ERROR);
83     return;
84   }
85 
86   tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
87   if (p_port == nullptr) {
88     RFCOMM_TRACE_WARNING("%s Unable to find DLCI port dlci:%d", __func__, dlci);
89     return;
90   }
91 
92   rfc_port_sm_execute(p_port, RFC_EVENT_OPEN, nullptr);
93 }
94 
95 /*******************************************************************************
96  *
97  * Function         RFCOMM_DlcEstablishRsp
98  *
99  * Description      This function is called by the port emulation entity
100  *                  acks Establish Indication.
101  *
102  ******************************************************************************/
RFCOMM_DlcEstablishRsp(tRFC_MCB * p_mcb,uint8_t dlci,UNUSED_ATTR uint16_t mtu,uint16_t result)103 void RFCOMM_DlcEstablishRsp(tRFC_MCB* p_mcb, uint8_t dlci,
104                             UNUSED_ATTR uint16_t mtu, uint16_t result) {
105   if ((p_mcb->state != RFC_MX_STATE_CONNECTED) && (result == RFCOMM_SUCCESS)) {
106     PORT_DlcReleaseInd(p_mcb, dlci);
107     return;
108   }
109 
110   tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
111   if (p_port == nullptr) {
112     RFCOMM_TRACE_WARNING("%s Unable to find DLCI port dlci:%d", __func__, dlci);
113     return;
114   }
115   rfc_port_sm_execute(p_port, RFC_EVENT_ESTABLISH_RSP, &result);
116 }
117 
118 /*******************************************************************************
119  *
120  * Function         RFCOMM_ParameterNegotiationRequest
121  *
122  * Description      This function is called by the user app to start
123  *                  DLC parameter negotiation.  Port emulation can send this
124  *                  request before actually establishing the DLC.  In this
125  *                  case the function will allocate RFCOMM connection control
126  *                  block.
127  *
128  ******************************************************************************/
RFCOMM_ParameterNegotiationRequest(tRFC_MCB * p_mcb,uint8_t dlci,uint16_t mtu)129 void RFCOMM_ParameterNegotiationRequest(tRFC_MCB* p_mcb, uint8_t dlci,
130                                         uint16_t mtu) {
131   uint8_t flow;
132   uint8_t cl;
133   uint8_t k;
134 
135   tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
136   if (p_port == nullptr) {
137     RFCOMM_TRACE_WARNING("%s Unable to find DLCI port dlci:%d", __func__, dlci);
138     return;
139   }
140 
141   if (p_mcb->state != RFC_MX_STATE_CONNECTED) {
142     p_port->error = PORT_PAR_NEG_FAILED;
143     return;
144   }
145 
146   /* Negotiate the flow control mechanism.  If flow control mechanism for */
147   /* mux has not been set yet, use our default value.  If it has been set, */
148   /* use that value. */
149   flow = (p_mcb->flow == PORT_FC_UNDEFINED) ? PORT_FC_DEFAULT : p_mcb->flow;
150 
151   /* Set convergence layer and number of credits (k) */
152   if (flow == PORT_FC_CREDIT) {
153     cl = RFCOMM_PN_CONV_LAYER_CBFC_I;
154     k = (p_port->credit_rx_max < RFCOMM_K_MAX) ? p_port->credit_rx_max
155                                                : RFCOMM_K_MAX;
156     p_port->credit_rx = k;
157   } else {
158     cl = RFCOMM_PN_CONV_LAYER_TYPE_1;
159     k = 0;
160   }
161 
162   /* Send Parameter Negotiation Command UIH frame */
163   p_port->rfc.expected_rsp |= RFC_RSP_PN;
164 
165   rfc_send_pn(p_mcb, dlci, true, mtu, cl, k);
166 
167   rfc_port_timer_start(p_port, RFC_T2_TIMEOUT);
168 }
169 
170 /*******************************************************************************
171  *
172  * Function         RFCOMM_ParameterNegotiationResponse
173  *
174  * Description      This function is called by the user app to acknowledge
175  *                  DLC parameter negotiation.
176  *
177  ******************************************************************************/
RFCOMM_ParameterNegotiationResponse(tRFC_MCB * p_mcb,uint8_t dlci,uint16_t mtu,uint8_t cl,uint8_t k)178 void RFCOMM_ParameterNegotiationResponse(tRFC_MCB* p_mcb, uint8_t dlci,
179                                          uint16_t mtu, uint8_t cl, uint8_t k) {
180   if (p_mcb->state != RFC_MX_STATE_CONNECTED) return;
181 
182   /* Send Parameter Negotiation Response UIH frame */
183   rfc_send_pn(p_mcb, dlci, false, mtu, cl, k);
184 }
185 
186 /*******************************************************************************
187  *
188  * Function         RFCOMM_PortParameterNegotiationRequest
189  *
190  * Description      This function is called by the user app to start
191  *                  Remote Port parameter negotiation.  Port emulation can
192  *                  send this request before actually establishing the DLC.
193  *                  In this case the function will allocate RFCOMM connection
194  *                  control block.
195  *
196  ******************************************************************************/
RFCOMM_PortParameterNegotiationRequest(tRFC_MCB * p_mcb,uint8_t dlci,tPORT_STATE * p_pars)197 void RFCOMM_PortParameterNegotiationRequest(tRFC_MCB* p_mcb, uint8_t dlci,
198                                             tPORT_STATE* p_pars) {
199   if (p_mcb->state != RFC_MX_STATE_CONNECTED) {
200     PORT_PortNegCnf(p_mcb, dlci, nullptr, RFCOMM_ERROR);
201     return;
202   }
203 
204   tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
205   if (p_port == nullptr) {
206     RFCOMM_TRACE_WARNING("%s Unable to find DLCI port dlci:%d", __func__, dlci);
207     return;
208   }
209 
210   /* Send Parameter Negotiation Command UIH frame */
211   if (!p_pars)
212     p_port->rfc.expected_rsp |= RFC_RSP_RPN_REPLY;
213   else
214     p_port->rfc.expected_rsp |= RFC_RSP_RPN;
215 
216   rfc_send_rpn(p_mcb, dlci, true, p_pars, RFCOMM_RPN_PM_MASK);
217   rfc_port_timer_start(p_port, RFC_T2_TIMEOUT);
218 }
219 
220 /*******************************************************************************
221  *
222  * Function         RFCOMM_PortParameterNegotiationResponse
223  *
224  * Description      This function is called by the user app to acknowledge
225  *                  Port parameters negotiation.
226  *
227  ******************************************************************************/
RFCOMM_PortParameterNegotiationResponse(tRFC_MCB * p_mcb,uint8_t dlci,tPORT_STATE * p_pars,uint16_t param_mask)228 void RFCOMM_PortParameterNegotiationResponse(tRFC_MCB* p_mcb, uint8_t dlci,
229                                              tPORT_STATE* p_pars,
230                                              uint16_t param_mask) {
231   if (p_mcb->state != RFC_MX_STATE_CONNECTED) return;
232 
233   rfc_send_rpn(p_mcb, dlci, false, p_pars, param_mask);
234 }
235 
236 /*******************************************************************************
237  *
238  * Function         RFCOMM_ControlReq
239  *
240  * Description      This function is called by the port entity to send control
241  *                  parameters to remote port emulation entity.
242  *
243  ******************************************************************************/
RFCOMM_ControlReq(tRFC_MCB * p_mcb,uint8_t dlci,tPORT_CTRL * p_pars)244 void RFCOMM_ControlReq(tRFC_MCB* p_mcb, uint8_t dlci, tPORT_CTRL* p_pars) {
245   tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
246   if (p_port == nullptr) {
247     RFCOMM_TRACE_WARNING("%s Unable to find DLCI port dlci:%d", __func__, dlci);
248     return;
249   }
250 
251   if ((p_port->state != PORT_STATE_OPENED) ||
252       (p_port->rfc.state != RFC_STATE_OPENED))
253     return;
254 
255   p_port->port_ctrl |= PORT_CTRL_REQ_SENT;
256 
257   p_port->rfc.expected_rsp |= RFC_RSP_MSC;
258 
259   rfc_send_msc(p_mcb, dlci, true, p_pars);
260   rfc_port_timer_start(p_port, RFC_T2_TIMEOUT);
261 }
262 
263 /*******************************************************************************
264  *
265  * Function         RFCOMM_FlowReq
266  *
267  * Description      This function is called by the port entity when flow
268  *                  control state has changed.  Enable flag passed shows if
269  *                  port can accept more data.
270  *
271  ******************************************************************************/
RFCOMM_FlowReq(tRFC_MCB * p_mcb,uint8_t dlci,bool enable)272 void RFCOMM_FlowReq(tRFC_MCB* p_mcb, uint8_t dlci, bool enable) {
273   tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
274   if (p_port == nullptr) {
275     RFCOMM_TRACE_WARNING("%s Unable to find DLCI port dlci:%d", __func__, dlci);
276     return;
277   }
278 
279   if ((p_port->state != PORT_STATE_OPENED) ||
280       (p_port->rfc.state != RFC_STATE_OPENED))
281     return;
282 
283   p_port->local_ctrl.fc = !enable;
284 
285   p_port->rfc.expected_rsp |= RFC_RSP_MSC;
286 
287   rfc_send_msc(p_mcb, dlci, true, &p_port->local_ctrl);
288   rfc_port_timer_start(p_port, RFC_T2_TIMEOUT);
289 }
290 
291 /*******************************************************************************
292  *
293  * Function         RFCOMM_LineStatusReq
294  *
295  * Description      This function is called by the port entity when line
296  *                  status should be delivered to the peer.
297  *
298  ******************************************************************************/
RFCOMM_LineStatusReq(tRFC_MCB * p_mcb,uint8_t dlci,uint8_t status)299 void RFCOMM_LineStatusReq(tRFC_MCB* p_mcb, uint8_t dlci, uint8_t status) {
300   tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
301   if (p_port == nullptr) {
302     RFCOMM_TRACE_WARNING("%s Unable to find DLCI port dlci:%d", __func__, dlci);
303     return;
304   }
305 
306   if ((p_port->state != PORT_STATE_OPENED) ||
307       (p_port->rfc.state != RFC_STATE_OPENED))
308     return;
309 
310   p_port->rfc.expected_rsp |= RFC_RSP_RLS;
311 
312   rfc_send_rls(p_mcb, dlci, true, status);
313   rfc_port_timer_start(p_port, RFC_T2_TIMEOUT);
314 }
315 
316 /*******************************************************************************
317  *
318  * Function         RFCOMM_DlcReleaseReq
319  *
320  * Description      This function is called by the PORT unit to close DLC
321  *
322  ******************************************************************************/
RFCOMM_DlcReleaseReq(tRFC_MCB * p_mcb,uint8_t dlci)323 void RFCOMM_DlcReleaseReq(tRFC_MCB* p_mcb, uint8_t dlci) {
324   rfc_port_sm_execute(port_find_mcb_dlci_port(p_mcb, dlci), RFC_EVENT_CLOSE,
325                       nullptr);
326 }
327 
328 /*******************************************************************************
329  *
330  * Function         RFCOMM_DataReq
331  *
332  * Description      This function is called by the user app to send data buffer
333  *
334  ******************************************************************************/
RFCOMM_DataReq(tRFC_MCB * p_mcb,uint8_t dlci,BT_HDR * p_buf)335 void RFCOMM_DataReq(tRFC_MCB* p_mcb, uint8_t dlci, BT_HDR* p_buf) {
336   rfc_port_sm_execute(port_find_mcb_dlci_port(p_mcb, dlci), RFC_EVENT_DATA,
337                       p_buf);
338 }
339