summaryrefslogtreecommitdiff
path: root/system/stack/btm/btm_sco.h
blob: 8e85f1d06c4bb3ba81cf76866fc9176572973fe8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/*
 * Copyright 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <cstdint>
#include <string>

#include "device/include/esco_parameters.h"
#include "stack/include/btm_api_types.h"

constexpr uint16_t kMaxScoLinks = static_cast<uint16_t>(BTM_MAX_SCO_LINKS);

#ifndef ESCO_DATA_PATH
#ifdef OS_ANDROID
#define ESCO_DATA_PATH ESCO_DATA_PATH_PCM
#else
#define ESCO_DATA_PATH ESCO_DATA_PATH_HCI
#endif
#endif

// SCO-over-HCI audio related definitions
namespace bluetooth::audio::sco {

// Initialize SCO-over-HCI socket (UIPC); the client is audio server.
void init();

// Open the socket when there is SCO connection open
void open();

// Clean up the socket when the SCO connection is done
void cleanup();

// Read from the socket (audio server) for SCO Tx
size_t read(uint8_t* p_buf, uint32_t len);

// Write to the socket from SCO Rx
size_t write(const uint8_t* buf, uint32_t len);
}  // namespace bluetooth::audio::sco

/* Define the structures needed by sco
 */

typedef enum : uint16_t {
  SCO_ST_UNUSED = 0,
  SCO_ST_LISTENING = 1,
  SCO_ST_W4_CONN_RSP = 2,
  SCO_ST_CONNECTING = 3,
  SCO_ST_CONNECTED = 4,
  SCO_ST_DISCONNECTING = 5,
  SCO_ST_PEND_UNPARK = 6,
  SCO_ST_PEND_ROLECHANGE = 7,
  SCO_ST_PEND_MODECHANGE = 8,
} tSCO_STATE;

inline std::string sco_state_text(const tSCO_STATE& state) {
  switch (state) {
    case SCO_ST_UNUSED:
      return std::string("unused");
    case SCO_ST_LISTENING:
      return std::string("listening");
    case SCO_ST_W4_CONN_RSP:
      return std::string("connect_response");
    case SCO_ST_CONNECTING:
      return std::string("connecting");
    case SCO_ST_CONNECTED:
      return std::string("connected");
    case SCO_ST_DISCONNECTING:
      return std::string("disconnecting");
    case SCO_ST_PEND_UNPARK:
      return std::string("pending_unpark");
    case SCO_ST_PEND_ROLECHANGE:
      return std::string("pending_role_change");
    case SCO_ST_PEND_MODECHANGE:
      return std::string("pending_mode_change");
  }
}

/* Define the structure that contains (e)SCO data */
typedef struct {
  tBTM_ESCO_CBACK* p_esco_cback; /* Callback for eSCO events     */
  enh_esco_params_t setup;
  tBTM_ESCO_DATA data; /* Connection complete information */
  uint8_t hci_status;
} tBTM_ESCO_INFO;

/* Define the structure used for SCO Management
 */
typedef struct {
  tBTM_ESCO_INFO esco;    /* Current settings             */
  tBTM_SCO_CB* p_conn_cb; /* Callback for when connected  */
  tBTM_SCO_CB* p_disc_cb; /* Callback for when disconnect */
  tSCO_STATE state;       /* The state of the SCO link    */

  uint16_t hci_handle;    /* HCI Handle                   */
 public:
  bool is_active() const { return state != SCO_ST_UNUSED; }
  uint16_t Handle() const { return hci_handle; }

  bool is_orig;           /* true if the originator       */
  bool rem_bd_known;      /* true if remote BD addr known */

} tSCO_CONN;

/* SCO Management control block */
typedef struct {
  tSCO_CONN sco_db[BTM_MAX_SCO_LINKS];
  enh_esco_params_t def_esco_parms;
  bool esco_supported;        /* true if 1.2 cntlr AND supports eSCO links */

  tSCO_CONN* get_sco_connection_from_index(uint16_t index) {
    return (index < kMaxScoLinks) ? (&sco_db[index]) : nullptr;
  }

  tSCO_CONN* get_sco_connection_from_handle(uint16_t handle) {
    tSCO_CONN* p_sco = sco_db;
    for (uint16_t xx = 0; xx < kMaxScoLinks; xx++, p_sco++) {
      if (p_sco->hci_handle == handle) {
        return p_sco;
      }
    }
    return nullptr;
  }

  void Init() {
    def_esco_parms = esco_parameters_for_codec(ESCO_CODEC_CVSD_S3);
  }

  void Free() { bluetooth::audio::sco::cleanup(); }

  uint16_t get_index(const tSCO_CONN* p_sco) const {
    CHECK(p_sco != nullptr);
    const tSCO_CONN* p = sco_db;
    for (uint16_t xx = 0; xx < kMaxScoLinks; xx++, p++) {
      if (p_sco == p) {
        return xx;
      }
    }
    return 0xffff;
  }

} tSCO_CB;

extern void btm_sco_chk_pend_rolechange(uint16_t hci_handle);
extern void btm_sco_disc_chk_pend_for_modechange(uint16_t hci_handle);

// Visible for test only
BT_HDR* btm_sco_make_packet(std::vector<uint8_t> data, uint16_t sco_handle);

// Send a SCO packet
void btm_send_sco_packet(std::vector<uint8_t> data);