Home | History | Annotate | Download | only in alsa_sound
      1 /* AudioUsbALSA.cpp
      2 Copyright (c) 2012, Code Aurora Forum. All rights reserved.
      3 
      4 Redistribution and use in source and binary forms, with or without
      5 modification, are permitted provided that the following conditions are
      6 met:
      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 
     17 THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
     18 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
     20 ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
     21 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     24 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     25 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     26 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     27 IF 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"
     50 struct pollfd pfdProxyPlayback[2];
     51 struct pollfd pfdUsbPlayback[2];
     52 struct pollfd pfdProxyRecording[1];
     53 struct pollfd pfdUsbRecording[1];
     54 
     55 #define USB_PERIOD_SIZE 2048
     56 #define PROXY_PERIOD_SIZE 3072
     57 
     58 namespace android_audio_legacy
     59 {
     60 AudioUsbALSA::AudioUsbALSA()
     61 {
     62     mproxypfdPlayback = -1;
     63     musbpfdPlayback = -1;
     64     mkillPlayBackThread = false;
     65     mkillRecordingThread = false;
     66 }
     67 
     68 AudioUsbALSA::~AudioUsbALSA()
     69 {
     70     mkillPlayBackThread = true;
     71     mkillRecordingThread = true;
     72 }
     73 
     74 
     75 int 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 
     91 status_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 
    232 void 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 
    255 void 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 
    273 void AudioUsbALSA::setkillUsbRecordingThread(bool val){
    274     ALOGD("setkillUsbRecordingThread");
    275     mkillRecordingThread = val;
    276 }
    277 
    278 status_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 
    327 status_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 
    364 status_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 
    378 void 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 
    580 void *AudioUsbALSA::PlaybackThreadWrapper(void *me) {
    581     static_cast<AudioUsbALSA *>(me)->PlaybackThreadEntry();
    582     return NULL;
    583 }
    584 
    585 void *AudioUsbALSA::RecordingThreadWrapper(void *me) {
    586     static_cast<AudioUsbALSA *>(me)->RecordingThreadEntry();
    587     return NULL;
    588 }
    589 
    590 struct 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 
    637 status_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 
    666 status_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 
    683 void 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 
    726 void 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 
    768 void 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 
   1049 void AudioUsbALSA::startPlayback()
   1050 {
   1051     mkillPlayBackThread = false;
   1052     ALOGD("Creating USB Playback Thread");
   1053     pthread_create(&mPlaybackUsb, NULL, PlaybackThreadWrapper, this);
   1054 }
   1055 
   1056 void 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