"LA.UM.9.1.r1-14600-SMxxx0.QSSI14.0"

* tag 'LA.UM.9.1.r1-14600-SMxxx0.QSSI14.0' of https://git.codelinaro.org/clo/la/platform/vendor/opensource/audio-kernel:
  dsp: q6asm: Add check for ADSP payload size
  ASoC: msm-pcm-host-voice: Check validity of session idx
  ASoC: msm-pcm-host-voice: Check validity of session idx
  dsp: q6lsm: Address use after free for mmap handle
  ASoC: msm-pcm-host-voice: Check validity of session idx
  dsp: q6lsm: Address use after free for mmap handle
  ASoC: msm-pcm-host-voice: Check validity of session idx
  dsp: afe: Copyright update.
  ASoC: msm-pcm-voip: Avoid interger underflow
  ASoC: msm-pcm-voip: Avoid interger underflow
  dsp: q6voice: Add buf size check for cvs cal data
  dsp: asm: validate payload size before access
  dsp: q6core: Avoid OOB access in q6core
  ASoC: msm-pcm-host-voice: Handle OOB access in hpcm_start
  dsp: afe: Add check for sidetone iir config copy size
  ASoC: msm-pcm-voip: Avoid interger underflow
  ASoC: msm-pcm-voip: Avoid interger underflow
  ASoC: msm-pcm-host-voice: Address buffer overflow in hpcm copy
  dsp: add lock in ion free to avoid use after free
  Asoc: check for invalid voice session id

Change-Id: I288b010a1612fb33e30746d584a0460d0906d76c
This commit is contained in:
Richard Raya 2023-12-07 20:10:28 -03:00
commit c21740b406
12 changed files with 177 additions and 50 deletions

View File

