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