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
71typedef 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
80struct a2dp_stream_out;
81
82struct a2dp_audio_device {
83    struct audio_hw_device device;
84    struct a2dp_stream_out *output;
85};
86
87struct 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
95struct 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
105struct a2dp_stream_in {
106    struct audio_stream_in stream;
107};
108
109/*****************************************************************************
110**  Static variables
111******************************************************************************/
112
113/*****************************************************************************
114**  Static functions
115******************************************************************************/
116
117static 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
131static 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 */
147static 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
172static 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
188static 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
219static 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
246static 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
266static 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
304static 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
326static 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
363static 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
392static 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
418static 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
437static 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
493static 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
502static 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
519static 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
528static 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
537static 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
544static 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
551static 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
571static 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
578static 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
632static 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
643static 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
659static 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
671static int out_get_render_position(const struct audio_stream_out *stream,
672                                   uint32_t *dsp_frames)
673{
674    FNLOG();
675    return -EINVAL;
676}
677
678static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
679{
680    FNLOG();
681    return 0;
682}
683
684static 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
694static uint32_t in_get_sample_rate(const struct audio_stream *stream)
695{
696    FNLOG();
697    return 8000;
698}
699
700static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
701{
702    FNLOG();
703    return 0;
704}
705
706static size_t in_get_buffer_size(const struct audio_stream *stream)
707{
708    FNLOG();
709    return 320;
710}
711
712static uint32_t in_get_channels(const struct audio_stream *stream)
713{
714    FNLOG();
715    return AUDIO_CHANNEL_IN_MONO;
716}
717
718static audio_format_t in_get_format(const struct audio_stream *stream)
719{
720    FNLOG();
721    return AUDIO_FORMAT_PCM_16_BIT;
722}
723
724static int in_set_format(struct audio_stream *stream, audio_format_t format)
725{
726    FNLOG();
727    return 0;
728}
729
730static int in_standby(struct audio_stream *stream)
731{
732    FNLOG();
733    return 0;
734}
735
736static int in_dump(const struct audio_stream *stream, int fd)
737{
738    FNLOG();
739    return 0;
740}
741
742static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
743{
744    FNLOG();
745    return 0;
746}
747
748static char * in_get_parameters(const struct audio_stream *stream,
749                                const char *keys)
750{
751    FNLOG();
752    return strdup("");
753}
754
755static int in_set_gain(struct audio_stream_in *stream, float gain)
756{
757    FNLOG();
758    return 0;
759}
760
761static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
762                       size_t bytes)
763{
764    FNLOG();
765    return bytes;
766}
767
768static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
769{
770    FNLOG();
771    return 0;
772}
773
774static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
775{
776    FNLOG();
777    return 0;
778}
779
780static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
781{
782    FNLOG();
783
784    return 0;
785}
786
787static 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
866err_open:
867    free(out);
868    *stream_out = NULL;
869    ERROR("failed");
870    return ret;
871}
872
873static 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
891static 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
907static 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
923static 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
932static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
933{
934    FNLOG();
935
936    return -ENOSYS;
937}
938
939static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
940{
941    FNLOG();
942
943    return -ENOSYS;
944}
945
946static int adev_set_mode(struct audio_hw_device *dev, int mode)
947{
948    FNLOG();
949
950    return 0;
951}
952
953static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
954{
955    FNLOG();
956
957    return -ENOSYS;
958}
959
960static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
961{
962    FNLOG();
963
964    return -ENOSYS;
965}
966
967static 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
975static 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
1011err_open:
1012    free(in);
1013    *stream_in = NULL;
1014    return ret;
1015}
1016
1017static void adev_close_input_stream(struct audio_hw_device *dev,
1018                                   struct audio_stream_in *in)
1019{
1020    FNLOG();
1021
1022    return;
1023}
1024
1025static int adev_dump(const audio_hw_device_t *device, int fd)
1026{
1027    FNLOG();
1028
1029    return 0;
1030}
1031
1032static int adev_close(hw_device_t *device)
1033{
1034    FNLOG();
1035
1036    free(device);
1037    return 0;
1038}
1039
1040static 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
1088static struct hw_module_methods_t hal_module_methods = {
1089    .open = adev_open,
1090};
1091
1092struct 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