/*
* EMU10k1 loader
*
* Copyright (c) 2003,2004 by Peter Zubaj
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <alsa/asoundlib.h>
#include <signal.h>
#include "ld10k1.h"
#include "ld10k1_fnc.h"
#include "ld10k1_fnc_int.h"
#include "ld10k1_debug.h"
#include "ld10k1_error.h"
#include "ld10k1_dump.h"
#include "ld10k1_driver.h"
#include "ld10k1_mixer.h"
#include "comm.h"
void ld10k1_fnc_prepare_free();
int ld10k1_fnc_patch_add(int data_conn, int op, int size);
int ld10k1_fnc_patch_del(int data_conn, int op, int size);
int ld10k1_fnc_patch_conn(int data_conn, int op, int size);
int ld10k1_fnc_name_find(int data_conn, int op, int size);
int ld10k1_fnc_name_rename(int data_conn, int op, int size);
int ld10k1_fnc_dsp_init(int data_conn, int op, int size);
int ld10k1_fnc_get_io_count(int data_conn, int op, int size);
int ld10k1_fnc_get_io(int data_conn, int op, int size);
int ld10k1_fnc_get_pio_count(int data_conn, int op, int size);
int ld10k1_fnc_get_pio(int data_conn, int op, int size);
int ld10k1_fnc_get_patches_info(int data_conn, int op, int size);
int ld10k1_fnc_get_patch(int data_conn, int op, int size);
int ld10k1_fnc_dump(int data_conn, int op, int size);
int ld10k1_fnc_version(int data_conn, int op, int size);
int ld10k1_fnc_get_points_info(int data_conn, int op, int size);
int ld10k1_fnc_get_point_info(int data_conn, int op, int size);
int ld10k1_fnc_get_dsp_info(int data_conn, int op, int size);
ld10k1_dsp_mgr_t dsp_mgr;
struct fnc_table_t
{
int fnc;
int min_size;
int max_size;
int (*fnc_code)(int data_conn, int op, int size);
};
struct fnc_table_t fnc_table[] =
{
{FNC_PATCH_ADD, sizeof(ld10k1_fnc_patch_add_t), sizeof(ld10k1_fnc_patch_add_t), ld10k1_fnc_patch_add},
{FNC_PATCH_DEL, sizeof(ld10k1_fnc_patch_del_t), sizeof(ld10k1_fnc_patch_del_t), ld10k1_fnc_patch_del},
{FNC_CONNECTION_ADD, sizeof(ld10k1_fnc_connection_t), sizeof(ld10k1_fnc_connection_t), ld10k1_fnc_patch_conn},
{FNC_CONNECTION_DEL, sizeof(ld10k1_fnc_connection_t), sizeof(ld10k1_fnc_connection_t), ld10k1_fnc_patch_conn},
{FNC_DEBUG, sizeof(ld10k1_fnc_debug_t), sizeof(ld10k1_fnc_debug_t), ld10k1_fnc_debug},
{FNC_PATCH_RENAME, sizeof(ld10k1_fnc_name_t), sizeof(ld10k1_fnc_name_t), ld10k1_fnc_name_rename},
{FNC_PATCH_FIND, sizeof(ld10k1_fnc_name_t), sizeof(ld10k1_fnc_name_t), ld10k1_fnc_name_find},
{FNC_FX_FIND, sizeof(ld10k1_fnc_name_t), sizeof(ld10k1_fnc_name_t), ld10k1_fnc_name_find},
{FNC_IN_FIND, sizeof(ld10k1_fnc_name_t), sizeof(ld10k1_fnc_name_t), ld10k1_fnc_name_find},
{FNC_OUT_FIND, sizeof(ld10k1_fnc_name_t), sizeof(ld10k1_fnc_name_t), ld10k1_fnc_name_find},
{FNC_PATCH_IN_FIND, sizeof(ld10k1_fnc_name_t), sizeof(ld10k1_fnc_name_t), ld10k1_fnc_name_find},
{FNC_PATCH_OUT_FIND, sizeof(ld10k1_fnc_name_t), sizeof(ld10k1_fnc_name_t), ld10k1_fnc_name_find},
{FNC_FX_RENAME, sizeof(ld10k1_fnc_name_t), sizeof(ld10k1_fnc_name_t), ld10k1_fnc_name_rename},
{FNC_IN_RENAME, sizeof(ld10k1_fnc_name_t), sizeof(ld10k1_fnc_name_t), ld10k1_fnc_name_rename},
{FNC_OUT_RENAME, sizeof(ld10k1_fnc_name_t), sizeof(ld10k1_fnc_name_t), ld10k1_fnc_name_rename},
{FNC_PATCH_IN_RENAME, sizeof(ld10k1_fnc_name_t), sizeof(ld10k1_fnc_name_t), ld10k1_fnc_name_rename},
{FNC_PATCH_OUT_RENAME, sizeof(ld10k1_fnc_name_t), sizeof(ld10k1_fnc_name_t), ld10k1_fnc_name_rename},
{FNC_GET_FX_COUNT, 0, 0, ld10k1_fnc_get_io_count},
{FNC_GET_IN_COUNT, 0, 0, ld10k1_fnc_get_io_count},
{FNC_GET_OUT_COUNT, 0, 0, ld10k1_fnc_get_io_count},
{FNC_GET_PIN_COUNT, sizeof(int), sizeof(int), ld10k1_fnc_get_pio_count},
{FNC_GET_POUT_COUNT, sizeof(int), sizeof(int), ld10k1_fnc_get_pio_count},
{FNC_GET_FX, sizeof(int), sizeof(int), ld10k1_fnc_get_io},
{FNC_GET_IN, sizeof(int), sizeof(int), ld10k1_fnc_get_io},
{FNC_GET_OUT, sizeof(int), sizeof(int), ld10k1_fnc_get_io},
{FNC_GET_PIN, sizeof(int) * 2, sizeof(int) * 2, ld10k1_fnc_get_pio},
{FNC_GET_POUT, sizeof(int) * 2, sizeof(int) * 2, ld10k1_fnc_get_pio},
{FNC_GET_PATCHES_INFO, 0, 0, ld10k1_fnc_get_patches_info},
{FNC_GET_PATCH, sizeof(int), sizeof(int), ld10k1_fnc_get_patch},
{FNC_DSP_INIT, 0, 0, ld10k1_fnc_dsp_init},
{FNC_DUMP, 0, 0, ld10k1_fnc_dump},
{FNC_VERSION, 0, 0, ld10k1_fnc_version},
{FNC_GET_POINTS_INFO, 0, 0, ld10k1_fnc_get_points_info},
{FNC_GET_POINT_INFO, sizeof(int), sizeof(int), ld10k1_fnc_get_point_info},
{FNC_GET_DSP_INFO, 0, 0, ld10k1_fnc_get_dsp_info},
{-1, 0, 0, NULL}
};
ld10k1_dsp_mgr_t dsp_mgr;
int send_response_ok(int conn_num)
{
return send_response(conn_num, FNC_OK, 0, NULL, 0);
}
int send_response_err(int conn_num, int err)
{
return send_response(conn_num, FNC_ERR, err, NULL, 0);
}
int send_response_wd(int conn_num, void *data, int data_size)
{
return send_response(conn_num, FNC_OK, 0, data, data_size);
}
struct ClientDefTag
{
int used;
int socket;
};
typedef struct ClientDefTag ClientDef;
#define MAX_CLIENTS 10
ClientDef clients[MAX_CLIENTS];
int clients_count = 0;
static void client_init()
{
int i;
for (i = 0; i < MAX_CLIENTS; i++)
clients[i].used = 0;
clients_count = 0;
}
static int client_add()
{
int i;
for (i = 0; i < MAX_CLIENTS; i++)
if (clients[i].used == 0) {
clients[i].used = 1;
clients_count++;
return i;
}
return -1;
}
static void client_del(int client)
{
if (client >= 0 && client < MAX_CLIENTS && clients[client].used == 1) {
clients[client].used = 0;
clients_count--;
}
}
static int client_find_by_socket(int socket)
{
int i;
for (i = 0; i < MAX_CLIENTS; i++)
if (clients[i].socket == socket)
return i;
return -1;
}
int main_loop(comm_param *param, int audigy, const char *card_id, int tram_size, snd_ctl_t *ctlp)
{
fd_set active_fd_set/*, read_fd_set*/;
int i, j, res = 0;
__sighandler_t old_sig_pipe;
int main_sock = 0;
int data_sock = 0;
int new_client = 0;
int op = 0;
int data_size = 0;
int retval = 0;
dsp_mgr.audigy = audigy;
dsp_mgr.card_id = card_id;
if (ld10k1_dsp_mgr_init(&dsp_mgr))
return -1;
/* initialize id generators */
ld10k1_dsp_mgr_init_id_gen(&dsp_mgr);
if (ld10k1_init_driver(&dsp_mgr, tram_size) < 0) {
ld10k1_dsp_mgr_free(&dsp_mgr);
return -1;
}
if (ld10k1_init_reserved_ctls(&dsp_mgr, ctlp) < 0) {
ld10k1_dsp_mgr_free(&dsp_mgr);
return -1;
}
old_sig_pipe = signal(SIGPIPE, SIG_IGN);
param->server = 1;
if ((main_sock = setup_comm(param)) < 0)
goto error;
if (listen_comm(main_sock))
goto error;
/* Initialize the set of active sockets. */
client_init();
while (1) {
/* Block until input arrives on one or more active sockets. */
FD_ZERO (&active_fd_set);
FD_SET (main_sock, &active_fd_set);
for (i = 0; i < MAX_CLIENTS; i++)
if (clients[i].used)
FD_SET(clients[i].socket, &active_fd_set);
if (select(FD_SETSIZE, &active_fd_set, NULL, NULL, NULL) < 0)
goto error;
for (i = 0; i < FD_SETSIZE; i++)
if (FD_ISSET (i, &active_fd_set)) {
if (i == main_sock) {
/* Connection request on original socket. */
if ((data_sock = accept_comm(main_sock)) < 0)
goto error;
new_client = client_add();
if (new_client < 0)
free_comm(data_sock);
else
clients[new_client].socket = data_sock;
/*FD_SET(data_sock, &active_fd_set);*/
} else {
/* Data arriving on an already-connected socket. */
if (receive_request(i, &op, &data_size))
/*goto error;*/
op = -1; /* probably client closes */
if (op == FNC_CLOSE_CONN) {
/* wait some time */
usleep(10000);
goto e_close;
}
if (op >= 0) {
/* search in function table */
res = 1;
for (j = 0; fnc_table[j].fnc >= 0; j++) {
if ((fnc_table[j].fnc == op) &&
(data_size >= fnc_table[j].min_size) &&
(data_size <= fnc_table[j].max_size)) {
res = (*fnc_table[j].fnc_code)(i, op, data_size);
break;
}
}
if (!res) {
if (send_response(i, FNC_OK, 0, NULL, 0) < 0)
goto e_close;
} else {
if (send_response(i, FNC_ERR, res, NULL, 0) < 0)
goto e_close;
}
} else {
e_close:
if (op != FNC_CLOSE_CONN)
printf("error protocol fnc:%d - %d\n", op, res);
client_del(client_find_by_socket(i));
/*FD_CLR (i, &active_fd_set);*/
/* close connection */
if (free_comm(i))
data_sock = 0;
}
}
}
}
end:
signal(SIGPIPE, old_sig_pipe);
for (i = 0; i < MAX_CLIENTS; i++)
if (clients[i].used) {
client_del(i);
free_comm(clients[i].socket);
}
free_comm(main_sock);
ld10k1_free_reserved_ctls(&dsp_mgr);
ld10k1_dsp_mgr_free(&dsp_mgr);
return retval;
error:
retval = -1;
goto end;
}
int ld10k1_fnc_receive_patch_info(int data_conn, ld10k1_dsp_patch_t *new_patch, int *where)
{
ld10k1_fnc_patch_add_t tmp_info;
if (receive_msg_data(data_conn, &tmp_info, sizeof(ld10k1_fnc_patch_add_t)) < 0)
return LD10K1_ERR_PROTOCOL;
memcpy(new_patch, &(tmp_info.patch), sizeof(ld10k1_dsp_patch_t));
*where = tmp_info.where;
new_patch->patch_name[MAX_NAME_LEN - 1] = '\n';
if (new_patch->in_count < 0 || new_patch->in_count > 32)
return LD10K1_ERR_PROTOCOL_IN_COUNT;
if (new_patch->out_count < 0 || new_patch->out_count > 32)
return LD10K1_ERR_PROTOCOL_OUT_COUNT;
if (new_patch->const_count < 0 || new_patch->const_count > 255)
return LD10K1_ERR_PROTOCOL_CONST_COUNT;
if (new_patch->static_count < 0 || new_patch->static_count > 255)
return LD10K1_ERR_PROTOCOL_STATIC_COUNT;
if (new_patch->dynamic_count < 0 || new_patch->dynamic_count > 255)
return LD10K1_ERR_PROTOCOL_DYNAMIC_COUNT;
if (new_patch->hw_count < 0 || new_patch->hw_count > 255)
return LD10K1_ERR_PROTOCOL_HW_COUNT;
if (new_patch->tram_count < 0 || new_patch->tram_count > 255)
return LD10K1_ERR_PROTOCOL_TRAM_COUNT;
if (new_patch->tram_acc_count < 0 || new_patch->tram_acc_count > 255)
return LD10K1_ERR_PROTOCOL_TRAM_ACC_COUNT;
if (new_patch->ctl_count < 0 || new_patch->ctl_count > 255)
return LD10K1_ERR_PROTOCOL_CTL_COUNT;
if (new_patch->instr_count < 0 || new_patch->instr_count > 512)
return LD10K1_ERR_PROTOCOL_INSTR_COUNT;
return send_response_ok(data_conn);
}
int ld10k1_fnc_receive_patch_in(int data_conn, ld10k1_patch_t *new_patch)
{
ld10k1_dsp_p_in_out_t *new_in = NULL;
int i;
int err;
if (!new_patch->in_count)
return 0;
if (!(new_in = (ld10k1_dsp_p_in_out_t *)receive_msg_data_malloc(data_conn, sizeof(ld10k1_dsp_p_in_out_t) * new_patch->in_count)))
return LD10K1_ERR_PROTOCOL;
/* copy values */
for (i = 0; i < new_patch->in_count; i++) {
if (!ld10k1_dsp_mgr_name_new(&(new_patch->ins[i].name), new_in[i].name)) {
err = LD10K1_ERR_NO_MEM;
goto error;
}
}
return send_response_ok(data_conn);
error:
free(new_in);
return err;
}
int ld10k1_fnc_receive_patch_out(int data_conn, ld10k1_patch_t *new_patch)
{
ld10k1_dsp_p_in_out_t *new_out = NULL;
int i;
int err;
if (!new_patch->out_count)
return 0;
if (!(new_out = (ld10k1_dsp_p_in_out_t *)receive_msg_data_malloc(data_conn, sizeof(ld10k1_dsp_p_in_out_t) * new_patch->out_count)))
return LD10K1_ERR_PROTOCOL;
/* copy values */
for (i = 0; i < new_patch->out_count; i++) {
if (!ld10k1_dsp_mgr_name_new(&(new_patch->outs[i].name), new_out[i].name)) {
err = LD10K1_ERR_NO_MEM;
goto error;
}
}
return send_response_ok(data_conn);
error:
free(new_out);
return err;
}
int ld10k1_fnc_receive_patch_const(int data_conn, ld10k1_patch_t *new_patch)
{
ld10k1_dsp_p_const_static_t *new_const = NULL;
int i;
if (!new_patch->const_count)
return 0;
if (!(new_const = (ld10k1_dsp_p_const_static_t *)receive_msg_data_malloc(data_conn, sizeof(ld10k1_dsp_p_const_static_t) * new_patch->const_count)))
return LD10K1_ERR_PROTOCOL;
/* copy values */
for (i = 0; i < new_patch->const_count; i++)
new_patch->consts[i].const_val = new_const[i].const_val;
return send_response_ok(data_conn);
}
int ld10k1_fnc_receive_patch_sta(int data_conn, ld10k1_patch_t *new_patch)
{
ld10k1_dsp_p_const_static_t *new_sta = NULL;
int i;
if (!new_patch->sta_count)
return 0;
if (!(new_sta = (ld10k1_dsp_p_const_static_t *)receive_msg_data_malloc(data_conn, sizeof(ld10k1_dsp_p_const_static_t) * new_patch->sta_count)))
return LD10K1_ERR_PROTOCOL;
/* copy values */
for (i = 0; i < new_patch->sta_count; i++)
new_patch->stas[i].const_val = new_sta[i].const_val;
return send_response_ok(data_conn);
}
int ld10k1_fnc_receive_patch_hw(int data_conn, ld10k1_patch_t *new_patch)
{
ld10k1_dsp_p_hw_t *new_hw = NULL;
int i;
if (!new_patch->hw_count)
return 0;
if (!(new_hw = (ld10k1_dsp_p_hw_t *)receive_msg_data_malloc(data_conn, sizeof(ld10k1_dsp_p_hw_t) * new_patch->hw_count)))
return LD10K1_ERR_PROTOCOL;
/* copy values */
for (i = 0; i < new_patch->hw_count; i++)
new_patch->hws[i].reg_idx = new_hw[i].hw_val;
return send_response_ok(data_conn);
}
int ld10k1_fnc_receive_patch_tram_grp(int data_conn, ld10k1_patch_t *new_patch)
{
ld10k1_dsp_tram_grp_t *new_tram_grp = NULL;
int i;
if (!new_patch->tram_count)
return 0;
if (!(new_tram_grp = (ld10k1_dsp_tram_grp_t *)receive_msg_data_malloc(data_conn, sizeof(ld10k1_dsp_tram_grp_t) * new_patch->tram_count)))
return LD10K1_ERR_PROTOCOL;
/* copy values */
for (i = 0; i < new_patch->tram_count; i++) {
new_patch->tram_grp[i].grp_type = new_tram_grp[i].grp_type;
new_patch->tram_grp[i].grp_size = new_tram_grp[i].grp_size;
new_patch->tram_grp[i].grp_pos = new_tram_grp[i].grp_pos;
}
return send_response_ok(data_conn);
}
int ld10k1_fnc_receive_patch_tram_acc(int data_conn, ld10k1_patch_t *new_patch)
{
ld10k1_dsp_tram_acc_t *new_tram_acc = NULL;
int i;
if (!new_patch->tram_acc_count)
return 0;
if (!(new_tram_acc = (ld10k1_dsp_tram_acc_t *)receive_msg_data_malloc(data_conn, sizeof(ld10k1_dsp_tram_acc_t) * new_patch->tram_acc_count)))
return LD10K1_ERR_PROTOCOL;
/* copy values */
for (i = 0; i < new_patch->tram_acc_count; i++) {
new_patch->tram_acc[i].acc_type = new_tram_acc[i].acc_type;
new_patch->tram_acc[i].acc_offset = new_tram_acc[i].acc_offset;
new_patch->tram_acc[i].grp = new_tram_acc[i].grp;
}
return send_response_ok(data_conn);
}
int ld10k1_fnc_receive_patch_ctl(int data_conn, ld10k1_patch_t *new_patch)
{
ld10k1_dsp_ctl_t *new_ctl = NULL;
int i, j;
if (!new_patch->ctl_count)
return 0;
if (!(new_ctl = (ld10k1_dsp_ctl_t *)receive_msg_data_malloc(data_conn, sizeof(ld10k1_dsp_ctl_t) * new_patch->ctl_count)))
return LD10K1_ERR_PROTOCOL;
/* copy values */
for (i = 0; i < new_patch->ctl_count; i++) {
strncpy(new_patch->ctl[i].name, new_ctl[i].name, 43);
new_patch->ctl[i].name[43] = '\0';
new_patch->ctl[i].index = -1;
new_patch->ctl[i].want_index = new_ctl[i].index;
new_patch->ctl[i].count = new_ctl[i].count;
new_patch->ctl[i].vcount = new_ctl[i].vcount;
new_patch->ctl[i].min = new_ctl[i].min;
new_patch->ctl[i].max = new_ctl[i].max;
new_patch->ctl[i].translation = new_ctl[i].translation;
for (j = 0; j < new_patch->ctl[i].count; j++)
new_patch->ctl[i].value[j] = new_ctl[i].value[j];
}
return send_response_ok(data_conn);
}
int ld10k1_fnc_receive_patch_instr(int data_conn, ld10k1_patch_t *new_patch)
{
ld10k1_dsp_instr_t *new_instr = NULL;
int i, j;
if (!new_patch->instr_count)
return 0;
if (!(new_instr = (ld10k1_dsp_instr_t *)receive_msg_data_malloc(data_conn, sizeof(ld10k1_dsp_instr_t) * new_patch->instr_count)))
return LD10K1_ERR_PROTOCOL;
/* copy values */
for (i = 0; i < new_patch->instr_count; i++) {
new_patch->instr[i].op_code = new_instr[i].op_code;
for (j = 0; j < 4; j++)
new_patch->instr[i].arg[j] = new_instr[i].arg[j];
new_patch->instr[i].used = 1;
new_patch->instr[i].modified = 1;
}
return send_response_ok(data_conn);
}
int ld10k1_fnc_patch_add(int data_conn, int op, int size)
{
int err;
int loaded[2];
int where;
ld10k1_dsp_patch_t new_patch_info;
/* allocate new patch */
ld10k1_patch_t *new_patch = NULL;
if ((err = ld10k1_fnc_receive_patch_info(data_conn, &new_patch_info, &where)) < 0)
goto error;
if (!(new_patch = ld10k1_dsp_mgr_patch_new())) {
err = LD10K1_ERR_NO_MEM;
goto error;
}
/* name */
if (!ld10k1_dsp_mgr_name_new(&(new_patch->patch_name), new_patch_info.patch_name)) {
err = LD10K1_ERR_NO_MEM;
goto error;
}
/* set sizes */
if (new_patch_info.in_count)
if (!ld10k1_dsp_mgr_patch_in_new(new_patch, new_patch_info.in_count)) {
err = LD10K1_ERR_NO_MEM;
goto error;
}
if (new_patch_info.out_count)
if (!ld10k1_dsp_mgr_patch_out_new(new_patch, new_patch_info.out_count)) {
err = LD10K1_ERR_NO_MEM;
goto error;
}
if (new_patch_info.const_count)
if (!ld10k1_dsp_mgr_patch_const_new(new_patch, new_patch_info.const_count)) {
err = LD10K1_ERR_NO_MEM;
goto error;
}
if (new_patch_info.static_count)
if (!ld10k1_dsp_mgr_patch_sta_new(new_patch, new_patch_info.static_count)) {
err = LD10K1_ERR_NO_MEM;
goto error;
}
if (new_patch_info.dynamic_count)
if (!ld10k1_dsp_mgr_patch_dyn_new(new_patch, new_patch_info.dynamic_count)) {
err = LD10K1_ERR_NO_MEM;
goto error;
}
if (new_patch_info.hw_count)
if (!ld10k1_dsp_mgr_patch_hw_new(new_patch, new_patch_info.hw_count)) {
err = LD10K1_ERR_NO_MEM;
goto error;
}
if (new_patch_info.tram_count)
if (!ld10k1_dsp_mgr_patch_tram_new(new_patch, new_patch_info.tram_count)) {
err = LD10K1_ERR_NO_MEM;
goto error;
}
if (new_patch_info.tram_acc_count)
if (!ld10k1_dsp_mgr_patch_tram_acc_new(new_patch, new_patch_info.tram_acc_count)) {
err = LD10K1_ERR_NO_MEM;
goto error;
}
if (new_patch_info.ctl_count)
if (!ld10k1_dsp_mgr_patch_ctl_new(new_patch,new_patch_info.ctl_count)) {
err = LD10K1_ERR_NO_MEM;
goto error;
}
if (!ld10k1_dsp_mgr_patch_instr_new(new_patch, new_patch_info.instr_count)) {
err = LD10K1_ERR_NO_MEM;
goto error;
}
/* receive next parts */
if (new_patch_info.in_count)
if ((err = ld10k1_fnc_receive_patch_in(data_conn, new_patch)) < 0)
goto error;
if (new_patch_info.out_count)
if ((err = ld10k1_fnc_receive_patch_out(data_conn, new_patch)) < 0)
goto error;
if (new_patch_info.const_count)
if ((err = ld10k1_fnc_receive_patch_const(data_conn, new_patch)) < 0)
goto error;
if (new_patch_info.static_count)
if ((err = ld10k1_fnc_receive_patch_sta(data_conn, new_patch)) < 0)
goto error;
if (new_patch_info.hw_count)
if ((err = ld10k1_fnc_receive_patch_hw(data_conn, new_patch)) < 0)
goto error;
if (new_patch_info.tram_count)
if ((err = ld10k1_fnc_receive_patch_tram_grp(data_conn, new_patch)) < 0)
goto error;
if (new_patch_info.tram_acc_count)
if ((err = ld10k1_fnc_receive_patch_tram_acc(data_conn, new_patch)) < 0)
goto error;
if (new_patch_info.ctl_count)
if ((err = ld10k1_fnc_receive_patch_ctl(data_conn, new_patch)) < 0)
goto error;
if ((err = ld10k1_fnc_receive_patch_instr(data_conn, new_patch)) < 0)
goto error;
/* check patch */
if ((err = ld10k1_patch_fnc_check_patch(&dsp_mgr, new_patch)) < 0)
goto error;
/* load patch */
if ((err = ld10k1_dsp_mgr_patch_load(&dsp_mgr, new_patch, where, loaded)) < 0)
goto error;
if ((err = send_response_wd(data_conn, loaded, sizeof(loaded))) < 0)
return err;
return 0;
error:
if (new_patch)
ld10k1_dsp_mgr_patch_free(new_patch);
return err;
}
int ld10k1_fnc_patch_del(int data_conn, int op, int size)
{
ld10k1_fnc_patch_del_t patch_info;
int err;
if ((err = receive_msg_data(data_conn, &patch_info, sizeof(ld10k1_fnc_patch_del_t))) < 0)
return err;
return ld10k1_patch_fnc_del(&dsp_mgr, &patch_info);
}
int ld10k1_fnc_patch_conn(int data_conn, int op, int size)
{
ld10k1_fnc_connection_t connection_info;
int err;
int conn_id;
if ((err = receive_msg_data(data_conn, &connection_info, sizeof(ld10k1_fnc_connection_t))) < 0)
return err;
if ((err = ld10k1_connection_fnc(&dsp_mgr, &connection_info, &conn_id)) < 0)
return err;
return send_response_wd(data_conn, &conn_id, sizeof(conn_id));
}
int ld10k1_fnc_name_find(int data_conn, int op, int size)
{
ld10k1_fnc_name_t name_info;
int i;
static int ret;
int err;
ld10k1_patch_t *patch;
ret = -1;
if ((err = receive_msg_data(data_conn, &name_info, sizeof(ld10k1_fnc_name_t))) < 0)
return err;
name_info.name[MAX_NAME_LEN - 1] = '\0';
switch (op) {
case FNC_PATCH_FIND:
for (i = 0; i < EMU10K1_PATCH_MAX ; i++)
if (dsp_mgr.patch_ptr[i])
if (strcmp(dsp_mgr.patch_ptr[i]->patch_name, name_info.name) == 0) {
ret = i;
break;
}
break;
case FNC_FX_FIND:
for (i = 0; i < dsp_mgr.fx_count ; i++)
if (dsp_mgr.fxs[i].name)
if (strcmp(dsp_mgr.fxs[i].name, name_info.name) == 0) {
ret = i;
break;
}
break;
case FNC_IN_FIND:
for (i = 0; i < dsp_mgr.in_count ; i++)
if (dsp_mgr.ins[i].name)
if (strcmp(dsp_mgr.ins[i].name, name_info.name) == 0) {
ret = i;
break;
}
break;
case FNC_OUT_FIND:
for (i = 0; i < dsp_mgr.out_count ; i++)
if (dsp_mgr.outs[i].name)
if (strcmp(dsp_mgr.outs[i].name, name_info.name) == 0) {
ret = i;
break;
}
break;
case FNC_PATCH_IN_FIND :
if (name_info.patch_num >= 0 || name_info.patch_num < EMU10K1_PATCH_MAX) {
patch = dsp_mgr.patch_ptr[name_info.patch_num];
if (patch)
for (i = 0; i < patch->in_count ; i++)
if (patch->ins[i].name)
if (strcmp(patch->ins[i].name, name_info.name) == 0) {
ret = i;
break;
}
}
break;
case FNC_PATCH_OUT_FIND :
if (name_info.patch_num >= 0 || name_info.patch_num < EMU10K1_PATCH_MAX) {
patch = dsp_mgr.patch_ptr[name_info.patch_num];
if (patch)
for (i = 0; i < patch->out_count ; i++)
if (patch->outs[i].name)
if (strcmp(patch->outs[i].name, name_info.name) == 0) {
ret = i;
break;
}
}
break;
}
return send_response_wd(data_conn, &ret, sizeof(ret));
}
int ld10k1_fnc_name_rename(int data_conn, int op, int size)
{
ld10k1_fnc_name_t name_info;
int ret;
int err;
ld10k1_patch_t *patch;
ret = -1;
if ((err = receive_msg_data(data_conn, &name_info, sizeof(ld10k1_fnc_name_t))) < 0)
return err;
name_info.name[MAX_NAME_LEN - 1] = '\0';
switch (op) {
case FNC_PATCH_RENAME:
if (name_info.patch_num >= 0 || name_info.patch_num < EMU10K1_PATCH_MAX) {
patch = dsp_mgr.patch_ptr[name_info.patch_num];
if (patch) {
if (!ld10k1_dsp_mgr_name_new(&(patch->patch_name), name_info.name))
return LD10K1_ERR_PATCH_RENAME;
} else
return LD10K1_ERR_UNKNOWN_PATCH_NUM;
} else
return LD10K1_ERR_UNKNOWN_PATCH_NUM;
break;
case FNC_FX_RENAME:
if (name_info.gpr < 0 || name_info.gpr >= dsp_mgr.fx_count)
return LD10K1_ERR_UNKNOWN_REG_NUM;
if (!ld10k1_dsp_mgr_name_new(&(dsp_mgr.fxs[name_info.gpr].name), name_info.name))
return LD10K1_ERR_REG_RENAME;
break;
case FNC_IN_RENAME:
if (name_info.gpr < 0 || name_info.gpr >= dsp_mgr.in_count)
return LD10K1_ERR_UNKNOWN_REG_NUM;
if (!ld10k1_dsp_mgr_name_new(&(dsp_mgr.ins[name_info.gpr].name), name_info.name))
return LD10K1_ERR_REG_RENAME;
break;
case FNC_OUT_RENAME:
if (name_info.gpr < 0 || name_info.gpr >= dsp_mgr.out_count)
return LD10K1_ERR_UNKNOWN_REG_NUM;
if (!ld10k1_dsp_mgr_name_new(&(dsp_mgr.outs[name_info.gpr].name), name_info.name))
return LD10K1_ERR_REG_RENAME;
break;
case FNC_PATCH_IN_RENAME:
if (name_info.patch_num >= 0 || name_info.patch_num < EMU10K1_PATCH_MAX) {
patch = dsp_mgr.patch_ptr[name_info.patch_num];
if (patch) {
if (name_info.gpr < 0 || name_info.gpr >= patch->in_count)
return LD10K1_ERR_UNKNOWN_PATCH_REG_NUM;
if (!ld10k1_dsp_mgr_name_new(&(patch->ins[name_info.gpr].name), name_info.name))
return LD10K1_ERR_PATCH_REG_RENAME;
} else
return LD10K1_ERR_UNKNOWN_PATCH_NUM;
} else
return LD10K1_ERR_UNKNOWN_PATCH_NUM;
break;
case FNC_PATCH_OUT_RENAME:
if (name_info.patch_num >= 0 || name_info.patch_num < EMU10K1_PATCH_MAX) {
patch = dsp_mgr.patch_ptr[name_info.patch_num];
if (patch) {
if (name_info.gpr < 0 || name_info.gpr >= patch->out_count)
return LD10K1_ERR_UNKNOWN_PATCH_REG_NUM;
if (!ld10k1_dsp_mgr_name_new(&(patch->outs[name_info.gpr].name), name_info.name))
return LD10K1_ERR_PATCH_REG_RENAME;
} else
return LD10K1_ERR_UNKNOWN_PATCH_NUM;
} else
return LD10K1_ERR_UNKNOWN_PATCH_NUM;
break;
}
return 0;
}
int ld10k1_fnc_dsp_init(int data_conn, int op, int size)
{
int audigy;
int err, i;
ld10k1_reserved_ctl_list_item_t *rlist;
int save_ids[EMU10K1_PATCH_MAX];
audigy = dsp_mgr.audigy;
rlist = dsp_mgr.reserved_ctl_list; /* FIXME - hack to save reserved ctls and ids */
for (i = 0; i < EMU10K1_PATCH_MAX; i++)
save_ids[i] = dsp_mgr.patch_id_gens[i];
ld10k1_dsp_mgr_free(&dsp_mgr);
memset(&dsp_mgr, 0, sizeof(dsp_mgr));
dsp_mgr.audigy = audigy;
if ((err = ld10k1_dsp_mgr_init(&dsp_mgr)) < 0)
return err;
dsp_mgr.reserved_ctl_list = rlist; /* hack to seve reserved ctls */
for (i = 0; i < EMU10K1_PATCH_MAX; i++)
dsp_mgr.patch_id_gens[i] = save_ids[i];
return ld10k1_init_driver(&dsp_mgr, -1);
}
int ld10k1_fnc_get_io_count(int data_conn, int op, int size)
{
int reg_count;
reg_count = 0;
if (op == FNC_GET_FX_COUNT)
/* fxs */
reg_count = dsp_mgr.fx_count;
else if (op == FNC_GET_IN_COUNT)
/* ins */
reg_count = dsp_mgr.in_count;
else
/* outs */
reg_count = dsp_mgr.out_count;
return send_response_wd(data_conn, ®_count, sizeof(int));
}
int ld10k1_fnc_get_io(int data_conn, int op, int size)
{
int err;
int reg_count;
int reg_num;
ld10k1_fnc_get_io_t io;
if ((err = receive_msg_data(data_conn, ®_num, sizeof(int))) < 0)
return err;
if (op == FNC_GET_FX)
/* fx */
reg_count = dsp_mgr.fx_count;
else if (op == FNC_GET_IN)
/* in */
reg_count = dsp_mgr.in_count;
else
/* out */
reg_count = dsp_mgr.out_count;
if (reg_num < 0 || reg_num >= reg_count)
return LD10K1_ERR_UNKNOWN_REG_NUM;
if (op == FNC_GET_FX) {
/* fx */
memset(io.name, 0, sizeof(io.name));
if (dsp_mgr.fxs[reg_num].name)
strcpy(io.name, dsp_mgr.fxs[reg_num].name);
} else if (op == FNC_GET_IN) {
/* in */
memset(io.name, 0, sizeof(io.name));
if (dsp_mgr.ins[reg_num].name)
strcpy(io.name, dsp_mgr.ins[reg_num].name);
} else {
/* out */
memset(io.name, 0, sizeof(io.name));
if (dsp_mgr.outs[reg_num].name)
strcpy(io.name, dsp_mgr.outs[reg_num].name);
}
return send_response_wd(data_conn, &io, sizeof(ld10k1_fnc_get_io_t));
}
int ld10k1_fnc_get_pio_count(int data_conn, int op, int size)
{
int patch_num;
int err;
int reg_count;
ld10k1_patch_t *patch;
if ((err = receive_msg_data(data_conn, &patch_num, sizeof(int))) < 0)
return err;
reg_count = 0;
/* patch */
if (patch_num >= 0 && patch_num < EMU10K1_PATCH_MAX) {
/* patch register */
patch = dsp_mgr.patch_ptr[patch_num];
if (!patch)
return LD10K1_ERR_UNKNOWN_PATCH_NUM;
if (op == FNC_GET_PIN_COUNT)
/* pin */
reg_count = patch->in_count;
else
/* pout */
reg_count = patch->out_count;
} else
return LD10K1_ERR_UNKNOWN_PATCH_NUM;
return send_response_wd(data_conn, ®_count, sizeof(int));
}
int ld10k1_fnc_get_pio(int data_conn, int op, int size)
{
int patch_num;
int reg_num;
int err;
int tmp_num[2];
int reg_count;
ld10k1_fnc_get_io_t io;
ld10k1_patch_t *patch;
if ((err = receive_msg_data(data_conn, tmp_num, sizeof(int) * 2)) < 0)
return err;
patch_num = tmp_num[0];
reg_num = tmp_num[1];
reg_count = 0;
/* patch */
if (patch_num >= 0 && patch_num < EMU10K1_PATCH_MAX) {
/* patch register */
patch = dsp_mgr.patch_ptr[patch_num];
if (!patch)
return LD10K1_ERR_UNKNOWN_PATCH_NUM;
if (op == FNC_GET_PIN)
/* pin */
reg_count = patch->in_count;
else
/* pout */
reg_count = patch->out_count;
if (reg_num < 0 || reg_num >= reg_count)
return LD10K1_ERR_UNKNOWN_PATCH_REG_NUM;
if (op == FNC_GET_PIN) {
/* pin */
memset(io.name, 0, sizeof(io.name));
if (patch->ins[reg_num].name)
strcpy(io.name, patch->ins[reg_num].name);
} else {
/* pout */
memset(io.name, 0, sizeof(io.name));
if (patch->outs[reg_num].name)
strcpy(io.name, patch->outs[reg_num].name);
}
} else
return LD10K1_ERR_UNKNOWN_PATCH_NUM;
return send_response_wd(data_conn, &io, sizeof(ld10k1_fnc_get_io_t));
}
int ld10k1_fnc_get_patches_info(int data_conn, int op, int size)
{
int i, idx, j;
ld10k1_fnc_patches_info_t *info;
ld10k1_patch_t *patch;
info = NULL;
if (dsp_mgr.patch_count >= 0) {
/* alloc space */
info = (ld10k1_fnc_patches_info_t *)malloc(sizeof(ld10k1_fnc_patches_info_t) * dsp_mgr.patch_count);
if (!info)
return LD10K1_ERR_NO_MEM;
memset(info, 0, sizeof(ld10k1_fnc_patches_info_t) * dsp_mgr.patch_count);
/* copy values */
for (i = 0, j = 0; i < dsp_mgr.patch_count; i++) {
idx = dsp_mgr.patch_order[i];
patch = dsp_mgr.patch_ptr[idx];
if (patch) {
info[j].patch_num = idx;
info[j].id = patch->id;
strcpy(info[j].patch_name, patch->patch_name);
j++;
}
}
}
return send_response_wd(data_conn, info, sizeof(ld10k1_fnc_patches_info_t) * dsp_mgr.patch_count);
}
int ld10k1_fnc_version(int data_conn, int op, int size)
{
ld10k1_fnc_version_t version;
strcpy(version.ld10k1_version, VERSION);
return send_response_wd(data_conn, &version, sizeof(ld10k1_fnc_version_t));
}
int ld10k1_fnc_send_patch_in(int data_conn, ld10k1_patch_t *patch)
{
int i, err;
ld10k1_dsp_p_in_out_t *ins = NULL;
if (patch->in_count) {
ins = (ld10k1_dsp_p_in_out_t *)malloc(sizeof(ld10k1_dsp_p_in_out_t) * patch->in_count);
if (!ins)
return LD10K1_ERR_NO_MEM;
memset(ins, 0, sizeof(ld10k1_dsp_p_in_out_t) * patch->in_count);
for (i = 0; i < patch->in_count; i++) {
if (patch->ins[i].name)
strcpy(ins[i].name, patch->ins[i].name);
else
ins[i].name[0] = '\0';
}
if ((err = send_response(data_conn, FNC_CONTINUE, 0, ins, sizeof(ld10k1_dsp_p_in_out_t) * patch->in_count)) < 0) {
free(ins);
return err;
}
free(ins);
}
return 0;
}
int ld10k1_fnc_send_patch_out(int data_conn, ld10k1_patch_t *patch)
{
int i, err;
ld10k1_dsp_p_in_out_t *outs = NULL;
if (patch->out_count) {
outs = (ld10k1_dsp_p_in_out_t *)malloc(sizeof(ld10k1_dsp_p_in_out_t) * patch->out_count);
if (!outs)
return LD10K1_ERR_NO_MEM;
memset(outs, 0, sizeof(ld10k1_dsp_p_in_out_t) * patch->out_count);
for (i = 0; i < patch->out_count; i++) {
if (patch->outs[i].name)
strcpy(outs[i].name, patch->outs[i].name);
else
outs[i].name[0] = '\0';
}
if ((err = send_response(data_conn, FNC_CONTINUE, 0, outs, sizeof(ld10k1_dsp_p_in_out_t) * patch->out_count)) < 0) {
free(outs);
return err;
}
free(outs);
}
return 0;
}
int ld10k1_fnc_send_patch_const(int data_conn, ld10k1_patch_t *patch)
{
int i, err;
ld10k1_dsp_p_const_static_t *consts = NULL;
if (patch->const_count) {
consts = (ld10k1_dsp_p_const_static_t *)malloc(sizeof(ld10k1_dsp_p_const_static_t) * patch->const_count);
if (!consts)
return LD10K1_ERR_NO_MEM;
for (i = 0; i < patch->const_count; i++)
consts[i].const_val = patch->consts[i].const_val;
if ((err = send_response(data_conn, FNC_CONTINUE, 0, consts, sizeof(ld10k1_dsp_p_const_static_t) * patch->const_count)) < 0) {
free(consts);
return err;
}
free(consts);
}
return 0;
}
int ld10k1_fnc_send_patch_sta(int data_conn, ld10k1_patch_t *patch)
{
int i, err;
ld10k1_dsp_p_const_static_t *stas = NULL;
if (patch->sta_count) {
stas = (ld10k1_dsp_p_const_static_t *)malloc(sizeof(ld10k1_dsp_p_const_static_t) * patch->sta_count);
if (!stas)
return LD10K1_ERR_NO_MEM;
for (i = 0; i < patch->sta_count; i++)
stas[i].const_val = patch->stas[i].const_val;
if ((err = send_response(data_conn, FNC_CONTINUE, 0, stas, sizeof(ld10k1_dsp_p_const_static_t) * patch->sta_count)) < 0) {
free(stas);
return err;
}
free(stas);
}
return 0;
}
int ld10k1_fnc_send_patch_hw(int data_conn, ld10k1_patch_t *patch)
{
int i, err;
ld10k1_dsp_p_hw_t *hws = NULL;
if (patch->hw_count) {
hws = (ld10k1_dsp_p_hw_t *)malloc(sizeof(ld10k1_dsp_p_hw_t) * patch->hw_count);
if (!hws)
return LD10K1_ERR_NO_MEM;
for (i = 0; i < patch->hw_count; i++)
hws[i].hw_val = patch->hws[i].reg_idx;
if ((err = send_response(data_conn, FNC_CONTINUE, 0, hws, sizeof(ld10k1_dsp_p_hw_t) * patch->hw_count)) < 0) {
free(hws);
return err;
}
free(hws);
}
return 0;
}
int ld10k1_fnc_send_patch_tram_grp(int data_conn, ld10k1_patch_t *patch)
{
int i, err;
ld10k1_dsp_tram_grp_t *grps = NULL;
if (patch->tram_count) {
grps = (ld10k1_dsp_tram_grp_t *)malloc(sizeof(ld10k1_dsp_tram_grp_t) * patch->tram_count);
if (!grps)
return LD10K1_ERR_NO_MEM;
for (i = 0; i < patch->tram_count; i++) {
grps[i].grp_type = patch->tram_grp[i].grp_type;
grps[i].grp_size = patch->tram_grp[i].grp_size;
grps[i].grp_pos = patch->tram_grp[i].grp_pos;
}
if ((err = send_response(data_conn, FNC_CONTINUE, 0, grps, sizeof(ld10k1_dsp_tram_grp_t) * patch->tram_count)) < 0) {
free(grps);
return err;
}
free(grps);
}
return 0;
}
int ld10k1_fnc_send_patch_tram_acc(int data_conn, ld10k1_patch_t *patch)
{
int i, err;
ld10k1_dsp_tram_acc_t *accs = NULL;
if (patch->tram_acc_count) {
accs = (ld10k1_dsp_tram_acc_t *)malloc(sizeof(ld10k1_dsp_tram_acc_t) * patch->tram_acc_count);
if (!accs)
return LD10K1_ERR_NO_MEM;
for (i = 0; i < patch->tram_acc_count; i++) {
accs[i].acc_type = patch->tram_acc[i].acc_type;
accs[i].acc_offset = patch->tram_acc[i].acc_offset;
accs[i].grp = patch->tram_acc[i].grp;
}
if ((err = send_response(data_conn, FNC_CONTINUE, 0, accs, sizeof(ld10k1_dsp_tram_acc_t) * patch->tram_acc_count)) < 0) {
free(accs);
return err;
}
free(accs);
}
return 0;
}
int ld10k1_fnc_send_patch_ctl(int data_conn, ld10k1_patch_t *patch)
{
int i, j, err;
ld10k1_dsp_ctl_t *ctls = NULL;
if (patch->ctl_count) {
ctls = (ld10k1_dsp_ctl_t *)malloc(sizeof(ld10k1_dsp_ctl_t) * patch->ctl_count);
if (!ctls)
return LD10K1_ERR_NO_MEM;
memset(ctls, 0, sizeof(ld10k1_dsp_ctl_t) * patch->ctl_count);
for (i = 0; i < patch->ctl_count; i++) {
strncpy(ctls[i].name, patch->ctl[i].name, 43);
ctls[i].name[43] = '\0';
ctls[i].index = patch->ctl[i].want_index;
ctls[i].count = patch->ctl[i].count;
ctls[i].vcount = patch->ctl[i].vcount;
ctls[i].min = patch->ctl[i].min;
ctls[i].max = patch->ctl[i].max;
ctls[i].translation = patch->ctl[i].translation;
for (j = 0; j < ctls[i].count; j++)
ctls[i].value[j] = patch->ctl[i].value[j];
}
if ((err = send_response(data_conn, FNC_CONTINUE, 0, ctls, sizeof(ld10k1_dsp_ctl_t) * patch->ctl_count)) < 0) {
free(ctls);
return err;
}
free(ctls);
}
return 0;
}
int ld10k1_fnc_send_patch_instr(int data_conn, ld10k1_patch_t *patch)
{
int i, j, err;
ld10k1_dsp_instr_t *instrs = NULL;
if (patch->instr_count) {
instrs = (ld10k1_dsp_instr_t *)malloc(sizeof(ld10k1_dsp_instr_t) * patch->instr_count);
if (!instrs)
return LD10K1_ERR_NO_MEM;
for (i = 0; i < patch->instr_count; i++) {
instrs[i].op_code = patch->instr[i].op_code;
for (j = 0; j < 4; j++)
instrs[i].arg[j] = patch->instr[i].arg[j];
}
if ((err = send_response(data_conn, FNC_CONTINUE, 0, instrs, sizeof(ld10k1_dsp_instr_t) * patch->instr_count)) < 0) {
free(instrs);
return err;
}
free(instrs);
}
return 0;
}
int ld10k1_fnc_get_patch(int data_conn, int op, int size)
{
int err;
ld10k1_dsp_patch_t patch_info;
int patch_num = -1;
ld10k1_patch_t *patch;
if ((err = receive_msg_data(data_conn, &patch_num, sizeof(patch_num))) < 0)
return err;
if (dsp_mgr.patch_count >= 0) {
if (patch_num > EMU10K1_PATCH_MAX)
return LD10K1_ERR_UNKNOWN_PATCH_NUM;
patch = dsp_mgr.patch_ptr[patch_num];
if (!patch)
return LD10K1_ERR_UNKNOWN_PATCH_NUM;
strcpy(patch_info.patch_name, patch->patch_name);
patch_info.id = patch->id;
patch_info.in_count = patch->in_count;
patch_info.out_count = patch->out_count;
patch_info.const_count = patch->const_count;
patch_info.static_count = patch->sta_count;
patch_info.dynamic_count = patch->dyn_count;
patch_info.hw_count = patch->hw_count;
patch_info.tram_count = patch->tram_count;
patch_info.tram_acc_count = patch->tram_acc_count;
patch_info.ctl_count = patch->ctl_count;
patch_info.instr_count = patch->instr_count;
if ((err = send_response(data_conn, FNC_CONTINUE, 0, &patch_info, sizeof(ld10k1_dsp_patch_t))) < 0)
return err;
/* send next parts */
if ((err = ld10k1_fnc_send_patch_in(data_conn, patch)) < 0)
return err;
if ((err = ld10k1_fnc_send_patch_out(data_conn, patch)) < 0)
return err;
if ((err = ld10k1_fnc_send_patch_const(data_conn, patch)) < 0)
return err;
if ((err = ld10k1_fnc_send_patch_sta(data_conn, patch)) < 0)
return err;
if ((err = ld10k1_fnc_send_patch_hw(data_conn, patch)) < 0)
return err;
if ((err = ld10k1_fnc_send_patch_tram_grp(data_conn, patch)) < 0)
return err;
if ((err = ld10k1_fnc_send_patch_tram_acc(data_conn, patch)) < 0)
return err;
if ((err = ld10k1_fnc_send_patch_ctl(data_conn, patch)) < 0)
return err;
if ((err = ld10k1_fnc_send_patch_instr(data_conn, patch)) < 0)
return err;
}
return 0;
}
int ld10k1_fnc_dump(int data_conn, int op, int size)
{
int err;
void *dump = NULL;
int dump_size = 0;
if ((err = ld10k1_make_dump(&dsp_mgr, &dump, &dump_size)) < 0)
return err;
if ((err = send_response(data_conn, FNC_CONTINUE, 0, dump, dump_size)) < 0)
return err;
free(dump);
return 0;
}
int ld10k1_fnc_get_points_info(int data_conn, int op, int size)
{
int point_count;
int i, j = 0;
int *info = NULL;
ld10k1_conn_point_t *point;
point_count = 0;
for (i = 0; i < 2; i++) {
if (i) {
if (!point_count)
break;
info = (int *)malloc(sizeof(int) * point_count);
if (!info)
return LD10K1_ERR_NO_MEM;
j = 0;
}
point = dsp_mgr.point_list;
while (point) {
if (!i)
point_count++;
else
info[j++] = point->id;
point = point->next;
}
}
return send_response_wd(data_conn, info, sizeof(int) * point_count);
}
int ld10k1_fnc_get_point_info(int data_conn, int op, int size)
{
int err;
int k, l;
ld10k1_dsp_point_t info;
ld10k1_conn_point_t *point;
ld10k1_conn_point_t *found_point;
int what_point_id;
/*info = NULL;*/
if ((err = receive_msg_data(data_conn, &what_point_id, sizeof(int))) < 0)
return err;
found_point = NULL;
point = dsp_mgr.point_list;
while (point) {
if (point->id == what_point_id) {
found_point = point;
break;
}
point = point->next;
}
if (!found_point)
return LD10K1_ERR_UNKNOWN_POINT;
info.id = point->id;
if (EMU10K1_REG_TYPE_B(point->con_gpr_idx) == EMU10K1_REG_TYPE_NORMAL)
info.type = CON_IO_NORMAL;
else if (EMU10K1_REG_TYPE_B(point->con_gpr_idx) == EMU10K1_REG_TYPE_INPUT)
info.type = CON_IO_IN;
else if (EMU10K1_REG_TYPE_B(point->con_gpr_idx) == EMU10K1_REG_TYPE_OUTPUT)
info.type = CON_IO_OUT;
else if (EMU10K1_REG_TYPE_B(point->con_gpr_idx) == EMU10K1_REG_TYPE_FX)
info.type = CON_IO_FX;
info.io_idx = point->con_gpr_idx & ~EMU10K1_REG_TYPE_MASK;
info.simple = point->simple;
info.conn_count = point->con_count;
if (info.conn_count > 2 && info.type == CON_IO_NORMAL)
info.multi = 1;
else if (info.conn_count > 1 && info.type != CON_IO_NORMAL)
info.multi = 1;
else
info.multi = 0;
for (k = 0, l = 0; k < POINT_MAX_CONN_PER_POINT; k++) {
if (point->type[k]) {
info.io_type[l] = point->type[k] == CON_IO_PIN ? 0 : 1;
info.patch[l] = point->patch[k] ? point->patch[k]->id : -1;
info.io[l] = point->io[k];
l++;
}
}
return send_response_wd(data_conn, &info, sizeof(ld10k1_dsp_point_t));
}
int ld10k1_fnc_get_dsp_info(int data_conn, int op, int size)
{
ld10k1_fnc_dsp_info_t info;
info.chip_type = dsp_mgr.audigy;
return send_response_wd(data_conn, &info, sizeof(ld10k1_fnc_dsp_info_t));
}