1 /* Spa SCO I/O
2  *
3  * Copyright © 2019 Collabora Ltd.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24 
25 #include <unistd.h>
26 #include <stddef.h>
27 #include <stdio.h>
28 #include <arpa/inet.h>
29 #include <sys/ioctl.h>
30 
31 #include <spa/support/plugin.h>
32 #include <spa/support/loop.h>
33 #include <spa/support/log.h>
34 #include <spa/support/system.h>
35 #include <spa/utils/list.h>
36 #include <spa/utils/keys.h>
37 #include <spa/utils/names.h>
38 #include <spa/monitor/device.h>
39 
40 #include <spa/node/node.h>
41 #include <spa/node/utils.h>
42 #include <spa/node/io.h>
43 #include <spa/node/keys.h>
44 #include <spa/param/param.h>
45 #include <spa/param/audio/format.h>
46 #include <spa/param/audio/format-utils.h>
47 #include <spa/pod/filter.h>
48 
49 #include <sbc/sbc.h>
50 
51 #include "defs.h"
52 
53 
54 /* We'll use the read rx data size to find the correct packet size for writing,
55  * since kernel might not report it as the socket MTU, see
56  * https://lore.kernel.org/linux-bluetooth/20201210003528.3pmaxvubiwegxmhl@pali/T/
57  *
58  * Since 24 is the packet size for the smallest setting (ALT1), we'll stop
59  * reading when rx packet of at least this size is seen, and use its size as the
60  * heuristic maximum write MTU. Of course, if we have a source connected, we'll
61  * continue reading without stopping.
62  *
63  * XXX: when the kernel/backends start giving the right values, the heuristic
64  * XXX: can be removed
65  */
66 #define HEURISTIC_MIN_MTU 24
67 
68 #define MAX_MTU 1024
69 
70 
71 struct spa_bt_sco_io {
72 	bool started;
73 
74 	uint8_t read_buffer[MAX_MTU];
75 	uint32_t read_size;
76 
77 	int fd;
78 	uint16_t read_mtu;
79 	uint16_t write_mtu;
80 
81 	struct spa_loop *data_loop;
82 	struct spa_source source;
83 
84 	int (*source_cb)(void *userdata, uint8_t *data, int size);
85 	void *source_userdata;
86 
87 	int (*sink_cb)(void *userdata);
88 	void *sink_userdata;
89 };
90 
91 
update_source(struct spa_bt_sco_io * io)92 static void update_source(struct spa_bt_sco_io *io)
93 {
94 	int enabled;
95 	int changed = 0;
96 
97 	enabled = io->source_cb != NULL || io->read_size < HEURISTIC_MIN_MTU;
98 	if (SPA_FLAG_IS_SET(io->source.mask, SPA_IO_IN) != enabled) {
99 		SPA_FLAG_UPDATE(io->source.mask, SPA_IO_IN, enabled);
100 		changed = 1;
101 	}
102 
103 	enabled = io->sink_cb != NULL;
104 	if (SPA_FLAG_IS_SET(io->source.mask, SPA_IO_OUT) != enabled) {
105 		SPA_FLAG_UPDATE(io->source.mask, SPA_IO_OUT, enabled);
106 		changed = 1;
107 	}
108 
109 	if (changed) {
110 		spa_loop_update_source(io->data_loop, &io->source);
111 	}
112 }
113 
sco_io_on_ready(struct spa_source * source)114 static void sco_io_on_ready(struct spa_source *source)
115 {
116 	struct spa_bt_sco_io *io = source->data;
117 
118 	if (SPA_FLAG_IS_SET(source->rmask, SPA_IO_IN)) {
119 		int res;
120 
121 		/*
122 		 * Note that we will read from the socket for a few times even
123 		 * when there is no source callback, to autodetect packet size.
124 		 */
125 
126 	read_again:
127 		res = read(io->fd, io->read_buffer, SPA_MIN(io->read_mtu, MAX_MTU));
128 		if (res <= 0) {
129 			if (errno == EINTR) {
130 				/* retry if interrupted */
131 				goto read_again;
132 			} else if (errno == EAGAIN || errno == EWOULDBLOCK) {
133 				/* no data: try it next time */
134 				goto read_done;
135 			}
136 
137 			/* error */
138 			goto stop;
139 		}
140 
141 		io->read_size = res;
142 
143 		if (io->source_cb) {
144 			int res;
145 			res = io->source_cb(io->source_userdata, io->read_buffer, io->read_size);
146 			if (res) {
147 				io->source_cb = NULL;
148 			}
149 		}
150 	}
151 
152 read_done:
153 	if (SPA_FLAG_IS_SET(source->rmask, SPA_IO_OUT)) {
154 		if (io->sink_cb) {
155 			int res;
156 			res = io->sink_cb(io->sink_userdata);
157 			if (res) {
158 				io->sink_cb = NULL;
159 			}
160 		}
161 	}
162 
163 	if (SPA_FLAG_IS_SET(source->rmask, SPA_IO_ERR) || SPA_FLAG_IS_SET(source->rmask, SPA_IO_HUP)) {
164 		goto stop;
165 	}
166 
167 	/* Poll socket in/out only if necessary */
168 	update_source(io);
169 
170 	return;
171 
172 stop:
173 	if (io->source.loop) {
174 		spa_loop_remove_source(io->data_loop, &io->source);
175 		io->started = false;
176 	}
177 }
178 
179 /*
180  * Write data to socket in correctly sized blocks.
181  * Returns the number of bytes written, 0 when data cannot be written now or
182  * there is too little of it to write, and <0 on write error.
183  */
spa_bt_sco_io_write(struct spa_bt_sco_io * io,uint8_t * buf,int size)184 int spa_bt_sco_io_write(struct spa_bt_sco_io *io, uint8_t *buf, int size)
185 {
186 	uint16_t packet_size;
187 	uint8_t *buf_start = buf;
188 
189 	if (io->read_size == 0) {
190 		/* The proper write packet size is not known yet */
191 		return 0;
192 	}
193 
194 	packet_size = SPA_MIN(io->write_mtu, io->read_size);
195 
196 	if (size < packet_size) {
197 		return 0;
198 	}
199 
200 	do {
201 		int written;
202 
203 		written = write(io->fd, buf, packet_size);
204 		if (written < 0) {
205 			if (errno == EINTR) {
206 				/* retry if interrupted */
207 				continue;
208 			} else if (errno == EAGAIN || errno == EWOULDBLOCK) {
209 				/* Don't continue writing */
210 				break;
211 			}
212 			return -errno;
213 		}
214 
215 		buf += written;
216 		size -= written;
217 	} while (size >= packet_size);
218 
219 	return buf - buf_start;
220 }
221 
222 
spa_bt_sco_io_create(struct spa_loop * data_loop,int fd,uint16_t read_mtu,uint16_t write_mtu)223 struct spa_bt_sco_io *spa_bt_sco_io_create(struct spa_loop *data_loop,
224                                            int fd,
225                                            uint16_t read_mtu,
226                                            uint16_t write_mtu)
227 {
228 	struct spa_bt_sco_io *io;
229 
230 	io = calloc(1, sizeof(struct spa_bt_sco_io));
231 	if (io == NULL)
232 		return io;
233 
234 	io->fd = fd;
235 	io->read_mtu = read_mtu;
236 	io->write_mtu = write_mtu;
237 	io->data_loop = data_loop;
238 
239 	io->read_size = 0;
240 
241 	/* Add the ready callback */
242 	io->source.data = io;
243 	io->source.fd = io->fd;
244 	io->source.func = sco_io_on_ready;
245 	io->source.mask = SPA_IO_IN | SPA_IO_OUT | SPA_IO_ERR | SPA_IO_HUP;
246 	io->source.rmask = 0;
247 	spa_loop_add_source(io->data_loop, &io->source);
248 
249 	io->started = true;
250 
251 	return io;
252 }
253 
do_remove_source(struct spa_loop * loop,bool async,uint32_t seq,const void * data,size_t size,void * user_data)254 static int do_remove_source(struct spa_loop *loop,
255                             bool async,
256                             uint32_t seq,
257                             const void *data,
258                             size_t size,
259                             void *user_data)
260 {
261 	struct spa_bt_sco_io *io = user_data;
262 
263 	if (io->source.loop)
264 		spa_loop_remove_source(io->data_loop, &io->source);
265 
266 	return 0;
267 }
268 
spa_bt_sco_io_destroy(struct spa_bt_sco_io * io)269 void spa_bt_sco_io_destroy(struct spa_bt_sco_io *io)
270 {
271 	if (io->started)
272 		spa_loop_invoke(io->data_loop, do_remove_source, 0, NULL, 0, true, io);
273 
274 	io->started = false;
275 	free(io);
276 }
277 
278 /* Set source callback.
279  * This function should only be called from the data thread.
280  * Callback is called (in data loop) with data just read from the socket.
281  */
spa_bt_sco_io_set_source_cb(struct spa_bt_sco_io * io,int (* source_cb)(void *,uint8_t *,int),void * userdata)282 void spa_bt_sco_io_set_source_cb(struct spa_bt_sco_io *io, int (*source_cb)(void *, uint8_t *, int), void *userdata)
283 {
284 	io->source_cb = source_cb;
285 	io->source_userdata = userdata;
286 
287 	if (io->started) {
288 		update_source(io);
289 	}
290 }
291 
292 /* Set sink callback.
293  * This function should only be called from the data thread.
294  * Callback is called (in data loop) when socket can be written to.
295  */
spa_bt_sco_io_set_sink_cb(struct spa_bt_sco_io * io,int (* sink_cb)(void *),void * userdata)296 void spa_bt_sco_io_set_sink_cb(struct spa_bt_sco_io *io, int (*sink_cb)(void *), void *userdata)
297 {
298 	io->sink_cb = sink_cb;
299 	io->sink_userdata = userdata;
300 
301 	if (io->started) {
302 		update_source(io);
303 	}
304 }
305