blob: c0540811ea40a69b9a3abd8f276d39d56c91279f [file] [log] [blame]
Iliyan Malchev4765c432012-06-11 14:36:16 -07001/* AudioUsbALSA.cpp
2Copyright (c) 2012, Code Aurora Forum. All rights reserved.
3
4Redistribution and use in source and binary forms, with or without
5modification, are permitted provided that the following conditions are
6met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above
10 copyright notice, this list of conditions and the following
11 disclaimer in the documentation and/or other materials provided
12 with the distribution.
13 * Neither the name of Code Aurora Forum, Inc. nor the names of its
14 contributors may be used to endorse or promote products derived
15 from this software without specific prior written permission.
16
17THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/
28
29#define LOG_TAG "AudioUsbALSA"
30//#define LOG_NDEBUG 0
31//#define LOG_NDDEBUG 0
32#include <utils/Log.h>
33#include <utils/String8.h>
34
35#include <cutils/properties.h>
36#include <media/AudioRecord.h>
37#include <hardware_legacy/power.h>
38#include <sys/poll.h>
39#include <sys/ioctl.h>
40#include <fcntl.h>
41#include <string.h>
42#include <sys/stat.h>
43#include <errno.h>
44#include <jni.h>
45#include <stdio.h>
46#include <sys/eventfd.h>
47
48
49#include "AudioUsbALSA.h"
50struct pollfd pfdProxyPlayback[2];
51struct pollfd pfdUsbPlayback[2];
52struct pollfd pfdProxyRecording[1];
53struct pollfd pfdUsbRecording[1];
54
55namespace android_audio_legacy
56{
57AudioUsbALSA::AudioUsbALSA()
58{
59 mproxypfdPlayback = -1;
60 musbpfdPlayback = -1;
61 mkillPlayBackThread = false;
62 mkillRecordingThread = false;
63}
64
65AudioUsbALSA::~AudioUsbALSA()
66{
67 mkillPlayBackThread = true;
68 mkillRecordingThread = true;
69}
70
71
72int AudioUsbALSA::getnumOfRates(char *ratesStr){
73 int i, size = 0;
74 char *nextSRString, *temp_ptr;
75 nextSRString = strtok_r(ratesStr, " ,", &temp_ptr);
76 if (nextSRString == NULL) {
77 LOGE("ERROR: getnumOfRates: could not find rates string");
78 return NULL;
79 }
80 for (i = 1; nextSRString != NULL; i++) {
81 size ++;
82 nextSRString = strtok_r(NULL, " ,.-", &temp_ptr);
83 }
84 return size;
85}
86
87status_t AudioUsbALSA::getPlaybackCap()
88{
89 LOGD("getPlaybackCap");
90 long unsigned fileSize;
91 FILE *fp;
92 char *buffer;
93 int err = 1;
94 int size = 0;
95 int fd, i, lchannelsPlayback;
96 char *read_buf, *playbackstr_start, *channel_start, *ratesStr, *ratesStrForVal,
97 *ratesStrStart, *chString, *nextSRStr, *test, *nextSRString, *temp_ptr;
98 struct stat st;
99 memset(&st, 0x0, sizeof(struct stat));
100 msampleRatePlayback = 0;
101 fd = open(PATH, O_RDONLY);
102 if (fd <0) {
103 LOGE("ERROR: failed to open config file %s error: %d\n", PATH, errno);
104 close(fd);
105 return UNKNOWN_ERROR;
106 }
107
108 if (fstat(fd, &st) < 0) {
109 LOGE("ERROR: failed to stat %s error %d\n", PATH, errno);
110 close(fd);
111 return UNKNOWN_ERROR;
112 }
113
114 fileSize = st.st_size;
115
116 read_buf = (char *)malloc(BUFFSIZE);
117 memset(read_buf, 0x0, BUFFSIZE);
118 err = read(fd, read_buf, BUFFSIZE);
119 playbackstr_start = strstr(read_buf, "Playback:");
120 if (playbackstr_start == NULL) {
121 LOGE("ERROR:Playback section not found in usb config file");
122 close(fd);
123 free(read_buf);
124 return UNKNOWN_ERROR;
125 }
126
127 channel_start = strstr(playbackstr_start, "Channels:");
128 if (channel_start == NULL) {
129 LOGE("ERROR: Could not find Channels information");
130 close(fd);
131 free(read_buf);
132 return UNKNOWN_ERROR;
133 }
134 channel_start = strstr(channel_start, " ");
135 if (channel_start == NULL) {
136 LOGE("ERROR: Channel section not found in usb config file");
137 close(fd);
138 free(read_buf);
139 return UNKNOWN_ERROR;
140 }
141
142 lchannelsPlayback = atoi(channel_start);
143 if (lchannelsPlayback == 1) {
144 mchannelsPlayback = 1;
145 } else {
146 mchannelsPlayback = 2;
147 }
148 LOGD("channels supported by device: %d", lchannelsPlayback);
149 ratesStrStart = strstr(playbackstr_start, "Rates:");
150 if (ratesStrStart == NULL) {
151 LOGE("ERROR: Cant find rates information");
152 close(fd);
153 free(read_buf);
154 return UNKNOWN_ERROR;
155 }
156
157 ratesStrStart = strstr(ratesStrStart, " ");
158 if (ratesStrStart == NULL) {
159 LOGE("ERROR: Channel section not found in usb config file");
160 close(fd);
161 free(read_buf);
162 return UNKNOWN_ERROR;
163 }
164
165 //copy to ratesStr, current line.
166 char *target = strchr(ratesStrStart, '\n');
167 if (target == NULL) {
168 LOGE("ERROR: end of line not found");
169 close(fd);
170 free(read_buf);
171 return UNKNOWN_ERROR;
172 }
173 size = target - ratesStrStart;
174 ratesStr = (char *)malloc(size + 1) ;
175 ratesStrForVal = (char *)malloc(size + 1) ;
176 memcpy(ratesStr, ratesStrStart, size);
177 memcpy(ratesStrForVal, ratesStrStart, size);
178 ratesStr[size] = '\0';
179 ratesStrForVal[size] = '\0';
180
181 size = getnumOfRates(ratesStr);
182 if (!size) {
183 LOGE("ERROR: Could not get rate size, returning");
184 close(fd);
185 free(ratesStrForVal);
186 free(ratesStr);
187 free(read_buf);
188 return UNKNOWN_ERROR;
189 }
190
191 //populate playback rates array
192 int ratesSupported[size];
193 nextSRString = strtok_r(ratesStrForVal, " ,", &temp_ptr);
194 if (nextSRString == NULL) {
195 LOGE("ERROR: Could not get first rate val");
196 close(fd);
197 free(ratesStrForVal);
198 free(ratesStr);
199 free(read_buf);
200 return UNKNOWN_ERROR;
201 }
202
203 ratesSupported[0] = atoi(nextSRString);
204 for (i = 1; i<size; i++) {
205 nextSRString = strtok_r(NULL, " ,.-", &temp_ptr);
206 ratesSupported[i] = atoi(nextSRString);
207 LOGV("ratesSupported[%d] for playback: %d",i, ratesSupported[i]);
208 }
209
210 for (i = 0; i<=size; i++) {
211 if (ratesSupported[i] <= 48000) {
212 msampleRatePlayback = ratesSupported[i];
213 break;
214 }
215 }
216 LOGD("msampleRatePlayback: %d", msampleRatePlayback);
217
218 close(fd);
219 free(ratesStrForVal);
220 free(ratesStr);
221 free(read_buf);
222 ratesStrForVal = NULL;
223 ratesStr = NULL;
224 read_buf = NULL;
225 return NO_ERROR;
226}
227
228
229/******************************** Capture ******************************/
230status_t AudioUsbALSA::getCaptureCap(){
231 char *read_buf, *target, *capturestr_start, *channel_startCapture, *ratesStr, *ratesStrForVal,
232 *ratesStrStartCapture, *chString, *nextSRStr, *test, *nextSRString, *temp_ptr;
233
234 int fd, i, lchannelsCapture;
235
236 int err =1, size=0;
237 struct stat st;
238 memset(&st, 0x0, sizeof(struct stat));
239
240 msampleRateCapture = 0;
241 fd = open(PATH, O_RDONLY);
242 if (fd <0) {
243 LOGE("ERROR: failed to open config file %s error: %d\n", PATH, errno);
244 return UNKNOWN_ERROR;
245 }
246
247 if (fstat(fd, &st) < 0) {
248 LOGE("ERROR: failed to stat %s error %d\n", PATH, errno);
249 close(fd);
250 return UNKNOWN_ERROR;
251 }
252
253 read_buf = (char *)malloc(BUFFSIZE);
254 memset(read_buf, 0x0, BUFFSIZE);
255 err = read(fd, read_buf, BUFFSIZE);
256 capturestr_start = strstr(read_buf, "Capture:");
257 if (capturestr_start == NULL) {
258 LOGE("ERROR: Could not find capture section for recording");
259 free(read_buf);
260 close(fd);
261 return NULL;
262 }
263
264 channel_startCapture = strstr(capturestr_start, "Channels: ");
265 if (channel_startCapture == NULL) {
266 LOGE("ERROR: Could not find Channels info for recording");
267 close(fd);
268 free(read_buf);
269 return UNKNOWN_ERROR;
270 }
271 channel_startCapture = strstr(channel_startCapture, " ");
272 if (channel_startCapture == NULL) {
273 LOGE("ERROR: Could not find channels information for recording");
274 close(fd);
275 free(read_buf);
276 return UNKNOWN_ERROR;
277 } else {
278 lchannelsCapture = atoi(channel_startCapture);
279 if (lchannelsCapture == 1) {
280 mchannelsCapture = 1;
281 } else {
282 LOGD("lchannelsCapture: %d", lchannelsCapture);
283 mchannelsCapture = 2;
284 }
285 }
286
287 ratesStrStartCapture = strstr(capturestr_start, "Rates:");
288 if (ratesStrStartCapture == NULL) {
289 LOGE("ERROR; Could not find rates section in config file for recording");
290 close(fd);
291 free(read_buf);
292 return UNKNOWN_ERROR;
293 }
294 ratesStrStartCapture = strstr(ratesStrStartCapture, " ");
295 if (ratesStrStartCapture == NULL) {
296 LOGE("ERROR: Could not find rates section in config file for recording");
297 close(fd);
298 free(read_buf);
299 return UNKNOWN_ERROR;
300 }
301
302 //copy to ratesStr, current line.
303 target = strchr(ratesStrStartCapture, '\n');
304 if (target == NULL) {
305 LOGE("ERROR: end of line not found for rates");
306 close(fd);
307 free(read_buf);
308 return UNKNOWN_ERROR;
309 }
310
311 size = target - ratesStrStartCapture;
312 ratesStr = (char *)malloc(size + 1) ;
313 ratesStrForVal = (char *)malloc(size + 1) ;
314 memcpy(ratesStr, ratesStrStartCapture, size);
315 memcpy(ratesStrForVal, ratesStrStartCapture, size);
316 ratesStr[size] = '\0';
317 ratesStrForVal[size] = '\0';
318
319 size = getnumOfRates(ratesStr);
320 if (!size) {
321 LOGE("ERROR: Could not get rate size for capture, returning");
322 close(fd);
323 free(read_buf);
324 free(ratesStr);
325 free(ratesStrForVal);
326 return UNKNOWN_ERROR;
327 }
328
329 //populate playback rates array
330 int ratesSupportedCapture[size];
331 nextSRString = strtok_r(ratesStrForVal, " ,", &temp_ptr);
332 if (nextSRString == NULL) {
333 LOGE("ERROR: Could not find ratesStr for recording");
334 close(fd);
335 free(read_buf);
336 free(ratesStr);
337 free(ratesStrForVal);
338 return UNKNOWN_ERROR;
339 }
340
341 ratesSupportedCapture[0] = atoi(nextSRString);
342 for (i = 1; i<size; i++) {
343 nextSRString = strtok_r(NULL, " ,.-", &temp_ptr);
344 ratesSupportedCapture[i] = atoi(nextSRString);
345 }
346 for (i = 0;i<=size; i++) {
347 if (ratesSupportedCapture[i] <= 48000) {
348 msampleRateCapture = ratesSupportedCapture[i];
349 break;
350 }
351 }
352 LOGD("msampleRateCapture: %d", msampleRateCapture);
353
354 close(fd);
355 free(read_buf);
356 free(ratesStr);
357 free(ratesStrForVal);
358 read_buf = NULL;
359 ratesStr = NULL;
360 ratesStrForVal = NULL;
361 return NO_ERROR;
362}
363
364void AudioUsbALSA::exitPlaybackThread(uint64_t writeVal)
365{
366 LOGD("exitPlaybackThread, mproxypfdPlayback: %d", mproxypfdPlayback);
367 if (writeVal == SIGNAL_EVENT_KILLTHREAD) {
368 closePlaybackDevices();
369 }
370 if ((mproxypfdPlayback != -1) && (musbpfdPlayback != -1)) {
371 write(mproxypfdPlayback, &writeVal, sizeof(uint64_t));
372 write(musbpfdPlayback, &writeVal, sizeof(uint64_t));
373 mkillPlayBackThread = true;
374 pthread_join(mPlaybackUsb,NULL);
375 }
376}
377
378void AudioUsbALSA::exitRecordingThread(uint64_t writeVal)
379{
380 LOGD("exitRecordingThread");
381 if (writeVal == SIGNAL_EVENT_KILLTHREAD) {
382 closeRecordingDevices();
383 }
384 mkillRecordingThread = true;
385}
386
387void AudioUsbALSA::closeRecordingDevices(){
388 int err;
389
390 err = closeDevice(mproxyRecordingHandle);
391 if (err) {
392 LOGE("Info: Could not close proxy for recording %p", mproxyRecordingHandle);
393 }
394 err = closeDevice(musbRecordingHandle);
395 if (err) {
396 LOGE("Info: Could not close USB recording device %p", musbRecordingHandle);
397 }
398}
399
400void AudioUsbALSA::closePlaybackDevices(){
401 int err;
402
403 err = closeDevice(mproxyPlaybackHandle);
404 if (err) {
405 LOGE("Info: Could not close proxy %p", mproxyPlaybackHandle);
406 }
407 err = closeDevice(musbPlaybackHandle);
408 if (err) {
409 LOGE("Info: Could not close USB device %p", musbPlaybackHandle);
410 }
411}
412
413void AudioUsbALSA::setkillUsbRecordingThread(bool val){
414 LOGD("setkillUsbRecordingThread");
415 mkillRecordingThread = val;
416}
417
418status_t AudioUsbALSA::setHardwareParams(pcm *txHandle, uint32_t sampleRate, uint32_t channels)
419{
420 LOGD("setHardwareParams");
421 struct snd_pcm_hw_params *params;
422 unsigned long bufferSize, reqBuffSize;
423 unsigned int periodTime, bufferTime;
424 unsigned int requestedRate = sampleRate;
425 int status = 0;
426
427 params = (snd_pcm_hw_params*) calloc(1, sizeof(struct snd_pcm_hw_params));
428 if (!params) {
429 return NO_INIT;
430 }
431
432 param_init(params);
433 param_set_mask(params, SNDRV_PCM_HW_PARAM_ACCESS,
434 SNDRV_PCM_ACCESS_MMAP_INTERLEAVED);
435 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
436 SNDRV_PCM_FORMAT_S16_LE);
437 param_set_mask(params, SNDRV_PCM_HW_PARAM_SUBFORMAT,
438 SNDRV_PCM_SUBFORMAT_STD);
439 LOGV("Setting period size: 768 samplerate:%d, channels: %d",sampleRate, channels);
440 param_set_min(params, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 768);
441 param_set_int(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, 16);
442 param_set_int(params, SNDRV_PCM_HW_PARAM_FRAME_BITS,
443 channels - 1 ? 32 : 16);
444 param_set_int(params, SNDRV_PCM_HW_PARAM_CHANNELS,
445 channels);
446 param_set_int(params, SNDRV_PCM_HW_PARAM_RATE, sampleRate);
447 param_set_hw_refine(txHandle, params);
448
449 if (param_set_hw_params(txHandle, params)) {
450 LOGE("ERROR: cannot set hw params");
451 return NO_INIT;
452 }
453
454 param_dump(params);
455
456 txHandle->period_size = pcm_period_size(params);
457 txHandle->buffer_size = pcm_buffer_size(params);
458 txHandle->period_cnt = txHandle->buffer_size/txHandle->period_size;
459
460 LOGD("setHardwareParams: buffer_size %d, period_size %d, period_cnt %d",
461 txHandle->buffer_size, txHandle->period_size,
462 txHandle->period_cnt);
463
464 return NO_ERROR;
465}
466
467status_t AudioUsbALSA::setSoftwareParams(pcm *pcm)
468{
469 LOGD("setSoftwareParams");
470 struct snd_pcm_sw_params* params;
471
472 unsigned long periodSize = 1024;
473
474 params = (snd_pcm_sw_params*) calloc(1, sizeof(struct snd_pcm_sw_params));
475 if (!params) {
476 LOG_ALWAYS_FATAL("Failed to allocate ALSA software parameters!");
477 return NO_INIT;
478 }
479
480 params->tstamp_mode = SNDRV_PCM_TSTAMP_NONE;
481 params->period_step = 1;
482
483 params->avail_min = (pcm->flags & PCM_MONO) ? pcm->period_size/2 : pcm->period_size/4;
484
485 params->start_threshold = (pcm->flags & PCM_MONO) ? pcm->period_size/2 : pcm->period_size/4;
486 params->stop_threshold = pcm->buffer_size;
487 params->xfer_align = (pcm->flags & PCM_MONO) ? pcm->period_size/2 : pcm->period_size/4;
488 params->silence_size = 0;
489 params->silence_threshold = 0;
490
491 if (param_set_sw_params(pcm, params)) {
492 LOGE("ERROR: cannot set sw params");
493 return NO_INIT;
494 }
495
496 return NO_ERROR;
497}
498
499status_t AudioUsbALSA::closeDevice(pcm *handle)
500{
501 LOGD("closeDevice handle %p", handle);
502 status_t err = NO_ERROR;
503 if (handle) {
504 err = pcm_close(handle);
505 if (err != NO_ERROR) {
506 LOGE("INFO: closeDevice: pcm_close failed with err %d", err);
507 }
508 }
509 handle = NULL;
510 return err;
511}
512
513void AudioUsbALSA::RecordingThreadEntry() {
514 LOGD("Inside RecordingThreadEntry");
515 int nfds = 1;
516 mtimeOutRecording = TIMEOUT_INFINITE;
517 int fd;
518 long frames;
519 static int start = 0;
520 struct snd_xferi x;
521 int filed;
522 unsigned avail, bufsize;
523 int bytes_written;
524 uint32_t sampleRate;
525 uint32_t channels;
526 u_int8_t *srcUsb_addr = NULL;
527 u_int8_t *dstProxy_addr = NULL;
528 int err;
529 const char *fn = "/data/RecordPcm.pcm";
530 filed = open(fn, O_WRONLY | O_CREAT | O_TRUNC | O_APPEND, 0664);
531
532 err = configureUsbDeviceForRecording();
533 if (err) {
534 LOGE("ERROR: Could not configure USB device for recording");
535 closeDevice(musbRecordingHandle);
536 return;
537 } else {
538 LOGD("USB device Configured for recording");
539 }
540
541 pfdUsbRecording[0].fd = musbRecordingHandle->fd; //DEBUG
542 pfdUsbRecording[0].events = POLLIN;
543
544 err = configureProxyDeviceForRecording();
545 if (err) {
546 LOGE("ERROR: Could not configure Proxy for recording");
547 closeDevice(mproxyRecordingHandle);
548 closeDevice(musbRecordingHandle);
549 return;
550 } else {
551 LOGD("Proxy Configured for recording");
552 }
553
554 bufsize = musbRecordingHandle->period_size;
555 pfdProxyRecording[0].fd = mproxyRecordingHandle->fd;
556 pfdProxyRecording[0].events = POLLOUT;
557 frames = (musbRecordingHandle->flags & PCM_MONO) ? (bufsize / 2) : (bufsize / 4);
558 x.frames = (musbRecordingHandle->flags & PCM_MONO) ? (bufsize / 2) : (bufsize / 4);
559
560 /***********************keep reading from usb and writing to proxy******************************************/
561 while (mkillRecordingThread != true) {
562 if (!musbRecordingHandle->running) {
563 if (pcm_prepare(musbRecordingHandle)) {
564 LOGE("ERROR: pcm_prepare failed for usb device for recording");
565 mkillRecordingThread = true;
566 break;;
567 }
568 }
569 if (!mproxyRecordingHandle->running) {
570 if (pcm_prepare(mproxyRecordingHandle)) {
571 LOGE("ERROR: pcm_prepare failed for proxy device for recording");
572 mkillRecordingThread = true;
573 break;;
574 }
575 }
576
577 /********** USB syncing before write **************/
578 if (!musbRecordingHandle->start && !mkillRecordingThread) {
579 err = startDevice(musbRecordingHandle, &mkillRecordingThread);
580 if (err == EPIPE) {
581 continue;
582 } else if (err != NO_ERROR) {
583 mkillRecordingThread = true;
584 break;
585 }
586 }
587 for (;;) {
588 if (!musbRecordingHandle->running) {
589 if (pcm_prepare(musbRecordingHandle)) {
590 LOGE("ERROR: pcm_prepare failed for proxy device for recording");
591 mkillRecordingThread = true;
592 break;
593 }
594 }
595 /* Sync the current Application pointer from the kernel */
596 musbRecordingHandle->sync_ptr->flags = SNDRV_PCM_SYNC_PTR_APPL |
597 SNDRV_PCM_SYNC_PTR_AVAIL_MIN;
598
599 err = syncPtr(musbRecordingHandle, &mkillRecordingThread);
600 if (err == EPIPE) {
601 continue;
602 } else if (err != NO_ERROR) {
603 break;
604 }
605
606 avail = pcm_avail(musbRecordingHandle);
607 if (avail < musbRecordingHandle->sw_p->avail_min) {
608 poll(pfdUsbRecording, nfds, TIMEOUT_INFINITE);
609 continue;
610 } else {
611 break;
612 }
613 }
614 if (mkillRecordingThread) {
615 break;
616 }
617 if (x.frames > avail)
618 frames = avail;
619
620 srcUsb_addr = dst_address(musbRecordingHandle);
621 /**********End USB syncing before write**************/
622
623 /*************Proxy syncing before write ******************/
624
625 for (;;) {
626 if (!mproxyRecordingHandle->running) {
627 if (pcm_prepare(mproxyRecordingHandle)) {
628 LOGE("ERROR: pcm_prepare failed for proxy device for recording");
629 mkillRecordingThread = true;
630 break;
631 }
632 }
633 mproxyRecordingHandle->sync_ptr->flags = SNDRV_PCM_SYNC_PTR_APPL |
634 SNDRV_PCM_SYNC_PTR_AVAIL_MIN;
635
636 err = syncPtr(mproxyRecordingHandle, &mkillRecordingThread);
637 if (err == EPIPE) {
638 continue;
639 } else if (err != NO_ERROR) {
640 break;
641 }
642 avail = pcm_avail(mproxyRecordingHandle);
643 if (avail < mproxyRecordingHandle->sw_p->avail_min) {
644 poll(pfdProxyRecording, nfds, TIMEOUT_INFINITE);
645 continue;
646 } else {
647 break;
648 }
649 }
650 if (mkillRecordingThread) {
651 break;
652 }
653
654 dstProxy_addr = dst_address(mproxyRecordingHandle);
655 memset(dstProxy_addr, 0x0, bufsize);
656
657 /**************End Proxy syncing before write *************/
658
659 memcpy(dstProxy_addr, srcUsb_addr, bufsize );
660
661 /************* sync up after write -- USB *********************/
662 musbRecordingHandle->sync_ptr->c.control.appl_ptr += frames;
663 musbRecordingHandle->sync_ptr->flags = 0;
664 err = syncPtr(musbRecordingHandle, &mkillRecordingThread);
665 if (err == EPIPE) {
666 continue;
667 } else if (err != NO_ERROR) {
668 break;
669 }
670
671 /************* end sync up after write -- USB *********************/
672
673 /**************** sync up after write -- Proxy ************************/
674 mproxyRecordingHandle->sync_ptr->c.control.appl_ptr += frames;
675 mproxyRecordingHandle->sync_ptr->flags = 0;
676
677 err = syncPtr(mproxyRecordingHandle, &mkillRecordingThread);
678 if (err == EPIPE) {
679 continue;
680 } else if (err != NO_ERROR) {
681 break;
682 }
683
684 bytes_written = mproxyRecordingHandle->sync_ptr->c.control.appl_ptr - mproxyRecordingHandle->sync_ptr->s.status.hw_ptr;
685 if ((bytes_written >= mproxyRecordingHandle->sw_p->start_threshold) && (!mproxyRecordingHandle->start)) {
686 if (!mkillPlayBackThread) {
687 err = startDevice(mproxyRecordingHandle, &mkillRecordingThread);
688 if (err == EPIPE) {
689 continue;
690 } else if (err != NO_ERROR) {
691 mkillRecordingThread = true;
692 break;
693 }
694 }
695 }
696 }
697 /*************** End sync up after write -- Proxy *********************/
698 if (mkillRecordingThread) {
699 closeDevice(mproxyRecordingHandle);
700 closeDevice(musbRecordingHandle);
701 }
702 LOGD("Exiting USB Recording thread");
703}
704
705void *AudioUsbALSA::PlaybackThreadWrapper(void *me) {
706 static_cast<AudioUsbALSA *>(me)->PlaybackThreadEntry();
707 return NULL;
708}
709
710void *AudioUsbALSA::RecordingThreadWrapper(void *me) {
711 static_cast<AudioUsbALSA *>(me)->RecordingThreadEntry();
712 return NULL;
713}
714
715status_t AudioUsbALSA::configureUsbDevice(){
716 unsigned flags = 0;
717 int err = NO_ERROR;
718
719 flags = PCM_OUT|PCM_STEREO|PCM_MMAP;
720
721 musbPlaybackHandle = pcm_open(flags, (char *)"hw:1,0");
722 if (!musbPlaybackHandle) {
723 LOGE("ERROR: pcm_open failed for usb playback case");
724 return UNKNOWN_ERROR;
725 }
726
727 if (!pcm_ready(musbPlaybackHandle)) {
728 LOGE("ERROR: pcm_ready failed for usb playback case");
729 return err;
730 }
731
732 err = getPlaybackCap();
733 if (err) {
734 LOGE("ERROR: Could not get playback capabilities from usb device");
735 return UNKNOWN_ERROR;
736 }
737
738 LOGD("Setting hardware params: sampleRate:%d, channels: %d",msampleRatePlayback, mchannelsPlayback);
739 err = setHardwareParams(musbPlaybackHandle, msampleRatePlayback, mchannelsPlayback);
740 if (err != NO_ERROR) {
741 LOGE("ERROR: setHardwareParams failed for usb playback case");
742 return err;
743 }
744
745 err = setSoftwareParams(musbPlaybackHandle);
746 if (err != NO_ERROR) {
747 LOGE("ERROR: setSoftwareParams failed for usb playback case");
748 return err;
749 }
750
751 err = mmap_buffer(musbPlaybackHandle);
752 if (err) {
753 LOGE("ERROR: mmap_buffer failed for usb playback case");
754 return err;
755 }
756
757 err = pcm_prepare(musbPlaybackHandle);
758 if (err) {
759 LOGE("ERROR: pcm_prepare failed for usb playback case");
760 return err;
761 }
762
763 return err;
764}
765
766status_t AudioUsbALSA::configureUsbDeviceForRecording(){
767 unsigned flags = 0;
768 int err = NO_ERROR;
769
770 flags = PCM_IN|PCM_MONO|PCM_MMAP;
771
772 musbRecordingHandle = pcm_open(flags, (char *)"hw:1,0");
773 if (!musbRecordingHandle) {
774 LOGE("ERROR: pcm_open failed for usb recording case");
775 return UNKNOWN_ERROR;
776 }
777
778 if (!pcm_ready(musbRecordingHandle)) {
779 LOGE("ERROR: pcm_ready failed for usb recording case");
780 return err;
781 }
782
783 err = getCaptureCap();
784 if (err) {
785 LOGE("ERROR: Could not get capture capabilities from usb device");
786 return UNKNOWN_ERROR;
787 }
788
789 LOGD("Setting hardwareParams for Usb recording msampleRateCapture %d, mchannelsCapture %d", msampleRateCapture, mchannelsCapture);
790 err = setHardwareParams(musbRecordingHandle, msampleRateCapture, mchannelsCapture);
791 if (err != NO_ERROR) {
792 LOGE("ERROR: setHardwareParams failed for usb recording case");
793 return err;
794 }
795
796 err = setSoftwareParams(musbRecordingHandle);
797 if (err != NO_ERROR) {
798 LOGE("ERROR: setSoftwareParams failed for usb recording case");
799 return err;
800 }
801
802 err = mmap_buffer(musbRecordingHandle);
803 if (err) {
804 LOGE("ERROR: mmap_buffer failed for usb recording case");
805 return err;
806 }
807
808 err = pcm_prepare(musbRecordingHandle);
809 if (err) {
810 LOGE("ERROR: pcm_prepare failed for usb recording case");
811 return err;
812 }
813
814 return err;
815}
816
817status_t AudioUsbALSA::configureProxyDeviceForRecording(){
818 unsigned flags = 0;
819 int err = 0;
820 flags = PCM_OUT|PCM_MONO|PCM_MMAP;
821 mproxyRecordingHandle = pcm_open(flags, (char *)"hw:0,7");
822 if (!mproxyRecordingHandle) {
823 LOGE("ERROR: pcm_open failed for proxy recording case");
824 return UNKNOWN_ERROR;
825 }
826
827 if (!pcm_ready(mproxyRecordingHandle)) {
828 LOGE("ERROR: pcm_ready failed for proxy recording case");
829 return UNKNOWN_ERROR;
830 }
831
832 err = setHardwareParams(mproxyRecordingHandle, msampleRateCapture, mchannelsCapture);
833 if (err != NO_ERROR) {
834 LOGE("ERROR: setHardwareParams failed for proxy recording case");
835 return err;
836 }
837
838 err = setSoftwareParams(mproxyRecordingHandle);
839 if (err != NO_ERROR) {
840 LOGE("ERROR: setSoftwareParams failed for proxy recording case");
841 return err;
842 }
843
844 err = mmap_buffer(mproxyRecordingHandle);
845 if (err != NO_ERROR) {
846 LOGE("ERROR: mmap_buffer failed for proxy recording case");
847 return err;
848 }
849
850 err = pcm_prepare(mproxyRecordingHandle);
851 if (err != NO_ERROR) {
852 LOGE("ERROR: pcm_prepare failed for proxy recording case");
853 return err;
854 }
855
856 return err;
857}
858
859status_t AudioUsbALSA::configureProxyDevice(){
860 unsigned flags = 0;
861 int err = 0;
862 flags = PCM_IN|PCM_STEREO|PCM_MMAP;
863 mproxyPlaybackHandle = pcm_open(flags, (char *)"hw:0,8");
864 if (!mproxyPlaybackHandle) {
865 LOGE("ERROR: pcm_open failed for proxy playback case");
866 return UNKNOWN_ERROR;
867 }
868
869 if (!pcm_ready(mproxyPlaybackHandle)) {
870 LOGE("ERROR: pcm_ready failed for proxy playback case");
871 return err;
872 }
873
874 err = setHardwareParams(mproxyPlaybackHandle, msampleRatePlayback, mchannelsPlayback);
875 if (err != NO_ERROR) {
876 LOGE("ERROR: setHardwareParams failed for proxy playback case");
877 return err;;
878 }
879
880 err = setSoftwareParams(mproxyPlaybackHandle);
881 if (err != NO_ERROR) {
882 LOGE("ERROR: setSoftwareParams failed for proxy playback case");
883 return err;
884 }
885
886 err = mmap_buffer(mproxyPlaybackHandle);
887 if (err != NO_ERROR) {
888 LOGE("ERROR: mmap_buffer failed for proxy playback case");
889 return err;
890 }
891
892 err = pcm_prepare(mproxyPlaybackHandle);
893 if (err != NO_ERROR) {
894 LOGE("ERROR: pcm_prepare failed for proxy playback case");
895 return err;
896 }
897
898 return err;
899}
900
901status_t AudioUsbALSA::startDevice(pcm *handle, bool *killThread) {
902 int err = NO_ERROR;;
903 if (ioctl(handle->fd, SNDRV_PCM_IOCTL_START)) {
904 err = -errno;
905 if (errno == EPIPE) {
906 LOGE("ERROR: SNDRV_PCM_IOCTL_START returned EPIPE for usb recording case");
907 handle->underruns++;
908 handle->running = 0;
909 handle->start = 0;
910 return errno;
911 } else {
912 LOGE("ERROR: SNDRV_PCM_IOCTL_START failed for usb recording case errno:%d", errno);
913 *killThread = true;
914 return errno;
915 }
916 }
917 handle->start = 1;
918 if (handle == musbRecordingHandle) {
919 LOGD("Usb Driver started for recording");
920 } else if (handle == mproxyRecordingHandle) {
921 LOGD("Proxy Driver started for recording");
922 } else if (handle == musbPlaybackHandle) {
923 LOGD("Usb Driver started for playback");
924 } else if (handle == mproxyPlaybackHandle) {
925 LOGD("proxy Driver started for playback");
926 }
927 return NO_ERROR;
928}
929
930status_t AudioUsbALSA::syncPtr(struct pcm *handle, bool *killThread) {
931 int err;
932 err = sync_ptr(handle);
933 if (err == EPIPE) {
934 LOGE("ERROR: Failed in sync_ptr \n");
935 handle->running = 0;
936 handle->underruns++;
937 handle->start = 0;
938 } else if (err == ENODEV) {
939 LOGE("Info: Device not available");
940 } else if (err != NO_ERROR) {
941 LOGE("ERROR: Sync ptr returned %d", err);
942 *killThread = true;
943 }
944 return err;
945}
946
947void AudioUsbALSA::pollForProxyData(){
948 int err_poll = poll(pfdProxyPlayback, mnfdsPlayback, mtimeOut);
949 if (err_poll == 0 ) {
950 LOGD("POLL timedout");
951 mkillPlayBackThread = true;
952 pfdProxyPlayback[0].revents = 0;
953 pfdProxyPlayback[1].revents = 0;
954 return;
955 }
956
957 if (pfdProxyPlayback[1].revents & POLLIN) {
958 LOGD("Signalled from HAL about timeout");
959 uint64_t u;
960 read(mproxypfdPlayback, &u, sizeof(uint64_t));
961 pfdProxyPlayback[1].revents = 0;
962 if (u == SIGNAL_EVENT_KILLTHREAD) {
963 LOGD("kill thread event");
964 mkillPlayBackThread = true;
965 pfdProxyPlayback[0].revents = 0;
966 pfdProxyPlayback[1].revents = 0;
967 return;
968 } else if (u == SIGNAL_EVENT_TIMEOUT) {
969 LOGD("Setting timeout for 3 sec");
970 mtimeOut = POLL_TIMEOUT;
971 }
972 } else if (pfdProxyPlayback[1].revents & POLLERR || pfdProxyPlayback[1].revents & POLLHUP ||
973 pfdProxyPlayback[1].revents & POLLNVAL) {
974 LOGE("Info: proxy throwing error from location 1");
975 mkillPlayBackThread = true;
976 pfdProxyPlayback[0].revents = 0;
977 pfdProxyPlayback[1].revents = 0;
978 return;
979 }
980
981 if (pfdProxyPlayback[0].revents & POLLERR || pfdProxyPlayback[0].revents & POLLHUP ||
982 pfdProxyPlayback[0].revents & POLLNVAL) {
983 LOGE("Info: proxy throwing error");
984 mkillPlayBackThread = true;
985 pfdProxyPlayback[0].revents = 0;
986 pfdProxyPlayback[1].revents = 0;
987 }
988}
989
990void AudioUsbALSA::pollForUsbData(){
991 int err_poll = poll(pfdUsbPlayback, mnfdsPlayback, mtimeOut);
992 if (err_poll == 0 ) {
993 LOGD("POLL timedout");
994 mkillPlayBackThread = true;
995 pfdUsbPlayback[0].revents = 0;
996 pfdUsbPlayback[1].revents = 0;
997 return;
998 }
999
1000 if (pfdUsbPlayback[1].revents & POLLIN) {
1001 LOGD("Info: Signalled from HAL about an event");
1002 uint64_t u;
1003 read(musbpfdPlayback, &u, sizeof(uint64_t));
1004 pfdUsbPlayback[0].revents = 0;
1005 pfdUsbPlayback[1].revents = 0;
1006 if (u == SIGNAL_EVENT_KILLTHREAD) {
1007 LOGD("kill thread");
1008 mkillPlayBackThread = true;
1009 return;
1010 } else if (u == SIGNAL_EVENT_TIMEOUT) {
1011 LOGD("Setting timeout for 3 sec");
1012 mtimeOut = POLL_TIMEOUT;
1013 }
1014 } else if (pfdUsbPlayback[1].revents & POLLERR || pfdUsbPlayback[1].revents & POLLHUP ||
1015 pfdUsbPlayback[1].revents & POLLNVAL) {
1016 LOGE("Info: usb throwing error from location 1");
1017 mkillPlayBackThread = true;
1018 pfdUsbPlayback[0].revents = 0;
1019 pfdUsbPlayback[1].revents = 0;
1020 return;
1021 }
1022
1023 if (pfdUsbPlayback[0].revents & POLLERR || pfdProxyPlayback[0].revents & POLLHUP ||
1024 pfdUsbPlayback[0].revents & POLLNVAL) {
1025 LOGE("Info: usb throwing error");
1026 mkillPlayBackThread = true;
1027 pfdUsbPlayback[0].revents = 0;
1028 return;
1029 }
1030}
1031
1032void AudioUsbALSA::PlaybackThreadEntry() {
1033 LOGD("PlaybackThreadEntry");
1034 mnfdsPlayback = 2;
1035 mtimeOut = TIMEOUT_INFINITE;
1036 long frames;
1037 static int fd;
1038 struct snd_xferi x;
1039 int bytes_written;
1040 unsigned avail, xfer, bufsize;
1041 uint32_t sampleRate;
1042 uint32_t channels;
1043 unsigned int tmp;
1044 int numOfBytesWritten;
1045 int err;
1046 int filed;
1047 const char *fn = "/data/test.pcm";
1048 mdstUsb_addr = NULL;
1049 msrcProxy_addr = NULL;
1050
1051 filed = open(fn, O_WRONLY | O_CREAT | O_TRUNC | O_APPEND, 0664);
1052 err = configureUsbDevice();
1053 if (err) {
1054 LOGE("ERROR: configureUsbDevice failed, returning");
1055 closeDevice(musbPlaybackHandle);
1056 return;
1057 } else {
1058 LOGD("USB Configured for playback");
1059 }
1060
1061 if (!mkillPlayBackThread) {
1062 pfdUsbPlayback[0].fd = musbPlaybackHandle->fd;
1063 pfdUsbPlayback[0].events = POLLOUT;
1064 musbpfdPlayback = eventfd(0,0);
1065 pfdUsbPlayback[1].fd = musbpfdPlayback;
1066 pfdUsbPlayback[1].events = (POLLIN | POLLOUT | POLLERR | POLLNVAL | POLLHUP);
1067 }
1068
1069 err = configureProxyDevice();
1070 if (err) {
1071 LOGE("ERROR: Could not configure Proxy, returning");
1072 closeDevice(musbPlaybackHandle);
1073 closeDevice(mproxyPlaybackHandle);
1074 return;
1075 } else {
1076 LOGD("Proxy Configured for playback");
1077 }
1078
1079 bufsize = mproxyPlaybackHandle->period_size;
1080
1081 if (!mkillPlayBackThread) {
1082 pfdProxyPlayback[0].fd = mproxyPlaybackHandle->fd;
1083 pfdProxyPlayback[0].events = (POLLIN); // | POLLERR | POLLNVAL);
1084 mproxypfdPlayback = eventfd(0,0);
1085 pfdProxyPlayback[1].fd = mproxypfdPlayback;
1086 pfdProxyPlayback[1].events = (POLLIN | POLLOUT| POLLERR | POLLNVAL);
1087 }
1088
1089 frames = (mproxyPlaybackHandle->flags & PCM_MONO) ? (bufsize / 2) : (bufsize / 4);
1090 x.frames = (mproxyPlaybackHandle->flags & PCM_MONO) ? (bufsize / 2) : (bufsize / 4);
1091
1092 /***********************keep reading from proxy and writing to USB******************************************/
1093 while (mkillPlayBackThread != true) {
1094 if (!mproxyPlaybackHandle->running) {
1095 if (pcm_prepare(mproxyPlaybackHandle)) {
1096 LOGE("ERROR: pcm_prepare failed for proxy");
1097 mkillPlayBackThread = true;
1098 break;
1099 }
1100 }
1101 if (!musbPlaybackHandle->running) {
1102 if (pcm_prepare(musbPlaybackHandle)) {
1103 LOGE("ERROR: pcm_prepare failed for usb");
1104 mkillPlayBackThread = true;
1105 break;
1106 }
1107 }
1108
1109 /********** Proxy syncing before write **************/
1110 if (!mkillPlayBackThread && (!mproxyPlaybackHandle->start)) {
1111 err = startDevice(mproxyPlaybackHandle, &mkillPlayBackThread);
1112 if (err == EPIPE) {
1113 continue;
1114 } else if (err != NO_ERROR) {
1115 mkillPlayBackThread = true;
1116 break;
1117 }
1118 }
1119
1120 for (;;) {
1121 if (!mproxyPlaybackHandle->running) {
1122 if (pcm_prepare(mproxyPlaybackHandle)) {
1123 LOGE("ERROR: pcm_prepare failed for proxy");
1124 mkillPlayBackThread = true;
1125 break;
1126 }
1127 }
1128 /* Sync the current Application pointer from the kernel */
1129 mproxyPlaybackHandle->sync_ptr->flags = SNDRV_PCM_SYNC_PTR_APPL |
1130 SNDRV_PCM_SYNC_PTR_AVAIL_MIN;
1131
1132 if (mtimeOut == TIMEOUT_INFINITE && !mkillPlayBackThread) {
1133 err = syncPtr(mproxyPlaybackHandle, &mkillPlayBackThread);
1134 if (err == EPIPE) {
1135 continue;
1136 } else if (err != NO_ERROR) {
1137 break;
1138 }
1139 avail = pcm_avail(mproxyPlaybackHandle);
1140 }
1141 if (avail < mproxyPlaybackHandle->sw_p->avail_min && !mkillPlayBackThread) {
1142 pollForProxyData();
1143 //if polling returned some error
1144 if (!mkillPlayBackThread) {
1145 continue;
1146 } else {
1147 break;
1148 }
1149 } else { //Got some data or mkillPlayBackThread is true
1150 break;
1151 }
1152 }
1153 if (mkillPlayBackThread) {
1154 break;
1155 }
1156
1157 if (x.frames > avail)
1158 frames = avail;
1159
1160 if (!mkillPlayBackThread) {
1161 msrcProxy_addr = dst_address(mproxyPlaybackHandle);
1162 /**********End Proxy syncing before write**************/
1163 }
1164
1165 for (;;) {
1166 if (!musbPlaybackHandle->running) {
1167 if (pcm_prepare(musbPlaybackHandle)) {
1168 LOGE("ERROR: pcm_prepare failed for usb");
1169 mkillPlayBackThread = true;
1170 break;
1171 }
1172 }
1173 /*************USB syncing before write ******************/
1174 musbPlaybackHandle->sync_ptr->flags = SNDRV_PCM_SYNC_PTR_APPL |
1175 SNDRV_PCM_SYNC_PTR_AVAIL_MIN;
1176 if (mtimeOut == TIMEOUT_INFINITE && !mkillPlayBackThread) {
1177 err = syncPtr(musbPlaybackHandle, &mkillPlayBackThread);
1178 if (err == EPIPE) {
1179 continue;
1180 } else if (err != NO_ERROR) {
1181 break;
1182 }
1183 avail = pcm_avail(musbPlaybackHandle);
1184 //LOGV("Avail USB is: %d", avail);
1185 }
1186
1187 if (avail < musbPlaybackHandle->sw_p->avail_min && !mkillPlayBackThread) {
1188 pollForUsbData();
1189 if (!mkillPlayBackThread) {
1190 continue;
1191 } else {
1192 break;
1193 }
1194 } else {
1195 break;
1196 }
1197 }
1198 if (mkillPlayBackThread) {
1199 break;
1200 }
1201
1202 if (!mkillPlayBackThread) {
1203 mdstUsb_addr = dst_address(musbPlaybackHandle);
1204 memset(mdstUsb_addr, 0x0, bufsize);
1205
1206 /**************End USB syncing before write *************/
1207
1208 memcpy(mdstUsb_addr, msrcProxy_addr, bufsize );
1209
1210 /************* sync up after write -- Proxy *********************/
1211 x.frames -= frames;
1212 mproxyPlaybackHandle->sync_ptr->c.control.appl_ptr += frames;
1213 mproxyPlaybackHandle->sync_ptr->flags = 0;
1214 }
1215
1216 if (!mkillPlayBackThread) {
1217 err = syncPtr(mproxyPlaybackHandle, &mkillPlayBackThread);
1218 if (err == EPIPE) {
1219 continue;
1220 } else if (err != NO_ERROR) {
1221 break;
1222 }
1223 }
1224 /************* end sync up after write -- Proxy *********************/
1225
1226
1227 /**************** sync up after write -- USB ************************/
1228 musbPlaybackHandle->sync_ptr->c.control.appl_ptr += frames;
1229 musbPlaybackHandle->sync_ptr->flags = 0;
1230 if (!mkillPlayBackThread) {
1231 err = syncPtr(musbPlaybackHandle, &mkillPlayBackThread);
1232 if (err == EPIPE) {
1233 continue;
1234 } else if (err != NO_ERROR) {
1235 break;
1236 }
1237 }
1238
1239 bytes_written = musbPlaybackHandle->sync_ptr->c.control.appl_ptr - musbPlaybackHandle->sync_ptr->s.status.hw_ptr;
1240 if ((bytes_written >= musbPlaybackHandle->sw_p->start_threshold) && (!musbPlaybackHandle->start)) {
1241 if (!mkillPlayBackThread) {
1242 err = startDevice(musbPlaybackHandle, &mkillPlayBackThread);
1243 if (err == EPIPE) {
1244 continue;
1245 } else if (err != NO_ERROR) {
1246 mkillPlayBackThread = true;
1247 break;
1248 }
1249 }
1250 }
1251 /*************** End sync up after write -- USB *********************/
1252 }
1253 if (mkillPlayBackThread) {
1254 mproxypfdPlayback = -1;
1255 musbpfdPlayback = -1;
1256 closeDevice(mproxyPlaybackHandle);
1257 closeDevice(musbPlaybackHandle);
1258 }
1259 LOGD("Exiting USB Playback Thread");
1260}
1261
1262void AudioUsbALSA::startPlayback()
1263{
1264 mkillPlayBackThread = false;
1265 LOGD("Creating USB Playback Thread");
1266 pthread_create(&mPlaybackUsb, NULL, PlaybackThreadWrapper, this);
1267}
1268
1269void AudioUsbALSA::startRecording()
1270{
1271 //create Thread
1272 mkillRecordingThread = false;
1273 LOGV("Creating USB recording Thread");
1274 pthread_create(&mRecordingUsb, NULL, RecordingThreadWrapper, this);
1275}
1276}