/* * 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; }