blob: 65ebbe4cba4805bfe4fb27730e0e2dc462c6eb29
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 "usb_audio_hw" |
18 | //#define LOG_NDEBUG 0 |
19 | |
20 | #include <errno.h> |
21 | #include <pthread.h> |
22 | #include <stdint.h> |
23 | #include <sys/time.h> |
24 | #include <stdlib.h> |
25 | #include <sys/stat.h> |
26 | #include <fcntl.h> |
27 | |
28 | #include <cutils/log.h> |
29 | #include <cutils/str_parms.h> |
30 | #include <cutils/properties.h> |
31 | |
32 | #include <hardware/hardware.h> |
33 | #include <system/audio.h> |
34 | #include <hardware/audio.h> |
35 | |
36 | #include <tinyalsa/asoundlib.h> |
37 | #include <audio_utils/resampler.h> |
38 | |
39 | #include "audio_resampler.h" |
40 | |
41 | #define DEFAULT_OUT_SAMPLING_RATE 44100 |
42 | #define RESAMPLER_BUFFER_SIZE 4096 |
43 | #define DEFAULT_PERIOD_SIZE 1024 |
44 | #define PERIOD_COUNT 4 |
45 | #define BUFFSIZE 100000 |
46 | |
47 | struct pcm_config pcm_out_config = { |
48 | .channels = 2, |
49 | .rate = DEFAULT_OUT_SAMPLING_RATE, |
50 | .period_size = DEFAULT_PERIOD_SIZE, |
51 | .period_count = PERIOD_COUNT, |
52 | .format = PCM_FORMAT_S16_LE, |
53 | }; |
54 | |
55 | struct pcm_config pcm_in_config = { |
56 | .channels = 1, |
57 | .rate = DEFAULT_OUT_SAMPLING_RATE, |
58 | .period_size = DEFAULT_PERIOD_SIZE, |
59 | .period_count = PERIOD_COUNT, |
60 | .format = PCM_FORMAT_S16_LE, |
61 | }; |
62 | |
63 | struct aml_audio_device { |
64 | struct audio_hw_device hw_device; |
65 | |
66 | pthread_mutex_t lock; /* see note below on mutex acquisition order */ |
67 | int card; |
68 | int card_device; |
69 | audio_devices_t in_device; |
70 | audio_devices_t out_device; |
71 | struct aml_stream_in *active_input; |
72 | struct aml_stream_out *active_output; |
73 | |
74 | bool mic_mute; |
75 | bool standby; |
76 | }; |
77 | |
78 | struct aml_stream_out { |
79 | struct audio_stream_out stream; |
80 | pthread_mutex_t lock; /* see note below on mutex acquisition order */ |
81 | struct pcm_config out_config; |
82 | struct pcm *out_pcm; |
83 | struct resample_para resampler; |
84 | void *buffer; |
85 | bool standby; |
86 | |
87 | struct aml_audio_device *dev; |
88 | }; |
89 | |
90 | struct aml_stream_in { |
91 | struct audio_stream_in stream; |
92 | pthread_mutex_t lock; /* see note below on mutex acquisition order */ |
93 | struct pcm_config in_config; |
94 | struct pcm *in_pcm; |
95 | struct resampler_itfe *resampler; |
96 | struct resampler_buffer_provider buf_provider; |
97 | int16_t *buffer; |
98 | size_t frames_in; |
99 | unsigned int requested_rate; |
100 | bool standby; |
101 | int read_status; |
102 | |
103 | struct aml_audio_device *dev; |
104 | }; |
105 | static int get_usb_card(struct aml_audio_device *dev); |
106 | |
107 | int getnumOfRates(char *ratesStr){ |
108 | int i, size = 0; |
109 | char *nextSRString, *temp_ptr; |
110 | nextSRString = strtok_r(ratesStr, " ,", &temp_ptr); |
111 | if (nextSRString == NULL) { |
112 | ALOGE("ERROR: getnumOfRates: could not find rates string"); |
113 | return 0; |
114 | } |
115 | for (i = 1; nextSRString != NULL; i++) { |
116 | size ++; |
117 | nextSRString = strtok_r(NULL, " ,.-", &temp_ptr); |
118 | } |
119 | return size; |
120 | } |
121 | |
122 | static int get_usb_cap(char *type, uint *channels, uint *sampleRate, int card) |
123 | { |
124 | ALOGV("getCap for %s",type); |
125 | long unsigned fileSize; |
126 | FILE *fp; |
127 | char path[32]; |
128 | char *buffer; |
129 | int err = 1; |
130 | int size = 0; |
131 | int needRsmp = 1; |
132 | int fd, i, lchannelsPlayback; |
133 | char *read_buf, *str_start, *channel_start, *ratesStr, *ratesStrForVal, |
134 | *ratesStrStart, *chString, *nextSRStr, *test, *nextSRString, *temp_ptr; |
135 | struct stat st; |
136 | memset(&st, 0x0, sizeof(struct stat)); |
137 | err = sprintf(path,"/proc/asound/card%d/stream0", card); |
138 | ALOGD("path = %s",path); |
139 | |
140 | fd = open(path, O_RDONLY); |
141 | if (fd <0) { |
142 | ALOGE("ERROR: failed to open config file %s error: %d\n", path, errno); |
143 | close(fd); |
144 | return -EINVAL; |
145 | } |
146 | |
147 | if (fstat(fd, &st) < 0) { |
148 | ALOGE("ERROR: failed to stat %s error %d\n", path, errno); |
149 | close(fd); |
150 | return -EINVAL; |
151 | } |
152 | |
153 | read_buf = (char *)malloc(BUFFSIZE); |
154 | memset(read_buf, 0x0, BUFFSIZE); |
155 | err = read(fd, read_buf, BUFFSIZE); |
156 | str_start = strstr(read_buf, type); |
157 | if (str_start == NULL) { |
158 | ALOGE("ERROR:%s section not found in usb config file", type); |
159 | close(fd); |
160 | free(read_buf); |
161 | return -EINVAL; |
162 | } |
163 | |
164 | channel_start = strstr(str_start, "Channels:"); |
165 | if (channel_start == NULL) { |
166 | ALOGE("ERROR: Could not find Channels information"); |
167 | close(fd); |
168 | free(read_buf); |
169 | return -EINVAL; |
170 | } |
171 | channel_start = strstr(channel_start, " "); |
172 | if (channel_start == NULL) { |
173 | ALOGE("ERROR: Channel section not found in usb config file"); |
174 | close(fd); |
175 | free(read_buf); |
176 | return -EINVAL; |
177 | } |
178 | |
179 | lchannelsPlayback = atoi(channel_start); |
180 | if (lchannelsPlayback == 1) { |
181 | *channels = 1; |
182 | } else { |
183 | *channels = 2; |
184 | } |
185 | ratesStrStart = strstr(str_start, "Rates:"); |
186 | if (ratesStrStart == NULL) { |
187 | ALOGE("ERROR: Cant find rates information"); |
188 | close(fd); |
189 | free(read_buf); |
190 | return -EINVAL; |
191 | } |
192 | |
193 | ratesStrStart = strstr(ratesStrStart, " "); |
194 | if (ratesStrStart == NULL) { |
195 | ALOGE("ERROR: Channel section not found in usb config file"); |
196 | close(fd); |
197 | free(read_buf); |
198 | return -EINVAL; |
199 | } |
200 | |
201 | //copy to ratesStr, current line. |
202 | char *target = strchr(ratesStrStart, '\n'); |
203 | if (target == NULL) { |
204 | ALOGE("ERROR: end of line not found"); |
205 | close(fd); |
206 | free(read_buf); |
207 | return -EINVAL; |
208 | } |
209 | size = target - ratesStrStart; |
210 | ratesStr = (char *)malloc(size + 1) ; |
211 | ratesStrForVal = (char *)malloc(size + 1) ; |
212 | memcpy(ratesStr, ratesStrStart, size); |
213 | memcpy(ratesStrForVal, ratesStrStart, size); |
214 | ratesStr[size] = '\0'; |
215 | ratesStrForVal[size] = '\0'; |
216 | |
217 | size = getnumOfRates(ratesStr); |
218 | if (!size) { |
219 | ALOGE("ERROR: Could not get rate size, returning"); |
220 | close(fd); |
221 | free(ratesStrForVal); |
222 | free(ratesStr); |
223 | free(read_buf); |
224 | return -EINVAL; |
225 | } |
226 | |
227 | //populate playback rates array |
228 | uint ratesSupported[size]; |
229 | nextSRString = strtok_r(ratesStrForVal, " ,", &temp_ptr); |
230 | if (nextSRString == NULL) { |
231 | ALOGE("ERROR: Could not get first rate val"); |
232 | close(fd); |
233 | free(ratesStrForVal); |
234 | free(ratesStr); |
235 | free(read_buf); |
236 | return -EINVAL; |
237 | } |
238 | |
239 | ratesSupported[0] = atoi(nextSRString); |
240 | ALOGV("ratesSupported[0] for %s:: %d", type, ratesSupported[0]); |
241 | for (i = 1; i<size; i++) { |
242 | nextSRString = strtok_r(NULL, " ,.-", &temp_ptr); |
243 | ratesSupported[i] = atoi(nextSRString); |
244 | ALOGV("ratesSupported[%d] for %s:: %d", i, type, ratesSupported[i]); |
245 | } |
246 | |
247 | for (i = 0; i<size; i++) { |
248 | if((*sampleRate == ratesSupported[i]) && (ratesSupported[i] <= 48000)) { |
249 | needRsmp = 0; |
250 | ALOGV("**sampleRate supports**"); |
251 | } |
252 | } |
253 | if (needRsmp) { |
254 | *sampleRate = ratesSupported[size-1]; |
255 | ALOGE("sampleRate do not support!! Using Need resampler!!"); |
256 | } |
257 | ALOGD("sampleRate: %d", *sampleRate); |
258 | |
259 | close(fd); |
260 | free(ratesStrForVal); |
261 | free(ratesStr); |
262 | free(read_buf); |
263 | ratesStrForVal = NULL; |
264 | ratesStr = NULL; |
265 | read_buf = NULL; |
266 | return 0; |
267 | } |
268 | |
269 | /** |
270 | * NOTE: when multiple mutexes have to be acquired, always respect the |
271 | * following order: hw device > out stream |
272 | */ |
273 | |
274 | /* Helper functions */ |
275 | |
276 | /* must be called with hw device and output stream mutexes locked */ |
277 | static int start_output_stream(struct aml_stream_out *out) |
278 | { |
279 | ALOGD("%s", __func__); |
280 | struct aml_audio_device *adev = out->dev; |
281 | int i, err; |
282 | if ((adev->card < 0) || (adev->card_device < 0)) { |
283 | return -EINVAL; |
284 | } |
285 | if (adev->out_device & AUDIO_DEVICE_OUT_USB_DEVICE) { |
286 | err = get_usb_cap("Playback:", &out->out_config.channels, &out->out_config.rate, adev->card); |
287 | if (err) { |
288 | ALOGE("ERROR: Could not get playback capabilities from usb device"); |
289 | return -EINVAL; |
290 | } |
291 | } |
292 | out->buffer = NULL; |
293 | if (out->out_config.rate != pcm_out_config.rate) { |
294 | out->resampler.input_sr = pcm_out_config.rate; |
295 | out->resampler.output_sr = out->out_config.rate; |
296 | out->resampler.channels = out->out_config.channels; |
297 | resampler_init(&out->resampler); |
298 | int buffersize = DEFAULT_PERIOD_SIZE * out->out_config.rate / pcm_out_config.rate + 1; |
299 | out->buffer = malloc(buffersize*4); |
300 | ALOGE("out->buffer: %p, buffer_size = %d",out->buffer,buffersize); |
301 | if (!out->buffer) |
302 | return -ENOMEM; |
303 | } |
304 | |
305 | out->out_pcm = pcm_open(adev->card, adev->card_device, PCM_OUT, &out->out_config); |
306 | |
307 | if (!pcm_is_ready(out->out_pcm)) { |
308 | ALOGE("pcm_open() failed: %s", pcm_get_error(out->out_pcm)); |
309 | pcm_close(out->out_pcm); |
310 | adev->active_output = NULL; |
311 | return -ENOMEM; |
312 | } |
313 | return 0; |
314 | } |
315 | |
316 | /* API functions */ |
317 | |
318 | static uint32_t out_get_sample_rate(const struct audio_stream *stream) |
319 | { |
320 | return pcm_out_config.rate; |
321 | } |
322 | |
323 | static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate) |
324 | { |
325 | ALOGD("%s(%p, %d)", __FUNCTION__, stream, rate); |
326 | |
327 | return 0; |
328 | } |
329 | |
330 | static size_t out_get_buffer_size(const struct audio_stream *stream) |
331 | { |
332 | struct aml_stream_out *out = (struct aml_stream_out *)stream; |
333 | |
334 | /* take resampling into account and return the closest majoring |
335 | * multiple of 16 frames, as audioflinger expects audio buffers to |
336 | * be a multiple of 16 frames |
337 | */ |
338 | size_t size = (pcm_out_config.period_size * DEFAULT_OUT_SAMPLING_RATE) / out->out_config.rate; |
339 | size = ((size + 15) / 16) * 16; |
340 | return size * audio_stream_frame_size((struct audio_stream *)stream); |
341 | } |
342 | |
343 | static audio_channel_mask_t out_get_channels(const struct audio_stream *stream) |
344 | { |
345 | //ALOGD("%s(%p)", __FUNCTION__, stream); |
346 | /*struct aml_stream_out *out = (struct aml_stream_out *)stream; |
347 | |
348 | if (out->config.channels == 1) { |
349 | return AUDIO_CHANNEL_OUT_MONO; |
350 | } else { |
351 | return AUDIO_CHANNEL_OUT_STEREO; |
352 | } |
353 | */ |
354 | return AUDIO_CHANNEL_OUT_STEREO; |
355 | } |
356 | |
357 | static audio_format_t out_get_format(const struct audio_stream *stream) |
358 | { |
359 | //ALOGD("%s(%p)", __FUNCTION__, stream); |
360 | return AUDIO_FORMAT_PCM_16_BIT; |
361 | } |
362 | |
363 | static int out_set_format(struct audio_stream *stream, audio_format_t format) |
364 | { |
365 | //ALOGD("%s(%p)", __FUNCTION__, stream); |
366 | return 0; |
367 | } |
368 | |
369 | /* must be called with hw device and output stream mutexes locked */ |
370 | static int do_output_standby(struct aml_stream_out *out) |
371 | { |
372 | struct aml_audio_device *adev = out->dev; |
373 | |
374 | ALOGD("%s(%p)", __FUNCTION__, out); |
375 | |
376 | if (!out->standby) { |
377 | pcm_close(out->out_pcm); |
378 | out->out_pcm = NULL; |
379 | |
380 | adev->active_output = 0; |
381 | |
382 | if (out->buffer != NULL){ |
383 | free(out->buffer); |
384 | out->buffer = NULL; |
385 | } |
386 | out->standby = true; |
387 | } |
388 | return 0; |
389 | } |
390 | |
391 | static int out_standby(struct audio_stream *stream) |
392 | { |
393 | struct aml_stream_out *out = (struct aml_stream_out *)stream; |
394 | int status; |
395 | |
396 | ALOGD("%s(%p)", __FUNCTION__, stream); |
397 | |
398 | pthread_mutex_lock(&out->dev->lock); |
399 | pthread_mutex_lock(&out->lock); |
400 | status = do_output_standby(out); |
401 | pthread_mutex_unlock(&out->lock); |
402 | pthread_mutex_unlock(&out->dev->lock); |
403 | return status; |
404 | } |
405 | |
406 | static int out_dump(const struct audio_stream *stream, int fd) |
407 | { |
408 | ALOGD("%s(%p, %d)", __FUNCTION__, stream, fd); |
409 | return 0; |
410 | } |
411 | |
412 | static int out_set_parameters(struct audio_stream *stream, const char *kvpairs) |
413 | { |
414 | struct aml_stream_out *out = (struct aml_stream_out *)stream; |
415 | struct aml_audio_device *adev = out->dev; |
416 | |
417 | //int ret = get_usb_card(adev); |
418 | //if (ret < 0){ |
419 | // ALOGE("out_set_parameters*****ERROR: Could not get usb card number"); |
420 | //} |
421 | |
422 | struct str_parms *parms; |
423 | char value[32]; |
424 | |
425 | int ret = 0; |
426 | int routing = 0; |
427 | ALOGD("******%s*****%s*", __func__, kvpairs); |
428 | |
429 | parms = str_parms_create_str(kvpairs); |
430 | pthread_mutex_lock(&adev->lock); |
431 | |
432 | ret = str_parms_get_str(parms, "card", value, sizeof(value)); |
433 | if (ret >= 0) |
434 | adev->card = atoi(value); |
435 | |
436 | ret = str_parms_get_str(parms, "device", value, sizeof(value)); |
437 | if (ret >= 0) |
438 | adev->card_device = atoi(value); |
439 | pthread_mutex_unlock(&adev->lock); |
440 | str_parms_destroy(parms); |
441 | return 0; |
442 | } |
443 | |
444 | static char * out_get_parameters(const struct audio_stream *stream, const char *keys) |
445 | { |
446 | //ALOGD("%s(%p, %s)", __FUNCTION__, stream, keys); |
447 | return strdup(""); |
448 | } |
449 | |
450 | static uint32_t out_get_latency(const struct audio_stream_out *stream) |
451 | { |
452 | struct aml_stream_out *out = (struct aml_stream_out *)stream; |
453 | return (pcm_out_config.period_size * pcm_out_config.period_count * 1000) / |
454 | out->out_config.rate; |
455 | } |
456 | |
457 | static int out_set_volume(struct audio_stream_out *stream, float left, |
458 | float right) |
459 | { |
460 | return -ENOSYS; |
461 | } |
462 | |
463 | static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, |
464 | size_t bytes) |
465 | { |
466 | int ret; |
467 | struct aml_stream_out *out = (struct aml_stream_out *)stream; |
468 | struct aml_audio_device *adev = out->dev; |
469 | size_t frame_size = audio_stream_frame_size(&out->stream.common); |
470 | size_t in_frames = bytes / frame_size; |
471 | size_t out_frames = RESAMPLER_BUFFER_SIZE / frame_size; |
472 | bool force_input_standby = false; |
473 | //struct aml_stream_in *in; |
474 | int kernel_frames; |
475 | void *buf; |
476 | //ALOGD("*****out_write**device=0x%x****",adev->out_device); |
477 | pthread_mutex_lock(&out->dev->lock); |
478 | pthread_mutex_lock(&out->lock); |
479 | if (out->standby) { |
480 | ret = start_output_stream(out); |
481 | if (ret != 0) { |
482 | pthread_mutex_unlock(&adev->lock); |
483 | goto exit; |
484 | } |
485 | out->standby = false; |
486 | } |
487 | #if 0 |
488 | FILE * fp=fopen("/data/audio_in","a+"); |
489 | if (fp) { |
490 | int flen=fwrite((char *)buffer,1,bytes,fp); |
491 | ALOGD("flen = %d---audio_in=%d ", flen, bytes); |
492 | fclose(fp); |
493 | }else{ |
494 | ALOGD("could not open file: audio_in"); |
495 | } |
496 | #endif |
497 | /* only use resampler if required */ |
498 | if (out->out_config.rate != DEFAULT_OUT_SAMPLING_RATE) { |
499 | out_frames = resample_process(&out->resampler, in_frames, |
500 | (short *)buffer, (short *)out->buffer); |
501 | buf = out->buffer; |
502 | } else { |
503 | out_frames = in_frames; |
504 | buf = (void *)buffer; |
505 | } |
506 | |
507 | pcm_write(out->out_pcm, (void *)buf, out_frames * out->out_config.channels * 2); |
508 | |
509 | pthread_mutex_unlock(&out->lock); |
510 | pthread_mutex_unlock(&out->dev->lock); |
511 | |
512 | return bytes; |
513 | |
514 | exit: |
515 | pthread_mutex_unlock(&out->lock); |
516 | if (ret != 0) { |
517 | usleep(bytes * 1000000 / audio_stream_frame_size(&stream->common) / |
518 | out_get_sample_rate(&stream->common)); |
519 | } |
520 | |
521 | return bytes; |
522 | } |
523 | |
524 | static int out_get_render_position(const struct audio_stream_out *stream, |
525 | uint32_t *dsp_frames) |
526 | { |
527 | //ALOGD("%s(%p, %p)", __FUNCTION__, stream, dsp_frames); |
528 | return -EINVAL; |
529 | } |
530 | |
531 | static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect) |
532 | { |
533 | ALOGD("%s(%p, %p)", __FUNCTION__, stream, effect); |
534 | return 0; |
535 | } |
536 | |
537 | static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect) |
538 | { |
539 | return 0; |
540 | } |
541 | static int out_get_next_write_timestamp(const struct audio_stream_out *stream, |
542 | int64_t *timestamp) |
543 | { |
544 | return -EINVAL; |
545 | } |
546 | |
547 | |
548 | static uint32_t in_get_sample_rate(const struct audio_stream *stream) |
549 | { |
550 | struct aml_stream_in *in = (struct aml_stream_in *)stream; |
551 | |
552 | //ALOGD("%s(%p)", __FUNCTION__, stream); |
553 | return in->requested_rate; |
554 | } |
555 | |
556 | static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate) |
557 | { |
558 | //ALOGD("%s(%p, %d)", __FUNCTION__, stream, rate); |
559 | return 0; |
560 | } |
561 | static size_t get_input_buffer_size(uint32_t sample_rate, int format, int channel_count) |
562 | { |
563 | size_t size; |
564 | size_t device_rate; |
565 | |
566 | /* take resampling into account and return the closest majoring |
567 | multiple of 16 frames, as audioflinger expects audio buffers to |
568 | be a multiple of 16 frames */ |
569 | size = (pcm_in_config.period_size * sample_rate) / pcm_in_config.rate; |
570 | size = ((size + 15) / 16) * 16; |
571 | |
572 | return size * channel_count * sizeof(short); |
573 | } |
574 | |
575 | static size_t in_get_buffer_size(const struct audio_stream *stream) |
576 | { |
577 | struct aml_stream_in *in = (struct aml_stream_in *)stream; |
578 | |
579 | //ALOGD("%s(%p)", __FUNCTION__, stream); |
580 | return get_input_buffer_size(in->in_config.rate, |
581 | AUDIO_FORMAT_PCM_16_BIT, |
582 | in->in_config.channels); |
583 | } |
584 | |
585 | static audio_channel_mask_t in_get_channels(const struct audio_stream *stream) |
586 | { |
587 | struct aml_stream_in *in = (struct aml_stream_in *)stream; |
588 | //ALOGD("%s(%p)", __FUNCTION__, stream); |
589 | |
590 | if (in->in_config.channels == 1) { |
591 | return AUDIO_CHANNEL_IN_MONO; |
592 | } else { |
593 | return AUDIO_CHANNEL_IN_STEREO; |
594 | } |
595 | } |
596 | |
597 | static audio_format_t in_get_format(const struct audio_stream *stream) |
598 | { |
599 | //ALOGD("%s(%p)", __FUNCTION__, stream); |
600 | return AUDIO_FORMAT_PCM_16_BIT; |
601 | } |
602 | |
603 | static int in_set_format(struct audio_stream *stream, audio_format_t format) |
604 | { |
605 | //ALOGD("%s(%p, %d)", __FUNCTION__, stream, format); |
606 | return 0; |
607 | } |
608 | |
609 | /* must be called with hw device and input stream mutexes locked */ |
610 | static int do_input_standby(struct aml_stream_in *in) |
611 | { |
612 | struct aml_audio_device *adev = in->dev; |
613 | ALOGD("******%s******", __func__); |
614 | |
615 | if (!in->standby) { |
616 | pcm_close(in->in_pcm); |
617 | in->in_pcm = NULL; |
618 | adev->active_input = 0; |
619 | in->standby = true; |
620 | } |
621 | return 0; |
622 | } |
623 | static int in_standby(struct audio_stream *stream) |
624 | { |
625 | struct aml_stream_in *in = (struct aml_stream_in *)stream; |
626 | int status; |
627 | ALOGD("%s(%p)", __FUNCTION__, stream); |
628 | |
629 | pthread_mutex_lock(&in->dev->lock); |
630 | pthread_mutex_lock(&in->lock); |
631 | status = do_input_standby(in); |
632 | pthread_mutex_unlock(&in->lock); |
633 | pthread_mutex_unlock(&in->dev->lock); |
634 | return status; |
635 | } |
636 | |
637 | static int in_dump(const struct audio_stream *stream, int fd) |
638 | { |
639 | //ALOGD("%s(%p, %d)", __FUNCTION__, stream, fd); |
640 | return 0; |
641 | } |
642 | |
643 | static int in_set_parameters(struct audio_stream *stream, const char *kvpairs) |
644 | { |
645 | return 0; |
646 | } |
647 | |
648 | static char * in_get_parameters(const struct audio_stream *stream, |
649 | const char *keys) |
650 | { |
651 | //ALOGD("%s(%p, %s)", __FUNCTION__, stream, keys); |
652 | return strdup(""); |
653 | } |
654 | |
655 | static int in_set_gain(struct audio_stream_in *stream, float gain) |
656 | { |
657 | //ALOGD("%s(%p, %f)", __FUNCTION__, stream, gain); |
658 | return 0; |
659 | } |
660 | |
661 | #define USB_AUDIO_PCM "/proc/asound/usb_audio_info" |
662 | |
663 | static int get_usb_card(struct aml_audio_device *dev) |
664 | { |
665 | int card = -1,err=0; |
666 | int fd; |
667 | struct aml_audio_device *adev = dev; |
668 | uint i=0,usbid; |
669 | int string_length=32,str_len=8; |
670 | char *read_buf, *str; |
671 | int card_num; |
672 | char *str_start; |
673 | fd = open(USB_AUDIO_PCM, O_RDONLY); |
674 | |
675 | if (fd <0) { |
676 | ALOGE("ERROR: failed to open config file %s error: %d\n", USB_AUDIO_PCM, errno); |
677 | close(fd); |
678 | return -EINVAL; |
679 | } |
680 | |
681 | read_buf = (char *)malloc(string_length); |
682 | str = (char*)malloc(str_len); |
683 | memset(read_buf, 0x0, string_length); |
684 | memset(read_buf, 0x0, str_len); |
685 | err = read(fd, read_buf, string_length); |
686 | memcpy(str,read_buf,8); |
687 | //ALOGD("****str=%s****",str); |
688 | |
689 | usbid = strtoul(str, NULL, 16); |
690 | card = atoi(read_buf + 9); |
691 | adev->card = card; |
692 | ALOGD("******get_usb_card***card=%d***",adev->card); |
693 | adev->card_device= 0; |
694 | |
695 | free(read_buf); |
696 | free(str); |
697 | read_buf = NULL; |
698 | str = NULL; |
699 | close(fd); |
700 | return err; |
701 | |
702 | |
703 | } |
704 | |
705 | static int get_next_buffer(struct resampler_buffer_provider *buffer_provider, |
706 | struct resampler_buffer* buffer) |
707 | { |
708 | struct aml_stream_in *in; |
709 | |
710 | //ALOGD("%s(%p, %p)", __FUNCTION__, buffer_provider, buffer); |
711 | if (buffer_provider == NULL || buffer == NULL) |
712 | return -EINVAL; |
713 | |
714 | in = (struct aml_stream_in *)((char *)buffer_provider - |
715 | offsetof(struct aml_stream_in, buf_provider)); |
716 | |
717 | if (in->in_pcm == NULL) { |
718 | buffer->raw = NULL; |
719 | buffer->frame_count = 0; |
720 | in->read_status = -ENODEV; |
721 | return -ENODEV; |
722 | } |
723 | |
724 | if (in->frames_in == 0) { |
725 | in->read_status = pcm_read(in->in_pcm, |
726 | (void*)in->buffer, |
727 | in->in_config.period_size * |
728 | audio_stream_frame_size(&in->stream.common)); |
729 | if (in->read_status != 0) { |
730 | ALOGE("get_next_buffer() pcm_read error %d", in->read_status); |
731 | buffer->raw = NULL; |
732 | buffer->frame_count = 0; |
733 | return in->read_status; |
734 | } |
735 | in->frames_in = in->in_config.period_size; |
736 | } |
737 | |
738 | buffer->frame_count = (buffer->frame_count > in->frames_in) ? |
739 | in->frames_in : buffer->frame_count; |
740 | buffer->i16 = in->buffer + (in->in_config.period_size - in->frames_in) * |
741 | in->in_config.channels; |
742 | |
743 | return in->read_status; |
744 | |
745 | } |
746 | |
747 | static void release_buffer(struct resampler_buffer_provider *buffer_provider, |
748 | struct resampler_buffer* buffer) |
749 | { |
750 | struct aml_stream_in *in; |
751 | |
752 | //ALOGD("%s(%p, %p)", __FUNCTION__, buffer_provider, buffer); |
753 | if (buffer_provider == NULL || buffer == NULL) |
754 | return; |
755 | |
756 | in = (struct aml_stream_in *)((char *)buffer_provider - |
757 | offsetof(struct aml_stream_in, buf_provider)); |
758 | |
759 | in->frames_in -= buffer->frame_count; |
760 | } |
761 | |
762 | static int start_input_stream(struct aml_stream_in *in) |
763 | { |
764 | int err; |
765 | struct aml_audio_device *adev = in->dev; |
766 | adev->active_input = in; |
767 | //get_usb_card(in); |
768 | if ((adev->card < 0) || (adev->card_device < 0)) { |
769 | ALOGE("ERROR: Could not get usb card info"); |
770 | return -EINVAL; |
771 | } |
772 | #if 0 |
773 | err = get_usb_cap((char *)"Capture:", &in->in_config.channels, &in->in_config.rate, adev->card); |
774 | if (err) { |
775 | ALOGE("ERROR: Could not get capture capabilities from usb device"); |
776 | return -EINVAL; |
777 | } |
778 | if (in->requested_rate != in->in_config.rate) { |
779 | in->buf_provider.get_next_buffer = get_next_buffer; |
780 | in->buf_provider.release_buffer = release_buffer; |
781 | ALOGD("Create resampler for input stream"); |
782 | err = create_resampler(in->in_config.rate, |
783 | in->requested_rate, |
784 | in->in_config.channels, |
785 | RESAMPLER_QUALITY_DEFAULT, |
786 | &in->buf_provider, |
787 | &in->resampler); |
788 | if (err != 0) { |
789 | err = -EINVAL; |
790 | goto err; |
791 | } |
792 | } |
793 | #endif |
794 | ALOGD("pcm_open in: card(%d), port(%d)", adev->card, adev->card_device); |
795 | in->in_pcm = pcm_open(adev->card, adev->card_device, PCM_IN, &in->in_config); |
796 | if (!pcm_is_ready(in->in_pcm)) { |
797 | ALOGE("cannot open pcm_in driver: %s", pcm_get_error(in->in_pcm)); |
798 | pcm_close(in->in_pcm); |
799 | adev->active_input = NULL; |
800 | return -ENOMEM; |
801 | } |
802 | ALOGD("pcm_open in: card(%d), port(%d)", adev->card, adev->card_device); |
803 | return 0; |
804 | |
805 | err: |
806 | if (in->resampler) |
807 | release_resampler(in->resampler); |
808 | return err; |
809 | } |
810 | /* read_frames() reads frames from kernel driver, down samples to capture rate |
811 | * if necessary and output the number of frames requested to the buffer specified */ |
812 | static ssize_t read_frames(struct aml_stream_in *in, void *buffer, ssize_t frames) |
813 | { |
814 | ssize_t frames_wr = 0; |
815 | //ALOGD("%s(in->resampler=%p, %ld)", __FUNCTION__, in->resampler, frames); |
816 | while (frames_wr < frames) { |
817 | size_t frames_rd = frames - frames_wr; |
818 | if (in->resampler != NULL) { |
819 | in->resampler->resample_from_provider(in->resampler, |
820 | (int16_t *)((char *)buffer + |
821 | frames_wr * audio_stream_frame_size(&in->stream.common)), |
822 | &frames_rd); |
823 | } else { |
824 | struct resampler_buffer buf = { |
825 | { raw : NULL, }, |
826 | frame_count : frames_rd, |
827 | }; |
828 | get_next_buffer(&in->buf_provider, &buf); |
829 | if (buf.raw != NULL) { |
830 | memcpy((char *)buffer + |
831 | frames_wr * audio_stream_frame_size(&in->stream.common), |
832 | buf.raw, |
833 | buf.frame_count * audio_stream_frame_size(&in->stream.common)); |
834 | frames_rd = buf.frame_count; |
835 | } |
836 | release_buffer(&in->buf_provider, &buf); |
837 | } |
838 | /* in->read_status is updated by getNextBuffer() also called by |
839 | * in->resampler->resample_from_provider() */ |
840 | if (in->read_status != 0) |
841 | return in->read_status; |
842 | |
843 | frames_wr += frames_rd; |
844 | } |
845 | return frames_wr; |
846 | } |
847 | |
848 | static ssize_t in_read(struct audio_stream_in *stream, void* buffer, |
849 | size_t bytes) |
850 | { |
851 | // ALOGD("============in_read====bytes=%d=======",bytes); |
852 | int ret = 0; |
853 | struct aml_stream_in *in = (struct aml_stream_in *)stream; |
854 | struct aml_audio_device *adev = in->dev; |
855 | size_t frames_rq = bytes / audio_stream_frame_size(&stream->common); |
856 | //ALOGD("%s(in->num_preprocessors=%d, frames_rq=%d)", __FUNCTION__, in->num_preprocessors, frames_rq); |
857 | |
858 | /* acquiring hw device mutex systematically is useful if a low priority thread is waiting |
859 | * on the input stream mutex - e.g. executing select_mode() while holding the hw device |
860 | * mutex |
861 | */ |
862 | pthread_mutex_lock(&adev->lock); |
863 | pthread_mutex_lock(&in->lock); |
864 | if (in->standby) { |
865 | ret = start_input_stream(in); |
866 | if (ret == 0) |
867 | in->standby = 0; |
868 | } |
869 | pthread_mutex_unlock(&adev->lock); |
870 | |
871 | #if 0 |
872 | FILE * fp=fopen("/data/audio_in/temp.data","a+"); |
873 | if (fp) { |
874 | int flen=fwrite((char *)buffer,1,bytes,fp); |
875 | ALOGD("flen = %d---audio_in=%d ", flen, bytes); |
876 | fclose(fp); |
877 | }else{ |
878 | ALOGD("could not open file: audio_in"); |
879 | } |
880 | #endif |
881 | |
882 | if (ret < 0) |
883 | goto exit; |
884 | |
885 | if (in->resampler != NULL) |
886 | ret = read_frames(in, buffer, frames_rq); |
887 | else |
888 | ret = pcm_read(in->in_pcm, buffer, bytes); |
889 | if (ret > 0) |
890 | ret = 0; |
891 | |
892 | if (ret == 0 && adev->mic_mute) { |
893 | memset(buffer, 0, bytes); |
894 | } |
895 | |
896 | #if 0 |
897 | FILE *dump_fp = NULL; |
898 | |
899 | dump_fp = fopen("/data/dump_in.pcm", "a+"); |
900 | if (dump_fp != NULL) { |
901 | fwrite(buffer, bytes, 1, dump_fp); |
902 | fclose(dump_fp); |
903 | } |
904 | else { |
905 | ALOGW("[Error] Can't write to /data/dump_in.pcm"); |
906 | } |
907 | #endif |
908 | |
909 | exit: |
910 | if (ret < 0) |
911 | usleep(bytes * 1000000 / audio_stream_frame_size(&stream->common) / |
912 | in_get_sample_rate(&stream->common)); |
913 | |
914 | pthread_mutex_unlock(&in->lock); |
915 | return bytes; |
916 | |
917 | } |
918 | |
919 | static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream) |
920 | { |
921 | return 0; |
922 | } |
923 | |
924 | static int in_add_audio_effect(const struct audio_stream *stream, |
925 | effect_handle_t effect) |
926 | { |
927 | return 0; |
928 | } |
929 | |
930 | static int in_remove_audio_effect(const struct audio_stream *stream, |
931 | effect_handle_t effect) |
932 | { |
933 | return 0; |
934 | } |
935 | |
936 | static int adev_open_output_stream(struct audio_hw_device *dev, |
937 | audio_io_handle_t handle, |
938 | audio_devices_t devices, |
939 | audio_output_flags_t flags, |
940 | struct audio_config *config, |
941 | struct audio_stream_out **stream_out) |
942 | { |
943 | struct aml_audio_device *adev = (struct aml_audio_device *)dev; |
944 | struct aml_stream_out *out; |
945 | struct mixer *usb_mixer; |
946 | int ret = 0; |
947 | |
948 | out = (struct aml_stream_out *)calloc(1, sizeof(struct aml_stream_out)); |
949 | if (!out) |
950 | return -ENOMEM; |
951 | |
952 | out->stream.common.get_sample_rate = out_get_sample_rate; |
953 | out->stream.common.set_sample_rate = out_set_sample_rate; |
954 | out->stream.common.get_buffer_size = out_get_buffer_size; |
955 | out->stream.common.get_channels = out_get_channels; |
956 | out->stream.common.get_format = out_get_format; |
957 | out->stream.common.set_format = out_set_format; |
958 | out->stream.common.standby = out_standby; |
959 | out->stream.common.dump = out_dump; |
960 | out->stream.common.set_parameters = out_set_parameters; |
961 | out->stream.common.get_parameters = out_get_parameters; |
962 | out->stream.common.add_audio_effect = out_add_audio_effect; |
963 | out->stream.common.remove_audio_effect = out_remove_audio_effect; |
964 | //out->stream.common.set_voip_mode = out_set_voip_mode; |
965 | out->stream.get_latency = out_get_latency; |
966 | out->stream.set_volume = out_set_volume; |
967 | out->stream.write = out_write; |
968 | out->stream.get_render_position = out_get_render_position; |
969 | out->stream.get_next_write_timestamp = out_get_next_write_timestamp; |
970 | out->out_config = pcm_out_config; |
971 | |
972 | out->dev = adev; |
973 | //ret = get_usb_card(adev); |
974 | //if (ret < 0){ |
975 | // ALOGE("ERROR: Could not get usb card number"); |
976 | // goto err_open; |
977 | //} |
978 | |
979 | usb_mixer = mixer_open(adev->card); |
980 | if (!usb_mixer) { |
981 | ALOGE("Unable to open the mixer, aborting."); |
982 | goto err_open; |
983 | } |
984 | config->format = out_get_format(&out->stream.common); |
985 | config->channel_mask = out_get_channels(&out->stream.common); |
986 | config->sample_rate = out_get_sample_rate(&out->stream.common); |
987 | out->standby = true; |
988 | |
989 | adev->card = -1; |
990 | adev->card_device = -1; |
991 | adev->out_device = devices; |
992 | |
993 | *stream_out = &out->stream; |
994 | return 0; |
995 | |
996 | err_open: |
997 | mixer_close(usb_mixer); |
998 | free(out); |
999 | *stream_out = NULL; |
1000 | return ret; |
1001 | } |
1002 | |
1003 | static void adev_close_output_stream(struct audio_hw_device *dev, |
1004 | struct audio_stream_out *stream) |
1005 | { |
1006 | struct aml_stream_out *out = (struct aml_stream_out *)stream; |
1007 | ALOGD("******%s******", __func__);// |
1008 | |
1009 | out_standby(&stream->common); |
1010 | free(stream); |
1011 | } |
1012 | |
1013 | static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs) |
1014 | { |
1015 | return 0; |
1016 | } |
1017 | |
1018 | static char * adev_get_parameters(const struct audio_hw_device *dev, |
1019 | const char *keys) |
1020 | { |
1021 | //ALOGD("%s(%p, %s)", __FUNCTION__, dev, keys); |
1022 | return strdup(""); |
1023 | } |
1024 | |
1025 | static int adev_init_check(const struct audio_hw_device *dev) |
1026 | { |
1027 | //ALOGD("%s(%p)", __FUNCTION__, dev); |
1028 | return 0; |
1029 | } |
1030 | |
1031 | static int adev_set_voice_volume(struct audio_hw_device *dev, float volume) |
1032 | { |
1033 | struct aml_audio_device *adev = (struct aml_audio_device *)dev; |
1034 | |
1035 | //adev->voice_volume = volume; |
1036 | |
1037 | //ALOGD("%s(%p, %f)", __FUNCTION__, dev, volume); |
1038 | //if (adev->mode == AUDIO_MODE_IN_CALL) |
1039 | // ril_set_call_volume(&adev->ril, SOUND_TYPE_VOICE, volume); |
1040 | |
1041 | return 0; |
1042 | } |
1043 | |
1044 | static int adev_set_master_volume(struct audio_hw_device *dev, float volume) |
1045 | { |
1046 | //ALOGD("%s(%p, %f)", __FUNCTION__, dev, volume); |
1047 | return -ENOSYS; |
1048 | } |
1049 | |
1050 | static int adev_get_master_volume(struct audio_hw_device *dev, |
1051 | float *volume) |
1052 | { |
1053 | return -ENOSYS; |
1054 | } |
1055 | |
1056 | static int adev_set_master_mute(struct audio_hw_device *dev, bool muted) |
1057 | { |
1058 | return -ENOSYS; |
1059 | } |
1060 | |
1061 | static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted) |
1062 | { |
1063 | return -ENOSYS; |
1064 | } |
1065 | static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode) |
1066 | { |
1067 | return 0; |
1068 | } |
1069 | |
1070 | static int adev_set_mic_mute(struct audio_hw_device *dev, bool state) |
1071 | { |
1072 | return -ENOSYS; |
1073 | } |
1074 | |
1075 | static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state) |
1076 | { |
1077 | return -ENOSYS; |
1078 | } |
1079 | |
1080 | static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev, |
1081 | const struct audio_config *config) |
1082 | { |
1083 | return 0; |
1084 | } |
1085 | |
1086 | static int adev_open_input_stream(struct audio_hw_device *dev, |
1087 | audio_io_handle_t handle, |
1088 | audio_devices_t devices, |
1089 | struct audio_config *config, |
1090 | struct audio_stream_in **stream_in) |
1091 | { |
1092 | struct aml_audio_device *adev = (struct aml_audio_device *)dev; |
1093 | struct aml_stream_in *in; |
1094 | struct mixer *usb_mixer = NULL; |
1095 | int ret = 0; |
1096 | |
1097 | in = (struct aml_stream_in *)calloc(1, sizeof(struct aml_stream_in)); |
1098 | if (!in) |
1099 | return -ENOMEM; |
1100 | |
1101 | in->stream.common.get_sample_rate = in_get_sample_rate; |
1102 | in->stream.common.set_sample_rate = in_set_sample_rate; |
1103 | in->stream.common.get_buffer_size = in_get_buffer_size; |
1104 | in->stream.common.get_channels = in_get_channels; |
1105 | in->stream.common.get_format = in_get_format; |
1106 | in->stream.common.set_format = in_set_format; |
1107 | in->stream.common.standby = in_standby; |
1108 | in->stream.common.dump = in_dump; |
1109 | in->stream.common.set_parameters = in_set_parameters; |
1110 | in->stream.common.get_parameters = in_get_parameters; |
1111 | in->stream.common.add_audio_effect = in_add_audio_effect; |
1112 | in->stream.common.remove_audio_effect = in_remove_audio_effect; |
1113 | //in->stream.common.set_voip_mode = in_set_voip_mode; |
1114 | in->stream.set_gain = in_set_gain; |
1115 | in->stream.read = in_read; |
1116 | in->stream.get_input_frames_lost = in_get_input_frames_lost; |
1117 | |
1118 | in->requested_rate = config->sample_rate; |
1119 | in->in_config=pcm_in_config; |
1120 | |
1121 | //memcpy(&in->in_config, &pcm_config_in, sizeof(pcm_config_in)); |
1122 | in->dev = adev; |
1123 | in->in_config.rate = in->requested_rate; |
1124 | |
1125 | //ret = get_usb_card(adev); |
1126 | //if (ret < 0){ |
1127 | // ALOGE("ERROR: Could not get usb card number"); |
1128 | // goto err_open; |
1129 | //} |
1130 | |
1131 | usb_mixer = mixer_open(adev->card); |
1132 | if (!usb_mixer) { |
1133 | ALOGE("Unable to open the mixer, aborting."); |
1134 | goto err_open; |
1135 | } |
1136 | |
1137 | ret = get_usb_cap("Capture:", &in->in_config.channels, &in->in_config.rate, adev->card); |
1138 | |
1139 | if (ret) { |
1140 | ALOGE("ERROR: Could not get capture capabilities from usb device"); |
1141 | goto err_open; |
1142 | } |
1143 | if (in->requested_rate != in->in_config.rate) { |
1144 | in->buffer = malloc(in->in_config.period_size * |
1145 | audio_stream_frame_size(&in->stream.common)); |
1146 | if (!in->buffer) { |
1147 | ret = -ENOMEM; |
1148 | goto err_open; |
1149 | } |
1150 | in->buf_provider.get_next_buffer = get_next_buffer; |
1151 | in->buf_provider.release_buffer = release_buffer; |
1152 | ALOGD("Create resampler for input stream"); |
1153 | ret = create_resampler(in->in_config.rate, |
1154 | in->requested_rate, |
1155 | in->in_config.channels, |
1156 | RESAMPLER_QUALITY_DEFAULT, |
1157 | &in->buf_provider, |
1158 | &in->resampler); |
1159 | if (ret != 0) { |
1160 | ret = -EINVAL; |
1161 | goto err_open; |
1162 | } |
1163 | } |
1164 | |
1165 | config->format = in_get_format(&in->stream.common); |
1166 | config->channel_mask = in_get_channels(&in->stream.common); |
1167 | config->sample_rate = in_get_sample_rate(&in->stream.common); |
1168 | |
1169 | in->standby = true; |
1170 | *stream_in = &in->stream; |
1171 | return 0; |
1172 | |
1173 | err_open: |
1174 | if (in->resampler) |
1175 | release_resampler(in->resampler); |
1176 | mixer_close(usb_mixer); |
1177 | free(in); |
1178 | *stream_in = NULL; |
1179 | return ret; |
1180 | } |
1181 | |
1182 | static void adev_close_input_stream(struct audio_hw_device *dev, |
1183 | struct audio_stream_in *stream) |
1184 | { |
1185 | struct aml_stream_in *in = (struct aml_stream_in *)stream; |
1186 | ALOGD("******%s******", __func__); |
1187 | |
1188 | in_standby(&stream->common); |
1189 | free(stream); |
1190 | } |
1191 | |
1192 | static int adev_dump(const audio_hw_device_t *device, int fd) |
1193 | { |
1194 | //ALOGD("%s(%p, %d)", __FUNCTION__, device, fd); |
1195 | return 0; |
1196 | } |
1197 | |
1198 | static int adev_close(hw_device_t *device) |
1199 | { |
1200 | struct aml_audio_device *adev = (struct aml_audio_device *)device; |
1201 | |
1202 | ALOGD("%s(%p)", __func__, device); |
1203 | |
1204 | free(device); |
1205 | return 0; |
1206 | } |
1207 | |
1208 | #if 0 |
1209 | static uint32_t adev_get_supported_devices(const struct audio_hw_device *dev) |
1210 | { |
1211 | return AUDIO_DEVICE_OUT_ALL_USB|AUDIO_DEVICE_IN_USB_DEVICE; |
1212 | } |
1213 | |
1214 | #endif |
1215 | static int adev_open(const hw_module_t* module, const char* name, |
1216 | hw_device_t** device) |
1217 | { |
1218 | struct aml_audio_device *adev; |
1219 | int ret; |
1220 | ALOGD("%s(%p, %s, %p)", __FUNCTION__, module, name, device); |
1221 | if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) |
1222 | return -EINVAL; |
1223 | |
1224 | adev = calloc(1, sizeof(struct aml_audio_device)); |
1225 | if (!adev) |
1226 | return -ENOMEM; |
1227 | |
1228 | adev->hw_device.common.tag = HARDWARE_DEVICE_TAG; |
1229 | adev->hw_device.common.version = AUDIO_DEVICE_API_VERSION_2_0; |
1230 | adev->hw_device.common.module = (struct hw_module_t *) module; |
1231 | adev->hw_device.common.close = adev_close; |
1232 | |
1233 | //adev->hw_device.get_supported_devices = adev_get_supported_devices; |
1234 | adev->hw_device.init_check = adev_init_check; |
1235 | adev->hw_device.set_voice_volume = adev_set_voice_volume; |
1236 | adev->hw_device.set_master_volume = adev_set_master_volume; |
1237 | adev->hw_device.get_master_volume = adev_get_master_volume; |
1238 | adev->hw_device.set_master_mute = adev_set_master_mute; |
1239 | adev->hw_device.get_master_mute = adev_get_master_mute; |
1240 | adev->hw_device.set_mode = adev_set_mode; |
1241 | adev->hw_device.set_mic_mute = adev_set_mic_mute; |
1242 | adev->hw_device.get_mic_mute = adev_get_mic_mute; |
1243 | adev->hw_device.set_parameters = adev_set_parameters; |
1244 | adev->hw_device.get_parameters = adev_get_parameters; |
1245 | adev->hw_device.get_input_buffer_size = adev_get_input_buffer_size; |
1246 | adev->hw_device.open_output_stream = adev_open_output_stream; |
1247 | adev->hw_device.close_output_stream = adev_close_output_stream; |
1248 | adev->hw_device.open_input_stream = adev_open_input_stream; |
1249 | adev->hw_device.close_input_stream = adev_close_input_stream; |
1250 | adev->hw_device.dump = adev_dump; |
1251 | |
1252 | |
1253 | *device = &adev->hw_device.common; |
1254 | return 0; |
1255 | } |
1256 | |
1257 | static struct hw_module_methods_t hal_module_methods = { |
1258 | .open = adev_open, |
1259 | }; |
1260 | |
1261 | struct audio_module HAL_MODULE_INFO_SYM = { |
1262 | .common = { |
1263 | .tag = HARDWARE_MODULE_TAG, |
1264 | .module_api_version = AUDIO_MODULE_API_VERSION_0_1, |
1265 | .hal_api_version = HARDWARE_HAL_API_VERSION, |
1266 | .id = AUDIO_HARDWARE_MODULE_ID, |
1267 | .name = "USB audio HW HAL", |
1268 | .author = "amlogic, Corp.", |
1269 | .methods = &hal_module_methods, |
1270 | }, |
1271 | }; |
1272 |