• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 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 "audio_hw_generic"
18 /*#define LOG_NDEBUG 0*/
19 
20 #include <errno.h>
21 #include <pthread.h>
22 #include <stdint.h>
23 #include <stdlib.h>
24 #include <sys/time.h>
25 #include <fcntl.h>
26 
27 #include <cutils/log.h>
28 #include <cutils/str_parms.h>
29 
30 #include <hardware/hardware.h>
31 #include <system/audio.h>
32 #include <hardware/audio.h>
33 
34 
35 #define AUDIO_DEVICE_NAME "/dev/eac"
36 #define OUT_BUFFER_SIZE 4096
37 #define OUT_LATENCY_MS 20
38 #define IN_SAMPLING_RATE 8000
39 #define IN_BUFFER_SIZE 320
40 
41 
42 struct generic_audio_device {
43     struct audio_hw_device device;
44     pthread_mutex_t lock;
45     struct audio_stream_out *output;
46     struct audio_stream_in *input;
47     int fd;
48     bool mic_mute;
49 };
50 
51 
52 struct generic_stream_out {
53     struct audio_stream_out stream;
54     struct generic_audio_device *dev;
55     audio_devices_t device;
56     uint32_t sample_rate;
57 };
58 
59 struct generic_stream_in {
60     struct audio_stream_in stream;
61     struct generic_audio_device *dev;
62     audio_devices_t device;
63 };
64 
65 
out_get_sample_rate(const struct audio_stream * stream)66 static uint32_t out_get_sample_rate(const struct audio_stream *stream)
67 {
68     struct generic_stream_out *out = (struct generic_stream_out *)stream;
69     return out->sample_rate;
70 }
71 
out_set_sample_rate(struct audio_stream * stream,uint32_t rate)72 static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
73 {
74     return -ENOSYS;
75 }
76 
out_get_buffer_size(const struct audio_stream * stream)77 static size_t out_get_buffer_size(const struct audio_stream *stream)
78 {
79     return OUT_BUFFER_SIZE;
80 }
81 
out_get_channels(const struct audio_stream * stream)82 static audio_channel_mask_t out_get_channels(const struct audio_stream *stream)
83 {
84     return AUDIO_CHANNEL_OUT_STEREO;
85 }
86 
out_get_format(const struct audio_stream * stream)87 static audio_format_t out_get_format(const struct audio_stream *stream)
88 {
89     return AUDIO_FORMAT_PCM_16_BIT;
90 }
91 
out_set_format(struct audio_stream * stream,audio_format_t format)92 static int out_set_format(struct audio_stream *stream, audio_format_t format)
93 {
94     return -ENOSYS;
95 }
96 
out_standby(struct audio_stream * stream)97 static int out_standby(struct audio_stream *stream)
98 {
99     // out_standby is a no op
100     return 0;
101 }
102 
out_dump(const struct audio_stream * stream,int fd)103 static int out_dump(const struct audio_stream *stream, int fd)
104 {
105     struct generic_stream_out *out = (struct generic_stream_out *)stream;
106 
107     dprintf(fd, "\tout_dump:\n"
108                 "\t\tsample rate: %u\n"
109                 "\t\tbuffer size: %u\n"
110                 "\t\tchannel mask: %08x\n"
111                 "\t\tformat: %d\n"
112                 "\t\tdevice: %08x\n"
113                 "\t\taudio dev: %p\n\n",
114                 out_get_sample_rate(stream),
115                 out_get_buffer_size(stream),
116                 out_get_channels(stream),
117                 out_get_format(stream),
118                 out->device,
119                 out->dev);
120 
121     return 0;
122 }
123 
out_set_parameters(struct audio_stream * stream,const char * kvpairs)124 static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
125 {
126     struct generic_stream_out *out = (struct generic_stream_out *)stream;
127     struct str_parms *parms;
128     char value[32];
129     int ret;
130     long val;
131     char *end;
132 
133     parms = str_parms_create_str(kvpairs);
134 
135     ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING,
136                             value, sizeof(value));
137     if (ret >= 0) {
138         errno = 0;
139         val = strtol(value, &end, 10);
140         if (errno == 0 && (end != NULL) && (*end == '\0') && ((int)val == val)) {
141             out->device = (int)val;
142         } else {
143             ret = -EINVAL;
144         }
145     }
146 
147     str_parms_destroy(parms);
148     return ret;
149 }
150 
out_get_parameters(const struct audio_stream * stream,const char * keys)151 static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
152 {
153     struct generic_stream_out *out = (struct generic_stream_out *)stream;
154     struct str_parms *query = str_parms_create_str(keys);
155     char *str;
156     char value[256];
157     struct str_parms *reply = str_parms_create();
158     int ret;
159 
160     ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
161     if (ret >= 0) {
162         str_parms_add_int(reply, AUDIO_PARAMETER_STREAM_ROUTING, out->device);
163         str = strdup(str_parms_to_str(reply));
164     } else {
165         str = strdup(keys);
166     }
167 
168     str_parms_destroy(query);
169     str_parms_destroy(reply);
170     return str;
171 }
172 
out_get_latency(const struct audio_stream_out * stream)173 static uint32_t out_get_latency(const struct audio_stream_out *stream)
174 {
175     return OUT_LATENCY_MS;
176 }
177 
out_set_volume(struct audio_stream_out * stream,float left,float right)178 static int out_set_volume(struct audio_stream_out *stream, float left,
179                           float right)
180 {
181     return -ENOSYS;
182 }
183 
out_write(struct audio_stream_out * stream,const void * buffer,size_t bytes)184 static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
185                          size_t bytes)
186 {
187     struct generic_stream_out *out = (struct generic_stream_out *)stream;
188     struct generic_audio_device *adev = out->dev;
189 
190     pthread_mutex_lock(&adev->lock);
191     if (adev->fd >= 0)
192         bytes = write(adev->fd, buffer, bytes);
193     pthread_mutex_unlock(&adev->lock);
194 
195     return bytes;
196 }
197 
out_get_render_position(const struct audio_stream_out * stream,uint32_t * dsp_frames)198 static int out_get_render_position(const struct audio_stream_out *stream,
199                                    uint32_t *dsp_frames)
200 {
201     return -ENOSYS;
202 }
203 
out_add_audio_effect(const struct audio_stream * stream,effect_handle_t effect)204 static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
205 {
206     // out_add_audio_effect is a no op
207     return 0;
208 }
209 
out_remove_audio_effect(const struct audio_stream * stream,effect_handle_t effect)210 static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
211 {
212     // out_remove_audio_effect is a no op
213     return 0;
214 }
215 
out_get_next_write_timestamp(const struct audio_stream_out * stream,int64_t * timestamp)216 static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
217                                         int64_t *timestamp)
218 {
219     return -ENOSYS;
220 }
221 
222 /** audio_stream_in implementation **/
in_get_sample_rate(const struct audio_stream * stream)223 static uint32_t in_get_sample_rate(const struct audio_stream *stream)
224 {
225     return IN_SAMPLING_RATE;
226 }
227 
in_set_sample_rate(struct audio_stream * stream,uint32_t rate)228 static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
229 {
230     return -ENOSYS;
231 }
232 
in_get_buffer_size(const struct audio_stream * stream)233 static size_t in_get_buffer_size(const struct audio_stream *stream)
234 {
235     return IN_BUFFER_SIZE;
236 }
237 
in_get_channels(const struct audio_stream * stream)238 static audio_channel_mask_t in_get_channels(const struct audio_stream *stream)
239 {
240     return AUDIO_CHANNEL_IN_MONO;
241 }
242 
in_get_format(const struct audio_stream * stream)243 static audio_format_t in_get_format(const struct audio_stream *stream)
244 {
245     return AUDIO_FORMAT_PCM_16_BIT;
246 }
247 
in_set_format(struct audio_stream * stream,audio_format_t format)248 static int in_set_format(struct audio_stream *stream, audio_format_t format)
249 {
250     return -ENOSYS;
251 }
252 
in_standby(struct audio_stream * stream)253 static int in_standby(struct audio_stream *stream)
254 {
255     // in_standby is a no op
256     return 0;
257 }
258 
in_dump(const struct audio_stream * stream,int fd)259 static int in_dump(const struct audio_stream *stream, int fd)
260 {
261     struct generic_stream_in *in = (struct generic_stream_in *)stream;
262 
263     dprintf(fd, "\tin_dump:\n"
264                 "\t\tsample rate: %u\n"
265                 "\t\tbuffer size: %u\n"
266                 "\t\tchannel mask: %08x\n"
267                 "\t\tformat: %d\n"
268                 "\t\tdevice: %08x\n"
269                 "\t\taudio dev: %p\n\n",
270                 in_get_sample_rate(stream),
271                 in_get_buffer_size(stream),
272                 in_get_channels(stream),
273                 in_get_format(stream),
274                 in->device,
275                 in->dev);
276 
277     return 0;
278 }
279 
in_set_parameters(struct audio_stream * stream,const char * kvpairs)280 static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
281 {
282     struct generic_stream_in *in = (struct generic_stream_in *)stream;
283     struct str_parms *parms;
284     char value[32];
285     int ret;
286     long val;
287     char *end;
288 
289     parms = str_parms_create_str(kvpairs);
290 
291     ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING,
292                             value, sizeof(value));
293     if (ret >= 0) {
294         errno = 0;
295         val = strtol(value, &end, 10);
296         if ((errno == 0) && (end != NULL) && (*end == '\0') && ((int)val == val)) {
297             in->device = (int)val;
298         } else {
299             ret = -EINVAL;
300         }
301     }
302 
303     str_parms_destroy(parms);
304     return ret;
305 }
306 
in_get_parameters(const struct audio_stream * stream,const char * keys)307 static char * in_get_parameters(const struct audio_stream *stream,
308                                 const char *keys)
309 {
310     struct generic_stream_in *in = (struct generic_stream_in *)stream;
311     struct str_parms *query = str_parms_create_str(keys);
312     char *str;
313     char value[256];
314     struct str_parms *reply = str_parms_create();
315     int ret;
316 
317     ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
318     if (ret >= 0) {
319         str_parms_add_int(reply, AUDIO_PARAMETER_STREAM_ROUTING, in->device);
320         str = strdup(str_parms_to_str(reply));
321     } else {
322         str = strdup(keys);
323     }
324 
325     str_parms_destroy(query);
326     str_parms_destroy(reply);
327     return str;
328 }
329 
in_set_gain(struct audio_stream_in * stream,float gain)330 static int in_set_gain(struct audio_stream_in *stream, float gain)
331 {
332     // in_set_gain is a no op
333     return 0;
334 }
335 
in_read(struct audio_stream_in * stream,void * buffer,size_t bytes)336 static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
337                        size_t bytes)
338 {
339     struct generic_stream_in *in = (struct generic_stream_in *)stream;
340     struct generic_audio_device *adev = in->dev;
341 
342     pthread_mutex_lock(&adev->lock);
343     if (adev->fd >= 0)
344         bytes = read(adev->fd, buffer, bytes);
345     if (adev->mic_mute && (bytes > 0)) {
346         memset(buffer, 0, bytes);
347     }
348     pthread_mutex_unlock(&adev->lock);
349 
350     return bytes;
351 }
352 
in_get_input_frames_lost(struct audio_stream_in * stream)353 static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
354 {
355     return 0;
356 }
357 
in_add_audio_effect(const struct audio_stream * stream,effect_handle_t effect)358 static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
359 {
360     // in_add_audio_effect is a no op
361     return 0;
362 }
363 
in_remove_audio_effect(const struct audio_stream * stream,effect_handle_t effect)364 static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
365 {
366     // in_add_audio_effect is a no op
367     return 0;
368 }
369 
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,const char * address __unused)370 static int adev_open_output_stream(struct audio_hw_device *dev,
371                                    audio_io_handle_t handle,
372                                    audio_devices_t devices,
373                                    audio_output_flags_t flags,
374                                    struct audio_config *config,
375                                    struct audio_stream_out **stream_out,
376                                    const char *address __unused)
377 {
378     struct generic_audio_device *adev = (struct generic_audio_device *)dev;
379     struct generic_stream_out *out;
380     static const uint32_t sample_rates [] = { 44100, 48000 };
381     static const int sample_rates_count = sizeof(sample_rates)/sizeof(sample_rates[0]);
382     int ret = 0;
383 
384     pthread_mutex_lock(&adev->lock);
385     if (adev->output != NULL) {
386         ret = -ENOSYS;
387         goto error;
388     }
389 
390     if ((config->format != AUDIO_FORMAT_PCM_16_BIT) ||
391         (config->channel_mask != AUDIO_CHANNEL_OUT_STEREO) ) {
392         ALOGE("Error opening output stream, format %d, channel_mask %04x",
393               config->format, config->channel_mask);
394         config->format = AUDIO_FORMAT_PCM_16_BIT;
395         config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
396         ret = -EINVAL;
397     }
398 
399     for (int idx = 0; idx < sample_rates_count; idx++) {
400         if (config->sample_rate < sample_rates[idx]) {
401             config->sample_rate = sample_rates[idx];
402             ALOGE("Error opening output stream, sample_rate %u", config->sample_rate);
403             ret = -EINVAL;
404             break;
405         } else if (config->sample_rate == sample_rates[idx]) {
406             break;
407         } else if (idx == sample_rates_count-1) {
408             // Cap it to the highest rate we support
409             config->sample_rate = sample_rates[idx];
410             ALOGE("Error opening output stream, sample_rate %u", config->sample_rate);
411             ret = -EINVAL;
412         }
413     }
414 
415     if (ret != 0) goto error;
416 
417     out = (struct generic_stream_out *)calloc(1, sizeof(struct generic_stream_out));
418 
419     out->stream.common.get_sample_rate = out_get_sample_rate;
420     out->stream.common.set_sample_rate = out_set_sample_rate;
421     out->stream.common.get_buffer_size = out_get_buffer_size;
422     out->stream.common.get_channels = out_get_channels;
423     out->stream.common.get_format = out_get_format;
424     out->stream.common.set_format = out_set_format;
425     out->stream.common.standby = out_standby;
426     out->stream.common.dump = out_dump;
427     out->stream.common.set_parameters = out_set_parameters;
428     out->stream.common.get_parameters = out_get_parameters;
429     out->stream.common.add_audio_effect = out_add_audio_effect;
430     out->stream.common.remove_audio_effect = out_remove_audio_effect;
431     out->stream.get_latency = out_get_latency;
432     out->stream.set_volume = out_set_volume;
433     out->stream.write = out_write;
434     out->stream.get_render_position = out_get_render_position;
435     out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
436     out->sample_rate = config->sample_rate;
437 
438     out->dev = adev;
439     out->device = devices;
440     adev->output = (struct audio_stream_out *)out;
441     *stream_out = &out->stream;
442 
443 error:
444     pthread_mutex_unlock(&adev->lock);
445 
446     return ret;
447 }
448 
adev_close_output_stream(struct audio_hw_device * dev,struct audio_stream_out * stream)449 static void adev_close_output_stream(struct audio_hw_device *dev,
450                                      struct audio_stream_out *stream)
451 {
452     struct generic_audio_device *adev = (struct generic_audio_device *)dev;
453 
454     pthread_mutex_lock(&adev->lock);
455     if (stream == adev->output) {
456         free(stream);
457         adev->output = NULL;
458     }
459     pthread_mutex_unlock(&adev->lock);
460 }
461 
adev_set_parameters(struct audio_hw_device * dev,const char * kvpairs)462 static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
463 {
464     return 0;
465 }
466 
adev_get_parameters(const struct audio_hw_device * dev,const char * keys)467 static char * adev_get_parameters(const struct audio_hw_device *dev,
468                                   const char *keys)
469 {
470     return strdup("");
471 }
472 
adev_init_check(const struct audio_hw_device * dev)473 static int adev_init_check(const struct audio_hw_device *dev)
474 {
475     struct generic_audio_device *adev = (struct generic_audio_device *)dev;
476 
477     if (adev->fd >= 0)
478         return 0;
479 
480     return -ENODEV;
481 }
482 
adev_set_voice_volume(struct audio_hw_device * dev,float volume)483 static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
484 {
485     // adev_set_voice_volume is a no op (simulates phones)
486     return 0;
487 }
488 
adev_set_master_volume(struct audio_hw_device * dev,float volume)489 static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
490 {
491     return -ENOSYS;
492 }
493 
adev_get_master_volume(struct audio_hw_device * dev,float * volume)494 static int adev_get_master_volume(struct audio_hw_device *dev, float *volume)
495 {
496     return -ENOSYS;
497 }
498 
adev_set_master_mute(struct audio_hw_device * dev,bool muted)499 static int adev_set_master_mute(struct audio_hw_device *dev, bool muted)
500 {
501     return -ENOSYS;
502 }
503 
adev_get_master_mute(struct audio_hw_device * dev,bool * muted)504 static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted)
505 {
506     return -ENOSYS;
507 }
508 
adev_set_mode(struct audio_hw_device * dev,audio_mode_t mode)509 static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
510 {
511     // adev_set_mode is a no op (simulates phones)
512     return 0;
513 }
514 
adev_set_mic_mute(struct audio_hw_device * dev,bool state)515 static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
516 {
517     struct generic_audio_device *adev = (struct generic_audio_device *)dev;
518 
519     pthread_mutex_lock(&adev->lock);
520     adev->mic_mute = state;
521     pthread_mutex_unlock(&adev->lock);
522     return 0;
523 }
524 
adev_get_mic_mute(const struct audio_hw_device * dev,bool * state)525 static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
526 {
527     struct generic_audio_device *adev = (struct generic_audio_device *)dev;
528 
529     pthread_mutex_lock(&adev->lock);
530     *state = adev->mic_mute;
531     pthread_mutex_unlock(&adev->lock);
532 
533     return 0;
534 }
535 
adev_get_input_buffer_size(const struct audio_hw_device * dev,const struct audio_config * config)536 static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
537                                          const struct audio_config *config)
538 {
539     return IN_BUFFER_SIZE;
540 }
541 
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,audio_input_flags_t flags __unused,const char * address __unused,audio_source_t source __unused)542 static int adev_open_input_stream(struct audio_hw_device *dev,
543                                   audio_io_handle_t handle,
544                                   audio_devices_t devices,
545                                   struct audio_config *config,
546                                   struct audio_stream_in **stream_in,
547                                   audio_input_flags_t flags __unused,
548                                   const char *address __unused,
549                                   audio_source_t source __unused)
550 {
551     struct generic_audio_device *adev = (struct generic_audio_device *)dev;
552     struct generic_stream_in *in;
553     int ret = 0;
554 
555     pthread_mutex_lock(&adev->lock);
556     if (adev->input != NULL) {
557         ret = -ENOSYS;
558         goto error;
559     }
560 
561     if ((config->format != AUDIO_FORMAT_PCM_16_BIT) ||
562         (config->channel_mask != AUDIO_CHANNEL_IN_MONO) ||
563         (config->sample_rate != IN_SAMPLING_RATE)) {
564         ALOGE("Error opening input stream format %d, channel_mask %04x, sample_rate %u",
565               config->format, config->channel_mask, config->sample_rate);
566         config->format = AUDIO_FORMAT_PCM_16_BIT;
567         config->channel_mask = AUDIO_CHANNEL_IN_MONO;
568         config->sample_rate = IN_SAMPLING_RATE;
569         ret = -EINVAL;
570         goto error;
571     }
572 
573     in = (struct generic_stream_in *)calloc(1, sizeof(struct generic_stream_in));
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     in->dev = adev;
592     in->device = devices;
593     adev->input = (struct audio_stream_in *)in;
594     *stream_in = &in->stream;
595 
596 error:
597     pthread_mutex_unlock(&adev->lock);
598 
599     return ret;
600 }
601 
adev_close_input_stream(struct audio_hw_device * dev,struct audio_stream_in * stream)602 static void adev_close_input_stream(struct audio_hw_device *dev,
603                                    struct audio_stream_in *stream)
604 {
605     struct generic_audio_device *adev = (struct generic_audio_device *)dev;
606 
607     pthread_mutex_lock(&adev->lock);
608     if (stream == adev->input) {
609         free(stream);
610         adev->input = NULL;
611     }
612     pthread_mutex_unlock(&adev->lock);
613 }
614 
adev_dump(const audio_hw_device_t * dev,int fd)615 static int adev_dump(const audio_hw_device_t *dev, int fd)
616 {
617     struct generic_audio_device *adev = (struct generic_audio_device *)dev;
618 
619     const size_t SIZE = 256;
620     char buffer[SIZE];
621 
622     dprintf(fd, "\nadev_dump:\n"
623                 "\tfd: %d\n"
624                 "\tmic_mute: %s\n"
625                 "\toutput: %p\n"
626                 "\tinput: %p\n\n",
627                 adev->fd,
628                 adev->mic_mute ? "true": "false",
629                 adev->output,
630                 adev->input);
631 
632     if (adev->output != NULL)
633         out_dump((const struct audio_stream *)adev->output, fd);
634     if (adev->input != NULL)
635         in_dump((const struct audio_stream *)adev->input, fd);
636 
637     return 0;
638 }
639 
adev_close(hw_device_t * dev)640 static int adev_close(hw_device_t *dev)
641 {
642     struct generic_audio_device *adev = (struct generic_audio_device *)dev;
643 
644     adev_close_output_stream((struct audio_hw_device *)dev, adev->output);
645     adev_close_input_stream((struct audio_hw_device *)dev, adev->input);
646 
647     if (adev->fd >= 0)
648         close(adev->fd);
649 
650     free(dev);
651     return 0;
652 }
653 
adev_open(const hw_module_t * module,const char * name,hw_device_t ** device)654 static int adev_open(const hw_module_t* module, const char* name,
655                      hw_device_t** device)
656 {
657     struct generic_audio_device *adev;
658     int fd;
659 
660     if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
661         return -EINVAL;
662 
663     fd = open(AUDIO_DEVICE_NAME, O_RDWR);
664     if (fd < 0)
665         return -ENOSYS;
666 
667     adev = calloc(1, sizeof(struct generic_audio_device));
668 
669     adev->fd = fd;
670 
671     adev->device.common.tag = HARDWARE_DEVICE_TAG;
672     adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
673     adev->device.common.module = (struct hw_module_t *) module;
674     adev->device.common.close = adev_close;
675 
676     adev->device.init_check = adev_init_check;
677     adev->device.set_voice_volume = adev_set_voice_volume;
678     adev->device.set_master_volume = adev_set_master_volume;
679     adev->device.get_master_volume = adev_get_master_volume;
680     adev->device.set_master_mute = adev_set_master_mute;
681     adev->device.get_master_mute = adev_get_master_mute;
682     adev->device.set_mode = adev_set_mode;
683     adev->device.set_mic_mute = adev_set_mic_mute;
684     adev->device.get_mic_mute = adev_get_mic_mute;
685     adev->device.set_parameters = adev_set_parameters;
686     adev->device.get_parameters = adev_get_parameters;
687     adev->device.get_input_buffer_size = adev_get_input_buffer_size;
688     adev->device.open_output_stream = adev_open_output_stream;
689     adev->device.close_output_stream = adev_close_output_stream;
690     adev->device.open_input_stream = adev_open_input_stream;
691     adev->device.close_input_stream = adev_close_input_stream;
692     adev->device.dump = adev_dump;
693 
694     *device = &adev->device.common;
695 
696     return 0;
697 }
698 
699 static struct hw_module_methods_t hal_module_methods = {
700     .open = adev_open,
701 };
702 
703 struct audio_module HAL_MODULE_INFO_SYM = {
704     .common = {
705         .tag = HARDWARE_MODULE_TAG,
706         .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
707         .hal_api_version = HARDWARE_HAL_API_VERSION,
708         .id = AUDIO_HARDWARE_MODULE_ID,
709         .name = "Generic audio HW HAL",
710         .author = "The Android Open Source Project",
711         .methods = &hal_module_methods,
712     },
713 };
714