blob: 399b9b962dfc57615d8e1a8ff729700c579fdb88 [file] [log] [blame]
/*
* voicebuf.c
*
* Copyright (C) 2010 Mindspeed Technologies, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "cmm.h"
#include "fpp.h"
#include "cmmd.h"
#include "voicebuf.h"
static int voice_file_fd[VOICE_FILE_MAX];
int voice_file_load(FCI_CLIENT *fci_handle, cmmd_voice_file_load_cmd_t *cmd, u_int16_t *res_buf, u_int16_t *res_len)
{
fpp_voice_buffer_load_cmd_t fpp_cmd;
struct usr_scatter_list sc;
int file_fd;
int file_size;
int buf_fd;
int i;
int rc = 0;
cmm_print(DEBUG_INFO, "%s\n", __func__);
*res_len = 2;
if (cmd->file_id >= VOICE_FILE_MAX)
{
cmm_print(DEBUG_ERROR, "%s: fileid(%d) out of range\n", __func__, cmd->file_id);
res_buf[0] = CMMD_ERR_WRONG_COMMAND_PARAM;
goto err0;
}
if (voice_file_fd[cmd->file_id])
{
cmm_print(DEBUG_ERROR, "%s: fileid(%d) already loaded\n", __func__, cmd->file_id);
res_buf[0] = CMMD_ERR_WRONG_COMMAND_PARAM;
goto err0;
}
file_fd = open(cmd->filename, O_RDONLY, 0);
if (file_fd < 0)
{
cmm_print(DEBUG_ERROR, "%s: open(%s) error, %s\n", __func__, cmd->filename, strerror(errno));
rc = -1;
goto err0;
}
buf_fd = open(MEMBUF_CHAR_DEVNAME, O_WRONLY, 0);
if (buf_fd < 0)
{
cmm_print(DEBUG_ERROR, "%s: open(%s) error, %s\n", __func__, MEMBUF_CHAR_DEVNAME, strerror(errno));
rc = -1;
goto err1;
}
file_size = lseek(file_fd, 0, SEEK_END);
if (file_size < 0)
{
cmm_print(DEBUG_ERROR, "%s: lseek() error, %s\n", __func__, strerror(errno));
rc = -1;
goto err2;
}
rc = lseek(buf_fd, file_size, SEEK_SET);
if (rc < 0)
{
cmm_print(DEBUG_ERROR, "%s: lseek() error, %s\n", __func__, strerror(errno));
goto err2;
}
rc = lseek(file_fd, 0, SEEK_SET);
if (rc < 0)
{
cmm_print(DEBUG_ERROR, "%s: lseek() error, %s\n", __func__, strerror(errno));
goto err2;
}
rc = lseek(buf_fd, 0, SEEK_SET);
if (rc < 0)
{
cmm_print(DEBUG_ERROR, "%s: lseek() error, %s\n", __func__, strerror(errno));
goto err2;
}
while (1)
{
char buf[4096];
int len;
len = read(file_fd, buf, 4096);
if (!len)
break;
if (len < 0)
{
if (errno != EINTR)
{
cmm_print(DEBUG_ERROR, "%s: read() error, %s\n", __func__, strerror(errno));
rc = -1;
goto err2;
}
}
while (len)
{
rc = write(buf_fd, buf, len);
if (rc <= 0)
{
if (errno != EINTR)
{
cmm_print(DEBUG_ERROR, "%s: write() error, %s\n", __func__, strerror(errno));
goto err2;
}
continue;
}
len -= rc;
}
}
rc = ioctl(buf_fd, MEMBUF_GET_SCATTER, &sc);
if (rc < 0)
{
cmm_print(DEBUG_ERROR, "%s: ioctl() error, %s\n", __func__, strerror(errno));
goto err2;
}
fpp_cmd.buffer_id = cmd->file_id;
fpp_cmd.payload_type = cmd->payload_type;
fpp_cmd.frame_size = cmd->frame_size;
fpp_cmd.entries = sc.entries;
fpp_cmd.data_len = file_size;
for (i = 0; i < sc.entries; i++)
{
fpp_cmd.page_order[i] = sc.pg_order[i];
fpp_cmd.addr[i] = sc.addr[i];
cmm_print(DEBUG_INFO, "%s: %d %x %x\n", __func__, i, fpp_cmd.page_order[i], fpp_cmd.addr[i]);
}
cmm_print(DEBUG_COMMAND, "%s: Send FPP_CMD_VOICE_BUFFER_LOAD\n", __func__);
rc = fci_cmd(fci_handle, FPP_CMD_VOICE_BUFFER_LOAD, (u_int16_t *) &fpp_cmd, sizeof(fpp_cmd), res_buf, res_len);
if (rc == 0 && res_buf[0] == FPP_ERR_OK)
{
voice_file_fd[cmd->file_id] = buf_fd;
}
else
{
if (rc < 0)
cmm_print(DEBUG_ERROR, "%s: FPP_CMD_VOICE_BUFFER_LOAD failed, '%s'\n", __func__, strerror(errno));
else
cmm_print(DEBUG_ERROR, "%s: FPP_CMD_VOICE_BUFFER_LOAD failed, %d\n", __func__, res_buf[0]);
goto err2;
}
close(file_fd);
return rc;
err2:
close(buf_fd);
err1:
close(file_fd);
err0:
return rc;
}
int voice_file_unload(FCI_CLIENT *fci_handle, cmmd_voice_file_unload_cmd_t *cmd, u_int16_t *res_buf, u_int16_t *res_len)
{
fpp_voice_buffer_unload_cmd_t fpp_cmd;
int rc = 0;
cmm_print(DEBUG_INFO, "%s:\n", __func__);
*res_len = 2;
if (cmd->file_id >= VOICE_FILE_MAX)
{
cmm_print(DEBUG_ERROR, "%s: fileid(%d) out of range\n", __func__, cmd->file_id);
res_buf[0] = CMMD_ERR_WRONG_COMMAND_PARAM;
goto err;
}
if (!voice_file_fd[cmd->file_id])
{
cmm_print(DEBUG_ERROR, "%s: fileid(%d) not loaded\n", __func__, cmd->file_id);
res_buf[0] = CMMD_ERR_WRONG_COMMAND_PARAM;
goto err;
}
fpp_cmd.buffer_id = cmd->file_id;
cmm_print(DEBUG_COMMAND, "%s: Send FPP_CMD_VOICE_BUFFER_UNLOAD\n", __func__);
rc = fci_cmd(fci_handle, FPP_CMD_VOICE_BUFFER_UNLOAD, (u_int16_t *) &fpp_cmd, sizeof(fpp_cmd), res_buf, res_len);
if (rc == 0 && res_buf[0] == FPP_ERR_OK)
{
close(voice_file_fd[cmd->file_id]);
voice_file_fd[cmd->file_id] = 0;
}
else
{
if (rc < 0)
cmm_print(DEBUG_ERROR, "%s: FPP_CMD_VOICE_BUFFER_UNLOAD failed, '%s'\n", __func__, strerror(errno));
else
cmm_print(DEBUG_ERROR, "%s: FPP_CMD_VOICE_BUFFER_UNLOAD failed, %d\n", __func__, res_buf[0]);
goto err;
}
err:
return rc;
}
int voice_buffer_reset(FCI_CLIENT *fci_handle)
{
int rc;
int i;
rc = fci_write(fci_handle, FPP_CMD_VOICE_BUFFER_RESET, 0, NULL);
for (i = 0; i < VOICE_FILE_MAX;i++)
if (voice_file_fd[i])
{
close(voice_file_fd[i]);
voice_file_fd[i] = 0;
}
return rc;
}
static void voice_buffer_set_usage(void)
{
cmm_print(DEBUG_STDOUT,
"Usage: set voicebuf \n"
"\n"
" [load] <file_id> <payload_type> <frame_size> <filename>\n"
"\n"
" [unload] <file_id>\n"
"\n"
" [start] <socket_id> <buffer_id> <seq_number_base> <ssrc> <timestamp_base>\n"
"\n"
" [stop] <socket_id>\n"
);
}
/* CMM client side voicebuf control */
int cmmVoiceBufSetProcess(int argc, char *argv[], daemon_handle_t daemon_handle)
{
char buf[CMM_BUF_SIZE];
int i = 0;
int rc;
const char* cmd_str = NULL;
if (argc < 1)
{
fprintf(stderr, "%s: missing arguments for voicebuf command\n", __func__);
goto err;
}
if (!strncasecmp(argv[i], "load", 4))
{
cmmd_voice_file_load_cmd_t cmd;
if (argc < 5)
{
fprintf(stderr, "%s: missing arguments for voicebuf load command\n", __func__);
goto err;
}
i++;
cmd.file_id = strtoul(argv[i], NULL, 0);
i++;
cmd.payload_type = strtoul(argv[i], NULL, 0);
i++;
cmd.frame_size = strtoul(argv[i], NULL, 0);
i++;
strncpy(cmd.filename, argv[i], CMMD_VOICE_FILE_MAX_NAMESIZE);
rc = cmmSendToDaemon(daemon_handle, CMMD_CMD_VOICE_FILE_LOAD, &cmd, sizeof(cmd), buf);
cmd_str = "CMD_VOICE_FILE_LOAD";
}
else if (!strncasecmp(argv[i], "unload", 6))
{
cmmd_voice_file_unload_cmd_t cmd;
if (argc < 2)
{
fprintf(stderr, "%s: missing arguments for voicebuf unload command\n", __func__);
goto err;
}
i++;
cmd.file_id = strtoul(argv[i], NULL, 0);
rc = cmmSendToDaemon(daemon_handle, CMMD_CMD_VOICE_FILE_UNLOAD, &cmd, sizeof(cmd), buf);
cmd_str = "CMD_VOICE_FILE_UNLOAD";
}
else if (!strncasecmp(argv[i], "start", 5))
{
fpp_voice_buffer_start_cmd_t cmd;
if (argc < 6)
{
fprintf(stderr, "%s: missing arguments for voicebuf start command\n", __func__);
goto err;
}
i++;
cmd.socket_id = strtoul(argv[i], NULL, 0);
i++;
cmd.buffer_id = strtoul(argv[i], NULL, 0);
i++;
cmd.seq_number_base = strtoul(argv[i], NULL, 0);
i++;
cmd.ssrc = strtoul(argv[i], NULL, 0);
i++;
cmd.timestamp_base = strtoul(argv[i], NULL, 0);
rc = cmmSendToDaemon(daemon_handle, FPP_CMD_VOICE_BUFFER_START, &cmd, sizeof(cmd), buf);
cmd_str = "CMD_VOICE_BUFFER_START";
}
else if (!strncasecmp(argv[i], "stop", 4))
{
fpp_voice_buffer_stop_cmd_t cmd;
if (argc < 2)
{
fprintf(stderr, "%s: missing arguments for voicebuf stop command\n", __func__);
goto err;
}
i++;
cmd.socket_id = strtoul(argv[i], NULL, 0);
rc = cmmSendToDaemon(daemon_handle, FPP_CMD_VOICE_BUFFER_STOP, &cmd, sizeof(cmd), buf);
cmd_str = "CMD_VOICE_BUFFER_STOP";
}
else
goto err;
if (rc == 2)
{
if (((u_int16_t*)buf)[0] != CMMD_ERR_OK)
{
fprintf(stdout, "%s: error sending %s: %d\n", __func__, cmd_str, ((u_int16_t*)buf)[0]);
return -1;
}
}
else
{
if (rc > 0)
fprintf(stdout, "%s: unexpected response size received for %s: %d\n", __func__, cmd_str, rc);
else
fprintf(stdout, "%s: error sending %s: '%s'\n", __func__, cmd_str, strerror(errno));
return -1;
}
return 0;
err:
/* print usage */
voice_buffer_set_usage();
return -1;
}