/*
* (C) 2016 by Holger Hans Peter Freyther
* (C) 2016 by On-Waves
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation; either version 3 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
static const struct value_string trau_names[] = {
{ Trau_PrimId_GetCapReq, "Trau_GetCapReq" },
{ Trau_PrimId_GetCapCnf, "Trau_GetCapCnf" },
{ Trau_PrimId_AllocChanReq, "Trau_AllocChanReq" },
{ Trau_PrimId_AllocChanCnf, "Trau_AllocChanCnf" },
{ Trau_PrimId_FreeChanReq, "Trau_FreeChanReq" },
{ Trau_PrimId_SetupChanReq, "Trau_SetupChanReq" },
{ Trau_PrimId_SetupChanCnf, "Trau_SetupChan_Cnf" },
{ Trau_PrimId_ApplyReq, "Trau_ApplyReq" },
{ Trau_PrimId_ApplyCnf, "Trau_ApplyCnf" },
{ 0, NULL },
};
enum {
STATE_NONE,
STATE_ALLOCATED,
STATE_BROKEN,
};
struct dsp_transcode_chan {
int queue_id;
int state;
struct llist_head queue;
};
struct dsp_transcode_mgr {
/* FDs for DSP->ARM, ARM->DSP of the trau queue */
struct osmo_wqueue trau_a2d;
struct osmo_fd trau_d2a;
/* All the channels for transcoding */
struct dsp_transcode_chan chans[TRAU_MAX_CHANNEL];
};
static struct dsp_transcode_mgr g_dsp;
static int trau_arm2dsp_cb(struct osmo_fd *fd, struct msgb *msg)
{
int rc;
rc = write(fd->fd, msg->l2h, msgb_l2len(msg));
if (rc != msgb_l2len(msg)) {
LOGP(DMGCP, LOGL_ERROR,
"Failed to write frame to DSP %d/%d%s\n",
rc, errno, strerror(errno));
return -1;
}
return 0;
}
static void dispatch_trau(struct dsp_transcode_mgr *mgr, struct Trau_Prim *trau)
{
switch (trau->id) {
case Trau_PrimId_AllocChanCnf:
break;
//case Trau_PrimId_FreeChanCnf:
// this doesn't exist but should
}
}
static int trau_dsp2arm_cb(struct osmo_fd *fd, unsigned int what)
{
struct Trau_Prim trau;
int rc;
if (!(what & BSC_FD_READ)) {
LOGP(DMGCP, LOGL_ERROR,
"Activated for not read: %u\n", what);
return -1;
}
rc = read(fd->fd, &trau, sizeof(trua));
if (rc != sizeof(trau)) {
LOGP(DMGCP, LOGL_ERROR,
"Failed to to read trau reply.\n");
return -1;
}
dispatch_trau(&g_dsp, &trau);
return 0;
}
int mgcp_transcoding_dsp_init(void)
{
int i;
memset(&g_dsp, 0, sizeof(g_dsp));
for (i = 0; i < ARRAY_SIZE(g_dsp.chans); ++i)
INIT_LLIST_HEAD(&g_dsp.chans[i].queue);
osmo_wqueue_init(&g_dsp.trau_a2d, 20);
g_dsp.trau_a2d.bfd.data = &g_dsp;
g_dsp.trau_a2d.write_cb = trau_arm2dsp_cb;
g_dsp.trau_a2d.bfd.fd = open("/dev/msgq/trau_arm2dsp", O_WRONLY);
if (g_dsp.trau_a2d.bfd.fd < 0) {
LOGP(DMGCP, LOGL_ERROR, "Failed to open arm2dsp queue: %d/%s\n",
g_dsp.trau_a2d.bfd.fd, strerror(errno));
return 1;
}
g_dsp.trau_d2a.data = &g_dsp;
g_dsp.trau_d2a.cb = trau_dsp2arm_cb;
g_dsp.trau_d2a.fd = open("/dev/msgq/trau_dsp2arm", O_RDONLY);
if (g_dsp.trau_d2a.fd < 0) {
close(g_dsp.trau_a2d.bfd.fd);
return 2;
}
return 0;
}