Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5792d4b1 authored by Apoorv Raghuvanshi's avatar Apoorv Raghuvanshi
Browse files

hal: Support for usb audio features

Added support for usb audio feature and
related proxy device support

Change-Id: Ia64e9eff20fbbada6f08795686cdbc0ba462bafb
parent 42576848
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -34,6 +34,11 @@ ifneq ($(strip $(AUDIO_FEATURE_DISABLED_FM)),true)
    LOCAL_SRC_FILES += audio_extn/fm.c
endif

ifneq ($(strip $(AUDIO_FEATURE_DISABLED_USBAUDIO)),true)
    LOCAL_CFLAGS += -DUSB_HEADSET_ENABLED
    LOCAL_SRC_FILES += audio_extn/usb.c
endif

LOCAL_SHARED_LIBRARIES := \
	liblog \
	libcutils \
+6 −4
Original line number Diff line number Diff line
@@ -62,7 +62,7 @@ bool audio_extn_get_anc_enabled(void)

bool audio_extn_should_use_handset_anc(int in_channels)
{
    char prop_aanc[128] = "false";
    char prop_aanc[PROPERTY_VALUE_MAX] = "false";

    property_get("persist.aanc.enable", prop_aanc, "0");
    if (!strncmp("true", prop_aanc, 4)) {
@@ -76,7 +76,7 @@ bool audio_extn_should_use_handset_anc(int in_channels)

bool audio_extn_should_use_fb_anc(void)
{
  char prop_anc[128] = "feedforward";
  char prop_anc[PROPERTY_VALUE_MAX] = "feedforward";

  property_get("persist.headset.anc.type", prop_anc, "0");
  if (!strncmp("feedback", prop_anc, sizeof("feedback"))) {
@@ -171,7 +171,9 @@ char* audio_extn_get_afe_proxy_parameters(struct str_parms *query,
    ret = str_parms_get_str(query, AUDIO_PARAMETER_CAN_OPEN_PROXY, value,
                            sizeof(value));
    if (ret >= 0) {
        /* Todo: check if proxy is free by maintaining a state flag*/
        if (audio_extn_usb_is_proxy_inuse())
            val = 0;
        else
            val = 1;
        str_parms_add_int(reply, AUDIO_PARAMETER_CAN_OPEN_PROXY, val);
        str = str_parms_to_str(reply);
+20 −0
Original line number Diff line number Diff line
@@ -44,4 +44,24 @@ bool audio_extn_should_use_handset_anc(int in_channels);
int32_t audio_extn_set_afe_proxy_channel_mixer(struct audio_device *adev);
#endif

#ifndef USB_HEADSET_ENABLED
#define audio_extn_usb_init(adev)                        (0)
#define audio_extn_usb_deinit()                          (0)
#define audio_extn_usb_start_playback(adev)              (0)
#define audio_extn_usb_stop_playback()                   (0)
#define audio_extn_usb_start_capture(adev)               (0)
#define audio_extn_usb_stop_capture()                    (0)
#define audio_extn_usb_set_proxy_sound_card(sndcard_idx) (0)
#define audio_extn_usb_is_proxy_inuse()                  (0)
#else
void audio_extn_usb_init(void *adev);
void audio_extn_usb_deinit();
void audio_extn_usb_start_playback(void *adev);
void audio_extn_usb_stop_playback();
void audio_extn_usb_start_capture(void *adev);
void audio_extn_usb_stop_capture();
void audio_extn_usb_set_proxy_sound_card(uint32_t sndcard_idx);
bool audio_extn_usb_is_proxy_inuse();
#endif

#endif /* AUDIO_EXTN_H */

hal/audio_extn/usb.c

0 → 100644
+673 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2013, The Linux Foundation. All rights reserved.
 * Not a Contribution.
 *
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "audio_hw_usb"
#define LOG_NDEBUG 0
#define LOG_NDDEBUG 0

#include <errno.h>
#include <pthread.h>
#include <stdlib.h>
#include <cutils/log.h>
#include <cutils/str_parms.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sys/stat.h>

#include <system/audio.h>
#include <tinyalsa/asoundlib.h>

#ifdef USB_HEADSET_ENABLED
#define USB_LOW_LATENCY_OUTPUT_PERIOD_SIZE   512
#define USB_LOW_LATENCY_OUTPUT_PERIOD_COUNT  8
#define USB_DEFAULT_OUTPUT_SAMPLING_RATE     48000

#define USB_PROXY_DEFAULT_SAMPLING_RATE      48000
#define USB_PROXY_OPEN_RETRY_COUNT           100
#define USB_PROXY_OPEN_WAIT_TIME             20
#define USB_PROXY_PERIOD_SIZE                3072
#define USB_PROXY_RATE_8000                  8000
#define USB_PROXY_RATE_16000                 16000
#define USB_PROXY_RATE_48000                 48000
#define USB_PERIOD_SIZE                      2048
#define USB_BUFF_SIZE                        2048
#define AFE_PROXY_PERIOD_COUNT               32
#define AFE_PROXY_PLAYBACK_DEVICE            8
#define AFE_PROXY_CAPTURE_DEVICE             7

struct usb_module {
    uint32_t usb_card;
    uint32_t proxy_card;
    uint32_t usb_device_id;
    uint32_t proxy_device_id;

    int32_t channels_playback;
    int32_t sample_rate_playback;
    int32_t channels_record;
    int32_t sample_rate_record;

    bool is_playback_running;
    bool is_record_running;

    pthread_t usb_playback_thr;
    pthread_t usb_record_thr;
    pthread_mutex_t usb_playback_lock;
    pthread_mutex_t usb_record_lock;

    struct pcm *proxy_pcm_playback_handle;
    struct pcm *usb_pcm_playback_handle;
    struct pcm *proxy_pcm_record_handle;
    struct pcm *usb_pcm_record_handle;
    struct audio_device *adev;
};

static struct usb_module *usbmod = NULL;
static pthread_once_t alloc_usbmod_once_ctl = PTHREAD_ONCE_INIT;

struct pcm_config pcm_config_usbmod = {
    .channels = 2,
    .rate = USB_DEFAULT_OUTPUT_SAMPLING_RATE,
    .period_size = USB_LOW_LATENCY_OUTPUT_PERIOD_SIZE,
    .period_count = USB_LOW_LATENCY_OUTPUT_PERIOD_COUNT,
    .format = PCM_FORMAT_S16_LE,
    .start_threshold = USB_LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
    .stop_threshold = INT_MAX,
    .avail_min = USB_LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
};

static void usb_alloc()
{
    usbmod = calloc(1, sizeof(struct usb_module));
}

static int usb_get_numof_rates(char *rates_str)
{
    int i, size = 0;
    char *next_sr_string, *temp_ptr;
    next_sr_string = strtok_r(rates_str, " ,", &temp_ptr);

    if (next_sr_string == NULL) {
        ALOGE("%s: get_numof_rates: could not find rates string", __func__);
        return (int)NULL;
    }

    for (i = 1; next_sr_string != NULL; i++) {
        size ++;
        next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
    }
    return size;
}

static int usb_get_capability(char *type, int32_t *channels,
                                    int32_t *sample_rate)
{
    ALOGD("%s: for %s", __func__, type);
    long unsigned file_size;
    FILE *fp;
    char *buffer;
    int32_t err = 1;
    int32_t size = 0;
    int32_t fd, i, channels_playback;
    char *read_buf, *str_start, *channel_start, *rates_str, *rates_str_for_val,
    *rates_str_start, *next_sr_str, *test, *next_sr_string, *temp_ptr;
    struct stat st;
    int rates_supported[size];
    char path[128];

    memset(&st, 0x0, sizeof(struct stat));
    *sample_rate = 0;
    snprintf(path, sizeof(path), "/proc/asound/card%u/stream0",
             usbmod->usb_card);

    fd = open(path, O_RDONLY);
    if (fd <0) {
        ALOGE("%s: error failed to open config file %s error: %d\n",
              __func__, path, errno);
        close(fd);
        return -EINVAL;
    }

    if (fstat(fd, &st) < 0) {
        ALOGE("%s: error failed to stat %s error %d\n",
             __func__, path, errno);
        close(fd);
        return -EINVAL;
    }

    file_size = st.st_size;

    read_buf = (char *)calloc(1, USB_BUFF_SIZE);
    err = read(fd, read_buf, USB_BUFF_SIZE);
    str_start = strstr(read_buf, type);
    if (str_start == NULL) {
        ALOGE("%s: error %s section not found in usb config file",
               __func__, type);
        close(fd);
        free(read_buf);
        return -EINVAL;
    }

    channel_start = strstr(str_start, "Channels:");
    if (channel_start == NULL) {
        ALOGE("%s: error could not find Channels information", __func__);
        close(fd);
        free(read_buf);
        return -EINVAL;
    }

    channel_start = strstr(channel_start, " ");
    if (channel_start == NULL) {
        ALOGE("%s: error channel section not found in usb config file",
               __func__);
        close(fd);
        free(read_buf);
        return -EINVAL;
    }

    channels_playback = atoi(channel_start);
    if (channels_playback == 1) {
        *channels = 1;
    } else {
        *channels = 2;
    }

    ALOGD("%s: channels supported by device: %d", __func__, *channels);
    rates_str_start = strstr(str_start, "Rates:");
    if (rates_str_start == NULL) {
        ALOGE("%s: error cant find rates information", __func__);
        close(fd);
        free(read_buf);
        return -EINVAL;
    }

    rates_str_start = strstr(rates_str_start, " ");
    if (rates_str_start == NULL) {
        ALOGE("%s: error channel section not found in usb config file",
               __func__);
        close(fd);
        free(read_buf);
        return -EINVAL;
    }

    char *target = strchr(rates_str_start, '\n');
    if (target == NULL) {
        ALOGE("%s: error end of line not found", __func__);
        close(fd);
        free(read_buf);
        return -EINVAL;
    }

    size = target - rates_str_start;
    if ((rates_str = (char *)malloc(size + 1)) == NULL) {
        ALOGE("%s: error unable to allocate memory to hold sample rate strings",
              __func__);
        close(fd);
        free(read_buf);
        return -ENOMEM;
    }

    if ((rates_str_for_val = (char *)malloc(size + 1)) == NULL) {
        ALOGE("%s: error unable to allocate memory to hold sample rate string",
               __func__);
        close(fd);
        free(rates_str);
        free(read_buf);
        return -ENOMEM;
    }

    memcpy(rates_str, rates_str_start, size);
    memcpy(rates_str_for_val, rates_str_start, size);
    rates_str[size] = '\0';
    rates_str_for_val[size] = '\0';

    size = usb_get_numof_rates(rates_str);
    if (!size) {
        ALOGE("%s: error could not get rate size, returning", __func__);
        close(fd);
        free(rates_str_for_val);
        free(rates_str);
        free(read_buf);
        return -EINVAL;
    }

    next_sr_string = strtok_r(rates_str_for_val, " ,", &temp_ptr);
    if (next_sr_string == NULL) {
        ALOGE("%s: error could not get first rate val", __func__);
        close(fd);
        free(rates_str_for_val);
        free(rates_str);
        free(read_buf);
        return -EINVAL;
    }

    rates_supported[0] = atoi(next_sr_string);
    ALOGD("%s: rates_supported[0] for playback: %d",
           __func__, rates_supported[0]);
    for (i = 1; i<size; i++) {
        next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
        rates_supported[i] = atoi(next_sr_string);
        ALOGD("rates_supported[%d] for playback: %d",i, rates_supported[i]);
    }

    for (i = 0; i<size; i++) {
        if ((rates_supported[i] > *sample_rate) &&
            (rates_supported[i] <= 48000)) {
            /* Sample Rate should be one of the proxy supported rates only
               This is because proxy port is used to read from/write to DSP */
            if ((rates_supported[i] == USB_PROXY_RATE_8000) ||
                (rates_supported[i] == USB_PROXY_RATE_16000) ||
                (rates_supported[i] == USB_PROXY_RATE_48000)) {
                *sample_rate = rates_supported[i];
            }
        }
    }
    ALOGD("%s: sample_rate: %d", __func__, *sample_rate);

    close(fd);
    free(rates_str_for_val);
    free(rates_str);
    free(read_buf);
    return 0;
}

static int32_t usb_playback_entry(void *adev)
{
    unsigned char usbbuf[USB_PROXY_PERIOD_SIZE] = {0};
    int32_t ret, bytes, proxy_open_retry_count;

    ALOGD("%s: entry", __func__);
    /* update audio device pointer */
    usbmod->adev = (struct audio_device*)adev;
    proxy_open_retry_count = USB_PROXY_OPEN_RETRY_COUNT;

    /* get capabilities */
    pthread_mutex_lock(&usbmod->usb_playback_lock);
    ret = usb_get_capability((char *)"Playback:",
            &usbmod->channels_playback, &usbmod->sample_rate_playback);
    if (ret) {
        ALOGE("%s: could not get playback capabilities from usb device",
               __func__);
        pthread_mutex_unlock(&usbmod->usb_playback_lock);
        return -EINVAL;
    }
    /* update config for usb
       1 pcm frame(sample)= 4 bytes since two channels*/
    pcm_config_usbmod.period_size = USB_PERIOD_SIZE/4;
    pcm_config_usbmod.channels = usbmod->channels_playback;
    pcm_config_usbmod.rate = usbmod->sample_rate_playback;
    ALOGV("%s: usb device %u:period %u:channels %u:sample", __func__,
          pcm_config_usbmod.period_size, pcm_config_usbmod.channels,
          pcm_config_usbmod.rate);

    usbmod->usb_pcm_playback_handle = pcm_open(usbmod->usb_card, \
                                    usbmod->usb_device_id, PCM_OUT |
                                    PCM_MMAP | PCM_NOIRQ , &pcm_config_usbmod);

    if ((usbmod->usb_pcm_playback_handle \
        && !pcm_is_ready(usbmod->usb_pcm_playback_handle))
        || (!usbmod->is_playback_running)) {
        ALOGE("%s: failed: %s", __func__,
               pcm_get_error(usbmod->usb_pcm_playback_handle));
        pcm_close(usbmod->usb_pcm_playback_handle);
        usbmod->usb_pcm_playback_handle = NULL;
        pthread_mutex_unlock(&usbmod->usb_playback_lock);
        return -ENOMEM;
    }
    ALOGD("%s: USB configured for playback", __func__);

    /* update config for proxy*/
    pcm_config_usbmod.period_size = USB_PROXY_PERIOD_SIZE/3;
    pcm_config_usbmod.rate = usbmod->sample_rate_playback;
    pcm_config_usbmod.channels = usbmod->channels_playback;
    pcm_config_usbmod.period_count = AFE_PROXY_PERIOD_COUNT;
    usbmod->proxy_device_id = AFE_PROXY_PLAYBACK_DEVICE;
    ALOGV("%s: proxy device %u:period %u:channels %u:sample", __func__,
          pcm_config_usbmod.period_size, pcm_config_usbmod.channels,
          pcm_config_usbmod.rate);

    while(proxy_open_retry_count){
        usbmod->proxy_pcm_playback_handle = pcm_open(usbmod->proxy_card,
                                            usbmod->proxy_device_id, PCM_IN |
                                     PCM_MMAP | PCM_NOIRQ, &pcm_config_usbmod);
        if(!usbmod->proxy_pcm_playback_handle){
                     proxy_open_retry_count--;
                     usleep(USB_PROXY_OPEN_WAIT_TIME * 1000);
                     ALOGE("%s: pcm_open for proxy failed retrying = %d",
                            __func__, proxy_open_retry_count);
                }
                else{
                  break;
                }
    }

    if ((usbmod->proxy_pcm_playback_handle
        && !pcm_is_ready(usbmod->proxy_pcm_playback_handle))
        || (!usbmod->is_playback_running)) {
        ALOGE("%s: failed: %s", __func__,
               pcm_get_error(usbmod->proxy_pcm_playback_handle));
        pcm_close(usbmod->proxy_pcm_playback_handle);
        usbmod->proxy_pcm_playback_handle = NULL;
        pthread_mutex_unlock(&usbmod->usb_playback_lock);
        return -ENOMEM;
    }
    ALOGD("%s: PROXY configured for playback", __func__);
    pthread_mutex_unlock(&usbmod->usb_playback_lock);

    /* main loop to read from proxy and write to usb */
    while (usbmod->is_playback_running) {
        /* read data from proxy */
        ret = pcm_mmap_read(usbmod->proxy_pcm_playback_handle,
                                 (void *)usbbuf, USB_PROXY_PERIOD_SIZE);
        /* Write to usb */
        ret = pcm_mmap_write(usbmod->usb_pcm_playback_handle,
                                (void *)usbbuf, USB_PROXY_PERIOD_SIZE);
        if(!usbmod->is_playback_running)
            break;

        memset(usbbuf, 0, USB_PROXY_PERIOD_SIZE);
    } /* main loop end */

    ALOGD("%s: exiting USB playback thread",__func__);
    return 0;
}

static void* usb_playback_launcher(void *adev)
{
    int32_t ret;

    usbmod->is_playback_running = true;
    ret = usb_playback_entry(adev);

    if (ret) {
        ALOGE("%s: failed with err:%d", __func__, ret);
        usbmod->is_playback_running = false;
    }
    return NULL;
}

static int32_t usb_record_entry(void *adev)
{
    unsigned char usbbuf[USB_PROXY_PERIOD_SIZE] = {0};
    int32_t ret, bytes, proxy_open_retry_count;
    ALOGD("%s: entry", __func__);

    /* update audio device pointer */
    usbmod->adev = (struct audio_device*)adev;
    proxy_open_retry_count = USB_PROXY_OPEN_RETRY_COUNT;

    /* get capabilities */
    pthread_mutex_lock(&usbmod->usb_record_lock);
    ret = usb_get_capability((char *)"Capture:",
            &usbmod->channels_record, &usbmod->sample_rate_record);
    if (ret) {
        ALOGE("%s: could not get capture capabilities from usb device",
               __func__);
        pthread_mutex_unlock(&usbmod->usb_record_lock);
        return -EINVAL;
    }
    /* update config for usb
       1 pcm frame(sample)= 4 bytes since two channels*/
    pcm_config_usbmod.period_size = USB_PERIOD_SIZE/4;
    pcm_config_usbmod.channels = usbmod->channels_record;
    pcm_config_usbmod.rate = usbmod->sample_rate_record;
    ALOGV("%s: usb device %u:period %u:channels %u:sample", __func__,
          pcm_config_usbmod.period_size, pcm_config_usbmod.channels,
          pcm_config_usbmod.rate);

    usbmod->usb_pcm_record_handle = pcm_open(usbmod->usb_card, \
                                    usbmod->usb_device_id, PCM_IN |
                                    PCM_MMAP | PCM_NOIRQ , &pcm_config_usbmod);

    if ((usbmod->usb_pcm_record_handle \
        && !pcm_is_ready(usbmod->usb_pcm_record_handle))
        || (!usbmod->is_record_running)) {
        ALOGE("%s: failed: %s", __func__,
               pcm_get_error(usbmod->usb_pcm_record_handle));
        pcm_close(usbmod->usb_pcm_record_handle);
        usbmod->usb_pcm_record_handle = NULL;
        pthread_mutex_unlock(&usbmod->usb_record_lock);
        return -ENOMEM;
    }
    ALOGD("%s: USB configured for capture", __func__);

    /* update config for proxy*/
    pcm_config_usbmod.period_size = USB_PROXY_PERIOD_SIZE/4;
    pcm_config_usbmod.rate = usbmod->sample_rate_record;
    pcm_config_usbmod.channels = usbmod->channels_record;
    pcm_config_usbmod.period_count = AFE_PROXY_PERIOD_COUNT * 2;
    usbmod->proxy_device_id = AFE_PROXY_CAPTURE_DEVICE;
    ALOGV("%s: proxy device %u:period %u:channels %u:sample", __func__,
          pcm_config_usbmod.period_size, pcm_config_usbmod.channels,
          pcm_config_usbmod.rate);

    while(proxy_open_retry_count){
        usbmod->proxy_pcm_record_handle = pcm_open(usbmod->proxy_card,
                                            usbmod->proxy_device_id, PCM_OUT |
                                     PCM_MMAP | PCM_NOIRQ, &pcm_config_usbmod);
        if(!usbmod->proxy_pcm_record_handle){
                     proxy_open_retry_count--;
                     usleep(USB_PROXY_OPEN_WAIT_TIME * 1000);
                     ALOGE("%s: pcm_open for proxy(recording) failed retrying = %d",
                            __func__, proxy_open_retry_count);
                }
                else{
                  break;
                }
    }
    if ((usbmod->proxy_pcm_record_handle
        && !pcm_is_ready(usbmod->proxy_pcm_record_handle))
        || (!usbmod->is_record_running)) {
        ALOGE("%s: failed: %s", __func__,
               pcm_get_error(usbmod->proxy_pcm_record_handle));
        pcm_close(usbmod->proxy_pcm_record_handle);
        usbmod->proxy_pcm_record_handle = NULL;
        pthread_mutex_unlock(&usbmod->usb_record_lock);
        return -ENOMEM;
    }
    ALOGD("%s: PROXY configured for capture", __func__);
    pthread_mutex_unlock(&usbmod->usb_record_lock);

    /* main loop to read from usb and write to proxy */
    while (usbmod->is_record_running) {
        /* read data from usb */
        ret = pcm_mmap_read(usbmod->usb_pcm_record_handle,
                                 (void *)usbbuf, USB_PROXY_PERIOD_SIZE);
        /* Write to proxy */
        ret = pcm_mmap_write(usbmod->proxy_pcm_record_handle,
                                (void *)usbbuf, USB_PROXY_PERIOD_SIZE);
        if(!usbmod->is_record_running)
            break;

        memset(usbbuf, 0, USB_PROXY_PERIOD_SIZE);
    } /* main loop end */

    ALOGD("%s: exiting USB capture thread",__func__);
    return 0;
}

static void* usb_capture_launcher(void *adev)
{
    int32_t ret;

    usbmod->is_record_running = true;
    ret = usb_record_entry(adev);

    if (ret) {
        ALOGE("%s: failed with err:%d", __func__, ret);
        usbmod->is_record_running = false;
    }
    return NULL;
}

void audio_extn_usb_init(void *adev)
{
    pthread_once(&alloc_usbmod_once_ctl, usb_alloc);

    usbmod->is_playback_running = false;
    usbmod->is_record_running = false;

    usbmod->usb_pcm_playback_handle = NULL;
    usbmod->proxy_pcm_playback_handle = NULL;

    usbmod->usb_pcm_record_handle = NULL;
    usbmod->proxy_pcm_record_handle = NULL;

    usbmod->usb_card = 1;
    usbmod->usb_device_id = 0;
    usbmod->proxy_card = 0;
    usbmod->proxy_device_id = AFE_PROXY_PLAYBACK_DEVICE;
    usbmod->adev = (struct audio_device*)adev;
}

void audio_extn_usb_deinit()
{
    if (NULL != usbmod){
        free(usbmod);
        usbmod = NULL;
    }
}

void audio_extn_usb_set_proxy_sound_card(uint32_t sndcard_idx)
{
    /* Proxy port and USB headset are related to two different sound cards */
    if (sndcard_idx == usbmod->usb_card) {
        usbmod->usb_card = usbmod->proxy_card;
    }

    usbmod->proxy_card = sndcard_idx;
}

void audio_extn_usb_start_playback(void *adev)
{
    int32_t ret;

    if (NULL == usbmod){
        ALOGE("%s: USB device object is NULL", __func__);
        return;
    }

    if (usbmod->is_playback_running){
        ALOGE("%s: USB playback thread already running", __func__);
        return;
    }

    ALOGD("%s: creating USB playback thread", __func__);
    ret = pthread_create(&usbmod->usb_playback_thr, NULL,
                         usb_playback_launcher, (void*)adev);
    if (ret)
        ALOGE("%s: failed to create USB playback thread with err:%d",
              __func__, ret);
}

void audio_extn_usb_stop_playback()
{
    int32_t ret;
    ALOGD("%s: entry", __func__);

    usbmod->is_playback_running = false;
    if (NULL != usbmod->proxy_pcm_playback_handle)
        pcm_stop(usbmod->proxy_pcm_playback_handle);

    if (NULL != usbmod->usb_pcm_playback_handle)
        pcm_stop(usbmod->usb_pcm_playback_handle);

    if(usbmod->usb_playback_thr) {
        ret = pthread_join(usbmod->usb_playback_thr,NULL);
        ALOGE("%s: return for pthread_join = %d", __func__, ret);
        usbmod->usb_playback_thr = (pthread_t)NULL;
    }

    pthread_mutex_lock(&usbmod->usb_playback_lock);
    if (NULL != usbmod->usb_pcm_playback_handle){
        pcm_close(usbmod->usb_pcm_playback_handle);
        usbmod->usb_pcm_playback_handle = NULL;
    }

    if (NULL != usbmod->proxy_pcm_playback_handle){
        pcm_close(usbmod->proxy_pcm_playback_handle);
        usbmod->proxy_pcm_playback_handle = NULL;
    }
    pthread_mutex_unlock(&usbmod->usb_playback_lock);

    ALOGD("%s: exiting",__func__);
}

void audio_extn_usb_start_capture(void *adev)
{
    int32_t ret;

    if (NULL == usbmod){
        ALOGE("%s: USB device object is NULL", __func__);
        return;
    }

    if (usbmod->is_record_running){
        ALOGE("%s: USB capture thread already running", __func__);
        return;
    }

    ALOGD("%s: creating USB capture thread", __func__);
    ret = pthread_create(&usbmod->usb_record_thr, NULL,
                         usb_capture_launcher, (void*)adev);
    if (ret)
        ALOGE("%s: failed to create USB capture thread with err:%d",
              __func__, ret);
}

void audio_extn_usb_stop_capture()
{
    int32_t ret;
    ALOGD("%s: entry", __func__);

    usbmod->is_record_running = false;
    if (NULL != usbmod->proxy_pcm_record_handle)
        pcm_stop(usbmod->proxy_pcm_record_handle);

    if (NULL != usbmod->usb_pcm_record_handle)
        pcm_stop(usbmod->usb_pcm_record_handle);

    if(usbmod->usb_record_thr) {
        ret = pthread_join(usbmod->usb_record_thr,NULL);
        ALOGE("%s: return for pthread_join = %d", __func__, ret);
        usbmod->usb_record_thr = (pthread_t)NULL;
    }

    pthread_mutex_lock(&usbmod->usb_record_lock);
    if (NULL != usbmod->usb_pcm_record_handle){
        pcm_close(usbmod->usb_pcm_record_handle);
        usbmod->usb_pcm_record_handle = NULL;
    }

    if (NULL != usbmod->proxy_pcm_record_handle){
        pcm_close(usbmod->proxy_pcm_record_handle);
        usbmod->proxy_pcm_record_handle = NULL;
    }
    pthread_mutex_unlock(&usbmod->usb_record_lock);

    ALOGD("%s: exiting",__func__);
}

bool audio_extn_usb_is_proxy_inuse()
{
    if( usbmod->is_record_running || usbmod->is_playback_running)
        return true;
    else
        return false;
}
#endif /*USB_HEADSET_ENABLED end*/
Loading