• 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_SetScoPacketTypes
1020  *
1021  * Description      This function is called to set the packet types used for
1022  *                  a specific SCO connection,
1023  *
1024  * Parameters       pkt_types - One or more of the following
1025  *                  BTM_SCO_PKT_TYPES_MASK_HV1
1026  *                  BTM_SCO_PKT_TYPES_MASK_HV2
1027  *                  BTM_SCO_PKT_TYPES_MASK_HV3
1028  *                  BTM_SCO_PKT_TYPES_MASK_EV3
1029  *                  BTM_SCO_PKT_TYPES_MASK_EV4
1030  *                  BTM_SCO_PKT_TYPES_MASK_EV5
1031  *                  BTM_SCO_PKT_TYPES_MASK_NO_2_EV3
1032  *                  BTM_SCO_PKT_TYPES_MASK_NO_3_EV3
1033  *                  BTM_SCO_PKT_TYPES_MASK_NO_2_EV5
1034  *                  BTM_SCO_PKT_TYPES_MASK_NO_3_EV5
1035  *
1036  *                  BTM_SCO_LINK_ALL_MASK   - enables all supported types
1037  *
1038  * Returns          status of the operation
1039  *
1040  ******************************************************************************/
BTM_SetScoPacketTypes(uint16_t sco_inx,uint16_t pkt_types)1041 tBTM_STATUS BTM_SetScoPacketTypes(uint16_t sco_inx, uint16_t pkt_types) {
1042 #if (BTM_MAX_SCO_LINKS > 0)
1043   tBTM_CHG_ESCO_PARAMS parms;
1044   tSCO_CONN* p;
1045 
1046   /* Validity check */
1047   if (sco_inx >= BTM_MAX_SCO_LINKS) return (BTM_UNKNOWN_ADDR);
1048 
1049   p = &btm_cb.sco_cb.sco_db[sco_inx];
1050   parms.packet_types = pkt_types;
1051 
1052   /* Keep the other parameters the same for SCO */
1053   parms.max_latency_ms = p->esco.setup.max_latency_ms;
1054   parms.retransmission_effort = p->esco.setup.retransmission_effort;
1055 
1056   return (BTM_ChangeEScoLinkParms(sco_inx, &parms));
1057 #else
1058   return (BTM_UNKNOWN_ADDR);
1059 #endif
1060 }
1061 
1062 /*******************************************************************************
1063  *
1064  * Function         BTM_ReadScoPacketTypes
1065  *
1066  * Description      This function is read the packet types used for a specific
1067  *                  SCO connection.
1068  *
1069  * Returns          Packet types supported for the connection
1070  *                  One or more of the following (bitmask):
1071  *                  BTM_SCO_PKT_TYPES_MASK_HV1
1072  *                  BTM_SCO_PKT_TYPES_MASK_HV2
1073  *                  BTM_SCO_PKT_TYPES_MASK_HV3
1074  *                  BTM_SCO_PKT_TYPES_MASK_EV3
1075  *                  BTM_SCO_PKT_TYPES_MASK_EV4
1076  *                  BTM_SCO_PKT_TYPES_MASK_EV5
1077  *                  BTM_SCO_PKT_TYPES_MASK_NO_2_EV3
1078  *                  BTM_SCO_PKT_TYPES_MASK_NO_3_EV3
1079  *                  BTM_SCO_PKT_TYPES_MASK_NO_2_EV5
1080  *                  BTM_SCO_PKT_TYPES_MASK_NO_3_EV5
1081  *
1082  ******************************************************************************/
BTM_ReadScoPacketTypes(uint16_t sco_inx)1083 uint16_t BTM_ReadScoPacketTypes(uint16_t sco_inx) {
1084 #if (BTM_MAX_SCO_LINKS > 0)
1085   tSCO_CONN* p = &btm_cb.sco_cb.sco_db[sco_inx];
1086 
1087   /* Validity check */
1088   if ((sco_inx < BTM_MAX_SCO_LINKS) && (p->state == SCO_ST_CONNECTED))
1089     return (p->esco.setup.packet_types);
1090   else
1091     return (0);
1092 #else
1093   return (0);
1094 #endif
1095 }
1096 
1097 /*******************************************************************************
1098  *
1099  * Function         BTM_ReadScoDiscReason
1100  *
1101  * Description      This function is returns the reason why an (e)SCO connection
1102  *                  has been removed. It contains the value until read, or until
1103  *                  another (e)SCO connection has disconnected.
1104  *
1105  * Returns          HCI reason or BTM_INVALID_SCO_DISC_REASON if not set.
1106  *
1107  ******************************************************************************/
BTM_ReadScoDiscReason(void)1108 uint16_t BTM_ReadScoDiscReason(void) {
1109   uint16_t res = btm_cb.sco_cb.sco_disc_reason;
1110   btm_cb.sco_cb.sco_disc_reason = BTM_INVALID_SCO_DISC_REASON;
1111   return (res);
1112 }
1113 
1114 /*******************************************************************************
1115  *
1116  * Function         BTM_ReadDeviceScoPacketTypes
1117  *
1118  * Description      This function is read the SCO packet types that
1119  *                  the device supports.
1120  *
1121  * Returns          Packet types supported by the device.
1122  *                  One or more of the following (bitmask):
1123  *                  BTM_SCO_PKT_TYPES_MASK_HV1
1124  *                  BTM_SCO_PKT_TYPES_MASK_HV2
1125  *                  BTM_SCO_PKT_TYPES_MASK_HV3
1126  *                  BTM_SCO_PKT_TYPES_MASK_EV3
1127  *                  BTM_SCO_PKT_TYPES_MASK_EV4
1128  *                  BTM_SCO_PKT_TYPES_MASK_EV5
1129  *                  BTM_SCO_PKT_TYPES_MASK_NO_2_EV3
1130  *                  BTM_SCO_PKT_TYPES_MASK_NO_3_EV3
1131  *                  BTM_SCO_PKT_TYPES_MASK_NO_2_EV5
1132  *                  BTM_SCO_PKT_TYPES_MASK_NO_3_EV5
1133  *
1134  ******************************************************************************/
BTM_ReadDeviceScoPacketTypes(void)1135 uint16_t BTM_ReadDeviceScoPacketTypes(void) {
1136   return (btm_cb.btm_sco_pkt_types_supported);
1137 }
1138 
1139 /*******************************************************************************
1140  *
1141  * Function         BTM_ReadScoHandle
1142  *
1143  * Description      This function is used to read the HCI handle used for a
1144  *                  specific SCO connection,
1145  *
1146  * Returns          handle for the connection, or 0xFFFF if invalid SCO index.
1147  *
1148  ******************************************************************************/
BTM_ReadScoHandle(uint16_t sco_inx)1149 uint16_t BTM_ReadScoHandle(uint16_t sco_inx) {
1150 #if (BTM_MAX_SCO_LINKS > 0)
1151   tSCO_CONN* p = &btm_cb.sco_cb.sco_db[sco_inx];
1152 
1153   /* Validity check */
1154   if ((sco_inx < BTM_MAX_SCO_LINKS) && (p->state == SCO_ST_CONNECTED))
1155     return (p->hci_handle);
1156   else
1157     return (BTM_INVALID_HCI_HANDLE);
1158 #else
1159   return (BTM_INVALID_HCI_HANDLE);
1160 #endif
1161 }
1162 
1163 /*******************************************************************************
1164  *
1165  * Function         BTM_ReadScoBdAddr
1166  *
1167  * Description      This function is read the remote BD Address for a specific
1168  *                  SCO connection,
1169  *
1170  * Returns          pointer to BD address or NULL if not known
1171  *
1172  ******************************************************************************/
BTM_ReadScoBdAddr(uint16_t sco_inx)1173 const RawAddress* BTM_ReadScoBdAddr(uint16_t sco_inx) {
1174 #if (BTM_MAX_SCO_LINKS > 0)
1175   tSCO_CONN* p = &btm_cb.sco_cb.sco_db[sco_inx];
1176 
1177   /* Validity check */
1178   if ((sco_inx < BTM_MAX_SCO_LINKS) && (p->rem_bd_known))
1179     return &(p->esco.data.bd_addr);
1180   else
1181     return (NULL);
1182 #else
1183   return (NULL);
1184 #endif
1185 }
1186 
1187 /*******************************************************************************
1188  *
1189  * Function         BTM_SetEScoMode
1190  *
1191  * Description      This function sets up the negotiated parameters for SCO or
1192  *                  eSCO, and sets as the default mode used for outgoing calls
1193  *                  to BTM_CreateSco.  It does not change any currently active
1194  *                  (e)SCO links.
1195  *                  Note:  Incoming (e)SCO connections will always use packet
1196  *                      types supported by the controller.  If eSCO is not
1197  *                      desired the feature should be disabled in the
1198  *                      controller's feature mask.
1199  *
1200  * Returns          BTM_SUCCESS if the successful.
1201  *                  BTM_BUSY if there are one or more active (e)SCO links.
1202  *
1203  ******************************************************************************/
BTM_SetEScoMode(enh_esco_params_t * p_parms)1204 tBTM_STATUS BTM_SetEScoMode(enh_esco_params_t* p_parms) {
1205   enh_esco_params_t* p_def = &btm_cb.sco_cb.def_esco_parms;
1206 
1207   if (btm_cb.sco_cb.esco_supported) {
1208     *p_def = *p_parms;
1209   } else {
1210     /* Load defaults for SCO only */
1211     *p_def = esco_parameters_for_codec(ESCO_CODEC_CVSD);
1212     p_def->packet_types &= BTM_SCO_LINK_ONLY_MASK;
1213     p_def->retransmission_effort = ESCO_RETRANSMISSION_OFF;
1214     p_def->max_latency_ms = 12;
1215     BTM_TRACE_WARNING("%s: eSCO not supported", __func__);
1216   }
1217 
1218   BTM_TRACE_API(
1219       "%s: txbw 0x%08x, rxbw 0x%08x, max_lat 0x%04x, "
1220       "pkt 0x%04x, rtx effort 0x%02x",
1221       __func__, p_def->transmit_bandwidth, p_def->receive_bandwidth,
1222       p_def->max_latency_ms, p_def->packet_types, p_def->retransmission_effort);
1223 
1224   return BTM_SUCCESS;
1225 }
1226 
1227 /*******************************************************************************
1228  *
1229  * Function         BTM_RegForEScoEvts
1230  *
1231  * Description      This function registers a SCO event callback with the
1232  *                  specified instance.  It should be used to received
1233  *                  connection indication events and change of link parameter
1234  *                  events.
1235  *
1236  * Returns          BTM_SUCCESS if the successful.
1237  *                  BTM_ILLEGAL_VALUE if there is an illegal sco_inx
1238  *                  BTM_MODE_UNSUPPORTED if controller version is not BT1.2 or
1239  *                          later or does not support eSCO.
1240  *
1241  ******************************************************************************/
BTM_RegForEScoEvts(uint16_t sco_inx,tBTM_ESCO_CBACK * p_esco_cback)1242 tBTM_STATUS BTM_RegForEScoEvts(uint16_t sco_inx,
1243                                tBTM_ESCO_CBACK* p_esco_cback) {
1244 #if (BTM_MAX_SCO_LINKS > 0)
1245   if (!btm_cb.sco_cb.esco_supported) {
1246     btm_cb.sco_cb.sco_db[sco_inx].esco.p_esco_cback = NULL;
1247     return (BTM_MODE_UNSUPPORTED);
1248   }
1249 
1250   if (sco_inx < BTM_MAX_SCO_LINKS &&
1251       btm_cb.sco_cb.sco_db[sco_inx].state != SCO_ST_UNUSED) {
1252     btm_cb.sco_cb.sco_db[sco_inx].esco.p_esco_cback = p_esco_cback;
1253     return (BTM_SUCCESS);
1254   }
1255   return (BTM_ILLEGAL_VALUE);
1256 #else
1257   return (BTM_MODE_UNSUPPORTED);
1258 #endif
1259 }
1260 
1261 /*******************************************************************************
1262  *
1263  * Function         BTM_ReadEScoLinkParms
1264  *
1265  * Description      This function returns the current eSCO link parameters for
1266  *                  the specified handle.  This can be called anytime a
1267  *                  connection is active, but is typically called after
1268  *                  receiving the SCO opened callback.
1269  *
1270  *                  Note: If called over a 1.1 controller, only the packet types
1271  *                        field has meaning.
1272  *
1273  * Returns          BTM_SUCCESS if returned data is valid connection.
1274  *                  BTM_WRONG_MODE if no connection with a peer device or bad
1275  *                                 sco_inx.
1276  *
1277  ******************************************************************************/
BTM_ReadEScoLinkParms(uint16_t sco_inx,tBTM_ESCO_DATA * p_parms)1278 tBTM_STATUS BTM_ReadEScoLinkParms(uint16_t sco_inx, tBTM_ESCO_DATA* p_parms) {
1279 #if (BTM_MAX_SCO_LINKS > 0)
1280   uint8_t index;
1281 
1282   BTM_TRACE_API("%s: -> sco_inx 0x%04x", __func__, sco_inx);
1283 
1284   if (sco_inx < BTM_MAX_SCO_LINKS &&
1285       btm_cb.sco_cb.sco_db[sco_inx].state >= SCO_ST_CONNECTED) {
1286     *p_parms = btm_cb.sco_cb.sco_db[sco_inx].esco.data;
1287     return (BTM_SUCCESS);
1288   }
1289 
1290   if (sco_inx == BTM_FIRST_ACTIVE_SCO_INDEX) {
1291     for (index = 0; index < BTM_MAX_SCO_LINKS; index++) {
1292       if (btm_cb.sco_cb.sco_db[index].state >= SCO_ST_CONNECTED) {
1293         BTM_TRACE_API("%s: the first active SCO index is %d", __func__, index);
1294         *p_parms = btm_cb.sco_cb.sco_db[index].esco.data;
1295         return (BTM_SUCCESS);
1296       }
1297     }
1298   }
1299 
1300 #endif
1301 
1302   BTM_TRACE_API("BTM_ReadEScoLinkParms cannot find the SCO index!");
1303   memset(p_parms, 0, sizeof(tBTM_ESCO_DATA));
1304   return (BTM_WRONG_MODE);
1305 }
1306 
1307 /*******************************************************************************
1308  *
1309  * Function         BTM_ChangeEScoLinkParms
1310  *
1311  * Description      This function requests renegotiation of the parameters on
1312  *                  the current eSCO Link.  If any of the changes are accepted
1313  *                  by the controllers, the BTM_ESCO_CHG_EVT event is sent in
1314  *                  the tBTM_ESCO_CBACK function with the current settings of
1315  *                  the link. The callback is registered through the call to
1316  *                  BTM_SetEScoMode.
1317  *
1318  *                  Note: If called over a SCO link (including 1.1 controller),
1319  *                        a change packet type request is sent out instead.
1320  *
1321  * Returns          BTM_CMD_STARTED if command is successfully initiated.
1322  *                  BTM_NO_RESOURCES - not enough resources to initiate command.
1323  *                  BTM_WRONG_MODE if no connection with a peer device or bad
1324  *                                 sco_inx.
1325  *
1326  ******************************************************************************/
BTM_ChangeEScoLinkParms(uint16_t sco_inx,tBTM_CHG_ESCO_PARAMS * p_parms)1327 tBTM_STATUS BTM_ChangeEScoLinkParms(uint16_t sco_inx,
1328                                     tBTM_CHG_ESCO_PARAMS* p_parms) {
1329 #if (BTM_MAX_SCO_LINKS > 0)
1330 
1331   /* Make sure sco handle is valid and on an active link */
1332   if (sco_inx >= BTM_MAX_SCO_LINKS ||
1333       btm_cb.sco_cb.sco_db[sco_inx].state != SCO_ST_CONNECTED)
1334     return (BTM_WRONG_MODE);
1335 
1336   tSCO_CONN* p_sco = &btm_cb.sco_cb.sco_db[sco_inx];
1337   enh_esco_params_t* p_setup = &p_sco->esco.setup;
1338 
1339   /* Save the previous types in case command fails */
1340   uint16_t saved_packet_types = p_setup->packet_types;
1341 
1342   /* If SCO connection OR eSCO not supported just send change packet types */
1343   if (p_sco->esco.data.link_type == BTM_LINK_TYPE_SCO ||
1344       !btm_cb.sco_cb.esco_supported) {
1345     p_setup->packet_types =
1346         p_parms->packet_types &
1347         (btm_cb.btm_sco_pkt_types_supported & BTM_SCO_LINK_ONLY_MASK);
1348 
1349     BTM_TRACE_API("%s: SCO Link for handle 0x%04x, pkt 0x%04x", __func__,
1350                   p_sco->hci_handle, p_setup->packet_types);
1351 
1352     BTM_TRACE_API("%s: SCO Link for handle 0x%04x, pkt 0x%04x", __func__,
1353                   p_sco->hci_handle, p_setup->packet_types);
1354 
1355     btsnd_hcic_change_conn_type(p_sco->hci_handle,
1356                                 BTM_ESCO_2_SCO(p_setup->packet_types));
1357   } else /* eSCO is supported and the link type is eSCO */
1358   {
1359     uint16_t temp_packet_types =
1360         (p_parms->packet_types & BTM_SCO_SUPPORTED_PKTS_MASK &
1361          btm_cb.btm_sco_pkt_types_supported);
1362 
1363     /* OR in any exception packet types */
1364     temp_packet_types |=
1365         ((p_parms->packet_types & BTM_SCO_EXCEPTION_PKTS_MASK) |
1366          (btm_cb.btm_sco_pkt_types_supported & BTM_SCO_EXCEPTION_PKTS_MASK));
1367     p_setup->packet_types = temp_packet_types;
1368 
1369     BTM_TRACE_API("%s -> eSCO Link for handle 0x%04x", __func__,
1370                   p_sco->hci_handle);
1371     BTM_TRACE_API(
1372         "   txbw 0x%x, rxbw 0x%x, lat 0x%x, retrans 0x%02x, pkt 0x%04x",
1373         p_setup->transmit_bandwidth, p_setup->receive_bandwidth,
1374         p_parms->max_latency_ms, p_parms->retransmission_effort,
1375         temp_packet_types);
1376 
1377     /* Use Enhanced Synchronous commands if supported */
1378     if (controller_get_interface()
1379             ->supports_enhanced_setup_synchronous_connection()) {
1380       /* Use the saved SCO routing */
1381       p_setup->input_data_path = p_setup->output_data_path =
1382           btm_cb.sco_cb.sco_route;
1383 
1384       btsnd_hcic_enhanced_set_up_synchronous_connection(p_sco->hci_handle,
1385                                                         p_setup);
1386       p_setup->packet_types = saved_packet_types;
1387     } else { /* Use older command */
1388       uint16_t voice_content_format = btm_sco_voice_settings_to_legacy(p_setup);
1389       /* When changing an existing link, only change latency, retrans, and
1390        * pkts */
1391       btsnd_hcic_setup_esco_conn(p_sco->hci_handle, p_setup->transmit_bandwidth,
1392                                  p_setup->receive_bandwidth,
1393                                  p_parms->max_latency_ms, voice_content_format,
1394                                  p_parms->retransmission_effort,
1395                                  p_setup->packet_types);
1396     }
1397 
1398     BTM_TRACE_API(
1399         "%s: txbw 0x%x, rxbw 0x%x, lat 0x%x, retrans 0x%02x, pkt 0x%04x",
1400         __func__, p_setup->transmit_bandwidth, p_setup->receive_bandwidth,
1401         p_parms->max_latency_ms, p_parms->retransmission_effort,
1402         temp_packet_types);
1403   }
1404 
1405   return (BTM_CMD_STARTED);
1406 #else
1407   return (BTM_WRONG_MODE);
1408 #endif
1409 }
1410 
1411 /*******************************************************************************
1412  *
1413  * Function         BTM_EScoConnRsp
1414  *
1415  * Description      This function is called upon receipt of an (e)SCO connection
1416  *                  request event (BTM_ESCO_CONN_REQ_EVT) to accept or reject
1417  *                  the request. Parameters used to negotiate eSCO links.
1418  *                  If p_parms is NULL, then values set through BTM_SetEScoMode
1419  *                  are used.
1420  *                  If the link type of the incoming request is SCO, then only
1421  *                  the tx_bw, max_latency, content format, and packet_types are
1422  *                  valid.  The hci_status parameter should be
1423  *                  ([0x0] to accept, [0x0d..0x0f] to reject)
1424  *
1425  *
1426  * Returns          void
1427  *
1428  ******************************************************************************/
BTM_EScoConnRsp(uint16_t sco_inx,uint8_t hci_status,enh_esco_params_t * p_parms)1429 void BTM_EScoConnRsp(uint16_t sco_inx, uint8_t hci_status,
1430                      enh_esco_params_t* p_parms) {
1431 #if (BTM_MAX_SCO_LINKS > 0)
1432   if (sco_inx < BTM_MAX_SCO_LINKS &&
1433       btm_cb.sco_cb.sco_db[sco_inx].state == SCO_ST_W4_CONN_RSP) {
1434     btm_esco_conn_rsp(sco_inx, hci_status,
1435                       btm_cb.sco_cb.sco_db[sco_inx].esco.data.bd_addr, p_parms);
1436   }
1437 #endif
1438 }
1439 
1440 /*******************************************************************************
1441  *
1442  * Function         btm_read_def_esco_mode
1443  *
1444  * Description      This function copies the current default esco settings into
1445  *                  the return buffer.
1446  *
1447  * Returns          tBTM_SCO_TYPE
1448  *
1449  ******************************************************************************/
btm_read_def_esco_mode(enh_esco_params_t * p_parms)1450 void btm_read_def_esco_mode(enh_esco_params_t* p_parms) {
1451 #if (BTM_MAX_SCO_LINKS > 0)
1452   *p_parms = btm_cb.sco_cb.def_esco_parms;
1453 #endif
1454 }
1455 
1456 /*******************************************************************************
1457  *
1458  * Function         btm_esco_proc_conn_chg
1459  *
1460  * Description      This function is called by BTIF when an SCO connection
1461  *                  is changed.
1462  *
1463  * Returns          void
1464  *
1465  ******************************************************************************/
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)1466 void btm_esco_proc_conn_chg(uint8_t status, uint16_t handle,
1467                             uint8_t tx_interval, uint8_t retrans_window,
1468                             uint16_t rx_pkt_len, uint16_t tx_pkt_len) {
1469 #if (BTM_MAX_SCO_LINKS > 0)
1470   tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0];
1471   tBTM_CHG_ESCO_EVT_DATA data;
1472   uint16_t xx;
1473 
1474   BTM_TRACE_EVENT("btm_esco_proc_conn_chg -> handle 0x%04x, status 0x%02x",
1475                   handle, status);
1476 
1477   for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
1478     if (p->state == SCO_ST_CONNECTED && handle == p->hci_handle) {
1479       /* If upper layer wants notification */
1480       if (p->esco.p_esco_cback) {
1481         data.bd_addr = p->esco.data.bd_addr;
1482         data.hci_status = status;
1483         data.sco_inx = xx;
1484         data.rx_pkt_len = p->esco.data.rx_pkt_len = rx_pkt_len;
1485         data.tx_pkt_len = p->esco.data.tx_pkt_len = tx_pkt_len;
1486         data.tx_interval = p->esco.data.tx_interval = tx_interval;
1487         data.retrans_window = p->esco.data.retrans_window = retrans_window;
1488 
1489         tBTM_ESCO_EVT_DATA btm_esco_evt_data;
1490         btm_esco_evt_data.chg_evt = data;
1491         (*p->esco.p_esco_cback)(BTM_ESCO_CHG_EVT, &btm_esco_evt_data);
1492       }
1493       return;
1494     }
1495   }
1496 #endif
1497 }
1498 
1499 /*******************************************************************************
1500  *
1501  * Function         btm_is_sco_active
1502  *
1503  * Description      This function is called to see if a SCO handle is already in
1504  *                  use.
1505  *
1506  * Returns          bool
1507  *
1508  ******************************************************************************/
btm_is_sco_active(uint16_t handle)1509 bool btm_is_sco_active(uint16_t handle) {
1510 #if (BTM_MAX_SCO_LINKS > 0)
1511   uint16_t xx;
1512   tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0];
1513 
1514   for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
1515     if (handle == p->hci_handle && p->state == SCO_ST_CONNECTED) return (true);
1516   }
1517 #endif
1518   return (false);
1519 }
1520 
1521 /*******************************************************************************
1522  *
1523  * Function         BTM_GetNumScoLinks
1524  *
1525  * Description      This function returns the number of active sco links.
1526  *
1527  * Returns          uint8_t
1528  *
1529  ******************************************************************************/
BTM_GetNumScoLinks(void)1530 uint8_t BTM_GetNumScoLinks(void) {
1531 #if (BTM_MAX_SCO_LINKS > 0)
1532   tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0];
1533   uint16_t xx;
1534   uint8_t num_scos = 0;
1535 
1536   for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
1537     switch (p->state) {
1538       case SCO_ST_W4_CONN_RSP:
1539       case SCO_ST_CONNECTING:
1540       case SCO_ST_CONNECTED:
1541       case SCO_ST_DISCONNECTING:
1542       case SCO_ST_PEND_UNPARK:
1543         num_scos++;
1544     }
1545   }
1546   return (num_scos);
1547 #else
1548   return (0);
1549 #endif
1550 }
1551 
1552 /*******************************************************************************
1553  *
1554  * Function         btm_is_sco_active_by_bdaddr
1555  *
1556  * Description      This function is called to see if a SCO connection is active
1557  *                  for a bd address.
1558  *
1559  * Returns          bool
1560  *
1561  ******************************************************************************/
btm_is_sco_active_by_bdaddr(const RawAddress & remote_bda)1562 bool btm_is_sco_active_by_bdaddr(const RawAddress& remote_bda) {
1563 #if (BTM_MAX_SCO_LINKS > 0)
1564   uint8_t xx;
1565   tSCO_CONN* p = &btm_cb.sco_cb.sco_db[0];
1566 
1567   /* If any SCO is being established to the remote BD address, refuse this */
1568   for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
1569     if (p->esco.data.bd_addr == remote_bda && p->state == SCO_ST_CONNECTED) {
1570       return (true);
1571     }
1572   }
1573 #endif
1574   return (false);
1575 }
1576 
1577 /*******************************************************************************
1578  *
1579  * Function         btm_sco_voice_settings_2_legacy
1580  *
1581  * Description      This function is called to convert the Enhanced eSCO
1582  *                  parameters into voice setting parameter mask used
1583  *                  for legacy setup synchronous connection HCI commands
1584  *
1585  * Returns          UINT16 - 16-bit mask for voice settings
1586  *
1587  *          HCI_INP_CODING_LINEAR           0x0000 (0000000000)
1588  *          HCI_INP_CODING_U_LAW            0x0100 (0100000000)
1589  *          HCI_INP_CODING_A_LAW            0x0200 (1000000000)
1590  *          HCI_INP_CODING_MASK             0x0300 (1100000000)
1591  *
1592  *          HCI_INP_DATA_FMT_1S_COMPLEMENT  0x0000 (0000000000)
1593  *          HCI_INP_DATA_FMT_2S_COMPLEMENT  0x0040 (0001000000)
1594  *          HCI_INP_DATA_FMT_SIGN_MAGNITUDE 0x0080 (0010000000)
1595  *          HCI_INP_DATA_FMT_UNSIGNED       0x00c0 (0011000000)
1596  *          HCI_INP_DATA_FMT_MASK           0x00c0 (0011000000)
1597  *
1598  *          HCI_INP_SAMPLE_SIZE_8BIT        0x0000 (0000000000)
1599  *          HCI_INP_SAMPLE_SIZE_16BIT       0x0020 (0000100000)
1600  *          HCI_INP_SAMPLE_SIZE_MASK        0x0020 (0000100000)
1601  *
1602  *          HCI_INP_LINEAR_PCM_BIT_POS_MASK 0x001c (0000011100)
1603  *          HCI_INP_LINEAR_PCM_BIT_POS_OFFS 2
1604  *
1605  *          HCI_AIR_CODING_FORMAT_CVSD      0x0000 (0000000000)
1606  *          HCI_AIR_CODING_FORMAT_U_LAW     0x0001 (0000000001)
1607  *          HCI_AIR_CODING_FORMAT_A_LAW     0x0002 (0000000010)
1608  *          HCI_AIR_CODING_FORMAT_TRANSPNT  0x0003 (0000000011)
1609  *          HCI_AIR_CODING_FORMAT_MASK      0x0003 (0000000011)
1610  *
1611  *          default (0001100000)
1612  *          HCI_DEFAULT_VOICE_SETTINGS    (HCI_INP_CODING_LINEAR \
1613  *                                   | HCI_INP_DATA_FMT_2S_COMPLEMENT \
1614  *                                   | HCI_INP_SAMPLE_SIZE_16BIT \
1615  *                                   | HCI_AIR_CODING_FORMAT_CVSD)
1616  *
1617  ******************************************************************************/
btm_sco_voice_settings_to_legacy(enh_esco_params_t * p_params)1618 static uint16_t btm_sco_voice_settings_to_legacy(enh_esco_params_t* p_params) {
1619   uint16_t voice_settings = 0;
1620 
1621   /* Convert Input Coding Format: If no uLaw or aLAW then Linear will be used
1622    * (0) */
1623   if (p_params->input_coding_format.coding_format == ESCO_CODING_FORMAT_ULAW)
1624     voice_settings |= HCI_INP_CODING_U_LAW;
1625   else if (p_params->input_coding_format.coding_format ==
1626            ESCO_CODING_FORMAT_ALAW)
1627     voice_settings |= HCI_INP_CODING_A_LAW;
1628   /* else default value of '0 is good 'Linear' */
1629 
1630   /* Convert Input Data Format. Use 2's Compliment as the default */
1631   switch (p_params->input_pcm_data_format) {
1632     case ESCO_PCM_DATA_FORMAT_1_COMP:
1633       /* voice_settings |= HCI_INP_DATA_FMT_1S_COMPLEMENT;     value is '0'
1634        * already */
1635       break;
1636 
1637     case ESCO_PCM_DATA_FORMAT_SIGN:
1638       voice_settings |= HCI_INP_DATA_FMT_SIGN_MAGNITUDE;
1639       break;
1640 
1641     case ESCO_PCM_DATA_FORMAT_UNSIGN:
1642       voice_settings |= HCI_INP_DATA_FMT_UNSIGNED;
1643       break;
1644 
1645     default: /* 2's Compliment */
1646       voice_settings |= HCI_INP_DATA_FMT_2S_COMPLEMENT;
1647       break;
1648   }
1649 
1650   /* Convert Over the Air Coding. Use CVSD as the default */
1651   switch (p_params->transmit_coding_format.coding_format) {
1652     case ESCO_CODING_FORMAT_ULAW:
1653       voice_settings |= HCI_AIR_CODING_FORMAT_U_LAW;
1654       break;
1655 
1656     case ESCO_CODING_FORMAT_ALAW:
1657       voice_settings |= HCI_AIR_CODING_FORMAT_A_LAW;
1658       break;
1659 
1660     case ESCO_CODING_FORMAT_MSBC:
1661       voice_settings |= HCI_AIR_CODING_FORMAT_TRANSPNT;
1662       break;
1663 
1664     default: /* CVSD (0) */
1665       break;
1666   }
1667 
1668   /* Convert PCM payload MSB position (0000011100) */
1669   voice_settings |= (uint16_t)(((p_params->input_pcm_payload_msb_position & 0x7)
1670                                 << HCI_INP_LINEAR_PCM_BIT_POS_OFFS));
1671 
1672   /* Convert Input Sample Size (0000011100) */
1673   if (p_params->input_coded_data_size == 16)
1674     voice_settings |= HCI_INP_SAMPLE_SIZE_16BIT;
1675   else /* Use 8 bit for all others */
1676     voice_settings |= HCI_INP_SAMPLE_SIZE_8BIT;
1677 
1678   BTM_TRACE_DEBUG("%s: voice setting for legacy 0x%03x", __func__,
1679                   voice_settings);
1680 
1681   return (voice_settings);
1682 }
1683