blob: 808b567fb9fd5624a93880aacbcb6f58e6cc751e [file] [log] [blame]
The Android Open Source Project5738f832012-12-12 16:00:35 -08001/******************************************************************************
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 the Serial Port API code
22 *
23 ******************************************************************************/
24
Marie Janssen49a86702015-07-08 11:48:57 -070025#define LOG_TAG "bt_port_api"
26
Jakub Pawlowski1979fa32017-06-16 10:46:47 -070027#include <base/logging.h>
The Android Open Source Project5738f832012-12-12 16:00:35 -080028#include <string.h>
Marie Janssen49a86702015-07-08 11:48:57 -070029
Andre Eisenbachd3842ed2015-10-12 18:32:46 -070030#include "osi/include/log.h"
31#include "osi/include/mutex.h"
32
Myles Watson911d1ae2016-11-28 16:44:40 -080033#include "bt_common.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080034#include "btm_api.h"
Marie Janssen49a86702015-07-08 11:48:57 -070035#include "btm_int.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080036#include "l2c_api.h"
Andre Eisenbachd3842ed2015-10-12 18:32:46 -070037#include "port_api.h"
Marie Janssen49a86702015-07-08 11:48:57 -070038#include "port_int.h"
39#include "rfc_int.h"
40#include "rfcdefs.h"
41#include "sdp_api.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080042
43/* duration of break in 200ms units */
Myles Watson911d1ae2016-11-28 16:44:40 -080044#define PORT_BREAK_DURATION 1
The Android Open Source Project5738f832012-12-12 16:00:35 -080045
Myles Watson911d1ae2016-11-28 16:44:40 -080046#define info(fmt, ...) LOG_INFO(LOG_TAG, "%s: " fmt, __func__, ##__VA_ARGS__)
47#define debug(fmt, ...) LOG_DEBUG(LOG_TAG, "%s: " fmt, __func__, ##__VA_ARGS__)
48#define error(fmt, ...) \
49 LOG_ERROR(LOG_TAG, "## ERROR : %s: " fmt "##", __func__, ##__VA_ARGS__)
50#define asrt(s) \
51 if (!(s)) \
52 LOG_ERROR(LOG_TAG, "## %s assert %s failed at line:%d ##", __func__, #s, \
53 __LINE__)
The Android Open Source Project5738f832012-12-12 16:00:35 -080054
June R. Tate-Gans1e8cb562014-12-02 12:48:03 -080055/* Mapping from PORT_* result codes to human readable strings. */
Myles Watson911d1ae2016-11-28 16:44:40 -080056static const char* result_code_strings[] = {"Success",
57 "Unknown error",
58 "Already opened",
59 "Command pending",
60 "App not registered",
61 "No memory",
62 "No resources",
63 "Bad BD address",
64 "Unspecified error",
65 "Bad handle",
66 "Not opened",
67 "Line error",
68 "Start failed",
69 "Parameter negotiation failed",
70 "Port negotiation failed",
71 "Sec failed",
72 "Peer connection failed",
73 "Peer failed",
74 "Peer timeout",
75 "Closed",
76 "TX full",
77 "Local closed",
78 "Local timeout",
79 "TX queue disabled",
80 "Page timeout",
81 "Invalid SCN",
82 "Unknown result code"};
The Android Open Source Project5738f832012-12-12 16:00:35 -080083
84/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -080085 *
86 * Function RFCOMM_CreateConnection
87 *
Myles Watson9ca07092016-11-28 16:41:53 -080088 * Description RFCOMM_CreateConnection function is used from the
89 * application to establish serial port connection to the peer
90 * device, or allow RFCOMM to accept a connection from the peer
Myles Watsonee96a3c2016-11-23 14:49:54 -080091 * application.
92 *
93 * Parameters: scn - Service Channel Number as registered with
94 * the SDP (server) or obtained using SDP from
95 * the peer device (client).
96 * is_server - true if requesting application is a server
97 * mtu - Maximum frame size the application can accept
Jakub Pawlowski1979fa32017-06-16 10:46:47 -070098 * bd_addr - address of the peer (client)
Myles Watsonee96a3c2016-11-23 14:49:54 -080099 * mask - specifies events to be enabled. A value
100 * of zero disables all events.
101 * p_handle - OUT pointer to the handle.
102 * p_mgmt_cb - pointer to callback function to receive
103 * connection up/down events.
104 * Notes:
105 *
106 * Server can call this function with the same scn parameter multiple times if
107 * it is ready to accept multiple simulteneous connections.
108 *
109 * DLCI for the connection is (scn * 2 + 1) if client originates connection on
110 * existing none initiator multiplexer channel. Otherwise it is (scn * 2).
111 * For the server DLCI can be changed later if client will be calling it using
112 * (scn * 2 + 1) dlci.
113 *
114 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800115int RFCOMM_CreateConnection(uint16_t uuid, uint8_t scn, bool is_server,
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700116 uint16_t mtu, const RawAddress& bd_addr,
Jakub Pawlowski1979fa32017-06-16 10:46:47 -0700117 uint16_t* p_handle, tPORT_CALLBACK* p_mgmt_cb) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800118 tPORT* p_port;
Myles Watson911d1ae2016-11-28 16:44:40 -0800119 uint8_t dlci;
120 tRFC_MCB* p_mcb = port_find_mcb(bd_addr);
121 uint16_t rfcomm_mtu;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800122
Jakub Pawlowski1979fa32017-06-16 10:46:47 -0700123 VLOG(0) << __func__ << " BDA: " << bd_addr;
Chris Mantoncccf02f2014-10-21 13:55:24 -0700124
Myles Watson911d1ae2016-11-28 16:44:40 -0800125 *p_handle = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800126
Myles Watson911d1ae2016-11-28 16:44:40 -0800127 if ((scn == 0) || (scn >= PORT_MAX_RFC_PORTS)) {
128 /* Server Channel Number(SCN) should be in range 1...30 */
129 RFCOMM_TRACE_ERROR("RFCOMM_CreateConnection - invalid SCN");
130 return (PORT_INVALID_SCN);
131 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800132
Myles Watson911d1ae2016-11-28 16:44:40 -0800133 /* For client that originate connection on the existing none initiator */
134 /* multiplexer channel DLCI should be odd */
135 if (p_mcb && !p_mcb->is_initiator && !is_server)
136 dlci = (scn << 1) + 1;
137 else
138 dlci = (scn << 1);
139 RFCOMM_TRACE_API(
140 "RFCOMM_CreateConnection(): scn:%d, dlci:%d, is_server:%d mtu:%d, "
141 "p_mcb:%p",
142 scn, dlci, is_server, mtu, p_mcb);
143
144 /* For the server side always allocate a new port. On the client side */
145 /* do not allow the same (dlci, bd_addr) to be opened twice by application */
Marie Janssenf9c57522017-02-22 08:35:29 -0800146 if (!is_server) {
147 p_port = port_find_port(dlci, bd_addr);
148 if (p_port != NULL) {
149 /* if existing port is also a client port */
150 if (p_port->is_server == false) {
151 RFCOMM_TRACE_ERROR(
152 "RFCOMM_CreateConnection - already opened state:%d, RFC state:%d, "
153 "MCB state:%d",
154 p_port->state, p_port->rfc.state,
155 p_port->rfc.p_mcb ? p_port->rfc.p_mcb->state : 0);
156 *p_handle = p_port->inx;
157 return (PORT_ALREADY_OPENED);
158 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800159 }
Myles Watson911d1ae2016-11-28 16:44:40 -0800160 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800161
Myles Watson911d1ae2016-11-28 16:44:40 -0800162 p_port = port_allocate_port(dlci, bd_addr);
163 if (p_port == NULL) {
164 RFCOMM_TRACE_WARNING("RFCOMM_CreateConnection - no resources");
165 return (PORT_NO_RESOURCES);
166 }
167 RFCOMM_TRACE_API(
168 "RFCOMM_CreateConnection(): scn:%d, dlci:%d, is_server:%d mtu:%d, "
169 "p_mcb:%p, p_port:%p",
170 scn, dlci, is_server, mtu, p_mcb, p_port);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800171
Myles Watson911d1ae2016-11-28 16:44:40 -0800172 p_port->default_signal_state =
173 (PORT_DTRDSR_ON | PORT_CTSRTS_ON | PORT_DCD_ON);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800174
Myles Watson911d1ae2016-11-28 16:44:40 -0800175 switch (uuid) {
The Android Open Source Project5738f832012-12-12 16:00:35 -0800176 case UUID_PROTOCOL_OBEX:
Myles Watson911d1ae2016-11-28 16:44:40 -0800177 p_port->default_signal_state = PORT_OBEX_DEFAULT_SIGNAL_STATE;
178 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800179 case UUID_SERVCLASS_SERIAL_PORT:
Myles Watson911d1ae2016-11-28 16:44:40 -0800180 p_port->default_signal_state = PORT_SPP_DEFAULT_SIGNAL_STATE;
181 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800182 case UUID_SERVCLASS_LAN_ACCESS_USING_PPP:
Myles Watson911d1ae2016-11-28 16:44:40 -0800183 p_port->default_signal_state = PORT_PPP_DEFAULT_SIGNAL_STATE;
184 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800185 case UUID_SERVCLASS_DIALUP_NETWORKING:
186 case UUID_SERVCLASS_FAX:
Myles Watson911d1ae2016-11-28 16:44:40 -0800187 p_port->default_signal_state = PORT_DUN_DEFAULT_SIGNAL_STATE;
188 break;
189 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800190
Myles Watson911d1ae2016-11-28 16:44:40 -0800191 RFCOMM_TRACE_EVENT("RFCOMM_CreateConnection dlci:%d signal state:0x%x", dlci,
192 p_port->default_signal_state);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800193
Myles Watson911d1ae2016-11-28 16:44:40 -0800194 *p_handle = p_port->inx;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800195
Myles Watson911d1ae2016-11-28 16:44:40 -0800196 p_port->state = PORT_STATE_OPENING;
197 p_port->uuid = uuid;
198 p_port->is_server = is_server;
199 p_port->scn = scn;
200 p_port->ev_mask = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800201
Myles Watson911d1ae2016-11-28 16:44:40 -0800202 /* If the MTU is not specified (0), keep MTU decision until the
203 * PN frame has to be send
204 * at that time connection should be established and we
205 * will know for sure our prefered MTU
206 */
The Android Open Source Project5738f832012-12-12 16:00:35 -0800207
Myles Watson911d1ae2016-11-28 16:44:40 -0800208 rfcomm_mtu = L2CAP_MTU_SIZE - RFCOMM_DATA_OVERHEAD;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800209
Myles Watson911d1ae2016-11-28 16:44:40 -0800210 if (mtu)
211 p_port->mtu = (mtu < rfcomm_mtu) ? mtu : rfcomm_mtu;
212 else
213 p_port->mtu = rfcomm_mtu;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800214
Myles Watson911d1ae2016-11-28 16:44:40 -0800215 /* server doesn't need to release port when closing */
216 if (is_server) {
217 p_port->keep_port_handle = true;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800218
Myles Watson911d1ae2016-11-28 16:44:40 -0800219 /* keep mtu that user asked, p_port->mtu could be updated during param
220 * negotiation */
221 p_port->keep_mtu = p_port->mtu;
222 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800223
Myles Watson911d1ae2016-11-28 16:44:40 -0800224 p_port->local_ctrl.modem_signal = p_port->default_signal_state;
225 p_port->local_ctrl.fc = false;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800226
Myles Watson911d1ae2016-11-28 16:44:40 -0800227 p_port->p_mgmt_callback = p_mgmt_cb;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800228
Jakub Pawlowski1979fa32017-06-16 10:46:47 -0700229 p_port->bd_addr = bd_addr;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800230
Myles Watson911d1ae2016-11-28 16:44:40 -0800231 /* If this is not initiator of the connection need to just wait */
232 if (p_port->is_server) {
233 return (PORT_SUCCESS);
234 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800235
Myles Watson911d1ae2016-11-28 16:44:40 -0800236 /* Open will be continued after security checks are passed */
237 return port_open_continue(p_port);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800238}
239
The Android Open Source Project5738f832012-12-12 16:00:35 -0800240/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800241 *
242 * Function RFCOMM_RemoveConnection
243 *
244 * Description This function is called to close the specified connection.
245 *
246 * Parameters: handle - Handle returned in the RFCOMM_CreateConnection
247 *
248 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800249int RFCOMM_RemoveConnection(uint16_t handle) {
250 tPORT* p_port;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800251
Myles Watson911d1ae2016-11-28 16:44:40 -0800252 RFCOMM_TRACE_API("RFCOMM_RemoveConnection() handle:%d", handle);
Chris Mantoncccf02f2014-10-21 13:55:24 -0700253
Myles Watson911d1ae2016-11-28 16:44:40 -0800254 /* Check if handle is valid to avoid crashing */
255 if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
256 RFCOMM_TRACE_ERROR("RFCOMM_RemoveConnection() BAD handle:%d", handle);
257 return (PORT_BAD_HANDLE);
258 }
259 p_port = &rfc_cb.port.port[handle - 1];
The Android Open Source Project5738f832012-12-12 16:00:35 -0800260
Myles Watson911d1ae2016-11-28 16:44:40 -0800261 if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
262 RFCOMM_TRACE_EVENT("RFCOMM_RemoveConnection() Not opened:%d", handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800263 return (PORT_SUCCESS);
Myles Watson911d1ae2016-11-28 16:44:40 -0800264 }
265
266 p_port->state = PORT_STATE_CLOSING;
267
268 port_start_close(p_port);
269
270 return (PORT_SUCCESS);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800271}
272
273/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800274 *
275 * Function RFCOMM_RemoveServer
276 *
277 * Description This function is called to close the server port.
278 *
279 * Parameters: handle - Handle returned in the RFCOMM_CreateConnection
280 *
281 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800282int RFCOMM_RemoveServer(uint16_t handle) {
283 tPORT* p_port;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800284
Myles Watson911d1ae2016-11-28 16:44:40 -0800285 RFCOMM_TRACE_API("RFCOMM_RemoveServer() handle:%d", handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800286
Myles Watson911d1ae2016-11-28 16:44:40 -0800287 /* Check if handle is valid to avoid crashing */
288 if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
289 RFCOMM_TRACE_ERROR("RFCOMM_RemoveServer() BAD handle:%d", handle);
290 return (PORT_BAD_HANDLE);
291 }
292 p_port = &rfc_cb.port.port[handle - 1];
The Android Open Source Project5738f832012-12-12 16:00:35 -0800293
Myles Watson911d1ae2016-11-28 16:44:40 -0800294 /* Do not report any events to the client any more. */
295 p_port->p_mgmt_callback = NULL;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800296
Myles Watson911d1ae2016-11-28 16:44:40 -0800297 if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
298 RFCOMM_TRACE_EVENT("RFCOMM_RemoveServer() Not opened:%d", handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800299 return (PORT_SUCCESS);
Myles Watson911d1ae2016-11-28 16:44:40 -0800300 }
301
302 /* this port will be deallocated after closing */
303 p_port->keep_port_handle = false;
304 p_port->state = PORT_STATE_CLOSING;
305
306 port_start_close(p_port);
307
308 return (PORT_SUCCESS);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800309}
310
311/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800312 *
313 * Function PORT_SetEventCallback
314 *
315 * Description This function is called to provide an address of the
316 * function which will be called when one of the events
317 * specified in the mask occures.
318 *
319 * Parameters: handle - Handle returned in the RFCOMM_CreateConnection
320 * p_callback - address of the callback function which should
321 * be called from the RFCOMM when an event
322 * specified in the mask occures.
323 *
324 *
325 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800326int PORT_SetEventCallback(uint16_t port_handle, tPORT_CALLBACK* p_port_cb) {
327 tPORT* p_port;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800328
Myles Watson911d1ae2016-11-28 16:44:40 -0800329 /* Check if handle is valid to avoid crashing */
330 if ((port_handle == 0) || (port_handle > MAX_RFC_PORTS)) {
331 return (PORT_BAD_HANDLE);
332 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800333
Myles Watson911d1ae2016-11-28 16:44:40 -0800334 p_port = &rfc_cb.port.port[port_handle - 1];
The Android Open Source Project5738f832012-12-12 16:00:35 -0800335
Myles Watson911d1ae2016-11-28 16:44:40 -0800336 if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
337 return (PORT_NOT_OPENED);
338 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800339
Myles Watson911d1ae2016-11-28 16:44:40 -0800340 RFCOMM_TRACE_API("PORT_SetEventCallback() handle:%d", port_handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800341
Myles Watson911d1ae2016-11-28 16:44:40 -0800342 p_port->p_callback = p_port_cb;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800343
Myles Watson911d1ae2016-11-28 16:44:40 -0800344 return (PORT_SUCCESS);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800345}
Matthew Xie9ac641d2013-01-15 15:54:03 -0800346/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800347 *
348 * Function PORT_ClearKeepHandleFlag
349 *
Myles Watson9ca07092016-11-28 16:41:53 -0800350 * Description Clear the keep handle flag, which will cause not to keep the
351 * port handle open when closed
Myles Watsonee96a3c2016-11-23 14:49:54 -0800352 * Parameters: handle - Handle returned in the RFCOMM_CreateConnection
353 *
354 ******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800355
Myles Watson911d1ae2016-11-28 16:44:40 -0800356int PORT_ClearKeepHandleFlag(uint16_t port_handle) {
357 tPORT* p_port;
Matthew Xie9ac641d2013-01-15 15:54:03 -0800358
Myles Watson911d1ae2016-11-28 16:44:40 -0800359 /* Check if handle is valid to avoid crashing */
360 if ((port_handle == 0) || (port_handle > MAX_RFC_PORTS)) {
361 return (PORT_BAD_HANDLE);
362 }
Matthew Xie9ac641d2013-01-15 15:54:03 -0800363
Myles Watson911d1ae2016-11-28 16:44:40 -0800364 p_port = &rfc_cb.port.port[port_handle - 1];
365 p_port->keep_port_handle = 0;
366 return (PORT_SUCCESS);
Matthew Xie9ac641d2013-01-15 15:54:03 -0800367}
The Android Open Source Project5738f832012-12-12 16:00:35 -0800368
369/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800370 *
371 * Function PORT_SetDataCallback
372 *
373 * Description This function is when a data packet is received
374 *
375 * Parameters: handle - Handle returned in the RFCOMM_CreateConnection
376 * p_callback - address of the callback function which should
377 * be called from the RFCOMM when data packet
378 * is received.
379 *
380 *
381 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800382int PORT_SetDataCallback(uint16_t port_handle, tPORT_DATA_CALLBACK* p_port_cb) {
383 tPORT* p_port;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800384
Myles Watson911d1ae2016-11-28 16:44:40 -0800385 RFCOMM_TRACE_API("PORT_SetDataCallback() handle:%d cb 0x%x", port_handle,
386 p_port_cb);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800387
Myles Watson911d1ae2016-11-28 16:44:40 -0800388 /* Check if handle is valid to avoid crashing */
389 if ((port_handle == 0) || (port_handle > MAX_RFC_PORTS)) {
390 return (PORT_BAD_HANDLE);
391 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800392
Myles Watson911d1ae2016-11-28 16:44:40 -0800393 p_port = &rfc_cb.port.port[port_handle - 1];
The Android Open Source Project5738f832012-12-12 16:00:35 -0800394
Myles Watson911d1ae2016-11-28 16:44:40 -0800395 if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
396 return (PORT_NOT_OPENED);
397 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800398
Myles Watson911d1ae2016-11-28 16:44:40 -0800399 p_port->p_data_callback = p_port_cb;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800400
Myles Watson911d1ae2016-11-28 16:44:40 -0800401 return (PORT_SUCCESS);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800402}
403/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800404 *
405 * Function PORT_SetCODataCallback
406 *
407 * Description This function is when a data packet is received
408 *
409 * Parameters: handle - Handle returned in the RFCOMM_CreateConnection
410 * p_callback - address of the callback function which should
411 * be called from the RFCOMM when data packet
412 * is received.
413 *
414 *
415 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800416int PORT_SetDataCOCallback(uint16_t port_handle,
417 tPORT_DATA_CO_CALLBACK* p_port_cb) {
418 tPORT* p_port;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800419
Myles Watson911d1ae2016-11-28 16:44:40 -0800420 RFCOMM_TRACE_API("PORT_SetDataCOCallback() handle:%d cb 0x%x", port_handle,
421 p_port_cb);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800422
Myles Watson911d1ae2016-11-28 16:44:40 -0800423 /* Check if handle is valid to avoid crashing */
424 if ((port_handle == 0) || (port_handle > MAX_RFC_PORTS)) {
425 return (PORT_BAD_HANDLE);
426 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800427
Myles Watson911d1ae2016-11-28 16:44:40 -0800428 p_port = &rfc_cb.port.port[port_handle - 1];
The Android Open Source Project5738f832012-12-12 16:00:35 -0800429
Myles Watson911d1ae2016-11-28 16:44:40 -0800430 if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
431 return (PORT_NOT_OPENED);
432 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800433
Myles Watson911d1ae2016-11-28 16:44:40 -0800434 p_port->p_data_co_callback = p_port_cb;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800435
Myles Watson911d1ae2016-11-28 16:44:40 -0800436 return (PORT_SUCCESS);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800437}
438
The Android Open Source Project5738f832012-12-12 16:00:35 -0800439/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800440 *
441 * Function PORT_SetEventMask
442 *
443 * Description This function is called to close the specified connection.
444 *
445 * Parameters: handle - Handle returned in the RFCOMM_CreateConnection
446 * mask - Bitmask of the events the host is interested in
447 *
448 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800449int PORT_SetEventMask(uint16_t port_handle, uint32_t mask) {
450 tPORT* p_port;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800451
Myles Watson911d1ae2016-11-28 16:44:40 -0800452 RFCOMM_TRACE_API("PORT_SetEventMask() handle:%d mask:0x%x", port_handle,
453 mask);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800454
Myles Watson911d1ae2016-11-28 16:44:40 -0800455 /* Check if handle is valid to avoid crashing */
456 if ((port_handle == 0) || (port_handle > MAX_RFC_PORTS)) {
457 return (PORT_BAD_HANDLE);
458 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800459
Myles Watson911d1ae2016-11-28 16:44:40 -0800460 p_port = &rfc_cb.port.port[port_handle - 1];
The Android Open Source Project5738f832012-12-12 16:00:35 -0800461
Myles Watson911d1ae2016-11-28 16:44:40 -0800462 if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
463 return (PORT_NOT_OPENED);
464 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800465
Myles Watson911d1ae2016-11-28 16:44:40 -0800466 p_port->ev_mask = mask;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800467
Myles Watson911d1ae2016-11-28 16:44:40 -0800468 return (PORT_SUCCESS);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800469}
470
The Android Open Source Project5738f832012-12-12 16:00:35 -0800471/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800472 *
473 * Function PORT_CheckConnection
474 *
475 * Description This function returns PORT_SUCCESS if connection referenced
476 * by handle is up and running
477 *
478 * Parameters: handle - Handle returned in the RFCOMM_CreateConnection
479 * bd_addr - OUT bd_addr of the peer
480 * p_lcid - OUT L2CAP's LCID
481 *
482 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700483int PORT_CheckConnection(uint16_t handle, RawAddress& bd_addr,
Jakub Pawlowski1979fa32017-06-16 10:46:47 -0700484 uint16_t* p_lcid) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800485 tPORT* p_port;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800486
Myles Watson911d1ae2016-11-28 16:44:40 -0800487 RFCOMM_TRACE_API("PORT_CheckConnection() handle:%d", handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800488
Myles Watson911d1ae2016-11-28 16:44:40 -0800489 /* Check if handle is valid to avoid crashing */
490 if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
491 return (PORT_BAD_HANDLE);
492 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800493
Myles Watson911d1ae2016-11-28 16:44:40 -0800494 p_port = &rfc_cb.port.port[handle - 1];
The Android Open Source Project5738f832012-12-12 16:00:35 -0800495
Myles Watson911d1ae2016-11-28 16:44:40 -0800496 if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
497 return (PORT_NOT_OPENED);
498 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800499
Myles Watson911d1ae2016-11-28 16:44:40 -0800500 if (!p_port->rfc.p_mcb || !p_port->rfc.p_mcb->peer_ready ||
501 (p_port->rfc.state != RFC_STATE_OPENED)) {
502 return (PORT_LINE_ERR);
503 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800504
Jakub Pawlowski1979fa32017-06-16 10:46:47 -0700505 bd_addr = p_port->rfc.p_mcb->bd_addr;
Myles Watson911d1ae2016-11-28 16:44:40 -0800506 if (p_lcid) *p_lcid = p_port->rfc.p_mcb->lcid;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800507
Myles Watson911d1ae2016-11-28 16:44:40 -0800508 return (PORT_SUCCESS);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800509}
510
511/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800512 *
513 * Function PORT_IsOpening
514 *
515 * Description This function returns true if there is any RFCOMM connection
516 * opening in process.
517 *
518 * Parameters: true if any connection opening is found
519 * bd_addr - bd_addr of the peer
520 *
521 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700522bool PORT_IsOpening(RawAddress& bd_addr) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800523 uint8_t xx, yy;
524 tRFC_MCB* p_mcb = NULL;
525 tPORT* p_port;
526 bool found_port;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800527
Myles Watson911d1ae2016-11-28 16:44:40 -0800528 /* Check for any rfc_mcb which is in the middle of opening. */
529 for (xx = 0; xx < MAX_BD_CONNECTIONS; xx++) {
530 if ((rfc_cb.port.rfc_mcb[xx].state > RFC_MX_STATE_IDLE) &&
531 (rfc_cb.port.rfc_mcb[xx].state < RFC_MX_STATE_CONNECTED)) {
Jakub Pawlowski1979fa32017-06-16 10:46:47 -0700532 bd_addr = rfc_cb.port.rfc_mcb[xx].bd_addr;
Myles Watson911d1ae2016-11-28 16:44:40 -0800533 return true;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800534 }
535
Myles Watson911d1ae2016-11-28 16:44:40 -0800536 if (rfc_cb.port.rfc_mcb[xx].state == RFC_MX_STATE_CONNECTED) {
537 found_port = false;
538 p_mcb = &rfc_cb.port.rfc_mcb[xx];
539 p_port = &rfc_cb.port.port[0];
540
541 for (yy = 0; yy < MAX_RFC_PORTS; yy++, p_port++) {
542 if (p_port->rfc.p_mcb == p_mcb) {
543 found_port = true;
544 break;
545 }
546 }
547
548 if ((!found_port) ||
549 (found_port && (p_port->rfc.state < RFC_STATE_OPENED))) {
550 /* Port is not established yet. */
Jakub Pawlowski1979fa32017-06-16 10:46:47 -0700551 bd_addr = rfc_cb.port.rfc_mcb[xx].bd_addr;
Myles Watson911d1ae2016-11-28 16:44:40 -0800552 return true;
553 }
554 }
555 }
556
557 return false;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800558}
559
560/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800561 *
562 * Function PORT_SetState
563 *
564 * Description This function configures connection according to the
565 * specifications in the tPORT_STATE structure.
566 *
567 * Parameters: handle - Handle returned in the RFCOMM_CreateConnection
568 * p_settings - Pointer to a tPORT_STATE structure containing
569 * configuration information for the connection.
570 *
571 *
572 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800573int PORT_SetState(uint16_t handle, tPORT_STATE* p_settings) {
574 tPORT* p_port;
575 uint8_t baud_rate;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800576
Myles Watson911d1ae2016-11-28 16:44:40 -0800577 RFCOMM_TRACE_API("PORT_SetState() handle:%d", handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800578
Myles Watson911d1ae2016-11-28 16:44:40 -0800579 /* Check if handle is valid to avoid crashing */
580 if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
581 return (PORT_BAD_HANDLE);
582 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800583
Myles Watson911d1ae2016-11-28 16:44:40 -0800584 p_port = &rfc_cb.port.port[handle - 1];
The Android Open Source Project5738f832012-12-12 16:00:35 -0800585
Myles Watson911d1ae2016-11-28 16:44:40 -0800586 if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
587 return (PORT_NOT_OPENED);
588 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800589
Myles Watson911d1ae2016-11-28 16:44:40 -0800590 if (p_port->line_status) {
591 return (PORT_LINE_ERR);
592 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800593
Myles Watson911d1ae2016-11-28 16:44:40 -0800594 RFCOMM_TRACE_API("PORT_SetState() handle:%d FC_TYPE:0x%x", handle,
595 p_settings->fc_type);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800596
Myles Watson911d1ae2016-11-28 16:44:40 -0800597 baud_rate = p_port->user_port_pars.baud_rate;
598 p_port->user_port_pars = *p_settings;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800599
Myles Watson911d1ae2016-11-28 16:44:40 -0800600 /* for now we've been asked to pass only baud rate */
601 if (baud_rate != p_settings->baud_rate) {
602 port_start_par_neg(p_port);
603 }
604 return (PORT_SUCCESS);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800605}
606
607/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800608 *
609 * Function PORT_GetRxQueueCnt
610 *
611 * Description This function return number of buffers on the rx queue.
612 *
613 * Parameters: handle - Handle returned in the RFCOMM_CreateConnection
614 * p_rx_queue_count - Pointer to return queue count in.
615 *
616 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800617int PORT_GetRxQueueCnt(uint16_t handle, uint16_t* p_rx_queue_count) {
618 tPORT* p_port;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800619
Myles Watson911d1ae2016-11-28 16:44:40 -0800620 RFCOMM_TRACE_API("PORT_GetRxQueueCnt() handle:%d", handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800621
Myles Watson911d1ae2016-11-28 16:44:40 -0800622 /* Check if handle is valid to avoid crashing */
623 if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
624 return (PORT_BAD_HANDLE);
625 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800626
Myles Watson911d1ae2016-11-28 16:44:40 -0800627 p_port = &rfc_cb.port.port[handle - 1];
The Android Open Source Project5738f832012-12-12 16:00:35 -0800628
Myles Watson911d1ae2016-11-28 16:44:40 -0800629 if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
630 return (PORT_NOT_OPENED);
631 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800632
Myles Watson911d1ae2016-11-28 16:44:40 -0800633 if (p_port->line_status) {
634 return (PORT_LINE_ERR);
635 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800636
Myles Watson911d1ae2016-11-28 16:44:40 -0800637 *p_rx_queue_count = p_port->rx.queue_size;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800638
Myles Watson911d1ae2016-11-28 16:44:40 -0800639 RFCOMM_TRACE_API(
640 "PORT_GetRxQueueCnt() p_rx_queue_count:%d, p_port->rx.queue.count = %d",
641 *p_rx_queue_count, p_port->rx.queue_size);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800642
Myles Watson911d1ae2016-11-28 16:44:40 -0800643 return (PORT_SUCCESS);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800644}
645
646/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800647 *
648 * Function PORT_GetState
649 *
650 * Description This function is called to fill tPORT_STATE structure
651 * with the curremt control settings for the port
652 *
653 * Parameters: handle - Handle returned in the RFCOMM_CreateConnection
654 * p_settings - Pointer to a tPORT_STATE structure in which
655 * configuration information is returned.
656 *
657 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800658int PORT_GetState(uint16_t handle, tPORT_STATE* p_settings) {
659 tPORT* p_port;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800660
Myles Watson911d1ae2016-11-28 16:44:40 -0800661 RFCOMM_TRACE_API("PORT_GetState() handle:%d", handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800662
Myles Watson911d1ae2016-11-28 16:44:40 -0800663 /* Check if handle is valid to avoid crashing */
664 if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
665 return (PORT_BAD_HANDLE);
666 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800667
Myles Watson911d1ae2016-11-28 16:44:40 -0800668 p_port = &rfc_cb.port.port[handle - 1];
The Android Open Source Project5738f832012-12-12 16:00:35 -0800669
Myles Watson911d1ae2016-11-28 16:44:40 -0800670 if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
671 return (PORT_NOT_OPENED);
672 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800673
Myles Watson911d1ae2016-11-28 16:44:40 -0800674 if (p_port->line_status) {
675 return (PORT_LINE_ERR);
676 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800677
Myles Watson911d1ae2016-11-28 16:44:40 -0800678 *p_settings = p_port->user_port_pars;
679 return (PORT_SUCCESS);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800680}
681
The Android Open Source Project5738f832012-12-12 16:00:35 -0800682/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800683 *
684 * Function PORT_Control
685 *
686 * Description This function directs a specified connection to pass control
687 * control information to the peer device.
688 *
689 * Parameters: handle - Handle returned in the RFCOMM_CreateConnection
690 * signal = specify the function to be passed
691 *
692 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800693int PORT_Control(uint16_t handle, uint8_t signal) {
694 tPORT* p_port;
695 uint8_t old_modem_signal;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800696
Myles Watson911d1ae2016-11-28 16:44:40 -0800697 RFCOMM_TRACE_API("PORT_Control() handle:%d signal:0x%x", handle, signal);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800698
Myles Watson911d1ae2016-11-28 16:44:40 -0800699 /* Check if handle is valid to avoid crashing */
700 if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
701 return (PORT_BAD_HANDLE);
702 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800703
Myles Watson911d1ae2016-11-28 16:44:40 -0800704 p_port = &rfc_cb.port.port[handle - 1];
The Android Open Source Project5738f832012-12-12 16:00:35 -0800705
Myles Watson911d1ae2016-11-28 16:44:40 -0800706 if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
707 return (PORT_NOT_OPENED);
708 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800709
Myles Watson911d1ae2016-11-28 16:44:40 -0800710 old_modem_signal = p_port->local_ctrl.modem_signal;
711 p_port->local_ctrl.break_signal = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800712
Myles Watson911d1ae2016-11-28 16:44:40 -0800713 switch (signal) {
The Android Open Source Project5738f832012-12-12 16:00:35 -0800714 case PORT_SET_CTSRTS:
Myles Watson911d1ae2016-11-28 16:44:40 -0800715 p_port->local_ctrl.modem_signal |= PORT_CTSRTS_ON;
716 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800717
718 case PORT_CLR_CTSRTS:
Myles Watson911d1ae2016-11-28 16:44:40 -0800719 p_port->local_ctrl.modem_signal &= ~PORT_CTSRTS_ON;
720 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800721
722 case PORT_SET_DTRDSR:
Myles Watson911d1ae2016-11-28 16:44:40 -0800723 p_port->local_ctrl.modem_signal |= PORT_DTRDSR_ON;
724 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800725
726 case PORT_CLR_DTRDSR:
Myles Watson911d1ae2016-11-28 16:44:40 -0800727 p_port->local_ctrl.modem_signal &= ~PORT_DTRDSR_ON;
728 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800729
730 case PORT_SET_RI:
Myles Watson911d1ae2016-11-28 16:44:40 -0800731 p_port->local_ctrl.modem_signal |= PORT_RING_ON;
732 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800733
734 case PORT_CLR_RI:
Myles Watson911d1ae2016-11-28 16:44:40 -0800735 p_port->local_ctrl.modem_signal &= ~PORT_RING_ON;
736 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800737
738 case PORT_SET_DCD:
Myles Watson911d1ae2016-11-28 16:44:40 -0800739 p_port->local_ctrl.modem_signal |= PORT_DCD_ON;
740 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800741
742 case PORT_CLR_DCD:
Myles Watson911d1ae2016-11-28 16:44:40 -0800743 p_port->local_ctrl.modem_signal &= ~PORT_DCD_ON;
744 break;
745 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800746
Myles Watson911d1ae2016-11-28 16:44:40 -0800747 if (signal == PORT_BREAK)
748 p_port->local_ctrl.break_signal = PORT_BREAK_DURATION;
749 else if (p_port->local_ctrl.modem_signal == old_modem_signal)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800750 return (PORT_SUCCESS);
Myles Watson911d1ae2016-11-28 16:44:40 -0800751
752 port_start_control(p_port);
753
754 RFCOMM_TRACE_EVENT(
755 "PORT_Control DTR_DSR : %d, RTS_CTS : %d, RI : %d, DCD : %d",
756 ((p_port->local_ctrl.modem_signal & MODEM_SIGNAL_DTRDSR) ? 1 : 0),
757 ((p_port->local_ctrl.modem_signal & MODEM_SIGNAL_RTSCTS) ? 1 : 0),
758 ((p_port->local_ctrl.modem_signal & MODEM_SIGNAL_RI) ? 1 : 0),
759 ((p_port->local_ctrl.modem_signal & MODEM_SIGNAL_DCD) ? 1 : 0));
760
761 return (PORT_SUCCESS);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800762}
763
The Android Open Source Project5738f832012-12-12 16:00:35 -0800764/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800765 *
766 * Function PORT_FlowControl
767 *
768 * Description This function directs a specified connection to pass
769 * flow control message to the peer device. Enable flag passed
770 * shows if port can accept more data.
771 *
772 * Parameters: handle - Handle returned in the RFCOMM_CreateConnection
773 * enable - enables data flow
774 *
775 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800776int PORT_FlowControl(uint16_t handle, bool enable) {
777 tPORT* p_port;
778 bool old_fc;
779 uint32_t events;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800780
Myles Watson911d1ae2016-11-28 16:44:40 -0800781 RFCOMM_TRACE_API("PORT_FlowControl() handle:%d enable: %d", handle, enable);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800782
Myles Watson911d1ae2016-11-28 16:44:40 -0800783 /* Check if handle is valid to avoid crashing */
784 if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
785 return (PORT_BAD_HANDLE);
786 }
787
788 p_port = &rfc_cb.port.port[handle - 1];
789
790 if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
791 return (PORT_NOT_OPENED);
792 }
793
794 if (!p_port->rfc.p_mcb) {
795 return (PORT_NOT_OPENED);
796 }
797
798 p_port->rx.user_fc = !enable;
799
800 if (p_port->rfc.p_mcb->flow == PORT_FC_CREDIT) {
801 if (!p_port->rx.user_fc) {
802 port_flow_control_peer(p_port, true, 0);
803 }
804 } else {
805 old_fc = p_port->local_ctrl.fc;
806
807 /* FC is set if user is set or peer is set */
808 p_port->local_ctrl.fc = (p_port->rx.user_fc | p_port->rx.peer_fc);
809
810 if (p_port->local_ctrl.fc != old_fc) port_start_control(p_port);
811 }
812
813 /* Need to take care of the case when we could not deliver events */
814 /* to the application because we were flow controlled */
815 if (enable && (p_port->rx.queue_size != 0)) {
816 events = PORT_EV_RXCHAR;
817 if (p_port->rx_flag_ev_pending) {
818 p_port->rx_flag_ev_pending = false;
819 events |= PORT_EV_RXFLAG;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800820 }
821
Myles Watson911d1ae2016-11-28 16:44:40 -0800822 events &= p_port->ev_mask;
823 if (p_port->p_callback && events) {
824 p_port->p_callback(events, p_port->inx);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800825 }
Myles Watson911d1ae2016-11-28 16:44:40 -0800826 }
827 return (PORT_SUCCESS);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800828}
zzy181adbe2013-08-09 17:52:52 -0700829/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800830 *
831 * Function PORT_FlowControl_MaxCredit
832 *
833 * Description This function directs a specified connection to pass
834 * flow control message to the peer device. Enable flag passed
835 * shows if port can accept more data. It also sends max credit
836 * when data flow enabled
837 *
838 * Parameters: handle - Handle returned in the RFCOMM_CreateConnection
839 * enable - enables data flow
840 *
841 ******************************************************************************/
zzy181adbe2013-08-09 17:52:52 -0700842
Myles Watson911d1ae2016-11-28 16:44:40 -0800843int PORT_FlowControl_MaxCredit(uint16_t handle, bool enable) {
844 tPORT* p_port;
845 bool old_fc;
846 uint32_t events;
zzy181adbe2013-08-09 17:52:52 -0700847
Myles Watson911d1ae2016-11-28 16:44:40 -0800848 RFCOMM_TRACE_API("PORT_FlowControl() handle:%d enable: %d", handle, enable);
zzy181adbe2013-08-09 17:52:52 -0700849
Myles Watson911d1ae2016-11-28 16:44:40 -0800850 /* Check if handle is valid to avoid crashing */
851 if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
852 return (PORT_BAD_HANDLE);
853 }
854
855 p_port = &rfc_cb.port.port[handle - 1];
856
857 if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
858 return (PORT_NOT_OPENED);
859 }
860
861 if (!p_port->rfc.p_mcb) {
862 return (PORT_NOT_OPENED);
863 }
864
865 p_port->rx.user_fc = !enable;
866
867 if (p_port->rfc.p_mcb->flow == PORT_FC_CREDIT) {
868 if (!p_port->rx.user_fc) {
869 port_flow_control_peer(p_port, true, p_port->credit_rx);
870 }
871 } else {
872 old_fc = p_port->local_ctrl.fc;
873
874 /* FC is set if user is set or peer is set */
875 p_port->local_ctrl.fc = (p_port->rx.user_fc | p_port->rx.peer_fc);
876
877 if (p_port->local_ctrl.fc != old_fc) port_start_control(p_port);
878 }
879
880 /* Need to take care of the case when we could not deliver events */
881 /* to the application because we were flow controlled */
882 if (enable && (p_port->rx.queue_size != 0)) {
883 events = PORT_EV_RXCHAR;
884 if (p_port->rx_flag_ev_pending) {
885 p_port->rx_flag_ev_pending = false;
886 events |= PORT_EV_RXFLAG;
zzy181adbe2013-08-09 17:52:52 -0700887 }
888
Myles Watson911d1ae2016-11-28 16:44:40 -0800889 events &= p_port->ev_mask;
890 if (p_port->p_callback && events) {
891 p_port->p_callback(events, p_port->inx);
zzy181adbe2013-08-09 17:52:52 -0700892 }
Myles Watson911d1ae2016-11-28 16:44:40 -0800893 }
894 return (PORT_SUCCESS);
zzy181adbe2013-08-09 17:52:52 -0700895}
The Android Open Source Project5738f832012-12-12 16:00:35 -0800896
The Android Open Source Project5738f832012-12-12 16:00:35 -0800897/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800898 *
899 * Function PORT_GetModemStatus
900 *
901 * Description This function retrieves modem control signals. Normally
902 * application will call this function after a callback
903 * function is called with notification that one of signals
904 * has been changed.
905 *
906 * Parameters: handle - Handle returned in the RFCOMM_CreateConnection
907 * p_signal - specify the pointer to control signals info
908 *
909 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800910int PORT_GetModemStatus(uint16_t handle, uint8_t* p_signal) {
911 tPORT* p_port;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800912
Myles Watson911d1ae2016-11-28 16:44:40 -0800913 if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
914 return (PORT_BAD_HANDLE);
915 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800916
Myles Watson911d1ae2016-11-28 16:44:40 -0800917 p_port = &rfc_cb.port.port[handle - 1];
The Android Open Source Project5738f832012-12-12 16:00:35 -0800918
Myles Watson911d1ae2016-11-28 16:44:40 -0800919 if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
920 return (PORT_NOT_OPENED);
921 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800922
Myles Watson911d1ae2016-11-28 16:44:40 -0800923 *p_signal = p_port->peer_ctrl.modem_signal;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800924
Myles Watson911d1ae2016-11-28 16:44:40 -0800925 RFCOMM_TRACE_API("PORT_GetModemStatus() handle:%d signal:%x", handle,
926 *p_signal);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800927
Myles Watson911d1ae2016-11-28 16:44:40 -0800928 return (PORT_SUCCESS);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800929}
930
The Android Open Source Project5738f832012-12-12 16:00:35 -0800931/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800932 *
933 * Function PORT_ClearError
934 *
935 * Description This function retreives information about a communications
936 * error and reports current status of a connection. The
937 * function should be called when an error occures to clear
938 * the connection error flag and to enable additional read
939 * and write operations.
940 *
941 * Parameters: handle - Handle returned in the RFCOMM_CreateConnection
942 * p_errors - pointer of the variable to receive error codes
943 * p_status - pointer to the tPORT_STATUS structur to receive
944 * connection status
945 *
946 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800947int PORT_ClearError(uint16_t handle, uint16_t* p_errors,
948 tPORT_STATUS* p_status) {
949 tPORT* p_port;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800950
Myles Watson911d1ae2016-11-28 16:44:40 -0800951 RFCOMM_TRACE_API("PORT_ClearError() handle:%d", handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800952
Myles Watson911d1ae2016-11-28 16:44:40 -0800953 if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
954 return (PORT_BAD_HANDLE);
955 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800956
Myles Watson911d1ae2016-11-28 16:44:40 -0800957 p_port = &rfc_cb.port.port[handle - 1];
The Android Open Source Project5738f832012-12-12 16:00:35 -0800958
Myles Watson911d1ae2016-11-28 16:44:40 -0800959 if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
960 return (PORT_NOT_OPENED);
961 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800962
Myles Watson911d1ae2016-11-28 16:44:40 -0800963 *p_errors = p_port->line_status;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800964
Myles Watson911d1ae2016-11-28 16:44:40 -0800965 /* This is the only call to clear error status. We can not clear */
966 /* connection failed status. To clean it port should be closed and reopened
967 */
968 p_port->line_status = (p_port->line_status & LINE_STATUS_FAILED);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800969
Myles Watson911d1ae2016-11-28 16:44:40 -0800970 PORT_GetQueueStatus(handle, p_status);
971 return (PORT_SUCCESS);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800972}
973
The Android Open Source Project5738f832012-12-12 16:00:35 -0800974/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800975 *
976 * Function PORT_SendError
977 *
978 * Description This function send a communications error to the peer device
979 *
980 * Parameters: handle - Handle returned in the RFCOMM_CreateConnection
981 * errors - receive error codes
982 *
983 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800984int PORT_SendError(uint16_t handle, uint8_t errors) {
985 tPORT* p_port;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800986
Myles Watson911d1ae2016-11-28 16:44:40 -0800987 RFCOMM_TRACE_API("PORT_SendError() handle:%d errors:0x%x", handle, errors);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800988
Myles Watson911d1ae2016-11-28 16:44:40 -0800989 if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
990 return (PORT_BAD_HANDLE);
991 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800992
Myles Watson911d1ae2016-11-28 16:44:40 -0800993 p_port = &rfc_cb.port.port[handle - 1];
The Android Open Source Project5738f832012-12-12 16:00:35 -0800994
Myles Watson911d1ae2016-11-28 16:44:40 -0800995 if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
996 return (PORT_NOT_OPENED);
997 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800998
Myles Watson911d1ae2016-11-28 16:44:40 -0800999 if (!p_port->rfc.p_mcb) {
1000 return (PORT_NOT_OPENED);
1001 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001002
Myles Watson911d1ae2016-11-28 16:44:40 -08001003 RFCOMM_LineStatusReq(p_port->rfc.p_mcb, p_port->dlci, errors);
1004 return (PORT_SUCCESS);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001005}
1006
The Android Open Source Project5738f832012-12-12 16:00:35 -08001007/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -08001008 *
1009 * Function PORT_GetQueueStatus
1010 *
1011 * Description This function reports current status of a connection.
1012 *
1013 * Parameters: handle - Handle returned in the RFCOMM_CreateConnection
1014 * p_status - pointer to the tPORT_STATUS structur to receive
1015 * connection status
1016 *
1017 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -08001018int PORT_GetQueueStatus(uint16_t handle, tPORT_STATUS* p_status) {
1019 tPORT* p_port;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001020
Myles Watson911d1ae2016-11-28 16:44:40 -08001021 /* RFCOMM_TRACE_API ("PORT_GetQueueStatus() handle:%d", handle); */
The Android Open Source Project5738f832012-12-12 16:00:35 -08001022
Myles Watson911d1ae2016-11-28 16:44:40 -08001023 if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
1024 return (PORT_BAD_HANDLE);
1025 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001026
Myles Watson911d1ae2016-11-28 16:44:40 -08001027 p_port = &rfc_cb.port.port[handle - 1];
The Android Open Source Project5738f832012-12-12 16:00:35 -08001028
Myles Watson911d1ae2016-11-28 16:44:40 -08001029 if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
1030 return (PORT_NOT_OPENED);
1031 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001032
Myles Watson911d1ae2016-11-28 16:44:40 -08001033 p_status->in_queue_size = (uint16_t)p_port->rx.queue_size;
1034 p_status->out_queue_size = (uint16_t)p_port->tx.queue_size;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001035
Myles Watson911d1ae2016-11-28 16:44:40 -08001036 p_status->mtu_size = (uint16_t)p_port->peer_mtu;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001037
Myles Watson911d1ae2016-11-28 16:44:40 -08001038 p_status->flags = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001039
Myles Watson911d1ae2016-11-28 16:44:40 -08001040 if (!(p_port->peer_ctrl.modem_signal & PORT_CTSRTS_ON))
1041 p_status->flags |= PORT_FLAG_CTS_HOLD;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001042
Myles Watson911d1ae2016-11-28 16:44:40 -08001043 if (!(p_port->peer_ctrl.modem_signal & PORT_DTRDSR_ON))
1044 p_status->flags |= PORT_FLAG_DSR_HOLD;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001045
Myles Watson911d1ae2016-11-28 16:44:40 -08001046 if (!(p_port->peer_ctrl.modem_signal & PORT_DCD_ON))
1047 p_status->flags |= PORT_FLAG_RLSD_HOLD;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001048
Myles Watson911d1ae2016-11-28 16:44:40 -08001049 return (PORT_SUCCESS);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001050}
1051
The Android Open Source Project5738f832012-12-12 16:00:35 -08001052/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -08001053 *
1054 * Function PORT_Purge
1055 *
1056 * Description This function discards all the data from the output or
1057 * input queues of the specified connection.
1058 *
1059 * Parameters: handle - Handle returned in the RFCOMM_CreateConnection
1060 * purge_flags - specify the action to take.
1061 *
1062 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -08001063int PORT_Purge(uint16_t handle, uint8_t purge_flags) {
1064 tPORT* p_port;
1065 BT_HDR* p_buf;
1066 uint16_t count;
1067 uint32_t events;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001068
Myles Watson911d1ae2016-11-28 16:44:40 -08001069 RFCOMM_TRACE_API("PORT_Purge() handle:%d flags:0x%x", handle, purge_flags);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001070
Myles Watson911d1ae2016-11-28 16:44:40 -08001071 /* Check if handle is valid to avoid crashing */
1072 if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
1073 return (PORT_BAD_HANDLE);
1074 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001075
Myles Watson911d1ae2016-11-28 16:44:40 -08001076 p_port = &rfc_cb.port.port[handle - 1];
The Android Open Source Project5738f832012-12-12 16:00:35 -08001077
Myles Watson911d1ae2016-11-28 16:44:40 -08001078 if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
1079 return (PORT_NOT_OPENED);
1080 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001081
Myles Watson911d1ae2016-11-28 16:44:40 -08001082 if (purge_flags & PORT_PURGE_RXCLEAR) {
1083 mutex_global_lock(); /* to prevent missing credit */
The Android Open Source Project5738f832012-12-12 16:00:35 -08001084
Myles Watson911d1ae2016-11-28 16:44:40 -08001085 count = fixed_queue_length(p_port->rx.queue);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001086
Myles Watson911d1ae2016-11-28 16:44:40 -08001087 while ((p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_port->rx.queue)) != NULL)
1088 osi_free(p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001089
Myles Watson911d1ae2016-11-28 16:44:40 -08001090 p_port->rx.queue_size = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001091
Myles Watson911d1ae2016-11-28 16:44:40 -08001092 mutex_global_unlock();
The Android Open Source Project5738f832012-12-12 16:00:35 -08001093
Myles Watson911d1ae2016-11-28 16:44:40 -08001094 /* If we flowed controlled peer based on rx_queue size enable data again */
1095 if (count) port_flow_control_peer(p_port, true, count);
1096 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001097
Myles Watson911d1ae2016-11-28 16:44:40 -08001098 if (purge_flags & PORT_PURGE_TXCLEAR) {
1099 mutex_global_lock(); /* to prevent tx.queue_size from being negative */
The Android Open Source Project5738f832012-12-12 16:00:35 -08001100
Myles Watson911d1ae2016-11-28 16:44:40 -08001101 while ((p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_port->tx.queue)) != NULL)
1102 osi_free(p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001103
Myles Watson911d1ae2016-11-28 16:44:40 -08001104 p_port->tx.queue_size = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001105
Myles Watson911d1ae2016-11-28 16:44:40 -08001106 mutex_global_unlock();
The Android Open Source Project5738f832012-12-12 16:00:35 -08001107
Myles Watson911d1ae2016-11-28 16:44:40 -08001108 events = PORT_EV_TXEMPTY;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001109
Myles Watson911d1ae2016-11-28 16:44:40 -08001110 events |= port_flow_control_user(p_port);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001111
Myles Watson911d1ae2016-11-28 16:44:40 -08001112 events &= p_port->ev_mask;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001113
Myles Watson911d1ae2016-11-28 16:44:40 -08001114 if ((p_port->p_callback != NULL) && events)
1115 (p_port->p_callback)(events, p_port->inx);
1116 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001117
Myles Watson911d1ae2016-11-28 16:44:40 -08001118 return (PORT_SUCCESS);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001119}
1120
The Android Open Source Project5738f832012-12-12 16:00:35 -08001121/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -08001122 *
1123 * Function PORT_ReadData
1124 *
1125 * Description Normally not GKI aware application will call this function
1126 * after receiving PORT_EV_RXCHAR event.
1127 *
1128 * Parameters: handle - Handle returned in the RFCOMM_CreateConnection
1129 * p_data - Data area
1130 * max_len - Byte count requested
1131 * p_len - Byte count received
1132 *
1133 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -08001134int PORT_ReadData(uint16_t handle, char* p_data, uint16_t max_len,
1135 uint16_t* p_len) {
1136 tPORT* p_port;
1137 BT_HDR* p_buf;
1138 uint16_t count;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001139
Myles Watson911d1ae2016-11-28 16:44:40 -08001140 RFCOMM_TRACE_API("PORT_ReadData() handle:%d max_len:%d", handle, max_len);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001141
Myles Watson911d1ae2016-11-28 16:44:40 -08001142 /* Initialize this in case of an error */
1143 *p_len = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001144
Myles Watson911d1ae2016-11-28 16:44:40 -08001145 /* Check if handle is valid to avoid crashing */
1146 if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
1147 return (PORT_BAD_HANDLE);
1148 }
1149
1150 p_port = &rfc_cb.port.port[handle - 1];
1151
1152 if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
1153 return (PORT_NOT_OPENED);
1154 }
1155
1156 if (p_port->line_status) {
1157 return (PORT_LINE_ERR);
1158 }
1159
1160 if (fixed_queue_is_empty(p_port->rx.queue)) return (PORT_SUCCESS);
1161
1162 count = 0;
1163
1164 while (max_len) {
1165 p_buf = (BT_HDR*)fixed_queue_try_peek_first(p_port->rx.queue);
1166 if (p_buf == NULL) break;
1167
1168 if (p_buf->len > max_len) {
1169 memcpy(p_data, (uint8_t*)(p_buf + 1) + p_buf->offset, max_len);
1170 p_buf->offset += max_len;
1171 p_buf->len -= max_len;
1172
1173 *p_len += max_len;
1174
1175 mutex_global_lock();
1176
1177 p_port->rx.queue_size -= max_len;
1178
1179 mutex_global_unlock();
1180
1181 break;
1182 } else {
1183 memcpy(p_data, (uint8_t*)(p_buf + 1) + p_buf->offset, p_buf->len);
1184
1185 *p_len += p_buf->len;
1186 max_len -= p_buf->len;
1187
1188 mutex_global_lock();
1189
1190 p_port->rx.queue_size -= p_buf->len;
1191
1192 if (max_len) {
1193 p_data += p_buf->len;
1194 }
1195
1196 osi_free(fixed_queue_try_dequeue(p_port->rx.queue));
1197
1198 mutex_global_unlock();
1199
1200 count++;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001201 }
Myles Watson911d1ae2016-11-28 16:44:40 -08001202 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001203
Myles Watson911d1ae2016-11-28 16:44:40 -08001204 if (*p_len == 1) {
1205 RFCOMM_TRACE_EVENT("PORT_ReadData queue:%d returned:%d %x",
1206 p_port->rx.queue_size, *p_len, (p_data[0]));
1207 } else {
1208 RFCOMM_TRACE_EVENT("PORT_ReadData queue:%d returned:%d",
1209 p_port->rx.queue_size, *p_len);
1210 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001211
Myles Watson911d1ae2016-11-28 16:44:40 -08001212 /* If rfcomm suspended traffic from the peer based on the rx_queue_size */
1213 /* check if it can be resumed now */
1214 port_flow_control_peer(p_port, true, count);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001215
Myles Watson911d1ae2016-11-28 16:44:40 -08001216 return (PORT_SUCCESS);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001217}
1218
The Android Open Source Project5738f832012-12-12 16:00:35 -08001219/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -08001220 *
1221 * Function PORT_Read
1222 *
1223 * Description Normally application will call this function after receiving
1224 * PORT_EV_RXCHAR event.
1225 *
1226 * Parameters: handle - Handle returned in the RFCOMM_CreateConnection
1227 * pp_buf - pointer to address of buffer with data,
1228 *
1229 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -08001230int PORT_Read(uint16_t handle, BT_HDR** pp_buf) {
1231 tPORT* p_port;
1232 BT_HDR* p_buf;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001233
Myles Watson911d1ae2016-11-28 16:44:40 -08001234 RFCOMM_TRACE_API("PORT_Read() handle:%d", handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001235
Myles Watson911d1ae2016-11-28 16:44:40 -08001236 /* Check if handle is valid to avoid crashing */
1237 if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
1238 return (PORT_BAD_HANDLE);
1239 }
1240 p_port = &rfc_cb.port.port[handle - 1];
The Android Open Source Project5738f832012-12-12 16:00:35 -08001241
Myles Watson911d1ae2016-11-28 16:44:40 -08001242 if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
1243 return (PORT_NOT_OPENED);
1244 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001245
Myles Watson911d1ae2016-11-28 16:44:40 -08001246 if (p_port->line_status) {
1247 return (PORT_LINE_ERR);
1248 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001249
Myles Watson911d1ae2016-11-28 16:44:40 -08001250 mutex_global_lock();
The Android Open Source Project5738f832012-12-12 16:00:35 -08001251
Myles Watson911d1ae2016-11-28 16:44:40 -08001252 p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_port->rx.queue);
1253 if (p_buf) {
1254 p_port->rx.queue_size -= p_buf->len;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001255
Myles Watson911d1ae2016-11-28 16:44:40 -08001256 mutex_global_unlock();
The Android Open Source Project5738f832012-12-12 16:00:35 -08001257
Myles Watson911d1ae2016-11-28 16:44:40 -08001258 /* If rfcomm suspended traffic from the peer based on the rx_queue_size */
1259 /* check if it can be resumed now */
1260 port_flow_control_peer(p_port, true, 1);
1261 } else {
1262 mutex_global_unlock();
1263 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001264
Myles Watson911d1ae2016-11-28 16:44:40 -08001265 *pp_buf = p_buf;
1266 return (PORT_SUCCESS);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001267}
1268
The Android Open Source Project5738f832012-12-12 16:00:35 -08001269/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -08001270 *
1271 * Function port_write
1272 *
1273 * Description This function when a data packet is received from the apper
1274 * layer task.
1275 *
1276 * Parameters: p_port - pointer to address of port control block
1277 * p_buf - pointer to address of buffer with data,
1278 *
1279 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -08001280static int port_write(tPORT* p_port, BT_HDR* p_buf) {
1281 /* We should not allow to write data in to server port when connection is not
1282 * opened */
1283 if (p_port->is_server && (p_port->rfc.state != RFC_STATE_OPENED)) {
1284 osi_free(p_buf);
1285 return (PORT_CLOSED);
1286 }
1287
1288 /* Keep the data in pending queue if peer does not allow data, or */
1289 /* Peer is not ready or Port is not yet opened or initial port control */
1290 /* command has not been sent */
1291 if (p_port->tx.peer_fc || !p_port->rfc.p_mcb ||
1292 !p_port->rfc.p_mcb->peer_ready ||
1293 (p_port->rfc.state != RFC_STATE_OPENED) ||
1294 ((p_port->port_ctrl & (PORT_CTRL_REQ_SENT | PORT_CTRL_IND_RECEIVED)) !=
1295 (PORT_CTRL_REQ_SENT | PORT_CTRL_IND_RECEIVED))) {
1296 if ((p_port->tx.queue_size > PORT_TX_CRITICAL_WM) ||
1297 (fixed_queue_length(p_port->tx.queue) > PORT_TX_BUF_CRITICAL_WM)) {
1298 RFCOMM_TRACE_WARNING("PORT_Write: Queue size: %d", p_port->tx.queue_size);
1299
1300 osi_free(p_buf);
1301
1302 if ((p_port->p_callback != NULL) && (p_port->ev_mask & PORT_EV_ERR))
1303 p_port->p_callback(PORT_EV_ERR, p_port->inx);
1304
1305 return (PORT_TX_FULL);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001306 }
1307
Myles Watson911d1ae2016-11-28 16:44:40 -08001308 RFCOMM_TRACE_EVENT(
1309 "PORT_Write : Data is enqued. flow disabled %d peer_ready %d state %d "
1310 "ctrl_state %x",
1311 p_port->tx.peer_fc,
1312 (p_port->rfc.p_mcb && p_port->rfc.p_mcb->peer_ready), p_port->rfc.state,
1313 p_port->port_ctrl);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001314
Myles Watson911d1ae2016-11-28 16:44:40 -08001315 fixed_queue_enqueue(p_port->tx.queue, p_buf);
1316 p_port->tx.queue_size += p_buf->len;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001317
Myles Watson911d1ae2016-11-28 16:44:40 -08001318 return (PORT_CMD_PENDING);
1319 } else {
1320 RFCOMM_TRACE_EVENT("PORT_Write : Data is being sent");
The Android Open Source Project5738f832012-12-12 16:00:35 -08001321
Myles Watson911d1ae2016-11-28 16:44:40 -08001322 RFCOMM_DataReq(p_port->rfc.p_mcb, p_port->dlci, p_buf);
1323 return (PORT_SUCCESS);
1324 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001325}
1326
1327/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -08001328 *
1329 * Function PORT_Write
1330 *
1331 * Description This function when a data packet is received from the apper
1332 * layer task.
1333 *
1334 * Parameters: handle - Handle returned in the RFCOMM_CreateConnection
1335 * pp_buf - pointer to address of buffer with data,
1336 *
1337 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -08001338int PORT_Write(uint16_t handle, BT_HDR* p_buf) {
1339 tPORT* p_port;
1340 uint32_t event = 0;
1341 int rc;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001342
Myles Watson911d1ae2016-11-28 16:44:40 -08001343 RFCOMM_TRACE_API("PORT_Write() handle:%d", handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001344
Myles Watson911d1ae2016-11-28 16:44:40 -08001345 /* Check if handle is valid to avoid crashing */
1346 if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
1347 osi_free(p_buf);
1348 return (PORT_BAD_HANDLE);
1349 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001350
Myles Watson911d1ae2016-11-28 16:44:40 -08001351 p_port = &rfc_cb.port.port[handle - 1];
The Android Open Source Project5738f832012-12-12 16:00:35 -08001352
Myles Watson911d1ae2016-11-28 16:44:40 -08001353 if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
1354 osi_free(p_buf);
1355 return (PORT_NOT_OPENED);
1356 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001357
Myles Watson911d1ae2016-11-28 16:44:40 -08001358 if (p_port->line_status) {
1359 RFCOMM_TRACE_WARNING("PORT_Write: Data dropped line_status:0x%x",
1360 p_port->line_status);
1361 osi_free(p_buf);
1362 return (PORT_LINE_ERR);
1363 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001364
Myles Watson911d1ae2016-11-28 16:44:40 -08001365 rc = port_write(p_port, p_buf);
1366 event |= port_flow_control_user(p_port);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001367
Myles Watson911d1ae2016-11-28 16:44:40 -08001368 switch (rc) {
The Android Open Source Project5738f832012-12-12 16:00:35 -08001369 case PORT_TX_FULL:
Myles Watson911d1ae2016-11-28 16:44:40 -08001370 event |= PORT_EV_ERR;
1371 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001372
1373 case PORT_SUCCESS:
Myles Watson911d1ae2016-11-28 16:44:40 -08001374 event |= (PORT_EV_TXCHAR | PORT_EV_TXEMPTY);
1375 break;
1376 }
1377 /* Mask out all events that are not of interest to user */
1378 event &= p_port->ev_mask;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001379
Myles Watson911d1ae2016-11-28 16:44:40 -08001380 /* Send event to the application */
1381 if (p_port->p_callback && event) (p_port->p_callback)(event, p_port->inx);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001382
Myles Watson911d1ae2016-11-28 16:44:40 -08001383 return (PORT_SUCCESS);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001384}
1385/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -08001386 *
1387 * Function PORT_WriteDataCO
1388 *
1389 * Description Normally not GKI aware application will call this function
1390 * to send data to the port by callout functions
1391 *
1392 * Parameters: handle - Handle returned in the RFCOMM_CreateConnection
1393 * fd - socket fd
1394 * p_len - Byte count returned
1395 *
1396 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -08001397int PORT_WriteDataCO(uint16_t handle, int* p_len) {
1398 tPORT* p_port;
1399 BT_HDR* p_buf;
1400 uint32_t event = 0;
1401 int rc = 0;
1402 uint16_t length;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001403
Myles Watson911d1ae2016-11-28 16:44:40 -08001404 RFCOMM_TRACE_API("PORT_WriteDataCO() handle:%d", handle);
1405 *p_len = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001406
Myles Watson911d1ae2016-11-28 16:44:40 -08001407 /* Check if handle is valid to avoid crashing */
1408 if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
1409 return (PORT_BAD_HANDLE);
1410 }
1411 p_port = &rfc_cb.port.port[handle - 1];
The Android Open Source Project5738f832012-12-12 16:00:35 -08001412
Myles Watson911d1ae2016-11-28 16:44:40 -08001413 if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
1414 RFCOMM_TRACE_WARNING("PORT_WriteDataByFd() no port state:%d",
1415 p_port->state);
1416 return (PORT_NOT_OPENED);
1417 }
1418
1419 if (!p_port->peer_mtu) {
1420 RFCOMM_TRACE_ERROR("PORT_WriteDataByFd() peer_mtu:%d", p_port->peer_mtu);
1421 return (PORT_UNKNOWN_ERROR);
1422 }
1423 int available = 0;
1424 // if(ioctl(fd, FIONREAD, &available) < 0)
1425 if (p_port->p_data_co_callback(
1426 handle, (uint8_t*)&available, sizeof(available),
1427 DATA_CO_CALLBACK_TYPE_OUTGOING_SIZE) == false) {
1428 RFCOMM_TRACE_ERROR(
1429 "p_data_co_callback DATA_CO_CALLBACK_TYPE_INCOMING_SIZE failed, "
1430 "available:%d",
1431 available);
1432 return (PORT_UNKNOWN_ERROR);
1433 }
1434 if (available == 0) return PORT_SUCCESS;
1435 /* Length for each buffer is the smaller of GKI buffer, peer MTU, or max_len
1436 */
1437 length = RFCOMM_DATA_BUF_SIZE -
1438 (uint16_t)(sizeof(BT_HDR) + L2CAP_MIN_OFFSET + RFCOMM_DATA_OVERHEAD);
1439
1440 /* If there are buffers scheduled for transmission check if requested */
1441 /* data fits into the end of the queue */
1442 mutex_global_lock();
1443
Marie Janssenf9c57522017-02-22 08:35:29 -08001444 p_buf = (BT_HDR*)fixed_queue_try_peek_last(p_port->tx.queue);
1445 if ((p_buf != NULL) &&
Myles Watson911d1ae2016-11-28 16:44:40 -08001446 (((int)p_buf->len + available) <= (int)p_port->peer_mtu) &&
1447 (((int)p_buf->len + available) <= (int)length)) {
1448 // if(recv(fd, (uint8_t *)(p_buf + 1) + p_buf->offset + p_buf->len,
1449 // available, 0) != available)
1450 if (p_port->p_data_co_callback(
1451 handle, (uint8_t*)(p_buf + 1) + p_buf->offset + p_buf->len,
1452 available, DATA_CO_CALLBACK_TYPE_OUTGOING) == false)
1453
The Android Open Source Project5738f832012-12-12 16:00:35 -08001454 {
Myles Watson911d1ae2016-11-28 16:44:40 -08001455 error(
1456 "p_data_co_callback DATA_CO_CALLBACK_TYPE_OUTGOING failed, "
1457 "available:%d",
1458 available);
1459 mutex_global_unlock();
1460 return (PORT_UNKNOWN_ERROR);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001461 }
Myles Watson911d1ae2016-11-28 16:44:40 -08001462 // memcpy ((uint8_t *)(p_buf + 1) + p_buf->offset + p_buf->len, p_data,
1463 // max_len);
1464 p_port->tx.queue_size += (uint16_t)available;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001465
Myles Watson911d1ae2016-11-28 16:44:40 -08001466 *p_len = available;
1467 p_buf->len += (uint16_t)available;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001468
Pavlin Radoslavove29c3432015-09-27 23:27:10 -07001469 mutex_global_unlock();
The Android Open Source Project5738f832012-12-12 16:00:35 -08001470
The Android Open Source Project5738f832012-12-12 16:00:35 -08001471 return (PORT_SUCCESS);
Myles Watson911d1ae2016-11-28 16:44:40 -08001472 }
1473
1474 mutex_global_unlock();
1475
1476 // int max_read = length < p_port->peer_mtu ? length : p_port->peer_mtu;
1477
1478 // max_read = available < max_read ? available : max_read;
1479
1480 while (available) {
1481 /* if we're over buffer high water mark, we're done */
1482 if ((p_port->tx.queue_size > PORT_TX_HIGH_WM) ||
1483 (fixed_queue_length(p_port->tx.queue) > PORT_TX_BUF_HIGH_WM)) {
1484 port_flow_control_user(p_port);
1485 event |= PORT_EV_FC;
1486 RFCOMM_TRACE_EVENT(
1487 "tx queue is full,tx.queue_size:%d,tx.queue.count:%d,available:%d",
1488 p_port->tx.queue_size, fixed_queue_length(p_port->tx.queue),
1489 available);
1490 break;
1491 }
1492
1493 /* continue with rfcomm data write */
1494 p_buf = (BT_HDR*)osi_malloc(RFCOMM_DATA_BUF_SIZE);
1495 p_buf->offset = L2CAP_MIN_OFFSET + RFCOMM_MIN_OFFSET;
1496 p_buf->layer_specific = handle;
1497
1498 if (p_port->peer_mtu < length) length = p_port->peer_mtu;
1499 if (available < (int)length) length = (uint16_t)available;
1500 p_buf->len = length;
1501 p_buf->event = BT_EVT_TO_BTU_SP_DATA;
1502
1503 // memcpy ((uint8_t *)(p_buf + 1) + p_buf->offset, p_data, length);
1504 // if(recv(fd, (uint8_t *)(p_buf + 1) + p_buf->offset, (int)length, 0) !=
1505 // (int)length)
1506 if (p_port->p_data_co_callback(
1507 handle, (uint8_t*)(p_buf + 1) + p_buf->offset, length,
1508 DATA_CO_CALLBACK_TYPE_OUTGOING) == false) {
1509 error(
1510 "p_data_co_callback DATA_CO_CALLBACK_TYPE_OUTGOING failed, length:%d",
1511 length);
1512 return (PORT_UNKNOWN_ERROR);
1513 }
1514
1515 RFCOMM_TRACE_EVENT("PORT_WriteData %d bytes", length);
1516
1517 rc = port_write(p_port, p_buf);
1518
1519 /* If queue went below the threashold need to send flow control */
1520 event |= port_flow_control_user(p_port);
1521
1522 if (rc == PORT_SUCCESS) event |= PORT_EV_TXCHAR;
1523
1524 if ((rc != PORT_SUCCESS) && (rc != PORT_CMD_PENDING)) break;
1525
1526 *p_len += length;
1527 available -= (int)length;
1528 }
1529 if (!available && (rc != PORT_CMD_PENDING) && (rc != PORT_TX_QUEUE_DISABLED))
1530 event |= PORT_EV_TXEMPTY;
1531
1532 /* Mask out all events that are not of interest to user */
1533 event &= p_port->ev_mask;
1534
1535 /* Send event to the application */
1536 if (p_port->p_callback && event) (p_port->p_callback)(event, p_port->inx);
1537
1538 return (PORT_SUCCESS);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001539}
1540
The Android Open Source Project5738f832012-12-12 16:00:35 -08001541/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -08001542 *
1543 * Function PORT_WriteData
1544 *
1545 * Description Normally not GKI aware application will call this function
1546 * to send data to the port.
1547 *
1548 * Parameters: handle - Handle returned in the RFCOMM_CreateConnection
1549 * p_data - Data area
1550 * max_len - Byte count requested
1551 * p_len - Byte count received
1552 *
1553 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -08001554int PORT_WriteData(uint16_t handle, const char* p_data, uint16_t max_len,
1555 uint16_t* p_len) {
1556 tPORT* p_port;
1557 BT_HDR* p_buf;
1558 uint32_t event = 0;
1559 int rc = 0;
1560 uint16_t length;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001561
Myles Watson911d1ae2016-11-28 16:44:40 -08001562 RFCOMM_TRACE_API("PORT_WriteData() max_len:%d", max_len);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001563
Myles Watson911d1ae2016-11-28 16:44:40 -08001564 *p_len = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001565
Myles Watson911d1ae2016-11-28 16:44:40 -08001566 /* Check if handle is valid to avoid crashing */
1567 if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
1568 return (PORT_BAD_HANDLE);
1569 }
1570 p_port = &rfc_cb.port.port[handle - 1];
The Android Open Source Project5738f832012-12-12 16:00:35 -08001571
Myles Watson911d1ae2016-11-28 16:44:40 -08001572 if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
1573 RFCOMM_TRACE_WARNING("PORT_WriteData() no port state:%d", p_port->state);
1574 return (PORT_NOT_OPENED);
1575 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001576
Myles Watson911d1ae2016-11-28 16:44:40 -08001577 if (!max_len || !p_port->peer_mtu) {
1578 RFCOMM_TRACE_ERROR("PORT_WriteData() peer_mtu:%d", p_port->peer_mtu);
1579 return (PORT_UNKNOWN_ERROR);
1580 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001581
Myles Watson911d1ae2016-11-28 16:44:40 -08001582 /* Length for each buffer is the smaller of GKI buffer, peer MTU, or max_len
1583 */
1584 length = RFCOMM_DATA_BUF_SIZE -
1585 (uint16_t)(sizeof(BT_HDR) + L2CAP_MIN_OFFSET + RFCOMM_DATA_OVERHEAD);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001586
Myles Watson911d1ae2016-11-28 16:44:40 -08001587 /* If there are buffers scheduled for transmission check if requested */
1588 /* data fits into the end of the queue */
1589 mutex_global_lock();
The Android Open Source Project5738f832012-12-12 16:00:35 -08001590
Marie Janssenf9c57522017-02-22 08:35:29 -08001591 p_buf = (BT_HDR*)fixed_queue_try_peek_last(p_port->tx.queue);
1592 if ((p_buf != NULL) && ((p_buf->len + max_len) <= p_port->peer_mtu) &&
Myles Watson911d1ae2016-11-28 16:44:40 -08001593 ((p_buf->len + max_len) <= length)) {
1594 memcpy((uint8_t*)(p_buf + 1) + p_buf->offset + p_buf->len, p_data, max_len);
1595 p_port->tx.queue_size += max_len;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001596
Myles Watson911d1ae2016-11-28 16:44:40 -08001597 *p_len = max_len;
1598 p_buf->len += max_len;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001599
Pavlin Radoslavove29c3432015-09-27 23:27:10 -07001600 mutex_global_unlock();
The Android Open Source Project5738f832012-12-12 16:00:35 -08001601
The Android Open Source Project5738f832012-12-12 16:00:35 -08001602 return (PORT_SUCCESS);
Myles Watson911d1ae2016-11-28 16:44:40 -08001603 }
1604
1605 mutex_global_unlock();
1606
1607 while (max_len) {
1608 /* if we're over buffer high water mark, we're done */
1609 if ((p_port->tx.queue_size > PORT_TX_HIGH_WM) ||
1610 (fixed_queue_length(p_port->tx.queue) > PORT_TX_BUF_HIGH_WM))
1611 break;
1612
1613 /* continue with rfcomm data write */
1614 p_buf = (BT_HDR*)osi_malloc(RFCOMM_DATA_BUF_SIZE);
1615 p_buf->offset = L2CAP_MIN_OFFSET + RFCOMM_MIN_OFFSET;
1616 p_buf->layer_specific = handle;
1617
1618 if (p_port->peer_mtu < length) length = p_port->peer_mtu;
1619 if (max_len < length) length = max_len;
1620 p_buf->len = length;
1621 p_buf->event = BT_EVT_TO_BTU_SP_DATA;
1622
1623 memcpy((uint8_t*)(p_buf + 1) + p_buf->offset, p_data, length);
1624
1625 RFCOMM_TRACE_EVENT("PORT_WriteData %d bytes", length);
1626
1627 rc = port_write(p_port, p_buf);
1628
1629 /* If queue went below the threashold need to send flow control */
1630 event |= port_flow_control_user(p_port);
1631
1632 if (rc == PORT_SUCCESS) event |= PORT_EV_TXCHAR;
1633
1634 if ((rc != PORT_SUCCESS) && (rc != PORT_CMD_PENDING)) break;
1635
1636 *p_len += length;
1637 max_len -= length;
1638 p_data += length;
1639 }
1640 if (!max_len && (rc != PORT_CMD_PENDING) && (rc != PORT_TX_QUEUE_DISABLED))
1641 event |= PORT_EV_TXEMPTY;
1642
1643 /* Mask out all events that are not of interest to user */
1644 event &= p_port->ev_mask;
1645
1646 /* Send event to the application */
1647 if (p_port->p_callback && event) (p_port->p_callback)(event, p_port->inx);
1648
1649 return (PORT_SUCCESS);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001650}
1651
The Android Open Source Project5738f832012-12-12 16:00:35 -08001652/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -08001653 *
1654 * Function PORT_Test
1655 *
1656 * Description Application can call this function to send RFCOMM Test frame
1657 *
1658 * Parameters: handle - Handle returned in the RFCOMM_CreateConnection
1659 * p_data - Data area
1660 * max_len - Byte count requested
1661 *
1662 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -08001663int PORT_Test(uint16_t handle, uint8_t* p_data, uint16_t len) {
1664 tPORT* p_port;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001665
Myles Watson911d1ae2016-11-28 16:44:40 -08001666 RFCOMM_TRACE_API("PORT_Test() len:%d", len);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001667
Myles Watson911d1ae2016-11-28 16:44:40 -08001668 if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
1669 return (PORT_BAD_HANDLE);
1670 }
1671 p_port = &rfc_cb.port.port[handle - 1];
The Android Open Source Project5738f832012-12-12 16:00:35 -08001672
Myles Watson911d1ae2016-11-28 16:44:40 -08001673 if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
1674 return (PORT_NOT_OPENED);
1675 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001676
Myles Watson911d1ae2016-11-28 16:44:40 -08001677 if (len > ((p_port->mtu == 0) ? RFCOMM_DEFAULT_MTU : p_port->mtu)) {
1678 return (PORT_UNKNOWN_ERROR);
1679 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001680
Myles Watson911d1ae2016-11-28 16:44:40 -08001681 BT_HDR* p_buf = (BT_HDR*)osi_malloc(RFCOMM_CMD_BUF_SIZE);
1682 p_buf->offset = L2CAP_MIN_OFFSET + RFCOMM_MIN_OFFSET + 2;
1683 p_buf->len = len;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001684
Myles Watson911d1ae2016-11-28 16:44:40 -08001685 memcpy((uint8_t*)(p_buf + 1) + p_buf->offset, p_data, p_buf->len);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001686
Myles Watson911d1ae2016-11-28 16:44:40 -08001687 rfc_send_test(p_port->rfc.p_mcb, true, p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001688
Myles Watson911d1ae2016-11-28 16:44:40 -08001689 return (PORT_SUCCESS);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001690}
1691
1692/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -08001693 *
1694 * Function RFCOMM_Init
1695 *
1696 * Description This function is called to initialize RFCOMM layer
1697 *
1698 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -08001699void RFCOMM_Init(void) {
1700 memset(&rfc_cb, 0, sizeof(tRFC_CB)); /* Init RFCOMM control block */
The Android Open Source Project5738f832012-12-12 16:00:35 -08001701
Myles Watson911d1ae2016-11-28 16:44:40 -08001702 rfc_cb.rfc.last_mux = MAX_BD_CONNECTIONS;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001703
1704#if defined(RFCOMM_INITIAL_TRACE_LEVEL)
Myles Watson911d1ae2016-11-28 16:44:40 -08001705 rfc_cb.trace_level = RFCOMM_INITIAL_TRACE_LEVEL;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001706#else
Myles Watson911d1ae2016-11-28 16:44:40 -08001707 rfc_cb.trace_level = BT_TRACE_LEVEL_NONE; /* No traces */
The Android Open Source Project5738f832012-12-12 16:00:35 -08001708#endif
1709
Myles Watson911d1ae2016-11-28 16:44:40 -08001710 rfcomm_l2cap_if_init();
The Android Open Source Project5738f832012-12-12 16:00:35 -08001711}
1712
1713/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -08001714 *
1715 * Function PORT_SetTraceLevel
1716 *
Myles Watson9ca07092016-11-28 16:41:53 -08001717 * Description Set the trace level for RFCOMM. If called with 0xFF, it
1718 * simply reads the current trace level.
Myles Watsonee96a3c2016-11-23 14:49:54 -08001719 *
1720 * Returns the new (current) trace level
1721 *
1722 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -08001723uint8_t PORT_SetTraceLevel(uint8_t new_level) {
1724 if (new_level != 0xFF) rfc_cb.trace_level = new_level;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001725
Myles Watson911d1ae2016-11-28 16:44:40 -08001726 return (rfc_cb.trace_level);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001727}
1728
June R. Tate-Gans1e8cb562014-12-02 12:48:03 -08001729/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -08001730 *
1731 * Function PORT_GetResultString
1732 *
1733 * Description This function returns the human-readable string for a given
1734 * result code.
1735 *
1736 * Returns a pointer to the human-readable string for the given result.
1737 *
1738 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -08001739const char* PORT_GetResultString(const uint8_t result_code) {
June R. Tate-Gans1e8cb562014-12-02 12:48:03 -08001740 if (result_code > PORT_ERR_MAX) {
1741 return result_code_strings[PORT_ERR_MAX];
1742 }
1743
1744 return result_code_strings[result_code];
1745}