1/*
2 * Copyright (C) 2011 The Android Open Source Project
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#define LOG_TAG "legacy_audio_hw_hal"
18//#define LOG_NDEBUG 0
19
20#include <stdint.h>
21
22#include <hardware/hardware.h>
23#include <system/audio.h>
24#include <hardware/audio.h>
25
26#include <hardware_legacy/AudioHardwareInterface.h>
27#include <hardware_legacy/AudioSystemLegacy.h>
28
29namespace android_audio_legacy {
30
31extern "C" {
32
33struct legacy_audio_module {
34    struct audio_module module;
35};
36
37struct legacy_audio_device {
38    struct audio_hw_device device;
39
40    struct AudioHardwareInterface *hwif;
41};
42
43struct legacy_stream_out {
44    struct audio_stream_out stream;
45
46    AudioStreamOut *legacy_out;
47};
48
49struct legacy_stream_in {
50    struct audio_stream_in stream;
51
52    AudioStreamIn *legacy_in;
53};
54
55
56enum {
57    HAL_API_REV_1_0,
58    HAL_API_REV_2_0,
59    HAL_API_REV_NUM
60} hal_api_rev;
61
62static uint32_t audio_device_conv_table[][HAL_API_REV_NUM] =
63{
64    /* output devices */
65    { AudioSystem::DEVICE_OUT_EARPIECE, AUDIO_DEVICE_OUT_EARPIECE },
66    { AudioSystem::DEVICE_OUT_SPEAKER, AUDIO_DEVICE_OUT_SPEAKER },
67    { AudioSystem::DEVICE_OUT_WIRED_HEADSET, AUDIO_DEVICE_OUT_WIRED_HEADSET },
68    { AudioSystem::DEVICE_OUT_WIRED_HEADPHONE, AUDIO_DEVICE_OUT_WIRED_HEADPHONE },
69    { AudioSystem::DEVICE_OUT_BLUETOOTH_SCO, AUDIO_DEVICE_OUT_BLUETOOTH_SCO },
70    { AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET, AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET },
71    { AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT, AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT },
72    { AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP },
73    { AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES },
74    { AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER },
75    { AudioSystem::DEVICE_OUT_AUX_DIGITAL, AUDIO_DEVICE_OUT_AUX_DIGITAL },
76    { AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET, AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET },
77    { AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET, AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET },
78    { AudioSystem::DEVICE_OUT_DEFAULT, AUDIO_DEVICE_OUT_DEFAULT },
79    /* input devices */
80    { AudioSystem::DEVICE_IN_COMMUNICATION, AUDIO_DEVICE_IN_COMMUNICATION },
81    { AudioSystem::DEVICE_IN_AMBIENT, AUDIO_DEVICE_IN_AMBIENT },
82    { AudioSystem::DEVICE_IN_BUILTIN_MIC, AUDIO_DEVICE_IN_BUILTIN_MIC },
83    { AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET, AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET },
84    { AudioSystem::DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_IN_WIRED_HEADSET },
85    { AudioSystem::DEVICE_IN_AUX_DIGITAL, AUDIO_DEVICE_IN_AUX_DIGITAL },
86    { AudioSystem::DEVICE_IN_VOICE_CALL, AUDIO_DEVICE_IN_VOICE_CALL },
87    { AudioSystem::DEVICE_IN_BACK_MIC, AUDIO_DEVICE_IN_BACK_MIC },
88    { AudioSystem::DEVICE_IN_DEFAULT, AUDIO_DEVICE_IN_DEFAULT },
89};
90
91static uint32_t convert_audio_device(uint32_t from_device, int from_rev, int to_rev)
92{
93    const uint32_t k_num_devices = sizeof(audio_device_conv_table)/sizeof(uint32_t)/HAL_API_REV_NUM;
94    uint32_t to_device = AUDIO_DEVICE_NONE;
95    uint32_t in_bit = 0;
96
97    if (from_rev != HAL_API_REV_1_0) {
98        in_bit = from_device & AUDIO_DEVICE_BIT_IN;
99        from_device &= ~AUDIO_DEVICE_BIT_IN;
100    }
101
102    while (from_device) {
103        uint32_t i = 31 - __builtin_clz(from_device);
104        uint32_t cur_device = (1 << i) | in_bit;
105
106        for (i = 0; i < k_num_devices; i++) {
107            if (audio_device_conv_table[i][from_rev] == cur_device) {
108                to_device |= audio_device_conv_table[i][to_rev];
109                break;
110            }
111        }
112        from_device &= ~cur_device;
113    }
114    return to_device;
115}
116
117
118/** audio_stream_out implementation **/
119static uint32_t out_get_sample_rate(const struct audio_stream *stream)
120{
121    const struct legacy_stream_out *out =
122        reinterpret_cast<const struct legacy_stream_out *>(stream);
123    return out->legacy_out->sampleRate();
124}
125
126static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
127{
128    struct legacy_stream_out *out =
129        reinterpret_cast<struct legacy_stream_out *>(stream);
130
131    ALOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
132    /* TODO: implement this */
133    return 0;
134}
135
136static size_t out_get_buffer_size(const struct audio_stream *stream)
137{
138    const struct legacy_stream_out *out =
139        reinterpret_cast<const struct legacy_stream_out *>(stream);
140    return out->legacy_out->bufferSize();
141}
142
143static audio_channel_mask_t out_get_channels(const struct audio_stream *stream)
144{
145    const struct legacy_stream_out *out =
146        reinterpret_cast<const struct legacy_stream_out *>(stream);
147    return (audio_channel_mask_t) out->legacy_out->channels();
148}
149
150static audio_format_t out_get_format(const struct audio_stream *stream)
151{
152    const struct legacy_stream_out *out =
153        reinterpret_cast<const struct legacy_stream_out *>(stream);
154    // legacy API, don't change return type
155    return (audio_format_t) out->legacy_out->format();
156}
157
158static int out_set_format(struct audio_stream *stream, audio_format_t format)
159{
160    struct legacy_stream_out *out =
161        reinterpret_cast<struct legacy_stream_out *>(stream);
162    ALOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
163    /* TODO: implement me */
164    return 0;
165}
166
167static int out_standby(struct audio_stream *stream)
168{
169    struct legacy_stream_out *out =
170        reinterpret_cast<struct legacy_stream_out *>(stream);
171    return out->legacy_out->standby();
172}
173
174static int out_dump(const struct audio_stream *stream, int fd)
175{
176    const struct legacy_stream_out *out =
177        reinterpret_cast<const struct legacy_stream_out *>(stream);
178    Vector<String16> args;
179    return out->legacy_out->dump(fd, args);
180}
181
182static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
183{
184    struct legacy_stream_out *out =
185        reinterpret_cast<struct legacy_stream_out *>(stream);
186    int val;
187    String8 s8 = String8(kvpairs);
188    AudioParameter parms = AudioParameter(String8(kvpairs));
189
190    if (parms.getInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val) == NO_ERROR) {
191        val = convert_audio_device(val, HAL_API_REV_2_0, HAL_API_REV_1_0);
192        parms.remove(String8(AUDIO_PARAMETER_STREAM_ROUTING));
193        parms.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val);
194        s8 = parms.toString();
195    }
196
197    return out->legacy_out->setParameters(s8);
198}
199
200static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
201{
202    const struct legacy_stream_out *out =
203        reinterpret_cast<const struct legacy_stream_out *>(stream);
204    String8 s8;
205    int val;
206
207    s8 = out->legacy_out->getParameters(String8(keys));
208
209    AudioParameter parms = AudioParameter(s8);
210    if (parms.getInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val) == NO_ERROR) {
211        val = convert_audio_device(val, HAL_API_REV_1_0, HAL_API_REV_2_0);
212        parms.remove(String8(AUDIO_PARAMETER_STREAM_ROUTING));
213        parms.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val);
214        s8 = parms.toString();
215    }
216
217    return strdup(s8.string());
218}
219
220static uint32_t out_get_latency(const struct audio_stream_out *stream)
221{
222    const struct legacy_stream_out *out =
223        reinterpret_cast<const struct legacy_stream_out *>(stream);
224    return out->legacy_out->latency();
225}
226
227static int out_set_volume(struct audio_stream_out *stream, float left,
228                          float right)
229{
230    struct legacy_stream_out *out =
231        reinterpret_cast<struct legacy_stream_out *>(stream);
232    return out->legacy_out->setVolume(left, right);
233}
234
235static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
236                         size_t bytes)
237{
238    struct legacy_stream_out *out =
239        reinterpret_cast<struct legacy_stream_out *>(stream);
240    return out->legacy_out->write(buffer, bytes);
241}
242
243static int out_get_render_position(const struct audio_stream_out *stream,
244                                   uint32_t *dsp_frames)
245{
246    const struct legacy_stream_out *out =
247        reinterpret_cast<const struct legacy_stream_out *>(stream);
248    return out->legacy_out->getRenderPosition(dsp_frames);
249}
250
251static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
252                                        int64_t *timestamp)
253{
254    const struct legacy_stream_out *out =
255        reinterpret_cast<const struct legacy_stream_out *>(stream);
256    return out->legacy_out->getNextWriteTimestamp(timestamp);
257}
258
259static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
260{
261    return 0;
262}
263
264static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
265{
266    return 0;
267}
268
269/** audio_stream_in implementation **/
270static uint32_t in_get_sample_rate(const struct audio_stream *stream)
271{
272    const struct legacy_stream_in *in =
273        reinterpret_cast<const struct legacy_stream_in *>(stream);
274    return in->legacy_in->sampleRate();
275}
276
277static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
278{
279    struct legacy_stream_in *in =
280        reinterpret_cast<struct legacy_stream_in *>(stream);
281
282    ALOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
283    /* TODO: implement this */
284    return 0;
285}
286
287static size_t in_get_buffer_size(const struct audio_stream *stream)
288{
289    const struct legacy_stream_in *in =
290        reinterpret_cast<const struct legacy_stream_in *>(stream);
291    return in->legacy_in->bufferSize();
292}
293
294static audio_channel_mask_t in_get_channels(const struct audio_stream *stream)
295{
296    const struct legacy_stream_in *in =
297        reinterpret_cast<const struct legacy_stream_in *>(stream);
298    return (audio_channel_mask_t) in->legacy_in->channels();
299}
300
301static audio_format_t in_get_format(const struct audio_stream *stream)
302{
303    const struct legacy_stream_in *in =
304        reinterpret_cast<const struct legacy_stream_in *>(stream);
305    // legacy API, don't change return type
306    return (audio_format_t) in->legacy_in->format();
307}
308
309static int in_set_format(struct audio_stream *stream, audio_format_t format)
310{
311    struct legacy_stream_in *in =
312        reinterpret_cast<struct legacy_stream_in *>(stream);
313    ALOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
314    /* TODO: implement me */
315    return 0;
316}
317
318static int in_standby(struct audio_stream *stream)
319{
320    struct legacy_stream_in *in = reinterpret_cast<struct legacy_stream_in *>(stream);
321    return in->legacy_in->standby();
322}
323
324static int in_dump(const struct audio_stream *stream, int fd)
325{
326    const struct legacy_stream_in *in =
327        reinterpret_cast<const struct legacy_stream_in *>(stream);
328    Vector<String16> args;
329    return in->legacy_in->dump(fd, args);
330}
331
332static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
333{
334    struct legacy_stream_in *in =
335        reinterpret_cast<struct legacy_stream_in *>(stream);
336    int val;
337    AudioParameter parms = AudioParameter(String8(kvpairs));
338    String8 s8 = String8(kvpairs);
339
340    if (parms.getInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val) == NO_ERROR) {
341        val = convert_audio_device(val, HAL_API_REV_2_0, HAL_API_REV_1_0);
342        parms.remove(String8(AUDIO_PARAMETER_STREAM_ROUTING));
343        parms.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val);
344        s8 = parms.toString();
345    }
346
347    return in->legacy_in->setParameters(s8);
348}
349
350static char * in_get_parameters(const struct audio_stream *stream,
351                                const char *keys)
352{
353    const struct legacy_stream_in *in =
354        reinterpret_cast<const struct legacy_stream_in *>(stream);
355    String8 s8;
356    int val;
357
358    s8 = in->legacy_in->getParameters(String8(keys));
359
360    AudioParameter parms = AudioParameter(s8);
361    if (parms.getInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val) == NO_ERROR) {
362        val = convert_audio_device(val, HAL_API_REV_1_0, HAL_API_REV_2_0);
363        parms.remove(String8(AUDIO_PARAMETER_STREAM_ROUTING));
364        parms.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), val);
365        s8 = parms.toString();
366    }
367
368    return strdup(s8.string());
369}
370
371static int in_set_gain(struct audio_stream_in *stream, float gain)
372{
373    struct legacy_stream_in *in =
374        reinterpret_cast<struct legacy_stream_in *>(stream);
375    return in->legacy_in->setGain(gain);
376}
377
378static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
379                       size_t bytes)
380{
381    struct legacy_stream_in *in =
382        reinterpret_cast<struct legacy_stream_in *>(stream);
383    return in->legacy_in->read(buffer, bytes);
384}
385
386static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
387{
388    struct legacy_stream_in *in =
389        reinterpret_cast<struct legacy_stream_in *>(stream);
390    return in->legacy_in->getInputFramesLost();
391}
392
393static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
394{
395    const struct legacy_stream_in *in =
396        reinterpret_cast<const struct legacy_stream_in *>(stream);
397    return in->legacy_in->addAudioEffect(effect);
398}
399
400static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
401{
402    const struct legacy_stream_in *in =
403        reinterpret_cast<const struct legacy_stream_in *>(stream);
404    return in->legacy_in->removeAudioEffect(effect);
405}
406
407/** audio_hw_device implementation **/
408static inline struct legacy_audio_device * to_ladev(struct audio_hw_device *dev)
409{
410    return reinterpret_cast<struct legacy_audio_device *>(dev);
411}
412
413static inline const struct legacy_audio_device * to_cladev(const struct audio_hw_device *dev)
414{
415    return reinterpret_cast<const struct legacy_audio_device *>(dev);
416}
417
418static int adev_init_check(const struct audio_hw_device *dev)
419{
420    const struct legacy_audio_device *ladev = to_cladev(dev);
421
422    return ladev->hwif->initCheck();
423}
424
425static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
426{
427    struct legacy_audio_device *ladev = to_ladev(dev);
428    return ladev->hwif->setVoiceVolume(volume);
429}
430
431static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
432{
433    struct legacy_audio_device *ladev = to_ladev(dev);
434    return ladev->hwif->setMasterVolume(volume);
435}
436
437static int adev_get_master_volume(struct audio_hw_device *dev, float* volume)
438{
439    struct legacy_audio_device *ladev = to_ladev(dev);
440    return ladev->hwif->getMasterVolume(volume);
441}
442
443static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
444{
445    struct legacy_audio_device *ladev = to_ladev(dev);
446    // as this is the legacy API, don't change it to use audio_mode_t instead of int
447    return ladev->hwif->setMode((int) mode);
448}
449
450static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
451{
452    struct legacy_audio_device *ladev = to_ladev(dev);
453    return ladev->hwif->setMicMute(state);
454}
455
456static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
457{
458    const struct legacy_audio_device *ladev = to_cladev(dev);
459    return ladev->hwif->getMicMute(state);
460}
461
462static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
463{
464    struct legacy_audio_device *ladev = to_ladev(dev);
465    return ladev->hwif->setParameters(String8(kvpairs));
466}
467
468static char * adev_get_parameters(const struct audio_hw_device *dev,
469                                  const char *keys)
470{
471    const struct legacy_audio_device *ladev = to_cladev(dev);
472    String8 s8;
473
474    s8 = ladev->hwif->getParameters(String8(keys));
475    return strdup(s8.string());
476}
477
478static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
479                                         const struct audio_config *config)
480{
481    const struct legacy_audio_device *ladev = to_cladev(dev);
482    return ladev->hwif->getInputBufferSize(config->sample_rate, (int) config->format,
483                                           popcount(config->channel_mask));
484}
485
486static int adev_open_output_stream(struct audio_hw_device *dev,
487                                   audio_io_handle_t handle,
488                                   audio_devices_t devices,
489                                   audio_output_flags_t flags,
490                                   struct audio_config *config,
491                                   struct audio_stream_out **stream_out)
492{
493    struct legacy_audio_device *ladev = to_ladev(dev);
494    status_t status;
495    struct legacy_stream_out *out;
496    int ret;
497
498    out = (struct legacy_stream_out *)calloc(1, sizeof(*out));
499    if (!out)
500        return -ENOMEM;
501
502    devices = convert_audio_device(devices, HAL_API_REV_2_0, HAL_API_REV_1_0);
503
504    out->legacy_out = ladev->hwif->openOutputStream(devices, (int *) &config->format,
505                                                    &config->channel_mask,
506                                                    &config->sample_rate, &status);
507    if (!out->legacy_out) {
508        ret = status;
509        goto err_open;
510    }
511
512    out->stream.common.get_sample_rate = out_get_sample_rate;
513    out->stream.common.set_sample_rate = out_set_sample_rate;
514    out->stream.common.get_buffer_size = out_get_buffer_size;
515    out->stream.common.get_channels = out_get_channels;
516    out->stream.common.get_format = out_get_format;
517    out->stream.common.set_format = out_set_format;
518    out->stream.common.standby = out_standby;
519    out->stream.common.dump = out_dump;
520    out->stream.common.set_parameters = out_set_parameters;
521    out->stream.common.get_parameters = out_get_parameters;
522    out->stream.common.add_audio_effect = out_add_audio_effect;
523    out->stream.common.remove_audio_effect = out_remove_audio_effect;
524    out->stream.get_latency = out_get_latency;
525    out->stream.set_volume = out_set_volume;
526    out->stream.write = out_write;
527    out->stream.get_render_position = out_get_render_position;
528    out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
529
530    *stream_out = &out->stream;
531    return 0;
532
533err_open:
534    free(out);
535    *stream_out = NULL;
536    return ret;
537}
538
539static void adev_close_output_stream(struct audio_hw_device *dev,
540                                     struct audio_stream_out* stream)
541{
542    struct legacy_audio_device *ladev = to_ladev(dev);
543    struct legacy_stream_out *out = reinterpret_cast<struct legacy_stream_out *>(stream);
544
545    ladev->hwif->closeOutputStream(out->legacy_out);
546    free(out);
547}
548
549/** This method creates and opens the audio hardware input stream */
550static int adev_open_input_stream(struct audio_hw_device *dev,
551                                  audio_io_handle_t handle,
552                                  audio_devices_t devices,
553                                  struct audio_config *config,
554                                  struct audio_stream_in **stream_in)
555{
556    struct legacy_audio_device *ladev = to_ladev(dev);
557    status_t status;
558    struct legacy_stream_in *in;
559    int ret;
560
561    in = (struct legacy_stream_in *)calloc(1, sizeof(*in));
562    if (!in)
563        return -ENOMEM;
564
565    devices = convert_audio_device(devices, HAL_API_REV_2_0, HAL_API_REV_1_0);
566
567    in->legacy_in = ladev->hwif->openInputStream(devices, (int *) &config->format,
568                                                 &config->channel_mask, &config->sample_rate,
569                                                 &status, (AudioSystem::audio_in_acoustics)0);
570    if (!in->legacy_in) {
571        ret = status;
572        goto err_open;
573    }
574
575    in->stream.common.get_sample_rate = in_get_sample_rate;
576    in->stream.common.set_sample_rate = in_set_sample_rate;
577    in->stream.common.get_buffer_size = in_get_buffer_size;
578    in->stream.common.get_channels = in_get_channels;
579    in->stream.common.get_format = in_get_format;
580    in->stream.common.set_format = in_set_format;
581    in->stream.common.standby = in_standby;
582    in->stream.common.dump = in_dump;
583    in->stream.common.set_parameters = in_set_parameters;
584    in->stream.common.get_parameters = in_get_parameters;
585    in->stream.common.add_audio_effect = in_add_audio_effect;
586    in->stream.common.remove_audio_effect = in_remove_audio_effect;
587    in->stream.set_gain = in_set_gain;
588    in->stream.read = in_read;
589    in->stream.get_input_frames_lost = in_get_input_frames_lost;
590
591    *stream_in = &in->stream;
592    return 0;
593
594err_open:
595    free(in);
596    *stream_in = NULL;
597    return ret;
598}
599
600static void adev_close_input_stream(struct audio_hw_device *dev,
601                               struct audio_stream_in *stream)
602{
603    struct legacy_audio_device *ladev = to_ladev(dev);
604    struct legacy_stream_in *in =
605        reinterpret_cast<struct legacy_stream_in *>(stream);
606
607    ladev->hwif->closeInputStream(in->legacy_in);
608    free(in);
609}
610
611static int adev_dump(const struct audio_hw_device *dev, int fd)
612{
613    const struct legacy_audio_device *ladev = to_cladev(dev);
614    Vector<String16> args;
615
616    return ladev->hwif->dumpState(fd, args);
617}
618
619static int legacy_adev_close(hw_device_t* device)
620{
621    struct audio_hw_device *hwdev =
622                        reinterpret_cast<struct audio_hw_device *>(device);
623    struct legacy_audio_device *ladev = to_ladev(hwdev);
624
625    if (!ladev)
626        return 0;
627
628    if (ladev->hwif)
629        delete ladev->hwif;
630
631    free(ladev);
632    return 0;
633}
634
635static int legacy_adev_open(const hw_module_t* module, const char* name,
636                            hw_device_t** device)
637{
638    struct legacy_audio_device *ladev;
639    int ret;
640
641    if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
642        return -EINVAL;
643
644    ladev = (struct legacy_audio_device *)calloc(1, sizeof(*ladev));
645    if (!ladev)
646        return -ENOMEM;
647
648    ladev->device.common.tag = HARDWARE_DEVICE_TAG;
649    ladev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
650    ladev->device.common.module = const_cast<hw_module_t*>(module);
651    ladev->device.common.close = legacy_adev_close;
652
653    ladev->device.init_check = adev_init_check;
654    ladev->device.set_voice_volume = adev_set_voice_volume;
655    ladev->device.set_master_volume = adev_set_master_volume;
656    ladev->device.get_master_volume = adev_get_master_volume;
657    ladev->device.set_mode = adev_set_mode;
658    ladev->device.set_mic_mute = adev_set_mic_mute;
659    ladev->device.get_mic_mute = adev_get_mic_mute;
660    ladev->device.set_parameters = adev_set_parameters;
661    ladev->device.get_parameters = adev_get_parameters;
662    ladev->device.get_input_buffer_size = adev_get_input_buffer_size;
663    ladev->device.open_output_stream = adev_open_output_stream;
664    ladev->device.close_output_stream = adev_close_output_stream;
665    ladev->device.open_input_stream = adev_open_input_stream;
666    ladev->device.close_input_stream = adev_close_input_stream;
667    ladev->device.dump = adev_dump;
668
669    ladev->hwif = createAudioHardware();
670    if (!ladev->hwif) {
671        ret = -EIO;
672        goto err_create_audio_hw;
673    }
674
675    *device = &ladev->device.common;
676
677    return 0;
678
679err_create_audio_hw:
680    free(ladev);
681    return ret;
682}
683
684static struct hw_module_methods_t legacy_audio_module_methods = {
685        open: legacy_adev_open
686};
687
688struct legacy_audio_module HAL_MODULE_INFO_SYM = {
689    module: {
690        common: {
691            tag: HARDWARE_MODULE_TAG,
692            module_api_version: AUDIO_MODULE_API_VERSION_0_1,
693            hal_api_version: HARDWARE_HAL_API_VERSION,
694            id: AUDIO_HARDWARE_MODULE_ID,
695            name: "LEGACY Audio HW HAL",
696            author: "The Android Open Source Project",
697            methods: &legacy_audio_module_methods,
698            dso : NULL,
699            reserved : {0},
700        },
701    },
702};
703
704}; // extern "C"
705
706}; // namespace android_audio_legacy
707