1 /*
2 * Copyright 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #pragma once
18
19 #include <cstdint>
20 #include <string>
21
22 #include "btm_sco_hfp_hal.h"
23 #include "device/include/esco_parameters.h"
24 #include "stack/include/btm_api_types.h"
25
26 #define BTM_MSBC_CODE_SIZE 240
27
28 constexpr uint16_t kMaxScoLinks = static_cast<uint16_t>(BTM_MAX_SCO_LINKS);
29
30 /* SCO-over-HCI audio related definitions */
31 namespace bluetooth::audio::sco {
32
33 /* Initialize SCO-over-HCI socket (UIPC); the client is audio server */
34 void init();
35
36 /* Open the socket when there is SCO connection open */
37 void open();
38
39 /* Clean up the socket when the SCO connection is done */
40 void cleanup();
41
42 /* Read PCM data from the socket (audio server) for SCO Tx */
43 size_t read(uint8_t* p_buf, uint32_t len);
44
45 /* Write PCM data to the socket from SCO Rx */
46 size_t write(const uint8_t* buf, uint32_t len);
47 } // namespace bluetooth::audio::sco
48
49 /* SCO-over-HCI audio HFP WBS related definitions */
50 namespace bluetooth::audio::sco::wbs {
51
52 /* Initialize struct used for storing WBS related information.
53 * Args:
54 * pkt_size - Length of the SCO packet. It is determined based on the BT-USB
55 * adapter's capability and alt mode setting. The value should be queried
56 * from HAL interface. It will be used to determine the size of the SCO
57 * packet buffer. Currently, the stack only supports 60 and 72.
58 * Returns:
59 * The selected packet size. Will fallback to the typical mSBC packet
60 * length(60) if the pkt_size argument is not supported.
61 */
62 size_t init(size_t pkt_size);
63
64 /* Clean up when the SCO connection is done */
65 void cleanup();
66
67 /* Fill in packet loss stats
68 * Args:
69 * num_decoded_frames - Output argument for the number of decode frames
70 * packet_loss_ratio - Output argument for the ratio of lost frames
71 * Returns:
72 * False for invalid arguments or unreasonable stats. True otherwise.
73 */
74 bool fill_plc_stats(int* num_decoded_frames, double* packet_loss_ratio);
75
76 /* Try to enqueue a packet to a buffer.
77 * Args:
78 * data - Pointer to received packet data bytes.
79 * pkt_size - Length of input packet. Passing packet with inconsistent size
80 * from the pkt_size set in init() will fail the call.
81 * corrupted - If the current mSBC packet read is corrupted.
82 * Returns:
83 * The length of enqueued bytes. 0 if failed.
84 */
85 size_t enqueue_packet(const uint8_t* data, size_t pkt_size, bool corrupted);
86
87 /* Try to decode mSBC frames from the packets in the buffer.
88 * Args:
89 * output - Pointer to the decoded PCM bytes caller can read from.
90 * Returns:
91 * The length of decoded bytes. 0 if failed.
92 */
93 size_t decode(const uint8_t** output);
94
95 /* Try to encode PCM data into one SCO packet and put the packets in the buffer.
96 * Args:
97 * data - Pointer to the input PCM bytes for the encoder to encode.
98 * len - Length of the input data.
99 * Returns:
100 * The length of input data that is encoded. 0 if failed.
101 */
102 size_t encode(int16_t* data, size_t len);
103
104 /* Dequeue a SCO packet with encoded mSBC data if possible. The length of the
105 * packet is determined by the pkt_size set by the init().
106 * Args:
107 * output - Pointer to output mSBC packets encoded by the encoder.
108 * Returns:
109 * The length of dequeued packet. 0 if failed.
110 */
111 size_t dequeue_packet(const uint8_t** output);
112
113 } // namespace bluetooth::audio::sco::wbs
114
115 #ifndef CASE_RETURN_TEXT
116 #define CASE_RETURN_TEXT(code) \
117 case code: \
118 return #code
119 #endif
120
121 /* Define the structures needed by sco */
122 typedef enum : uint16_t {
123 SCO_ST_UNUSED = 0,
124 SCO_ST_LISTENING = 1,
125 SCO_ST_W4_CONN_RSP = 2,
126 SCO_ST_CONNECTING = 3,
127 SCO_ST_CONNECTED = 4,
128 SCO_ST_DISCONNECTING = 5,
129 SCO_ST_PEND_UNPARK = 6,
130 SCO_ST_PEND_ROLECHANGE = 7,
131 SCO_ST_PEND_MODECHANGE = 8,
132 } tSCO_STATE;
133
sco_state_text(const tSCO_STATE & state)134 inline std::string sco_state_text(const tSCO_STATE& state) {
135 switch (state) {
136 CASE_RETURN_TEXT(SCO_ST_UNUSED);
137 CASE_RETURN_TEXT(SCO_ST_LISTENING);
138 CASE_RETURN_TEXT(SCO_ST_W4_CONN_RSP);
139 CASE_RETURN_TEXT(SCO_ST_CONNECTING);
140 CASE_RETURN_TEXT(SCO_ST_CONNECTED);
141 CASE_RETURN_TEXT(SCO_ST_DISCONNECTING);
142 CASE_RETURN_TEXT(SCO_ST_PEND_UNPARK);
143 CASE_RETURN_TEXT(SCO_ST_PEND_ROLECHANGE);
144 CASE_RETURN_TEXT(SCO_ST_PEND_MODECHANGE);
145 default:
146 return std::string("unknown_sco_state: ") +
147 std::to_string(static_cast<uint16_t>(state));
148 }
149 }
150
151 #undef CASE_RETURN_TEXT
152
153 /* Define the structure that contains (e)SCO data */
154 typedef struct {
155 tBTM_ESCO_CBACK* p_esco_cback; /* Callback for eSCO events */
156 enh_esco_params_t setup;
157 tBTM_ESCO_DATA data; /* Connection complete information */
158 uint8_t hci_status;
159 } tBTM_ESCO_INFO;
160
161 /* Define the structure used for SCO Management */
162 typedef struct {
163 tBTM_ESCO_INFO esco; /* Current settings */
164 tBTM_SCO_CB* p_conn_cb; /* Callback for when connected */
165 tBTM_SCO_CB* p_disc_cb; /* Callback for when disconnect */
166 tSCO_STATE state; /* The state of the SCO link */
167
168 uint16_t hci_handle; /* HCI Handle */
169 public:
is_active__anon788907a70308170 bool is_active() const { return state != SCO_ST_UNUSED; }
is_inband__anon788907a70308171 bool is_inband() const {
172 return esco.setup.input_data_path == ESCO_DATA_PATH_HCI;
173 }
is_wbs__anon788907a70308174 bool is_wbs() const {
175 return esco.setup.transmit_coding_format.coding_format ==
176 ESCO_CODING_FORMAT_TRANSPNT ||
177 esco.setup.transmit_coding_format.coding_format ==
178 ESCO_CODING_FORMAT_MSBC;
179 }
Handle__anon788907a70308180 uint16_t Handle() const { return hci_handle; }
181
182 bool is_orig; /* true if the originator */
183 bool rem_bd_known; /* true if remote BD addr known */
184
185 } tSCO_CONN;
186
187 /* SCO Management control block */
188 typedef struct {
189 tSCO_CONN sco_db[BTM_MAX_SCO_LINKS];
190 enh_esco_params_t def_esco_parms;
191 bool esco_supported; /* true if 1.2 cntlr AND supports eSCO links */
192
get_sco_connection_from_index__anon788907a70408193 tSCO_CONN* get_sco_connection_from_index(uint16_t index) {
194 return (index < kMaxScoLinks) ? (&sco_db[index]) : nullptr;
195 }
196
get_sco_connection_from_handle__anon788907a70408197 tSCO_CONN* get_sco_connection_from_handle(uint16_t handle) {
198 tSCO_CONN* p_sco = sco_db;
199 for (uint16_t xx = 0; xx < kMaxScoLinks; xx++, p_sco++) {
200 if (p_sco->hci_handle == handle) {
201 return p_sco;
202 }
203 }
204 return nullptr;
205 }
206
Init__anon788907a70408207 void Init() {
208 hfp_hal_interface::init();
209 def_esco_parms = esco_parameters_for_codec(
210 ESCO_CODEC_CVSD_S3, hfp_hal_interface::get_offload_enabled());
211 }
212
Free__anon788907a70408213 void Free() { bluetooth::audio::sco::cleanup(); }
214
get_index__anon788907a70408215 uint16_t get_index(const tSCO_CONN* p_sco) const {
216 CHECK(p_sco != nullptr);
217 const tSCO_CONN* p = sco_db;
218 for (uint16_t xx = 0; xx < kMaxScoLinks; xx++, p++) {
219 if (p_sco == p) {
220 return xx;
221 }
222 }
223 return 0xffff;
224 }
225
226 } tSCO_CB;
227
228 void btm_sco_chk_pend_rolechange(uint16_t hci_handle);
229 void btm_sco_disc_chk_pend_for_modechange(uint16_t hci_handle);
230
231 /* Visible for test only */
232 BT_HDR* btm_sco_make_packet(std::vector<uint8_t> data, uint16_t sco_handle);
233
234 /* Send a SCO packet */
235 void btm_send_sco_packet(std::vector<uint8_t> data);
236