| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907 |
- /******************************************************************************
- *
- * Copyright (C) 2000-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 functions that handle SCO connections. This includes
- * operations such as connect, disconnect, change supported packet types.
- *
- ******************************************************************************/
- #include <string.h>
- #include "stack/bt_types.h"
- #include "common/bt_target.h"
- #include "stack/bt_types.h"
- #include "stack/hcimsgs.h"
- #include "stack/btu.h"
- #include "stack/btm_api.h"
- #include "osi/allocator.h"
- #include "btm_int.h"
- #include "stack/hcidefs.h"
- //#include "bt_utils.h"
- #if BTM_SCO_INCLUDED == TRUE
- /********************************************************************************/
- /* L O C A L D A T A D E F I N I T I O N S */
- /********************************************************************************/
- #define SCO_ST_UNUSED 0
- #define SCO_ST_LISTENING 1
- #define SCO_ST_W4_CONN_RSP 2
- #define SCO_ST_CONNECTING 3
- #define SCO_ST_CONNECTED 4
- #define SCO_ST_DISCONNECTING 5
- #define SCO_ST_PEND_UNPARK 6
- #define SCO_ST_PEND_ROLECHANGE 7
- /********************************************************************************/
- /* L O C A L F U N C T I O N P R O T O T Y P E S */
- /********************************************************************************/
- static const tBTM_ESCO_PARAMS btm_esco_defaults = {
- BTM_64KBITS_RATE, /* TX Bandwidth (64 kbits/sec) */
- BTM_64KBITS_RATE, /* RX Bandwidth (64 kbits/sec) */
- 0x000a, /* 10 ms (HS/HF can use EV3, 2-EV3, 3-EV3) */
- 0x0060, /* Inp Linear, Air CVSD, 2s Comp, 16bit */
- (BTM_SCO_PKT_TYPES_MASK_HV1 + /* Packet Types */
- BTM_SCO_PKT_TYPES_MASK_HV2 +
- BTM_SCO_PKT_TYPES_MASK_HV3 +
- BTM_SCO_PKT_TYPES_MASK_EV3 +
- BTM_SCO_PKT_TYPES_MASK_EV4 +
- BTM_SCO_PKT_TYPES_MASK_EV5),
- BTM_ESCO_RETRANS_POWER /* Retransmission Effort (Power) */
- };
- /*******************************************************************************
- **
- ** Function btm_sco_flush_sco_data
- **
- ** Description This function is called to flush the SCO data for this channel.
- **
- ** Returns void
- **
- *******************************************************************************/
- void btm_sco_flush_sco_data(UINT16 sco_inx)
- {
- #if BTM_SCO_HCI_INCLUDED == TRUE
- #if (BTM_MAX_SCO_LINKS>0)
- tSCO_CONN *p ;
- BT_HDR *p_buf;
- if (sco_inx < BTM_MAX_SCO_LINKS) {
- p = &btm_cb.sco_cb.sco_db[sco_inx];
- while ((p_buf = (BT_HDR *)fixed_queue_dequeue(p->xmit_data_q, 0)) != NULL) {
- osi_free(p_buf);
- }
- }
- #else
- UNUSED(sco_inx);
- #endif
- #else
- UNUSED(sco_inx);
- #endif
- }
- /*******************************************************************************
- **
- ** Function btm_sco_init
- **
- ** Description This function is called at BTM startup to initialize
- **
- ** Returns void
- **
- *******************************************************************************/
- void btm_sco_init (void)
- {
- #if 0 /* cleared in btm_init; put back in if called from anywhere else! */
- memset (&btm_cb.sco_cb, 0, sizeof(tSCO_CB));
- #endif
- #if (BTM_SCO_HCI_INCLUDED == TRUE)
- for (int i = 0; i < BTM_MAX_SCO_LINKS; i++) {
- btm_cb.sco_cb.sco_db[i].xmit_data_q = fixed_queue_new(QUEUE_SIZE_MAX);
- }
- #endif
- /* Initialize nonzero defaults */
- btm_cb.sco_cb.sco_disc_reason = BTM_INVALID_SCO_DISC_REASON;
- btm_cb.sco_cb.def_esco_parms = btm_esco_defaults; /* Initialize with defaults */
- btm_cb.sco_cb.desired_sco_mode = BTM_DEFAULT_SCO_MODE;
- }
- /*******************************************************************************
- **
- ** Function btm_esco_conn_rsp
- **
- ** Description This function is called upon receipt of an (e)SCO connection
- ** request event (BTM_ESCO_CONN_REQ_EVT) to accept or reject
- ** the request. Parameters used to negotiate eSCO links.
- ** If p_parms is NULL, then default values are used.
- ** If the link type of the incoming request is SCO, then only
- ** the tx_bw, max_latency, content format, and packet_types are
- ** valid. The hci_status parameter should be
- ** ([0x0] to accept, [0x0d..0x0f] to reject)
- **
- ** Returns void
- **
- *******************************************************************************/
- static void btm_esco_conn_rsp (UINT16 sco_inx, UINT8 hci_status, BD_ADDR bda,
- tBTM_ESCO_PARAMS *p_parms)
- {
- #if (BTM_MAX_SCO_LINKS>0)
- tSCO_CONN *p_sco = NULL;
- tBTM_ESCO_PARAMS *p_setup;
- UINT16 temp_pkt_types;
- if (sco_inx < BTM_MAX_SCO_LINKS) {
- p_sco = &btm_cb.sco_cb.sco_db[sco_inx];
- }
- /* Reject the connect request if refused by caller or wrong state */
- if (hci_status != HCI_SUCCESS || p_sco == NULL) {
- if (p_sco) {
- p_sco->state = (p_sco->state == SCO_ST_W4_CONN_RSP) ? SCO_ST_LISTENING
- : SCO_ST_UNUSED;
- }
- if (!btm_cb.sco_cb.esco_supported) {
- if (!btsnd_hcic_reject_conn (bda, hci_status)) {
- BTM_TRACE_ERROR("Could not reject (e)SCO conn: No Buffer!!!");
- }
- } else {
- if (!btsnd_hcic_reject_esco_conn (bda, hci_status)) {
- BTM_TRACE_ERROR("Could not reject (e)SCO conn: No Buffer!!!");
- }
- }
- } else { /* Connection is being accepted */
- p_sco->state = SCO_ST_CONNECTING;
- p_setup = &p_sco->esco.setup;
- /* If parameters not specified use the default */
- if (p_parms) {
- *p_setup = *p_parms;
- } else { /* Use the last setup passed thru BTM_SetEscoMode (or defaults) */
- *p_setup = btm_cb.sco_cb.def_esco_parms;
- }
- temp_pkt_types = (p_setup->packet_types &
- BTM_SCO_SUPPORTED_PKTS_MASK &
- btm_cb.btm_sco_pkt_types_supported);
- /* Make sure at least one eSCO packet type is sent, else might confuse peer */
- /* Taking this out to confirm with BQB tests
- ** Real application would like to include this though, as many devices
- ** do not retry with SCO only if an eSCO connection fails.
- if (!(temp_pkt_types & BTM_ESCO_LINK_ONLY_MASK))
- {
- temp_pkt_types |= BTM_SCO_PKT_TYPES_MASK_EV3;
- }
- */
- /* If SCO request, remove eSCO packet types (conformance) */
- if (p_sco->esco.data.link_type == BTM_LINK_TYPE_SCO) {
- temp_pkt_types &= BTM_SCO_LINK_ONLY_MASK;
- temp_pkt_types |= BTM_SCO_EXCEPTION_PKTS_MASK;
- } else {
- /* OR in any exception packet types */
- temp_pkt_types |= ((p_setup->packet_types & BTM_SCO_EXCEPTION_PKTS_MASK) |
- (btm_cb.btm_sco_pkt_types_supported & BTM_SCO_EXCEPTION_PKTS_MASK));
- }
- if (btsnd_hcic_accept_esco_conn (bda, p_setup->tx_bw, p_setup->rx_bw,
- p_setup->max_latency, p_setup->voice_contfmt,
- p_setup->retrans_effort, temp_pkt_types)) {
- p_setup->packet_types = temp_pkt_types;
- } else {
- BTM_TRACE_ERROR("Could not accept SCO conn: No Buffer!!!");
- }
- }
- #endif
- }
- #if BTM_SCO_HCI_INCLUDED == TRUE
- void btm_sco_process_num_bufs (UINT16 num_lm_sco_bufs)
- {
- BTM_TRACE_DEBUG("%s, %d", __FUNCTION__, num_lm_sco_bufs);
- btm_cb.sco_cb.num_lm_sco_bufs = btm_cb.sco_cb.xmit_window_size = num_lm_sco_bufs;
- }
- /*******************************************************************************
- **
- ** Function BTM_ConfigScoPath
- **
- ** Description This function enable/disable SCO over HCI and registers SCO
- ** data callback if SCO over HCI is enabled.
- **
- ** Parameter path: SCO or HCI
- ** p_sco_data_cb: callback function or SCO data if path is set
- ** to transport.
- ** p_pcm_param: pointer to the PCM interface parameter. If a NULL
- ** pointer is used, PCM parameter maintained in
- ** the control block will be used; otherwise update
- ** control block value.
- ** err_data_rpt: Lisbon feature to enable the erronous data report
- ** or not.
- **
- ** Returns BTM_SUCCESS if the successful.
- ** BTM_NO_RESOURCES: no rsource to start the command.
- ** BTM_ILLEGAL_VALUE: invalid callback function pointer.
- ** BTM_CMD_STARTED :Command sent. Waiting for command cmpl event.
- **
- **
- *******************************************************************************/
- //extern
- tBTM_STATUS BTM_ConfigScoPath (tBTM_SCO_ROUTE_TYPE path,
- tBTM_SCO_DATA_CB *p_sco_data_cb,
- tBTM_SCO_PCM_PARAM *p_pcm_param,
- BOOLEAN err_data_rpt)
- {
- UNUSED(err_data_rpt);
- UNUSED(p_pcm_param);
- btm_cb.sco_cb.sco_path = path;
- if (path == BTM_SCO_ROUTE_PCM) {
- return BTM_SUCCESS;
- } else if (path == BTM_SCO_ROUTE_HCI) {
- if (p_sco_data_cb) {
- btm_cb.sco_cb.p_data_cb = p_sco_data_cb;
- }
- }
- return BTM_SUCCESS;
- }
- static void hci_sco_data_to_lower(BT_HDR *p_buf)
- {
- p_buf->event = BT_EVT_TO_LM_HCI_SCO;
- if (p_buf->offset == 0) {
- BTM_TRACE_ERROR("offset cannot be 0");
- osi_free(p_buf);
- }
- bte_main_hci_send(p_buf, (UINT16)(BT_EVT_TO_LM_HCI_SCO | LOCAL_BLE_CONTROLLER_ID));
- }
- /*******************************************************************************
- **
- ** Function btm_sco_check_send_pkts
- **
- ** Description This function is called to check if it can send packets
- ** to the Host Controller.
- **
- ** Returns void
- **
- *******************************************************************************/
- void btm_sco_check_send_pkts (UINT16 sco_inx)
- {
- tSCO_CB *p_cb = &btm_cb.sco_cb;
- tSCO_CONN *p_ccb = &p_cb->sco_db[sco_inx];
- /* If there is data to send, send it now */
- BT_HDR *p_buf;
- while (p_cb->xmit_window_size != 0)
- {
- if ((p_buf = (BT_HDR *)fixed_queue_dequeue(p_ccb->xmit_data_q, 0)) == NULL) {
- break;
- }
- #if BTM_SCO_HCI_DEBUG
- BTM_TRACE_DEBUG("btm: [%d] buf in xmit_data_q",
- fixed_queue_length(p_ccb->xmit_data_q) + 1);
- #endif
- /* Don't go negative */
- p_cb->xmit_window_size -= 1;
- p_ccb->sent_not_acked += 1;
- // HCI_SCO_DATA_TO_LOWER(p_buf);
- hci_sco_data_to_lower(p_buf);
- }
- }
- void btm_sco_process_num_completed_pkts (UINT8 *p)
- {
- UINT8 num_handles, xx;
- UINT16 handle;
- UINT16 num_sent;
- UINT16 sco_inx;
- tSCO_CB *p_cb = &btm_cb.sco_cb;
- tSCO_CONN * p_ccb;
- STREAM_TO_UINT8 (num_handles, p);
- for (xx = 0; xx < num_handles; xx++) {
- STREAM_TO_UINT16 (handle, p);
- STREAM_TO_UINT16 (num_sent, p);
- if ((sco_inx = btm_find_scb_by_handle(handle)) == BTM_MAX_SCO_LINKS) {
- continue;
- }
- BTM_TRACE_DEBUG("%s, %d, %u", __FUNCTION__, handle, p_cb->xmit_window_size); //debug
- p_ccb = &p_cb->sco_db[sco_inx];
- p_ccb->sent_not_acked -= num_sent;
- // don't go negative
- if (p_ccb->sent_not_acked < 0) {
- BTM_TRACE_WARNING("SCO: un-acked underf: %u", p_ccb->sent_not_acked);
- p_ccb->sent_not_acked = 0;
- }
- p_cb->xmit_window_size += num_sent;
- if (p_cb->xmit_window_size > p_cb->num_lm_sco_bufs) {
- BTM_TRACE_WARNING("SCO xwind: %d, max %d", p_cb->xmit_window_size, p_cb->num_lm_sco_bufs);
- p_cb->xmit_window_size = p_cb->num_lm_sco_bufs;
- }
- btm_sco_check_send_pkts (sco_inx);
- }
- return;
- }
- /*******************************************************************************
- **
- ** Function btm_pkt_stat_nums_update
- **
- ** Description Update the number of received SCO data packet status.
- **
- ** Returns void
- **
- *******************************************************************************/
- static void btm_pkt_stat_nums_update(uint16_t sco_inx, uint8_t pkt_status)
- {
- tSCO_CONN *p_ccb = &btm_cb.sco_cb.sco_db[sco_inx];
- p_ccb->pkt_stat_nums.rx_total++;
- if (pkt_status == BTM_SCO_DATA_CORRECT) {
- p_ccb->pkt_stat_nums.rx_correct++;
- } else if (pkt_status == BTM_SCO_DATA_PAR_ERR) {
- p_ccb->pkt_stat_nums.rx_err++;
- } else if (pkt_status == BTM_SCO_DATA_NONE) {
- p_ccb->pkt_stat_nums.rx_none++;
- } else {
- p_ccb->pkt_stat_nums.rx_lost++;
- }
- }
- /*******************************************************************************
- **
- ** Function btm_pkt_stat_send_nums_update
- **
- ** Description Update the number of send packet status.
- **
- ** Returns void
- **
- *******************************************************************************/
- static void btm_pkt_stat_send_nums_update(uint16_t sco_inx, uint8_t pkt_status)
- {
- tSCO_CONN *p_ccb = &btm_cb.sco_cb.sco_db[sco_inx];
- p_ccb->pkt_stat_nums.tx_total++;
- if (pkt_status != BTM_SUCCESS && pkt_status != BTM_NO_RESOURCES && pkt_status != BTM_SCO_BAD_LENGTH) {
- p_ccb->pkt_stat_nums.tx_discarded++;
- }
- }
- /*******************************************************************************
- **
- ** Function btm_pkt_stat_nums_reset
- **
- ** Description This function is called to reset the number of packet status struct
- **
- ** Returns void
- **
- *******************************************************************************/
- static void btm_pkt_stat_nums_reset(uint16_t sco_inx)
- {
- memset(&btm_cb.sco_cb.sco_db[sco_inx].pkt_stat_nums, 0, sizeof(tBTM_SCO_PKT_STAT_NUMS));
- }
- /*******************************************************************************
- **
- ** Function BTM_PktStatNumsGet
- **
- ** Description This function is called to get the number of packet status struct
- **
- ** Returns void
- **
- *******************************************************************************/
- void BTM_PktStatNumsGet(uint16_t sync_conn_handle, tBTM_SCO_PKT_STAT_NUMS *p_pkt_nums)
- {
- uint16_t sco_inx = btm_find_scb_by_handle(sync_conn_handle);
- if (sco_inx < BTM_MAX_SCO_LINKS) {
- memcpy(p_pkt_nums, &btm_cb.sco_cb.sco_db[sco_inx].pkt_stat_nums, sizeof(tBTM_SCO_PKT_STAT_NUMS));
- } else {
- memset(p_pkt_nums, 0, sizeof(tBTM_SCO_PKT_STAT_NUMS));
- }
- }
- #endif /* BTM_SCO_HCI_INCLUDED == TRUE */
- /*******************************************************************************
- **
- ** Function btm_route_sco_data
- **
- ** Description Route received SCO data.
- **
- ** Returns void
- **
- *******************************************************************************/
- void btm_route_sco_data(BT_HDR *p_msg)
- {
- #if BTM_SCO_HCI_INCLUDED == TRUE
- UINT16 sco_inx, handle;
- UINT8 *p = (UINT8 *)(p_msg + 1) + p_msg->offset;
- UINT8 pkt_size = 0;
- UINT8 pkt_status = 0;
- /* Extract Packet_Status_Flag and handle */
- STREAM_TO_UINT16 (handle, p);
- pkt_status = HCID_GET_EVENT(handle);
- handle = HCID_GET_HANDLE (handle);
- STREAM_TO_UINT8 (pkt_size, p);
- UNUSED(pkt_size);
- if ((sco_inx = btm_find_scb_by_handle(handle)) != BTM_MAX_SCO_LINKS ) {
- /* send data callback */
- if (!btm_cb.sco_cb.p_data_cb )
- /* if no data callback registered, just free the buffer */
- {
- osi_free (p_msg);
- } else {
- btm_pkt_stat_nums_update(sco_inx, pkt_status);
- (*btm_cb.sco_cb.p_data_cb)(sco_inx, p_msg, (tBTM_SCO_DATA_FLAG) pkt_status);
- }
- } else { /* no mapping handle SCO connection is active, free the buffer */
- osi_free (p_msg);
- }
- BTM_TRACE_DEBUG ("SCO: hdl %x, len %d, pkt_sz %d\n", handle, p_msg->len, pkt_size);
- #else
- osi_free(p_msg);
- #endif
- }
- /*******************************************************************************
- **
- ** Function BTM_WriteScoData
- **
- ** Description This function write SCO data to a specified instance. The data
- ** to be written p_buf needs to carry an offset of
- ** HCI_SCO_PREAMBLE_SIZE bytes, and the data length can not
- ** exceed BTM_SCO_DATA_SIZE_MAX bytes, whose default value is set
- ** to 60 and is configurable. Data longer than the maximum bytes
- ** will be truncated.
- **
- ** Returns BTM_SUCCESS: data write is successful
- ** BTM_ILLEGAL_VALUE: SCO data contains illegal offset value.
- ** BTM_SCO_BAD_LENGTH: SCO data length exceeds the max SCO packet
- ** size.
- ** BTM_NO_RESOURCES: no resources.
- ** BTM_UNKNOWN_ADDR: unknown SCO connection handle, or SCO is not
- ** routed via HCI.
- ** BTM_ERR_PROCESSING: transmit queue overflow
- **
- **
- *******************************************************************************/
- tBTM_STATUS BTM_WriteScoData (UINT16 sco_inx, BT_HDR *p_buf)
- {
- APPL_TRACE_DEBUG("%s", __FUNCTION__);
- #if (BTM_SCO_HCI_INCLUDED == TRUE) && (BTM_MAX_SCO_LINKS>0)
- tSCO_CONN *p_ccb = &btm_cb.sco_cb.sco_db[sco_inx];
- UINT8 *p;
- tBTM_STATUS status = BTM_SUCCESS;
- if (sco_inx < BTM_MAX_SCO_LINKS && btm_cb.sco_cb.p_data_cb &&
- p_ccb->state == SCO_ST_CONNECTED) {
- /* Ensure we have enough space in the buffer for the SCO and HCI headers */
- if (p_buf->offset < HCI_SCO_PREAMBLE_SIZE) {
- BTM_TRACE_ERROR ("BTM SCO - cannot send buffer, offset: %d", p_buf->offset);
- status = BTM_ILLEGAL_VALUE;
- } else { /* write HCI header */
- /* Step back 3 bytes to add the headers */
- p_buf->offset -= HCI_SCO_PREAMBLE_SIZE;
- /* Set the pointer to the beginning of the data */
- p = (UINT8 *)(p_buf + 1) + p_buf->offset;
- /* add HCI handle */
- UINT16_TO_STREAM (p, p_ccb->hci_handle);
- /* only sent the first BTM_SCO_DATA_SIZE_MAX bytes data if more than max,
- and set warning status */
- if (p_buf->len > BTM_SCO_DATA_SIZE_MAX) {
- BTM_TRACE_WARNING ("BTM SCO hdl %x, bad len %u", p_ccb->hci_handle, p_buf->len);
- p_buf->len = BTM_SCO_DATA_SIZE_MAX;
- status = BTM_SCO_BAD_LENGTH;
- }
- UINT8_TO_STREAM (p, (UINT8)p_buf->len);
- p_buf->len += HCI_SCO_PREAMBLE_SIZE;
- if (fixed_queue_length(p_ccb->xmit_data_q) < BTM_SCO_XMIT_QUEUE_THRS) {
- if (fixed_queue_length(p_ccb->xmit_data_q) >= BTM_SCO_XMIT_QUEUE_HIGH_WM) {
- status = BTM_NO_RESOURCES;
- }
- fixed_queue_enqueue(p_ccb->xmit_data_q, p_buf, FIXED_QUEUE_MAX_TIMEOUT);
- btm_sco_check_send_pkts (sco_inx);
- } else {
- BTM_TRACE_WARNING ("SCO xmit Q overflow, pkt dropped");
- status = BTM_ERR_PROCESSING;
- }
- }
- } else {
- BTM_TRACE_WARNING ("BTM_WriteScoData, invalid sco index: %d at state [%d]",
- sco_inx, btm_cb.sco_cb.sco_db[sco_inx].state);
- status = BTM_UNKNOWN_ADDR;
- }
- if (status != BTM_SUCCESS && status!= BTM_NO_RESOURCES && status != BTM_SCO_BAD_LENGTH) {
- BTM_TRACE_WARNING ("stat %d", status);
- osi_free(p_buf);
- }
- btm_pkt_stat_send_nums_update(sco_inx, status);
- return (status);
- #else
- UNUSED(sco_inx);
- UNUSED(p_buf);
- return (BTM_NO_RESOURCES);
- #endif
- }
- #if (BTM_MAX_SCO_LINKS>0)
- /*******************************************************************************
- **
- ** Function btm_send_connect_request
- **
- ** Description This function is called to respond to SCO connect indications
- **
- ** Returns void
- **
- *******************************************************************************/
- static tBTM_STATUS btm_send_connect_request(UINT16 acl_handle,
- tBTM_ESCO_PARAMS *p_setup)
- {
- UINT16 temp_pkt_types;
- tACL_CONN *p_acl;
- /* Send connect request depending on version of spec */
- if (!btm_cb.sco_cb.esco_supported) {
- if (!btsnd_hcic_add_SCO_conn (acl_handle, BTM_ESCO_2_SCO(p_setup->packet_types))) {
- return (BTM_NO_RESOURCES);
- }
- } else {
- temp_pkt_types = (p_setup->packet_types & BTM_SCO_SUPPORTED_PKTS_MASK &
- btm_cb.btm_sco_pkt_types_supported);
- /* OR in any exception packet types */
- temp_pkt_types |= ((p_setup->packet_types & BTM_SCO_EXCEPTION_PKTS_MASK) |
- (btm_cb.btm_sco_pkt_types_supported & BTM_SCO_EXCEPTION_PKTS_MASK));
- /* Finally, remove EDR eSCO if the remote device doesn't support it */
- /* UPF25: Only SCO was brought up in this case */
- p_acl = btm_handle_to_acl(acl_handle);
- if (p_acl) {
- if (!HCI_EDR_ESCO_2MPS_SUPPORTED(p_acl->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0])) {
- BTM_TRACE_WARNING("BTM Remote does not support 2-EDR eSCO");
- temp_pkt_types |= (HCI_ESCO_PKT_TYPES_MASK_NO_2_EV3 |
- HCI_ESCO_PKT_TYPES_MASK_NO_2_EV5);
- }
- if (!HCI_EDR_ESCO_3MPS_SUPPORTED(p_acl->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0])) {
- BTM_TRACE_WARNING("BTM Remote does not support 3-EDR eSCO");
- temp_pkt_types |= (HCI_ESCO_PKT_TYPES_MASK_NO_3_EV3 |
- HCI_ESCO_PKT_TYPES_MASK_NO_3_EV5);
- }
- /* Check to see if BR/EDR Secure Connections is being used
- ** If so, we cannot use SCO-only packet types (HFP 1.7)
- */
- if (BTM_BothEndsSupportSecureConnections(p_acl->remote_addr)) {
- temp_pkt_types &= ~(BTM_SCO_PKT_TYPE_MASK);
- BTM_TRACE_DEBUG("%s: SCO Conn: pkt_types after removing SCO (0x%04x)", __FUNCTION__,
- temp_pkt_types);
- /* Return error if no packet types left */
- if (temp_pkt_types == 0) {
- BTM_TRACE_ERROR("%s: SCO Conn (BR/EDR SC): No packet types available",__FUNCTION__);
- return (BTM_WRONG_MODE);
- }
- } else {
- BTM_TRACE_DEBUG("%s: SCO Conn(BR/EDR SC):local or peer does not support BR/EDR SC",__FUNCTION__);
- }
- }
- BTM_TRACE_API("txbw 0x%x, rxbw 0x%x, lat 0x%x, voice 0x%x, retrans 0x%02x, pkt 0x%04x",
- p_setup->tx_bw, p_setup->rx_bw,
- p_setup->max_latency, p_setup->voice_contfmt,
- p_setup->retrans_effort, temp_pkt_types);
- if (!btsnd_hcic_setup_esco_conn(acl_handle,
- p_setup->tx_bw,
- p_setup->rx_bw,
- p_setup->max_latency,
- p_setup->voice_contfmt,
- p_setup->retrans_effort,
- temp_pkt_types)) {
- return (BTM_NO_RESOURCES);
- } else {
- p_setup->packet_types = temp_pkt_types;
- }
- }
- return (BTM_CMD_STARTED);
- }
- #endif
- /*******************************************************************************
- **
- ** Function btm_set_sco_ind_cback
- **
- ** Description This function is called to register for TCS SCO connect
- ** indications.
- **
- ** Returns void
- **
- *******************************************************************************/
- void btm_set_sco_ind_cback( tBTM_SCO_IND_CBACK *sco_ind_cb )
- {
- btm_cb.sco_cb.app_sco_ind_cb = sco_ind_cb;
- }
- /*******************************************************************************
- **
- ** Function btm_accept_sco_link
- **
- ** Description This function is called to respond to TCS SCO connect
- ** indications
- **
- ** Returns void
- **
- *******************************************************************************/
- void btm_accept_sco_link(UINT16 sco_inx, tBTM_ESCO_PARAMS *p_setup,
- tBTM_SCO_CB *p_conn_cb, tBTM_SCO_CB *p_disc_cb)
- {
- #if (BTM_MAX_SCO_LINKS>0)
- tSCO_CONN *p_sco;
- if (sco_inx >= BTM_MAX_SCO_LINKS) {
- BTM_TRACE_ERROR("btm_accept_sco_link: Invalid sco_inx(%d)", sco_inx);
- return;
- }
- /* Link role is ignored in for this message */
- p_sco = &btm_cb.sco_cb.sco_db[sco_inx];
- p_sco->p_conn_cb = p_conn_cb;
- p_sco->p_disc_cb = p_disc_cb;
- p_sco->esco.data.link_type = BTM_LINK_TYPE_ESCO; /* Accept with all supported types */
- BTM_TRACE_DEBUG("TCS accept SCO: Packet Types 0x%04x", p_setup->packet_types);
- btm_esco_conn_rsp(sco_inx, HCI_SUCCESS, p_sco->esco.data.bd_addr, p_setup);
- #else
- btm_reject_sco_link(sco_inx);
- #endif
- }
- /*******************************************************************************
- **
- ** Function btm_reject_sco_link
- **
- ** Description This function is called to respond to SCO connect indications
- **
- ** Returns void
- **
- *******************************************************************************/
- void btm_reject_sco_link( UINT16 sco_inx )
- {
- btm_esco_conn_rsp(sco_inx, HCI_ERR_HOST_REJECT_RESOURCES,
- btm_cb.sco_cb.sco_db[sco_inx].esco.data.bd_addr, NULL);
- }
- /*******************************************************************************
- **
- ** Function BTM_CreateSco
- **
- ** Description This function is called to create an SCO connection. If the
- ** "is_orig" flag is TRUE, the connection will be originated,
- ** otherwise BTM will wait for the other side to connect.
- **
- ** NOTE: If BTM_IGNORE_SCO_PKT_TYPE is passed in the pkt_types
- ** parameter the default packet types is used.
- **
- ** Returns BTM_UNKNOWN_ADDR if the ACL connection is not up
- ** BTM_BUSY if another SCO being set up to
- ** the same BD address
- ** BTM_NO_RESOURCES if the max SCO limit has been reached
- ** BTM_CMD_STARTED if the connection establishment is started.
- ** In this case, "*p_sco_inx" is filled in
- ** with the sco index used for the connection.
- **
- *******************************************************************************/
- tBTM_STATUS BTM_CreateSco (BD_ADDR remote_bda, BOOLEAN is_orig, UINT16 pkt_types,
- UINT16 *p_sco_inx, tBTM_SCO_CB *p_conn_cb,
- tBTM_SCO_CB *p_disc_cb)
- {
- #if (BTM_MAX_SCO_LINKS > 0)
- tBTM_ESCO_PARAMS *p_setup;
- tSCO_CONN *p = &btm_cb.sco_cb.sco_db[0];
- UINT16 xx;
- UINT16 acl_handle = 0;
- UINT16 temp_pkt_types;
- tACL_CONN *p_acl;
- #if (BTM_SCO_WAKE_PARKED_LINK == TRUE)
- tBTM_PM_MODE md;
- tBTM_PM_PWR_MD pm;
- #else // BTM_SCO_WAKE_PARKED_LINK
- UINT8 mode;
- #endif // BTM_SCO_WAKE_PARKED_LINK
- *p_sco_inx = BTM_INVALID_SCO_INDEX;
- /* If originating, ensure that there is an ACL connection to the BD Address */
- if (is_orig) {
- if ((!remote_bda) || ((acl_handle = BTM_GetHCIConnHandle (remote_bda, BT_TRANSPORT_BR_EDR)) == 0xFFFF)) {
- return (BTM_UNKNOWN_ADDR);
- }
- }
- if (remote_bda) {
- /* If any SCO is being established to the remote BD address, refuse this */
- for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
- if (((p->state == SCO_ST_CONNECTING) || (p->state == SCO_ST_LISTENING)
- || (p->state == SCO_ST_PEND_UNPARK))
- && (!memcmp (p->esco.data.bd_addr, remote_bda, BD_ADDR_LEN))) {
- return (BTM_BUSY);
- }
- }
- } else {
- /* Support only 1 wildcard BD address at a time */
- for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
- if ((p->state == SCO_ST_LISTENING) && (!p->rem_bd_known)) {
- return (BTM_BUSY);
- }
- }
- }
- /* Now, try to find an unused control block, and kick off the SCO establishment */
- for (xx = 0, p = &btm_cb.sco_cb.sco_db[0]; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
- if (p->state == SCO_ST_UNUSED) {
- if (remote_bda) {
- if (is_orig) {
- /* can not create SCO link if in park mode */
- #if BTM_SCO_WAKE_PARKED_LINK == TRUE
- if (BTM_ReadPowerMode(remote_bda, &md) == BTM_SUCCESS) {
- if (md == BTM_PM_MD_PARK || md == BTM_PM_MD_SNIFF) {
- memset( (void *)&pm, 0, sizeof(pm));
- pm.mode = BTM_PM_MD_ACTIVE;
- BTM_SetPowerMode(BTM_PM_SET_ONLY_ID, remote_bda, &pm);
- p->state = SCO_ST_PEND_UNPARK;
- }
- }
- #else // BTM_SCO_WAKE_PARKED_LINK
- if ( (BTM_ReadPowerMode(remote_bda, &mode) == BTM_SUCCESS) && (mode == BTM_PM_MD_PARK) ) {
- return (BTM_WRONG_MODE);
- }
- #endif // BTM_SCO_WAKE_PARKED_LINK
- }
- memcpy (p->esco.data.bd_addr, remote_bda, BD_ADDR_LEN);
- p->rem_bd_known = TRUE;
- } else {
- p->rem_bd_known = FALSE;
- }
- /* Link role is ignored in for this message */
- if (pkt_types == BTM_IGNORE_SCO_PKT_TYPE) {
- pkt_types = btm_cb.sco_cb.def_esco_parms.packet_types;
- }
- p_setup = &p->esco.setup;
- *p_setup = btm_cb.sco_cb.def_esco_parms;
- p_setup->packet_types = (btm_cb.sco_cb.desired_sco_mode == BTM_LINK_TYPE_SCO)
- ? (pkt_types & BTM_SCO_LINK_ONLY_MASK) : pkt_types;
- temp_pkt_types = (p_setup->packet_types & BTM_SCO_SUPPORTED_PKTS_MASK &
- btm_cb.btm_sco_pkt_types_supported);
- /* OR in any exception packet types */
- if (btm_cb.sco_cb.desired_sco_mode == HCI_LINK_TYPE_ESCO) {
- temp_pkt_types |= ((p_setup->packet_types & BTM_SCO_EXCEPTION_PKTS_MASK) |
- (btm_cb.btm_sco_pkt_types_supported & BTM_SCO_EXCEPTION_PKTS_MASK));
- } else { /* Only using SCO packet types; turn off EDR also */
- temp_pkt_types |= BTM_SCO_EXCEPTION_PKTS_MASK;
- }
- p_setup->packet_types = temp_pkt_types;
- p->p_conn_cb = p_conn_cb;
- p->p_disc_cb = p_disc_cb;
- p->hci_handle = BTM_INVALID_HCI_HANDLE;
- p->is_orig = is_orig;
- if ( p->state != SCO_ST_PEND_UNPARK ) {
- if (is_orig) {
- /* If role change is in progress, do not proceed with SCO setup
- * Wait till role change is complete */
- p_acl = btm_bda_to_acl(remote_bda, BT_TRANSPORT_BR_EDR);
- if (p_acl && p_acl->switch_role_state != BTM_ACL_SWKEY_STATE_IDLE) {
- BTM_TRACE_API("Role Change is in progress for ACL handle 0x%04x", acl_handle);
- p->state = SCO_ST_PEND_ROLECHANGE;
- }
- }
- }
- if ( p->state != SCO_ST_PEND_UNPARK && p->state != SCO_ST_PEND_ROLECHANGE ) {
- if (is_orig) {
- BTM_TRACE_API("BTM_CreateSco -> (e)SCO Link for ACL handle 0x%04x, Desired Type %d",
- acl_handle, btm_cb.sco_cb.desired_sco_mode);
- if ((btm_send_connect_request(acl_handle, p_setup)) != BTM_CMD_STARTED) {
- return (BTM_NO_RESOURCES);
- }
- p->state = SCO_ST_CONNECTING;
- } else {
- p->state = SCO_ST_LISTENING;
- }
- }
- *p_sco_inx = xx;
- return (BTM_CMD_STARTED);
- }
- }
- #endif
- /* If here, all SCO blocks in use */
- return (BTM_NO_RESOURCES);
- }
- #if (BTM_SCO_WAKE_PARKED_LINK == TRUE)
- /*******************************************************************************
- **
- ** Function btm_sco_chk_pend_unpark
- **
- ** Description This function is called by BTIF when there is a mode change
- ** event to see if there are SCO commands waiting for the unpark.
- **
- ** Returns void
- **
- *******************************************************************************/
- void btm_sco_chk_pend_unpark (UINT8 hci_status, UINT16 hci_handle)
- {
- #if (BTM_MAX_SCO_LINKS>0)
- UINT16 xx;
- UINT16 acl_handle;
- tSCO_CONN *p = &btm_cb.sco_cb.sco_db[0];
- for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
- if ((p->state == SCO_ST_PEND_UNPARK) &&
- ((acl_handle = BTM_GetHCIConnHandle (p->esco.data.bd_addr, BT_TRANSPORT_BR_EDR)) == hci_handle))
- {
- BTM_TRACE_API("btm_sco_chk_pend_unpark -> (e)SCO Link for ACL handle 0x%04x, Desired Type %d, hci_status 0x%02x",
- acl_handle, btm_cb.sco_cb.desired_sco_mode, hci_status);
- if ((btm_send_connect_request(acl_handle, &p->esco.setup)) == BTM_CMD_STARTED) {
- p->state = SCO_ST_CONNECTING;
- }
- }
- }
- #endif // BTM_MAX_SCO_LINKS
- }
- #endif // BTM_SCO_WAKE_PARKED_LINK
- /*******************************************************************************
- **
- ** Function btm_sco_chk_pend_rolechange
- **
- ** Description This function is called by BTIF when there is a role change
- ** event to see if there are SCO commands waiting for the role change.
- **
- ** Returns void
- **
- *******************************************************************************/
- void btm_sco_chk_pend_rolechange (UINT16 hci_handle)
- {
- #if (BTM_MAX_SCO_LINKS>0)
- UINT16 xx;
- UINT16 acl_handle;
- tSCO_CONN *p = &btm_cb.sco_cb.sco_db[0];
- for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
- if ((p->state == SCO_ST_PEND_ROLECHANGE) &&
- ((acl_handle = BTM_GetHCIConnHandle (p->esco.data.bd_addr, BT_TRANSPORT_BR_EDR)) == hci_handle))
- {
- BTM_TRACE_API("btm_sco_chk_pend_rolechange -> (e)SCO Link for ACL handle 0x%04x", acl_handle);
- if ((btm_send_connect_request(acl_handle, &p->esco.setup)) == BTM_CMD_STARTED) {
- p->state = SCO_ST_CONNECTING;
- }
- }
- }
- #endif
- }
- /*******************************************************************************
- **
- ** Function btm_sco_conn_req
- **
- ** Description This function is called by BTIF when an SCO connection
- ** request is received from a remote.
- **
- ** Returns void
- **
- *******************************************************************************/
- void btm_sco_conn_req (BD_ADDR bda, DEV_CLASS dev_class, UINT8 link_type)
- {
- #if (BTM_MAX_SCO_LINKS>0)
- tSCO_CB *p_sco = &btm_cb.sco_cb;
- tSCO_CONN *p = &p_sco->sco_db[0];
- UINT16 xx;
- tBTM_ESCO_CONN_REQ_EVT_DATA evt_data;
- for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
- /*
- * If the sco state is in the SCO_ST_CONNECTING state, we still need
- * to return accept sco to avoid race conditon for sco creation
- */
- int rem_bd_matches = p->rem_bd_known &&
- !memcmp (p->esco.data.bd_addr, bda, BD_ADDR_LEN);
- if (((p->state == SCO_ST_CONNECTING) && rem_bd_matches) ||
- ((p->state == SCO_ST_LISTENING) && (rem_bd_matches || !p->rem_bd_known))) {
- /* If this guy was a wildcard, he is not one any more */
- p->rem_bd_known = TRUE;
- p->esco.data.link_type = link_type;
- p->state = SCO_ST_W4_CONN_RSP;
- memcpy (p->esco.data.bd_addr, bda, BD_ADDR_LEN);
- /* If no callback, auto-accept the connection if packet types match */
- if (!p->esco.p_esco_cback) {
- /* If requesting eSCO reject if default parameters are SCO only */
- if ((link_type == BTM_LINK_TYPE_ESCO
- && !(p_sco->def_esco_parms.packet_types & BTM_ESCO_LINK_ONLY_MASK)
- && ((p_sco->def_esco_parms.packet_types & BTM_SCO_EXCEPTION_PKTS_MASK)
- == BTM_SCO_EXCEPTION_PKTS_MASK))
- /* Reject request if SCO is desired but no SCO packets delected */
- || (link_type == BTM_LINK_TYPE_SCO
- && !(p_sco->def_esco_parms.packet_types & BTM_SCO_LINK_ONLY_MASK))) {
- btm_esco_conn_rsp(xx, HCI_ERR_HOST_REJECT_RESOURCES, bda, NULL);
- } else { /* Accept the request */
- btm_esco_conn_rsp(xx, HCI_SUCCESS, bda, NULL);
- }
- } else { /* Notify upper layer of connect indication */
- memcpy(evt_data.bd_addr, bda, BD_ADDR_LEN);
- memcpy(evt_data.dev_class, dev_class, DEV_CLASS_LEN);
- evt_data.link_type = link_type;
- evt_data.sco_inx = xx;
- p->esco.p_esco_cback(BTM_ESCO_CONN_REQ_EVT, (tBTM_ESCO_EVT_DATA *)&evt_data);
- }
- return;
- }
- }
- /* TCS usage */
- if (btm_cb.sco_cb.app_sco_ind_cb) {
- /* Now, try to find an unused control block */
- for (xx = 0, p = &btm_cb.sco_cb.sco_db[0]; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
- if (p->state == SCO_ST_UNUSED) {
- p->is_orig = FALSE;
- p->state = SCO_ST_LISTENING;
- p->esco.data.link_type = link_type;
- memcpy (p->esco.data.bd_addr, bda, BD_ADDR_LEN);
- p->rem_bd_known = TRUE;
- break;
- }
- }
- if ( xx < BTM_MAX_SCO_LINKS) {
- btm_cb.sco_cb.app_sco_ind_cb(xx);
- return;
- }
- }
- #endif
- /* If here, no one wants the SCO connection. Reject it */
- BTM_TRACE_WARNING("btm_sco_conn_req: No one wants this SCO connection; rejecting it");
- btm_esco_conn_rsp(BTM_MAX_SCO_LINKS, HCI_ERR_HOST_REJECT_RESOURCES, bda, NULL);
- }
- /*******************************************************************************
- **
- ** Function btm_sco_connected
- **
- ** Description This function is called by BTIF when an (e)SCO connection
- ** is connected.
- **
- ** Returns void
- **
- *******************************************************************************/
- void btm_sco_connected (UINT8 hci_status, BD_ADDR bda, UINT16 hci_handle,
- tBTM_ESCO_DATA *p_esco_data)
- {
- #if (BTM_MAX_SCO_LINKS>0)
- tSCO_CONN *p = &btm_cb.sco_cb.sco_db[0];
- UINT16 xx;
- BOOLEAN spt = FALSE;
- tBTM_CHG_ESCO_PARAMS parms;
- #endif
- btm_cb.sco_cb.sco_disc_reason = hci_status;
- BTM_TRACE_API("%s, handle %x", __FUNCTION__, hci_handle);
- #if (BTM_MAX_SCO_LINKS>0)
- for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
- if (((p->state == SCO_ST_CONNECTING) ||
- (p->state == SCO_ST_LISTENING) ||
- (p->state == SCO_ST_W4_CONN_RSP))
- && (p->rem_bd_known)
- && (!bda || !memcmp (p->esco.data.bd_addr, bda, BD_ADDR_LEN))) {
- if (hci_status != HCI_SUCCESS) {
- /* Report the error if originator, otherwise remain in Listen mode */
- if (p->is_orig) {
- /* If role switch is pending, we need try again after role switch is complete */
- if (hci_status == HCI_ERR_ROLE_SWITCH_PENDING) {
- BTM_TRACE_API("Role Change pending for HCI handle 0x%04x", hci_handle);
- p->state = SCO_ST_PEND_ROLECHANGE;
- }
- /* avoid calling disconnect callback because of sco creation race */
- else if (hci_status != HCI_ERR_LMP_ERR_TRANS_COLLISION) {
- p->state = SCO_ST_UNUSED;
- (*p->p_disc_cb)(xx);
- }
- } else {
- /* Notify the upper layer that incoming sco connection has failed. */
- if (p->state == SCO_ST_CONNECTING) {
- p->state = SCO_ST_UNUSED;
- (*p->p_disc_cb)(xx);
- } else {
- p->state = SCO_ST_LISTENING;
- }
- }
- return;
- }
- if (p->state == SCO_ST_LISTENING) {
- spt = TRUE;
- }
- #if BTM_SCO_HCI_INCLUDED == TRUE
- p->sent_not_acked = 0;
- btm_pkt_stat_nums_reset(xx);
- #endif
- p->state = SCO_ST_CONNECTED;
- p->hci_handle = hci_handle;
- if (!btm_cb.sco_cb.esco_supported) {
- p->esco.data.link_type = BTM_LINK_TYPE_SCO;
- if (spt) {
- parms.packet_types = p->esco.setup.packet_types;
- /* Keep the other parameters the same for SCO */
- parms.max_latency = p->esco.setup.max_latency;
- parms.retrans_effort = p->esco.setup.retrans_effort;
- BTM_ChangeEScoLinkParms(xx, &parms);
- }
- } else {
- if (p_esco_data) {
- p->esco.data = *p_esco_data;
- }
- }
- (*p->p_conn_cb)(xx);
- return;
- }
- }
- #endif
- }
- /*******************************************************************************
- **
- ** Function btm_find_scb_by_handle
- **
- ** Description Look through all active SCO connection for a match based on the
- ** HCI handle.
- **
- ** Returns index to matched SCO connection CB, or BTM_MAX_SCO_LINKS if
- ** no match.
- **
- *******************************************************************************/
- UINT16 btm_find_scb_by_handle (UINT16 handle)
- {
- int xx;
- tSCO_CONN *p = &btm_cb.sco_cb.sco_db[0];
- for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
- if ((p->state == SCO_ST_CONNECTED) && (p->hci_handle == handle)) {
- return (xx);
- }
- }
- /* If here, no match found */
- return (xx);
- }
- /*******************************************************************************
- **
- ** Function BTM_RemoveSco
- **
- ** Description This function is called to remove a specific SCO connection.
- **
- ** Returns status of the operation
- **
- *******************************************************************************/
- tBTM_STATUS BTM_RemoveSco (UINT16 sco_inx)
- {
- #if (BTM_MAX_SCO_LINKS>0)
- tSCO_CONN *p = &btm_cb.sco_cb.sco_db[sco_inx];
- UINT16 tempstate;
- /* Validity check */
- if ((sco_inx >= BTM_MAX_SCO_LINKS) || (p->state == SCO_ST_UNUSED)) {
- return (BTM_UNKNOWN_ADDR);
- }
- /* If no HCI handle, simply drop the connection and return */
- if (p->hci_handle == BTM_INVALID_HCI_HANDLE || p->state == SCO_ST_PEND_UNPARK) {
- p->hci_handle = BTM_INVALID_HCI_HANDLE;
- p->state = SCO_ST_UNUSED;
- p->esco.p_esco_cback = NULL; /* Deregister the eSCO event callback */
- return (BTM_SUCCESS);
- }
- tempstate = p->state;
- p->state = SCO_ST_DISCONNECTING;
- if (!btsnd_hcic_disconnect (p->hci_handle, HCI_ERR_PEER_USER)) {
- p->state = tempstate;
- return (BTM_NO_RESOURCES);
- }
- return (BTM_CMD_STARTED);
- #else
- return (BTM_NO_RESOURCES);
- #endif
- }
- /*******************************************************************************
- **
- ** Function btm_remove_sco_links
- **
- ** Description This function is called to remove all sco links for an ACL link.
- **
- ** Returns void
- **
- *******************************************************************************/
- void btm_remove_sco_links (BD_ADDR bda)
- {
- #if (BTM_MAX_SCO_LINKS>0)
- tSCO_CONN *p = &btm_cb.sco_cb.sco_db[0];
- UINT16 xx;
- for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
- if (p->rem_bd_known && (!memcmp (p->esco.data.bd_addr, bda, BD_ADDR_LEN))) {
- BTM_RemoveSco(xx);
- }
- }
- #endif
- }
- /*******************************************************************************
- **
- ** Function btm_sco_removed
- **
- ** Description This function is called by BTIF when an SCO connection
- ** is removed.
- **
- ** Returns void
- **
- *******************************************************************************/
- void btm_sco_removed (UINT16 hci_handle, UINT8 reason)
- {
- #if (BTM_MAX_SCO_LINKS>0)
- tSCO_CONN *p = &btm_cb.sco_cb.sco_db[0];
- UINT16 xx;
- #endif
- btm_cb.sco_cb.sco_disc_reason = reason;
- #if (BTM_MAX_SCO_LINKS>0)
- p = &btm_cb.sco_cb.sco_db[0];
- for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
- if ((p->state != SCO_ST_UNUSED) && (p->state != SCO_ST_LISTENING) && (p->hci_handle == hci_handle)) {
- btm_sco_flush_sco_data(xx);
- p->state = SCO_ST_UNUSED;
- #if BTM_SCO_HCI_INCLUDED == TRUE
- btm_cb.sco_cb.xmit_window_size += p->sent_not_acked;
- /* avoid overflow */
- if (btm_cb.sco_cb.xmit_window_size > btm_cb.sco_cb.num_lm_sco_bufs) {
- btm_cb.sco_cb.xmit_window_size = btm_cb.sco_cb.num_lm_sco_bufs;
- }
- p->sent_not_acked = 0;
- #endif
- p->hci_handle = BTM_INVALID_HCI_HANDLE;
- p->rem_bd_known = FALSE;
- p->esco.p_esco_cback = NULL; /* Deregister eSCO callback */
- (*p->p_disc_cb)(xx);
- return;
- }
- }
- #endif
- }
- /*******************************************************************************
- **
- ** Function btm_sco_acl_removed
- **
- ** Description This function is called when an ACL connection is
- ** removed. If the BD address is NULL, it is assumed that
- ** the local device is down, and all SCO links are removed.
- ** If a specific BD address is passed, only SCO connections
- ** to that BD address are removed.
- **
- ** Returns void
- **
- *******************************************************************************/
- void btm_sco_acl_removed (BD_ADDR bda)
- {
- #if (BTM_MAX_SCO_LINKS>0)
- tSCO_CONN *p = &btm_cb.sco_cb.sco_db[0];
- UINT16 xx;
- for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
- if (p->state != SCO_ST_UNUSED) {
- if ((!bda) || (!memcmp (p->esco.data.bd_addr, bda, BD_ADDR_LEN) && p->rem_bd_known)) {
- btm_sco_flush_sco_data(xx);
- p->state = SCO_ST_UNUSED;
- p->esco.p_esco_cback = NULL; /* Deregister eSCO callback */
- (*p->p_disc_cb)(xx);
- }
- }
- }
- #endif
- }
- /*******************************************************************************
- **
- ** Function BTM_SetScoPacketTypes
- **
- ** Description This function is called to set the packet types used for
- ** a specific SCO connection,
- **
- ** Parameters pkt_types - One or more of the following
- ** BTM_SCO_PKT_TYPES_MASK_HV1
- ** BTM_SCO_PKT_TYPES_MASK_HV2
- ** BTM_SCO_PKT_TYPES_MASK_HV3
- ** BTM_SCO_PKT_TYPES_MASK_EV3
- ** BTM_SCO_PKT_TYPES_MASK_EV4
- ** BTM_SCO_PKT_TYPES_MASK_EV5
- ** BTM_SCO_PKT_TYPES_MASK_NO_2_EV3
- ** BTM_SCO_PKT_TYPES_MASK_NO_3_EV3
- ** BTM_SCO_PKT_TYPES_MASK_NO_2_EV5
- ** BTM_SCO_PKT_TYPES_MASK_NO_3_EV5
- **
- ** BTM_SCO_LINK_ALL_MASK - enables all supported types
- **
- ** Returns status of the operation
- **
- *******************************************************************************/
- tBTM_STATUS BTM_SetScoPacketTypes (UINT16 sco_inx, UINT16 pkt_types)
- {
- #if (BTM_MAX_SCO_LINKS>0)
- tBTM_CHG_ESCO_PARAMS parms;
- tSCO_CONN *p;
- /* Validity check */
- if (sco_inx >= BTM_MAX_SCO_LINKS) {
- return (BTM_UNKNOWN_ADDR);
- }
- p = &btm_cb.sco_cb.sco_db[sco_inx];
- parms.packet_types = pkt_types;
- /* Keep the other parameters the same for SCO */
- parms.max_latency = p->esco.setup.max_latency;
- parms.retrans_effort = p->esco.setup.retrans_effort;
- return (BTM_ChangeEScoLinkParms(sco_inx, &parms));
- #else
- return (BTM_UNKNOWN_ADDR);
- #endif
- }
- /*******************************************************************************
- **
- ** Function BTM_ReadScoPacketTypes
- **
- ** Description This function is read the packet types used for a specific
- ** SCO connection.
- **
- ** Returns Packet types supported for the connection
- ** One or more of the following (bitmask):
- ** BTM_SCO_PKT_TYPES_MASK_HV1
- ** BTM_SCO_PKT_TYPES_MASK_HV2
- ** BTM_SCO_PKT_TYPES_MASK_HV3
- ** BTM_SCO_PKT_TYPES_MASK_EV3
- ** BTM_SCO_PKT_TYPES_MASK_EV4
- ** BTM_SCO_PKT_TYPES_MASK_EV5
- ** BTM_SCO_PKT_TYPES_MASK_NO_2_EV3
- ** BTM_SCO_PKT_TYPES_MASK_NO_3_EV3
- ** BTM_SCO_PKT_TYPES_MASK_NO_2_EV5
- ** BTM_SCO_PKT_TYPES_MASK_NO_3_EV5
- **
- *******************************************************************************/
- UINT16 BTM_ReadScoPacketTypes (UINT16 sco_inx)
- {
- #if (BTM_MAX_SCO_LINKS>0)
- tSCO_CONN *p = &btm_cb.sco_cb.sco_db[sco_inx];
- /* Validity check */
- if ((sco_inx < BTM_MAX_SCO_LINKS) && (p->state == SCO_ST_CONNECTED)) {
- return (p->esco.setup.packet_types);
- } else {
- return (0);
- }
- #else
- return (0);
- #endif
- }
- /*******************************************************************************
- **
- ** Function BTM_ReadScoDiscReason
- **
- ** Description This function is returns the reason why an (e)SCO connection
- ** has been removed. It contains the value until read, or until
- ** another (e)SCO connection has disconnected.
- **
- ** Returns HCI reason or BTM_INVALID_SCO_DISC_REASON if not set.
- **
- *******************************************************************************/
- UINT16 BTM_ReadScoDiscReason (void)
- {
- UINT16 res = btm_cb.sco_cb.sco_disc_reason;
- btm_cb.sco_cb.sco_disc_reason = BTM_INVALID_SCO_DISC_REASON;
- return (res);
- }
- /*******************************************************************************
- **
- ** Function BTM_ReadDeviceScoPacketTypes
- **
- ** Description This function is read the SCO packet types that
- ** the device supports.
- **
- ** Returns Packet types supported by the device.
- ** One or more of the following (bitmask):
- ** BTM_SCO_PKT_TYPES_MASK_HV1
- ** BTM_SCO_PKT_TYPES_MASK_HV2
- ** BTM_SCO_PKT_TYPES_MASK_HV3
- ** BTM_SCO_PKT_TYPES_MASK_EV3
- ** BTM_SCO_PKT_TYPES_MASK_EV4
- ** BTM_SCO_PKT_TYPES_MASK_EV5
- ** BTM_SCO_PKT_TYPES_MASK_NO_2_EV3
- ** BTM_SCO_PKT_TYPES_MASK_NO_3_EV3
- ** BTM_SCO_PKT_TYPES_MASK_NO_2_EV5
- ** BTM_SCO_PKT_TYPES_MASK_NO_3_EV5
- **
- *******************************************************************************/
- UINT16 BTM_ReadDeviceScoPacketTypes (void)
- {
- return (btm_cb.btm_sco_pkt_types_supported);
- }
- /*******************************************************************************
- **
- ** Function BTM_ReadScoHandle
- **
- ** Description This function is used to read the HCI handle used for a specific
- ** SCO connection,
- **
- ** Returns handle for the connection, or 0xFFFF if invalid SCO index.
- **
- *******************************************************************************/
- UINT16 BTM_ReadScoHandle (UINT16 sco_inx)
- {
- #if (BTM_MAX_SCO_LINKS>0)
- tSCO_CONN *p = &btm_cb.sco_cb.sco_db[sco_inx];
- /* Validity check */
- if ((sco_inx < BTM_MAX_SCO_LINKS) && (p->state == SCO_ST_CONNECTED)) {
- return (p->hci_handle);
- } else {
- return (BTM_INVALID_HCI_HANDLE);
- }
- #else
- return (BTM_INVALID_HCI_HANDLE);
- #endif
- }
- /*******************************************************************************
- **
- ** Function BTM_ReadScoBdAddr
- **
- ** Description This function is read the remote BD Address for a specific
- ** SCO connection,
- **
- ** Returns pointer to BD address or NULL if not known
- **
- *******************************************************************************/
- UINT8 *BTM_ReadScoBdAddr (UINT16 sco_inx)
- {
- #if (BTM_MAX_SCO_LINKS>0)
- tSCO_CONN *p = &btm_cb.sco_cb.sco_db[sco_inx];
- /* Validity check */
- if ((sco_inx < BTM_MAX_SCO_LINKS) && (p->rem_bd_known)) {
- return (p->esco.data.bd_addr);
- } else {
- return (NULL);
- }
- #else
- return (NULL);
- #endif
- }
- /*******************************************************************************
- **
- ** Function BTM_SetEScoMode
- **
- ** Description This function sets up the negotiated parameters for SCO or
- ** eSCO, and sets as the default mode used for outgoing calls to
- ** BTM_CreateSco. It does not change any currently active (e)SCO links.
- ** Note: Incoming (e)SCO connections will always use packet types
- ** supported by the controller. If eSCO is not desired the
- ** feature should be disabled in the controller's feature mask.
- **
- ** Returns BTM_SUCCESS if the successful.
- ** BTM_BUSY if there are one or more active (e)SCO links.
- **
- *******************************************************************************/
- tBTM_STATUS BTM_SetEScoMode (tBTM_SCO_TYPE sco_mode, tBTM_ESCO_PARAMS *p_parms)
- {
- tSCO_CB *p_esco = &btm_cb.sco_cb;
- tBTM_ESCO_PARAMS *p_def = &p_esco->def_esco_parms;
- if (p_esco->esco_supported) {
- if (p_parms) {
- if (sco_mode == BTM_LINK_TYPE_ESCO) {
- *p_def = *p_parms; /* Save as the default parameters */
- } else { /* Load only the SCO packet types */
- p_def->packet_types = p_parms->packet_types;
- p_def->tx_bw = BTM_64KBITS_RATE;
- p_def->rx_bw = BTM_64KBITS_RATE;
- p_def->max_latency = 0x000a;
- p_def->voice_contfmt = 0x0060;
- p_def->retrans_effort = 0;
- /* OR in any exception packet types */
- p_def->packet_types |= BTM_SCO_EXCEPTION_PKTS_MASK;
- }
- }
- p_esco->desired_sco_mode = sco_mode;
- BTM_TRACE_API("BTM_SetEScoMode -> mode %d", sco_mode);
- } else {
- p_esco->desired_sco_mode = BTM_LINK_TYPE_SCO;
- p_def->packet_types &= BTM_SCO_LINK_ONLY_MASK;
- p_def->retrans_effort = 0;
- BTM_TRACE_API("BTM_SetEScoMode -> mode SCO (eSCO not supported)");
- }
- BTM_TRACE_DEBUG(" txbw 0x%08x, rxbw 0x%08x, max_lat 0x%04x, voice 0x%04x, pkt 0x%04x, rtx effort 0x%02x",
- p_def->tx_bw, p_def->rx_bw, p_def->max_latency,
- p_def->voice_contfmt, p_def->packet_types,
- p_def->retrans_effort);
- return (BTM_SUCCESS);
- }
- /*******************************************************************************
- **
- ** Function BTM_RegForEScoEvts
- **
- ** Description This function registers a SCO event callback with the
- ** specified instance. It should be used to received
- ** connection indication events and change of link parameter
- ** events.
- **
- ** Returns BTM_SUCCESS if the successful.
- ** BTM_ILLEGAL_VALUE if there is an illegal sco_inx
- ** BTM_MODE_UNSUPPORTED if controller version is not BT1.2 or
- ** later or does not support eSCO.
- **
- *******************************************************************************/
- tBTM_STATUS BTM_RegForEScoEvts (UINT16 sco_inx, tBTM_ESCO_CBACK *p_esco_cback)
- {
- #if (BTM_MAX_SCO_LINKS>0)
- if (!btm_cb.sco_cb.esco_supported) {
- btm_cb.sco_cb.sco_db[sco_inx].esco.p_esco_cback = NULL;
- return (BTM_MODE_UNSUPPORTED);
- }
- if (sco_inx < BTM_MAX_SCO_LINKS &&
- btm_cb.sco_cb.sco_db[sco_inx].state != SCO_ST_UNUSED) {
- btm_cb.sco_cb.sco_db[sco_inx].esco.p_esco_cback = p_esco_cback;
- return (BTM_SUCCESS);
- }
- return (BTM_ILLEGAL_VALUE);
- #else
- return (BTM_MODE_UNSUPPORTED);
- #endif
- }
- /*******************************************************************************
- **
- ** Function BTM_ReadEScoLinkParms
- **
- ** Description This function returns the current eSCO link parameters for
- ** the specified handle. This can be called anytime a connection
- ** is active, but is typically called after receiving the SCO
- ** opened callback.
- **
- ** Note: If called over a 1.1 controller, only the packet types
- ** field has meaning.
- **
- ** Returns BTM_SUCCESS if returned data is valid connection.
- ** BTM_WRONG_MODE if no connection with a peer device or bad sco_inx.
- **
- *******************************************************************************/
- tBTM_STATUS BTM_ReadEScoLinkParms (UINT16 sco_inx, tBTM_ESCO_DATA *p_parms)
- {
- #if (BTM_MAX_SCO_LINKS>0)
- UINT8 index;
- BTM_TRACE_API("BTM_ReadEScoLinkParms -> sco_inx 0x%04x", sco_inx);
- if (sco_inx < BTM_MAX_SCO_LINKS &&
- btm_cb.sco_cb.sco_db[sco_inx].state >= SCO_ST_CONNECTED) {
- *p_parms = btm_cb.sco_cb.sco_db[sco_inx].esco.data;
- return (BTM_SUCCESS);
- }
- if (sco_inx == BTM_FIRST_ACTIVE_SCO_INDEX) {
- for (index = 0; index < BTM_MAX_SCO_LINKS; index++) {
- if (btm_cb.sco_cb.sco_db[index].state >= SCO_ST_CONNECTED) {
- BTM_TRACE_API("BTM_ReadEScoLinkParms the first active SCO index is %d", index);
- *p_parms = btm_cb.sco_cb.sco_db[index].esco.data;
- return (BTM_SUCCESS);
- }
- }
- }
- #endif
- BTM_TRACE_API("BTM_ReadEScoLinkParms cannot find the SCO index!");
- memset(p_parms, 0, sizeof(tBTM_ESCO_DATA));
- return (BTM_WRONG_MODE);
- }
- /*******************************************************************************
- **
- ** Function BTM_ChangeEScoLinkParms
- **
- ** Description This function requests renegotiation of the parameters on
- ** the current eSCO Link. If any of the changes are accepted
- ** by the controllers, the BTM_ESCO_CHG_EVT event is sent in
- ** the tBTM_ESCO_CBACK function with the current settings of
- ** the link. The callback is registered through the call to
- ** BTM_SetEScoMode.
- **
- ** Note: If called over a SCO link (including 1.1 controller),
- ** a change packet type request is sent out instead.
- **
- ** Returns BTM_CMD_STARTED if command is successfully initiated.
- ** BTM_NO_RESOURCES - not enough resources to initiate command.
- ** BTM_WRONG_MODE if no connection with a peer device or bad sco_inx.
- **
- *******************************************************************************/
- tBTM_STATUS BTM_ChangeEScoLinkParms (UINT16 sco_inx, tBTM_CHG_ESCO_PARAMS *p_parms)
- {
- #if (BTM_MAX_SCO_LINKS>0)
- tBTM_ESCO_PARAMS *p_setup;
- tSCO_CONN *p_sco;
- UINT16 temp_pkt_types;
- /* Make sure sco handle is valid and on an active link */
- if (sco_inx >= BTM_MAX_SCO_LINKS ||
- btm_cb.sco_cb.sco_db[sco_inx].state != SCO_ST_CONNECTED) {
- return (BTM_WRONG_MODE);
- }
- p_sco = &btm_cb.sco_cb.sco_db[sco_inx];
- p_setup = &p_sco->esco.setup;
- /* If SCO connection OR eSCO not supported just send change packet types */
- if (p_sco->esco.data.link_type == BTM_LINK_TYPE_SCO ||
- !btm_cb.sco_cb.esco_supported) {
- p_setup->packet_types = p_parms->packet_types &
- (btm_cb.btm_sco_pkt_types_supported & BTM_SCO_LINK_ONLY_MASK);
- BTM_TRACE_API("BTM_ChangeEScoLinkParms -> SCO Link for handle 0x%04x, pkt 0x%04x",
- p_sco->hci_handle, p_setup->packet_types);
- if (!btsnd_hcic_change_conn_type (p_sco->hci_handle,
- BTM_ESCO_2_SCO(p_setup->packet_types))) {
- return (BTM_NO_RESOURCES);
- }
- } else {
- temp_pkt_types = (p_parms->packet_types & BTM_SCO_SUPPORTED_PKTS_MASK &
- btm_cb.btm_sco_pkt_types_supported);
- /* OR in any exception packet types */
- temp_pkt_types |= ((p_parms->packet_types & BTM_SCO_EXCEPTION_PKTS_MASK) |
- (btm_cb.btm_sco_pkt_types_supported & BTM_SCO_EXCEPTION_PKTS_MASK));
- BTM_TRACE_API("BTM_ChangeEScoLinkParms -> eSCO Link for handle 0x%04x", p_sco->hci_handle);
- BTM_TRACE_API(" txbw 0x%x, rxbw 0x%x, lat 0x%x, voice 0x%x, retrans 0x%02x, pkt 0x%04x",
- p_setup->tx_bw, p_setup->rx_bw, p_parms->max_latency,
- p_setup->voice_contfmt, p_parms->retrans_effort, temp_pkt_types);
- /* When changing an existing link, only change latency, retrans, and pkts */
- if (!btsnd_hcic_setup_esco_conn(p_sco->hci_handle, p_setup->tx_bw,
- p_setup->rx_bw, p_parms->max_latency,
- p_setup->voice_contfmt,
- p_parms->retrans_effort,
- temp_pkt_types)) {
- return (BTM_NO_RESOURCES);
- } else {
- p_parms->packet_types = temp_pkt_types;
- }
- }
- return (BTM_CMD_STARTED);
- #else
- return (BTM_WRONG_MODE);
- #endif
- }
- /*******************************************************************************
- **
- ** Function BTM_EScoConnRsp
- **
- ** Description This function is called upon receipt of an (e)SCO connection
- ** request event (BTM_ESCO_CONN_REQ_EVT) to accept or reject
- ** the request. Parameters used to negotiate eSCO links.
- ** If p_parms is NULL, then values set through BTM_SetEScoMode
- ** are used.
- ** If the link type of the incoming request is SCO, then only
- ** the tx_bw, max_latency, content format, and packet_types are
- ** valid. The hci_status parameter should be
- ** ([0x0] to accept, [0x0d..0x0f] to reject)
- **
- **
- ** Returns void
- **
- *******************************************************************************/
- void BTM_EScoConnRsp (UINT16 sco_inx, UINT8 hci_status, tBTM_ESCO_PARAMS *p_parms)
- {
- #if (BTM_MAX_SCO_LINKS>0)
- if (sco_inx < BTM_MAX_SCO_LINKS &&
- btm_cb.sco_cb.sco_db[sco_inx].state == SCO_ST_W4_CONN_RSP) {
- btm_esco_conn_rsp(sco_inx, hci_status,
- btm_cb.sco_cb.sco_db[sco_inx].esco.data.bd_addr,
- p_parms);
- }
- #endif
- }
- /*******************************************************************************
- **
- ** Function btm_read_def_esco_mode
- **
- ** Description This function copies the current default esco settings into
- ** the return buffer.
- **
- ** Returns tBTM_SCO_TYPE
- **
- *******************************************************************************/
- tBTM_SCO_TYPE btm_read_def_esco_mode (tBTM_ESCO_PARAMS *p_parms)
- {
- #if (BTM_MAX_SCO_LINKS>0)
- *p_parms = btm_cb.sco_cb.def_esco_parms;
- return btm_cb.sco_cb.desired_sco_mode;
- #else
- return BTM_LINK_TYPE_SCO;
- #endif
- }
- /*******************************************************************************
- **
- ** Function btm_esco_proc_conn_chg
- **
- ** Description This function is called by BTIF when an SCO connection
- ** is changed.
- **
- ** Returns void
- **
- *******************************************************************************/
- void btm_esco_proc_conn_chg (UINT8 status, UINT16 handle, UINT8 tx_interval,
- UINT8 retrans_window, UINT16 rx_pkt_len,
- UINT16 tx_pkt_len)
- {
- #if (BTM_MAX_SCO_LINKS>0)
- tSCO_CONN *p = &btm_cb.sco_cb.sco_db[0];
- tBTM_CHG_ESCO_EVT_DATA data;
- UINT16 xx;
- BTM_TRACE_EVENT("btm_esco_proc_conn_chg -> handle 0x%04x, status 0x%02x",
- handle, status);
- for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
- if (p->state == SCO_ST_CONNECTED && handle == p->hci_handle) {
- /* If upper layer wants notification */
- if (p->esco.p_esco_cback) {
- memcpy(data.bd_addr, p->esco.data.bd_addr, BD_ADDR_LEN);
- data.hci_status = status;
- data.sco_inx = xx;
- data.rx_pkt_len = p->esco.data.rx_pkt_len = rx_pkt_len;
- data.tx_pkt_len = p->esco.data.tx_pkt_len = tx_pkt_len;
- data.tx_interval = p->esco.data.tx_interval = tx_interval;
- data.retrans_window = p->esco.data.retrans_window = retrans_window;
- (*p->esco.p_esco_cback)(BTM_ESCO_CHG_EVT,
- (tBTM_ESCO_EVT_DATA *)&data);
- }
- return;
- }
- }
- #endif
- }
- /*******************************************************************************
- **
- ** Function btm_is_sco_active
- **
- ** Description This function is called to see if a SCO handle is already in
- ** use.
- **
- ** Returns BOOLEAN
- **
- *******************************************************************************/
- BOOLEAN btm_is_sco_active (UINT16 handle)
- {
- #if (BTM_MAX_SCO_LINKS>0)
- UINT16 xx;
- tSCO_CONN *p = &btm_cb.sco_cb.sco_db[0];
- for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
- if (handle == p->hci_handle && p->state == SCO_ST_CONNECTED) {
- return (TRUE);
- }
- }
- #endif
- return (FALSE);
- }
- /*******************************************************************************
- **
- ** Function BTM_GetNumScoLinks
- **
- ** Description This function returns the number of active sco links.
- **
- ** Returns UINT8
- **
- *******************************************************************************/
- UINT8 BTM_GetNumScoLinks (void)
- {
- #if (BTM_MAX_SCO_LINKS>0)
- tSCO_CONN *p = &btm_cb.sco_cb.sco_db[0];
- UINT16 xx;
- UINT8 num_scos = 0;
- for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
- switch (p->state) {
- case SCO_ST_W4_CONN_RSP:
- case SCO_ST_CONNECTING:
- case SCO_ST_CONNECTED:
- case SCO_ST_DISCONNECTING:
- case SCO_ST_PEND_UNPARK:
- num_scos++;
- }
- }
- return (num_scos);
- #else
- return (0);
- #endif
- }
- /*******************************************************************************
- **
- ** Function btm_is_sco_active_by_bdaddr
- **
- ** Description This function is called to see if a SCO active to a bd address.
- **
- ** Returns BOOLEAN
- **
- *******************************************************************************/
- BOOLEAN btm_is_sco_active_by_bdaddr (BD_ADDR remote_bda)
- {
- #if (BTM_MAX_SCO_LINKS>0)
- UINT8 xx;
- tSCO_CONN *p = &btm_cb.sco_cb.sco_db[0];
- /* If any SCO is being established to the remote BD address, refuse this */
- for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
- if ((!memcmp (p->esco.data.bd_addr, remote_bda, BD_ADDR_LEN)) && (p->state == SCO_ST_CONNECTED)) {
- return (TRUE);
- }
- }
- #endif
- return (FALSE);
- }
- #else /* SCO_EXCLUDED == TRUE (Link in stubs) */
- tBTM_STATUS BTM_CreateSco (BD_ADDR remote_bda, BOOLEAN is_orig,
- UINT16 pkt_types, UINT16 *p_sco_inx,
- tBTM_SCO_CB *p_conn_cb,
- tBTM_SCO_CB *p_disc_cb)
- {
- return (BTM_NO_RESOURCES);
- }
- tBTM_STATUS BTM_RemoveSco (UINT16 sco_inx)
- {
- return (BTM_NO_RESOURCES);
- }
- tBTM_STATUS BTM_SetScoPacketTypes (UINT16 sco_inx, UINT16 pkt_types)
- {
- return (BTM_NO_RESOURCES);
- }
- UINT16 BTM_ReadScoPacketTypes (UINT16 sco_inx)
- {
- return (0);
- }
- UINT16 BTM_ReadDeviceScoPacketTypes (void)
- {
- return (0);
- }
- UINT16 BTM_ReadScoHandle (UINT16 sco_inx)
- {
- return (BTM_INVALID_HCI_HANDLE);
- }
- UINT8 *BTM_ReadScoBdAddr(UINT16 sco_inx)
- {
- return ((UINT8 *) NULL);
- }
- UINT16 BTM_ReadScoDiscReason (void)
- {
- return (BTM_INVALID_SCO_DISC_REASON);
- }
- tBTM_STATUS BTM_SetEScoMode (tBTM_SCO_TYPE sco_mode, tBTM_ESCO_PARAMS *p_parms)
- {
- return (BTM_MODE_UNSUPPORTED);
- }
- tBTM_STATUS BTM_RegForEScoEvts (UINT16 sco_inx, tBTM_ESCO_CBACK *p_esco_cback)
- {
- return (BTM_ILLEGAL_VALUE);
- }
- tBTM_STATUS BTM_ReadEScoLinkParms (UINT16 sco_inx, tBTM_ESCO_DATA *p_parms)
- {
- return (BTM_MODE_UNSUPPORTED);
- }
- tBTM_STATUS BTM_ChangeEScoLinkParms (UINT16 sco_inx, tBTM_CHG_ESCO_PARAMS *p_parms)
- {
- return (BTM_MODE_UNSUPPORTED);
- }
- void BTM_EScoConnRsp (UINT16 sco_inx, UINT8 hci_status, tBTM_ESCO_PARAMS *p_parms) {}
- UINT8 BTM_GetNumScoLinks (void)
- {
- return (0);
- }
- #endif /* If SCO is being used */
|