Skip to content

Commit 2bfebaf

Browse files
Jeremy WuChromeos LUCI
Jeremy Wu
authored and
Chromeos LUCI
committed
floss: declare |lea_iodev| skeleton
This CL declares |lea_iodev| that will be used as the abstraction of LE audio groups as audio input output devices. BUG=b:317682584 TEST=Apply full patch series and verify unicast works Change-Id: Ic67258fda0084951c57726cff09b64573eaec81b Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/adhd/+/5467606 Commit-Queue: Jeremy Wu <[email protected]> Tested-by: [email protected] <[email protected]> Reviewed-by: Hsinyu Chao <[email protected]>
1 parent 7948fa0 commit 2bfebaf

File tree

3 files changed

+192
-0
lines changed

3 files changed

+192
-0
lines changed

cras/src/server/BUILD.bazel

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,8 @@ cc_library(
437437
"cras_alsa_usb_io.h",
438438
"cras_audio_thread_monitor.c",
439439
"cras_audio_thread_monitor.h",
440+
"cras_lea_iodev.c",
441+
"cras_lea_iodev.h",
440442
"cras_bt_adapter.c",
441443
"cras_bt_adapter.h",
442444
"cras_bt_battery_provider.c",

cras/src/server/cras_lea_iodev.c

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
/* Copyright 2024 The ChromiumOS Authors
2+
* Use of this source code is governed by a BSD-style license that can be
3+
* found in the LICENSE file.
4+
*/
5+
6+
#include <errno.h>
7+
#include <stdint.h>
8+
#include <sys/ioctl.h>
9+
#include <sys/param.h>
10+
#include <sys/socket.h>
11+
#include <sys/time.h>
12+
#include <sys/un.h>
13+
#include <syslog.h>
14+
#include <time.h>
15+
16+
#include "cras/src/common/byte_buffer.h"
17+
#include "cras/src/common/cras_string.h"
18+
#include "cras/src/server/audio_thread.h"
19+
#include "cras/src/server/audio_thread_log.h"
20+
#include "cras/src/server/cras_audio_area.h"
21+
#include "cras/src/server/cras_audio_thread_monitor.h"
22+
#include "cras/src/server/cras_iodev.h"
23+
#include "cras/src/server/cras_iodev_list.h"
24+
#include "cras/src/server/cras_utf8.h"
25+
#include "cras_types.h"
26+
#include "cras_util.h"
27+
#include "third_party/superfasthash/sfh.h"
28+
#include "third_party/utlist/utlist.h"
29+
30+
#define PCM_BUF_MAX_SIZE_FRAMES (8192 * 4)
31+
#define PCM_BLOCK_MS 10
32+
33+
#define FLOSS_LEA_MAX_BUF_SIZE_BYTES PCM_BUF_MAX_SIZE_FRAMES * 8
34+
35+
// Child of cras_iodev to handle LEA streaming.
36+
struct lea_io {
37+
// The cras_iodev structure "base class"
38+
struct cras_iodev base;
39+
// Buffer to hold pcm samples.
40+
struct byte_buffer* pcm_buf;
41+
// How many frames of audio samples we prefer to write in one
42+
// socket write.
43+
unsigned int write_block;
44+
// The associated ID of the corresponding LE audio group.
45+
int group_id;
46+
// If the device has been configured and attached with any stream.
47+
int started;
48+
};
49+
50+
static void lea_free_base_resources(struct lea_io* leaio) {
51+
struct cras_ionode* node;
52+
node = leaio->base.active_node;
53+
if (node) {
54+
cras_iodev_rm_node(&leaio->base, node);
55+
free(node);
56+
}
57+
free(leaio->base.supported_channel_counts);
58+
free(leaio->base.supported_rates);
59+
free(leaio->base.supported_formats);
60+
}
61+
62+
struct cras_iodev* lea_iodev_create(const char* name,
63+
int group_id,
64+
enum CRAS_STREAM_DIRECTION dir) {
65+
struct lea_io* leaio;
66+
struct cras_iodev* iodev;
67+
struct cras_ionode* node;
68+
int rc = 0;
69+
70+
leaio = (struct lea_io*)calloc(1, sizeof(*leaio));
71+
if (!leaio) {
72+
return NULL;
73+
}
74+
75+
leaio->started = 0;
76+
leaio->group_id = group_id;
77+
78+
iodev = &leaio->base;
79+
iodev->direction = dir;
80+
81+
snprintf(iodev->info.name, sizeof(iodev->info.name), "%s group %d", name,
82+
group_id);
83+
iodev->info.name[ARRAY_SIZE(iodev->info.name) - 1] = '\0';
84+
iodev->info.stable_id = SuperFastHash(
85+
iodev->info.name, strlen(iodev->info.name), strlen(iodev->info.name));
86+
87+
// Create an empty ionode
88+
node = (struct cras_ionode*)calloc(1, sizeof(*node));
89+
node->dev = iodev;
90+
node->btflags = CRAS_BT_FLAG_FLOSS | CRAS_BT_FLAG_LEA;
91+
node->type = CRAS_NODE_TYPE_BLUETOOTH;
92+
node->volume = 100;
93+
node->stable_id = iodev->info.stable_id;
94+
strlcpy(node->name, iodev->info.name, sizeof(node->name));
95+
node->ui_gain_scaler = 1.0f;
96+
gettimeofday(&node->plugged_time, NULL);
97+
98+
// The node name exposed to UI should be a valid UTF8 string.
99+
if (!is_utf8_string(node->name)) {
100+
strlcpy(node->name, "LEA UTF8 Group Name", sizeof(node->name));
101+
}
102+
103+
ewma_power_disable(&iodev->ewma);
104+
105+
cras_iodev_add_node(iodev, node);
106+
107+
if (iodev->direction == CRAS_STREAM_OUTPUT) {
108+
rc = cras_iodev_list_add(iodev);
109+
} else if (iodev->direction == CRAS_STREAM_INPUT) {
110+
rc = cras_iodev_list_add(iodev);
111+
}
112+
if (rc) {
113+
syslog(LOG_ERR, "Add LEA iodev to list err");
114+
goto error;
115+
}
116+
cras_iodev_set_active_node(iodev, node);
117+
118+
/* We need the buffer to read/write data from/to the LEA group even
119+
* when there is no corresponding stream. */
120+
leaio->pcm_buf = byte_buffer_create(FLOSS_LEA_MAX_BUF_SIZE_BYTES);
121+
if (!leaio->pcm_buf) {
122+
goto error;
123+
}
124+
125+
return iodev;
126+
error:
127+
lea_free_base_resources(leaio);
128+
free(leaio);
129+
return NULL;
130+
}
131+
132+
void lea_iodev_destroy(struct cras_iodev* iodev) {
133+
int rc;
134+
struct lea_io* leaio = (struct lea_io*)iodev;
135+
136+
byte_buffer_destroy(&leaio->pcm_buf);
137+
if (iodev->direction == CRAS_STREAM_OUTPUT) {
138+
rc = cras_iodev_list_rm(iodev);
139+
} else if (iodev->direction == CRAS_STREAM_INPUT) {
140+
rc = cras_iodev_list_rm(iodev);
141+
} else {
142+
syslog(LOG_ERR, "%s: Unsupported direction %d", __func__, iodev->direction);
143+
return;
144+
}
145+
146+
if (rc < 0) {
147+
syslog(LOG_ERR, "%s: Failed to remove iodev, rc=%d", __func__, rc);
148+
return;
149+
}
150+
151+
lea_free_base_resources(leaio);
152+
cras_iodev_free_resources(iodev);
153+
free(leaio);
154+
}

cras/src/server/cras_lea_iodev.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/* Copyright 2024 The ChromiumOS Authors
2+
* Use of this source code is governed by a BSD-style license that can be
3+
* found in the LICENSE file.
4+
*/
5+
6+
#ifndef CRAS_SRC_SERVER_CRAS_LEA_IODEV_H_
7+
#define CRAS_SRC_SERVER_CRAS_LEA_IODEV_H_
8+
9+
#include <stdint.h>
10+
11+
#include "cras_types.h"
12+
13+
#ifdef __cplusplus
14+
extern "C" {
15+
#endif
16+
17+
/* Creates a lea iodev representing a group.
18+
* Note that if a group supports both input and output, two `lea_iodev`s
19+
* will be instantiated.
20+
* Args:
21+
* name - Name associated to the LE audio group.
22+
* group - ID of the associated group.
23+
* dir - The direction of the iodev.
24+
*/
25+
struct cras_iodev* lea_iodev_create(const char* name,
26+
int group_id,
27+
enum CRAS_STREAM_DIRECTION dir);
28+
29+
// Destroys a lea iodev.
30+
void lea_iodev_destroy(struct cras_iodev* iodev);
31+
32+
#ifdef __cplusplus
33+
} // extern "C"
34+
#endif
35+
36+
#endif // CRAS_SRC_SERVER_CRAS_LEA_IODEV_H_

0 commit comments

Comments
 (0)