| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869 |
- /******************************************************************************
- *
- * Copyright (C) 1999-2012 Broadcom Corporation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************************/
- /******************************************************************************
- *
- * this file contains the Serial Port API code
- *
- ******************************************************************************/
- #include <string.h>
- #include "common/bt_target.h"
- #include "stack/rfcdefs.h"
- #include "stack/port_api.h"
- #include "port_int.h"
- #include "btm_int.h"
- #include "stack/btm_api.h"
- #include "rfc_int.h"
- #include "stack/l2c_api.h"
- #include "stack/sdp_api.h"
- #include "osi/allocator.h"
- #include "osi/mutex.h"
- #if (defined RFCOMM_INCLUDED && RFCOMM_INCLUDED == TRUE)
- /* duration of break in 200ms units */
- #define PORT_BREAK_DURATION 1
- /* Mapping from PORT_* result codes to human readable strings. */
- static const char *result_code_strings[] = {
- "Success",
- "Unknown error",
- "Already opened",
- "Command pending",
- "App not registered",
- "No memory",
- "No resources",
- "Bad BD address",
- "Unspecified error",
- "Bad handle",
- "Not opened",
- "Line error",
- "Start failed",
- "Parameter negotiation failed",
- "Port negotiation failed",
- "Sec failed",
- "Peer connection failed",
- "Peer failed",
- "Peer timeout",
- "Closed",
- "TX full",
- "Local closed",
- "Local timeout",
- "TX queue disabled",
- "Page timeout",
- "Invalid SCN",
- "Unknown result code"
- };
- /*******************************************************************************
- **
- ** Function RFCOMM_CreateConnection
- **
- ** Description RFCOMM_CreateConnection function is used from the application
- ** to establish serial port connection to the peer device,
- ** or allow RFCOMM to accept a connection from the peer
- ** application.
- **
- ** Parameters: scn - Service Channel Number as registered with
- ** the SDP (server) or obtained using SDP from
- ** the peer device (client).
- ** is_server - TRUE if requesting application is a server
- ** mtu - Maximum frame size the application can accept
- ** bd_addr - BD_ADDR of the peer (client)
- ** mask - specifies events to be enabled. A value
- ** of zero disables all events.
- ** p_handle - OUT pointer to the handle.
- ** p_mgmt_cb - pointer to callback function to receive
- ** connection up/down events.
- ** Notes:
- **
- ** Server can call this function with the same scn parameter multiple times if
- ** it is ready to accept multiple simulteneous connections.
- **
- ** DLCI for the connection is (scn * 2 + 1) if client originates connection on
- ** existing none initiator multiplexer channel. Otherwise it is (scn * 2).
- ** For the server DLCI can be changed later if client will be calling it using
- ** (scn * 2 + 1) dlci.
- **
- *******************************************************************************/
- int RFCOMM_CreateConnection (UINT16 uuid, UINT8 scn, BOOLEAN is_server,
- UINT16 mtu, BD_ADDR bd_addr, UINT16 *p_handle,
- tPORT_MGMT_CALLBACK *p_mgmt_cb)
- {
- tPORT *p_port;
- int i;
- UINT8 dlci;
- tRFC_MCB *p_mcb = port_find_mcb (bd_addr);
- UINT16 rfcomm_mtu;
- RFCOMM_TRACE_API ("RFCOMM_CreateConnection() BDA: %02x-%02x-%02x-%02x-%02x-%02x",
- bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]);
- *p_handle = 0;
- if (( scn == 0 ) || (scn >= PORT_MAX_RFC_PORTS )) {
- /* Server Channel Number(SCN) should be in range 1...30 */
- RFCOMM_TRACE_ERROR ("RFCOMM_CreateConnection - invalid SCN");
- return (PORT_INVALID_SCN);
- }
- /* For client that originate connection on the existing none initiator */
- /* multiplexer channel DLCI should be odd */
- if (p_mcb && !p_mcb->is_initiator && !is_server) {
- dlci = (scn << 1) + 1;
- } else {
- dlci = (scn << 1);
- }
- RFCOMM_TRACE_API("RFCOMM_CreateConnection(): scn:%d, dlci:%d, is_server:%d mtu:%d, p_mcb:%p",
- scn, dlci, is_server, mtu, p_mcb);
- /* For the server side always allocate a new port. On the client side */
- /* do not allow the same (dlci, bd_addr) to be opened twice by application */
- if (!is_server && ((p_port = port_find_port (dlci, bd_addr)) != NULL)) {
- /* if existing port is also a client port */
- if (p_port->is_server == FALSE) {
- RFCOMM_TRACE_ERROR ("RFCOMM_CreateConnection - already opened state:%d, RFC state:%d, MCB state:%d",
- p_port->state, p_port->rfc.state, p_port->rfc.p_mcb ? p_port->rfc.p_mcb->state : 0);
- return (PORT_ALREADY_OPENED);
- }
- }
- if ((p_port = port_allocate_port (dlci, bd_addr)) == NULL) {
- RFCOMM_TRACE_WARNING ("RFCOMM_CreateConnection - no resources");
- return (PORT_NO_RESOURCES);
- }
- RFCOMM_TRACE_API("RFCOMM_CreateConnection(): scn:%d, dlci:%d, is_server:%d mtu:%d, p_mcb:%p, p_port:%p",
- scn, dlci, is_server, mtu, p_mcb, p_port);
- p_port->default_signal_state = (PORT_DTRDSR_ON | PORT_CTSRTS_ON | PORT_DCD_ON);
- switch (uuid) {
- case UUID_PROTOCOL_OBEX:
- p_port->default_signal_state = PORT_OBEX_DEFAULT_SIGNAL_STATE;
- break;
- case UUID_SERVCLASS_SERIAL_PORT:
- p_port->default_signal_state = PORT_SPP_DEFAULT_SIGNAL_STATE;
- break;
- case UUID_SERVCLASS_LAN_ACCESS_USING_PPP:
- p_port->default_signal_state = PORT_PPP_DEFAULT_SIGNAL_STATE;
- break;
- case UUID_SERVCLASS_DIALUP_NETWORKING:
- case UUID_SERVCLASS_FAX:
- p_port->default_signal_state = PORT_DUN_DEFAULT_SIGNAL_STATE;
- break;
- }
- RFCOMM_TRACE_EVENT ("RFCOMM_CreateConnection dlci:%d signal state:0x%x", dlci, p_port->default_signal_state);
- *p_handle = p_port->inx;
- p_port->state = PORT_STATE_OPENING;
- p_port->uuid = uuid;
- p_port->is_server = is_server;
- p_port->scn = scn;
- p_port->ev_mask = 0;
- /* If the MTU is not specified (0), keep MTU decision until the
- * PN frame has to be send
- * at that time connection should be established and we
- * will know for sure our prefered MTU
- */
- rfcomm_mtu = L2CAP_MTU_SIZE - RFCOMM_DATA_OVERHEAD;
- if (mtu) {
- p_port->mtu = (mtu < rfcomm_mtu) ? mtu : rfcomm_mtu;
- } else {
- p_port->mtu = rfcomm_mtu;
- }
- /* server doesn't need to release port when closing */
- if ( is_server ) {
- p_port->keep_port_handle = TRUE;
- /* keep mtu that user asked, p_port->mtu could be updated during param negotiation */
- p_port->keep_mtu = p_port->mtu;
- }
- p_port->local_ctrl.modem_signal = p_port->default_signal_state;
- p_port->local_ctrl.fc = FALSE;
- p_port->p_mgmt_callback = p_mgmt_cb;
- for (i = 0; i < BD_ADDR_LEN; i++) {
- p_port->bd_addr[i] = bd_addr[i];
- }
- /* If this is not initiator of the connection need to just wait */
- if (p_port->is_server) {
- return (PORT_SUCCESS);
- }
- /* Open will be continued after security checks are passed */
- return port_open_continue (p_port);
- }
- /*******************************************************************************
- **
- ** Function RFCOMM_RemoveConnection
- **
- ** Description This function is called to close the specified connection.
- **
- ** Parameters: handle - Handle returned in the RFCOMM_CreateConnection
- **
- *******************************************************************************/
- int RFCOMM_RemoveConnection (UINT16 handle)
- {
- tPORT *p_port;
- RFCOMM_TRACE_API ("RFCOMM_RemoveConnection() handle:%d", handle);
- /* Check if handle is valid to avoid crashing */
- if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
- RFCOMM_TRACE_ERROR ("RFCOMM_RemoveConnection() BAD handle:%d", handle);
- return (PORT_BAD_HANDLE);
- }
- p_port = &rfc_cb.port.port[handle - 1];
- if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
- RFCOMM_TRACE_EVENT ("RFCOMM_RemoveConnection() Not opened:%d", handle);
- return (PORT_SUCCESS);
- }
- p_port->state = PORT_STATE_CLOSING;
- port_start_close (p_port);
- return (PORT_SUCCESS);
- }
- /*******************************************************************************
- **
- ** Function RFCOMM_RemoveServer
- **
- ** Description This function is called to close the server port.
- **
- ** Parameters: handle - Handle returned in the RFCOMM_CreateConnection
- **
- *******************************************************************************/
- int RFCOMM_RemoveServer (UINT16 handle)
- {
- tPORT *p_port;
- RFCOMM_TRACE_API ("RFCOMM_RemoveServer() handle:%d", handle);
- /* Check if handle is valid to avoid crashing */
- if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
- RFCOMM_TRACE_ERROR ("RFCOMM_RemoveServer() BAD handle:%d", handle);
- return (PORT_BAD_HANDLE);
- }
- p_port = &rfc_cb.port.port[handle - 1];
- /* Do not report any events to the client any more. */
- p_port->p_mgmt_callback = NULL;
- if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
- RFCOMM_TRACE_EVENT ("RFCOMM_RemoveServer() Not opened:%d", handle);
- return (PORT_SUCCESS);
- }
- /* this port will be deallocated after closing */
- p_port->keep_port_handle = FALSE;
- p_port->state = PORT_STATE_CLOSING;
- port_start_close (p_port);
- return (PORT_SUCCESS);
- }
- /*******************************************************************************
- **
- ** Function PORT_SetEventCallback
- **
- ** Description This function is called to provide an address of the
- ** function which will be called when one of the events
- ** specified in the mask occures.
- **
- ** Parameters: handle - Handle returned in the RFCOMM_CreateConnection
- ** p_callback - address of the callback function which should
- ** be called from the RFCOMM when an event
- ** specified in the mask occures.
- **
- **
- *******************************************************************************/
- int PORT_SetEventCallback (UINT16 port_handle, tPORT_CALLBACK *p_port_cb)
- {
- tPORT *p_port;
- /* Check if handle is valid to avoid crashing */
- if ((port_handle == 0) || (port_handle > MAX_RFC_PORTS)) {
- return (PORT_BAD_HANDLE);
- }
- p_port = &rfc_cb.port.port[port_handle - 1];
- if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
- return (PORT_NOT_OPENED);
- }
- RFCOMM_TRACE_API ("PORT_SetEventCallback() handle:%d", port_handle);
- p_port->p_callback = p_port_cb;
- return (PORT_SUCCESS);
- }
- /*******************************************************************************
- **
- ** Function PORT_ClearKeepHandleFlag
- **
- ** Description This function is called to clear the keep handle flag
- ** which will cause not to keep the port handle open when closed
- ** Parameters: handle - Handle returned in the RFCOMM_CreateConnection
- **
- *******************************************************************************/
- int PORT_ClearKeepHandleFlag (UINT16 port_handle)
- {
- tPORT *p_port;
- /* Check if handle is valid to avoid crashing */
- if ((port_handle == 0) || (port_handle > MAX_RFC_PORTS)) {
- return (PORT_BAD_HANDLE);
- }
- p_port = &rfc_cb.port.port[port_handle - 1];
- p_port->keep_port_handle = 0;
- return (PORT_SUCCESS);
- }
- /*******************************************************************************
- **
- ** Function PORT_SetDataCallback
- **
- ** Description This function is when a data packet is received
- **
- ** Parameters: handle - Handle returned in the RFCOMM_CreateConnection
- ** p_callback - address of the callback function which should
- ** be called from the RFCOMM when data packet
- ** is received.
- **
- **
- *******************************************************************************/
- int PORT_SetDataCallback (UINT16 port_handle, tPORT_DATA_CALLBACK *p_port_cb)
- {
- tPORT *p_port;
- // RFCOMM_TRACE_API ("PORT_SetDataCallback() handle:%d cb 0x%x", port_handle, p_port_cb);
- /* Check if handle is valid to avoid crashing */
- if ((port_handle == 0) || (port_handle > MAX_RFC_PORTS)) {
- return (PORT_BAD_HANDLE);
- }
- p_port = &rfc_cb.port.port[port_handle - 1];
- if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
- return (PORT_NOT_OPENED);
- }
- p_port->p_data_callback = p_port_cb;
- return (PORT_SUCCESS);
- }
- /*******************************************************************************
- **
- ** Function PORT_SetCODataCallback
- **
- ** Description This function is when a data packet is received
- **
- ** Parameters: handle - Handle returned in the RFCOMM_CreateConnection
- ** p_callback - address of the callback function which should
- ** be called from the RFCOMM when data packet
- ** is received.
- **
- **
- *******************************************************************************/
- int PORT_SetDataCOCallback (UINT16 port_handle, tPORT_DATA_CO_CALLBACK *p_port_cb)
- {
- tPORT *p_port;
- // RFCOMM_TRACE_API ("PORT_SetDataCOCallback() handle:%d cb 0x%x", port_handle, p_port_cb);
- /* Check if handle is valid to avoid crashing */
- if ((port_handle == 0) || (port_handle > MAX_RFC_PORTS)) {
- return (PORT_BAD_HANDLE);
- }
- p_port = &rfc_cb.port.port[port_handle - 1];
- if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
- return (PORT_NOT_OPENED);
- }
- p_port->p_data_co_callback = p_port_cb;
- return (PORT_SUCCESS);
- }
- /*******************************************************************************
- **
- ** Function PORT_SetEventMask
- **
- ** Description This function is called to close the specified connection.
- **
- ** Parameters: handle - Handle returned in the RFCOMM_CreateConnection
- ** mask - Bitmask of the events the host is interested in
- **
- *******************************************************************************/
- int PORT_SetEventMask (UINT16 port_handle, UINT32 mask)
- {
- tPORT *p_port;
- RFCOMM_TRACE_API ("PORT_SetEventMask() handle:%d mask:0x%x", port_handle, mask);
- /* Check if handle is valid to avoid crashing */
- if ((port_handle == 0) || (port_handle > MAX_RFC_PORTS)) {
- return (PORT_BAD_HANDLE);
- }
- p_port = &rfc_cb.port.port[port_handle - 1];
- if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
- return (PORT_NOT_OPENED);
- }
- p_port->ev_mask = mask;
- return (PORT_SUCCESS);
- }
- /*******************************************************************************
- **
- ** Function PORT_CheckConnection
- **
- ** Description This function returns PORT_SUCCESS if connection referenced
- ** by handle is up and running
- **
- ** Parameters: handle - Handle returned in the RFCOMM_CreateConnection
- ** ignore_rfc_state - If need to ignore rfc state
- ** bd_addr - OUT bd_addr of the peer
- ** p_lcid - OUT L2CAP's LCID
- **
- *******************************************************************************/
- int PORT_CheckConnection(UINT16 handle, BOOLEAN ignore_rfc_state, BD_ADDR bd_addr, UINT16 *p_lcid)
- {
- tPORT *p_port;
- RFCOMM_TRACE_API ("PORT_CheckConnection() handle:%d", handle);
- /* Check if handle is valid to avoid crashing */
- if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
- return (PORT_BAD_HANDLE);
- }
- p_port = &rfc_cb.port.port[handle - 1];
- if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
- return (PORT_NOT_OPENED);
- }
- if (!p_port->rfc.p_mcb || !p_port->rfc.p_mcb->peer_ready ||
- (!ignore_rfc_state ? (p_port->rfc.state != RFC_STATE_OPENED) : false)) {
- return (PORT_LINE_ERR);
- }
- memcpy (bd_addr, p_port->rfc.p_mcb->bd_addr, BD_ADDR_LEN);
- if (p_lcid) {
- *p_lcid = p_port->rfc.p_mcb->lcid;
- }
- return (PORT_SUCCESS);
- }
- /*******************************************************************************
- **
- ** Function PORT_IsOpening
- **
- ** Description This function returns TRUE if there is any RFCOMM connection
- ** opening in process.
- **
- ** Parameters: TRUE if any connection opening is found
- ** bd_addr - bd_addr of the peer
- **
- *******************************************************************************/
- BOOLEAN PORT_IsOpening (BD_ADDR bd_addr)
- {
- UINT8 xx, yy;
- tRFC_MCB *p_mcb = NULL;
- tPORT *p_port;
- BOOLEAN found_port;
- /* Check for any rfc_mcb which is in the middle of opening. */
- for (xx = 0; xx < MAX_BD_CONNECTIONS; xx++) {
- if ((rfc_cb.port.rfc_mcb[xx].state > RFC_MX_STATE_IDLE) &&
- (rfc_cb.port.rfc_mcb[xx].state < RFC_MX_STATE_CONNECTED)) {
- memcpy (bd_addr, rfc_cb.port.rfc_mcb[xx].bd_addr, BD_ADDR_LEN);
- return TRUE;
- }
- if (rfc_cb.port.rfc_mcb[xx].state == RFC_MX_STATE_CONNECTED) {
- found_port = FALSE;
- p_mcb = &rfc_cb.port.rfc_mcb[xx];
- p_port = &rfc_cb.port.port[0];
- for (yy = 0; yy < MAX_RFC_PORTS; yy++, p_port++) {
- if (p_port->rfc.p_mcb == p_mcb) {
- found_port = TRUE;
- break;
- }
- }
- if ((!found_port) ||
- (found_port && (p_port->rfc.state < RFC_STATE_OPENED))) {
- /* Port is not established yet. */
- memcpy (bd_addr, rfc_cb.port.rfc_mcb[xx].bd_addr, BD_ADDR_LEN);
- return TRUE;
- }
- }
- }
- return FALSE;
- }
- /*******************************************************************************
- **
- ** Function PORT_SetState
- **
- ** Description This function configures connection according to the
- ** specifications in the tPORT_STATE structure.
- **
- ** Parameters: handle - Handle returned in the RFCOMM_CreateConnection
- ** p_settings - Pointer to a tPORT_STATE structure containing
- ** configuration information for the connection.
- **
- **
- *******************************************************************************/
- int PORT_SetState (UINT16 handle, tPORT_STATE *p_settings)
- {
- tPORT *p_port;
- UINT8 baud_rate;
- RFCOMM_TRACE_API ("PORT_SetState() handle:%d", handle);
- /* Check if handle is valid to avoid crashing */
- if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
- return (PORT_BAD_HANDLE);
- }
- p_port = &rfc_cb.port.port[handle - 1];
- if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
- return (PORT_NOT_OPENED);
- }
- if (p_port->line_status) {
- return (PORT_LINE_ERR);
- }
- RFCOMM_TRACE_API ("PORT_SetState() handle:%d FC_TYPE:0x%x", handle,
- p_settings->fc_type);
- baud_rate = p_port->user_port_pars.baud_rate;
- p_port->user_port_pars = *p_settings;
- /* for now we've been asked to pass only baud rate */
- if (baud_rate != p_settings->baud_rate) {
- port_start_par_neg (p_port);
- }
- return (PORT_SUCCESS);
- }
- /*******************************************************************************
- **
- ** Function PORT_GetRxQueueCnt
- **
- ** Description This function return number of buffers on the rx queue.
- **
- ** Parameters: handle - Handle returned in the RFCOMM_CreateConnection
- ** p_rx_queue_count - Pointer to return queue count in.
- **
- *******************************************************************************/
- int PORT_GetRxQueueCnt (UINT16 handle, UINT16 *p_rx_queue_count)
- {
- tPORT *p_port;
- RFCOMM_TRACE_API ("PORT_GetRxQueueCnt() handle:%d", handle);
- /* Check if handle is valid to avoid crashing */
- if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
- return (PORT_BAD_HANDLE);
- }
- p_port = &rfc_cb.port.port[handle - 1];
- if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
- return (PORT_NOT_OPENED);
- }
- if (p_port->line_status) {
- return (PORT_LINE_ERR);
- }
- *p_rx_queue_count = p_port->rx.queue_size;
- RFCOMM_TRACE_API ("PORT_GetRxQueueCnt() p_rx_queue_count:%d, p_port->rx.queue.count = %d",
- *p_rx_queue_count, p_port->rx.queue_size);
- return (PORT_SUCCESS);
- }
- /*******************************************************************************
- **
- ** Function PORT_GetState
- **
- ** Description This function is called to fill tPORT_STATE structure
- ** with the curremt control settings for the port
- **
- ** Parameters: handle - Handle returned in the RFCOMM_CreateConnection
- ** p_settings - Pointer to a tPORT_STATE structure in which
- ** configuration information is returned.
- **
- *******************************************************************************/
- int PORT_GetState (UINT16 handle, tPORT_STATE *p_settings)
- {
- tPORT *p_port;
- RFCOMM_TRACE_API ("PORT_GetState() handle:%d", handle);
- /* Check if handle is valid to avoid crashing */
- if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
- return (PORT_BAD_HANDLE);
- }
- p_port = &rfc_cb.port.port[handle - 1];
- if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
- return (PORT_NOT_OPENED);
- }
- if (p_port->line_status) {
- return (PORT_LINE_ERR);
- }
- *p_settings = p_port->user_port_pars;
- return (PORT_SUCCESS);
- }
- /*******************************************************************************
- **
- ** Function PORT_Control
- **
- ** Description This function directs a specified connection to pass control
- ** control information to the peer device.
- **
- ** Parameters: handle - Handle returned in the RFCOMM_CreateConnection
- ** signal = specify the function to be passed
- **
- *******************************************************************************/
- int PORT_Control (UINT16 handle, UINT8 signal)
- {
- tPORT *p_port;
- UINT8 old_modem_signal;
- RFCOMM_TRACE_API ("PORT_Control() handle:%d signal:0x%x", handle, signal);
- /* Check if handle is valid to avoid crashing */
- if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
- return (PORT_BAD_HANDLE);
- }
- p_port = &rfc_cb.port.port[handle - 1];
- if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
- return (PORT_NOT_OPENED);
- }
- old_modem_signal = p_port->local_ctrl.modem_signal;
- p_port->local_ctrl.break_signal = 0;
- switch (signal) {
- case PORT_SET_CTSRTS:
- p_port->local_ctrl.modem_signal |= PORT_CTSRTS_ON;
- break;
- case PORT_CLR_CTSRTS:
- p_port->local_ctrl.modem_signal &= ~PORT_CTSRTS_ON;
- break;
- case PORT_SET_DTRDSR:
- p_port->local_ctrl.modem_signal |= PORT_DTRDSR_ON;
- break;
- case PORT_CLR_DTRDSR:
- p_port->local_ctrl.modem_signal &= ~PORT_DTRDSR_ON;
- break;
- case PORT_SET_RI:
- p_port->local_ctrl.modem_signal |= PORT_RING_ON;
- break;
- case PORT_CLR_RI:
- p_port->local_ctrl.modem_signal &= ~PORT_RING_ON;
- break;
- case PORT_SET_DCD:
- p_port->local_ctrl.modem_signal |= PORT_DCD_ON;
- break;
- case PORT_CLR_DCD:
- p_port->local_ctrl.modem_signal &= ~PORT_DCD_ON;
- break;
- }
- if (signal == PORT_BREAK) {
- p_port->local_ctrl.break_signal = PORT_BREAK_DURATION;
- } else if (p_port->local_ctrl.modem_signal == old_modem_signal) {
- return (PORT_SUCCESS);
- }
- port_start_control (p_port);
- RFCOMM_TRACE_EVENT ("PORT_Control DTR_DSR : %d, RTS_CTS : %d, RI : %d, DCD : %d",
- ((p_port->local_ctrl.modem_signal & MODEM_SIGNAL_DTRDSR) ? 1 : 0),
- ((p_port->local_ctrl.modem_signal & MODEM_SIGNAL_RTSCTS) ? 1 : 0),
- ((p_port->local_ctrl.modem_signal & MODEM_SIGNAL_RI) ? 1 : 0),
- ((p_port->local_ctrl.modem_signal & MODEM_SIGNAL_DCD) ? 1 : 0));
- return (PORT_SUCCESS);
- }
- /*******************************************************************************
- **
- ** Function PORT_FlowControl
- **
- ** Description This function directs a specified connection to pass
- ** flow control message to the peer device. Enable flag passed
- ** shows if port can accept more data.
- **
- ** Parameters: handle - Handle returned in the RFCOMM_CreateConnection
- ** enable - enables data flow
- **
- *******************************************************************************/
- int PORT_FlowControl (UINT16 handle, BOOLEAN enable)
- {
- tPORT *p_port;
- BOOLEAN old_fc;
- UINT32 events;
- RFCOMM_TRACE_API ("PORT_FlowControl() handle:%d enable: %d", handle, enable);
- /* Check if handle is valid to avoid crashing */
- if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
- return (PORT_BAD_HANDLE);
- }
- p_port = &rfc_cb.port.port[handle - 1];
- if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
- return (PORT_NOT_OPENED);
- }
- if (!p_port->rfc.p_mcb) {
- return (PORT_NOT_OPENED);
- }
- p_port->rx.user_fc = !enable;
- if (p_port->rfc.p_mcb->flow == PORT_FC_CREDIT) {
- if (!p_port->rx.user_fc) {
- port_flow_control_peer(p_port, TRUE, 0);
- }
- } else {
- old_fc = p_port->local_ctrl.fc;
- /* FC is set if user is set or peer is set */
- p_port->local_ctrl.fc = (p_port->rx.user_fc | p_port->rx.peer_fc);
- if (p_port->local_ctrl.fc != old_fc) {
- port_start_control (p_port);
- }
- }
- /* Need to take care of the case when we could not deliver events */
- /* to the application because we were flow controlled */
- if (enable && (p_port->rx.queue_size != 0)) {
- events = PORT_EV_RXCHAR;
- if (p_port->rx_flag_ev_pending) {
- p_port->rx_flag_ev_pending = FALSE;
- events |= PORT_EV_RXFLAG;
- }
- events &= p_port->ev_mask;
- if (p_port->p_callback && events) {
- p_port->p_callback (events, p_port->inx);
- }
- }
- return (PORT_SUCCESS);
- }
- #if 0 //Unused
- /*******************************************************************************
- **
- ** Function PORT_FlowControl_MaxCredit
- **
- ** Description This function directs a specified connection to pass
- ** flow control message to the peer device. Enable flag passed
- ** shows if port can accept more data. It also sends max credit
- ** when data flow enabled
- **
- ** Parameters: handle - Handle returned in the RFCOMM_CreateConnection
- ** enable - enables data flow
- **
- *******************************************************************************/
- int PORT_FlowControl_MaxCredit (UINT16 handle, BOOLEAN enable)
- {
- tPORT *p_port;
- BOOLEAN old_fc;
- UINT32 events;
- RFCOMM_TRACE_API ("PORT_FlowControl() handle:%d enable: %d", handle, enable);
- /* Check if handle is valid to avoid crashing */
- if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
- return (PORT_BAD_HANDLE);
- }
- p_port = &rfc_cb.port.port[handle - 1];
- if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
- return (PORT_NOT_OPENED);
- }
- if (!p_port->rfc.p_mcb) {
- return (PORT_NOT_OPENED);
- }
- p_port->rx.user_fc = !enable;
- if (p_port->rfc.p_mcb->flow == PORT_FC_CREDIT) {
- if (!p_port->rx.user_fc) {
- port_flow_control_peer(p_port, TRUE, p_port->credit_rx);
- }
- } else {
- old_fc = p_port->local_ctrl.fc;
- /* FC is set if user is set or peer is set */
- p_port->local_ctrl.fc = (p_port->rx.user_fc | p_port->rx.peer_fc);
- if (p_port->local_ctrl.fc != old_fc) {
- port_start_control (p_port);
- }
- }
- /* Need to take care of the case when we could not deliver events */
- /* to the application because we were flow controlled */
- if (enable && (p_port->rx.queue_size != 0)) {
- events = PORT_EV_RXCHAR;
- if (p_port->rx_flag_ev_pending) {
- p_port->rx_flag_ev_pending = FALSE;
- events |= PORT_EV_RXFLAG;
- }
- events &= p_port->ev_mask;
- if (p_port->p_callback && events) {
- p_port->p_callback (events, p_port->inx);
- }
- }
- return (PORT_SUCCESS);
- }
- #endif
- /*******************************************************************************
- **
- ** Function PORT_FlowControl_GiveCredit
- **
- ** Description This function gives specified credits to the peer
- **
- ** Parameters: handle - Handle returned in the RFCOMM_CreateConnection
- ** enable - enables data flow
- ** credits_given - credits to give
- **
- *******************************************************************************/
- int PORT_FlowControl_GiveCredit (UINT16 handle, BOOLEAN enable, UINT16 credits_given)
- {
- tPORT *p_port;
- BOOLEAN old_fc;
- UINT32 events;
- RFCOMM_TRACE_DEBUG("%s handle:%d enable: %d, cred %d", __func__, handle, enable, credits_given);
- /* Check if handle is valid to avoid crashing */
- if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
- return (PORT_BAD_HANDLE);
- }
- p_port = &rfc_cb.port.port[handle - 1];
- if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
- return (PORT_NOT_OPENED);
- }
- if (!p_port->rfc.p_mcb) {
- return (PORT_NOT_OPENED);
- }
- p_port->rx.user_fc = !enable;
- if (p_port->rfc.p_mcb->flow == PORT_FC_CREDIT) {
- if (!p_port->rx.user_fc) {
- port_flow_control_peer(p_port, TRUE, credits_given);
- }
- } else {
- assert(0); // karl: temporarily not allowed
- old_fc = p_port->local_ctrl.fc;
- /* FC is set if user is set or peer is set */
- p_port->local_ctrl.fc = (p_port->rx.user_fc | p_port->rx.peer_fc);
- if (p_port->local_ctrl.fc != old_fc) {
- port_start_control (p_port);
- }
- }
- /* Need to take care of the case when we could not deliver events */
- /* to the application because we were flow controlled */
- if (enable && (p_port->rx.queue_size != 0)) {
- assert(0); // karl: temporarily not allowed
- events = PORT_EV_RXCHAR;
- if (p_port->rx_flag_ev_pending) {
- p_port->rx_flag_ev_pending = FALSE;
- events |= PORT_EV_RXFLAG;
- }
- events &= p_port->ev_mask;
- if (p_port->p_callback && events) {
- p_port->p_callback (events, p_port->inx);
- }
- }
- return (PORT_SUCCESS);
- }
- /*******************************************************************************
- **
- ** Function PORT_GetModemStatus
- **
- ** Description This function retrieves modem control signals. Normally
- ** application will call this function after a callback
- ** function is called with notification that one of signals
- ** has been changed.
- **
- ** Parameters: handle - Handle returned in the RFCOMM_CreateConnection
- ** p_signal - specify the pointer to control signals info
- **
- *******************************************************************************/
- int PORT_GetModemStatus (UINT16 handle, UINT8 *p_signal)
- {
- tPORT *p_port;
- if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
- return (PORT_BAD_HANDLE);
- }
- p_port = &rfc_cb.port.port[handle - 1];
- if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
- return (PORT_NOT_OPENED);
- }
- *p_signal = p_port->peer_ctrl.modem_signal;
- RFCOMM_TRACE_API ("PORT_GetModemStatus() handle:%d signal:%x", handle, *p_signal);
- return (PORT_SUCCESS);
- }
- /*******************************************************************************
- **
- ** Function PORT_ClearError
- **
- ** Description This function retreives information about a communications
- ** error and reports current status of a connection. The
- ** function should be called when an error occures to clear
- ** the connection error flag and to enable additional read
- ** and write operations.
- **
- ** Parameters: handle - Handle returned in the RFCOMM_CreateConnection
- ** p_errors - pointer of the variable to receive error codes
- ** p_status - pointer to the tPORT_STATUS structur to receive
- ** connection status
- **
- *******************************************************************************/
- int PORT_ClearError (UINT16 handle, UINT16 *p_errors, tPORT_STATUS *p_status)
- {
- tPORT *p_port;
- RFCOMM_TRACE_API ("PORT_ClearError() handle:%d", handle);
- if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
- return (PORT_BAD_HANDLE);
- }
- p_port = &rfc_cb.port.port[handle - 1];
- if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
- return (PORT_NOT_OPENED);
- }
- *p_errors = p_port->line_status;
- /* This is the only call to clear error status. We can not clear */
- /* connection failed status. To clean it port should be closed and reopened */
- p_port->line_status = (p_port->line_status & LINE_STATUS_FAILED);
- PORT_GetQueueStatus (handle, p_status);
- return (PORT_SUCCESS);
- }
- /*******************************************************************************
- **
- ** Function PORT_SendError
- **
- ** Description This function send a communications error to the peer device
- **
- ** Parameters: handle - Handle returned in the RFCOMM_CreateConnection
- ** errors - receive error codes
- **
- *******************************************************************************/
- int PORT_SendError (UINT16 handle, UINT8 errors)
- {
- tPORT *p_port;
- RFCOMM_TRACE_API ("PORT_SendError() handle:%d errors:0x%x", handle, errors);
- if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
- return (PORT_BAD_HANDLE);
- }
- p_port = &rfc_cb.port.port[handle - 1];
- if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
- return (PORT_NOT_OPENED);
- }
- if (!p_port->rfc.p_mcb) {
- return (PORT_NOT_OPENED);
- }
- RFCOMM_LineStatusReq (p_port->rfc.p_mcb, p_port->dlci, errors);
- return (PORT_SUCCESS);
- }
- /*******************************************************************************
- **
- ** Function PORT_GetQueueStatus
- **
- ** Description This function reports current status of a connection.
- **
- ** Parameters: handle - Handle returned in the RFCOMM_CreateConnection
- ** p_status - pointer to the tPORT_STATUS structur to receive
- ** connection status
- **
- *******************************************************************************/
- int PORT_GetQueueStatus (UINT16 handle, tPORT_STATUS *p_status)
- {
- tPORT *p_port;
- /* RFCOMM_TRACE_API ("PORT_GetQueueStatus() handle:%d", handle); */
- if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
- return (PORT_BAD_HANDLE);
- }
- p_port = &rfc_cb.port.port[handle - 1];
- if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
- return (PORT_NOT_OPENED);
- }
- p_status->in_queue_size = (UINT16) p_port->rx.queue_size;
- p_status->out_queue_size = (UINT16) p_port->tx.queue_size;
- p_status->mtu_size = (UINT16) p_port->peer_mtu;
- p_status->flags = 0;
- if (!(p_port->peer_ctrl.modem_signal & PORT_CTSRTS_ON)) {
- p_status->flags |= PORT_FLAG_CTS_HOLD;
- }
- if (!(p_port->peer_ctrl.modem_signal & PORT_DTRDSR_ON)) {
- p_status->flags |= PORT_FLAG_DSR_HOLD;
- }
- if (!(p_port->peer_ctrl.modem_signal & PORT_DCD_ON)) {
- p_status->flags |= PORT_FLAG_RLSD_HOLD;
- }
- return (PORT_SUCCESS);
- }
- /*******************************************************************************
- **
- ** Function PORT_Purge
- **
- ** Description This function discards all the data from the output or
- ** input queues of the specified connection.
- **
- ** Parameters: handle - Handle returned in the RFCOMM_CreateConnection
- ** purge_flags - specify the action to take.
- **
- *******************************************************************************/
- int PORT_Purge (UINT16 handle, UINT8 purge_flags)
- {
- tPORT *p_port;
- BT_HDR *p_buf;
- UINT16 count;
- UINT32 events;
- RFCOMM_TRACE_API ("PORT_Purge() handle:%d flags:0x%x", handle, purge_flags);
- /* Check if handle is valid to avoid crashing */
- if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
- return (PORT_BAD_HANDLE);
- }
- p_port = &rfc_cb.port.port[handle - 1];
- if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
- return (PORT_NOT_OPENED);
- }
- if (purge_flags & PORT_PURGE_RXCLEAR) {
- osi_mutex_global_lock(); /* to prevent missing credit */
- count = fixed_queue_length(p_port->rx.queue);
- while ((p_buf = (BT_HDR *)fixed_queue_dequeue(p_port->rx.queue, 0)) != NULL) {
- osi_free (p_buf);
- }
- p_port->rx.queue_size = 0;
- osi_mutex_global_unlock();
- /* If we flowed controlled peer based on rx_queue size enable data again */
- if (count) {
- port_flow_control_peer (p_port, TRUE, count);
- }
- }
- if (purge_flags & PORT_PURGE_TXCLEAR) {
- osi_mutex_global_lock(); /* to prevent tx.queue_size from being negative */
- while ((p_buf = (BT_HDR *)fixed_queue_dequeue(p_port->tx.queue, 0)) != NULL) {
- osi_free (p_buf);
- }
- p_port->tx.queue_size = 0;
- osi_mutex_global_unlock();
- events = PORT_EV_TXEMPTY;
- events |= port_flow_control_user (p_port);
- events &= p_port->ev_mask;
- if ((p_port->p_callback != NULL) && events) {
- (p_port->p_callback)(events, p_port->inx);
- }
- }
- return (PORT_SUCCESS);
- }
- /*******************************************************************************
- **
- ** Function PORT_ReadData
- **
- ** Description Normally not GKI aware application will call this function
- ** after receiving PORT_EV_RXCHAR event.
- **
- ** Parameters: handle - Handle returned in the RFCOMM_CreateConnection
- ** p_data - Data area
- ** max_len - Byte count requested
- ** p_len - Byte count received
- **
- *******************************************************************************/
- int PORT_ReadData (UINT16 handle, char *p_data, UINT16 max_len, UINT16 *p_len)
- {
- tPORT *p_port;
- BT_HDR *p_buf;
- UINT16 count;
- RFCOMM_TRACE_API ("PORT_ReadData() handle:%d max_len:%d", handle, max_len);
- /* Initialize this in case of an error */
- *p_len = 0;
- /* Check if handle is valid to avoid crashing */
- if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
- return (PORT_BAD_HANDLE);
- }
- p_port = &rfc_cb.port.port[handle - 1];
- if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
- return (PORT_NOT_OPENED);
- }
- if (p_port->line_status) {
- return (PORT_LINE_ERR);
- }
- if (fixed_queue_is_empty(p_port->rx.queue)){
- return (PORT_SUCCESS);
- }
- count = 0;
- while (max_len)
- {
- p_buf = (BT_HDR *)fixed_queue_try_peek_first(p_port->rx.queue);
- if (p_buf == NULL){
- break;
- }
- if (p_buf->len > max_len) {
- memcpy (p_data, (UINT8 *)(p_buf + 1) + p_buf->offset, max_len);
- p_buf->offset += max_len;
- p_buf->len -= max_len;
- *p_len += max_len;
- osi_mutex_global_lock();
- p_port->rx.queue_size -= max_len;
- osi_mutex_global_unlock();
- break;
- } else {
- memcpy (p_data, (UINT8 *)(p_buf + 1) + p_buf->offset, p_buf->len);
- *p_len += p_buf->len;
- max_len -= p_buf->len;
- osi_mutex_global_lock();
- p_port->rx.queue_size -= p_buf->len;
- if (max_len) {
- p_data += p_buf->len;
- }
- osi_free(fixed_queue_dequeue(p_port->rx.queue, 0));
- osi_mutex_global_unlock();
- count++;
- }
- }
- if (*p_len == 1) {
- RFCOMM_TRACE_EVENT ("PORT_ReadData queue:%d returned:%d %x", p_port->rx.queue_size, *p_len, (p_data[0]));
- } else {
- RFCOMM_TRACE_EVENT ("PORT_ReadData queue:%d returned:%d", p_port->rx.queue_size, *p_len);
- }
- /* If rfcomm suspended traffic from the peer based on the rx_queue_size */
- /* check if it can be resumed now */
- port_flow_control_peer (p_port, TRUE, count);
- return (PORT_SUCCESS);
- }
- /*******************************************************************************
- **
- ** Function PORT_Read
- **
- ** Description Normally application will call this function after receiving
- ** PORT_EV_RXCHAR event.
- **
- ** Parameters: handle - Handle returned in the RFCOMM_CreateConnection
- ** pp_buf - pointer to address of buffer with data,
- **
- *******************************************************************************/
- int PORT_Read (UINT16 handle, BT_HDR **pp_buf)
- {
- tPORT *p_port;
- BT_HDR *p_buf;
- RFCOMM_TRACE_API ("PORT_Read() handle:%d", handle);
- /* Check if handle is valid to avoid crashing */
- if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
- return (PORT_BAD_HANDLE);
- }
- p_port = &rfc_cb.port.port[handle - 1];
- if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
- return (PORT_NOT_OPENED);
- }
- if (p_port->line_status) {
- return (PORT_LINE_ERR);
- }
- osi_mutex_global_lock();
- p_buf = (BT_HDR *)fixed_queue_dequeue(p_port->rx.queue, 0);
- if (p_buf) {
- p_port->rx.queue_size -= p_buf->len;
- osi_mutex_global_unlock();
- /* If rfcomm suspended traffic from the peer based on the rx_queue_size */
- /* check if it can be resumed now */
- port_flow_control_peer (p_port, TRUE, 1);
- } else {
- osi_mutex_global_unlock();
- }
- *pp_buf = p_buf;
- return (PORT_SUCCESS);
- }
- /*******************************************************************************
- **
- ** Function port_write
- **
- ** Description This function when a data packet is received from the apper
- ** layer task.
- **
- ** Parameters: p_port - pointer to address of port control block
- ** p_buf - pointer to address of buffer with data,
- **
- *******************************************************************************/
- static int port_write (tPORT *p_port, BT_HDR *p_buf)
- {
- /* We should not allow to write data in to server port when connection is not opened */
- if (p_port->is_server && (p_port->rfc.state != RFC_STATE_OPENED)) {
- osi_free (p_buf);
- return (PORT_CLOSED);
- }
- /* Keep the data in pending queue if peer does not allow data, or */
- /* Peer is not ready or Port is not yet opened or initial port control */
- /* command has not been sent */
- if (p_port->tx.peer_fc
- || !p_port->rfc.p_mcb
- || !p_port->rfc.p_mcb->peer_ready
- || (p_port->rfc.state != RFC_STATE_OPENED)
- || ((p_port->port_ctrl & (PORT_CTRL_REQ_SENT | PORT_CTRL_IND_RECEIVED)) !=
- (PORT_CTRL_REQ_SENT | PORT_CTRL_IND_RECEIVED))) {
- if ((p_port->tx.queue_size > PORT_TX_CRITICAL_WM)
- || (fixed_queue_length(p_port->tx.queue) > PORT_TX_BUF_CRITICAL_WM)){
- RFCOMM_TRACE_WARNING ("PORT_Write: Queue size: %d",
- p_port->tx.queue_size);
- osi_free (p_buf);
- if ((p_port->p_callback != NULL) && (p_port->ev_mask & PORT_EV_ERR)) {
- p_port->p_callback (PORT_EV_ERR, p_port->inx);
- }
- return (PORT_TX_FULL);
- }
- RFCOMM_TRACE_EVENT ("PORT_Write : Data is enqued. flow disabled %d peer_ready %d state %d ctrl_state %x",
- p_port->tx.peer_fc,
- (p_port->rfc.p_mcb && p_port->rfc.p_mcb->peer_ready),
- p_port->rfc.state,
- p_port->port_ctrl);
- fixed_queue_enqueue(p_port->tx.queue, p_buf, FIXED_QUEUE_MAX_TIMEOUT);
- p_port->tx.queue_size += p_buf->len;
- return (PORT_CMD_PENDING);
- } else {
- RFCOMM_TRACE_EVENT ("PORT_Write : Data is being sent");
- RFCOMM_DataReq (p_port->rfc.p_mcb, p_port->dlci, p_buf);
- return (PORT_SUCCESS);
- }
- }
- /*******************************************************************************
- **
- ** Function PORT_Write
- **
- ** Description This function when a data packet is received from the apper
- ** layer task.
- **
- ** Parameters: handle - Handle returned in the RFCOMM_CreateConnection
- ** pp_buf - pointer to address of buffer with data,
- **
- *******************************************************************************/
- int PORT_Write (UINT16 handle, BT_HDR *p_buf)
- {
- tPORT *p_port;
- UINT32 event = 0;
- int rc;
- RFCOMM_TRACE_API ("PORT_Write() handle:%d", handle);
- /* Check if handle is valid to avoid crashing */
- if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
- osi_free (p_buf);
- return (PORT_BAD_HANDLE);
- }
- p_port = &rfc_cb.port.port[handle - 1];
- if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
- osi_free (p_buf);
- return (PORT_NOT_OPENED);
- }
- if (p_port->line_status) {
- RFCOMM_TRACE_WARNING ("PORT_Write: Data dropped line_status:0x%x",
- p_port->line_status);
- osi_free (p_buf);
- return (PORT_LINE_ERR);
- }
- rc = port_write (p_port, p_buf);
- event |= port_flow_control_user (p_port);
- switch (rc) {
- case PORT_TX_FULL:
- event |= PORT_EV_ERR;
- break;
- case PORT_SUCCESS:
- event |= (PORT_EV_TXCHAR | PORT_EV_TXEMPTY);
- break;
- }
- /* Mask out all events that are not of interest to user */
- event &= p_port->ev_mask;
- /* Send event to the application */
- if (p_port->p_callback && event) {
- (p_port->p_callback)(event, p_port->inx);
- }
- return (PORT_SUCCESS);
- }
- /*******************************************************************************
- **
- ** Function PORT_WriteDataCO
- **
- ** Description Normally not GKI aware application will call this function
- ** to send data to the port by callout functions
- **
- ** Parameters: handle - Handle returned in the RFCOMM_CreateConnection
- ** fd - socket fd
- ** p_len - Byte count returned
- **
- *******************************************************************************/
- int PORT_WriteDataCO (UINT16 handle, int *p_len, int len, UINT8 *p_data)
- {
- tPORT *p_port;
- BT_HDR *p_buf;
- UINT32 event = 0;
- int rc = 0;
- UINT16 length;
- RFCOMM_TRACE_API ("PORT_WriteDataCO() handle:%d", handle);
- *p_len = 0;
- /* Check if handle is valid to avoid crashing */
- if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
- return (PORT_BAD_HANDLE);
- }
- p_port = &rfc_cb.port.port[handle - 1];
- if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
- RFCOMM_TRACE_WARNING ("PORT_WriteDataByFd() no port state:%d", p_port->state);
- return (PORT_NOT_OPENED);
- }
- if (!p_port->peer_mtu) {
- RFCOMM_TRACE_ERROR ("PORT_WriteDataByFd() peer_mtu:%d", p_port->peer_mtu);
- return (PORT_UNKNOWN_ERROR);
- }
- int available = 0;
- available = len;
- if (available == 0) {
- return PORT_SUCCESS;
- }
- /* Length for each buffer is the smaller of GKI buffer, peer MTU, or max_len */
- length = RFCOMM_DATA_BUF_SIZE -
- (UINT16)(sizeof(BT_HDR) + L2CAP_MIN_OFFSET + RFCOMM_DATA_OVERHEAD);
- while (available) {
- /* if we're over buffer high water mark, we're done */
- if ((p_port->tx.queue_size > PORT_TX_HIGH_WM)
- || (fixed_queue_length(p_port->tx.queue) > PORT_TX_BUF_HIGH_WM)) {
- port_flow_control_user(p_port);
- event |= PORT_EV_FC;
- RFCOMM_TRACE_EVENT ("tx queue is full,tx.queue_size:%d,tx.queue.count:%d,available:%d",
- p_port->tx.queue_size, fixed_queue_length(p_port->tx.queue), available);
- break;
- }
- /* continue with rfcomm data write */
- if (p_port->peer_mtu < length) {
- length = p_port->peer_mtu;
- }
- if (available < (int)length) {
- length = (UINT16)available;
- }
- UINT16 alloc_size = (UINT16)(sizeof(BT_HDR) + L2CAP_MIN_OFFSET + RFCOMM_DATA_OVERHEAD
- + length + L2CAP_FCS_LEN);
- p_buf = (BT_HDR *)osi_malloc(alloc_size);
- if (!p_buf) {
- RFCOMM_TRACE_EVENT ("PORT_WriteDataCO: out of heap.");
- break;
- }
- p_buf->offset = L2CAP_MIN_OFFSET + RFCOMM_MIN_OFFSET;
- p_buf->layer_specific = handle;
- p_buf->len = length;
- p_buf->event = BT_EVT_TO_BTU_SP_DATA;
- memcpy ((UINT8 *)(p_buf + 1) + p_buf->offset, p_data, length);
- RFCOMM_TRACE_EVENT ("PORT_WriteData %d bytes", length);
- rc = port_write (p_port, p_buf);
- /* If queue went below the threshold need to send flow control */
- event |= port_flow_control_user (p_port);
- if (rc == PORT_SUCCESS) {
- event |= PORT_EV_TXCHAR;
- }
- if ((rc != PORT_SUCCESS) && (rc != PORT_CMD_PENDING)) {
- break;
- }
- *p_len += length;
- available -= (int)length;
- p_data += length;
- }
- if (!available && (rc != PORT_CMD_PENDING) && (rc != PORT_TX_QUEUE_DISABLED)) {
- event |= PORT_EV_TXEMPTY;
- }
- /* Mask out all events that are not of interest to user */
- event &= p_port->ev_mask;
- /* Send event to the application */
- if (p_port->p_callback && event) {
- (p_port->p_callback)(event, p_port->inx);
- }
- return (PORT_SUCCESS);
- }
- /*******************************************************************************
- **
- ** Function PORT_WriteData
- **
- ** Description Normally not GKI aware application will call this function
- ** to send data to the port.
- **
- ** Parameters: handle - Handle returned in the RFCOMM_CreateConnection
- ** p_data - Data area
- ** max_len - Byte count requested
- ** p_len - Byte count received
- **
- *******************************************************************************/
- int PORT_WriteData (UINT16 handle, char *p_data, UINT16 max_len, UINT16 *p_len)
- {
- tPORT *p_port;
- BT_HDR *p_buf;
- UINT32 event = 0;
- int rc = 0;
- UINT16 length;
- RFCOMM_TRACE_API ("PORT_WriteData() max_len:%d", max_len);
- *p_len = 0;
- /* Check if handle is valid to avoid crashing */
- if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
- return (PORT_BAD_HANDLE);
- }
- p_port = &rfc_cb.port.port[handle - 1];
- if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
- RFCOMM_TRACE_WARNING ("PORT_WriteData() no port state:%d", p_port->state);
- return (PORT_NOT_OPENED);
- }
- if (!max_len || !p_port->peer_mtu) {
- RFCOMM_TRACE_ERROR ("PORT_WriteData() peer_mtu:%d", p_port->peer_mtu);
- return (PORT_UNKNOWN_ERROR);
- }
- /* Length for each buffer is the smaller of GKI buffer, peer MTU, or max_len */
- length = RFCOMM_DATA_BUF_SIZE -
- (UINT16)(sizeof(BT_HDR) + L2CAP_MIN_OFFSET + RFCOMM_DATA_OVERHEAD);
- /* If there are buffers scheduled for transmission check if requested */
- /* data fits into the end of the queue */
- osi_mutex_global_lock();
- if (((p_buf = (BT_HDR *)fixed_queue_try_peek_last(p_port->tx.queue)) != NULL)
- && ((p_buf->len + max_len) <= p_port->peer_mtu)
- && ((p_buf->len + max_len) <= length)) {
- memcpy ((UINT8 *)(p_buf + 1) + p_buf->offset + p_buf->len, p_data, max_len);
- p_port->tx.queue_size += max_len;
- *p_len = max_len;
- p_buf->len += max_len;
- osi_mutex_global_unlock();
- return (PORT_SUCCESS);
- }
- osi_mutex_global_unlock();
- while (max_len) {
- /* if we're over buffer high water mark, we're done */
- if ((p_port->tx.queue_size > PORT_TX_HIGH_WM)
- || (fixed_queue_length(p_port->tx.queue) > PORT_TX_BUF_HIGH_WM)) {
- break;
- }
- /* continue with rfcomm data write */
- p_buf = (BT_HDR *)osi_malloc(RFCOMM_DATA_BUF_SIZE);
- if (!p_buf) {
- break;
- }
- p_buf->offset = L2CAP_MIN_OFFSET + RFCOMM_MIN_OFFSET;
- p_buf->layer_specific = handle;
- if (p_port->peer_mtu < length) {
- length = p_port->peer_mtu;
- }
- if (max_len < length) {
- length = max_len;
- }
- p_buf->len = length;
- p_buf->event = BT_EVT_TO_BTU_SP_DATA;
- memcpy ((UINT8 *)(p_buf + 1) + p_buf->offset, p_data, length);
- RFCOMM_TRACE_EVENT ("PORT_WriteData %d bytes", length);
- rc = port_write (p_port, p_buf);
- /* If queue went below the threashold need to send flow control */
- event |= port_flow_control_user (p_port);
- if (rc == PORT_SUCCESS) {
- event |= PORT_EV_TXCHAR;
- }
- if ((rc != PORT_SUCCESS) && (rc != PORT_CMD_PENDING)) {
- break;
- }
- *p_len += length;
- max_len -= length;
- p_data += length;
- }
- if (!max_len && (rc != PORT_CMD_PENDING) && (rc != PORT_TX_QUEUE_DISABLED)) {
- event |= PORT_EV_TXEMPTY;
- }
- /* Mask out all events that are not of interest to user */
- event &= p_port->ev_mask;
- /* Send event to the application */
- if (p_port->p_callback && event) {
- (p_port->p_callback)(event, p_port->inx);
- }
- return (PORT_SUCCESS);
- }
- /*******************************************************************************
- **
- ** Function PORT_Test
- **
- ** Description Application can call this function to send RFCOMM Test frame
- **
- ** Parameters: handle - Handle returned in the RFCOMM_CreateConnection
- ** p_data - Data area
- ** max_len - Byte count requested
- **
- *******************************************************************************/
- int PORT_Test (UINT16 handle, UINT8 *p_data, UINT16 len)
- {
- BT_HDR *p_buf;
- tPORT *p_port;
- RFCOMM_TRACE_API ("PORT_Test() len:%d", len);
- if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
- return (PORT_BAD_HANDLE);
- }
- p_port = &rfc_cb.port.port[handle - 1];
- if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
- return (PORT_NOT_OPENED);
- }
- if (len > ((p_port->mtu == 0) ? RFCOMM_DEFAULT_MTU : p_port->mtu)) {
- return (PORT_UNKNOWN_ERROR);
- }
- if ((p_buf = (BT_HDR *)osi_malloc(RFCOMM_CMD_BUF_SIZE)) != NULL) {
- p_buf->offset = L2CAP_MIN_OFFSET + RFCOMM_MIN_OFFSET + 2;
- p_buf->len = len;
- memcpy ((UINT8 *)(p_buf + 1) + p_buf->offset, p_data, p_buf->len);
- rfc_send_test (p_port->rfc.p_mcb, TRUE, p_buf);
- return (PORT_SUCCESS);
- } else {
- return (PORT_NO_MEM);
- }
- }
- /*******************************************************************************
- **
- ** Function RFCOMM_Init
- **
- ** Description This function is called to initialize RFCOMM layer
- **
- ** Returns status
- **
- *******************************************************************************/
- bt_status_t RFCOMM_Init (void)
- {
- #if RFC_DYNAMIC_MEMORY == TRUE
- rfc_cb_ptr = (tRFC_CB *)osi_malloc(sizeof(tRFC_CB));
- if (rfc_cb_ptr == NULL) {
- return BT_STATUS_NOMEM;
- }
- #endif /* #if (RFC_DYNAMIC_MEMORY) */
- memset (&rfc_cb, 0, sizeof (tRFC_CB)); /* Init RFCOMM control block */
- rfc_cb.rfc.last_mux = MAX_BD_CONNECTIONS;
- #if defined(RFCOMM_INITIAL_TRACE_LEVEL)
- rfc_cb.trace_level = RFCOMM_INITIAL_TRACE_LEVEL;
- #else
- rfc_cb.trace_level = BT_TRACE_LEVEL_NONE; /* No traces */
- #endif
- rfcomm_l2cap_if_init ();
- return BT_STATUS_SUCCESS;
- }
- /*******************************************************************************
- **
- ** Function RFCOMM_Deinit
- **
- ** Description This function is called to deinitialize the control block
- ** for this layer.
- **
- ** Returns void
- **
- *******************************************************************************/
- void RFCOMM_Deinit(void)
- {
- #if RFC_DYNAMIC_MEMORY == TRUE
- if (rfc_cb_ptr){
- osi_free(rfc_cb_ptr);
- rfc_cb_ptr = NULL;
- }
- #endif
- }
- /*******************************************************************************
- **
- ** Function PORT_SetTraceLevel
- **
- ** Description This function sets the trace level for RFCOMM. If called with
- ** a value of 0xFF, it simply reads the current trace level.
- **
- ** Returns the new (current) trace level
- **
- *******************************************************************************/
- UINT8 PORT_SetTraceLevel (UINT8 new_level)
- {
- if (new_level != 0xFF) {
- rfc_cb.trace_level = new_level;
- }
- return (rfc_cb.trace_level);
- }
- /*******************************************************************************
- **
- ** Function PORT_GetResultString
- **
- ** Description This function returns the human-readable string for a given
- ** result code.
- **
- ** Returns a pointer to the human-readable string for the given result.
- **
- *******************************************************************************/
- const char *PORT_GetResultString (const uint8_t result_code)
- {
- if (result_code > PORT_ERR_MAX) {
- return result_code_strings[PORT_ERR_MAX];
- }
- return result_code_strings[result_code];
- }
- #endif ///(defined RFCOMM_INCLUDED && RFCOMM_INCLUDED == TRUE)
|