1/* 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
55#define USB_PERIOD_SIZE 2048
56#define PROXY_PERIOD_SIZE 3072
57
58namespace android_audio_legacy
59{
60AudioUsbALSA::AudioUsbALSA()
61{
62    mproxypfdPlayback = -1;
63    musbpfdPlayback = -1;
64    mkillPlayBackThread = false;
65    mkillRecordingThread = false;
66}
67
68AudioUsbALSA::~AudioUsbALSA()
69{
70    mkillPlayBackThread = true;
71    mkillRecordingThread = true;
72}
73
74
75int AudioUsbALSA::getnumOfRates(char *ratesStr){
76    int i, size = 0;
77    char *nextSRString, *temp_ptr;
78    nextSRString = strtok_r(ratesStr, " ,", &temp_ptr);
79    if (nextSRString == NULL) {
80        ALOGE("ERROR: getnumOfRates: could not find rates string");
81        return NULL;
82    }
83    for (i = 1; nextSRString != NULL; i++) {
84        size ++;
85        nextSRString = strtok_r(NULL, " ,.-", &temp_ptr);
86    }
87    return size;
88}
89
90
91status_t AudioUsbALSA::getCap(char * type, int &channels, int &sampleRate)
92{
93    ALOGD("getCap for %s",type);
94    long unsigned fileSize;
95    FILE *fp;
96    char *buffer;
97    int err = 1;
98    int size = 0;
99    int fd, i, lchannelsPlayback;
100    char *read_buf, *str_start, *channel_start, *ratesStr, *ratesStrForVal,
101    *ratesStrStart, *chString, *nextSRStr, *test, *nextSRString, *temp_ptr;
102    struct stat st;
103    memset(&st, 0x0, sizeof(struct stat));
104    sampleRate = 0;
105    fd = open(PATH, O_RDONLY);
106    if (fd <0) {
107        ALOGE("ERROR: failed to open config file %s error: %d\n", PATH, errno);
108        close(fd);
109        return UNKNOWN_ERROR;
110    }
111
112    if (fstat(fd, &st) < 0) {
113        ALOGE("ERROR: failed to stat %s error %d\n", PATH, errno);
114        close(fd);
115        return UNKNOWN_ERROR;
116    }
117
118    fileSize = st.st_size;
119
120    read_buf = (char *)malloc(BUFFSIZE);
121    memset(read_buf, 0x0, BUFFSIZE);
122    err = read(fd, read_buf, BUFFSIZE);
123    str_start = strstr(read_buf, type);
124    if (str_start == NULL) {
125        ALOGE("ERROR:%s section not found in usb config file", type);
126        close(fd);
127        free(read_buf);
128        return UNKNOWN_ERROR;
129    }
130
131    channel_start = strstr(str_start, "Channels:");
132    if (channel_start == NULL) {
133        ALOGE("ERROR: Could not find Channels information");
134        close(fd);
135        free(read_buf);
136        return UNKNOWN_ERROR;
137    }
138    channel_start = strstr(channel_start, " ");
139    if (channel_start == NULL) {
140        ALOGE("ERROR: Channel section not found in usb config file");
141        close(fd);
142        free(read_buf);
143        return UNKNOWN_ERROR;
144    }
145
146    lchannelsPlayback = atoi(channel_start);
147    if (lchannelsPlayback == 1) {
148        channels = 1;
149    } else {
150        channels = 2;
151    }
152    ALOGD("channels supported by device: %d", lchannelsPlayback);
153    ratesStrStart = strstr(str_start, "Rates:");
154    if (ratesStrStart == NULL) {
155        ALOGE("ERROR: Cant find rates information");
156        close(fd);
157        free(read_buf);
158        return UNKNOWN_ERROR;
159    }
160
161    ratesStrStart = strstr(ratesStrStart, " ");
162    if (ratesStrStart == NULL) {
163        ALOGE("ERROR: Channel section not found in usb config file");
164        close(fd);
165        free(read_buf);
166        return UNKNOWN_ERROR;
167    }
168
169    //copy to ratesStr, current line.
170    char *target = strchr(ratesStrStart, '\n');
171    if (target == NULL) {
172        ALOGE("ERROR: end of line not found");
173        close(fd);
174        free(read_buf);
175        return UNKNOWN_ERROR;
176    }
177    size = target - ratesStrStart;
178    ratesStr = (char *)malloc(size + 1) ;
179    ratesStrForVal = (char *)malloc(size + 1) ;
180    memcpy(ratesStr, ratesStrStart, size);
181    memcpy(ratesStrForVal, ratesStrStart, size);
182    ratesStr[size] = '\0';
183    ratesStrForVal[size] = '\0';
184
185    size = getnumOfRates(ratesStr);
186    if (!size) {
187        ALOGE("ERROR: Could not get rate size, returning");
188        close(fd);
189        free(ratesStrForVal);
190        free(ratesStr);
191        free(read_buf);
192        return UNKNOWN_ERROR;
193    }
194
195    //populate playback rates array
196    int ratesSupported[size];
197    nextSRString = strtok_r(ratesStrForVal, " ,", &temp_ptr);
198    if (nextSRString == NULL) {
199        ALOGE("ERROR: Could not get first rate val");
200        close(fd);
201        free(ratesStrForVal);
202        free(ratesStr);
203        free(read_buf);
204        return UNKNOWN_ERROR;
205    }
206
207    ratesSupported[0] = atoi(nextSRString);
208    for (i = 1; i<size; i++) {
209        nextSRString = strtok_r(NULL, " ,.-", &temp_ptr);
210        ratesSupported[i] = atoi(nextSRString);
211        ALOGV("ratesSupported[%d] for playback: %d",i, ratesSupported[i]);
212    }
213
214    for (i = 0; i<=size; i++) {
215        if (ratesSupported[i] <= 48000) {
216            sampleRate = ratesSupported[i];
217            break;
218        }
219    }
220    ALOGD("sampleRate: %d", sampleRate);
221
222    close(fd);
223    free(ratesStrForVal);
224    free(ratesStr);
225    free(read_buf);
226    ratesStrForVal = NULL;
227    ratesStr = NULL;
228    read_buf = NULL;
229    return NO_ERROR;
230}
231
232void AudioUsbALSA::exitPlaybackThread(uint64_t writeVal)
233{
234    ALOGD("exitPlaybackThread, mproxypfdPlayback: %d", mproxypfdPlayback);
235    if (writeVal == SIGNAL_EVENT_KILLTHREAD) {
236        int err;
237
238        err = closeDevice(mproxyPlaybackHandle);
239        if (err) {
240            ALOGE("Info: Could not close proxy %p", mproxyPlaybackHandle);
241        }
242        err = closeDevice(musbPlaybackHandle);
243        if (err) {
244            ALOGE("Info: Could not close USB device %p", musbPlaybackHandle);
245        }
246    }
247    if ((mproxypfdPlayback != -1) && (musbpfdPlayback != -1)) {
248        write(mproxypfdPlayback, &writeVal, sizeof(uint64_t));
249        write(musbpfdPlayback, &writeVal, sizeof(uint64_t));
250        mkillPlayBackThread = true;
251        pthread_join(mPlaybackUsb,NULL);
252    }
253}
254
255void AudioUsbALSA::exitRecordingThread(uint64_t writeVal)
256{
257    ALOGD("exitRecordingThread");
258    if (writeVal == SIGNAL_EVENT_KILLTHREAD) {
259        int err;
260
261        err = closeDevice(mproxyRecordingHandle);
262        if (err) {
263            ALOGE("Info: Could not close proxy for recording %p", mproxyRecordingHandle);
264        }
265        err = closeDevice(musbRecordingHandle);
266        if (err) {
267            ALOGE("Info: Could not close USB recording device %p", musbRecordingHandle);
268        }
269    }
270    mkillRecordingThread = true;
271}
272
273void AudioUsbALSA::setkillUsbRecordingThread(bool val){
274    ALOGD("setkillUsbRecordingThread");
275    mkillRecordingThread = val;
276}
277
278status_t AudioUsbALSA::setHardwareParams(pcm *txHandle, uint32_t sampleRate, uint32_t channels, int periodBytes)
279{
280    ALOGD("setHardwareParams");
281    struct snd_pcm_hw_params *params;
282    unsigned long bufferSize, reqBuffSize;
283    unsigned int periodTime, bufferTime;
284    unsigned int requestedRate = sampleRate;
285    int status = 0;
286
287    params = (snd_pcm_hw_params*) calloc(1, sizeof(struct snd_pcm_hw_params));
288    if (!params) {
289        return NO_INIT;
290    }
291
292    param_init(params);
293    param_set_mask(params, SNDRV_PCM_HW_PARAM_ACCESS,
294                   SNDRV_PCM_ACCESS_MMAP_INTERLEAVED);
295    param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
296                   SNDRV_PCM_FORMAT_S16_LE);
297    param_set_mask(params, SNDRV_PCM_HW_PARAM_SUBFORMAT,
298                   SNDRV_PCM_SUBFORMAT_STD);
299    ALOGV("Setting period size:%d samplerate:%d, channels: %d",periodBytes,sampleRate, channels);
300    param_set_min(params, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, periodBytes);
301    param_set_int(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, 16);
302    param_set_int(params, SNDRV_PCM_HW_PARAM_FRAME_BITS,
303                  channels - 1 ? 32 : 16);
304    param_set_int(params, SNDRV_PCM_HW_PARAM_CHANNELS,
305                  channels);
306    param_set_int(params, SNDRV_PCM_HW_PARAM_RATE, sampleRate);
307    param_set_hw_refine(txHandle, params);
308
309    if (param_set_hw_params(txHandle, params)) {
310        ALOGE("ERROR: cannot set hw params");
311        return NO_INIT;
312    }
313
314    param_dump(params);
315
316    txHandle->period_size = pcm_period_size(params);
317    txHandle->buffer_size = pcm_buffer_size(params);
318    txHandle->period_cnt = txHandle->buffer_size/txHandle->period_size;
319
320    ALOGD("setHardwareParams: buffer_size %d, period_size %d, period_cnt %d",
321         txHandle->buffer_size, txHandle->period_size,
322         txHandle->period_cnt);
323
324    return NO_ERROR;
325}
326
327status_t AudioUsbALSA::setSoftwareParams(pcm *pcm, bool playback)
328{
329    ALOGD("setSoftwareParams");
330    struct snd_pcm_sw_params* params;
331
332    params = (snd_pcm_sw_params*) calloc(1, sizeof(struct snd_pcm_sw_params));
333    if (!params) {
334        LOG_ALWAYS_FATAL("Failed to allocate ALSA software parameters!");
335        return NO_INIT;
336    }
337
338    params->tstamp_mode = SNDRV_PCM_TSTAMP_NONE;
339    params->period_step = 1;
340
341    params->avail_min = (pcm->flags & PCM_MONO) ? pcm->period_size/2 : pcm->period_size/4;
342
343    if (playback) {
344        params->start_threshold = (pcm->flags & PCM_MONO) ? pcm->period_size*8 : pcm->period_size*4;
345        params->xfer_align = (pcm->flags & PCM_MONO) ? pcm->period_size*8 : pcm->period_size*4;
346    } else {
347        params->start_threshold = (pcm->flags & PCM_MONO) ? pcm->period_size/2 : pcm->period_size/4;
348        params->xfer_align = (pcm->flags & PCM_MONO) ? pcm->period_size/2 : pcm->period_size/4;
349    }
350    params->stop_threshold = pcm->buffer_size;
351
352    params->xfer_align = (pcm->flags & PCM_MONO) ? pcm->period_size/2 : pcm->period_size/4;
353    params->silence_size = 0;
354    params->silence_threshold = 0;
355
356    if (param_set_sw_params(pcm, params)) {
357        ALOGE("ERROR: cannot set sw params");
358        return NO_INIT;
359    }
360
361    return NO_ERROR;
362}
363
364status_t AudioUsbALSA::closeDevice(pcm *handle)
365{
366    ALOGD("closeDevice handle %p", handle);
367    status_t err = NO_ERROR;
368    if (handle) {
369        err = pcm_close(handle);
370        if (err != NO_ERROR) {
371            ALOGE("INFO: closeDevice: pcm_close failed with err %d", err);
372        }
373    }
374    handle = NULL;
375    return err;
376}
377
378void AudioUsbALSA::RecordingThreadEntry() {
379    ALOGD("Inside RecordingThreadEntry");
380    int nfds = 1;
381    mtimeOutRecording = TIMEOUT_INFINITE;
382    int fd;
383    long frames;
384    static int start = 0;
385    struct snd_xferi x;
386    int filed;
387    unsigned avail, bufsize;
388    int bytes_written;
389    uint32_t sampleRate;
390    uint32_t channels;
391    u_int8_t *srcUsb_addr = NULL;
392    u_int8_t *dstProxy_addr = NULL;
393    int err;
394    const char *fn = "/data/RecordPcm.pcm";
395    filed = open(fn, O_WRONLY | O_CREAT | O_TRUNC | O_APPEND, 0664);
396
397    err = getCap((char *)"Capture:", mchannelsCapture, msampleRateCapture);
398    if (err) {
399        ALOGE("ERROR: Could not get capture capabilities from usb device");
400        return;
401    }
402    int channelFlag = PCM_MONO;
403    if (mchannelsCapture >= 2) {
404        channelFlag = PCM_STEREO;
405    }
406
407    musbRecordingHandle = configureDevice(PCM_IN|channelFlag|PCM_MMAP, (char *)"hw:1,0",
408                                         msampleRateCapture, mchannelsCapture,768,false);
409    if (!musbRecordingHandle) {
410        ALOGE("ERROR: Could not configure USB device for recording");
411        return;
412    } else {
413        ALOGD("USB device Configured for recording");
414    }
415
416    pfdUsbRecording[0].fd = musbRecordingHandle->fd;                           //DEBUG
417    pfdUsbRecording[0].events = POLLIN;
418
419    mproxyRecordingHandle = configureDevice(PCM_OUT|channelFlag|PCM_MMAP, (char *)"hw:0,7",
420                                            msampleRateCapture, mchannelsCapture,768,false);
421    if (!mproxyRecordingHandle) {
422        ALOGE("ERROR: Could not configure Proxy for recording");
423        closeDevice(musbRecordingHandle);
424        return;
425    } else {
426        ALOGD("Proxy Configured for recording");
427    }
428
429    bufsize = musbRecordingHandle->period_size;
430    pfdProxyRecording[0].fd = mproxyRecordingHandle->fd;
431    pfdProxyRecording[0].events = POLLOUT;
432    frames = (musbRecordingHandle->flags & PCM_MONO) ? (bufsize / 2) : (bufsize / 4);
433    x.frames = (musbRecordingHandle->flags & PCM_MONO) ? (bufsize / 2) : (bufsize / 4);
434
435    /***********************keep reading from usb and writing to proxy******************************************/
436    while (mkillRecordingThread != true) {
437        if (!musbRecordingHandle->running) {
438            if (pcm_prepare(musbRecordingHandle)) {
439                ALOGE("ERROR: pcm_prepare failed for usb device for recording");
440                mkillRecordingThread = true;
441                break;;
442            }
443        }
444        if (!mproxyRecordingHandle->running) {
445            if (pcm_prepare(mproxyRecordingHandle)) {
446                ALOGE("ERROR: pcm_prepare failed for proxy device for recording");
447                mkillRecordingThread = true;
448                break;;
449            }
450        }
451
452        /********** USB syncing before write **************/
453        if (!musbRecordingHandle->start && !mkillRecordingThread) {
454            err = startDevice(musbRecordingHandle, &mkillRecordingThread);
455            if (err == EPIPE) {
456                continue;
457            } else if (err != NO_ERROR) {
458                mkillRecordingThread = true;
459                break;
460            }
461        }
462        for (;;) {
463            if (!musbRecordingHandle->running) {
464                if (pcm_prepare(musbRecordingHandle)) {
465                    ALOGE("ERROR: pcm_prepare failed for proxy device for recording");
466                    mkillRecordingThread = true;
467                    break;
468                }
469            }
470            /* Sync the current Application pointer from the kernel */
471            musbRecordingHandle->sync_ptr->flags = SNDRV_PCM_SYNC_PTR_APPL |
472                                                   SNDRV_PCM_SYNC_PTR_AVAIL_MIN;
473
474            err = syncPtr(musbRecordingHandle, &mkillRecordingThread);
475            if (err == EPIPE) {
476                continue;
477            } else if (err != NO_ERROR) {
478                break;
479            }
480
481            avail = pcm_avail(musbRecordingHandle);
482            if (avail < musbRecordingHandle->sw_p->avail_min) {
483                poll(pfdUsbRecording, nfds, TIMEOUT_INFINITE);
484                continue;
485            } else {
486                break;
487            }
488        }
489        if (mkillRecordingThread) {
490            break;
491        }
492        if (x.frames > avail)
493            frames = avail;
494
495        srcUsb_addr = dst_address(musbRecordingHandle);
496        /**********End USB syncing before write**************/
497
498        /*************Proxy syncing before write ******************/
499
500        for (;;) {
501            if (!mproxyRecordingHandle->running) {
502                if (pcm_prepare(mproxyRecordingHandle)) {
503                    ALOGE("ERROR: pcm_prepare failed for proxy device for recording");
504                    mkillRecordingThread = true;
505                    break;
506                }
507            }
508            mproxyRecordingHandle->sync_ptr->flags = SNDRV_PCM_SYNC_PTR_APPL |
509                                                     SNDRV_PCM_SYNC_PTR_AVAIL_MIN;
510
511            err = syncPtr(mproxyRecordingHandle, &mkillRecordingThread);
512            if (err == EPIPE) {
513                continue;
514            } else if (err != NO_ERROR) {
515                break;
516            }
517            avail = pcm_avail(mproxyRecordingHandle);
518            if (avail < mproxyRecordingHandle->sw_p->avail_min) {
519                poll(pfdProxyRecording, nfds, TIMEOUT_INFINITE);
520                continue;
521            } else {
522                break;
523            }
524        }
525        if (mkillRecordingThread) {
526            break;
527        }
528
529        dstProxy_addr = dst_address(mproxyRecordingHandle);
530        memset(dstProxy_addr, 0x0, bufsize);
531
532        /**************End Proxy syncing before write *************/
533
534        memcpy(dstProxy_addr, srcUsb_addr, bufsize );
535
536        /************* sync up after write -- USB  *********************/
537        musbRecordingHandle->sync_ptr->c.control.appl_ptr += frames;
538        musbRecordingHandle->sync_ptr->flags = 0;
539        err = syncPtr(musbRecordingHandle, &mkillRecordingThread);
540        if (err == EPIPE) {
541            continue;
542        } else if (err != NO_ERROR) {
543            break;
544        }
545
546        /************* end sync up after write -- USB *********************/
547
548        /**************** sync up after write -- Proxy  ************************/
549        mproxyRecordingHandle->sync_ptr->c.control.appl_ptr += frames;
550        mproxyRecordingHandle->sync_ptr->flags = 0;
551
552        err = syncPtr(mproxyRecordingHandle, &mkillRecordingThread);
553        if (err == EPIPE) {
554            continue;
555        } else if (err != NO_ERROR) {
556            break;
557        }
558
559        bytes_written = mproxyRecordingHandle->sync_ptr->c.control.appl_ptr - mproxyRecordingHandle->sync_ptr->s.status.hw_ptr;
560        if ((bytes_written >= mproxyRecordingHandle->sw_p->start_threshold) && (!mproxyRecordingHandle->start)) {
561            if (!mkillPlayBackThread) {
562                err = startDevice(mproxyRecordingHandle, &mkillRecordingThread);
563                if (err == EPIPE) {
564                    continue;
565                } else if (err != NO_ERROR) {
566                    mkillRecordingThread = true;
567                    break;
568                }
569            }
570        }
571    }
572    /***************  End sync up after write -- Proxy *********************/
573    if (mkillRecordingThread) {
574        closeDevice(mproxyRecordingHandle);
575        closeDevice(musbRecordingHandle);
576    }
577    ALOGD("Exiting USB Recording thread");
578}
579
580void *AudioUsbALSA::PlaybackThreadWrapper(void *me) {
581    static_cast<AudioUsbALSA *>(me)->PlaybackThreadEntry();
582    return NULL;
583}
584
585void *AudioUsbALSA::RecordingThreadWrapper(void *me) {
586    static_cast<AudioUsbALSA *>(me)->RecordingThreadEntry();
587    return NULL;
588}
589
590struct pcm * AudioUsbALSA::configureDevice(unsigned flags, char* hw, int sampleRate, int channelCount, int periodSize, bool playback){
591    int err = NO_ERROR;
592    struct pcm * handle = NULL;
593    handle = pcm_open(flags, hw);
594    if (!handle || handle->fd < 0) {
595        ALOGE("ERROR: pcm_open failed");
596        return NULL;
597    }
598
599    if (!pcm_ready(handle)) {
600        ALOGE("ERROR: pcm_ready failed");
601        closeDevice(handle);
602        return NULL;
603    }
604
605    ALOGD("Setting hardware params: sampleRate:%d, channels: %d",sampleRate, channelCount);
606    err = setHardwareParams(handle, sampleRate, channelCount,periodSize);
607    if (err != NO_ERROR) {
608        ALOGE("ERROR: setHardwareParams failed");
609        closeDevice(handle);
610        return NULL;
611    }
612
613    err = setSoftwareParams(handle, playback);
614    if (err != NO_ERROR) {
615        ALOGE("ERROR: setSoftwareParams failed");
616        closeDevice(handle);
617        return NULL;
618    }
619
620    err = mmap_buffer(handle);
621    if (err) {
622        ALOGE("ERROR: mmap_buffer failed");
623        closeDevice(handle);
624        return NULL;
625    }
626
627    err = pcm_prepare(handle);
628    if (err) {
629        ALOGE("ERROR: pcm_prepare failed");
630        closeDevice(handle);
631        return NULL;
632    }
633
634    return handle;
635}
636
637status_t AudioUsbALSA::startDevice(pcm *handle, bool *killThread) {
638    int err = NO_ERROR;;
639    if (ioctl(handle->fd, SNDRV_PCM_IOCTL_START)) {
640        err = -errno;
641        if (errno == EPIPE) {
642            ALOGE("ERROR: SNDRV_PCM_IOCTL_START returned EPIPE for usb recording case");
643            handle->underruns++;
644            handle->running = 0;
645            handle->start = 0;
646            return errno;
647        } else {
648            ALOGE("ERROR: SNDRV_PCM_IOCTL_START failed for usb recording case errno:%d", errno);
649            *killThread = true;
650            return errno;
651        }
652    }
653    handle->start = 1;
654    if (handle == musbRecordingHandle) {
655        ALOGD("Usb Driver started for recording");
656    } else if (handle == mproxyRecordingHandle) {
657        ALOGD("Proxy Driver started for recording");
658    } else if (handle == musbPlaybackHandle) {
659        ALOGD("Usb Driver started for playback");
660    } else if (handle == mproxyPlaybackHandle) {
661        ALOGD("proxy Driver started for playback");
662    }
663    return NO_ERROR;
664}
665
666status_t AudioUsbALSA::syncPtr(struct pcm *handle, bool *killThread) {
667    int err;
668    err = sync_ptr(handle);
669    if (err == EPIPE) {
670        ALOGE("ERROR: Failed in sync_ptr \n");
671        handle->running = 0;
672        handle->underruns++;
673        handle->start = 0;
674    } else if (err == ENODEV) {
675        ALOGE("Info: Device not available");
676    } else if (err != NO_ERROR) {
677        ALOGE("ERROR: Sync ptr returned %d", err);
678        *killThread = true;
679    }
680    return err;
681}
682
683void AudioUsbALSA::pollForProxyData(){
684    int err_poll = poll(pfdProxyPlayback, mnfdsPlayback, mtimeOut);
685    if (err_poll == 0 ) {
686        ALOGD("POLL timedout");
687        mkillPlayBackThread = true;
688        pfdProxyPlayback[0].revents = 0;
689        pfdProxyPlayback[1].revents = 0;
690        return;
691    }
692
693    if (pfdProxyPlayback[1].revents & POLLIN) {
694        ALOGD("Signalled from HAL about timeout");
695        uint64_t u;
696        read(mproxypfdPlayback, &u, sizeof(uint64_t));
697        pfdProxyPlayback[1].revents = 0;
698        if (u == SIGNAL_EVENT_KILLTHREAD) {
699            ALOGD("kill thread event");
700            mkillPlayBackThread = true;
701            pfdProxyPlayback[0].revents = 0;
702            pfdProxyPlayback[1].revents = 0;
703            return;
704        } else if (u == SIGNAL_EVENT_TIMEOUT) {
705            ALOGD("Setting timeout for 3 sec");
706            mtimeOut = POLL_TIMEOUT;
707        }
708    } else if (pfdProxyPlayback[1].revents & POLLERR || pfdProxyPlayback[1].revents & POLLHUP ||
709               pfdProxyPlayback[1].revents & POLLNVAL) {
710        ALOGE("Info: proxy throwing error from location 1");
711        mkillPlayBackThread = true;
712        pfdProxyPlayback[0].revents = 0;
713        pfdProxyPlayback[1].revents = 0;
714        return;
715    }
716
717    if (pfdProxyPlayback[0].revents & POLLERR || pfdProxyPlayback[0].revents & POLLHUP ||
718        pfdProxyPlayback[0].revents & POLLNVAL) {
719        ALOGE("Info: proxy throwing error");
720        mkillPlayBackThread = true;
721        pfdProxyPlayback[0].revents = 0;
722        pfdProxyPlayback[1].revents = 0;
723    }
724}
725
726void AudioUsbALSA::pollForUsbData(){
727    int err_poll = poll(pfdUsbPlayback, mnfdsPlayback, mtimeOut);
728    if (err_poll == 0 ) {
729        ALOGD("POLL timedout");
730        mkillPlayBackThread = true;
731        pfdUsbPlayback[0].revents = 0;
732        pfdUsbPlayback[1].revents = 0;
733        return;
734    }
735
736    if (pfdUsbPlayback[1].revents & POLLIN) {
737        ALOGD("Info: Signalled from HAL about an event");
738        uint64_t u;
739        read(musbpfdPlayback, &u, sizeof(uint64_t));
740        pfdUsbPlayback[0].revents = 0;
741        pfdUsbPlayback[1].revents = 0;
742        if (u == SIGNAL_EVENT_KILLTHREAD) {
743            ALOGD("kill thread");
744            mkillPlayBackThread = true;
745            return;
746        } else if (u == SIGNAL_EVENT_TIMEOUT) {
747            ALOGD("Setting timeout for 3 sec");
748            mtimeOut = POLL_TIMEOUT;
749        }
750    } else if (pfdUsbPlayback[1].revents & POLLERR || pfdUsbPlayback[1].revents & POLLHUP ||
751               pfdUsbPlayback[1].revents & POLLNVAL) {
752        ALOGE("Info: usb throwing error from location 1");
753        mkillPlayBackThread = true;
754        pfdUsbPlayback[0].revents = 0;
755        pfdUsbPlayback[1].revents = 0;
756        return;
757    }
758
759    if (pfdUsbPlayback[0].revents & POLLERR || pfdProxyPlayback[0].revents & POLLHUP ||
760        pfdUsbPlayback[0].revents & POLLNVAL) {
761        ALOGE("Info: usb throwing error");
762        mkillPlayBackThread = true;
763        pfdUsbPlayback[0].revents = 0;
764        return;
765    }
766}
767
768void AudioUsbALSA::PlaybackThreadEntry() {
769    ALOGD("PlaybackThreadEntry");
770    mnfdsPlayback = 2;
771    mtimeOut = TIMEOUT_INFINITE;
772    long frames;
773    static int fd;
774    struct snd_xferi x;
775    int bytes_written;
776    unsigned avail, xfer, bufsize;
777    unsigned proxyPeriod, usbPeriod;
778    uint32_t sampleRate;
779    uint32_t channels;
780    unsigned int tmp;
781    int numOfBytesWritten;
782    int err;
783    int filed;
784    const char *fn = "/data/test.pcm";
785    mdstUsb_addr = NULL;
786    msrcProxy_addr = NULL;
787
788    int proxySizeRemaining = 0;
789    int usbSizeFilled = 0;
790
791    pid_t tid  = gettid();
792    androidSetThreadPriority(tid, ANDROID_PRIORITY_URGENT_AUDIO);
793
794    err = getCap((char *)"Playback:", mchannelsPlayback, msampleRatePlayback);
795    if (err) {
796        ALOGE("ERROR: Could not get playback capabilities from usb device");
797        return;
798    }
799
800    musbPlaybackHandle = configureDevice(PCM_OUT|PCM_STEREO|PCM_MMAP, (char *)"hw:1,0",
801                                         msampleRatePlayback, mchannelsPlayback, USB_PERIOD_SIZE, true);
802    if (!musbPlaybackHandle) {
803        ALOGE("ERROR: configureUsbDevice failed, returning");
804        closeDevice(musbPlaybackHandle);
805        return;
806    } else {
807        ALOGD("USB Configured for playback");
808    }
809
810    if (!mkillPlayBackThread) {
811        pfdUsbPlayback[0].fd = musbPlaybackHandle->timer_fd;
812        pfdUsbPlayback[0].events = POLLIN;
813        musbpfdPlayback = eventfd(0,0);
814        pfdUsbPlayback[1].fd = musbpfdPlayback;
815        pfdUsbPlayback[1].events = (POLLIN | POLLOUT | POLLERR | POLLNVAL | POLLHUP);
816    }
817
818    mproxyPlaybackHandle = configureDevice(PCM_IN|PCM_STEREO|PCM_MMAP, (char *)"hw:0,8",
819                               msampleRatePlayback, mchannelsPlayback, PROXY_PERIOD_SIZE, false);
820    if (!mproxyPlaybackHandle) {
821        ALOGE("ERROR: Could not configure Proxy, returning");
822        closeDevice(musbPlaybackHandle);
823        return;
824    } else {
825        ALOGD("Proxy Configured for playback");
826    }
827
828    proxyPeriod = mproxyPlaybackHandle->period_size;
829    usbPeriod = musbPlaybackHandle->period_size;
830
831    if (!mkillPlayBackThread) {
832        pfdProxyPlayback[0].fd = mproxyPlaybackHandle->fd;
833        pfdProxyPlayback[0].events = (POLLIN);                                 // | POLLERR | POLLNVAL);
834        mproxypfdPlayback = eventfd(0,0);
835        pfdProxyPlayback[1].fd = mproxypfdPlayback;
836        pfdProxyPlayback[1].events = (POLLIN | POLLOUT| POLLERR | POLLNVAL);
837    }
838
839    frames = (mproxyPlaybackHandle->flags & PCM_MONO) ? (proxyPeriod / 2) : (proxyPeriod / 4);
840    x.frames = (mproxyPlaybackHandle->flags & PCM_MONO) ? (proxyPeriod / 2) : (proxyPeriod / 4);
841    int usbframes = (musbPlaybackHandle->flags & PCM_MONO) ? (usbPeriod / 2) : (usbPeriod / 4);
842
843    u_int8_t *proxybuf = ( u_int8_t *) malloc(PROXY_PERIOD_SIZE);
844    u_int8_t *usbbuf = ( u_int8_t *) malloc(USB_PERIOD_SIZE);
845    memset(proxybuf, 0x0, PROXY_PERIOD_SIZE);
846    memset(usbbuf, 0x0, USB_PERIOD_SIZE);
847
848
849    /***********************keep reading from proxy and writing to USB******************************************/
850    while (mkillPlayBackThread != true) {
851        if (!mproxyPlaybackHandle->running) {
852            if (pcm_prepare(mproxyPlaybackHandle)) {
853                ALOGE("ERROR: pcm_prepare failed for proxy");
854                mkillPlayBackThread = true;
855                break;
856            }
857        }
858        if (!musbPlaybackHandle->running) {
859            if (pcm_prepare(musbPlaybackHandle)) {
860                ALOGE("ERROR: pcm_prepare failed for usb");
861                mkillPlayBackThread = true;
862                break;
863            }
864        }
865
866        /********** Proxy syncing before write **************/
867        if (!mkillPlayBackThread && (!mproxyPlaybackHandle->start)) {
868            err = startDevice(mproxyPlaybackHandle, &mkillPlayBackThread);
869            if (err == EPIPE) {
870                continue;
871            } else if (err != NO_ERROR) {
872                mkillPlayBackThread = true;
873                break;
874            }
875        }
876        if (proxySizeRemaining == 0) {
877            for (;;) {
878                if (!mproxyPlaybackHandle->running) {
879                    if (pcm_prepare(mproxyPlaybackHandle)) {
880                        ALOGE("ERROR: pcm_prepare failed for proxy");
881                        mkillPlayBackThread = true;
882                        break;
883                    }
884                }
885                /* Sync the current Application pointer from the kernel */
886                mproxyPlaybackHandle->sync_ptr->flags = SNDRV_PCM_SYNC_PTR_APPL |
887                                                        SNDRV_PCM_SYNC_PTR_AVAIL_MIN;
888
889                if (mtimeOut == TIMEOUT_INFINITE && !mkillPlayBackThread) {
890                    err = syncPtr(mproxyPlaybackHandle, &mkillPlayBackThread);
891                    if (err == EPIPE) {
892                        continue;
893                    } else if (err != NO_ERROR) {
894                        break;
895                    }
896                    avail = pcm_avail(mproxyPlaybackHandle);
897                }
898                if (avail < mproxyPlaybackHandle->sw_p->avail_min && !mkillPlayBackThread) {
899                    pollForProxyData();
900                    //if polling returned some error
901                    if (!mkillPlayBackThread) {
902                        continue;
903                    } else {
904                        break;
905                    }
906                } else {                                                           //Got some data or mkillPlayBackThread is true
907                    break;
908                }
909            }
910            if (mkillPlayBackThread) {
911                break;
912            }
913
914            if (x.frames > avail)
915                frames = avail;
916
917            if (!mkillPlayBackThread) {
918                msrcProxy_addr = dst_address(mproxyPlaybackHandle);
919                memcpy(proxybuf, msrcProxy_addr, proxyPeriod );
920
921                x.frames -= frames;
922                mproxyPlaybackHandle->sync_ptr->c.control.appl_ptr += frames;
923                mproxyPlaybackHandle->sync_ptr->flags = 0;
924                proxySizeRemaining = proxyPeriod;
925            }
926
927            if (!mkillPlayBackThread) {
928                err = syncPtr(mproxyPlaybackHandle, &mkillPlayBackThread);
929                if (err == EPIPE) {
930                    continue;
931                } else if (err != NO_ERROR) {
932                    break;
933                }
934            }
935        }
936        //ALOGE("usbSizeFilled %d, proxySizeRemaining %d ",usbSizeFilled,proxySizeRemaining);
937        if (usbPeriod - usbSizeFilled <= proxySizeRemaining) {
938            memcpy(usbbuf + usbSizeFilled, proxybuf + proxyPeriod - proxySizeRemaining, usbPeriod - usbSizeFilled);
939            proxySizeRemaining -= (usbPeriod - usbSizeFilled);
940            usbSizeFilled = usbPeriod;
941        }
942        else {
943            memcpy(usbbuf + usbSizeFilled, proxybuf + proxyPeriod - proxySizeRemaining,proxySizeRemaining);
944            usbSizeFilled += proxySizeRemaining;
945            proxySizeRemaining = 0;
946        }
947
948        if (usbSizeFilled == usbPeriod) {
949            for (;;) {
950                if (!musbPlaybackHandle->running) {
951                    if (pcm_prepare(musbPlaybackHandle)) {
952                        ALOGE("ERROR: pcm_prepare failed for usb");
953                        mkillPlayBackThread = true;
954                        break;
955                    }
956                }
957                /*************USB syncing before write ******************/
958                musbPlaybackHandle->sync_ptr->flags = SNDRV_PCM_SYNC_PTR_APPL |
959                                                      SNDRV_PCM_SYNC_PTR_AVAIL_MIN;
960                if (mtimeOut == TIMEOUT_INFINITE && !mkillPlayBackThread) {
961                    err = syncPtr(musbPlaybackHandle, &mkillPlayBackThread);
962                    if (err == EPIPE) {
963                        continue;
964                    } else if (err != NO_ERROR) {
965                        break;
966                    }
967                    avail = pcm_avail(musbPlaybackHandle);
968                    //ALOGV("Avail USB is: %d", avail);
969                }
970
971                if (avail < musbPlaybackHandle->sw_p->avail_min && !mkillPlayBackThread) {
972                    pollForUsbData();
973                    if (!mkillPlayBackThread) {
974                        continue;
975                    } else {
976                        break;
977                    }
978                } else {
979                    break;
980                }
981            }
982            if (mkillPlayBackThread) {
983                break;
984            }
985
986            if (!mkillPlayBackThread) {
987                mdstUsb_addr = dst_address(musbPlaybackHandle);
988
989                /**************End USB syncing before write *************/
990
991                memcpy(mdstUsb_addr, usbbuf, usbPeriod );
992                usbSizeFilled = 0;
993                memset(usbbuf, 0x0, usbPeriod);
994            }
995
996            /**************** sync up after write -- USB  ************************/
997            musbPlaybackHandle->sync_ptr->c.control.appl_ptr += usbframes;
998            musbPlaybackHandle->sync_ptr->flags = 0;
999            if (!mkillPlayBackThread) {
1000                err = syncPtr(musbPlaybackHandle, &mkillPlayBackThread);
1001                if (err == EPIPE) {
1002                    continue;
1003                } else if (err != NO_ERROR) {
1004                    break;
1005                }
1006            }
1007
1008            bytes_written = musbPlaybackHandle->sync_ptr->c.control.appl_ptr - musbPlaybackHandle->sync_ptr->s.status.hw_ptr;
1009            ALOGE("Appl ptr %d , hw_ptr %d, difference %d",musbPlaybackHandle->sync_ptr->c.control.appl_ptr, musbPlaybackHandle->sync_ptr->s.status.hw_ptr, bytes_written);
1010
1011            /*
1012                Following is the check to prevent USB from going to bad state.
1013                This happens in case of an underrun where there is not enough
1014                data from the proxy
1015            */
1016	    if (bytes_written <= usbPeriod && musbPlaybackHandle->start) {
1017                ioctl(musbPlaybackHandle->fd, SNDRV_PCM_IOCTL_PAUSE,1);
1018                pcm_prepare(musbPlaybackHandle);
1019                musbPlaybackHandle->start = false;
1020                continue;
1021            }
1022            if ((bytes_written >= musbPlaybackHandle->sw_p->start_threshold) && (!musbPlaybackHandle->start)) {
1023                if (!mkillPlayBackThread) {
1024                    err = startDevice(musbPlaybackHandle, &mkillPlayBackThread);
1025                    if (err == EPIPE) {
1026                        continue;
1027                    } else if (err != NO_ERROR) {
1028                        mkillPlayBackThread = true;
1029                        break;
1030                    }
1031                }
1032            }
1033            /***************  End sync up after write -- USB *********************/
1034        }
1035    }
1036    if (mkillPlayBackThread) {
1037        if (proxybuf)
1038            free(proxybuf);
1039        if (usbbuf)
1040            free(usbbuf);
1041        mproxypfdPlayback = -1;
1042        musbpfdPlayback = -1;
1043        closeDevice(mproxyPlaybackHandle);
1044        closeDevice(musbPlaybackHandle);
1045    }
1046    ALOGD("Exiting USB Playback Thread");
1047}
1048
1049void AudioUsbALSA::startPlayback()
1050{
1051    mkillPlayBackThread = false;
1052    ALOGD("Creating USB Playback Thread");
1053    pthread_create(&mPlaybackUsb, NULL, PlaybackThreadWrapper, this);
1054}
1055
1056void AudioUsbALSA::startRecording()
1057{
1058    //create Thread
1059    mkillRecordingThread = false;
1060    ALOGV("Creating USB recording Thread");
1061    pthread_create(&mRecordingUsb, NULL, RecordingThreadWrapper, this);
1062}
1063}
1064