• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright 2000-2012 Broadcom Corporation
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 /******************************************************************************
20  *
21  *  This file contains functions that handle SCO connections. This includes
22  *  operations such as connect, disconnect, change supported packet types.
23  *
24  ******************************************************************************/
25 
26 #include <device/include/esco_parameters.h>
27 #include <stack/include/btm_api_types.h>
28 #include <string.h>
29 #include "bt_common.h"
30 #include "bt_target.h"
31 #include "bt_types.h"
32 #include "bt_utils.h"
33 #include "btm_api.h"
34 #include "btm_int.h"
35 #include "btm_int_types.h"
36 #include "btu.h"
37 #include "device/include/controller.h"
38 #include "device/include/esco_parameters.h"
39 #include "hcidefs.h"
40 #include "hcimsgs.h"
41 #include "osi/include/osi.h"
42 
43 /******************************************************************************/
44 /*               L O C A L    D A T A    D E F I N I T I O N S                */
45 /******************************************************************************/
46 
47 #define SCO_ST_UNUSED 0
48 #define SCO_ST_LISTENING 1
49 #define SCO_ST_W4_CONN_RSP 2
50 #define SCO_ST_CONNECTING 3
51 #define SCO_ST_CONNECTED 4
52 #define SCO_ST_DISCONNECTING 5
53 #define SCO_ST_PEND_UNPARK 6
54 #define SCO_ST_PEND_ROLECHANGE 7
55 #define SCO_ST_PEND_MODECHANGE 8
56 
57 /******************************************************************************/
58 /*            L O C A L    F U N C T I O N     P R O T O T Y P E S            */
59 /******************************************************************************/
60 
61 static uint16_t btm_sco_voice_settings_to_legacy(enh_esco_params_t* p_parms);
62 
63 /*******************************************************************************
64  *
65  * Function         btm_sco_flush_sco_data
66  *
67  * Description      This function is called to flush the SCO data for this
68  *                  channel.
69  *
70  * Returns          void
71  *
72  ******************************************************************************/
btm_sco_flush_sco_data(UNUSED_ATTR uint16_t sco_inx)73 void btm_sco_flush_sco_data(UNUSED_ATTR uint16_t sco_inx) {}
74 
75 /*******************************************************************************
76  *
77  * Function         btm_sco_init
78  *
79  * Description      This function is called at BTM startup to initialize
80  *
81  * Returns          void
82  *
83  ******************************************************************************/
btm_sco_init(void)84 void btm_sco_init(void) {
85   /* Initialize nonzero defaults */
86   btm_cb.sco_cb.sco_disc_reason = BTM_INVALID_SCO_DISC_REASON;
87   btm_cb.sco_cb.def_esco_parms = esco_parameters_for_codec(ESCO_CODEC_CVSD);
88   btm_cb.sco_cb.def_esco_parms.max_latency_ms = 12;
89   btm_cb.sco_cb.sco_route = ESCO_DATA_PATH_PCM;
90 }
91 
92 /*******************************************************************************
93  *
94  * Function         btm_esco_conn_rsp
95  *
96  * Description      This function is called upon receipt of an (e)SCO connection
97  *                  request event (BTM_ESCO_CONN_REQ_EVT) to accept or reject
98  *                  the request. Parameters used to negotiate eSCO links.
99  *                  If p_parms is NULL, then default values are used.
100  *                  If the link type of the incoming request is SCO, then only
101  *                  the tx_bw, max_latency, content format, and packet_types are
102  *                  valid.  The hci_status parameter should be
103  *                  ([0x0] to accept, [0x0d..0x0f] to reject)
104  *
105  * Returns          void
106  *
107  ******************************************************************************/
btm_esco_conn_rsp(uint16_t sco_inx,uint8_t hci_status,const RawAddress & bda,enh_esco_params_t * p_parms)108 static void btm_esco_conn_rsp(uint16_t sco_inx, uint8_t hci_status,
109                               const RawAddress& bda,
110                               enh_esco_params_t* p_parms) {
111 #if (BTM_MAX_SCO_LINKS > 0)
112   tSCO_CONN* p_sco = NULL;
113 
114   if (sco_inx < BTM_MAX_SCO_LINKS) p_sco = &btm_cb.sco_cb.sco_db[sco_inx];
115 
116   /* Reject the connect request if refused by caller or wrong state */
117   if (hci_status != HCI_SUCCESS || p_sco == NULL) {
118     if (p_sco) {
119       p_sco->state = (p_sco->state == SCO_ST_W4_CONN_RSP) ? SCO_ST_LISTENING
120                                                           : SCO_ST_UNUSED;
121     }
122     if (!btm_cb.sco_cb.esco_supported) {
123       btsnd_hcic_reject_conn(bda, hci_status);
124     } else {
125       btsnd_hcic_reject_esco_conn(bda, hci_status);
126     }
127   } else {
128     /* Connection is being accepted */
129     p_sco->state = SCO_ST_CONNECTING;
130     enh_esco_params_t* p_setup = &p_sco->esco.setup;
131     /* If parameters not specified use the default */
132     if (p_parms) {
133       *p_setup = *p_parms;
134     } else {
135       /* Use the last setup passed thru BTM_SetEscoMode (or defaults) */
136       *p_setup = btm_cb.sco_cb.def_esco_parms;
137     }
138 
139     uint16_t temp_packet_types =
140         (p_setup->packet_types & BTM_SCO_SUPPORTED_PKTS_MASK &
141          btm_cb.btm_sco_pkt_types_supported);
142 
143     /* Make sure at least one eSCO packet type is sent, else might confuse peer
144      */
145     /* Taking this out to confirm with BQB tests
146     ** Real application would like to include this though, as many devices
147     ** do not retry with SCO only if an eSCO connection fails.
148     if (!(temp_packet_types & BTM_ESCO_LINK_ONLY_MASK))
149     {
150         temp_packet_types |= BTM_SCO_PKT_TYPES_MASK_EV3;
151     }
152     */
153     /* If SCO request, remove eSCO packet types (conformance) */
154     if (p_sco->esco.data.link_type == BTM_LINK_TYPE_SCO) {
155       temp_packet_types &= BTM_SCO_LINK_ONLY_MASK;
156       temp_packet_types |= BTM_SCO_EXCEPTION_PKTS_MASK;
157     } else {
158       /* OR in any exception packet types */
159       temp_packet_types |=
160           ((p_setup->packet_types & BTM_SCO_EXCEPTION_PKTS_MASK) |
161            (btm_cb.btm_sco_pkt_types_supported & BTM_SCO_EXCEPTION_PKTS_MASK));
162     }
163 
164     /* Use Enhanced Synchronous commands if supported */
165     if (controller_get_interface()
166             ->supports_enhanced_setup_synchronous_connection()) {
167       /* Use the saved SCO routing */
168       p_setup->input_data_path = p_setup->output_data_path =
169           btm_cb.sco_cb.sco_route;
170 
171       BTM_TRACE_DEBUG(
172           "%s: txbw 0x%x, rxbw 0x%x, lat 0x%x, retrans 0x%02x, "
173           "pkt 0x%04x, path %u",
174           __func__, p_setup->transmit_bandwidth, p_setup->receive_bandwidth,
175           p_setup->max_latency_ms, p_setup->retransmission_effort,
176           p_setup->packet_types, p_setup->input_data_path);
177 
178       btsnd_hcic_enhanced_accept_synchronous_connection(bda, p_setup);
179 
180     } else {
181       /* Use legacy command if enhanced SCO setup is not supported */
182       uint16_t voice_content_format = btm_sco_voice_settings_to_legacy(p_setup);
183       btsnd_hcic_accept_esco_conn(
184           bda, p_setup->transmit_bandwidth, p_setup->receive_bandwidth,
185           p_setup->max_latency_ms, voice_content_format,
186           p_setup->retransmission_effort, p_setup->packet_types);
187     }
188   }
189 #endif
190 }
191 
192 /*******************************************************************************
193  *
194  * Function         btm_route_sco_data
195  *
196  * Description      Route received SCO data.
197  *
198  * Returns          void
199  *
200  ******************************************************************************/
btm_route_sco_data(BT_HDR * p_msg)201 void btm_route_sco_data(BT_HDR* p_msg) {
202   osi_free(p_msg);
203 }
204 
205 /*******************************************************************************
206  *
207  * Function         BTM_WriteScoData
208  *
209  * Description      This function write SCO data to a specified instance. The
210  *                  data to be written p_buf needs to carry an offset of
211  *                  HCI_SCO_PREAMBLE_SIZE bytes, and the data length can not
212  *                  exceed BTM_SCO_DATA_SIZE_MAX bytes, whose default value is
213  *                  set to 60 and is configurable. Data longer than the maximum
214  *                  bytes will be truncated.
215  *
216  * Returns          BTM_SUCCESS: data write is successful
217  *                  BTM_ILLEGAL_VALUE: SCO data contains illegal offset value.
218  *                  BTM_SCO_BAD_LENGTH: SCO data length exceeds the max SCO
219  *                                      packet size.
220  *                  BTM_NO_RESOURCES: no resources.
221  *                  BTM_UNKNOWN_ADDR: unknown SCO connection handle, or SCO is
222  *                                    not routed via HCI.
223  *
224  *
225  ******************************************************************************/
BTM_WriteScoData(UNUSED_ATTR uint16_t sco_inx,UNUSED_ATTR BT_HDR * p_buf)226 tBTM_STATUS BTM_WriteScoData(UNUSED_ATTR uint16_t sco_inx,
227                              UNUSED_ATTR BT_HDR* p_buf) {
228   return (BTM_NO_RESOURCES);
229 }
230 
231 #if (BTM_MAX_SCO_LINKS > 0)
232 /*******************************************************************************
233  *
234  * Function         btm_send_connect_request
235  *
236  * Description      This function is called to respond to SCO connect
237  *                  indications
238  *
239  * Returns          void
240  *
241  ******************************************************************************/
btm_send_connect_request(uint16_t acl_handle,enh_esco_params_t * p_setup)242 static tBTM_STATUS btm_send_connect_request(uint16_t acl_handle,
243                                             enh_esco_params_t* p_setup) {
244   tACL_CONN* p_acl;
245 
246   /* Send connect request depending on version of spec */
247   if (!btm_cb.sco_cb.esco_supported) {
248     LOG(INFO) << __func__ << ": sending non-eSCO request for handle="
249               << unsigned(acl_handle);
250     btsnd_hcic_add_SCO_conn(acl_handle, BTM_ESCO_2_SCO(p_setup->packet_types));
251   } else {
252     uint16_t temp_packet_types =
253         (p_setup->packet_types &
254          static_cast<uint16_t>(BTM_SCO_SUPPORTED_PKTS_MASK) &
255          btm_cb.btm_sco_pkt_types_supported);
256 
257     /* OR in any exception packet types */
258     temp_packet_types |=
259         ((p_setup->packet_types & BTM_SCO_EXCEPTION_PKTS_MASK) |
260          (btm_cb.btm_sco_pkt_types_supported & BTM_SCO_EXCEPTION_PKTS_MASK));
261 
262     /* Finally, remove EDR eSCO if the remote device doesn't support it */
263     /* UPF25:  Only SCO was brought up in this case */
264     btm_handle_to_acl_index(acl_handle);
265     uint8_t acl_index = btm_handle_to_acl_index(acl_handle);
266     if (acl_index < MAX_L2CAP_LINKS) {
267       p_acl = &btm_cb.acl_db[acl_index];
268       if (!HCI_EDR_ESCO_2MPS_SUPPORTED(p_acl->peer_lmp_feature_pages[0])) {
269         BTM_TRACE_DEBUG("BTM Remote does not support 2-EDR eSCO");
270         temp_packet_types |=
271             (ESCO_PKT_TYPES_MASK_NO_2_EV3 | ESCO_PKT_TYPES_MASK_NO_2_EV5);
272       }
273       if (!HCI_EDR_ESCO_3MPS_SUPPORTED(p_acl->peer_lmp_feature_pages[0])) {
274         BTM_TRACE_DEBUG("BTM Remote does not support 3-EDR eSCO");
275         temp_packet_types |=
276             (ESCO_PKT_TYPES_MASK_NO_3_EV3 | ESCO_PKT_TYPES_MASK_NO_3_EV5);
277       }
278 
279       /* Check to see if BR/EDR Secure Connections is being used
280       ** If so, we cannot use SCO-only packet types (HFP 1.7)
281       */
282       if (BTM_BothEndsSupportSecureConnections(p_acl->remote_addr)) {
283         temp_packet_types &= ~(BTM_SCO_PKT_TYPE_MASK);
284         BTM_TRACE_DEBUG("%s: SCO Conn: pkt_types after removing SCO (0x%04x)",
285                         __func__, temp_packet_types);
286 
287         /* Return error if no packet types left */
288         if (temp_packet_types == 0) {
289           LOG(ERROR) << __func__
290                      << ": SCO Conn (BR/EDR SC): No packet types available for "
291                         "acl_handle "
292                      << unsigned(acl_handle);
293           return (BTM_WRONG_MODE);
294         }
295       } else {
296         LOG(WARNING) << __func__
297                      << ": SCO Conn(BR/EDR SC):local or peer does not support "
298                         "BR/EDR SC for acl_handle "
299                      << unsigned(acl_handle);
300       }
301     } else {
302       LOG(ERROR) << __func__ << ": acl_index " << unsigned(acl_index)
303                  << " out of range for acl_handle " << unsigned(acl_handle);
304     }
305 
306     /* Save the previous types in case command fails */
307     uint16_t saved_packet_types = p_setup->packet_types;
308     p_setup->packet_types = temp_packet_types;
309 
310     /* Use Enhanced Synchronous commands if supported */
311     if (controller_get_interface()
312             ->supports_enhanced_setup_synchronous_connection()) {
313       /* Use the saved SCO routing */
314       p_setup->input_data_path = p_setup->output_data_path =
315           btm_cb.sco_cb.sco_route;
316       LOG(INFO) << __func__ << std::hex << ": enhanced parameter list"
317                 << " txbw=0x" << unsigned(p_setup->transmit_bandwidth)
318                 << ", rxbw=0x" << unsigned(p_setup->receive_bandwidth)
319                 << ", latency_ms=0x" << unsigned(p_setup->max_latency_ms)
320                 << ", retransmit_effort=0x"
321                 << unsigned(p_setup->retransmission_effort) << ", pkt_type=0x"
322                 << unsigned(p_setup->packet_types) << ", path=0x"
323                 << unsigned(p_setup->input_data_path);
324       btsnd_hcic_enhanced_set_up_synchronous_connection(acl_handle, p_setup);
325       p_setup->packet_types = saved_packet_types;
326     } else { /* Use older command */
327       uint16_t voice_content_format = btm_sco_voice_settings_to_legacy(p_setup);
328       LOG(INFO) << __func__ << std::hex << ": legacy parameter list"
329                 << " txbw=0x" << unsigned(p_setup->transmit_bandwidth)
330                 << ", rxbw=0x" << unsigned(p_setup->receive_bandwidth)
331                 << ", latency_ms=0x" << unsigned(p_setup->max_latency_ms)
332                 << ", retransmit_effort=0x"
333                 << unsigned(p_setup->retransmission_effort)
334                 << ", voice_content_format=0x" << unsigned(voice_content_format)
335                 << ", pkt_type=0x" << unsigned(p_setup->packet_types);
336       btsnd_hcic_setup_esco_conn(
337           acl_handle, p_setup->transmit_bandwidth, p_setup->receive_bandwidth,
338           p_setup->max_latency_ms, voice_content_format,
339           p_setup->retransmission_effort, p_setup->packet_types);
340     }
341   }
342 
343   return (BTM_CMD_STARTED);
344 }
345 #endif
346 
347 /*******************************************************************************
348  *
349  * Function         btm_set_sco_ind_cback
350  *
351  * Description      This function is called to register for TCS SCO connect
352  *                  indications.
353  *
354  * Returns          void
355  *
356  ******************************************************************************/
btm_set_sco_ind_cback(tBTM_SCO_IND_CBACK * sco_ind_cb)357 void btm_set_sco_ind_cback(tBTM_SCO_IND_CBACK* sco_ind_cb) {
358   btm_cb.sco_cb.app_sco_ind_cb = sco_ind_cb;
359 }
360 
361 /*******************************************************************************
362  *
363  * Function         btm_accept_sco_link
364  *
365  * Description      This function is called to respond to TCS SCO connect
366  *                  indications
367  *
368  * Returns          void
369  *
370  ******************************************************************************/
btm_accept_sco_link(uint16_t sco_inx,enh_esco_params_t * p_setup,tBTM_SCO_CB * p_conn_cb,tBTM_SCO_CB * p_disc_cb)371 void btm_accept_sco_link(uint16_t sco_inx, enh_esco_params_t* p_setup,
372                          tBTM_SCO_CB* p_conn_cb, tBTM_SCO_CB* p_disc_cb) {
373 #if (BTM_MAX_SCO_LINKS > 0)
374   tSCO_CONN* p_sco;
375 
376   if (sco_inx >= BTM_MAX_SCO_LINKS) {
377     BTM_TRACE_ERROR("btm_accept_sco_link: Invalid sco_inx(%d)", sco_inx);
378     return;
379   }
380 
381   /* Link role is ignored in for this message */
382   p_sco = &btm_cb.sco_cb.sco_db[sco_inx];
383   p_sco->p_conn_cb = p_conn_cb;
384   p_sco->p_disc_cb = p_disc_cb;
385   p_sco->esco.data.link_type =
386       BTM_LINK_TYPE_ESCO; /* Accept with all supported types */
387 
388   BTM_TRACE_DEBUG("TCS accept SCO: Packet Types 0x%04x", p_setup->packet_types);
389 
390   btm_esco_conn_rsp(sco_inx, HCI_SUCCESS, p_sco->esco.data.bd_addr, p_setup);
391 #else
392   btm_reject_sco_link(sco_inx);
393 #endif
394 }
395 
396 /*******************************************************************************
397  *
398  * Function         btm_reject_sco_link
399  *
400  * Description      This function is called to respond to SCO connect
401  *                  indications
402  *
403  * Returns          void
404  *
405  ******************************************************************************/
btm_reject_sco_link(uint16_t sco_inx)406 void btm_reject_sco_link(uint16_t sco_inx) {
407   btm_esco_conn_rsp(sco_inx, HCI_ERR_HOST_REJECT_RESOURCES,
408                     btm_cb.sco_cb.sco_db[sco_inx].esco.data.bd_addr, NULL);
409 }
410 
411 /*******************************************************************************
412  *
413  * Function         BTM_CreateSco
414  *
415  * Description      This function is called to create an SCO connection. If the
416  *                  "is_orig" flag is true, the connection will be originated,
417  *                  otherwise BTM will wait for the other side to connect.
418  *
419  *                  NOTE:  If BTM_IGNORE_SCO_PKT_TYPE is passed in the pkt_types
420  *                      parameter the default packet types is used.
421  *
422  * Returns          BTM_UNKNOWN_ADDR if the ACL connection is not up
423  *                  BTM_BUSY         if another SCO being set up to
424  *                                   the same BD address
425  *                  BTM_NO_RESOURCES if the max SCO limit has been reached
426  *                  BTM_CMD_STARTED  if the connection establishment is started.
427  *                                   In this case, "*p_sco_inx" is filled in
428  *                                   with the sco index used for the connection.
429  *
430  ******************************************************************************/
BTM_CreateSco(const RawAddress * remote_bda,bool is_orig,uint16_t pkt_types,uint16_t * p_sco_inx,tBTM_SCO_CB * p_conn_cb,tBTM_SCO_CB * p_disc_cb)431 tBTM_STATUS BTM_CreateSco(const RawAddress* remote_bda, bool is_orig,
432                           uint16_t pkt_types, uint16_t* p_sco_inx,
433                           tBTM_SCO_CB* p_conn_cb, tBTM_SCO_CB* p_disc_cb) {
434 #if (BTM_MAX_SCO_LINKS > 0)
435   enh_esco_params_t* p_setup;
436   tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0];
437   uint16_t xx;
438   uint16_t acl_handle = 0;
439   tACL_CONN* p_acl;
440   *p_sco_inx = BTM_INVALID_SCO_INDEX;
441 
442   /* If originating, ensure that there is an ACL connection to the BD Address */
443 
444   if (is_orig) {
445     if (!remote_bda) {
446       LOG(ERROR) << __func__ << ": remote_bda is null";
447       return BTM_ILLEGAL_VALUE;
448     }
449     acl_handle = BTM_GetHCIConnHandle(*remote_bda, BT_TRANSPORT_BR_EDR);
450     if (acl_handle == 0xFFFF) {
451       LOG(ERROR) << __func__ << ": cannot find ACL handle for remote device "
452                  << remote_bda;
453       return BTM_UNKNOWN_ADDR;
454     }
455   }
456 
457   if (remote_bda) {
458     /* If any SCO is being established to the remote BD address, refuse this */
459     for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
460       if (((p->state == SCO_ST_CONNECTING) || (p->state == SCO_ST_LISTENING) ||
461            (p->state == SCO_ST_PEND_UNPARK)) &&
462           (p->esco.data.bd_addr == *remote_bda)) {
463         LOG(ERROR) << __func__ << ": a sco connection is already going on for "
464                    << *remote_bda << ", at state " << unsigned(p->state);
465         return BTM_BUSY;
466       }
467     }
468   } else {
469     /* Support only 1 wildcard BD address at a time */
470     for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
471       if ((p->state == SCO_ST_LISTENING) && (!p->rem_bd_known)) {
472         LOG(ERROR)
473             << __func__
474             << ": remote_bda is null and not known and we are still listening";
475         return BTM_BUSY;
476       }
477     }
478   }
479 
480   /* Try to find an unused control block, and kick off the SCO establishment */
481   for (xx = 0, p = &btm_cb.sco_cb.sco_db[0]; xx < BTM_MAX_SCO_LINKS;
482        xx++, p++) {
483     if (p->state == SCO_ST_UNUSED) {
484       if (remote_bda) {
485         if (is_orig) {
486           // can not create SCO link if in park mode
487           tBTM_PM_STATE state;
488           if ((btm_read_power_mode_state(*remote_bda, &state) == BTM_SUCCESS)) {
489             if (state == BTM_PM_ST_SNIFF || state == BTM_PM_ST_PARK ||
490                 state == BTM_PM_ST_PENDING) {
491               LOG(INFO) << __func__ << ": " << *remote_bda
492                         << " in sniff, park or pending mode "
493                         << unsigned(state);
494               tBTM_PM_PWR_MD pm = {};
495               pm.mode = BTM_PM_MD_ACTIVE;
496               BTM_SetPowerMode(BTM_PM_SET_ONLY_ID, *remote_bda, &pm);
497               p->state = SCO_ST_PEND_UNPARK;
498             }
499           } else {
500             LOG(ERROR) << __func__ << ": failed to read power mode for "
501                        << *remote_bda;
502           }
503         }
504         p->esco.data.bd_addr = *remote_bda;
505         p->rem_bd_known = true;
506       } else
507         p->rem_bd_known = false;
508 
509       p_setup = &p->esco.setup;
510       *p_setup = btm_cb.sco_cb.def_esco_parms;
511 
512       /* Determine the packet types */
513       p_setup->packet_types = pkt_types & BTM_SCO_SUPPORTED_PKTS_MASK &
514                               btm_cb.btm_sco_pkt_types_supported;
515       /* OR in any exception packet types */
516       if (controller_get_interface()->get_bt_version()->hci_version >=
517           HCI_PROTO_VERSION_2_0) {
518         p_setup->packet_types |=
519             (pkt_types & BTM_SCO_EXCEPTION_PKTS_MASK) |
520             (btm_cb.btm_sco_pkt_types_supported & BTM_SCO_EXCEPTION_PKTS_MASK);
521       }
522 
523       p->p_conn_cb = p_conn_cb;
524       p->p_disc_cb = p_disc_cb;
525       p->hci_handle = BTM_INVALID_HCI_HANDLE;
526       p->is_orig = is_orig;
527 
528       if (p->state != SCO_ST_PEND_UNPARK) {
529         if (is_orig) {
530           /* If role change is in progress, do not proceed with SCO setup
531            * Wait till role change is complete */
532           p_acl = btm_bda_to_acl(*remote_bda, BT_TRANSPORT_BR_EDR);
533           if (p_acl && p_acl->switch_role_state != BTM_ACL_SWKEY_STATE_IDLE) {
534             BTM_TRACE_API("Role Change is in progress for ACL handle 0x%04x",
535                           acl_handle);
536             p->state = SCO_ST_PEND_ROLECHANGE;
537           }
538         }
539       }
540 
541       if (p->state != SCO_ST_PEND_UNPARK &&
542           p->state != SCO_ST_PEND_ROLECHANGE) {
543         if (is_orig) {
544           BTM_TRACE_API("%s:(e)SCO Link for ACL handle 0x%04x", __func__,
545                         acl_handle);
546 
547           if ((btm_send_connect_request(acl_handle, p_setup)) !=
548               BTM_CMD_STARTED) {
549             LOG(ERROR) << __func__ << ": failed to send connect request for "
550                        << *remote_bda;
551             return (BTM_NO_RESOURCES);
552           }
553 
554           p->state = SCO_ST_CONNECTING;
555         } else {
556           BTM_TRACE_API("%s:(e)SCO listening for ACL handle 0x%04x", __func__,
557                         acl_handle);
558           p->state = SCO_ST_LISTENING;
559         }
560       }
561 
562       *p_sco_inx = xx;
563       BTM_TRACE_API("%s: BTM_CreateSco succeeded", __func__);
564       return BTM_CMD_STARTED;
565     }
566   }
567 
568 #endif
569   /* If here, all SCO blocks in use */
570   LOG(ERROR) << __func__ << ": all SCO control blocks are in use";
571   return BTM_NO_RESOURCES;
572 }
573 
574 /*******************************************************************************
575  *
576  * Function         btm_sco_chk_pend_unpark
577  *
578  * Description      This function is called by BTIF when there is a mode change
579  *                  event to see if there are SCO commands waiting for the
580  *                  unpark.
581  *
582  * Returns          void
583  *
584  ******************************************************************************/
btm_sco_chk_pend_unpark(uint8_t hci_status,uint16_t hci_handle)585 void btm_sco_chk_pend_unpark(uint8_t hci_status, uint16_t hci_handle) {
586 #if (BTM_MAX_SCO_LINKS > 0)
587   tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0];
588   for (uint16_t xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
589     uint16_t acl_handle =
590         BTM_GetHCIConnHandle(p->esco.data.bd_addr, BT_TRANSPORT_BR_EDR);
591     if ((p->state == SCO_ST_PEND_UNPARK) && (acl_handle == hci_handle)) {
592       LOG(INFO) << __func__ << ": " << p->esco.data.bd_addr
593                 << " unparked, sending connection request, acl_handle="
594                 << unsigned(acl_handle)
595                 << ", hci_status=" << unsigned(hci_status);
596       if (btm_send_connect_request(acl_handle, &p->esco.setup) ==
597           BTM_CMD_STARTED) {
598         p->state = SCO_ST_CONNECTING;
599       } else {
600         LOG(ERROR) << __func__ << ": failed to send connection request for "
601                    << p->esco.data.bd_addr;
602       }
603     }
604   }
605 #endif  // BTM_MAX_SCO_LINKS
606 }
607 
608 /*******************************************************************************
609  *
610  * Function         btm_sco_chk_pend_rolechange
611  *
612  * Description      This function is called by BTIF when there is a role change
613  *                  event to see if there are SCO commands waiting for the role
614  *                  change.
615  *
616  * Returns          void
617  *
618  ******************************************************************************/
btm_sco_chk_pend_rolechange(uint16_t hci_handle)619 void btm_sco_chk_pend_rolechange(uint16_t hci_handle) {
620 #if (BTM_MAX_SCO_LINKS > 0)
621   uint16_t xx;
622   uint16_t acl_handle;
623   tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0];
624 
625   for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
626     if ((p->state == SCO_ST_PEND_ROLECHANGE) &&
627         ((acl_handle = BTM_GetHCIConnHandle(
628               p->esco.data.bd_addr, BT_TRANSPORT_BR_EDR)) == hci_handle))
629 
630     {
631       BTM_TRACE_API(
632           "btm_sco_chk_pend_rolechange -> (e)SCO Link for ACL handle 0x%04x",
633           acl_handle);
634 
635       if ((btm_send_connect_request(acl_handle, &p->esco.setup)) ==
636           BTM_CMD_STARTED)
637         p->state = SCO_ST_CONNECTING;
638     }
639   }
640 #endif
641 }
642 
643 /*******************************************************************************
644  *
645  * Function        btm_sco_disc_chk_pend_for_modechange
646  *
647  * Description     This function is called by btm when there is a mode change
648  *                 event to see if there are SCO  disconnect commands waiting
649  *                 for the mode change.
650  *
651  * Returns         void
652  *
653  ******************************************************************************/
btm_sco_disc_chk_pend_for_modechange(uint16_t hci_handle)654 void btm_sco_disc_chk_pend_for_modechange(uint16_t hci_handle) {
655 #if (BTM_MAX_SCO_LINKS > 0)
656   tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0];
657 
658   BTM_TRACE_DEBUG("%s: hci_handle 0x%04x, p->state 0x%02x", __func__,
659                   hci_handle, p->state);
660 
661   for (uint16_t xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
662     if ((p->state == SCO_ST_PEND_MODECHANGE) &&
663         (BTM_GetHCIConnHandle(p->esco.data.bd_addr, BT_TRANSPORT_BR_EDR)) ==
664             hci_handle)
665 
666     {
667       BTM_TRACE_DEBUG("%s: SCO Link handle 0x%04x", __func__, p->hci_handle);
668       BTM_RemoveSco(xx);
669     }
670   }
671 #endif
672 }
673 
674 /*******************************************************************************
675  *
676  * Function         btm_sco_conn_req
677  *
678  * Description      This function is called by BTU HCIF when an SCO connection
679  *                  request is received from a remote.
680  *
681  * Returns          void
682  *
683  ******************************************************************************/
btm_sco_conn_req(const RawAddress & bda,DEV_CLASS dev_class,uint8_t link_type)684 void btm_sco_conn_req(const RawAddress& bda, DEV_CLASS dev_class,
685                       uint8_t link_type) {
686 #if (BTM_MAX_SCO_LINKS > 0)
687   tSCO_CB* p_sco = &btm_cb.sco_cb;
688   tSCO_CONN* p = &p_sco->sco_db[0];
689   tBTM_ESCO_CONN_REQ_EVT_DATA evt_data = {};
690 
691   for (uint16_t sco_index = 0; sco_index < BTM_MAX_SCO_LINKS;
692        sco_index++, p++) {
693     /*
694      * If the sco state is in the SCO_ST_CONNECTING state, we still need
695      * to return accept sco to avoid race conditon for sco creation
696      */
697     bool rem_bd_matches = p->rem_bd_known && p->esco.data.bd_addr == bda;
698     if (((p->state == SCO_ST_CONNECTING) && rem_bd_matches) ||
699         ((p->state == SCO_ST_LISTENING) &&
700          (rem_bd_matches || !p->rem_bd_known))) {
701       /* If this guy was a wildcard, he is not one any more */
702       p->rem_bd_known = true;
703       p->esco.data.link_type = link_type;
704       p->state = SCO_ST_W4_CONN_RSP;
705       p->esco.data.bd_addr = bda;
706 
707       /* If no callback, auto-accept the connection if packet types match */
708       if (!p->esco.p_esco_cback) {
709         /* If requesting eSCO reject if default parameters are SCO only */
710         if ((link_type == BTM_LINK_TYPE_ESCO &&
711              !(p_sco->def_esco_parms.packet_types & BTM_ESCO_LINK_ONLY_MASK) &&
712              ((p_sco->def_esco_parms.packet_types &
713                BTM_SCO_EXCEPTION_PKTS_MASK) == BTM_SCO_EXCEPTION_PKTS_MASK))
714 
715             /* Reject request if SCO is desired but no SCO packets delected */
716             ||
717             (link_type == BTM_LINK_TYPE_SCO &&
718              !(p_sco->def_esco_parms.packet_types & BTM_SCO_LINK_ONLY_MASK))) {
719           btm_esco_conn_rsp(sco_index, HCI_ERR_HOST_REJECT_RESOURCES, bda,
720                             nullptr);
721         } else {
722           /* Accept the request */
723           btm_esco_conn_rsp(sco_index, HCI_SUCCESS, bda, nullptr);
724         }
725       } else {
726         /* Notify upper layer of connect indication */
727         evt_data.bd_addr = bda;
728         memcpy(evt_data.dev_class, dev_class, DEV_CLASS_LEN);
729         evt_data.link_type = link_type;
730         evt_data.sco_inx = sco_index;
731         tBTM_ESCO_EVT_DATA btm_esco_evt_data = {};
732         btm_esco_evt_data.conn_evt = evt_data;
733         p->esco.p_esco_cback(BTM_ESCO_CONN_REQ_EVT, &btm_esco_evt_data);
734       }
735 
736       return;
737     }
738   }
739 
740   /* TCS usage */
741   if (btm_cb.sco_cb.app_sco_ind_cb) {
742     /* Now, try to find an unused control block */
743     uint16_t sco_index;
744     for (sco_index = 0, p = &btm_cb.sco_cb.sco_db[0];
745          sco_index < BTM_MAX_SCO_LINKS; sco_index++, p++) {
746       if (p->state == SCO_ST_UNUSED) {
747         p->is_orig = false;
748         p->state = SCO_ST_LISTENING;
749 
750         p->esco.data.link_type = link_type;
751         p->esco.data.bd_addr = bda;
752         p->rem_bd_known = true;
753         break;
754       }
755     }
756     if (sco_index < BTM_MAX_SCO_LINKS) {
757       btm_cb.sco_cb.app_sco_ind_cb(sco_index);
758       return;
759     }
760   }
761 
762 #endif
763   /* If here, no one wants the SCO connection. Reject it */
764   BTM_TRACE_WARNING("%s: rejecting SCO for %s", __func__,
765                     bda.ToString().c_str());
766   btm_esco_conn_rsp(BTM_MAX_SCO_LINKS, HCI_ERR_HOST_REJECT_RESOURCES, bda,
767                     nullptr);
768 }
769 
770 /*******************************************************************************
771  *
772  * Function         btm_sco_connected
773  *
774  * Description      This function is called by BTIF when an (e)SCO connection
775  *                  is connected.
776  *
777  * Returns          void
778  *
779  ******************************************************************************/
btm_sco_connected(uint8_t hci_status,const RawAddress * bda,uint16_t hci_handle,tBTM_ESCO_DATA * p_esco_data)780 void btm_sco_connected(uint8_t hci_status, const RawAddress* bda,
781                        uint16_t hci_handle, tBTM_ESCO_DATA* p_esco_data) {
782 #if (BTM_MAX_SCO_LINKS > 0)
783   tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0];
784   uint16_t xx;
785   bool spt = false;
786   tBTM_CHG_ESCO_PARAMS parms = {};
787 #endif
788 
789   btm_cb.sco_cb.sco_disc_reason = hci_status;
790 
791 #if (BTM_MAX_SCO_LINKS > 0)
792   for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
793     if (((p->state == SCO_ST_CONNECTING) || (p->state == SCO_ST_LISTENING) ||
794          (p->state == SCO_ST_W4_CONN_RSP)) &&
795         (p->rem_bd_known) && (!bda || p->esco.data.bd_addr == *bda)) {
796       if (hci_status != HCI_SUCCESS) {
797         /* Report the error if originator, otherwise remain in Listen mode */
798         if (p->is_orig) {
799           /* If role switch is pending, we need try again after role switch is
800            * complete */
801           if (hci_status == HCI_ERR_ROLE_SWITCH_PENDING) {
802             BTM_TRACE_API("Role Change pending for HCI handle 0x%04x",
803                           hci_handle);
804             p->state = SCO_ST_PEND_ROLECHANGE;
805           }
806           /* avoid calling disconnect callback because of sco creation race */
807           else if (hci_status != HCI_ERR_LMP_ERR_TRANS_COLLISION) {
808             p->state = SCO_ST_UNUSED;
809             (*p->p_disc_cb)(xx);
810           }
811         } else {
812           /* Notify the upper layer that incoming sco connection has failed. */
813           if (p->state == SCO_ST_CONNECTING) {
814             p->state = SCO_ST_UNUSED;
815             (*p->p_disc_cb)(xx);
816           } else
817             p->state = SCO_ST_LISTENING;
818         }
819 
820         return;
821       }
822 
823       if (p->state == SCO_ST_LISTENING) spt = true;
824 
825       p->state = SCO_ST_CONNECTED;
826       p->hci_handle = hci_handle;
827 
828       if (!btm_cb.sco_cb.esco_supported) {
829         p->esco.data.link_type = BTM_LINK_TYPE_SCO;
830         if (spt) {
831           parms.packet_types = p->esco.setup.packet_types;
832           /* Keep the other parameters the same for SCO */
833           parms.max_latency_ms = p->esco.setup.max_latency_ms;
834           parms.retransmission_effort = p->esco.setup.retransmission_effort;
835 
836           BTM_ChangeEScoLinkParms(xx, &parms);
837         }
838       } else {
839         if (p_esco_data) p->esco.data = *p_esco_data;
840       }
841 
842       (*p->p_conn_cb)(xx);
843 
844       return;
845     }
846   }
847 #endif
848 }
849 
850 /*******************************************************************************
851  *
852  * Function         btm_find_scb_by_handle
853  *
854  * Description      Look through all active SCO connection for a match based on
855  *                  the HCI handle.
856  *
857  * Returns          index to matched SCO connection CB, or BTM_MAX_SCO_LINKS if
858  *                  no match.
859  *
860  ******************************************************************************/
btm_find_scb_by_handle(uint16_t handle)861 uint16_t btm_find_scb_by_handle(uint16_t handle) {
862   int xx;
863   tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0];
864 
865   for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
866     if ((p->state == SCO_ST_CONNECTED) && (p->hci_handle == handle)) {
867       return (xx);
868     }
869   }
870 
871   /* If here, no match found */
872   return (xx);
873 }
874 
875 /*******************************************************************************
876  *
877  * Function         BTM_RemoveSco
878  *
879  * Description      This function is called to remove a specific SCO connection.
880  *
881  * Returns          status of the operation
882  *
883  ******************************************************************************/
BTM_RemoveSco(uint16_t sco_inx)884 tBTM_STATUS BTM_RemoveSco(uint16_t sco_inx) {
885 #if (BTM_MAX_SCO_LINKS > 0)
886   tSCO_CONN* p = &btm_cb.sco_cb.sco_db[sco_inx];
887   uint16_t tempstate;
888   tBTM_PM_STATE state = BTM_PM_ST_INVALID;
889 
890   BTM_TRACE_DEBUG("%s", __func__);
891 
892   /* Validity check */
893   if ((sco_inx >= BTM_MAX_SCO_LINKS) || (p->state == SCO_ST_UNUSED))
894     return (BTM_UNKNOWN_ADDR);
895 
896   /* If no HCI handle, simply drop the connection and return */
897   if (p->hci_handle == BTM_INVALID_HCI_HANDLE ||
898       p->state == SCO_ST_PEND_UNPARK) {
899     p->hci_handle = BTM_INVALID_HCI_HANDLE;
900     p->state = SCO_ST_UNUSED;
901     p->esco.p_esco_cback = NULL; /* Deregister the eSCO event callback */
902     return (BTM_SUCCESS);
903   }
904 
905   if ((btm_read_power_mode_state(p->esco.data.bd_addr, &state) ==
906        BTM_SUCCESS) &&
907       state == BTM_PM_ST_PENDING) {
908     BTM_TRACE_DEBUG("%s: BTM_PM_ST_PENDING for ACL mapped with SCO Link 0x%04x",
909                     __func__, p->hci_handle);
910     p->state = SCO_ST_PEND_MODECHANGE;
911     return (BTM_CMD_STARTED);
912   }
913 
914   tempstate = p->state;
915   p->state = SCO_ST_DISCONNECTING;
916 
917   btsnd_hcic_disconnect(p->hci_handle, HCI_ERR_PEER_USER);
918 
919   return (BTM_CMD_STARTED);
920 #else
921   return (BTM_NO_RESOURCES);
922 #endif
923 }
924 
925 /*******************************************************************************
926  *
927  * Function         btm_remove_sco_links
928  *
929  * Description      This function is called to remove all sco links for an ACL
930  *                  link.
931  *
932  * Returns          void
933  *
934  ******************************************************************************/
btm_remove_sco_links(const RawAddress & bda)935 void btm_remove_sco_links(const RawAddress& bda) {
936 #if (BTM_MAX_SCO_LINKS > 0)
937   tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0];
938   uint16_t xx;
939 
940   for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
941     if (p->rem_bd_known && p->esco.data.bd_addr == bda) {
942       BTM_RemoveSco(xx);
943     }
944   }
945 #endif
946 }
947 
948 /*******************************************************************************
949  *
950  * Function         btm_sco_removed
951  *
952  * Description      This function is called by BTIF when an SCO connection
953  *                  is removed.
954  *
955  * Returns          void
956  *
957  ******************************************************************************/
btm_sco_removed(uint16_t hci_handle,uint8_t reason)958 void btm_sco_removed(uint16_t hci_handle, uint8_t reason) {
959 #if (BTM_MAX_SCO_LINKS > 0)
960   tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0];
961   uint16_t xx;
962 #endif
963 
964   btm_cb.sco_cb.sco_disc_reason = reason;
965 
966 #if (BTM_MAX_SCO_LINKS > 0)
967   p = &btm_cb.sco_cb.sco_db[0];
968   for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
969     if ((p->state != SCO_ST_UNUSED) && (p->state != SCO_ST_LISTENING) &&
970         (p->hci_handle == hci_handle)) {
971       btm_sco_flush_sco_data(xx);
972 
973       p->state = SCO_ST_UNUSED;
974       p->hci_handle = BTM_INVALID_HCI_HANDLE;
975       p->rem_bd_known = false;
976       p->esco.p_esco_cback = NULL; /* Deregister eSCO callback */
977       (*p->p_disc_cb)(xx);
978 
979       return;
980     }
981   }
982 #endif
983 }
984 
985 /*******************************************************************************
986  *
987  * Function         btm_sco_acl_removed
988  *
989  * Description      This function is called when an ACL connection is
990  *                  removed. If the BD address is NULL, it is assumed that
991  *                  the local device is down, and all SCO links are removed.
992  *                  If a specific BD address is passed, only SCO connections
993  *                  to that BD address are removed.
994  *
995  * Returns          void
996  *
997  ******************************************************************************/
btm_sco_acl_removed(const RawAddress * bda)998 void btm_sco_acl_removed(const RawAddress* bda) {
999 #if (BTM_MAX_SCO_LINKS > 0)
1000   tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0];
1001   uint16_t xx;
1002 
1003   for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
1004     if (p->state != SCO_ST_UNUSED) {
1005       if ((!bda) || (p->esco.data.bd_addr == *bda && p->rem_bd_known)) {
1006         btm_sco_flush_sco_data(xx);
1007 
1008         p->state = SCO_ST_UNUSED;
1009         p->esco.p_esco_cback = NULL; /* Deregister eSCO callback */
1010         (*p->p_disc_cb)(xx);
1011       }
1012     }
1013   }
1014 #endif
1015 }
1016 
1017 /*******************************************************************************
1018  *
1019  * Function         BTM_ReadScoBdAddr
1020  *
1021  * Description      This function is read the remote BD Address for a specific
1022  *                  SCO connection,
1023  *
1024  * Returns          pointer to BD address or NULL if not known
1025  *
1026  ******************************************************************************/
BTM_ReadScoBdAddr(uint16_t sco_inx)1027 const RawAddress* BTM_ReadScoBdAddr(uint16_t sco_inx) {
1028 #if (BTM_MAX_SCO_LINKS > 0)
1029   tSCO_CONN* p = &btm_cb.sco_cb.sco_db[sco_inx];
1030 
1031   /* Validity check */
1032   if ((sco_inx < BTM_MAX_SCO_LINKS) && (p->rem_bd_known))
1033     return &(p->esco.data.bd_addr);
1034   else
1035     return (NULL);
1036 #else
1037   return (NULL);
1038 #endif
1039 }
1040 
1041 /*******************************************************************************
1042  *
1043  * Function         BTM_SetEScoMode
1044  *
1045  * Description      This function sets up the negotiated parameters for SCO or
1046  *                  eSCO, and sets as the default mode used for outgoing calls
1047  *                  to BTM_CreateSco.  It does not change any currently active
1048  *                  (e)SCO links.
1049  *                  Note:  Incoming (e)SCO connections will always use packet
1050  *                      types supported by the controller.  If eSCO is not
1051  *                      desired the feature should be disabled in the
1052  *                      controller's feature mask.
1053  *
1054  * Returns          BTM_SUCCESS if the successful.
1055  *                  BTM_BUSY if there are one or more active (e)SCO links.
1056  *
1057  ******************************************************************************/
BTM_SetEScoMode(enh_esco_params_t * p_parms)1058 tBTM_STATUS BTM_SetEScoMode(enh_esco_params_t* p_parms) {
1059   enh_esco_params_t* p_def = &btm_cb.sco_cb.def_esco_parms;
1060 
1061   if (btm_cb.sco_cb.esco_supported) {
1062     *p_def = *p_parms;
1063   } else {
1064     /* Load defaults for SCO only */
1065     *p_def = esco_parameters_for_codec(ESCO_CODEC_CVSD);
1066     p_def->packet_types &= BTM_SCO_LINK_ONLY_MASK;
1067     p_def->retransmission_effort = ESCO_RETRANSMISSION_OFF;
1068     p_def->max_latency_ms = 12;
1069     BTM_TRACE_WARNING("%s: eSCO not supported", __func__);
1070   }
1071 
1072   BTM_TRACE_API(
1073       "%s: txbw 0x%08x, rxbw 0x%08x, max_lat 0x%04x, "
1074       "pkt 0x%04x, rtx effort 0x%02x",
1075       __func__, p_def->transmit_bandwidth, p_def->receive_bandwidth,
1076       p_def->max_latency_ms, p_def->packet_types, p_def->retransmission_effort);
1077 
1078   return BTM_SUCCESS;
1079 }
1080 
1081 /*******************************************************************************
1082  *
1083  * Function         BTM_RegForEScoEvts
1084  *
1085  * Description      This function registers a SCO event callback with the
1086  *                  specified instance.  It should be used to received
1087  *                  connection indication events and change of link parameter
1088  *                  events.
1089  *
1090  * Returns          BTM_SUCCESS if the successful.
1091  *                  BTM_ILLEGAL_VALUE if there is an illegal sco_inx
1092  *                  BTM_MODE_UNSUPPORTED if controller version is not BT1.2 or
1093  *                          later or does not support eSCO.
1094  *
1095  ******************************************************************************/
BTM_RegForEScoEvts(uint16_t sco_inx,tBTM_ESCO_CBACK * p_esco_cback)1096 tBTM_STATUS BTM_RegForEScoEvts(uint16_t sco_inx,
1097                                tBTM_ESCO_CBACK* p_esco_cback) {
1098 #if (BTM_MAX_SCO_LINKS > 0)
1099   if (!btm_cb.sco_cb.esco_supported) {
1100     btm_cb.sco_cb.sco_db[sco_inx].esco.p_esco_cback = NULL;
1101     return (BTM_MODE_UNSUPPORTED);
1102   }
1103 
1104   if (sco_inx < BTM_MAX_SCO_LINKS &&
1105       btm_cb.sco_cb.sco_db[sco_inx].state != SCO_ST_UNUSED) {
1106     btm_cb.sco_cb.sco_db[sco_inx].esco.p_esco_cback = p_esco_cback;
1107     return (BTM_SUCCESS);
1108   }
1109   return (BTM_ILLEGAL_VALUE);
1110 #else
1111   return (BTM_MODE_UNSUPPORTED);
1112 #endif
1113 }
1114 
1115 /*******************************************************************************
1116  *
1117  * Function         BTM_ChangeEScoLinkParms
1118  *
1119  * Description      This function requests renegotiation of the parameters on
1120  *                  the current eSCO Link.  If any of the changes are accepted
1121  *                  by the controllers, the BTM_ESCO_CHG_EVT event is sent in
1122  *                  the tBTM_ESCO_CBACK function with the current settings of
1123  *                  the link. The callback is registered through the call to
1124  *                  BTM_SetEScoMode.
1125  *
1126  *                  Note: If called over a SCO link (including 1.1 controller),
1127  *                        a change packet type request is sent out instead.
1128  *
1129  * Returns          BTM_CMD_STARTED if command is successfully initiated.
1130  *                  BTM_NO_RESOURCES - not enough resources to initiate command.
1131  *                  BTM_WRONG_MODE if no connection with a peer device or bad
1132  *                                 sco_inx.
1133  *
1134  ******************************************************************************/
BTM_ChangeEScoLinkParms(uint16_t sco_inx,tBTM_CHG_ESCO_PARAMS * p_parms)1135 tBTM_STATUS BTM_ChangeEScoLinkParms(uint16_t sco_inx,
1136                                     tBTM_CHG_ESCO_PARAMS* p_parms) {
1137 #if (BTM_MAX_SCO_LINKS > 0)
1138 
1139   /* Make sure sco handle is valid and on an active link */
1140   if (sco_inx >= BTM_MAX_SCO_LINKS ||
1141       btm_cb.sco_cb.sco_db[sco_inx].state != SCO_ST_CONNECTED)
1142     return (BTM_WRONG_MODE);
1143 
1144   tSCO_CONN* p_sco = &btm_cb.sco_cb.sco_db[sco_inx];
1145   enh_esco_params_t* p_setup = &p_sco->esco.setup;
1146 
1147   /* Save the previous types in case command fails */
1148   uint16_t saved_packet_types = p_setup->packet_types;
1149 
1150   /* If SCO connection OR eSCO not supported just send change packet types */
1151   if (p_sco->esco.data.link_type == BTM_LINK_TYPE_SCO ||
1152       !btm_cb.sco_cb.esco_supported) {
1153     p_setup->packet_types =
1154         p_parms->packet_types &
1155         (btm_cb.btm_sco_pkt_types_supported & BTM_SCO_LINK_ONLY_MASK);
1156 
1157     BTM_TRACE_API("%s: SCO Link for handle 0x%04x, pkt 0x%04x", __func__,
1158                   p_sco->hci_handle, p_setup->packet_types);
1159 
1160     BTM_TRACE_API("%s: SCO Link for handle 0x%04x, pkt 0x%04x", __func__,
1161                   p_sco->hci_handle, p_setup->packet_types);
1162 
1163     btsnd_hcic_change_conn_type(p_sco->hci_handle,
1164                                 BTM_ESCO_2_SCO(p_setup->packet_types));
1165   } else /* eSCO is supported and the link type is eSCO */
1166   {
1167     uint16_t temp_packet_types =
1168         (p_parms->packet_types & BTM_SCO_SUPPORTED_PKTS_MASK &
1169          btm_cb.btm_sco_pkt_types_supported);
1170 
1171     /* OR in any exception packet types */
1172     temp_packet_types |=
1173         ((p_parms->packet_types & BTM_SCO_EXCEPTION_PKTS_MASK) |
1174          (btm_cb.btm_sco_pkt_types_supported & BTM_SCO_EXCEPTION_PKTS_MASK));
1175     p_setup->packet_types = temp_packet_types;
1176 
1177     BTM_TRACE_API("%s -> eSCO Link for handle 0x%04x", __func__,
1178                   p_sco->hci_handle);
1179     BTM_TRACE_API(
1180         "   txbw 0x%x, rxbw 0x%x, lat 0x%x, retrans 0x%02x, pkt 0x%04x",
1181         p_setup->transmit_bandwidth, p_setup->receive_bandwidth,
1182         p_parms->max_latency_ms, p_parms->retransmission_effort,
1183         temp_packet_types);
1184 
1185     /* Use Enhanced Synchronous commands if supported */
1186     if (controller_get_interface()
1187             ->supports_enhanced_setup_synchronous_connection()) {
1188       /* Use the saved SCO routing */
1189       p_setup->input_data_path = p_setup->output_data_path =
1190           btm_cb.sco_cb.sco_route;
1191 
1192       btsnd_hcic_enhanced_set_up_synchronous_connection(p_sco->hci_handle,
1193                                                         p_setup);
1194       p_setup->packet_types = saved_packet_types;
1195     } else { /* Use older command */
1196       uint16_t voice_content_format = btm_sco_voice_settings_to_legacy(p_setup);
1197       /* When changing an existing link, only change latency, retrans, and
1198        * pkts */
1199       btsnd_hcic_setup_esco_conn(p_sco->hci_handle, p_setup->transmit_bandwidth,
1200                                  p_setup->receive_bandwidth,
1201                                  p_parms->max_latency_ms, voice_content_format,
1202                                  p_parms->retransmission_effort,
1203                                  p_setup->packet_types);
1204     }
1205 
1206     BTM_TRACE_API(
1207         "%s: txbw 0x%x, rxbw 0x%x, lat 0x%x, retrans 0x%02x, pkt 0x%04x",
1208         __func__, p_setup->transmit_bandwidth, p_setup->receive_bandwidth,
1209         p_parms->max_latency_ms, p_parms->retransmission_effort,
1210         temp_packet_types);
1211   }
1212 
1213   return (BTM_CMD_STARTED);
1214 #else
1215   return (BTM_WRONG_MODE);
1216 #endif
1217 }
1218 
1219 /*******************************************************************************
1220  *
1221  * Function         BTM_EScoConnRsp
1222  *
1223  * Description      This function is called upon receipt of an (e)SCO connection
1224  *                  request event (BTM_ESCO_CONN_REQ_EVT) to accept or reject
1225  *                  the request. Parameters used to negotiate eSCO links.
1226  *                  If p_parms is NULL, then values set through BTM_SetEScoMode
1227  *                  are used.
1228  *                  If the link type of the incoming request is SCO, then only
1229  *                  the tx_bw, max_latency, content format, and packet_types are
1230  *                  valid.  The hci_status parameter should be
1231  *                  ([0x0] to accept, [0x0d..0x0f] to reject)
1232  *
1233  *
1234  * Returns          void
1235  *
1236  ******************************************************************************/
BTM_EScoConnRsp(uint16_t sco_inx,uint8_t hci_status,enh_esco_params_t * p_parms)1237 void BTM_EScoConnRsp(uint16_t sco_inx, uint8_t hci_status,
1238                      enh_esco_params_t* p_parms) {
1239 #if (BTM_MAX_SCO_LINKS > 0)
1240   if (sco_inx < BTM_MAX_SCO_LINKS &&
1241       btm_cb.sco_cb.sco_db[sco_inx].state == SCO_ST_W4_CONN_RSP) {
1242     btm_esco_conn_rsp(sco_inx, hci_status,
1243                       btm_cb.sco_cb.sco_db[sco_inx].esco.data.bd_addr, p_parms);
1244   }
1245 #endif
1246 }
1247 
1248 /*******************************************************************************
1249  *
1250  * Function         btm_read_def_esco_mode
1251  *
1252  * Description      This function copies the current default esco settings into
1253  *                  the return buffer.
1254  *
1255  * Returns          tBTM_SCO_TYPE
1256  *
1257  ******************************************************************************/
btm_read_def_esco_mode(enh_esco_params_t * p_parms)1258 void btm_read_def_esco_mode(enh_esco_params_t* p_parms) {
1259 #if (BTM_MAX_SCO_LINKS > 0)
1260   *p_parms = btm_cb.sco_cb.def_esco_parms;
1261 #endif
1262 }
1263 
1264 /*******************************************************************************
1265  *
1266  * Function         btm_esco_proc_conn_chg
1267  *
1268  * Description      This function is called by BTIF when an SCO connection
1269  *                  is changed.
1270  *
1271  * Returns          void
1272  *
1273  ******************************************************************************/
btm_esco_proc_conn_chg(uint8_t status,uint16_t handle,uint8_t tx_interval,uint8_t retrans_window,uint16_t rx_pkt_len,uint16_t tx_pkt_len)1274 void btm_esco_proc_conn_chg(uint8_t status, uint16_t handle,
1275                             uint8_t tx_interval, uint8_t retrans_window,
1276                             uint16_t rx_pkt_len, uint16_t tx_pkt_len) {
1277 #if (BTM_MAX_SCO_LINKS > 0)
1278   tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0];
1279   tBTM_CHG_ESCO_EVT_DATA data;
1280   uint16_t xx;
1281 
1282   BTM_TRACE_EVENT("btm_esco_proc_conn_chg -> handle 0x%04x, status 0x%02x",
1283                   handle, status);
1284 
1285   for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
1286     if (p->state == SCO_ST_CONNECTED && handle == p->hci_handle) {
1287       /* If upper layer wants notification */
1288       if (p->esco.p_esco_cback) {
1289         data.bd_addr = p->esco.data.bd_addr;
1290         data.hci_status = status;
1291         data.sco_inx = xx;
1292         data.rx_pkt_len = p->esco.data.rx_pkt_len = rx_pkt_len;
1293         data.tx_pkt_len = p->esco.data.tx_pkt_len = tx_pkt_len;
1294         data.tx_interval = p->esco.data.tx_interval = tx_interval;
1295         data.retrans_window = p->esco.data.retrans_window = retrans_window;
1296 
1297         tBTM_ESCO_EVT_DATA btm_esco_evt_data;
1298         btm_esco_evt_data.chg_evt = data;
1299         (*p->esco.p_esco_cback)(BTM_ESCO_CHG_EVT, &btm_esco_evt_data);
1300       }
1301       return;
1302     }
1303   }
1304 #endif
1305 }
1306 
1307 /*******************************************************************************
1308  *
1309  * Function         btm_is_sco_active
1310  *
1311  * Description      This function is called to see if a SCO handle is already in
1312  *                  use.
1313  *
1314  * Returns          bool
1315  *
1316  ******************************************************************************/
btm_is_sco_active(uint16_t handle)1317 bool btm_is_sco_active(uint16_t handle) {
1318 #if (BTM_MAX_SCO_LINKS > 0)
1319   uint16_t xx;
1320   tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0];
1321 
1322   for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
1323     if (handle == p->hci_handle && p->state == SCO_ST_CONNECTED) return (true);
1324   }
1325 #endif
1326   return (false);
1327 }
1328 
1329 /*******************************************************************************
1330  *
1331  * Function         BTM_GetNumScoLinks
1332  *
1333  * Description      This function returns the number of active sco links.
1334  *
1335  * Returns          uint8_t
1336  *
1337  ******************************************************************************/
BTM_GetNumScoLinks(void)1338 uint8_t BTM_GetNumScoLinks(void) {
1339 #if (BTM_MAX_SCO_LINKS > 0)
1340   tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0];
1341   uint16_t xx;
1342   uint8_t num_scos = 0;
1343 
1344   for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
1345     switch (p->state) {
1346       case SCO_ST_W4_CONN_RSP:
1347       case SCO_ST_CONNECTING:
1348       case SCO_ST_CONNECTED:
1349       case SCO_ST_DISCONNECTING:
1350       case SCO_ST_PEND_UNPARK:
1351         num_scos++;
1352     }
1353   }
1354   return (num_scos);
1355 #else
1356   return (0);
1357 #endif
1358 }
1359 
1360 /*******************************************************************************
1361  *
1362  * Function         btm_is_sco_active_by_bdaddr
1363  *
1364  * Description      This function is called to see if a SCO connection is active
1365  *                  for a bd address.
1366  *
1367  * Returns          bool
1368  *
1369  ******************************************************************************/
btm_is_sco_active_by_bdaddr(const RawAddress & remote_bda)1370 bool btm_is_sco_active_by_bdaddr(const RawAddress& remote_bda) {
1371 #if (BTM_MAX_SCO_LINKS > 0)
1372   uint8_t xx;
1373   tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0];
1374 
1375   /* If any SCO is being established to the remote BD address, refuse this */
1376   for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
1377     if (p->esco.data.bd_addr == remote_bda && p->state == SCO_ST_CONNECTED) {
1378       return (true);
1379     }
1380   }
1381 #endif
1382   return (false);
1383 }
1384 
1385 /*******************************************************************************
1386  *
1387  * Function         btm_sco_voice_settings_2_legacy
1388  *
1389  * Description      This function is called to convert the Enhanced eSCO
1390  *                  parameters into voice setting parameter mask used
1391  *                  for legacy setup synchronous connection HCI commands
1392  *
1393  * Returns          UINT16 - 16-bit mask for voice settings
1394  *
1395  *          HCI_INP_CODING_LINEAR           0x0000 (0000000000)
1396  *          HCI_INP_CODING_U_LAW            0x0100 (0100000000)
1397  *          HCI_INP_CODING_A_LAW            0x0200 (1000000000)
1398  *          HCI_INP_CODING_MASK             0x0300 (1100000000)
1399  *
1400  *          HCI_INP_DATA_FMT_1S_COMPLEMENT  0x0000 (0000000000)
1401  *          HCI_INP_DATA_FMT_2S_COMPLEMENT  0x0040 (0001000000)
1402  *          HCI_INP_DATA_FMT_SIGN_MAGNITUDE 0x0080 (0010000000)
1403  *          HCI_INP_DATA_FMT_UNSIGNED       0x00c0 (0011000000)
1404  *          HCI_INP_DATA_FMT_MASK           0x00c0 (0011000000)
1405  *
1406  *          HCI_INP_SAMPLE_SIZE_8BIT        0x0000 (0000000000)
1407  *          HCI_INP_SAMPLE_SIZE_16BIT       0x0020 (0000100000)
1408  *          HCI_INP_SAMPLE_SIZE_MASK        0x0020 (0000100000)
1409  *
1410  *          HCI_INP_LINEAR_PCM_BIT_POS_MASK 0x001c (0000011100)
1411  *          HCI_INP_LINEAR_PCM_BIT_POS_OFFS 2
1412  *
1413  *          HCI_AIR_CODING_FORMAT_CVSD      0x0000 (0000000000)
1414  *          HCI_AIR_CODING_FORMAT_U_LAW     0x0001 (0000000001)
1415  *          HCI_AIR_CODING_FORMAT_A_LAW     0x0002 (0000000010)
1416  *          HCI_AIR_CODING_FORMAT_TRANSPNT  0x0003 (0000000011)
1417  *          HCI_AIR_CODING_FORMAT_MASK      0x0003 (0000000011)
1418  *
1419  *          default (0001100000)
1420  *          HCI_DEFAULT_VOICE_SETTINGS    (HCI_INP_CODING_LINEAR \
1421  *                                   | HCI_INP_DATA_FMT_2S_COMPLEMENT \
1422  *                                   | HCI_INP_SAMPLE_SIZE_16BIT \
1423  *                                   | HCI_AIR_CODING_FORMAT_CVSD)
1424  *
1425  ******************************************************************************/
btm_sco_voice_settings_to_legacy(enh_esco_params_t * p_params)1426 static uint16_t btm_sco_voice_settings_to_legacy(enh_esco_params_t* p_params) {
1427   uint16_t voice_settings = 0;
1428 
1429   /* Convert Input Coding Format: If no uLaw or aLAW then Linear will be used
1430    * (0) */
1431   if (p_params->input_coding_format.coding_format == ESCO_CODING_FORMAT_ULAW)
1432     voice_settings |= HCI_INP_CODING_U_LAW;
1433   else if (p_params->input_coding_format.coding_format ==
1434            ESCO_CODING_FORMAT_ALAW)
1435     voice_settings |= HCI_INP_CODING_A_LAW;
1436   /* else default value of '0 is good 'Linear' */
1437 
1438   /* Convert Input Data Format. Use 2's Compliment as the default */
1439   switch (p_params->input_pcm_data_format) {
1440     case ESCO_PCM_DATA_FORMAT_1_COMP:
1441       /* voice_settings |= HCI_INP_DATA_FMT_1S_COMPLEMENT;     value is '0'
1442        * already */
1443       break;
1444 
1445     case ESCO_PCM_DATA_FORMAT_SIGN:
1446       voice_settings |= HCI_INP_DATA_FMT_SIGN_MAGNITUDE;
1447       break;
1448 
1449     case ESCO_PCM_DATA_FORMAT_UNSIGN:
1450       voice_settings |= HCI_INP_DATA_FMT_UNSIGNED;
1451       break;
1452 
1453     default: /* 2's Compliment */
1454       voice_settings |= HCI_INP_DATA_FMT_2S_COMPLEMENT;
1455       break;
1456   }
1457 
1458   /* Convert Over the Air Coding. Use CVSD as the default */
1459   switch (p_params->transmit_coding_format.coding_format) {
1460     case ESCO_CODING_FORMAT_ULAW:
1461       voice_settings |= HCI_AIR_CODING_FORMAT_U_LAW;
1462       break;
1463 
1464     case ESCO_CODING_FORMAT_ALAW:
1465       voice_settings |= HCI_AIR_CODING_FORMAT_A_LAW;
1466       break;
1467 
1468     case ESCO_CODING_FORMAT_MSBC:
1469       voice_settings |= HCI_AIR_CODING_FORMAT_TRANSPNT;
1470       break;
1471 
1472     default: /* CVSD (0) */
1473       break;
1474   }
1475 
1476   /* Convert PCM payload MSB position (0000011100) */
1477   voice_settings |= (uint16_t)(((p_params->input_pcm_payload_msb_position & 0x7)
1478                                 << HCI_INP_LINEAR_PCM_BIT_POS_OFFS));
1479 
1480   /* Convert Input Sample Size (0000011100) */
1481   if (p_params->input_coded_data_size == 16)
1482     voice_settings |= HCI_INP_SAMPLE_SIZE_16BIT;
1483   else /* Use 8 bit for all others */
1484     voice_settings |= HCI_INP_SAMPLE_SIZE_8BIT;
1485 
1486   BTM_TRACE_DEBUG("%s: voice setting for legacy 0x%03x", __func__,
1487                   voice_settings);
1488 
1489   return (voice_settings);
1490 }
1491