• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (C) 2009-2012 Broadcom Corporation
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 /*****************************************************************************
20  *
21  *  Filename:      audio_a2dp_hw.c
22  *
23  *  Description:   Implements hal for bluedroid a2dp audio device
24  *
25  *****************************************************************************/
26 
27 #include <errno.h>
28 #include <pthread.h>
29 #include <stdint.h>
30 #include <sys/time.h>
31 #include <sys/socket.h>
32 #include <sys/un.h>
33 #include <sys/poll.h>
34 #include <sys/errno.h>
35 #include <sys/stat.h>
36 #include <unistd.h>
37 #include <fcntl.h>
38 #include <cutils/str_parms.h>
39 #include <cutils/sockets.h>
40 
41 #include <system/audio.h>
42 #include <hardware/audio.h>
43 
44 #include <hardware/hardware.h>
45 #include "audio_a2dp_hw.h"
46 
47 #define LOG_TAG "audio_a2dp_hw"
48 /* #define LOG_NDEBUG 0 */
49 #include <cutils/log.h>
50 
51 /*****************************************************************************
52 **  Constants & Macros
53 ******************************************************************************/
54 
55 #define CTRL_CHAN_RETRY_COUNT 3
56 #define USEC_PER_SEC 1000000L
57 
58 #define CASE_RETURN_STR(const) case const: return #const;
59 
60 #define FNLOG()             ALOGV("%s", __FUNCTION__);
61 #define DEBUG(fmt, ...)     ALOGV("%s: " fmt,__FUNCTION__, ## __VA_ARGS__)
62 #define INFO(fmt, ...)      ALOGI("%s: " fmt,__FUNCTION__, ## __VA_ARGS__)
63 #define ERROR(fmt, ...)     ALOGE("%s: " fmt,__FUNCTION__, ## __VA_ARGS__)
64 
65 #define ASSERTC(cond, msg, val) if (!(cond)) {ERROR("### ASSERT : %s line %d %s (%d) ###", __FILE__, __LINE__, msg, val);}
66 
67 /*****************************************************************************
68 **  Local type definitions
69 ******************************************************************************/
70 
71 typedef enum {
72     AUDIO_A2DP_STATE_STARTING,
73     AUDIO_A2DP_STATE_STARTED,
74     AUDIO_A2DP_STATE_STOPPING,
75     AUDIO_A2DP_STATE_STOPPED,
76     AUDIO_A2DP_STATE_SUSPENDED, /* need explicit set param call to resume (suspend=false) */
77     AUDIO_A2DP_STATE_STANDBY    /* allows write to autoresume */
78 } a2dp_state_t;
79 
80 struct a2dp_stream_out;
81 
82 struct a2dp_audio_device {
83     struct audio_hw_device device;
84     struct a2dp_stream_out *output;
85 };
86 
87 struct a2dp_config {
88     uint32_t                rate;
89     uint32_t                channel_flags;
90     int                     format;
91 };
92 
93 /* move ctrl_fd outside output stream and keep open until HAL unloaded ? */
94 
95 struct a2dp_stream_out {
96     struct audio_stream_out stream;
97     pthread_mutex_t         lock;
98     int                     ctrl_fd;
99     int                     audio_fd;
100     size_t                  buffer_sz;
101     a2dp_state_t            state;
102     struct a2dp_config      cfg;
103 };
104 
105 struct a2dp_stream_in {
106     struct audio_stream_in stream;
107 };
108 
109 /*****************************************************************************
110 **  Static variables
111 ******************************************************************************/
112 
113 /*****************************************************************************
114 **  Static functions
115 ******************************************************************************/
116 
117 static size_t out_get_buffer_size(const struct audio_stream *stream);
118 
119 /*****************************************************************************
120 **  Externs
121 ******************************************************************************/
122 
123 /*****************************************************************************
124 **  Functions
125 ******************************************************************************/
126 
127 /*****************************************************************************
128 **   Miscellaneous helper functions
129 ******************************************************************************/
130 
dump_a2dp_ctrl_event(char event)131 static const char* dump_a2dp_ctrl_event(char event)
132 {
133     switch(event)
134     {
135         CASE_RETURN_STR(A2DP_CTRL_CMD_NONE)
136         CASE_RETURN_STR(A2DP_CTRL_CMD_CHECK_READY)
137         CASE_RETURN_STR(A2DP_CTRL_CMD_START)
138         CASE_RETURN_STR(A2DP_CTRL_CMD_STOP)
139         CASE_RETURN_STR(A2DP_CTRL_CMD_SUSPEND)
140         default:
141             return "UNKNOWN MSG ID";
142     }
143 }
144 
145 /* logs timestamp with microsec precision
146    pprev is optional in case a dedicated diff is required */
ts_log(char * tag,int val,struct timespec * pprev_opt)147 static void ts_log(char *tag, int val, struct timespec *pprev_opt)
148 {
149     struct timespec now;
150     static struct timespec prev = {0,0};
151     unsigned long long now_us;
152     unsigned long long diff_us;
153 
154     clock_gettime(CLOCK_MONOTONIC, &now);
155 
156     now_us = now.tv_sec*USEC_PER_SEC + now.tv_nsec/1000;
157 
158     if (pprev_opt)
159     {
160         diff_us = (now.tv_sec - prev.tv_sec) * USEC_PER_SEC + (now.tv_nsec - prev.tv_nsec)/1000;
161         *pprev_opt = now;
162         DEBUG("[%s] ts %08lld, *diff %08lld, val %d", tag, now_us, diff_us, val);
163     }
164     else
165     {
166         diff_us = (now.tv_sec - prev.tv_sec) * USEC_PER_SEC + (now.tv_nsec - prev.tv_nsec)/1000;
167         prev = now;
168         DEBUG("[%s] ts %08lld, diff %08lld, val %d", tag, now_us, diff_us, val);
169     }
170 }
171 
calc_audiotime(struct a2dp_config cfg,int bytes)172 static int calc_audiotime(struct a2dp_config cfg, int bytes)
173 {
174     int chan_count = popcount(cfg.channel_flags);
175 
176     ASSERTC(cfg.format == AUDIO_FORMAT_PCM_16_BIT,
177             "unsupported sample sz", cfg.format);
178 
179     return bytes*(1000000/(chan_count*2))/cfg.rate;
180 }
181 
182 /*****************************************************************************
183 **
184 **   bluedroid stack adaptation
185 **
186 *****************************************************************************/
187 
skt_connect(struct a2dp_stream_out * out,char * path)188 static int skt_connect(struct a2dp_stream_out *out, char *path)
189 {
190     int ret;
191     int skt_fd;
192     struct sockaddr_un remote;
193     int len;
194 
195     INFO("connect to %s (sz %d)", path, out->buffer_sz);
196 
197     skt_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
198 
199     if(socket_local_client_connect(skt_fd, path,
200             ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM) < 0)
201     {
202         ERROR("failed to connect (%s)", strerror(errno));
203         close(skt_fd);
204         return -1;
205     }
206 
207     len = out->buffer_sz;
208     ret = setsockopt(skt_fd, SOL_SOCKET, SO_SNDBUF, (char*)&len, (int)sizeof(len));
209 
210     /* only issue warning if failed */
211     if (ret < 0)
212         ERROR("setsockopt failed (%s)", strerror(errno));
213 
214     INFO("connected to stack fd = %d", skt_fd);
215 
216     return skt_fd;
217 }
218 
skt_write(int fd,const void * p,size_t len)219 static int skt_write(int fd, const void *p, size_t len)
220 {
221     int sent;
222     struct pollfd pfd;
223 
224     FNLOG();
225 
226     pfd.fd = fd;
227     pfd.events = POLLOUT;
228 
229     /* poll for 500 ms */
230 
231     /* send time out */
232     if (poll(&pfd, 1, 500) == 0)
233         return 0;
234 
235     ts_log("skt_write", len, NULL);
236 
237     if ((sent = send(fd, p, len, MSG_NOSIGNAL)) == -1)
238     {
239         ERROR("write failed with errno=%d\n", errno);
240         return -1;
241     }
242 
243     return sent;
244 }
245 
skt_disconnect(int fd)246 static int skt_disconnect(int fd)
247 {
248     INFO("fd %d", fd);
249 
250     if (fd != AUDIO_SKT_DISCONNECTED)
251     {
252         shutdown(fd, SHUT_RDWR);
253         close(fd);
254     }
255     return 0;
256 }
257 
258 
259 
260 /*****************************************************************************
261 **
262 **  AUDIO CONTROL PATH
263 **
264 *****************************************************************************/
265 
a2dp_command(struct a2dp_stream_out * out,char cmd)266 static int a2dp_command(struct a2dp_stream_out *out, char cmd)
267 {
268     char ack;
269 
270     DEBUG("A2DP COMMAND %s", dump_a2dp_ctrl_event(cmd));
271 
272     /* send command */
273     if (send(out->ctrl_fd, &cmd, 1, MSG_NOSIGNAL) == -1)
274     {
275         ERROR("cmd failed (%s)", strerror(errno));
276         skt_disconnect(out->ctrl_fd);
277         out->ctrl_fd = AUDIO_SKT_DISCONNECTED;
278         return -1;
279     }
280 
281     /* wait for ack byte */
282     if (recv(out->ctrl_fd, &ack, 1, MSG_NOSIGNAL) < 0)
283     {
284         ERROR("ack failed (%s)", strerror(errno));
285         skt_disconnect(out->ctrl_fd);
286         out->ctrl_fd = AUDIO_SKT_DISCONNECTED;
287         return -1;
288     }
289 
290     DEBUG("A2DP COMMAND %s DONE STATUS %d", dump_a2dp_ctrl_event(cmd), ack);
291 
292     if (ack != A2DP_CTRL_ACK_SUCCESS)
293         return -1;
294 
295     return 0;
296 }
297 
298 /*****************************************************************************
299 **
300 ** AUDIO DATA PATH
301 **
302 *****************************************************************************/
303 
a2dp_stream_out_init(struct a2dp_stream_out * out)304 static void a2dp_stream_out_init(struct a2dp_stream_out *out)
305 {
306     pthread_mutexattr_t lock_attr;
307 
308     FNLOG();
309 
310     pthread_mutexattr_init(&lock_attr);
311     pthread_mutexattr_settype(&lock_attr, PTHREAD_MUTEX_RECURSIVE);
312     pthread_mutex_init(&out->lock, &lock_attr);
313 
314     out->ctrl_fd = AUDIO_SKT_DISCONNECTED;
315     out->audio_fd = AUDIO_SKT_DISCONNECTED;
316     out->state = AUDIO_A2DP_STATE_STOPPED;
317 
318     out->cfg.channel_flags = AUDIO_STREAM_DEFAULT_CHANNEL_FLAG;
319     out->cfg.format = AUDIO_STREAM_DEFAULT_FORMAT;
320     out->cfg.rate = AUDIO_STREAM_DEFAULT_RATE;
321 
322     /* manages max capacity of socket pipe */
323     out->buffer_sz = AUDIO_STREAM_OUTPUT_BUFFER_SZ;
324 }
325 
start_audio_datapath(struct a2dp_stream_out * out)326 static int start_audio_datapath(struct a2dp_stream_out *out)
327 {
328     int oldstate = out->state;
329 
330     INFO("state %d", out->state);
331 
332     if (out->ctrl_fd == AUDIO_SKT_DISCONNECTED)
333         return -1;
334 
335     out->state = AUDIO_A2DP_STATE_STARTING;
336 
337     if (a2dp_command(out, A2DP_CTRL_CMD_START) < 0)
338     {
339         ERROR("audiopath start failed");
340 
341         out->state = oldstate;
342         return -1;
343     }
344 
345     /* connect socket if not yet connected */
346     if (out->audio_fd == AUDIO_SKT_DISCONNECTED)
347     {
348         out->audio_fd = skt_connect(out, A2DP_DATA_PATH);
349 
350         if (out->audio_fd < 0)
351         {
352             out->state = oldstate;
353             return -1;
354         }
355 
356         out->state = AUDIO_A2DP_STATE_STARTED;
357     }
358 
359     return 0;
360 }
361 
362 
stop_audio_datapath(struct a2dp_stream_out * out)363 static int stop_audio_datapath(struct a2dp_stream_out *out)
364 {
365     int oldstate = out->state;
366 
367     INFO("state %d", out->state);
368 
369     if (out->ctrl_fd == AUDIO_SKT_DISCONNECTED)
370          return -1;
371 
372     /* prevent any stray output writes from autostarting the stream
373        while stopping audiopath */
374     out->state = AUDIO_A2DP_STATE_STOPPING;
375 
376     if (a2dp_command(out, A2DP_CTRL_CMD_STOP) < 0)
377     {
378         ERROR("audiopath stop failed");
379         out->state = oldstate;
380         return -1;
381     }
382 
383     out->state = AUDIO_A2DP_STATE_STOPPED;
384 
385     /* disconnect audio path */
386     skt_disconnect(out->audio_fd);
387     out->audio_fd = AUDIO_SKT_DISCONNECTED;
388 
389     return 0;
390 }
391 
suspend_audio_datapath(struct a2dp_stream_out * out,bool standby)392 static int suspend_audio_datapath(struct a2dp_stream_out *out, bool standby)
393 {
394     INFO("state %d", out->state);
395 
396     if (out->ctrl_fd == AUDIO_SKT_DISCONNECTED)
397          return -1;
398 
399     if (out->state == AUDIO_A2DP_STATE_STOPPING)
400         return -1;
401 
402     if (a2dp_command(out, A2DP_CTRL_CMD_SUSPEND) < 0)
403         return -1;
404 
405     if (standby)
406         out->state = AUDIO_A2DP_STATE_STANDBY;
407     else
408         out->state = AUDIO_A2DP_STATE_SUSPENDED;
409 
410     /* disconnect audio path */
411     skt_disconnect(out->audio_fd);
412 
413     out->audio_fd = AUDIO_SKT_DISCONNECTED;
414 
415     return 0;
416 }
417 
check_a2dp_ready(struct a2dp_stream_out * out)418 static int check_a2dp_ready(struct a2dp_stream_out *out)
419 {
420     INFO("state %d", out->state);
421 
422     if (a2dp_command(out, A2DP_CTRL_CMD_CHECK_READY) < 0)
423     {
424         ERROR("check a2dp ready failed");
425         return -1;
426     }
427     return 0;
428 }
429 
430 
431 /*****************************************************************************
432 **
433 **  audio output callbacks
434 **
435 *****************************************************************************/
436 
out_write(struct audio_stream_out * stream,const void * buffer,size_t bytes)437 static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
438                          size_t bytes)
439 {
440     struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
441     int sent;
442 
443     DEBUG("write %d bytes (fd %d)", bytes, out->audio_fd);
444 
445     if (out->state == AUDIO_A2DP_STATE_SUSPENDED)
446     {
447         DEBUG("stream suspended");
448         return -1;
449     }
450 
451     /* only allow autostarting if we are in stopped or standby */
452     if ((out->state == AUDIO_A2DP_STATE_STOPPED) ||
453         (out->state == AUDIO_A2DP_STATE_STANDBY))
454     {
455         pthread_mutex_lock(&out->lock);
456 
457         if (start_audio_datapath(out) < 0)
458         {
459             /* emulate time this write represents to avoid very fast write
460                failures during transition periods or remote suspend */
461 
462             int us_delay = calc_audiotime(out->cfg, bytes);
463 
464             DEBUG("emulate a2dp write delay (%d us)", us_delay);
465 
466             usleep(us_delay);
467             pthread_mutex_unlock(&out->lock);
468             return -1;
469         }
470 
471         pthread_mutex_unlock(&out->lock);
472     }
473     else if (out->state != AUDIO_A2DP_STATE_STARTED)
474     {
475         ERROR("stream not in stopped or standby");
476         return -1;
477     }
478 
479     sent = skt_write(out->audio_fd, buffer,  bytes);
480 
481     if (sent == -1)
482     {
483         skt_disconnect(out->audio_fd);
484         out->audio_fd = AUDIO_SKT_DISCONNECTED;
485         out->state = AUDIO_A2DP_STATE_STOPPED;
486     }
487 
488     DEBUG("wrote %d bytes out of %d bytes", sent, bytes);
489     return sent;
490 }
491 
492 
out_get_sample_rate(const struct audio_stream * stream)493 static uint32_t out_get_sample_rate(const struct audio_stream *stream)
494 {
495     struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
496 
497     DEBUG("rate %d", out->cfg.rate);
498 
499     return out->cfg.rate;
500 }
501 
out_set_sample_rate(struct audio_stream * stream,uint32_t rate)502 static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
503 {
504     struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
505 
506     DEBUG("out_set_sample_rate : %d", rate);
507 
508     if (rate != AUDIO_STREAM_DEFAULT_RATE)
509     {
510         ERROR("only rate %d supported", AUDIO_STREAM_DEFAULT_RATE);
511         return -1;
512     }
513 
514     out->cfg.rate = rate;
515 
516     return 0;
517 }
518 
out_get_buffer_size(const struct audio_stream * stream)519 static size_t out_get_buffer_size(const struct audio_stream *stream)
520 {
521     struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
522 
523     DEBUG("buffer_size : %d", out->buffer_sz);
524 
525     return out->buffer_sz;
526 }
527 
out_get_channels(const struct audio_stream * stream)528 static uint32_t out_get_channels(const struct audio_stream *stream)
529 {
530     struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
531 
532     DEBUG("channels 0x%x", out->cfg.channel_flags);
533 
534     return out->cfg.channel_flags;
535 }
536 
out_get_format(const struct audio_stream * stream)537 static audio_format_t out_get_format(const struct audio_stream *stream)
538 {
539     struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
540     DEBUG("format 0x%x", out->cfg.format);
541     return out->cfg.format;
542 }
543 
out_set_format(struct audio_stream * stream,audio_format_t format)544 static int out_set_format(struct audio_stream *stream, audio_format_t format)
545 {
546     struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
547     DEBUG("setting format not yet supported (0x%x)", format);
548     return -ENOSYS;
549 }
550 
out_standby(struct audio_stream * stream)551 static int out_standby(struct audio_stream *stream)
552 {
553     struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
554     int retval = 0;
555 
556     int retVal = 0;
557 
558     FNLOG();
559 
560     pthread_mutex_lock(&out->lock);
561 
562     if (out->state == AUDIO_A2DP_STATE_STARTED)
563         retVal =  suspend_audio_datapath(out, true);
564     else
565         retVal = 0;
566     pthread_mutex_unlock (&out->lock);
567 
568     return retVal;
569 }
570 
out_dump(const struct audio_stream * stream,int fd)571 static int out_dump(const struct audio_stream *stream, int fd)
572 {
573     struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
574     FNLOG();
575     return 0;
576 }
577 
out_set_parameters(struct audio_stream * stream,const char * kvpairs)578 static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
579 {
580     struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
581     struct str_parms *parms;
582     char keyval[16];
583     int retval = 0;
584 
585     INFO("state %d", out->state);
586 
587     pthread_mutex_lock(&out->lock);
588 
589     parms = str_parms_create_str(kvpairs);
590 
591     /* dump params */
592     str_parms_dump(parms);
593 
594     retval = str_parms_get_str(parms, "closing", keyval, sizeof(keyval));
595 
596     if (retval >= 0)
597     {
598         if (strcmp(keyval, "true") == 0)
599         {
600             DEBUG("stream closing, disallow any writes");
601             out->state = AUDIO_A2DP_STATE_STOPPING;
602         }
603     }
604 
605     retval = str_parms_get_str(parms, "A2dpSuspended", keyval, sizeof(keyval));
606 
607     if (retval >= 0)
608     {
609         if (strcmp(keyval, "true") == 0)
610         {
611             if (out->state == AUDIO_A2DP_STATE_STARTED)
612                 retval = suspend_audio_datapath(out, false);
613         }
614         else
615         {
616             /* Do not start the streaming automatically. If the phone was streaming
617              * prior to being suspended, the next out_write shall trigger the
618              * AVDTP start procedure */
619             if (out->state == AUDIO_A2DP_STATE_SUSPENDED)
620                 out->state = AUDIO_A2DP_STATE_STANDBY;
621             /* Irrespective of the state, return 0 */
622             retval = 0;
623         }
624     }
625 
626     pthread_mutex_unlock(&out->lock);
627     str_parms_destroy(parms);
628 
629     return retval;
630 }
631 
out_get_parameters(const struct audio_stream * stream,const char * keys)632 static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
633 {
634     struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
635 
636     FNLOG();
637 
638     /* add populating param here */
639 
640     return strdup("");
641 }
642 
out_get_latency(const struct audio_stream_out * stream)643 static uint32_t out_get_latency(const struct audio_stream_out *stream)
644 {
645     int latency_us;
646 
647     struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
648 
649     FNLOG();
650 
651     latency_us = ((out->buffer_sz * 1000 ) /
652                     audio_stream_frame_size(&out->stream.common) /
653                     out->cfg.rate) * 1000;
654 
655 
656     return (latency_us / 1000) + 200;
657 }
658 
out_set_volume(struct audio_stream_out * stream,float left,float right)659 static int out_set_volume(struct audio_stream_out *stream, float left,
660                           float right)
661 {
662     FNLOG();
663 
664     /* volume controlled in audioflinger mixer (digital) */
665 
666     return -ENOSYS;
667 }
668 
669 
670 
out_get_render_position(const struct audio_stream_out * stream,uint32_t * dsp_frames)671 static int out_get_render_position(const struct audio_stream_out *stream,
672                                    uint32_t *dsp_frames)
673 {
674     FNLOG();
675     return -EINVAL;
676 }
677 
out_add_audio_effect(const struct audio_stream * stream,effect_handle_t effect)678 static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
679 {
680     FNLOG();
681     return 0;
682 }
683 
out_remove_audio_effect(const struct audio_stream * stream,effect_handle_t effect)684 static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
685 {
686     FNLOG();
687     return 0;
688 }
689 
690 /*
691  * AUDIO INPUT STREAM
692  */
693 
in_get_sample_rate(const struct audio_stream * stream)694 static uint32_t in_get_sample_rate(const struct audio_stream *stream)
695 {
696     FNLOG();
697     return 8000;
698 }
699 
in_set_sample_rate(struct audio_stream * stream,uint32_t rate)700 static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
701 {
702     FNLOG();
703     return 0;
704 }
705 
in_get_buffer_size(const struct audio_stream * stream)706 static size_t in_get_buffer_size(const struct audio_stream *stream)
707 {
708     FNLOG();
709     return 320;
710 }
711 
in_get_channels(const struct audio_stream * stream)712 static uint32_t in_get_channels(const struct audio_stream *stream)
713 {
714     FNLOG();
715     return AUDIO_CHANNEL_IN_MONO;
716 }
717 
in_get_format(const struct audio_stream * stream)718 static audio_format_t in_get_format(const struct audio_stream *stream)
719 {
720     FNLOG();
721     return AUDIO_FORMAT_PCM_16_BIT;
722 }
723 
in_set_format(struct audio_stream * stream,audio_format_t format)724 static int in_set_format(struct audio_stream *stream, audio_format_t format)
725 {
726     FNLOG();
727     return 0;
728 }
729 
in_standby(struct audio_stream * stream)730 static int in_standby(struct audio_stream *stream)
731 {
732     FNLOG();
733     return 0;
734 }
735 
in_dump(const struct audio_stream * stream,int fd)736 static int in_dump(const struct audio_stream *stream, int fd)
737 {
738     FNLOG();
739     return 0;
740 }
741 
in_set_parameters(struct audio_stream * stream,const char * kvpairs)742 static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
743 {
744     FNLOG();
745     return 0;
746 }
747 
in_get_parameters(const struct audio_stream * stream,const char * keys)748 static char * in_get_parameters(const struct audio_stream *stream,
749                                 const char *keys)
750 {
751     FNLOG();
752     return strdup("");
753 }
754 
in_set_gain(struct audio_stream_in * stream,float gain)755 static int in_set_gain(struct audio_stream_in *stream, float gain)
756 {
757     FNLOG();
758     return 0;
759 }
760 
in_read(struct audio_stream_in * stream,void * buffer,size_t bytes)761 static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
762                        size_t bytes)
763 {
764     FNLOG();
765     return bytes;
766 }
767 
in_get_input_frames_lost(struct audio_stream_in * stream)768 static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
769 {
770     FNLOG();
771     return 0;
772 }
773 
in_add_audio_effect(const struct audio_stream * stream,effect_handle_t effect)774 static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
775 {
776     FNLOG();
777     return 0;
778 }
779 
in_remove_audio_effect(const struct audio_stream * stream,effect_handle_t effect)780 static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
781 {
782     FNLOG();
783 
784     return 0;
785 }
786 
adev_open_output_stream(struct audio_hw_device * dev,audio_io_handle_t handle,audio_devices_t devices,audio_output_flags_t flags,struct audio_config * config,struct audio_stream_out ** stream_out)787 static int adev_open_output_stream(struct audio_hw_device *dev,
788                                    audio_io_handle_t handle,
789                                    audio_devices_t devices,
790                                    audio_output_flags_t flags,
791                                    struct audio_config *config,
792                                    struct audio_stream_out **stream_out)
793 
794 {
795     struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev;
796     struct a2dp_stream_out *out;
797     int ret = 0;
798     int i;
799 
800     INFO("opening output");
801 
802     out = (struct a2dp_stream_out *)calloc(1, sizeof(struct a2dp_stream_out));
803 
804     if (!out)
805         return -ENOMEM;
806 
807     out->stream.common.get_sample_rate = out_get_sample_rate;
808     out->stream.common.set_sample_rate = out_set_sample_rate;
809     out->stream.common.get_buffer_size = out_get_buffer_size;
810     out->stream.common.get_channels = out_get_channels;
811     out->stream.common.get_format = out_get_format;
812     out->stream.common.set_format = out_set_format;
813     out->stream.common.standby = out_standby;
814     out->stream.common.dump = out_dump;
815     out->stream.common.set_parameters = out_set_parameters;
816     out->stream.common.get_parameters = out_get_parameters;
817     out->stream.common.add_audio_effect = out_add_audio_effect;
818     out->stream.common.remove_audio_effect = out_remove_audio_effect;
819     out->stream.get_latency = out_get_latency;
820     out->stream.set_volume = out_set_volume;
821     out->stream.write = out_write;
822     out->stream.get_render_position = out_get_render_position;
823 
824     /* initialize a2dp specifics */
825     a2dp_stream_out_init(out);
826 
827    /* set output config values */
828    if (config)
829    {
830       config->format = out_get_format((const struct audio_stream *)&out->stream);
831       config->sample_rate = out_get_sample_rate((const struct audio_stream *)&out->stream);
832       config->channel_mask = out_get_channels((const struct audio_stream *)&out->stream);
833    }
834     *stream_out = &out->stream;
835     a2dp_dev->output = out;
836 
837     /* retry logic to catch any timing variations on control channel */
838     for (i = 0; i < CTRL_CHAN_RETRY_COUNT; i++)
839     {
840         /* connect control channel if not already connected */
841         if ((out->ctrl_fd = skt_connect(out, A2DP_CTRL_PATH)) > 0)
842         {
843             /* success, now check if stack is ready */
844             if (check_a2dp_ready(out) == 0)
845                 break;
846 
847             ERROR("error : a2dp not ready, wait 250 ms and retry");
848             usleep(250000);
849             skt_disconnect(out->ctrl_fd);
850         }
851 
852         /* ctrl channel not ready, wait a bit */
853         usleep(250000);
854     }
855 
856     if (out->ctrl_fd == AUDIO_SKT_DISCONNECTED)
857     {
858         ERROR("ctrl socket failed to connect (%s)", strerror(errno));
859         ret = -1;
860         goto err_open;
861     }
862 
863     DEBUG("success");
864     return 0;
865 
866 err_open:
867     free(out);
868     *stream_out = NULL;
869     ERROR("failed");
870     return ret;
871 }
872 
adev_close_output_stream(struct audio_hw_device * dev,struct audio_stream_out * stream)873 static void adev_close_output_stream(struct audio_hw_device *dev,
874                                      struct audio_stream_out *stream)
875 {
876     struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev;
877     struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
878 
879     INFO("closing output (state %d)", out->state);
880 
881     if ((out->state == AUDIO_A2DP_STATE_STARTED) || (out->state == AUDIO_A2DP_STATE_STOPPING))
882         stop_audio_datapath(out);
883 
884     skt_disconnect(out->ctrl_fd);
885     free(stream);
886     a2dp_dev->output = NULL;
887 
888     DEBUG("done");
889 }
890 
adev_set_parameters(struct audio_hw_device * dev,const char * kvpairs)891 static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
892 {
893     struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev;
894     struct a2dp_stream_out *out = a2dp_dev->output;
895     int retval = 0;
896 
897     if (out == NULL)
898         return retval;
899 
900     INFO("state %d", out->state);
901 
902     retval = out->stream.common.set_parameters((struct audio_stream *)out, kvpairs);
903 
904     return retval;
905 }
906 
adev_get_parameters(const struct audio_hw_device * dev,const char * keys)907 static char * adev_get_parameters(const struct audio_hw_device *dev,
908                                   const char *keys)
909 {
910     struct str_parms *parms;
911 
912     FNLOG();
913 
914     parms = str_parms_create_str(keys);
915 
916     str_parms_dump(parms);
917 
918     str_parms_destroy(parms);
919 
920     return strdup("");
921 }
922 
adev_init_check(const struct audio_hw_device * dev)923 static int adev_init_check(const struct audio_hw_device *dev)
924 {
925     struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device*)dev;
926 
927     FNLOG();
928 
929     return 0;
930 }
931 
adev_set_voice_volume(struct audio_hw_device * dev,float volume)932 static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
933 {
934     FNLOG();
935 
936     return -ENOSYS;
937 }
938 
adev_set_master_volume(struct audio_hw_device * dev,float volume)939 static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
940 {
941     FNLOG();
942 
943     return -ENOSYS;
944 }
945 
adev_set_mode(struct audio_hw_device * dev,int mode)946 static int adev_set_mode(struct audio_hw_device *dev, int mode)
947 {
948     FNLOG();
949 
950     return 0;
951 }
952 
adev_set_mic_mute(struct audio_hw_device * dev,bool state)953 static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
954 {
955     FNLOG();
956 
957     return -ENOSYS;
958 }
959 
adev_get_mic_mute(const struct audio_hw_device * dev,bool * state)960 static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
961 {
962     FNLOG();
963 
964     return -ENOSYS;
965 }
966 
adev_get_input_buffer_size(const struct audio_hw_device * dev,const struct audio_config * config)967 static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
968                                          const struct audio_config *config)
969 {
970     FNLOG();
971 
972     return 320;
973 }
974 
adev_open_input_stream(struct audio_hw_device * dev,audio_io_handle_t handle,audio_devices_t devices,struct audio_config * config,struct audio_stream_in ** stream_in)975 static int adev_open_input_stream(struct audio_hw_device *dev,
976                                   audio_io_handle_t handle,
977                                   audio_devices_t devices,
978                                   struct audio_config *config,
979                                   struct audio_stream_in **stream_in)
980 {
981     struct a2dp_audio_device *ladev = (struct a2dp_audio_device *)dev;
982     struct a2dp_stream_in *in;
983     int ret;
984 
985     FNLOG();
986 
987     in = (struct a2dp_stream_in *)calloc(1, sizeof(struct a2dp_stream_in));
988 
989     if (!in)
990         return -ENOMEM;
991 
992     in->stream.common.get_sample_rate = in_get_sample_rate;
993     in->stream.common.set_sample_rate = in_set_sample_rate;
994     in->stream.common.get_buffer_size = in_get_buffer_size;
995     in->stream.common.get_channels = in_get_channels;
996     in->stream.common.get_format = in_get_format;
997     in->stream.common.set_format = in_set_format;
998     in->stream.common.standby = in_standby;
999     in->stream.common.dump = in_dump;
1000     in->stream.common.set_parameters = in_set_parameters;
1001     in->stream.common.get_parameters = in_get_parameters;
1002     in->stream.common.add_audio_effect = in_add_audio_effect;
1003     in->stream.common.remove_audio_effect = in_remove_audio_effect;
1004     in->stream.set_gain = in_set_gain;
1005     in->stream.read = in_read;
1006     in->stream.get_input_frames_lost = in_get_input_frames_lost;
1007 
1008     *stream_in = &in->stream;
1009     return 0;
1010 
1011 err_open:
1012     free(in);
1013     *stream_in = NULL;
1014     return ret;
1015 }
1016 
adev_close_input_stream(struct audio_hw_device * dev,struct audio_stream_in * in)1017 static void adev_close_input_stream(struct audio_hw_device *dev,
1018                                    struct audio_stream_in *in)
1019 {
1020     FNLOG();
1021 
1022     return;
1023 }
1024 
adev_dump(const audio_hw_device_t * device,int fd)1025 static int adev_dump(const audio_hw_device_t *device, int fd)
1026 {
1027     FNLOG();
1028 
1029     return 0;
1030 }
1031 
adev_close(hw_device_t * device)1032 static int adev_close(hw_device_t *device)
1033 {
1034     FNLOG();
1035 
1036     free(device);
1037     return 0;
1038 }
1039 
adev_open(const hw_module_t * module,const char * name,hw_device_t ** device)1040 static int adev_open(const hw_module_t* module, const char* name,
1041                      hw_device_t** device)
1042 {
1043     struct a2dp_audio_device *adev;
1044     int ret;
1045 
1046     INFO(" adev_open in A2dp_hw module");
1047     FNLOG();
1048 
1049     if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
1050     {
1051         ERROR("interface %s not matching [%s]", name, AUDIO_HARDWARE_INTERFACE);
1052         return -EINVAL;
1053     }
1054 
1055     adev = calloc(1, sizeof(struct a2dp_audio_device));
1056 
1057     if (!adev)
1058         return -ENOMEM;
1059 
1060     adev->device.common.tag = HARDWARE_DEVICE_TAG;
1061     adev->device.common.version = AUDIO_DEVICE_API_VERSION_CURRENT;
1062     adev->device.common.module = (struct hw_module_t *) module;
1063     adev->device.common.close = adev_close;
1064 
1065     adev->device.init_check = adev_init_check;
1066     adev->device.set_voice_volume = adev_set_voice_volume;
1067     adev->device.set_master_volume = adev_set_master_volume;
1068     adev->device.set_mode = adev_set_mode;
1069     adev->device.set_mic_mute = adev_set_mic_mute;
1070     adev->device.get_mic_mute = adev_get_mic_mute;
1071     adev->device.set_parameters = adev_set_parameters;
1072     adev->device.get_parameters = adev_get_parameters;
1073     adev->device.get_input_buffer_size = adev_get_input_buffer_size;
1074     adev->device.open_output_stream = adev_open_output_stream;
1075     adev->device.close_output_stream = adev_close_output_stream;
1076     adev->device.open_input_stream = adev_open_input_stream;
1077     adev->device.close_input_stream = adev_close_input_stream;
1078     adev->device.dump = adev_dump;
1079 
1080     adev->output = NULL;
1081 
1082 
1083     *device = &adev->device.common;
1084 
1085     return 0;
1086 }
1087 
1088 static struct hw_module_methods_t hal_module_methods = {
1089     .open = adev_open,
1090 };
1091 
1092 struct audio_module HAL_MODULE_INFO_SYM = {
1093     .common = {
1094         .tag = HARDWARE_MODULE_TAG,
1095         .version_major = 1,
1096         .version_minor = 0,
1097         .id = AUDIO_HARDWARE_MODULE_ID,
1098         .name = "A2DP Audio HW HAL",
1099         .author = "The Android Open Source Project",
1100         .methods = &hal_module_methods,
1101     },
1102 };
1103 
1104