/*
* This file is part of uniaud.dll.
*
* Copyright (c) 2010 Mensys BV
* Copyright (c) 2007 Vlad Stelmahovsky aka Vladest
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* This library 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License and the GNU General Public License along with this library.
* If not, see .
*/
#define INCL_DOS
#define INCL_DOSERRORS
#include
#include
#include
#include
#include "internal.h"
/* internal mixer API */
int _uniaud_mixer_get_ctls_number(int card_id)
{
HFILE hFile = 0;
ULONG len;
ULONG id_len;
int ctls = 0;
APIRET rc = 0;
/* checking cards range */
if (card_id < 0 || card_id >= cards_num) // counting cards from 0
return -UNIAUD_INVALID_CARD;
//Check if 32 bits PDD was successfully loaded
if ((int)(hFile = DriverOpen()) >= 0)
{
rc = DosDevIOCtl(hFile, CAT_IOCTL_OSS32, IOCTL_OSS32_GET_CNTRLS_NUM,
&card_id, sizeof(card_id), &id_len,
&ctls, sizeof(ctls), &len);
DosClose(hFile);
if (rc != 0)
return -UNIAUD_ERROR_IN_DRIVER;
return ctls;
}
else
return -UNIAUD_ALSA32OPEN_ERROR;
}
UniaudControl * _uniaud_mixer_get_ctl_list(int card_id)
{
HFILE hFile = 0;
ULONG len;
ULONG id_len;
int ctls = 0;
APIRET rc = 0;
UniaudControl *pCtl = NULL;
/* checking cards range */
if (card_id < 0 || card_id >= cards_num) // counting cards from 0
return NULL;
//Check if 32 bits PDD was successfully loaded
if ((int)(hFile = DriverOpen()) >= 0)
{
rc = DosDevIOCtl(hFile, CAT_IOCTL_OSS32, IOCTL_OSS32_GET_CNTRLS_NUM,
&card_id, sizeof(card_id), &id_len,
&ctls, sizeof(ctls), &len);
if (rc == 0)
{
pCtl = (UniaudControl *)malloc(ctls*sizeof(UniaudControl));
if (pCtl)
{
memset(pCtl,0,ctls*sizeof(UniaudControl));
rc = DosDevIOCtl(hFile, CAT_IOCTL_OSS32, IOCTL_OSS32_GET_CNTRLS,
&card_id, sizeof(card_id), &id_len,
&pCtl, sizeof(pCtl), &len);
if (rc != 0)
{
free(pCtl);
pCtl = NULL;
}
}
}
DosClose(hFile);
}
return pCtl; // pointer to controls list
}
int uniaud_get_id_by_name(int card_id, char *name, int index)
{
int i;
UniaudControl *pCtl = NULL;
/* checking cards range */
if (card_id < 0 || card_id >= cards_num) // counting cards from 0
return -UNIAUD_INVALID_CARD;
if (!name)
return -UNIAUD_INVALID_PARAMETER;
pCtl = UniInst[card_id].ctls_list;
for (i=0; i < UniInst[card_id].ctls_num; i++)
{
//printf("%s\n",pCtl->name);
if (strcmp(pCtl->name, name) == 0 && pCtl->index == index)
return pCtl->numid;
pCtl++;
}
return -UNIAUD_NOT_FOUND;
}
/* external mixer API */
int uniaud_mixer_get_ctls_number(int card_id)
{
/* checking cards range */
if (card_id < 0 || card_id >= cards_num) // counting cards from 0
return -UNIAUD_INVALID_CARD;
return UniInst[card_id].ctls_num;
}
/* internal mixer API */
/* external mixer API */
UniaudControl * uniaud_mixer_get_ctl_list(int card_id)
{
/* checking cards range */
if (card_id < 0 || card_id >= cards_num) // counting cards from 0
return NULL;
return UniInst[card_id].ctls_list; // pointer to controls list
}
int uniaud_mixer_get_power_state(int card_id, ULONG *state)
{
HFILE hFile = 0;
ULONG len;
ULONG id, idlen;
APIRET rc = 0;
/* checking cards range */
if (card_id < 0 || card_id >= cards_num) // counting cards from 0
return -UNIAUD_INVALID_CARD;
//if (state < 0) return -UNIAUD_INVALID_PARAMETER;
if ((int)(hFile = DriverOpen()) >= 0)
{
id = card_id;
idlen = sizeof(id);
//printf("id: %x, card: %x, ctl: %x\n",id, card_id, pCtl->numid);
rc = DosDevIOCtl(hFile, CAT_IOCTL_OSS32,
IOCTL_OSS32_GET_POWER_STATE,
&id, sizeof(id), &idlen,
&state, sizeof(state), &len);
DosClose(hFile);
}
else
return UNIAUD_ALSA32OPEN_ERROR;
return UNIAUD_NO_ERROR;
}
int uniaud_mixer_set_power_state(int card_id, ULONG *state)
{
HFILE hFile = 0;
ULONG len;
ULONG id, idlen;
APIRET rc = 0;
/* checking cards range */
if (card_id < 0 || card_id >= cards_num) // counting cards from 0
return -UNIAUD_INVALID_CARD;
//if (state < 0) return -UNIAUD_INVALID_PARAMETER;
if ((int)(hFile = DriverOpen()) >= 0)
{
id = card_id;
idlen = sizeof(id);
//printf("id: %x, card: %x, ctl: %x\n",id, card_id, pCtl->numid);
rc = DosDevIOCtl(hFile, CAT_IOCTL_OSS32,
IOCTL_OSS32_SET_POWER_STATE,
&id, sizeof(id), &idlen,
&state, sizeof(state), &len);
DosClose(hFile);
}
else
return UNIAUD_ALSA32OPEN_ERROR;
return UNIAUD_NO_ERROR;
}
int uniaud_mixer_get_ctl_info(int card_id, ULONG list_id,
UniaudControlInfo *ctl_info)
{
HFILE hFile = 0;
ULONG len;
ULONG id, idlen;
APIRET rc = 0;
UniaudControl *pCtl = NULL;
int i = 0;
/* checking cards range */
if (card_id < 0 || card_id >= cards_num) // counting cards from 0
return -UNIAUD_INVALID_CARD;
if (!UniInst[card_id].ctls_list || !ctl_info)
return -UNIAUD_INVALID_PARAMETER;
if ((int)(hFile = DriverOpen()) >= 0)
{
pCtl = UniInst[card_id].ctls_list;
for(i=0; inumid)
{
id = card_id << 16;
id |= pCtl->numid;
idlen = sizeof(id);
//printf("id: %x, card: %x, ctl: %x\n",id, card_id, pCtl->numid);
rc = DosDevIOCtl(hFile, CAT_IOCTL_OSS32,
IOCTL_OSS32_CNTRL_INFO,
&id, sizeof(id), &idlen,
&ctl_info, sizeof(ctl_info), &len);
break;
}
pCtl++;
}
DosClose(hFile);
}
else
return UNIAUD_ALSA32OPEN_ERROR;
return UNIAUD_NO_ERROR;
}
int uniaud_mixer_get_ctl_val(int card_id, ULONG list_id, UniaudControlValue *ctl_val)
{
HFILE hFile = 0;
ULONG len;
ULONG id, idlen;
UniaudControl *pCtl = NULL;
int i = 0;
/* checking cards range */
if (card_id < 0 || card_id >= cards_num) // counting cards from 0
return -UNIAUD_INVALID_CARD;
if (!UniInst[card_id].ctls_list || !ctl_val)
return -UNIAUD_INVALID_PARAMETER;
if ((int)(hFile = DriverOpen()) >= 0)
{
pCtl = UniInst[card_id].ctls_list;
for(i=0; inumid)
{
id = card_id << 16;
id |= pCtl->numid;
DosDevIOCtl(hFile, CAT_IOCTL_OSS32,
IOCTL_OSS32_CNTRL_GET,
&id, sizeof(id), &idlen,
&ctl_val, sizeof(ctl_val), &len);
break;
}
pCtl++;
}
DosClose(hFile);
}
else
return -UNIAUD_ALSA32OPEN_ERROR;
return UNIAUD_NO_ERROR;
}
int uniaud_mixer_put_ctl_val(int card_id, ULONG list_id, UniaudControlValue *ctl_val)
{
HFILE hFile = 0;
ULONG len;
ULONG id, idlen;
/* checking cards range */
if (card_id < 0 || card_id >= cards_num) // counting cards from 0
return -UNIAUD_INVALID_CARD;
if (!ctl_val) return -UNIAUD_INVALID_PARAMETER;
if ((int)(hFile = DriverOpen()) >= 0) {
id = card_id << 16;
id |= list_id;
DosDevIOCtl(hFile, CAT_IOCTL_OSS32, IOCTL_OSS32_CNTRL_PUT,
&id, sizeof(id), &idlen,
&ctl_val, sizeof(ctl_val), &len);
DosClose(hFile);
} else
return -UNIAUD_ALSA32OPEN_ERROR;
return UNIAUD_NO_ERROR;
}
/*
* Wait for any control change and return changed control number
*/
int uniaud_mixer_wait(int card_id, int timeout)
{
HFILE hFile = 0;
ULONG len, id_len;
ULONG rc;
int ctl_id = 0;
ioctl_pcm io_pcm = {0};
/* checking cards range */
if (card_id < 0 || card_id >= cards_num) // counting cards from 0
return -UNIAUD_INVALID_CARD;
io_pcm.deviceid = card_id;
io_pcm.streamtype = timeout;
if ((int)(hFile = DriverOpen()) >= 0)
{
rc = DosDevIOCtl(hFile, CAT_IOCTL_OSS32, IOCTL_OSS32_CNTRL_WAIT,
&io_pcm, sizeof(io_pcm), &id_len,
&ctl_id, sizeof(ctl_id), &len);
DosClose(hFile);
if (rc != 0)
return -UNIAUD_ERROR_IN_DRIVER;
return ctl_id;
}
else
return -UNIAUD_ALSA32OPEN_ERROR;
}
int uniaud_mixer_put_value(int card_id, ULONG put_id, int put_val, int put_cnt)
{
UniaudControlInfo *ctl_info = NULL;
UniaudControlValue *ctl_val = NULL;
int err = 0;
if (put_id == 0) return -1;
ctl_info = (UniaudControlInfo *)malloc(sizeof(UniaudControlInfo));
if (!ctl_info) return -1;
ctl_val = (UniaudControlValue *)malloc(sizeof(UniaudControlValue));
if (!ctl_val) {
free(ctl_info);
return -1;
}
memset(ctl_info,0,sizeof(UniaudControlInfo));
memset(ctl_val,0,sizeof(UniaudControlValue));
if (DebugMode) {
printf("&ctl_val=%x, &id=%x sizeof(id)=%x &value=%x\n", ctl_val, &ctl_val->id, sizeof(ctl_val->id), &ctl_val->value);
printf("&val0=%x &val1=%x\n", &ctl_val->value.integer.value[0], &ctl_val->value.integer.value[1]);
printf("uniaud_mixer_put_value: id=%i cnt=%i val=%i\n", put_id, put_cnt, put_val);
}
if (!uniaud_mixer_get_ctl_info(card_id, put_id, ctl_info) &&
!uniaud_mixer_get_ctl_val(card_id, put_id, ctl_val)) {
if (put_cnt >= ctl_info->count) err = -1;
switch(ctl_info->type) {
case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
case SNDRV_CTL_ELEM_TYPE_INTEGER:
if (put_val >= ctl_info->value.integer.min && put_val <= ctl_info->value.integer.max)
ctl_val->value.integer.value[put_cnt] = put_val;
else
err = -2;
break;
case SNDRV_CTL_ELEM_TYPE_INTEGER64:
if (put_val >= ctl_info->value.integer64.min && put_val <= ctl_info->value.integer64.max)
ctl_val->value.integer64.value[put_cnt] = put_val;
else
err = -2;
break;
case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
if (put_val >= 0 && put_val <= ctl_info->value.enumerated.items-1) {
ctl_val->value.enumerated.item[put_cnt] = put_val;
ctl_info->value.enumerated.item = put_val; //?????
}
else
err = -2;
break;
} // switch
if (err == 0) {
if (DebugMode) printf("uniaud_mixer_put_value: card=%i id=%i Eid=%i E0=%i E1=%i\n",
card_id, put_id, ctl_val->id.numid, ctl_val->value.integer.value[0], ctl_val->value.integer.value[1]);
uniaud_mixer_put_ctl_val(card_id, put_id, ctl_val);
}
}
else
err = -3;
if (ctl_info) free(ctl_info);
if (ctl_val) free(ctl_val);
return err;
}
int uniaud_mixer_get_value(int card_id, ULONG put_id, int get_cnt)
{
UniaudControlInfo *ctl_info = NULL;
UniaudControlValue *ctl_val = NULL;
int err = 0;
int val = 0;
ctl_info = (UniaudControlInfo *)malloc(sizeof(UniaudControlInfo));
ctl_val = (UniaudControlValue *)malloc(sizeof(UniaudControlValue));
if (put_id == 0 || !ctl_info || !ctl_val) return -1;
memset(ctl_info,0,sizeof(UniaudControlInfo));
memset(ctl_val,0,sizeof(UniaudControlValue));
if (!uniaud_mixer_get_ctl_info(card_id, put_id, ctl_info) &&
!uniaud_mixer_get_ctl_val(card_id, put_id, ctl_val))
{
if (ctl_info->count < get_cnt+1)
err = -1;
switch(ctl_info->type)
{
case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
case SNDRV_CTL_ELEM_TYPE_INTEGER:
val = ctl_val->value.integer.value[get_cnt];
break;
case SNDRV_CTL_ELEM_TYPE_INTEGER64:
val = ctl_val->value.integer64.value[get_cnt];
break;
case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
val = ctl_val->value.enumerated.item[get_cnt];
break;
} // switch
}
if (ctl_info) free(ctl_info);
if (ctl_val) free(ctl_val);
return val;
}
int uniaud_mixer_get_min_max(int card_id, ULONG ctl_id, int *min, int*max)
{
UniaudControlInfo *ctl_info = NULL;
//int err = 0;
ctl_info = (UniaudControlInfo *)malloc(sizeof(UniaudControlInfo));
if (ctl_id == 0 || !ctl_info) return -1;
memset(ctl_info,0,sizeof(UniaudControlInfo));
if (!uniaud_mixer_get_ctl_info(card_id, ctl_id, ctl_info))
{
switch(ctl_info->type)
{
case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
case SNDRV_CTL_ELEM_TYPE_INTEGER:
if (min) *min = ctl_info->value.integer.min;
if (max) *max = ctl_info->value.integer.max;
break;
case SNDRV_CTL_ELEM_TYPE_INTEGER64:
if (min) *min = ctl_info->value.integer64.min;
if (max) *max = ctl_info->value.integer64.max;
break;
case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
if (min) *min = 0;
if (max) *max = ctl_info->value.enumerated.items;
break;
} // switch
}
if (ctl_info) free(ctl_info);
return 0;
}
int uniaud_mixer_get_count_of_values(int card_id, ULONG ctl_id, int *values_cnt)
{
UniaudControlInfo *ctl_info = NULL;
int err = 0;
ctl_info = (UniaudControlInfo *)malloc(sizeof(UniaudControlInfo));
if (ctl_id == 0 || !ctl_info) return -1;
memset(ctl_info,0,sizeof(UniaudControlInfo));
if (!uniaud_mixer_get_ctl_info(card_id, ctl_id, ctl_info))
{
if (values_cnt)
*values_cnt = ctl_info->count;
}
if (ctl_info) free(ctl_info);
return err;
}
int uniaud_mixer_put_value_by_name(int card_id, char *name, int put_val, int put_cnt, int index)
{
UniaudControlInfo *ctl_info = NULL;
UniaudControlValue *ctl_val = NULL;
int err = 0;
int put_id = -1;
ctl_info = (UniaudControlInfo *)malloc(sizeof(UniaudControlInfo));
ctl_val = (UniaudControlValue *)malloc(sizeof(UniaudControlValue));
if (!ctl_info || !ctl_val)
return -1;
put_id = uniaud_get_id_by_name(card_id, name, index);
if (put_id <= 0)
return -UNIAUD_INVALID_PARAMETER;
memset(ctl_info,0,sizeof(UniaudControlInfo));
memset(ctl_val,0,sizeof(UniaudControlValue));
if (!uniaud_mixer_get_ctl_info(card_id, put_id, ctl_info) &&
!uniaud_mixer_get_ctl_val(card_id, put_id, ctl_val))
{
if (ctl_info->count < put_cnt+1)
err = -1;
switch(ctl_info->type)
{
case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
case SNDRV_CTL_ELEM_TYPE_INTEGER:
if (put_val >= ctl_info->value.integer.min &&
put_val <= ctl_info->value.integer.max)
ctl_val->value.integer.value[put_cnt] = put_val;
else
err = -1;
break;
case SNDRV_CTL_ELEM_TYPE_INTEGER64:
if (put_val >= ctl_info->value.integer64.min &&
put_val <= ctl_info->value.integer64.max)
ctl_val->value.integer64.value[put_cnt] = put_val;
else
err = -1;
break;
case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
if (put_val >= 0 &&
put_val <= ctl_info->value.enumerated.items-1)
ctl_val->value.enumerated.item[put_cnt] = put_val;
else
err = -1;
break;
} // switch
if (err == 0)
uniaud_mixer_put_ctl_val(card_id, put_id, ctl_val);
}
else
err = -3;
if (ctl_info) free(ctl_info);
if (ctl_val) free(ctl_val);
return err;
}
int uniaud_mixer_get_value_by_name(int card_id, char *name, int get_cnt, int index)
{
UniaudControlInfo *ctl_info = NULL;
UniaudControlValue *ctl_val = NULL;
int err = 0;
int val = 0;
int put_id = -1;
ctl_info = (UniaudControlInfo *)malloc(sizeof(UniaudControlInfo));
ctl_val = (UniaudControlValue *)malloc(sizeof(UniaudControlValue));
if (!ctl_info || !ctl_val)
return -1;
put_id = uniaud_get_id_by_name(card_id, name, index);
if (put_id <= 0)
return -UNIAUD_INVALID_PARAMETER;
memset(ctl_info,0,sizeof(UniaudControlInfo));
memset(ctl_val,0,sizeof(UniaudControlValue));
if (!uniaud_mixer_get_ctl_info(card_id, put_id, ctl_info) &&
!uniaud_mixer_get_ctl_val(card_id, put_id, ctl_val))
{
if (ctl_info->count < get_cnt+1)
err = -1;
switch(ctl_info->type)
{
case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
case SNDRV_CTL_ELEM_TYPE_INTEGER:
val = ctl_val->value.integer.value[get_cnt];
break;
case SNDRV_CTL_ELEM_TYPE_INTEGER64:
val = ctl_val->value.integer64.value[get_cnt];
break;
case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
val = ctl_val->value.enumerated.item[get_cnt];
break;
} // switch
}
if (ctl_info) free(ctl_info);
if (ctl_val) free(ctl_val);
return val;
}
int uniaud_mixer_put_spdif_status(int card_id, char *name, int aes0, int aes1, int aes2, int aes3)
{
UniaudControlInfo *ctl_info = NULL;
UniaudControlValue *ctl_val = NULL;
int err = 0;
int put_id = -1;
int index = 0;
ctl_info = (UniaudControlInfo *)malloc(sizeof(UniaudControlInfo));
ctl_val = (UniaudControlValue *)malloc(sizeof(UniaudControlValue));
if (!ctl_info || !ctl_val)
return -1;
put_id = uniaud_get_id_by_name(card_id, name, index);
if (put_id <= 0)
return -UNIAUD_INVALID_PARAMETER;
memset(ctl_info,0,sizeof(UniaudControlInfo));
memset(ctl_val,0,sizeof(UniaudControlValue));
if (!uniaud_mixer_get_ctl_info(card_id, put_id, ctl_info) &&
!uniaud_mixer_get_ctl_val(card_id, put_id, ctl_val))
{
if (SNDRV_CTL_ELEM_TYPE_IEC958 == ctl_info->type)
{
ctl_val->value.iec958.status[0] = aes0;
ctl_val->value.iec958.status[1] = aes1;
ctl_val->value.iec958.status[2] = aes2;
ctl_val->value.iec958.status[3] = aes3;
}
if (err == 0)
uniaud_mixer_put_ctl_val(card_id, put_id, ctl_val);
}
else
err = -3;
if (ctl_info) free(ctl_info);
if (ctl_val) free(ctl_val);
return err;
}