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