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/** audio_stream_out implementation **/
56static uint32_t out_get_sample_rate(const struct audio_stream *stream)
57{
58    const struct legacy_stream_out *out =
59        reinterpret_cast<const struct legacy_stream_out *>(stream);
60    return out->legacy_out->sampleRate();
61}
62
63static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
64{
65    struct legacy_stream_out *out =
66        reinterpret_cast<struct legacy_stream_out *>(stream);
67
68    LOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
69    /* TODO: implement this */
70    return 0;
71}
72
73static size_t out_get_buffer_size(const struct audio_stream *stream)
74{
75    const struct legacy_stream_out *out =
76        reinterpret_cast<const struct legacy_stream_out *>(stream);
77    return out->legacy_out->bufferSize();
78}
79
80static uint32_t out_get_channels(const struct audio_stream *stream)
81{
82    const struct legacy_stream_out *out =
83        reinterpret_cast<const struct legacy_stream_out *>(stream);
84    return out->legacy_out->channels();
85}
86
87static int out_get_format(const struct audio_stream *stream)
88{
89    const struct legacy_stream_out *out =
90        reinterpret_cast<const struct legacy_stream_out *>(stream);
91    return out->legacy_out->format();
92}
93
94static int out_set_format(struct audio_stream *stream, int format)
95{
96    struct legacy_stream_out *out =
97        reinterpret_cast<struct legacy_stream_out *>(stream);
98    LOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
99    /* TODO: implement me */
100    return 0;
101}
102
103static int out_standby(struct audio_stream *stream)
104{
105    struct legacy_stream_out *out =
106        reinterpret_cast<struct legacy_stream_out *>(stream);
107    return out->legacy_out->standby();
108}
109
110static int out_dump(const struct audio_stream *stream, int fd)
111{
112    const struct legacy_stream_out *out =
113        reinterpret_cast<const struct legacy_stream_out *>(stream);
114    Vector<String16> args;
115    return out->legacy_out->dump(fd, args);
116}
117
118static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
119{
120    struct legacy_stream_out *out =
121        reinterpret_cast<struct legacy_stream_out *>(stream);
122    return out->legacy_out->setParameters(String8(kvpairs));
123}
124
125static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
126{
127    const struct legacy_stream_out *out =
128        reinterpret_cast<const struct legacy_stream_out *>(stream);
129    String8 s8;
130    s8 = out->legacy_out->getParameters(String8(keys));
131    return strdup(s8.string());
132}
133
134static uint32_t out_get_latency(const struct audio_stream_out *stream)
135{
136    const struct legacy_stream_out *out =
137        reinterpret_cast<const struct legacy_stream_out *>(stream);
138    return out->legacy_out->latency();
139}
140
141static int out_set_volume(struct audio_stream_out *stream, float left,
142                          float right)
143{
144    struct legacy_stream_out *out =
145        reinterpret_cast<struct legacy_stream_out *>(stream);
146    return out->legacy_out->setVolume(left, right);
147}
148
149static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
150                         size_t bytes)
151{
152    struct legacy_stream_out *out =
153        reinterpret_cast<struct legacy_stream_out *>(stream);
154    return out->legacy_out->write(buffer, bytes);
155}
156
157static int out_get_render_position(const struct audio_stream_out *stream,
158                                   uint32_t *dsp_frames)
159{
160    const struct legacy_stream_out *out =
161        reinterpret_cast<const struct legacy_stream_out *>(stream);
162    return out->legacy_out->getRenderPosition(dsp_frames);
163}
164
165static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
166{
167    return 0;
168}
169
170static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
171{
172    return 0;
173}
174
175/** audio_stream_in implementation **/
176static uint32_t in_get_sample_rate(const struct audio_stream *stream)
177{
178    const struct legacy_stream_in *in =
179        reinterpret_cast<const struct legacy_stream_in *>(stream);
180    return in->legacy_in->sampleRate();
181}
182
183static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
184{
185    struct legacy_stream_in *in =
186        reinterpret_cast<struct legacy_stream_in *>(stream);
187
188    LOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
189    /* TODO: implement this */
190    return 0;
191}
192
193static size_t in_get_buffer_size(const struct audio_stream *stream)
194{
195    const struct legacy_stream_in *in =
196        reinterpret_cast<const struct legacy_stream_in *>(stream);
197    return in->legacy_in->bufferSize();
198}
199
200static uint32_t in_get_channels(const struct audio_stream *stream)
201{
202    const struct legacy_stream_in *in =
203        reinterpret_cast<const struct legacy_stream_in *>(stream);
204    return in->legacy_in->channels();
205}
206
207static int in_get_format(const struct audio_stream *stream)
208{
209    const struct legacy_stream_in *in =
210        reinterpret_cast<const struct legacy_stream_in *>(stream);
211    return in->legacy_in->format();
212}
213
214static int in_set_format(struct audio_stream *stream, int format)
215{
216    struct legacy_stream_in *in =
217        reinterpret_cast<struct legacy_stream_in *>(stream);
218    LOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
219    /* TODO: implement me */
220    return 0;
221}
222
223static int in_standby(struct audio_stream *stream)
224{
225    struct legacy_stream_in *in = reinterpret_cast<struct legacy_stream_in *>(stream);
226    return in->legacy_in->standby();
227}
228
229static int in_dump(const struct audio_stream *stream, int fd)
230{
231    const struct legacy_stream_in *in =
232        reinterpret_cast<const struct legacy_stream_in *>(stream);
233    Vector<String16> args;
234    return in->legacy_in->dump(fd, args);
235}
236
237static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
238{
239    struct legacy_stream_in *in =
240        reinterpret_cast<struct legacy_stream_in *>(stream);
241    return in->legacy_in->setParameters(String8(kvpairs));
242}
243
244static char * in_get_parameters(const struct audio_stream *stream,
245                                const char *keys)
246{
247    const struct legacy_stream_in *in =
248        reinterpret_cast<const struct legacy_stream_in *>(stream);
249    String8 s8;
250    s8 = in->legacy_in->getParameters(String8(keys));
251    return strdup(s8.string());
252}
253
254static int in_set_gain(struct audio_stream_in *stream, float gain)
255{
256    struct legacy_stream_in *in =
257        reinterpret_cast<struct legacy_stream_in *>(stream);
258    return in->legacy_in->setGain(gain);
259}
260
261static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
262                       size_t bytes)
263{
264    struct legacy_stream_in *in =
265        reinterpret_cast<struct legacy_stream_in *>(stream);
266    return in->legacy_in->read(buffer, bytes);
267}
268
269static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
270{
271    struct legacy_stream_in *in =
272        reinterpret_cast<struct legacy_stream_in *>(stream);
273    return in->legacy_in->getInputFramesLost();
274}
275
276static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
277{
278    const struct legacy_stream_in *in =
279        reinterpret_cast<const struct legacy_stream_in *>(stream);
280    return in->legacy_in->addAudioEffect(effect);
281}
282
283static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
284{
285    const struct legacy_stream_in *in =
286        reinterpret_cast<const struct legacy_stream_in *>(stream);
287    return in->legacy_in->removeAudioEffect(effect);
288}
289
290/** audio_hw_device implementation **/
291static inline struct legacy_audio_device * to_ladev(struct audio_hw_device *dev)
292{
293    return reinterpret_cast<struct legacy_audio_device *>(dev);
294}
295
296static inline const struct legacy_audio_device * to_cladev(const struct audio_hw_device *dev)
297{
298    return reinterpret_cast<const struct legacy_audio_device *>(dev);
299}
300
301static uint32_t adev_get_supported_devices(const struct audio_hw_device *dev)
302{
303    /* XXX: The old AudioHardwareInterface interface is not smart enough to
304     * tell us this, so we'll lie and basically tell AF that we support the
305     * below input/output devices and cross our fingers. To do things properly,
306     * audio hardware interfaces that need advanced features (like this) should
307     * convert to the new HAL interface and not use this wrapper. */
308
309    return (/* OUT */
310            AUDIO_DEVICE_OUT_EARPIECE |
311            AUDIO_DEVICE_OUT_SPEAKER |
312            AUDIO_DEVICE_OUT_WIRED_HEADSET |
313            AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
314            AUDIO_DEVICE_OUT_AUX_DIGITAL |
315            AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET |
316            AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET |
317            AUDIO_DEVICE_OUT_ALL_SCO |
318            AUDIO_DEVICE_OUT_DEFAULT |
319            /* IN */
320            AUDIO_DEVICE_IN_COMMUNICATION |
321            AUDIO_DEVICE_IN_AMBIENT |
322            AUDIO_DEVICE_IN_BUILTIN_MIC |
323            AUDIO_DEVICE_IN_WIRED_HEADSET |
324            AUDIO_DEVICE_IN_AUX_DIGITAL |
325            AUDIO_DEVICE_IN_BACK_MIC |
326            AUDIO_DEVICE_IN_ALL_SCO |
327            AUDIO_DEVICE_IN_DEFAULT);
328}
329
330static int adev_init_check(const struct audio_hw_device *dev)
331{
332    const struct legacy_audio_device *ladev = to_cladev(dev);
333
334    return ladev->hwif->initCheck();
335}
336
337static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
338{
339    struct legacy_audio_device *ladev = to_ladev(dev);
340    return ladev->hwif->setVoiceVolume(volume);
341}
342
343static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
344{
345    struct legacy_audio_device *ladev = to_ladev(dev);
346    return ladev->hwif->setMasterVolume(volume);
347}
348
349static int adev_set_mode(struct audio_hw_device *dev, int mode)
350{
351    struct legacy_audio_device *ladev = to_ladev(dev);
352    return ladev->hwif->setMode(mode);
353}
354
355static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
356{
357    struct legacy_audio_device *ladev = to_ladev(dev);
358    return ladev->hwif->setMicMute(state);
359}
360
361static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
362{
363    const struct legacy_audio_device *ladev = to_cladev(dev);
364    return ladev->hwif->getMicMute(state);
365}
366
367static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
368{
369    struct legacy_audio_device *ladev = to_ladev(dev);
370    return ladev->hwif->setParameters(String8(kvpairs));
371}
372
373static char * adev_get_parameters(const struct audio_hw_device *dev,
374                                  const char *keys)
375{
376    const struct legacy_audio_device *ladev = to_cladev(dev);
377    String8 s8;
378
379    s8 = ladev->hwif->getParameters(String8(keys));
380    return strdup(s8.string());
381}
382
383static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
384                                         uint32_t sample_rate, int format,
385                                         int channel_count)
386{
387    const struct legacy_audio_device *ladev = to_cladev(dev);
388    return ladev->hwif->getInputBufferSize(sample_rate, format, channel_count);
389}
390
391static int adev_open_output_stream(struct audio_hw_device *dev,
392                                   uint32_t devices,
393                                   int *format,
394                                   uint32_t *channels,
395                                   uint32_t *sample_rate,
396                                   struct audio_stream_out **stream_out)
397{
398    struct legacy_audio_device *ladev = to_ladev(dev);
399    status_t status;
400    struct legacy_stream_out *out;
401    int ret;
402
403    out = (struct legacy_stream_out *)calloc(1, sizeof(*out));
404    if (!out)
405        return -ENOMEM;
406
407    out->legacy_out = ladev->hwif->openOutputStream(devices, format, channels,
408                                                    sample_rate, &status);
409    if (!out->legacy_out) {
410        ret = status;
411        goto err_open;
412    }
413
414    out->stream.common.get_sample_rate = out_get_sample_rate;
415    out->stream.common.set_sample_rate = out_set_sample_rate;
416    out->stream.common.get_buffer_size = out_get_buffer_size;
417    out->stream.common.get_channels = out_get_channels;
418    out->stream.common.get_format = out_get_format;
419    out->stream.common.set_format = out_set_format;
420    out->stream.common.standby = out_standby;
421    out->stream.common.dump = out_dump;
422    out->stream.common.set_parameters = out_set_parameters;
423    out->stream.common.get_parameters = out_get_parameters;
424    out->stream.common.add_audio_effect = out_add_audio_effect;
425    out->stream.common.remove_audio_effect = out_remove_audio_effect;
426    out->stream.get_latency = out_get_latency;
427    out->stream.set_volume = out_set_volume;
428    out->stream.write = out_write;
429    out->stream.get_render_position = out_get_render_position;
430
431    *stream_out = &out->stream;
432    return 0;
433
434err_open:
435    free(out);
436    *stream_out = NULL;
437    return ret;
438}
439
440static void adev_close_output_stream(struct audio_hw_device *dev,
441                                     struct audio_stream_out* stream)
442{
443    struct legacy_audio_device *ladev = to_ladev(dev);
444    struct legacy_stream_out *out = reinterpret_cast<struct legacy_stream_out *>(stream);
445
446    ladev->hwif->closeOutputStream(out->legacy_out);
447    free(out);
448}
449
450/** This method creates and opens the audio hardware input stream */
451static int adev_open_input_stream(struct audio_hw_device *dev,
452                                  uint32_t devices, int *format,
453                                  uint32_t *channels, uint32_t *sample_rate,
454                                  audio_in_acoustics_t acoustics,
455                                  struct audio_stream_in **stream_in)
456{
457    struct legacy_audio_device *ladev = to_ladev(dev);
458    status_t status;
459    struct legacy_stream_in *in;
460    int ret;
461
462    in = (struct legacy_stream_in *)calloc(1, sizeof(*in));
463    if (!in)
464        return -ENOMEM;
465
466    in->legacy_in = ladev->hwif->openInputStream(devices, format, channels,
467                                    sample_rate, &status,
468                                    (AudioSystem::audio_in_acoustics)acoustics);
469    if (!in->legacy_in) {
470        ret = status;
471        goto err_open;
472    }
473
474    in->stream.common.get_sample_rate = in_get_sample_rate;
475    in->stream.common.set_sample_rate = in_set_sample_rate;
476    in->stream.common.get_buffer_size = in_get_buffer_size;
477    in->stream.common.get_channels = in_get_channels;
478    in->stream.common.get_format = in_get_format;
479    in->stream.common.set_format = in_set_format;
480    in->stream.common.standby = in_standby;
481    in->stream.common.dump = in_dump;
482    in->stream.common.set_parameters = in_set_parameters;
483    in->stream.common.get_parameters = in_get_parameters;
484    in->stream.common.add_audio_effect = in_add_audio_effect;
485    in->stream.common.remove_audio_effect = in_remove_audio_effect;
486    in->stream.set_gain = in_set_gain;
487    in->stream.read = in_read;
488    in->stream.get_input_frames_lost = in_get_input_frames_lost;
489
490    *stream_in = &in->stream;
491    return 0;
492
493err_open:
494    free(in);
495    *stream_in = NULL;
496    return ret;
497}
498
499static void adev_close_input_stream(struct audio_hw_device *dev,
500                               struct audio_stream_in *stream)
501{
502    struct legacy_audio_device *ladev = to_ladev(dev);
503    struct legacy_stream_in *in =
504        reinterpret_cast<struct legacy_stream_in *>(stream);
505
506    ladev->hwif->closeInputStream(in->legacy_in);
507    free(in);
508}
509
510static int adev_dump(const struct audio_hw_device *dev, int fd)
511{
512    const struct legacy_audio_device *ladev = to_cladev(dev);
513    Vector<String16> args;
514
515    return ladev->hwif->dumpState(fd, args);
516}
517
518static int legacy_adev_close(hw_device_t* device)
519{
520    struct audio_hw_device *hwdev =
521                        reinterpret_cast<struct audio_hw_device *>(device);
522    struct legacy_audio_device *ladev = to_ladev(hwdev);
523
524    if (!ladev)
525        return 0;
526
527    if (ladev->hwif)
528        delete ladev->hwif;
529
530    free(ladev);
531    return 0;
532}
533
534static int legacy_adev_open(const hw_module_t* module, const char* name,
535                            hw_device_t** device)
536{
537    struct legacy_audio_device *ladev;
538    int ret;
539
540    if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
541        return -EINVAL;
542
543    ladev = (struct legacy_audio_device *)calloc(1, sizeof(*ladev));
544    if (!ladev)
545        return -ENOMEM;
546
547    ladev->device.common.tag = HARDWARE_DEVICE_TAG;
548    ladev->device.common.version = 0;
549    ladev->device.common.module = const_cast<hw_module_t*>(module);
550    ladev->device.common.close = legacy_adev_close;
551
552    ladev->device.get_supported_devices = adev_get_supported_devices;
553    ladev->device.init_check = adev_init_check;
554    ladev->device.set_voice_volume = adev_set_voice_volume;
555    ladev->device.set_master_volume = adev_set_master_volume;
556    ladev->device.set_mode = adev_set_mode;
557    ladev->device.set_mic_mute = adev_set_mic_mute;
558    ladev->device.get_mic_mute = adev_get_mic_mute;
559    ladev->device.set_parameters = adev_set_parameters;
560    ladev->device.get_parameters = adev_get_parameters;
561    ladev->device.get_input_buffer_size = adev_get_input_buffer_size;
562    ladev->device.open_output_stream = adev_open_output_stream;
563    ladev->device.close_output_stream = adev_close_output_stream;
564    ladev->device.open_input_stream = adev_open_input_stream;
565    ladev->device.close_input_stream = adev_close_input_stream;
566    ladev->device.dump = adev_dump;
567
568    ladev->hwif = createAudioHardware();
569    if (!ladev->hwif) {
570        ret = -EIO;
571        goto err_create_audio_hw;
572    }
573
574    *device = &ladev->device.common;
575
576    return 0;
577
578err_create_audio_hw:
579    free(ladev);
580    return ret;
581}
582
583static struct hw_module_methods_t legacy_audio_module_methods = {
584        open: legacy_adev_open
585};
586
587struct legacy_audio_module HAL_MODULE_INFO_SYM = {
588    module: {
589        common: {
590            tag: HARDWARE_MODULE_TAG,
591            version_major: 1,
592            version_minor: 0,
593            id: AUDIO_HARDWARE_MODULE_ID,
594            name: "LEGACY Audio HW HAL",
595            author: "The Android Open Source Project",
596            methods: &legacy_audio_module_methods,
597            dso : NULL,
598            reserved : {0},
599        },
600    },
601};
602
603}; // extern "C"
604
605}; // namespace android_audio_legacy
606