mirror of
https://github.com/alsa-project/alsa-tools.git
synced 2025-11-23 06:59:55 -05:00
Add ld10k1 tool
Added ld10k1 tool by Peter Zubaj.
This commit is contained in:
parent
37104ebf62
commit
2df1aa7c20
98 changed files with 19970 additions and 1 deletions
615
ld10k1/src/dl10k1.c
Normal file
615
ld10k1/src/dl10k1.c
Normal file
|
|
@ -0,0 +1,615 @@
|
|||
/*
|
||||
* EMU10k1 dump loader
|
||||
*
|
||||
* Copyright (c) 2003,2004 by Peter Zubaj
|
||||
*
|
||||
* Hwdep usage based on sb16_csp
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
/* TODO - kontrola dat, ktore nahravam */
|
||||
|
||||
#include <getopt.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <alsa/asoundlib.h>
|
||||
#include <alsa/sound/emu10k1.h>
|
||||
|
||||
#include <getopt.h>
|
||||
#include <bitops.h>
|
||||
|
||||
#include "ld10k1_dump_file.h"
|
||||
|
||||
#define DL10K1_SIGNATURE "DUMP Image (dl10k1)"
|
||||
int card = 0;
|
||||
snd_hwdep_t *handle;
|
||||
const char *card_proc_id;
|
||||
|
||||
void error(const char *fmt,...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
va_start(va, fmt);
|
||||
fprintf(stderr, "Error: ");
|
||||
vfprintf(stderr, fmt, va);
|
||||
fprintf(stderr, "\n");
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
static void help(char *command)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: %s [-options]\n"
|
||||
"\nAvailable options:\n"
|
||||
" -h, --help this help\n"
|
||||
" -c, --card select card number, default = 0\n"
|
||||
" -d, --dump file with dump\n"
|
||||
, command);
|
||||
}
|
||||
|
||||
int driver_set_tram_size(int tram_size)
|
||||
{
|
||||
if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_TRAM_SETUP, &tram_size) < 0) {
|
||||
error("unable to setup tram");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void free_code_struct(emu10k1_fx8010_code_t *code)
|
||||
{
|
||||
if (code->gpr_map)
|
||||
free(code->gpr_map);
|
||||
if (code->tram_data_map)
|
||||
free(code->tram_data_map);
|
||||
if (code->tram_addr_map)
|
||||
free(code->tram_addr_map);
|
||||
if (code->code)
|
||||
free(code->code);
|
||||
}
|
||||
|
||||
int alloc_code_struct(emu10k1_fx8010_code_t *code)
|
||||
{
|
||||
/* alloc code structure */
|
||||
code->gpr_map = NULL;
|
||||
code->tram_data_map = NULL;
|
||||
code->tram_addr_map = NULL;
|
||||
code->code = NULL;
|
||||
|
||||
code->gpr_map = (uint32_t *)malloc(sizeof(uint32_t) * 0x200);
|
||||
if (!code->gpr_map)
|
||||
goto err;
|
||||
memset(code->gpr_map, 0, sizeof(uint32_t) * 0x200);
|
||||
|
||||
code->tram_data_map = (uint32_t *)malloc(sizeof(uint32_t) * 0x100);
|
||||
if (!code->tram_data_map)
|
||||
goto err;
|
||||
memset(code->tram_data_map, 0, sizeof(uint32_t) * 0x100);
|
||||
|
||||
code->tram_addr_map = (uint32_t *)malloc(sizeof(uint32_t) * 0x100);
|
||||
if (!code->tram_addr_map)
|
||||
goto err;
|
||||
memset(code->tram_addr_map, 0, sizeof(uint32_t) * 0x100);
|
||||
|
||||
code->code = (uint32_t *)malloc(sizeof(uint32_t) * 1024 * 2);
|
||||
if (!code->code)
|
||||
goto err;
|
||||
memset(code->code, 0, sizeof(uint32_t) * 1024 * 2);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
free_code_struct(code);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int driver_init_dsp(int audigy)
|
||||
{
|
||||
int i;
|
||||
emu10k1_fx8010_code_t code;
|
||||
emu10k1_fx8010_control_gpr_t *ctrl;
|
||||
emu10k1_ctl_elem_id_t *ids;
|
||||
emu10k1_fx8010_pcm_t ipcm;
|
||||
unsigned int *iptr;
|
||||
|
||||
if (alloc_code_struct(&code) < 0) {
|
||||
error("no mem");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* get count of controls */
|
||||
code.gpr_list_control_count = 0;
|
||||
if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_CODE_PEEK, &code) < 0) {
|
||||
error("unable to peek code");
|
||||
free_code_struct(&code);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ctrl = (emu10k1_fx8010_control_gpr_t *)malloc(sizeof(emu10k1_fx8010_control_gpr_t) * code.gpr_list_control_total);
|
||||
if (!ctrl) {
|
||||
error("no mem");
|
||||
free_code_struct(&code);
|
||||
return 1;
|
||||
}
|
||||
|
||||
code.gpr_list_control_count = code.gpr_list_control_total;
|
||||
code.gpr_list_controls = ctrl;
|
||||
|
||||
for (i = 0; i < sizeof(code.gpr_valid) / sizeof(unsigned long); i++)
|
||||
code.gpr_valid[i] = 0x0;
|
||||
for (i = 0; i < sizeof(code.tram_valid) / sizeof(unsigned long); i++)
|
||||
code.tram_valid[i] = 0x0;
|
||||
for (i = 0; i < sizeof(code.code_valid) / sizeof(unsigned long); i++)
|
||||
code.code_valid[i] = 0x0;;
|
||||
|
||||
if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_CODE_PEEK, &code) < 0) {
|
||||
error("unable to peek code");
|
||||
free_code_struct(&code);
|
||||
free(ctrl);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* new name */
|
||||
strcpy(code.name, DL10K1_SIGNATURE);
|
||||
for (i = 0; i < sizeof(code.gpr_valid) / sizeof(unsigned long); i++)
|
||||
code.gpr_valid[i] = ~0;
|
||||
|
||||
for (i = 0; i < sizeof(code.gpr_valid) * 8; i++)
|
||||
code.gpr_map[i] = 0;
|
||||
|
||||
ids = (emu10k1_ctl_elem_id_t *)malloc(sizeof(emu10k1_ctl_elem_id_t) * code.gpr_list_control_total);
|
||||
if (!ids) {
|
||||
free_code_struct(&code);
|
||||
free(ctrl);
|
||||
error("no mem");
|
||||
return 1;
|
||||
}
|
||||
|
||||
code.gpr_del_control_count = code.gpr_list_control_total;
|
||||
if (code.gpr_del_control_count) {
|
||||
for (i = 0; i < code.gpr_del_control_count; i++) {
|
||||
memcpy(&(ids[i]), &(ctrl[i].id), sizeof(emu10k1_ctl_elem_id_t));
|
||||
}
|
||||
}
|
||||
|
||||
free(ctrl);
|
||||
|
||||
code.gpr_del_controls = ids;
|
||||
code.gpr_list_control_count = 0;
|
||||
code.gpr_add_control_count = 0;
|
||||
code.gpr_list_control_count = 0;
|
||||
|
||||
for (i = 0; i < sizeof(code.tram_valid) / sizeof(unsigned long); i++)
|
||||
code.tram_valid[i] = ~0;
|
||||
for (i = 0; i < sizeof(code.code_valid) / sizeof(unsigned long); i++)
|
||||
code.code_valid[i] = ~0;
|
||||
|
||||
for (i = 0; i < sizeof(code.tram_valid) * 8; i++) {
|
||||
code.tram_addr_map[i] = 0;
|
||||
code.tram_data_map[i] = 0;
|
||||
}
|
||||
|
||||
for (iptr = code.code, i = 0; i < sizeof(code.code_valid) * 8; i++, iptr += 2)
|
||||
if (audigy) {
|
||||
*iptr = ((0xcf & 0x7ff) << 12) | (0xc0 & 0x7ff);
|
||||
*(iptr + 1) = ((0x0f & 0x0f) << 24) | ((0xc0 & 0x7ff) << 12) | (0xc0 & 0x7ff);
|
||||
} else {
|
||||
*iptr = ((0x40 & 0x3ff) << 10) | (0x40 & 0x3ff);
|
||||
*(iptr + 1) = ((0x06 & 0x0f) << 20) | ((0x40 & 0x3ff) << 10) | (0x40 & 0x3ff);
|
||||
}
|
||||
|
||||
if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_CODE_POKE, &code) < 0) {
|
||||
error("unable to poke code");
|
||||
free_code_struct(&code);
|
||||
free(ids);
|
||||
return 1;
|
||||
}
|
||||
|
||||
free(ids);
|
||||
|
||||
/* delete tram pcm dsp part */
|
||||
if (!audigy) {
|
||||
for (i = 0; i < EMU10K1_FX8010_PCM_COUNT; i++) {
|
||||
ipcm.substream = i;
|
||||
ipcm.channels = 0;
|
||||
if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_PCM_POKE, &ipcm) < 0) {
|
||||
error("unable to poke code");
|
||||
free_code_struct(&code);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dump_load(int audigy, char *file_name)
|
||||
{
|
||||
struct stat dump_stat;
|
||||
void *dump_data, *ptr;
|
||||
FILE *dump_file;
|
||||
emu10k1_fx8010_control_gpr_t *ctrl = NULL;
|
||||
ld10k1_ctl_dump_t *fctrl = NULL;
|
||||
unsigned int *fgpr = NULL;
|
||||
ld10k1_tram_dump_t *ftram = NULL;
|
||||
ld10k1_instr_dump_t *finstr = NULL;
|
||||
int i, j;
|
||||
unsigned int vaddr, addr;
|
||||
int op;
|
||||
|
||||
unsigned int *iptr;
|
||||
|
||||
emu10k1_fx8010_code_t code;
|
||||
|
||||
ld10k1_dump_t *header = NULL;
|
||||
|
||||
/* first load patch to mem */
|
||||
if (stat(file_name, &dump_stat)) {
|
||||
error("unable to load patch %s", file_name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* minimal dump len is size of header */
|
||||
if (dump_stat.st_size < sizeof(ld10k1_dump_t)) {
|
||||
error("unable to load dump %s (wrong file size)", file_name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
dump_data = malloc(dump_stat.st_size);
|
||||
if (!dump_data) {
|
||||
error("no mem");
|
||||
return 1;
|
||||
}
|
||||
|
||||
dump_file = fopen(file_name, "r");
|
||||
if (!dump_file) {
|
||||
error("unable to open file %s", file_name);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (fread(dump_data, dump_stat.st_size, 1, dump_file) != 1) {
|
||||
error("unable to read data from file %s", file_name);
|
||||
goto err;
|
||||
} else
|
||||
fclose(dump_file);
|
||||
|
||||
/* signature check */
|
||||
|
||||
header = (ld10k1_dump_t *)dump_data;
|
||||
if (strncmp(header->signature, "LD10K1 DUMP 001", 16) != 0) {
|
||||
error("wrong dump file %s (wrong signature)", file_name);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*printf("Size header%d\nctc %d %d\ngpr %d %d\ntram %d %d\ninstr %d %d\n", sizeof(ld10k1_dump_t),
|
||||
header->ctl_count, sizeof(ld10k1_ctl_dump_t),
|
||||
header->gpr_count, sizeof(unsigned int),
|
||||
header->tram_count, sizeof(ld10k1_tram_dump_t),
|
||||
header->instr_count, sizeof(ld10k1_instr_dump_t));*/
|
||||
|
||||
/*check size */
|
||||
if (sizeof(ld10k1_dump_t) +
|
||||
header->ctl_count * sizeof(ld10k1_ctl_dump_t) +
|
||||
header->gpr_count * sizeof(unsigned int) +
|
||||
header->tram_count * sizeof(ld10k1_tram_dump_t) +
|
||||
header->instr_count * sizeof(ld10k1_instr_dump_t) != dump_stat.st_size)
|
||||
goto err;
|
||||
|
||||
/* check dump type */
|
||||
if (header->dump_type == DUMP_TYPE_LIVE && audigy) {
|
||||
error("can't load dump from Live to Audigy");
|
||||
goto err1;
|
||||
} else if ((header->dump_type == DUMP_TYPE_AUDIGY_OLD ||
|
||||
header->dump_type == DUMP_TYPE_AUDIGY) &&
|
||||
!audigy) {
|
||||
error("can't load dump from Audigy to Live");
|
||||
goto err1;
|
||||
} else if (header->dump_type == DUMP_TYPE_AUDIGY_OLD) {
|
||||
error("can't load dump from Audigy (not patched drivers) to Audigy (current drivers)");
|
||||
goto err1;
|
||||
}
|
||||
|
||||
ptr = dump_data;
|
||||
ptr += sizeof(ld10k1_dump_t);
|
||||
|
||||
ctrl = (emu10k1_fx8010_control_gpr_t *)malloc(sizeof(emu10k1_fx8010_control_gpr_t) * header->ctl_count);
|
||||
if (!ctrl) {
|
||||
error("no mem");
|
||||
goto err1;
|
||||
}
|
||||
|
||||
if (alloc_code_struct(&code) < 0) {
|
||||
error("no mem");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
strcpy(code.name, DL10K1_SIGNATURE);
|
||||
|
||||
/* copy ctls */
|
||||
fctrl = (ld10k1_ctl_dump_t *)ptr;
|
||||
memset(ctrl, 0, sizeof(emu10k1_fx8010_control_gpr_t) * header->ctl_count);
|
||||
for (i = 0; i < header->ctl_count; i++) {
|
||||
strcpy(ctrl[i].id.name, fctrl[i].name);
|
||||
ctrl[i].id.iface = EMU10K1_CTL_ELEM_IFACE_MIXER;
|
||||
ctrl[i].id.index = fctrl[i].index;
|
||||
ctrl[i].vcount = fctrl[i].vcount;
|
||||
ctrl[i].count = fctrl[i].count;
|
||||
for (j = 0; j < 32; j++) {
|
||||
ctrl[i].gpr[j] = fctrl[i].gpr_idx[j];
|
||||
ctrl[i].value[j] = fctrl[i].value[j];
|
||||
}
|
||||
ctrl[i].min = fctrl[i].min;
|
||||
ctrl[i].max = fctrl[i].max;
|
||||
ctrl[i].translation = fctrl[i].translation;
|
||||
}
|
||||
code.gpr_add_control_count = header->ctl_count;
|
||||
code.gpr_add_controls = ctrl;
|
||||
|
||||
code.gpr_del_control_count = 0;
|
||||
code.gpr_del_controls = NULL;
|
||||
|
||||
code.gpr_list_control_count = 0;
|
||||
code.gpr_list_controls = NULL;
|
||||
|
||||
/* copy gprs */
|
||||
ptr += sizeof(ld10k1_ctl_dump_t) * header->ctl_count;
|
||||
fgpr = (unsigned int *)ptr;
|
||||
|
||||
for (i = 0; i < sizeof(code.gpr_valid) / sizeof(unsigned long); i++)
|
||||
code.gpr_valid[i] = ~0;
|
||||
|
||||
for (i = 0; i < header->gpr_count; i++)
|
||||
code.gpr_map[i] = fgpr[i];
|
||||
|
||||
ptr += sizeof(unsigned int) * header->gpr_count;
|
||||
ftram = (ld10k1_tram_dump_t *)ptr;
|
||||
/* tram addr + data */
|
||||
for (i = 0; i < header->tram_count; i++) {
|
||||
addr = ftram[i].addr;
|
||||
vaddr = addr & 0xFFFFF;
|
||||
op = ftram[i].type;
|
||||
|
||||
set_bit(i, code.tram_valid);
|
||||
switch(op) {
|
||||
case DUMP_TRAM_READ:
|
||||
if (audigy)
|
||||
vaddr = vaddr | 0x2 << 20;
|
||||
else
|
||||
vaddr = vaddr | TANKMEMADDRREG_READ | TANKMEMADDRREG_ALIGN;
|
||||
break;
|
||||
case DUMP_TRAM_WRITE:
|
||||
if (audigy)
|
||||
vaddr = vaddr | 0x6 << 20;
|
||||
else
|
||||
vaddr = vaddr | TANKMEMADDRREG_WRITE | TANKMEMADDRREG_ALIGN;
|
||||
break;
|
||||
case DUMP_TRAM_NULL:
|
||||
default:
|
||||
vaddr = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
code.tram_addr_map[i] = vaddr;
|
||||
code.tram_data_map[i] = ftram[i].data;
|
||||
}
|
||||
|
||||
ptr += sizeof(ld10k1_tram_dump_t) * header->tram_count;
|
||||
finstr = (ld10k1_instr_dump_t *)ptr;
|
||||
for (iptr = code.code, i = 0; i < header->instr_count; i++, iptr += 2) {
|
||||
set_bit(i, code.code_valid);
|
||||
if (finstr[i].used) {
|
||||
if (audigy) {
|
||||
*iptr = ((finstr[i].arg[2] & 0x7ff) << 12) | (finstr[i].arg[3] & 0x7ff);
|
||||
*(iptr + 1) = ((finstr[i].op & 0x0f) << 24) | ((finstr[i].arg[0] & 0x7ff) << 12) | (finstr[i].arg[1] & 0x7ff);
|
||||
} else {
|
||||
if (i < 0x200) {
|
||||
*iptr = ((finstr[i].arg[2] & 0x3ff) << 10) | (finstr[i].arg[3] & 0x3ff);
|
||||
*(iptr + 1) = ((finstr[i].op & 0x0f) << 20) | ((finstr[i].arg[0] & 0x3ff) << 10) | (finstr[i].arg[1] & 0x3ff);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (audigy) {
|
||||
*iptr = ((0xcf & 0x7ff) << 12) | (0xc0 & 0x7ff);
|
||||
*(iptr + 1) = ((0x0f & 0x0f) << 24) | ((0xc0 & 0x7ff) << 12) | (0xc0 & 0x7ff);
|
||||
} else {
|
||||
if (i < 0x200) {
|
||||
*iptr = ((0x40 & 0x3ff) << 10) | (0x40 & 0x3ff);
|
||||
*(iptr + 1) = ((0x06 & 0x0f) << 20) | ((0x40 & 0x3ff) << 10) | (0x40 & 0x3ff);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (header->dump_type != DUMP_TYPE_AUDIGY_OLD &&
|
||||
driver_set_tram_size(header->tram_size))
|
||||
goto err1;
|
||||
|
||||
if (driver_init_dsp(audigy))
|
||||
goto err1;
|
||||
|
||||
if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_CODE_POKE, &code) < 0) {
|
||||
error("unable to poke code");
|
||||
goto err1;
|
||||
}
|
||||
|
||||
if (dump_data)
|
||||
free(dump_data);
|
||||
|
||||
if (ctrl)
|
||||
free(ctrl);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
error("wrong dump file format %s", file_name);
|
||||
err1:
|
||||
free_code_struct(&code);
|
||||
if (dump_data)
|
||||
free(dump_data);
|
||||
if (ctrl)
|
||||
free(ctrl);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int dev;
|
||||
int c;
|
||||
int err;
|
||||
int audigy;
|
||||
|
||||
int opt_help = 0;
|
||||
char *opt_dump_file = NULL;
|
||||
|
||||
char card_id[32];
|
||||
snd_ctl_t *ctl_handle;
|
||||
snd_ctl_card_info_t *card_info;
|
||||
snd_hwdep_info_t *hwdep_info;
|
||||
|
||||
char name[16];
|
||||
|
||||
snd_ctl_card_info_alloca(&card_info);
|
||||
snd_hwdep_info_alloca(&hwdep_info);
|
||||
|
||||
static struct option long_options[] = {
|
||||
{"help", 0, 0, 'h'},
|
||||
{"card", 1, 0, 'c'},
|
||||
{"dump", 1, 0, 'd'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
int option_index = 0;
|
||||
while ((c = getopt_long(argc, argv, "hc:d:",
|
||||
long_options, &option_index)) != EOF) {
|
||||
switch (c) {
|
||||
/* case 0: */
|
||||
/* break; */
|
||||
case 'h':
|
||||
opt_help = 1;
|
||||
break;
|
||||
case 'd':
|
||||
opt_dump_file = optarg;
|
||||
break;
|
||||
case 'c':
|
||||
card = snd_card_get_index(optarg);
|
||||
if (card < 0 || card > 31) {
|
||||
error("wrong -c argument '%s'\n", optarg);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (opt_help) {
|
||||
help(argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!opt_dump_file) {
|
||||
error("dump file not specified");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (getuid() != 0 )
|
||||
{
|
||||
error("You are not running dl10k1 as root.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Get control handle for selected card */
|
||||
sprintf(card_id, "hw:%i", card);
|
||||
if ((err = snd_ctl_open(&ctl_handle, card_id, 0)) < 0) {
|
||||
error("control open (%s): %s", card_id, snd_strerror(err));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Read control hardware info from card */
|
||||
if ((err = snd_ctl_card_info(ctl_handle, card_info)) < 0) {
|
||||
error("control hardware info (%s): %s", card_id, snd_strerror(err));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!(card_proc_id = snd_ctl_card_info_get_id (card_info))) {
|
||||
error("card id (%s): %s", card_id, snd_strerror(err));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
/* EMU10k1/EMU10k2 chip is present only on SB Live, Audigy, Audigy 2, E-mu APS cards */
|
||||
if (strcmp(snd_ctl_card_info_get_driver(card_info), "EMU10K1") != 0 &&
|
||||
strcmp(snd_ctl_card_info_get_driver(card_info), "Audigy") != 0 &&
|
||||
strcmp(snd_ctl_card_info_get_driver(card_info), "Audigy2") != 0 &&
|
||||
strcmp(snd_ctl_card_info_get_driver(card_info), "E-mu APS") != 0) {
|
||||
error("not a EMU10K1/EMU10K2 based card");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (strcmp(snd_ctl_card_info_get_driver(card_info), "Audigy") == 0 ||
|
||||
strcmp(snd_ctl_card_info_get_driver(card_info), "Audigy2") == 0)
|
||||
audigy = 1;
|
||||
else
|
||||
audigy = 0;
|
||||
|
||||
/* find EMU10k1 hardware dependant device and execute command */
|
||||
dev = -1;
|
||||
err = 1;
|
||||
while (1) {
|
||||
if (snd_ctl_hwdep_next_device(ctl_handle, &dev) < 0)
|
||||
error("hwdep next device (%s): %s", card_id, snd_strerror(err));
|
||||
if (dev < 0)
|
||||
break;
|
||||
snd_hwdep_info_set_device(hwdep_info, dev);
|
||||
if (snd_ctl_hwdep_info(ctl_handle, hwdep_info) < 0) {
|
||||
if (err != -ENOENT)
|
||||
error("control hwdep info (%s): %s", card_id, snd_strerror(err));
|
||||
continue;
|
||||
}
|
||||
if (snd_hwdep_info_get_iface(hwdep_info) == SND_HWDEP_IFACE_EMU10K1) {
|
||||
sprintf(name, "hw:%i,%i", card, dev);
|
||||
|
||||
/* open EMU10k1 hwdep device */
|
||||
if ((err = snd_hwdep_open(&handle, name, O_WRONLY)) < 0) {
|
||||
error("EMU10k1 open (%i-%i): %s", card, dev, snd_strerror(err));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
err = dump_load(audigy, opt_dump_file);
|
||||
|
||||
snd_hwdep_close(handle);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
snd_ctl_close(ctl_handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue