OSDN Git Service

android/hal-audio: Add audio_ipc_cmd
[android-x86/external-bluetooth-bluez.git] / android / hal-audio.c
1 /*
2  * Copyright (C) 2013 Intel Corporation
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
18 #include <errno.h>
19 #include <pthread.h>
20 #include <poll.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/socket.h>
25 #include <sys/un.h>
26 #include <unistd.h>
27
28 #include <hardware/audio.h>
29 #include <hardware/hardware.h>
30
31 #include "audio-msg.h"
32 #include "hal-log.h"
33 #include "hal-msg.h"
34
35 static int listen_sk = -1;
36 static int audio_sk = -1;
37 static bool close_thread = false;
38
39 static pthread_t ipc_th = 0;
40 static pthread_mutex_t close_mutex = PTHREAD_MUTEX_INITIALIZER;
41 static pthread_mutex_t sk_mutex = PTHREAD_MUTEX_INITIALIZER;
42
43 struct a2dp_audio_dev {
44         struct audio_hw_device dev;
45         struct audio_stream_out *out;
46 };
47
48 static void audio_ipc_cleanup(void)
49 {
50         if (audio_sk >= 0) {
51                 shutdown(audio_sk, SHUT_RDWR);
52                 audio_sk = -1;
53         }
54 }
55
56 static int audio_ipc_cmd(uint8_t service_id, uint8_t opcode, uint16_t len,
57                         void *param, size_t *rsp_len, void *rsp, int *fd)
58 {
59         ssize_t ret;
60         struct msghdr msg;
61         struct iovec iv[2];
62         struct hal_hdr cmd;
63         char cmsgbuf[CMSG_SPACE(sizeof(int))];
64         struct hal_status s;
65         size_t s_len = sizeof(s);
66
67         if (audio_sk < 0) {
68                 error("audio: Invalid cmd socket passed to audio_ipc_cmd");
69                 goto failed;
70         }
71
72         if (!rsp || !rsp_len) {
73                 memset(&s, 0, s_len);
74                 rsp_len = &s_len;
75                 rsp = &s;
76         }
77
78         memset(&msg, 0, sizeof(msg));
79         memset(&cmd, 0, sizeof(cmd));
80
81         cmd.service_id = service_id;
82         cmd.opcode = opcode;
83         cmd.len = len;
84
85         iv[0].iov_base = &cmd;
86         iv[0].iov_len = sizeof(cmd);
87
88         iv[1].iov_base = param;
89         iv[1].iov_len = len;
90
91         msg.msg_iov = iv;
92         msg.msg_iovlen = 2;
93
94         pthread_mutex_lock(&sk_mutex);
95
96         ret = sendmsg(audio_sk, &msg, 0);
97         if (ret < 0) {
98                 error("audio: Sending command failed:%s", strerror(errno));
99                 pthread_mutex_unlock(&sk_mutex);
100                 goto failed;
101         }
102
103         /* socket was shutdown */
104         if (ret == 0) {
105                 error("audio: Command socket closed");
106                 goto failed;
107         }
108
109         memset(&msg, 0, sizeof(msg));
110         memset(&cmd, 0, sizeof(cmd));
111
112         iv[0].iov_base = &cmd;
113         iv[0].iov_len = sizeof(cmd);
114
115         iv[1].iov_base = rsp;
116         iv[1].iov_len = *rsp_len;
117
118         msg.msg_iov = iv;
119         msg.msg_iovlen = 2;
120
121         if (fd) {
122                 memset(cmsgbuf, 0, sizeof(cmsgbuf));
123                 msg.msg_control = cmsgbuf;
124                 msg.msg_controllen = sizeof(cmsgbuf);
125         }
126
127         ret = recvmsg(audio_sk, &msg, 0);
128         if (ret < 0) {
129                 error("audio: Receiving command response failed:%s",
130                                                         strerror(errno));
131                 pthread_mutex_unlock(&sk_mutex);
132                 goto failed;
133         }
134
135         pthread_mutex_unlock(&sk_mutex);
136
137         if (ret < (ssize_t) sizeof(cmd)) {
138                 error("audio: Too small response received(%zd bytes)", ret);
139                 goto failed;
140         }
141
142         if (cmd.service_id != service_id) {
143                 error("audio: Invalid service id (%u vs %u)", cmd.service_id,
144                                                                 service_id);
145                 goto failed;
146         }
147
148         if (ret != (ssize_t) (sizeof(cmd) + cmd.len)) {
149                 error("audio: Malformed response received(%zd bytes)", ret);
150                 goto failed;
151         }
152
153         if (cmd.opcode != opcode && cmd.opcode != AUDIO_OP_STATUS) {
154                 error("audio: Invalid opcode received (%u vs %u)",
155                                                 cmd.opcode, opcode);
156                 goto failed;
157         }
158
159         if (cmd.opcode == AUDIO_OP_STATUS) {
160                 struct hal_status *s = rsp;
161
162                 if (sizeof(*s) != cmd.len) {
163                         error("audio: Invalid status length");
164                         goto failed;
165                 }
166
167                 if (s->code == AUDIO_STATUS_SUCCESS) {
168                         error("audio: Invalid success status response");
169                         goto failed;
170                 }
171
172                 return s->code;
173         }
174
175         /* Receive auxiliary data in msg */
176         if (fd) {
177                 struct cmsghdr *cmsg;
178
179                 *fd = -1;
180
181                 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg;
182                                         cmsg = CMSG_NXTHDR(&msg, cmsg)) {
183                         if (cmsg->cmsg_level == SOL_SOCKET
184                                         && cmsg->cmsg_type == SCM_RIGHTS) {
185                                 memcpy(fd, CMSG_DATA(cmsg), sizeof(int));
186                                 break;
187                         }
188                 }
189         }
190
191         if (rsp_len)
192                 *rsp_len = cmd.len;
193
194         return AUDIO_STATUS_SUCCESS;
195
196 failed:
197         /* Some serious issue happen on IPC - recover */
198         shutdown(audio_sk, SHUT_RDWR);
199         audio_sk = -1;
200         return AUDIO_STATUS_FAILED;
201 }
202
203 static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
204                                                                 size_t bytes)
205 {
206         DBG("");
207         return -ENOSYS;
208 }
209
210 static uint32_t out_get_sample_rate(const struct audio_stream *stream)
211 {
212         DBG("");
213         return -ENOSYS;
214 }
215
216 static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
217 {
218         DBG("");
219         return -ENOSYS;
220 }
221
222 static size_t out_get_buffer_size(const struct audio_stream *stream)
223 {
224         DBG("");
225         return -ENOSYS;
226 }
227
228 static uint32_t out_get_channels(const struct audio_stream *stream)
229 {
230         DBG("");
231         return -ENOSYS;
232 }
233
234 static audio_format_t out_get_format(const struct audio_stream *stream)
235 {
236         DBG("");
237         return -ENOSYS;
238 }
239
240 static int out_set_format(struct audio_stream *stream, audio_format_t format)
241 {
242         DBG("");
243         return -ENOSYS;
244 }
245
246 static int out_standby(struct audio_stream *stream)
247 {
248         DBG("");
249         return -ENOSYS;
250 }
251
252 static int out_dump(const struct audio_stream *stream, int fd)
253 {
254         DBG("");
255         return -ENOSYS;
256 }
257
258 static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
259 {
260         DBG("");
261         return -ENOSYS;
262 }
263
264 static char *out_get_parameters(const struct audio_stream *stream,
265                                                         const char *keys)
266 {
267         DBG("");
268         return strdup("");
269 }
270
271 static uint32_t out_get_latency(const struct audio_stream_out *stream)
272 {
273         DBG("");
274         return -ENOSYS;
275 }
276
277 static int out_set_volume(struct audio_stream_out *stream, float left,
278                                                                 float right)
279 {
280         DBG("");
281         /* volume controlled in audioflinger mixer (digital) */
282         return -ENOSYS;
283 }
284
285 static int out_get_render_position(const struct audio_stream_out *stream,
286                                                         uint32_t *dsp_frames)
287 {
288         DBG("");
289         return -ENOSYS;
290 }
291
292 static int out_add_audio_effect(const struct audio_stream *stream,
293                                                         effect_handle_t effect)
294 {
295         DBG("");
296         return -ENOSYS;
297 }
298
299 static int out_remove_audio_effect(const struct audio_stream *stream,
300                                                         effect_handle_t effect)
301 {
302         DBG("");
303         return -ENOSYS;
304 }
305
306 static uint32_t in_get_sample_rate(const struct audio_stream *stream)
307 {
308         DBG("");
309         return -ENOSYS;
310 }
311
312 static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
313 {
314         DBG("");
315         return -ENOSYS;
316 }
317
318 static size_t in_get_buffer_size(const struct audio_stream *stream)
319 {
320         DBG("");
321         return -ENOSYS;
322 }
323
324 static uint32_t in_get_channels(const struct audio_stream *stream)
325 {
326         DBG("");
327         return -ENOSYS;
328 }
329
330 static audio_format_t in_get_format(const struct audio_stream *stream)
331 {
332         DBG("");
333         return -ENOSYS;
334 }
335
336 static int in_set_format(struct audio_stream *stream, audio_format_t format)
337 {
338         DBG("");
339         return -ENOSYS;
340 }
341
342 static int in_standby(struct audio_stream *stream)
343 {
344         DBG("");
345         return -ENOSYS;
346 }
347
348 static int in_dump(const struct audio_stream *stream, int fd)
349 {
350         DBG("");
351         return -ENOSYS;
352 }
353
354 static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
355 {
356         DBG("");
357         return -ENOSYS;
358 }
359
360 static char *in_get_parameters(const struct audio_stream *stream,
361                                                         const char *keys)
362 {
363         DBG("");
364         return strdup("");
365 }
366
367 static int in_set_gain(struct audio_stream_in *stream, float gain)
368 {
369         DBG("");
370         return -ENOSYS;
371 }
372
373 static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
374                                                                 size_t bytes)
375 {
376         DBG("");
377         return -ENOSYS;
378 }
379
380 static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
381 {
382         DBG("");
383         return -ENOSYS;
384 }
385
386 static int in_add_audio_effect(const struct audio_stream *stream,
387                                                         effect_handle_t effect)
388 {
389         DBG("");
390         return -ENOSYS;
391 }
392
393 static int in_remove_audio_effect(const struct audio_stream *stream,
394                                                         effect_handle_t effect)
395 {
396         DBG("");
397         return -ENOSYS;
398 }
399
400 static int audio_open_output_stream(struct audio_hw_device *dev,
401                                         audio_io_handle_t handle,
402                                         audio_devices_t devices,
403                                         audio_output_flags_t flags,
404                                         struct audio_config *config,
405                                         struct audio_stream_out **stream_out)
406
407 {
408         struct a2dp_audio_dev *a2dp_dev = (struct a2dp_audio_dev *) dev;
409         struct audio_stream_out *out;
410
411         out = calloc(1, sizeof(struct audio_stream_out));
412         if (!out)
413                 return -ENOMEM;
414
415         DBG("");
416
417         out->common.get_sample_rate = out_get_sample_rate;
418         out->common.set_sample_rate = out_set_sample_rate;
419         out->common.get_buffer_size = out_get_buffer_size;
420         out->common.get_channels = out_get_channels;
421         out->common.get_format = out_get_format;
422         out->common.set_format = out_set_format;
423         out->common.standby = out_standby;
424         out->common.dump = out_dump;
425         out->common.set_parameters = out_set_parameters;
426         out->common.get_parameters = out_get_parameters;
427         out->common.add_audio_effect = out_add_audio_effect;
428         out->common.remove_audio_effect = out_remove_audio_effect;
429         out->get_latency = out_get_latency;
430         out->set_volume = out_set_volume;
431         out->write = out_write;
432         out->get_render_position = out_get_render_position;
433
434         *stream_out = out;
435         a2dp_dev->out = out;
436
437         return 0;
438 }
439
440 static void audio_close_output_stream(struct audio_hw_device *dev,
441                                         struct audio_stream_out *stream)
442 {
443         struct a2dp_audio_dev *a2dp_dev = (struct a2dp_audio_dev *) dev;
444
445         DBG("");
446
447         free(stream);
448         a2dp_dev->out = NULL;
449 }
450
451 static int audio_set_parameters(struct audio_hw_device *dev,
452                                                         const char *kvpairs)
453 {
454         DBG("");
455         return -ENOSYS;
456 }
457
458 static char *audio_get_parameters(const struct audio_hw_device *dev,
459                                                         const char *keys)
460 {
461         DBG("");
462         return strdup("");
463 }
464
465 static int audio_init_check(const struct audio_hw_device *dev)
466 {
467         DBG("");
468         return -ENOSYS;
469 }
470
471 static int audio_set_voice_volume(struct audio_hw_device *dev, float volume)
472 {
473         DBG("");
474         return -ENOSYS;
475 }
476
477 static int audio_set_master_volume(struct audio_hw_device *dev, float volume)
478 {
479         DBG("");
480         return -ENOSYS;
481 }
482
483 static int audio_set_mode(struct audio_hw_device *dev, int mode)
484 {
485         DBG("");
486         return -ENOSYS;
487 }
488
489 static int audio_set_mic_mute(struct audio_hw_device *dev, bool state)
490 {
491         DBG("");
492         return -ENOSYS;
493 }
494
495 static int audio_get_mic_mute(const struct audio_hw_device *dev, bool *state)
496 {
497         DBG("");
498         return -ENOSYS;
499 }
500
501 static size_t audio_get_input_buffer_size(const struct audio_hw_device *dev,
502                                         const struct audio_config *config)
503 {
504         DBG("");
505         return -ENOSYS;
506 }
507
508 static int audio_open_input_stream(struct audio_hw_device *dev,
509                                         audio_io_handle_t handle,
510                                         audio_devices_t devices,
511                                         struct audio_config *config,
512                                         struct audio_stream_in **stream_in)
513 {
514         struct audio_stream_in *in;
515
516         DBG("");
517
518         in = calloc(1, sizeof(struct audio_stream_in));
519         if (!in)
520                 return -ENOMEM;
521
522         in->common.get_sample_rate = in_get_sample_rate;
523         in->common.set_sample_rate = in_set_sample_rate;
524         in->common.get_buffer_size = in_get_buffer_size;
525         in->common.get_channels = in_get_channels;
526         in->common.get_format = in_get_format;
527         in->common.set_format = in_set_format;
528         in->common.standby = in_standby;
529         in->common.dump = in_dump;
530         in->common.set_parameters = in_set_parameters;
531         in->common.get_parameters = in_get_parameters;
532         in->common.add_audio_effect = in_add_audio_effect;
533         in->common.remove_audio_effect = in_remove_audio_effect;
534         in->set_gain = in_set_gain;
535         in->read = in_read;
536         in->get_input_frames_lost = in_get_input_frames_lost;
537
538         *stream_in = in;
539
540         return 0;
541 }
542
543 static void audio_close_input_stream(struct audio_hw_device *dev,
544                                         struct audio_stream_in *stream_in)
545 {
546         DBG("");
547         free(stream_in);
548 }
549
550 static int audio_dump(const audio_hw_device_t *device, int fd)
551 {
552         DBG("");
553         return -ENOSYS;
554 }
555
556 static int audio_close(hw_device_t *device)
557 {
558         struct a2dp_audio_dev *a2dp_dev = (struct a2dp_audio_dev *)device;
559
560         DBG("");
561
562         pthread_mutex_lock(&close_mutex);
563         audio_ipc_cleanup();
564         close_thread = true;
565         pthread_mutex_unlock(&close_mutex);
566
567         pthread_join(ipc_th, NULL);
568
569         close(listen_sk);
570         listen_sk = -1;
571
572         free(a2dp_dev);
573         return 0;
574 }
575
576 static void *ipc_handler(void *data)
577 {
578         bool done = false;
579         struct pollfd pfd;
580
581         DBG("");
582
583         while (!done) {
584                 DBG("Waiting for connection ...");
585                 audio_sk = accept(listen_sk, NULL, NULL);
586                 if (audio_sk < 0) {
587                         int err = errno;
588                         error("audio: Failed to accept socket: %d (%s)", err,
589                                                                 strerror(err));
590                         continue;
591                 }
592
593                 DBG("Audio IPC: Connected");
594
595                 memset(&pfd, 0, sizeof(pfd));
596                 pfd.fd = audio_sk;
597                 pfd.events = POLLHUP | POLLERR | POLLNVAL;
598
599                 /* Check if socket is still alive. Empty while loop.*/
600                 while (poll(&pfd, 1, -1) < 0 && errno == EINTR);
601
602                 if (pfd.revents & (POLLHUP | POLLERR | POLLNVAL)) {
603                         info("Audio HAL: Socket closed");
604                         audio_sk = -1;
605                 }
606
607                 /*Check if audio_dev is closed */
608                 pthread_mutex_lock(&close_mutex);
609                 done = close_thread;
610                 close_thread = false;
611                 pthread_mutex_unlock(&close_mutex);
612         }
613
614         info("Closing Audio IPC thread");
615         return NULL;
616 }
617
618 static int audio_ipc_init(void)
619 {
620         struct sockaddr_un addr;
621         int err;
622         int sk;
623
624         DBG("");
625
626         sk = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
627         if (sk < 0) {
628                 err = errno;
629                 error("audio: Failed to create socket: %d (%s)", err,
630                                                                 strerror(err));
631                 return err;
632         }
633
634         memset(&addr, 0, sizeof(addr));
635         addr.sun_family = AF_UNIX;
636
637         memcpy(addr.sun_path, BLUEZ_AUDIO_SK_PATH,
638                                         sizeof(BLUEZ_AUDIO_SK_PATH));
639
640         if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
641                 err = errno;
642                 error("audio: Failed to bind socket: %d (%s)", err,
643                                                                 strerror(err));
644                 goto failed;
645         }
646
647         if (listen(sk, 1) < 0) {
648                 err = errno;
649                 error("audio: Failed to listen on the socket: %d (%s)", err,
650                                                                 strerror(err));
651                 goto failed;
652         }
653
654         listen_sk = sk;
655
656         err = pthread_create(&ipc_th, NULL, ipc_handler, NULL);
657         if (err) {
658                 err = -err;
659                 ipc_th = 0;
660                 error("audio: Failed to start Audio IPC thread: %d (%s)",
661                                                         err, strerror(err));
662                 goto failed;
663         }
664
665         return 0;
666
667 failed:
668         close(sk);
669         return err;
670 }
671
672 static int audio_open(const hw_module_t *module, const char *name,
673                                                         hw_device_t **device)
674 {
675         struct a2dp_audio_dev *a2dp_dev;
676         int err;
677
678         DBG("");
679
680         if (strcmp(name, AUDIO_HARDWARE_INTERFACE)) {
681                 error("audio: interface %s not matching [%s]", name,
682                                                 AUDIO_HARDWARE_INTERFACE);
683                 return -EINVAL;
684         }
685
686         err = audio_ipc_init();
687         if (err)
688                 return -err;
689
690         a2dp_dev = calloc(1, sizeof(struct a2dp_audio_dev));
691         if (!a2dp_dev)
692                 return -ENOMEM;
693
694         a2dp_dev->dev.common.version = AUDIO_DEVICE_API_VERSION_CURRENT;
695         a2dp_dev->dev.common.module = (struct hw_module_t *) module;
696         a2dp_dev->dev.common.close = audio_close;
697
698         a2dp_dev->dev.init_check = audio_init_check;
699         a2dp_dev->dev.set_voice_volume = audio_set_voice_volume;
700         a2dp_dev->dev.set_master_volume = audio_set_master_volume;
701         a2dp_dev->dev.set_mode = audio_set_mode;
702         a2dp_dev->dev.set_mic_mute = audio_set_mic_mute;
703         a2dp_dev->dev.get_mic_mute = audio_get_mic_mute;
704         a2dp_dev->dev.set_parameters = audio_set_parameters;
705         a2dp_dev->dev.get_parameters = audio_get_parameters;
706         a2dp_dev->dev.get_input_buffer_size = audio_get_input_buffer_size;
707         a2dp_dev->dev.open_output_stream = audio_open_output_stream;
708         a2dp_dev->dev.close_output_stream = audio_close_output_stream;
709         a2dp_dev->dev.open_input_stream = audio_open_input_stream;
710         a2dp_dev->dev.close_input_stream = audio_close_input_stream;
711         a2dp_dev->dev.dump = audio_dump;
712
713         /* Note that &a2dp_dev->dev.common is the same pointer as a2dp_dev.
714          * This results from the structure of following structs:a2dp_audio_dev,
715          * audio_hw_device. We will rely on this later in the code.*/
716         *device = &a2dp_dev->dev.common;
717
718         return 0;
719 }
720
721 static struct hw_module_methods_t hal_module_methods = {
722         .open = audio_open,
723 };
724
725 struct audio_module HAL_MODULE_INFO_SYM = {
726         .common = {
727         .tag = HARDWARE_MODULE_TAG,
728         .version_major = 1,
729         .version_minor = 0,
730         .id = AUDIO_HARDWARE_MODULE_ID,
731         .name = "A2DP Bluez HW HAL",
732         .author = "Intel Corporation",
733         .methods = &hal_module_methods,
734         },
735 };