1*9cab9fdeSChristos Margiolis /*-
2*9cab9fdeSChristos Margiolis * Copyright (c) 2019 Google LLC, written by Richard Kralovic <riso@google.com>
3*9cab9fdeSChristos Margiolis *
4*9cab9fdeSChristos Margiolis * Redistribution and use in source and binary forms, with or without
5*9cab9fdeSChristos Margiolis * modification, are permitted provided that the following conditions
6*9cab9fdeSChristos Margiolis * are met:
7*9cab9fdeSChristos Margiolis * 1. Redistributions of source code must retain the above copyright
8*9cab9fdeSChristos Margiolis * notice, this list of conditions and the following disclaimer.
9*9cab9fdeSChristos Margiolis * 2. Redistributions in binary form must reproduce the above copyright
10*9cab9fdeSChristos Margiolis * notice, this list of conditions and the following disclaimer in the
11*9cab9fdeSChristos Margiolis * documentation and/or other materials provided with the distribution.
12*9cab9fdeSChristos Margiolis *
13*9cab9fdeSChristos Margiolis * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14*9cab9fdeSChristos Margiolis * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15*9cab9fdeSChristos Margiolis * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16*9cab9fdeSChristos Margiolis * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17*9cab9fdeSChristos Margiolis * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18*9cab9fdeSChristos Margiolis * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19*9cab9fdeSChristos Margiolis * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20*9cab9fdeSChristos Margiolis * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21*9cab9fdeSChristos Margiolis * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22*9cab9fdeSChristos Margiolis * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23*9cab9fdeSChristos Margiolis * SUCH DAMAGE.
24*9cab9fdeSChristos Margiolis */
25*9cab9fdeSChristos Margiolis
26*9cab9fdeSChristos Margiolis #include <sys/types.h>
27*9cab9fdeSChristos Margiolis #include <sys/rtprio.h>
28*9cab9fdeSChristos Margiolis #include <sys/soundcard.h>
29*9cab9fdeSChristos Margiolis
30*9cab9fdeSChristos Margiolis #include <dlfcn.h>
31*9cab9fdeSChristos Margiolis #include <err.h>
32*9cab9fdeSChristos Margiolis #include <fcntl.h>
33*9cab9fdeSChristos Margiolis #include <stdarg.h>
34*9cab9fdeSChristos Margiolis #include <stdint.h>
35*9cab9fdeSChristos Margiolis #include <stdio.h>
36*9cab9fdeSChristos Margiolis #include <stdlib.h>
37*9cab9fdeSChristos Margiolis #include <string.h>
38*9cab9fdeSChristos Margiolis #include <sysexits.h>
39*9cab9fdeSChristos Margiolis #include <time.h>
40*9cab9fdeSChristos Margiolis #include <unistd.h>
41*9cab9fdeSChristos Margiolis #include <poll.h>
42*9cab9fdeSChristos Margiolis #include <getopt.h>
43*9cab9fdeSChristos Margiolis
44*9cab9fdeSChristos Margiolis #define L2CAP_SOCKET_CHECKED
45*9cab9fdeSChristos Margiolis #include <bluetooth.h>
46*9cab9fdeSChristos Margiolis #include <sdp.h>
47*9cab9fdeSChristos Margiolis
48*9cab9fdeSChristos Margiolis #include "avdtp_signal.h"
49*9cab9fdeSChristos Margiolis #include "bt.h"
50*9cab9fdeSChristos Margiolis #include "utils.h"
51*9cab9fdeSChristos Margiolis
52*9cab9fdeSChristos Margiolis static int (*bt_receive_f)(struct bt_config *, void *, int, int);
53*9cab9fdeSChristos Margiolis static int (*avdtpACPHandlePacket_f)(struct bt_config *cfg);
54*9cab9fdeSChristos Margiolis static void (*avdtpACPFree_f)(struct bt_config *);
55*9cab9fdeSChristos Margiolis
56*9cab9fdeSChristos Margiolis static int bt_in_background;
57*9cab9fdeSChristos Margiolis
58*9cab9fdeSChristos Margiolis static void
message(const char * fmt,...)59*9cab9fdeSChristos Margiolis message(const char *fmt,...)
60*9cab9fdeSChristos Margiolis {
61*9cab9fdeSChristos Margiolis va_list list;
62*9cab9fdeSChristos Margiolis
63*9cab9fdeSChristos Margiolis if (bt_in_background)
64*9cab9fdeSChristos Margiolis return;
65*9cab9fdeSChristos Margiolis
66*9cab9fdeSChristos Margiolis va_start(list, fmt);
67*9cab9fdeSChristos Margiolis vfprintf(stderr, fmt, list);
68*9cab9fdeSChristos Margiolis va_end(list);
69*9cab9fdeSChristos Margiolis }
70*9cab9fdeSChristos Margiolis
71*9cab9fdeSChristos Margiolis struct bt_audio_receiver {
72*9cab9fdeSChristos Margiolis const char *devname;
73*9cab9fdeSChristos Margiolis const char *sdp_socket_path;
74*9cab9fdeSChristos Margiolis uint16_t l2cap_psm;
75*9cab9fdeSChristos Margiolis int fd_listen;
76*9cab9fdeSChristos Margiolis void *sdp_session;
77*9cab9fdeSChristos Margiolis uint32_t sdp_handle;
78*9cab9fdeSChristos Margiolis };
79*9cab9fdeSChristos Margiolis
80*9cab9fdeSChristos Margiolis static int
register_sdp(struct bt_audio_receiver * r)81*9cab9fdeSChristos Margiolis register_sdp(struct bt_audio_receiver *r)
82*9cab9fdeSChristos Margiolis {
83*9cab9fdeSChristos Margiolis struct sdp_audio_sink_profile record = {};
84*9cab9fdeSChristos Margiolis
85*9cab9fdeSChristos Margiolis r->sdp_session = sdp_open_local(r->sdp_socket_path);
86*9cab9fdeSChristos Margiolis if (r->sdp_session == NULL || sdp_error(r->sdp_session)) {
87*9cab9fdeSChristos Margiolis sdp_close(r->sdp_session);
88*9cab9fdeSChristos Margiolis r->sdp_session = NULL;
89*9cab9fdeSChristos Margiolis return (0);
90*9cab9fdeSChristos Margiolis }
91*9cab9fdeSChristos Margiolis
92*9cab9fdeSChristos Margiolis record.psm = r->l2cap_psm;
93*9cab9fdeSChristos Margiolis record.protover = 0x100;
94*9cab9fdeSChristos Margiolis record.features = 0x01; /* player only */
95*9cab9fdeSChristos Margiolis
96*9cab9fdeSChristos Margiolis if (sdp_register_service(r->sdp_session, SDP_SERVICE_CLASS_AUDIO_SINK,
97*9cab9fdeSChristos Margiolis NG_HCI_BDADDR_ANY, (const uint8_t *)&record, sizeof(record),
98*9cab9fdeSChristos Margiolis &r->sdp_handle)) {
99*9cab9fdeSChristos Margiolis message("SDP failed to register: %s\n",
100*9cab9fdeSChristos Margiolis strerror(sdp_error(r->sdp_session)));
101*9cab9fdeSChristos Margiolis sdp_close(r->sdp_session);
102*9cab9fdeSChristos Margiolis r->sdp_session = NULL;
103*9cab9fdeSChristos Margiolis return (0);
104*9cab9fdeSChristos Margiolis }
105*9cab9fdeSChristos Margiolis return (1);
106*9cab9fdeSChristos Margiolis }
107*9cab9fdeSChristos Margiolis
108*9cab9fdeSChristos Margiolis static void
unregister_sdp(struct bt_audio_receiver * r)109*9cab9fdeSChristos Margiolis unregister_sdp(struct bt_audio_receiver *r)
110*9cab9fdeSChristos Margiolis {
111*9cab9fdeSChristos Margiolis sdp_unregister_service(r->sdp_session, r->sdp_handle);
112*9cab9fdeSChristos Margiolis sdp_close(r->sdp_session);
113*9cab9fdeSChristos Margiolis r->sdp_session = NULL;
114*9cab9fdeSChristos Margiolis }
115*9cab9fdeSChristos Margiolis
116*9cab9fdeSChristos Margiolis static int
start_listen(struct bt_audio_receiver * r)117*9cab9fdeSChristos Margiolis start_listen(struct bt_audio_receiver *r)
118*9cab9fdeSChristos Margiolis {
119*9cab9fdeSChristos Margiolis struct sockaddr_l2cap addr = {};
120*9cab9fdeSChristos Margiolis
121*9cab9fdeSChristos Margiolis r->fd_listen = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BLUETOOTH_PROTO_L2CAP);
122*9cab9fdeSChristos Margiolis if (r->fd_listen < 0)
123*9cab9fdeSChristos Margiolis return (0);
124*9cab9fdeSChristos Margiolis
125*9cab9fdeSChristos Margiolis addr.l2cap_len = sizeof(addr);
126*9cab9fdeSChristos Margiolis addr.l2cap_family = AF_BLUETOOTH;
127*9cab9fdeSChristos Margiolis addr.l2cap_psm = r->l2cap_psm;
128*9cab9fdeSChristos Margiolis
129*9cab9fdeSChristos Margiolis if (bind(r->fd_listen, (struct sockaddr *)&addr, sizeof(addr)) < 0 ||
130*9cab9fdeSChristos Margiolis listen(r->fd_listen, 4) < 0) {
131*9cab9fdeSChristos Margiolis close(r->fd_listen);
132*9cab9fdeSChristos Margiolis return (0);
133*9cab9fdeSChristos Margiolis }
134*9cab9fdeSChristos Margiolis return (1);
135*9cab9fdeSChristos Margiolis }
136*9cab9fdeSChristos Margiolis
137*9cab9fdeSChristos Margiolis static void
stop_listen(struct bt_audio_receiver * r)138*9cab9fdeSChristos Margiolis stop_listen(struct bt_audio_receiver *r)
139*9cab9fdeSChristos Margiolis {
140*9cab9fdeSChristos Margiolis close(r->fd_listen);
141*9cab9fdeSChristos Margiolis }
142*9cab9fdeSChristos Margiolis
143*9cab9fdeSChristos Margiolis struct bt_audio_connection {
144*9cab9fdeSChristos Margiolis struct bt_audio_receiver *r;
145*9cab9fdeSChristos Margiolis struct sockaddr_l2cap peer_addr;
146*9cab9fdeSChristos Margiolis struct bt_config cfg;
147*9cab9fdeSChristos Margiolis int oss_fd;
148*9cab9fdeSChristos Margiolis };
149*9cab9fdeSChristos Margiolis
150*9cab9fdeSChristos Margiolis static void
close_connection(struct bt_audio_connection * c)151*9cab9fdeSChristos Margiolis close_connection(struct bt_audio_connection *c)
152*9cab9fdeSChristos Margiolis {
153*9cab9fdeSChristos Margiolis avdtpACPFree_f(&c->cfg);
154*9cab9fdeSChristos Margiolis if (c->cfg.fd != -1)
155*9cab9fdeSChristos Margiolis close(c->cfg.fd);
156*9cab9fdeSChristos Margiolis if (c->cfg.hc != -1)
157*9cab9fdeSChristos Margiolis close(c->cfg.hc);
158*9cab9fdeSChristos Margiolis if (c->oss_fd != -1)
159*9cab9fdeSChristos Margiolis close(c->oss_fd);
160*9cab9fdeSChristos Margiolis free(c);
161*9cab9fdeSChristos Margiolis }
162*9cab9fdeSChristos Margiolis
163*9cab9fdeSChristos Margiolis static struct bt_audio_connection *
wait_for_connection(struct bt_audio_receiver * r)164*9cab9fdeSChristos Margiolis wait_for_connection(struct bt_audio_receiver *r)
165*9cab9fdeSChristos Margiolis {
166*9cab9fdeSChristos Margiolis struct bt_audio_connection *c =
167*9cab9fdeSChristos Margiolis malloc(sizeof(struct bt_audio_connection));
168*9cab9fdeSChristos Margiolis socklen_t addrlen;
169*9cab9fdeSChristos Margiolis
170*9cab9fdeSChristos Margiolis memset(c, 0, sizeof(*c));
171*9cab9fdeSChristos Margiolis
172*9cab9fdeSChristos Margiolis c->r = r;
173*9cab9fdeSChristos Margiolis c->cfg.fd = -1;
174*9cab9fdeSChristos Margiolis c->oss_fd = -1;
175*9cab9fdeSChristos Margiolis
176*9cab9fdeSChristos Margiolis addrlen = sizeof(c->peer_addr);
177*9cab9fdeSChristos Margiolis c->cfg.hc = accept(r->fd_listen, (struct sockaddr *)&c->peer_addr, &addrlen);
178*9cab9fdeSChristos Margiolis
179*9cab9fdeSChristos Margiolis message("Accepted control connection, %d\n", c->cfg.hc);
180*9cab9fdeSChristos Margiolis if (c->cfg.hc < 0) {
181*9cab9fdeSChristos Margiolis close_connection(c);
182*9cab9fdeSChristos Margiolis return NULL;
183*9cab9fdeSChristos Margiolis }
184*9cab9fdeSChristos Margiolis c->cfg.sep = 0; /* to be set later */
185*9cab9fdeSChristos Margiolis c->cfg.media_Type = mediaTypeAudio;
186*9cab9fdeSChristos Margiolis c->cfg.chmode = MODE_DUAL;
187*9cab9fdeSChristos Margiolis c->cfg.aacMode1 = 0; /* TODO: support AAC */
188*9cab9fdeSChristos Margiolis c->cfg.aacMode2 = 0;
189*9cab9fdeSChristos Margiolis c->cfg.acceptor_state = acpInitial;
190*9cab9fdeSChristos Margiolis
191*9cab9fdeSChristos Margiolis return (c);
192*9cab9fdeSChristos Margiolis }
193*9cab9fdeSChristos Margiolis
194*9cab9fdeSChristos Margiolis static void
setup_oss(struct bt_audio_connection * c)195*9cab9fdeSChristos Margiolis setup_oss(struct bt_audio_connection *c)
196*9cab9fdeSChristos Margiolis {
197*9cab9fdeSChristos Margiolis c->oss_fd = open(c->r->devname, O_WRONLY);
198*9cab9fdeSChristos Margiolis
199*9cab9fdeSChristos Margiolis if (c->oss_fd < 0)
200*9cab9fdeSChristos Margiolis goto err;
201*9cab9fdeSChristos Margiolis
202*9cab9fdeSChristos Margiolis int v;
203*9cab9fdeSChristos Margiolis
204*9cab9fdeSChristos Margiolis switch (c->cfg.chmode) {
205*9cab9fdeSChristos Margiolis case MODE_STEREO:
206*9cab9fdeSChristos Margiolis case MODE_JOINT:
207*9cab9fdeSChristos Margiolis case MODE_DUAL:
208*9cab9fdeSChristos Margiolis v = 2;
209*9cab9fdeSChristos Margiolis break;
210*9cab9fdeSChristos Margiolis case MODE_MONO:
211*9cab9fdeSChristos Margiolis v = 1;
212*9cab9fdeSChristos Margiolis break;
213*9cab9fdeSChristos Margiolis default:
214*9cab9fdeSChristos Margiolis message("Wrong chmode\n");
215*9cab9fdeSChristos Margiolis goto err;
216*9cab9fdeSChristos Margiolis }
217*9cab9fdeSChristos Margiolis
218*9cab9fdeSChristos Margiolis if (ioctl(c->oss_fd, SNDCTL_DSP_CHANNELS, &v) < 0) {
219*9cab9fdeSChristos Margiolis message("SNDCTL_DSP_CHANNELS failed\n");
220*9cab9fdeSChristos Margiolis goto err;
221*9cab9fdeSChristos Margiolis }
222*9cab9fdeSChristos Margiolis v = AFMT_S16_NE;
223*9cab9fdeSChristos Margiolis if (ioctl(c->oss_fd, SNDCTL_DSP_SETFMT, &v) < 0) {
224*9cab9fdeSChristos Margiolis message("SNDCTL_DSP_SETFMT failed\n");
225*9cab9fdeSChristos Margiolis goto err;
226*9cab9fdeSChristos Margiolis }
227*9cab9fdeSChristos Margiolis switch (c->cfg.freq) {
228*9cab9fdeSChristos Margiolis case FREQ_16K:
229*9cab9fdeSChristos Margiolis v = 16000;
230*9cab9fdeSChristos Margiolis break;
231*9cab9fdeSChristos Margiolis case FREQ_32K:
232*9cab9fdeSChristos Margiolis v = 32000;
233*9cab9fdeSChristos Margiolis break;
234*9cab9fdeSChristos Margiolis case FREQ_44_1K:
235*9cab9fdeSChristos Margiolis v = 44100;
236*9cab9fdeSChristos Margiolis break;
237*9cab9fdeSChristos Margiolis case FREQ_48K:
238*9cab9fdeSChristos Margiolis v = 48000;
239*9cab9fdeSChristos Margiolis break;
240*9cab9fdeSChristos Margiolis default:
241*9cab9fdeSChristos Margiolis message("Wrong freq\n");
242*9cab9fdeSChristos Margiolis goto err;
243*9cab9fdeSChristos Margiolis }
244*9cab9fdeSChristos Margiolis
245*9cab9fdeSChristos Margiolis if (ioctl(c->oss_fd, SNDCTL_DSP_SPEED, &v) < 0) {
246*9cab9fdeSChristos Margiolis message("SNDCTL_DSP_SETFMT failed\n");
247*9cab9fdeSChristos Margiolis goto err;
248*9cab9fdeSChristos Margiolis }
249*9cab9fdeSChristos Margiolis v = (2 << 16) | 15; /* 2 fragments of 32k each */
250*9cab9fdeSChristos Margiolis if (ioctl(c->oss_fd, SNDCTL_DSP_SETFRAGMENT, &v) < 0) {
251*9cab9fdeSChristos Margiolis message("SNDCTL_DSP_SETFRAGMENT failed\n");
252*9cab9fdeSChristos Margiolis goto err;
253*9cab9fdeSChristos Margiolis }
254*9cab9fdeSChristos Margiolis return;
255*9cab9fdeSChristos Margiolis
256*9cab9fdeSChristos Margiolis err:
257*9cab9fdeSChristos Margiolis c->oss_fd = -1;
258*9cab9fdeSChristos Margiolis message("Cannot open oss device %s\n", c->r->devname);
259*9cab9fdeSChristos Margiolis }
260*9cab9fdeSChristos Margiolis
261*9cab9fdeSChristos Margiolis static void
process_connection(struct bt_audio_connection * c)262*9cab9fdeSChristos Margiolis process_connection(struct bt_audio_connection *c)
263*9cab9fdeSChristos Margiolis {
264*9cab9fdeSChristos Margiolis struct pollfd pfd[3] = {};
265*9cab9fdeSChristos Margiolis time_t oss_attempt = 0;
266*9cab9fdeSChristos Margiolis
267*9cab9fdeSChristos Margiolis while (c->cfg.acceptor_state != acpStreamClosed) {
268*9cab9fdeSChristos Margiolis int np;
269*9cab9fdeSChristos Margiolis
270*9cab9fdeSChristos Margiolis pfd[0].fd = c->r->fd_listen;
271*9cab9fdeSChristos Margiolis pfd[0].events = POLLIN | POLLRDNORM;
272*9cab9fdeSChristos Margiolis pfd[0].revents = 0;
273*9cab9fdeSChristos Margiolis
274*9cab9fdeSChristos Margiolis pfd[1].fd = c->cfg.hc;
275*9cab9fdeSChristos Margiolis pfd[1].events = POLLIN | POLLRDNORM;
276*9cab9fdeSChristos Margiolis pfd[1].revents = 0;
277*9cab9fdeSChristos Margiolis
278*9cab9fdeSChristos Margiolis pfd[2].fd = c->cfg.fd;
279*9cab9fdeSChristos Margiolis pfd[2].events = POLLIN | POLLRDNORM;
280*9cab9fdeSChristos Margiolis pfd[2].revents = 0;
281*9cab9fdeSChristos Margiolis
282*9cab9fdeSChristos Margiolis if (c->cfg.fd != -1)
283*9cab9fdeSChristos Margiolis np = 3;
284*9cab9fdeSChristos Margiolis else
285*9cab9fdeSChristos Margiolis np = 2;
286*9cab9fdeSChristos Margiolis
287*9cab9fdeSChristos Margiolis if (poll(pfd, np, INFTIM) < 0)
288*9cab9fdeSChristos Margiolis return;
289*9cab9fdeSChristos Margiolis
290*9cab9fdeSChristos Margiolis if (pfd[1].revents != 0) {
291*9cab9fdeSChristos Margiolis int retval;
292*9cab9fdeSChristos Margiolis
293*9cab9fdeSChristos Margiolis message("Handling packet: state = %d, ",
294*9cab9fdeSChristos Margiolis c->cfg.acceptor_state);
295*9cab9fdeSChristos Margiolis retval = avdtpACPHandlePacket_f(&c->cfg);
296*9cab9fdeSChristos Margiolis message("retval = %d\n", retval);
297*9cab9fdeSChristos Margiolis if (retval < 0)
298*9cab9fdeSChristos Margiolis return;
299*9cab9fdeSChristos Margiolis }
300*9cab9fdeSChristos Margiolis if (pfd[0].revents != 0) {
301*9cab9fdeSChristos Margiolis socklen_t addrlen = sizeof(c->peer_addr);
302*9cab9fdeSChristos Margiolis int fd = accept4(c->r->fd_listen,
303*9cab9fdeSChristos Margiolis (struct sockaddr *)&c->peer_addr, &addrlen,
304*9cab9fdeSChristos Margiolis SOCK_NONBLOCK);
305*9cab9fdeSChristos Margiolis
306*9cab9fdeSChristos Margiolis if (fd < 0)
307*9cab9fdeSChristos Margiolis return;
308*9cab9fdeSChristos Margiolis
309*9cab9fdeSChristos Margiolis if (c->cfg.fd < 0) {
310*9cab9fdeSChristos Margiolis if (c->cfg.acceptor_state == acpStreamOpened) {
311*9cab9fdeSChristos Margiolis socklen_t mtusize = sizeof(uint16_t);
312*9cab9fdeSChristos Margiolis c->cfg.fd = fd;
313*9cab9fdeSChristos Margiolis
314*9cab9fdeSChristos Margiolis if (getsockopt(c->cfg.fd, SOL_L2CAP, SO_L2CAP_IMTU, &c->cfg.mtu, &mtusize) == -1) {
315*9cab9fdeSChristos Margiolis message("Could not get MTU size\n");
316*9cab9fdeSChristos Margiolis return;
317*9cab9fdeSChristos Margiolis }
318*9cab9fdeSChristos Margiolis
319*9cab9fdeSChristos Margiolis int temp = c->cfg.mtu * 32;
320*9cab9fdeSChristos Margiolis
321*9cab9fdeSChristos Margiolis if (setsockopt(c->cfg.fd, SOL_SOCKET, SO_RCVBUF, &temp, sizeof(temp)) == -1) {
322*9cab9fdeSChristos Margiolis message("Could not set send buffer size\n");
323*9cab9fdeSChristos Margiolis return;
324*9cab9fdeSChristos Margiolis }
325*9cab9fdeSChristos Margiolis
326*9cab9fdeSChristos Margiolis temp = 1;
327*9cab9fdeSChristos Margiolis if (setsockopt(c->cfg.fd, SOL_SOCKET, SO_RCVLOWAT, &temp, sizeof(temp)) == -1) {
328*9cab9fdeSChristos Margiolis message("Could not set low water mark\n");
329*9cab9fdeSChristos Margiolis return;
330*9cab9fdeSChristos Margiolis }
331*9cab9fdeSChristos Margiolis message("Accepted data connection, %d\n", c->cfg.fd);
332*9cab9fdeSChristos Margiolis }
333*9cab9fdeSChristos Margiolis } else {
334*9cab9fdeSChristos Margiolis close(fd);
335*9cab9fdeSChristos Margiolis }
336*9cab9fdeSChristos Margiolis }
337*9cab9fdeSChristos Margiolis if (pfd[2].revents != 0) {
338*9cab9fdeSChristos Margiolis uint8_t data[65536];
339*9cab9fdeSChristos Margiolis int len;
340*9cab9fdeSChristos Margiolis
341*9cab9fdeSChristos Margiolis if ((len = bt_receive_f(&c->cfg, data, sizeof(data), 0)) < 0) {
342*9cab9fdeSChristos Margiolis return;
343*9cab9fdeSChristos Margiolis }
344*9cab9fdeSChristos Margiolis if (c->cfg.acceptor_state != acpStreamSuspended &&
345*9cab9fdeSChristos Margiolis c->oss_fd < 0 &&
346*9cab9fdeSChristos Margiolis time(NULL) != oss_attempt) {
347*9cab9fdeSChristos Margiolis message("Trying to open dsp\n");
348*9cab9fdeSChristos Margiolis setup_oss(c);
349*9cab9fdeSChristos Margiolis oss_attempt = time(NULL);
350*9cab9fdeSChristos Margiolis }
351*9cab9fdeSChristos Margiolis if (c->oss_fd > -1) {
352*9cab9fdeSChristos Margiolis uint8_t *end = data + len;
353*9cab9fdeSChristos Margiolis uint8_t *ptr = data;
354*9cab9fdeSChristos Margiolis unsigned delay;
355*9cab9fdeSChristos Margiolis unsigned jitter_limit;
356*9cab9fdeSChristos Margiolis
357*9cab9fdeSChristos Margiolis switch (c->cfg.freq) {
358*9cab9fdeSChristos Margiolis case FREQ_16K:
359*9cab9fdeSChristos Margiolis jitter_limit = (16000 / 20);
360*9cab9fdeSChristos Margiolis break;
361*9cab9fdeSChristos Margiolis case FREQ_32K:
362*9cab9fdeSChristos Margiolis jitter_limit = (32000 / 20);
363*9cab9fdeSChristos Margiolis break;
364*9cab9fdeSChristos Margiolis case FREQ_44_1K:
365*9cab9fdeSChristos Margiolis jitter_limit = (44100 / 20);
366*9cab9fdeSChristos Margiolis break;
367*9cab9fdeSChristos Margiolis default:
368*9cab9fdeSChristos Margiolis jitter_limit = (48000 / 20);
369*9cab9fdeSChristos Margiolis break;
370*9cab9fdeSChristos Margiolis }
371*9cab9fdeSChristos Margiolis
372*9cab9fdeSChristos Margiolis if (c->cfg.chmode == MODE_MONO) {
373*9cab9fdeSChristos Margiolis if (len >= 2 &&
374*9cab9fdeSChristos Margiolis ioctl(c->oss_fd, SNDCTL_DSP_GETODELAY, &delay) == 0 &&
375*9cab9fdeSChristos Margiolis delay < (jitter_limit * 2)) {
376*9cab9fdeSChristos Margiolis uint8_t jitter[jitter_limit * 4] __aligned(4);
377*9cab9fdeSChristos Margiolis size_t x;
378*9cab9fdeSChristos Margiolis
379*9cab9fdeSChristos Margiolis /* repeat last sample */
380*9cab9fdeSChristos Margiolis for (x = 0; x != sizeof(jitter); x++)
381*9cab9fdeSChristos Margiolis jitter[x] = ptr[x % 2];
382*9cab9fdeSChristos Margiolis
383*9cab9fdeSChristos Margiolis write(c->oss_fd, jitter, sizeof(jitter));
384*9cab9fdeSChristos Margiolis }
385*9cab9fdeSChristos Margiolis } else {
386*9cab9fdeSChristos Margiolis if (len >= 4 &&
387*9cab9fdeSChristos Margiolis ioctl(c->oss_fd, SNDCTL_DSP_GETODELAY, &delay) == 0 &&
388*9cab9fdeSChristos Margiolis delay < (jitter_limit * 4)) {
389*9cab9fdeSChristos Margiolis uint8_t jitter[jitter_limit * 8] __aligned(4);
390*9cab9fdeSChristos Margiolis size_t x;
391*9cab9fdeSChristos Margiolis
392*9cab9fdeSChristos Margiolis /* repeat last sample */
393*9cab9fdeSChristos Margiolis for (x = 0; x != sizeof(jitter); x++)
394*9cab9fdeSChristos Margiolis jitter[x] = ptr[x % 4];
395*9cab9fdeSChristos Margiolis
396*9cab9fdeSChristos Margiolis write(c->oss_fd, jitter, sizeof(jitter));
397*9cab9fdeSChristos Margiolis }
398*9cab9fdeSChristos Margiolis }
399*9cab9fdeSChristos Margiolis while (ptr != end) {
400*9cab9fdeSChristos Margiolis int written = write(c->oss_fd, ptr, end - ptr);
401*9cab9fdeSChristos Margiolis
402*9cab9fdeSChristos Margiolis if (written < 0) {
403*9cab9fdeSChristos Margiolis if (errno != EINTR && errno != EAGAIN)
404*9cab9fdeSChristos Margiolis break;
405*9cab9fdeSChristos Margiolis written = 0;
406*9cab9fdeSChristos Margiolis }
407*9cab9fdeSChristos Margiolis ptr += written;
408*9cab9fdeSChristos Margiolis }
409*9cab9fdeSChristos Margiolis if (ptr != end) {
410*9cab9fdeSChristos Margiolis message("Not all written, closing dsp\n");
411*9cab9fdeSChristos Margiolis close(c->oss_fd);
412*9cab9fdeSChristos Margiolis c->oss_fd = -1;
413*9cab9fdeSChristos Margiolis oss_attempt = time(NULL);
414*9cab9fdeSChristos Margiolis }
415*9cab9fdeSChristos Margiolis }
416*9cab9fdeSChristos Margiolis }
417*9cab9fdeSChristos Margiolis
418*9cab9fdeSChristos Margiolis if (c->cfg.acceptor_state == acpStreamSuspended &&
419*9cab9fdeSChristos Margiolis c->oss_fd > -1) {
420*9cab9fdeSChristos Margiolis close(c->oss_fd);
421*9cab9fdeSChristos Margiolis c->oss_fd = -1;
422*9cab9fdeSChristos Margiolis }
423*9cab9fdeSChristos Margiolis }
424*9cab9fdeSChristos Margiolis }
425*9cab9fdeSChristos Margiolis
426*9cab9fdeSChristos Margiolis static struct option bt_speaker_opts[] = {
427*9cab9fdeSChristos Margiolis {"device", required_argument, NULL, 'd'},
428*9cab9fdeSChristos Margiolis {"sdp_socket_path", required_argument, NULL, 'p'},
429*9cab9fdeSChristos Margiolis {"rtprio", required_argument, NULL, 'i'},
430*9cab9fdeSChristos Margiolis {"background", no_argument, NULL, 'B'},
431*9cab9fdeSChristos Margiolis {"help", no_argument, NULL, 'h'},
432*9cab9fdeSChristos Margiolis {NULL, 0, NULL, 0}
433*9cab9fdeSChristos Margiolis };
434*9cab9fdeSChristos Margiolis
435*9cab9fdeSChristos Margiolis static void
usage(void)436*9cab9fdeSChristos Margiolis usage(void)
437*9cab9fdeSChristos Margiolis {
438*9cab9fdeSChristos Margiolis fprintf(stderr, "Usage: virtual_bt_speaker -d /dev/dsp\n"
439*9cab9fdeSChristos Margiolis "\t" "-d, --device [device]\n"
440*9cab9fdeSChristos Margiolis "\t" "-p, --sdp_socket_path [path]\n"
441*9cab9fdeSChristos Margiolis "\t" "-i, --rtprio [priority]\n"
442*9cab9fdeSChristos Margiolis "\t" "-B, --background\n"
443*9cab9fdeSChristos Margiolis );
444*9cab9fdeSChristos Margiolis exit(EX_USAGE);
445*9cab9fdeSChristos Margiolis }
446*9cab9fdeSChristos Margiolis
447*9cab9fdeSChristos Margiolis int
main(int argc,char ** argv)448*9cab9fdeSChristos Margiolis main(int argc, char **argv)
449*9cab9fdeSChristos Margiolis {
450*9cab9fdeSChristos Margiolis struct bt_audio_receiver r = {};
451*9cab9fdeSChristos Margiolis struct rtprio rtp = {};
452*9cab9fdeSChristos Margiolis void *hdl;
453*9cab9fdeSChristos Margiolis int ch;
454*9cab9fdeSChristos Margiolis
455*9cab9fdeSChristos Margiolis r.devname = NULL;
456*9cab9fdeSChristos Margiolis r.sdp_socket_path = NULL;
457*9cab9fdeSChristos Margiolis r.l2cap_psm = SDP_UUID_PROTOCOL_AVDTP;
458*9cab9fdeSChristos Margiolis
459*9cab9fdeSChristos Margiolis while ((ch = getopt_long(argc, argv, "p:i:d:Bh", bt_speaker_opts, NULL)) != -1) {
460*9cab9fdeSChristos Margiolis switch (ch) {
461*9cab9fdeSChristos Margiolis case 'd':
462*9cab9fdeSChristos Margiolis r.devname = optarg;
463*9cab9fdeSChristos Margiolis break;
464*9cab9fdeSChristos Margiolis case 'p':
465*9cab9fdeSChristos Margiolis r.sdp_socket_path = optarg;
466*9cab9fdeSChristos Margiolis break;
467*9cab9fdeSChristos Margiolis case 'B':
468*9cab9fdeSChristos Margiolis bt_in_background = 1;
469*9cab9fdeSChristos Margiolis break;
470*9cab9fdeSChristos Margiolis case 'i':
471*9cab9fdeSChristos Margiolis rtp.type = RTP_PRIO_REALTIME;
472*9cab9fdeSChristos Margiolis rtp.prio = atoi(optarg);
473*9cab9fdeSChristos Margiolis if (rtprio(RTP_SET, getpid(), &rtp) != 0) {
474*9cab9fdeSChristos Margiolis message("Cannot set realtime priority\n");
475*9cab9fdeSChristos Margiolis }
476*9cab9fdeSChristos Margiolis break;
477*9cab9fdeSChristos Margiolis default:
478*9cab9fdeSChristos Margiolis usage();
479*9cab9fdeSChristos Margiolis break;
480*9cab9fdeSChristos Margiolis }
481*9cab9fdeSChristos Margiolis }
482*9cab9fdeSChristos Margiolis
483*9cab9fdeSChristos Margiolis if (r.devname == NULL)
484*9cab9fdeSChristos Margiolis errx(EX_USAGE, "No devicename specified");
485*9cab9fdeSChristos Margiolis
486*9cab9fdeSChristos Margiolis if (bt_in_background) {
487*9cab9fdeSChristos Margiolis if (daemon(0, 0) != 0)
488*9cab9fdeSChristos Margiolis errx(EX_SOFTWARE, "Cannot become daemon");
489*9cab9fdeSChristos Margiolis }
490*9cab9fdeSChristos Margiolis
491*9cab9fdeSChristos Margiolis if ((hdl = dlopen("/usr/lib/virtual_oss/voss_bt.so", RTLD_NOW)) == NULL)
492*9cab9fdeSChristos Margiolis errx(1, "%s", dlerror());
493*9cab9fdeSChristos Margiolis if ((bt_receive_f = dlsym(hdl, "bt_receive")) == NULL)
494*9cab9fdeSChristos Margiolis goto err_dlsym;
495*9cab9fdeSChristos Margiolis if ((avdtpACPHandlePacket_f = dlsym(hdl, "avdtpACPHandlePacket")) ==
496*9cab9fdeSChristos Margiolis NULL)
497*9cab9fdeSChristos Margiolis goto err_dlsym;
498*9cab9fdeSChristos Margiolis if ((avdtpACPFree_f = dlsym(hdl, "avdtpACPFree")) == NULL)
499*9cab9fdeSChristos Margiolis goto err_dlsym;
500*9cab9fdeSChristos Margiolis
501*9cab9fdeSChristos Margiolis while (1) {
502*9cab9fdeSChristos Margiolis message("Starting to listen\n");
503*9cab9fdeSChristos Margiolis if (!start_listen(&r)) {
504*9cab9fdeSChristos Margiolis message("Failed to initialize server socket\n");
505*9cab9fdeSChristos Margiolis goto err_listen;
506*9cab9fdeSChristos Margiolis }
507*9cab9fdeSChristos Margiolis message("Registering service via SDP\n");
508*9cab9fdeSChristos Margiolis if (!register_sdp(&r)) {
509*9cab9fdeSChristos Margiolis message("Failed to register in SDP\n");
510*9cab9fdeSChristos Margiolis goto err_sdp;
511*9cab9fdeSChristos Margiolis }
512*9cab9fdeSChristos Margiolis while (1) {
513*9cab9fdeSChristos Margiolis message("Waiting for connection...\n");
514*9cab9fdeSChristos Margiolis struct bt_audio_connection *c = wait_for_connection(&r);
515*9cab9fdeSChristos Margiolis
516*9cab9fdeSChristos Margiolis if (c == NULL) {
517*9cab9fdeSChristos Margiolis message("Failed to get connection\n");
518*9cab9fdeSChristos Margiolis goto err_conn;
519*9cab9fdeSChristos Margiolis }
520*9cab9fdeSChristos Margiolis message("Got connection...\n");
521*9cab9fdeSChristos Margiolis
522*9cab9fdeSChristos Margiolis process_connection(c);
523*9cab9fdeSChristos Margiolis
524*9cab9fdeSChristos Margiolis message("Connection finished...\n");
525*9cab9fdeSChristos Margiolis
526*9cab9fdeSChristos Margiolis close_connection(c);
527*9cab9fdeSChristos Margiolis }
528*9cab9fdeSChristos Margiolis err_conn:
529*9cab9fdeSChristos Margiolis message("Unregistering service\n");
530*9cab9fdeSChristos Margiolis unregister_sdp(&r);
531*9cab9fdeSChristos Margiolis err_sdp:
532*9cab9fdeSChristos Margiolis stop_listen(&r);
533*9cab9fdeSChristos Margiolis err_listen:
534*9cab9fdeSChristos Margiolis sleep(5);
535*9cab9fdeSChristos Margiolis }
536*9cab9fdeSChristos Margiolis return (0);
537*9cab9fdeSChristos Margiolis
538*9cab9fdeSChristos Margiolis err_dlsym:
539*9cab9fdeSChristos Margiolis warnx("%s", dlerror());
540*9cab9fdeSChristos Margiolis dlclose(hdl);
541*9cab9fdeSChristos Margiolis exit(EXIT_FAILURE);
542*9cab9fdeSChristos Margiolis }
543