@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/init.h>
@ -654,6 +655,11 @@ static void hpcm_copy_playback_data_from_queue(struct dai_data *dai_data,
struct hpcm_buf_node, list);
list_del(&buf_node->list);
*len = buf_node->frame.len;
if (*len > HPCM_MAX_VOC_PKT_SIZE) {
pr_err("%s: Playback data len %d overflow\n",
__func__, *len);
return;
}
memcpy((u8 *)dai_data->vocpcm_ion_buffer.kvaddr,
&buf_node->frame.voc_pkt[0],
buf_node->frame.len);
@ -681,6 +687,12 @@ static void hpcm_copy_capture_data_to_queue(struct dai_data *dai_data,
if (dai_data->substream == NULL)
return;
if (len > HPCM_MAX_VOC_PKT_SIZE) {
pr_err("%s: Copy capture data len %d overflow\n",
__func__, len);
return;
}
/* Copy out buffer packet into free_queue */
spin_lock_irqsave(&dai_data->dsp_lock, dsp_flags);
@ -723,6 +735,13 @@ void hpcm_notify_evt_processing(uint8_t *data, char *session,
return;
}
if (prtd->mixer_conf.sess_indx < VOICE_INDEX ||
prtd->mixer_conf.sess_indx >= MAX_SESSION) {
pr_err("%s:: Invalid session idx %d\n",
__func__, prtd->mixer_conf.sess_indx);
return;
}
if (notify_evt->tap_point == VSS_IVPCM_TAP_POINT_TX_DEFAULT) {
tp = &prtd->session[prtd->mixer_conf.sess_indx].tx_tap_point;
tmd = &prtd->mixer_conf.tx;

View File

@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/init.h>
@ -363,6 +364,13 @@ static void voip_process_ul_pkt(uint8_t *voc_pkt,
switch (prtd->mode) {
case MODE_AMR_WB:
case MODE_AMR: {
if (pkt_len <= DSP_FRAME_HDR_LEN) {
pr_err("%s: pkt_len %d is < required len\n",
__func__, pkt_len);
spin_unlock_irqrestore(&prtd->dsp_ul_lock,
dsp_flags);
return;
}
/* Remove the DSP frame info header. Header format:
* Bits 0-3: Frame rate
* Bits 4-7: Frame type
@ -383,6 +391,13 @@ static void voip_process_ul_pkt(uint8_t *voc_pkt,
case MODE_4GV_NB:
case MODE_4GV_WB:
case MODE_4GV_NW: {
if (pkt_len <= DSP_FRAME_HDR_LEN) {
pr_err("%s: pkt_len %d is < required len\n",
__func__, pkt_len);
spin_unlock_irqrestore(&prtd->dsp_ul_lock,
dsp_flags);
return;
}
/* Remove the DSP frame info header.
* Header format:
* Bits 0-3: frame rate
@ -420,6 +435,13 @@ static void voip_process_ul_pkt(uint8_t *voc_pkt,
buf_node->frame.frm_hdr.timestamp = timestamp;
voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
if (pkt_len <= 2 * DSP_FRAME_HDR_LEN) {
pr_err("%s: pkt_len %d is < required len\n",
__func__, pkt_len);
spin_unlock_irqrestore(&prtd->dsp_ul_lock,
dsp_flags);
return;
}
/* There are two frames in the buffer. Length of the
* first frame:
*/
@ -455,6 +477,13 @@ static void voip_process_ul_pkt(uint8_t *voc_pkt,
buf_node->frame.frm_hdr.timestamp = timestamp;
voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
if (pkt_len <= 2 * DSP_FRAME_HDR_LEN) {
pr_err("%s: pkt_len %d is < required len\n",
__func__, pkt_len);
spin_unlock_irqrestore(&prtd->dsp_ul_lock,
dsp_flags);
return;
}
/* There are two frames in the buffer. Length
* of the second frame:
*/

View File

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2013-2019, Linux Foundation. All rights reserved.
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/fs.h>
#include <linux/mutex.h>
@ -405,6 +406,10 @@ static int q6lsm_apr_send_pkt(struct lsm_client *client, void *handle,
}
pr_debug("%s: enter wait %d\n", __func__, wait);
if (mmap_handle_p) {
pr_debug("%s: Invalid mmap_handle\n", __func__);
return -EINVAL;
}
if (wait)
mutex_lock(&lsm_common.apr_lock);
if (mmap_p) {
@ -450,6 +455,7 @@ static int q6lsm_apr_send_pkt(struct lsm_client *client, void *handle,
if (mmap_p && *mmap_p == 0)
ret = -ENOMEM;
mmap_handle_p = NULL;
pr_debug("%s: leave ret %d\n", __func__, ret);
return ret;
}
@ -1910,7 +1916,8 @@ static int q6lsm_mmapcallback(struct apr_client_data *data, void *priv)
case LSM_SESSION_CMDRSP_SHARED_MEM_MAP_REGIONS:
if (atomic_read(&client->cmd_state) == CMD_STATE_WAIT_RESP) {
spin_lock_irqsave(&mmap_lock, flags);
*mmap_handle_p = command;
if (mmap_handle_p)
*mmap_handle_p = command;
/* spin_unlock_irqrestore implies barrier */
spin_unlock_irqrestore(&mmap_lock, flags);
atomic_set(&client->cmd_state, CMD_STATE_CLEARED);

View File

@ -1,13 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/init.h>
@ -632,6 +625,12 @@ static int hpcm_start_vocpcm(char *pcm_id, struct hpcm_drv *prtd,
}
}
if (*no_of_tp != no_of_tp_req && *no_of_tp > 2) {
pr_err("%s:: Invalid hpcm start request\n", __func__);
memset(&prtd->start_cmd, 0, sizeof(struct start_cmd));
return -EINVAL;
}
if ((prtd->mixer_conf.tx.enable || prtd->mixer_conf.rx.enable) &&
*no_of_tp == no_of_tp_req) {
voc_send_cvp_start_vocpcm(voc_get_session_id(sess_name),
@ -731,6 +730,13 @@ void hpcm_notify_evt_processing(uint8_t *data, char *session,
return;
}
if (prtd->mixer_conf.sess_indx < VOICE_INDEX ||
prtd->mixer_conf.sess_indx >= MAX_SESSION) {
pr_err("%s:: Invalid session idx %d\n",
__func__, prtd->mixer_conf.sess_indx);
return;
}
if (notify_evt->tap_point == VSS_IVPCM_TAP_POINT_TX_DEFAULT) {
tp = &prtd->session[prtd->mixer_conf.sess_indx].tx_tap_point;
tmd = &prtd->mixer_conf.tx;

View File

@ -2121,6 +2121,11 @@ static void msm_pcm_routing_process_voice(u16 reg, u16 val, int set)
pr_debug("%s: FE DAI 0x%x session_id 0x%x\n",
__func__, val, session_id);
if (!session_id) {
pr_err("%s: Invalid session_id %x\n", __func__, session_id);
return;
}
mutex_lock(&routing_lock);
if (set)

View File

@ -1,5 +1,6 @@
/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
*
* Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
@ -371,6 +372,14 @@ static void voip_process_ul_pkt(uint8_t *voc_pkt,
switch (prtd->mode) {
case MODE_AMR_WB:
case MODE_AMR: {
if (pkt_len <= DSP_FRAME_HDR_LEN) {
pr_err("%s: pkt_len %d is < required len\n",
__func__, pkt_len);
spin_unlock_irqrestore(&prtd->dsp_ul_lock,
dsp_flags);
return;
}
/* Remove the DSP frame info header. Header format:
* Bits 0-3: Frame rate
* Bits 4-7: Frame type
@ -391,6 +400,14 @@ static void voip_process_ul_pkt(uint8_t *voc_pkt,
case MODE_4GV_NB:
case MODE_4GV_WB:
case MODE_4GV_NW: {
if (pkt_len <= DSP_FRAME_HDR_LEN) {
pr_err("%s: pkt_len %d is < required len\n",
__func__, pkt_len);
spin_unlock_irqrestore(&prtd->dsp_ul_lock,
dsp_flags);
return;
}
/* Remove the DSP frame info header.
* Header format:
* Bits 0-3: frame rate
@ -428,6 +445,14 @@ static void voip_process_ul_pkt(uint8_t *voc_pkt,
buf_node->frame.frm_hdr.timestamp = timestamp;
voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
if (pkt_len <= 2 * DSP_FRAME_HDR_LEN) {
pr_err("%s: pkt_len %d is < required len\n",
__func__, pkt_len);
spin_unlock_irqrestore(&prtd->dsp_ul_lock,
dsp_flags);
return;
}
/* There are two frames in the buffer. Length of the
* first frame:
*/
@ -463,6 +488,13 @@ static void voip_process_ul_pkt(uint8_t *voc_pkt,
buf_node->frame.frm_hdr.timestamp = timestamp;
voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
if (pkt_len <= 2 * DSP_FRAME_HDR_LEN) {
pr_err("%s: pkt_len %d is < required len\n",
__func__, pkt_len);
spin_unlock_irqrestore(&prtd->dsp_ul_lock,
dsp_flags);
return;
}
/* There are two frames in the buffer. Length
* of the second frame:
*/

View File

@ -1,6 +1,8 @@
/*
* Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
*
* Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
@ -78,6 +80,7 @@ static void msm_audio_ion_add_allocation(
mutex_unlock(&(msm_audio_ion_data->list_mutex));
}
/* This function is called with ion_data list mutex lock */
static int msm_audio_dma_buf_map(struct dma_buf *dma_buf,
dma_addr_t *addr, size_t *len)
{
@ -166,7 +169,6 @@ static int msm_audio_dma_buf_unmap(struct dma_buf *dma_buf)
* should be explicitly acquired to avoid race condition
* on adding elements to the list.
*/
mutex_lock(&(msm_audio_ion_data.list_mutex));
list_for_each_safe(ptr, next,
&(msm_audio_ion_data.alloc_list)) {
@ -190,7 +192,6 @@ static int msm_audio_dma_buf_unmap(struct dma_buf *dma_buf)
break;
}
}
mutex_unlock(&(msm_audio_ion_data.list_mutex));
if (!found) {
dev_err(cb_dev,
@ -245,6 +246,7 @@ int msm_audio_ion_get_smmu_info(struct device **cb_dev,
return 0;
}
/* This function is called with ion_data list mutex lock */
static void *msm_audio_ion_map_kernel(struct dma_buf *dma_buf)
{
int rc = 0;
@ -293,7 +295,6 @@ static int msm_audio_ion_unmap_kernel(struct dma_buf *dma_buf)
* TBD: remove the below section once new API
* for unmapping kernel virtual address is available.
*/
mutex_lock(&(msm_audio_ion_data.list_mutex));
list_for_each_entry(alloc_data, &(msm_audio_ion_data.alloc_list),
list) {
if (alloc_data->dma_buf == dma_buf) {
@ -301,7 +302,6 @@ static int msm_audio_ion_unmap_kernel(struct dma_buf *dma_buf)
break;
}
}
mutex_unlock(&(msm_audio_ion_data.list_mutex));
if (!vaddr) {
dev_err(cb_dev,
@ -324,7 +324,8 @@ err:
return rc;
}
static int msm_audio_ion_map_buf(struct dma_buf *dma_buf, dma_addr_t *paddr,
/* This function is called with ion_data list mutex lock */
static int msm_audio_ion_buf_map(struct dma_buf *dma_buf, dma_addr_t *paddr,
size_t *plen, void **vaddr)
{
int rc = 0;
@ -346,7 +347,9 @@ static int msm_audio_ion_map_buf(struct dma_buf *dma_buf, dma_addr_t *paddr,
if (IS_ERR_OR_NULL(*vaddr)) {
pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
rc = -ENOMEM;
mutex_lock(&(msm_audio_ion_data.list_mutex));
msm_audio_dma_buf_unmap(dma_buf);
mutex_unlock(&(msm_audio_ion_data.list_mutex));
goto err;
}
@ -405,7 +408,7 @@ int msm_audio_ion_alloc(struct dma_buf **dma_buf, size_t bufsz,
goto err;
}
rc = msm_audio_ion_map_buf(*dma_buf, paddr, plen, vaddr);
rc = msm_audio_ion_buf_map(*dma_buf, paddr, plen, vaddr);
if (rc) {
pr_err("%s: failed to map ION buf, rc = %d\n", __func__, rc);
goto err;
@ -505,7 +508,7 @@ int msm_audio_ion_import(struct dma_buf **dma_buf, int fd,
}
}
rc = msm_audio_ion_map_buf(*dma_buf, paddr, plen, vaddr);
rc = msm_audio_ion_buf_map(*dma_buf, paddr, plen, vaddr);
if (rc) {
pr_err("%s: failed to map ION buf, rc = %d\n", __func__, rc);
goto err;
@ -531,6 +534,7 @@ EXPORT_SYMBOL(msm_audio_ion_import);
*
* Returns 0 on success or error on failure
*/
/* This funtion is called with ion_data list mutex lock */
int msm_audio_ion_free(struct dma_buf *dma_buf)
{
int ret = 0;
@ -540,11 +544,15 @@ int msm_audio_ion_free(struct dma_buf *dma_buf)
return -EINVAL;
}
mutex_lock(&(msm_audio_ion_data.list_mutex));
ret = msm_audio_ion_unmap_kernel(dma_buf);
if (ret)
if (ret) {
mutex_unlock(&(msm_audio_ion_data.list_mutex));
return ret;
}
msm_audio_dma_buf_unmap(dma_buf);
mutex_unlock(&(msm_audio_ion_data.list_mutex));
return 0;
}

View File

@ -1,14 +1,7 @@
/* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
* SPDX-License-Identifier: GPL-2.0-only
*/
#include <linux/slab.h>
#include <linux/debugfs.h>
#include <linux/kernel.h>
@ -6843,6 +6836,14 @@ static int afe_sidetone_iir(u16 tx_port_id)
pr_debug("%s: adding 2 to size:%d\n", __func__, size);
size = size + 2;
}
if (size > MAX_SIDETONE_IIR_DATA_SIZE) {
pr_err("%s: iir_config size is out of bounds:%d\n", __func__, size);
mutex_unlock(&this_afe.cal_data[cal_index]->lock);
ret = -EINVAL;
goto done;
}
memcpy(&filter_data.iir_config, &st_iir_cal_info->iir_config, size);
mutex_unlock(&this_afe.cal_data[cal_index]->lock);

View File

@ -1,5 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
* Author: Brian Swetland <swetland@google.com>
*
* This software is licensed under the terms of the GNU General Public
@ -2255,6 +2257,15 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
config_debug_fs_read_cb();
if (data->payload_size != (READDONE_IDX_SEQ_ID + 1) * sizeof(uint32_t)) {
pr_err("%s: payload size of %d is less than expected %d.\n",
__func__, data->payload_size,
((READDONE_IDX_SEQ_ID + 1) * sizeof(uint32_t)));
spin_unlock_irqrestore(
&(session[session_id].session_lock),
flags);
return -EINVAL;
}
dev_vdbg(ac->dev, "%s: ReadDone: status=%d buff_add=0x%x act_size=%d offset=%d\n",
__func__, payload[READDONE_IDX_STATUS],
payload[READDONE_IDX_BUFADD_LSW],
@ -2360,7 +2371,16 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
__func__, data->payload_size);
break;
case ASM_SESSION_CMDRSP_GET_MTMX_STRTR_PARAMS_V2:
q6asm_process_mtmx_get_param_rsp(ac, (void *) payload);
payload_size = sizeof(struct asm_mtmx_strtr_get_params_cmdrsp);
if (data->payload_size < payload_size) {
pr_err("%s: insufficient payload size = %d\n",
__func__, data->payload_size);
spin_unlock_irqrestore(
&(session[session_id].session_lock), flags);
return -EINVAL;
}
q6asm_process_mtmx_get_param_rsp(ac,
(struct asm_mtmx_strtr_get_params_cmdrsp *) payload);
break;
case ASM_STREAM_PP_EVENT:
case ASM_STREAM_CMD_ENCDEC_EVENTS:

View File

@ -1,13 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/kernel.h>
@ -196,7 +189,7 @@ EXPORT_SYMBOL(q6core_send_uevent);
static int parse_fwk_version_info(uint32_t *payload, uint16_t payload_size)
{
size_t ver_size;
int num_services;
uint16_t num_services;
pr_debug("%s: Payload info num services %d\n",
__func__, payload[4]);

View File

@ -1,6 +1,7 @@
/*
* Copyright (c) 2013-2019, Linux Foundation. All rights reserved.
*
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
@ -400,6 +401,10 @@ static int q6lsm_apr_send_pkt(struct lsm_client *client, void *handle,
}
pr_debug("%s: enter wait %d\n", __func__, wait);
if (mmap_handle_p) {
pr_debug("%s: Invalid mmap_handle\n", __func__);
return -EINVAL;
}
if (wait)
mutex_lock(&lsm_common.apr_lock);
if (mmap_p) {
@ -443,6 +448,7 @@ static int q6lsm_apr_send_pkt(struct lsm_client *client, void *handle,
if (wait)
mutex_unlock(&lsm_common.apr_lock);
mmap_handle_p = NULL;
pr_debug("%s: leave ret %d\n", __func__, ret);
return ret;
}
@ -1832,7 +1838,8 @@ static int q6lsm_mmapcallback(struct apr_client_data *data, void *priv)
case LSM_SESSION_CMDRSP_SHARED_MEM_MAP_REGIONS:
if (atomic_read(&client->cmd_state) == CMD_STATE_WAIT_RESP) {
spin_lock_irqsave(&mmap_lock, flags);
*mmap_handle_p = command;
if (mmap_handle_p)
*mmap_handle_p = command;
/* spin_unlock_irqrestore implies barrier */
spin_unlock_irqrestore(&mmap_lock, flags);
atomic_set(&client->cmd_state, CMD_STATE_CLEARED);

View File

@ -1,13 +1,6 @@
/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/slab.h>
#include <linux/kthread.h>
@ -2642,6 +2635,13 @@ static int voice_send_cvs_register_cal_cmd(struct voice_data *v)
goto unlock;
}
if (col_data->cal_data.size >= MAX_COL_INFO_SIZE) {
pr_err("%s: Invalid cal data size %d!\n",
__func__, col_data->cal_data.size);
ret = -EINVAL;
goto unlock;
}
memcpy(&cvs_reg_cal_cmd.cvs_cal_data.column_info[0],
(void *) &((struct audio_cal_info_voc_col *)
col_data->cal_info)->data,