Ignore:
Timestamp:
Jan 8, 2018, 2:07:36 AM (8 years ago)
Author:
David Azarewicz
Message:

Incorporated changes from Andy.
Added limited MSI support.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • GPL/trunk/lib32/soundmixer.c

    r598 r604  
    4141
    4242static struct {
    43         char *name;
    44         unsigned int index;
    45         unsigned int recsrc;
     43  char *name;
     44  unsigned int index;
     45  unsigned int recsrc;
    4646} ossid[OSS_MIXER_NRDEVICES] = {
    47         /* OSS_MIXER_VOLUME   */ { "Master", 0 , -1},
    48         /* OSS_MIXER_BASS         */ { "Tone Control - Bass", 0, -1},
    49         /* OSS_MIXER_TREBLE   */ { "Tone Control - Treble", 0, -1},
    50         /* OSS_MIXER_SYNTH        */ { "Synth", 0 , OSS32_MIX_RECSRC_SYNTH},
    51         /* OSS_MIXER_PCM          */ { "PCM", 0 , -1},
    52         /* OSS_MIXER_PCSPEAKER  */ { "PC Speaker", 0 , -1},
    53         /* OSS_MIXER_LINE         */ { "Line", 0 , OSS32_MIX_RECSRC_LINE},
    54         /* OSS_MIXER_MIC          */ { "Mic", 0, OSS32_MIX_RECSRC_MIC},
    55         /* OSS_MIXER_CD           */ { "CD", 0 , OSS32_MIX_RECSRC_CD},
    56         /* OSS_MIXER_IMIX         */ { "Monitor Mix", 0 , OSS32_MIX_RECSRC_MIXER},
    57         /* OSS_MIXER_ALTPCM   */ { "PCM",       1 , -1},
    58         /* OSS_MIXER_RECLEV   */ { "-- nothing --", 0 , -1},
    59         /* OSS_MIXER_IGAIN        */ { "Capture", 0 , -1},
    60         /* OSS_MIXER_OGAIN        */ { "Playback", 0 , -1},
    61         /* OSS_MIXER_LINE1        */ { "Aux", 0 , OSS32_MIX_RECSRC_AUX},
    62         /* OSS_MIXER_LINE2        */ { "Aux", 1 , -1},
    63         /* OSS_MIXER_LINE3        */ { "Aux", 2 , -1},
    64         /* OSS_MIXER_DIGITAL1 */ { "Digital", 0 , -1},
    65         /* OSS_MIXER_DIGITAL2 */ { "Digital", 1 , -1},
    66         /* OSS_MIXER_DIGITAL3 */ { "Digital", 2 , -1},
    67         /* OSS_MIXER_PHONEIN  */ { "Phone", 0 , OSS32_MIX_RECSRC_PHONE},
    68         /* OSS_MIXER_PHONEOUT */ { "Phone", 1 , -1},
    69         /* OSS_MIXER_VIDEO        */ { "Video", 0 , OSS32_MIX_RECSRC_VIDEO},
    70         /* OSS_MIXER_RADIO        */ { "Radio", 0 , -1},
    71         /* OSS_MIXER_MONITOR  */ { "Monitor", 0 , -1},
    72         /* OSS_MIXER_3DDEPTH  */ { "3D Control - Depth", 0 , -1},
    73         /* OSS_MIXER_3DCENTER */ { "3D Control - Center", 0 , -1},
    74         /* OSS_MIXER_FRONT        */ { "Front", 0 , -1},
    75         /* OSS_MIXER_SPEAKER  */ { "Speaker", 0 , -1},
    76         /* OSS_MIXER_HEADPHONE */ { "Headphone", 0 , -1},
     47  /* OSS_MIXER_VOLUME   */ { "Master", 0 , -1},
     48  /* OSS_MIXER_BASS   */ { "Tone Control - Bass", 0, -1},
     49  /* OSS_MIXER_TREBLE   */ { "Tone Control - Treble", 0, -1},
     50  /* OSS_MIXER_SYNTH    */ { "Synth", 0 , OSS32_MIX_RECSRC_SYNTH},
     51  /* OSS_MIXER_PCM    */ { "PCM", 0 , -1},
     52  /* OSS_MIXER_PCSPEAKER  */ { "PC Speaker", 0 , -1},
     53  /* OSS_MIXER_LINE   */ { "Line", 0 , OSS32_MIX_RECSRC_LINE},
     54  /* OSS_MIXER_MIC    */ { "Mic", 0, OSS32_MIX_RECSRC_MIC},
     55  /* OSS_MIXER_CD     */ { "CD", 0 , OSS32_MIX_RECSRC_CD},
     56  /* OSS_MIXER_IMIX   */ { "Monitor Mix", 0 , OSS32_MIX_RECSRC_MIXER},
     57  /* OSS_MIXER_ALTPCM   */ { "PCM", 1 , -1},
     58  /* OSS_MIXER_RECLEV   */ { "-- nothing --", 0 , -1},
     59  /* OSS_MIXER_IGAIN    */ { "Capture", 0 , -1},
     60  /* OSS_MIXER_OGAIN    */ { "Playback", 0 , -1},
     61  /* OSS_MIXER_LINE1    */ { "Aux", 0 , OSS32_MIX_RECSRC_AUX},
     62  /* OSS_MIXER_LINE2    */ { "Aux", 1 , -1},
     63  /* OSS_MIXER_LINE3    */ { "Aux", 2 , -1},
     64  /* OSS_MIXER_DIGITAL1 */ { "Digital", 0 , -1},
     65  /* OSS_MIXER_DIGITAL2 */ { "Digital", 1 , -1},
     66  /* OSS_MIXER_DIGITAL3 */ { "Digital", 2 , -1},
     67  /* OSS_MIXER_PHONEIN  */ { "Phone", 0 , OSS32_MIX_RECSRC_PHONE},
     68  /* OSS_MIXER_PHONEOUT */ { "Phone", 1 , -1},
     69  /* OSS_MIXER_VIDEO    */ { "Video", 0 , OSS32_MIX_RECSRC_VIDEO},
     70  /* OSS_MIXER_RADIO    */ { "Radio", 0 , -1},
     71  /* OSS_MIXER_MONITOR  */ { "Monitor", 0 , -1},
     72  /* OSS_MIXER_3DDEPTH  */ { "3D Control - Depth", 0 , -1},
     73  /* OSS_MIXER_3DCENTER */ { "3D Control - Center", 0 , -1},
     74  /* OSS_MIXER_FRONT    */ { "Front", 0 , -1},
     75  /* OSS_MIXER_SPEAKER  */ { "Speaker", 0 , -1},
     76  /* OSS_MIXER_HEADPHONE */ { "Headphone", 0 , -1},
    7777};
    7878char *szRecSources[OSS32_MIX_RECSRC_MAX] = {
    79         "Mic", "CD", "Line", "Video", "Aux", "Mix", "Mix Mono", "Phone", "Synth"
     79  "Mic", "CD", "Line", "Video", "Aux", "Mix", "Mix Mono", "Phone", "Synth"
    8080};
    8181
    8282static unsigned char LinToLog[OSS32_MAX_VOLUME+1] = {
    83   0,   0,       0,       0,   1,   2,   2,      5,   5,  10,
    84  10,  10,  16,  19,  20,  22,  24,      25,  27,  27,
    85  28,  28,  29,  30,  30,  35,  35,      35,  39,  39,
    86  43,  44,  45,  47,  48,  49,  50,      51,  52,  53,
    87  55,  56,  57,  59,  60,  62,  63,      64,  65,  66,
    88  67,  68,  69,  70,  71,  72,  73,      74,  74,  75,
    89  76,  77,  78,  79,  79,  80,  81,      82,  83,  84,
    90  85,  86,  87,  88,  89,  90,  91,      92,  92,  93,
    91  93,  94,  94,  95,  95,  96,  96,      97,  97,  98,
    92  98,  99,  99,  99,  99, 100, 100, 100, 100, 100,
     83  0,   0, 0,   0,   1,   2, 2,  5,   5,  10,
     84 10,  10,  16,  19,  20,  22,  24,  25,  27,  27,
     85 28,  28,  29,  30,  30,  35,  35,  35,  39,  39,
     86 43,  44,  45,  47,  48,  49,  50,  51,  52,  53,
     87 55,  56,  57,  59,  60,  62,  63,  64,  65,  66,
     88 67,  68,  69,  70,  71,  72,  73,  74,  74,  75,
     89 76,  77,  78,  79,  79,  80,  81,  82,  83,  84,
     90 85,  86,  87,  88,  89,  90,  91,  92,  92,  93,
     91 93,  94,  94,  95,  95,  96,  96,  97,  97,  98,
     92 98,  99,  99,  99,  99, 100, 100, 100, 100, 100,
    9393 100
    9494};
     
    9999ULONG ConvertVolume(ULONG ulLinVolume, ULONG ulLogVolMax)
    100100{
    101         if(ulLinVolume > OSS32_MAX_VOLUME) {
    102                 ulLinVolume = OSS32_MAX_VOLUME;
    103         }
    104         ulLinVolume = LinToLog[ulLinVolume];
    105 
    106         return (ulLinVolume * ulLogVolMax) / OSS32_MAX_VOLUME;
     101  if(ulLinVolume > OSS32_MAX_VOLUME) {
     102    ulLinVolume = OSS32_MAX_VOLUME;
     103  }
     104  ulLinVolume = LinToLog[ulLinVolume];
     105
     106  return (ulLinVolume * ulLogVolMax) / OSS32_MAX_VOLUME;
    107107}
    108108
     
    111111OSSRET OSS32_MixOpen(ULONG deviceid, OSSSTREAMID *pStreamId)
    112112{
    113         mixerhandle *pHandle = NULL;
    114         int              ret, i, j, sz;
    115 
    116         if(pStreamId == NULL) {
    117                 DebugInt3();
    118                 return OSSERR_INVALID_PARAMETER;
    119         }
    120         *pStreamId = 0;
    121 
    122         if(alsa_fops == NULL) {
    123                 ret = OSSERR_NO_DEVICE_AVAILABLE;
    124                 goto failure;
    125         }
    126 
    127         sz = sizeof(mixerhandle);
    128         pHandle = kmalloc(sz, GFP_KERNEL);
    129         if(pHandle == NULL) {
    130                 ret = OSSERR_OUT_OF_MEMORY;
    131                 goto failure;
    132         }
    133         memset(pHandle, 0, sizeof(mixerhandle));
    134 
    135         //set operation to non-blocking
    136         pHandle->file.f_flags = O_NONBLOCK;
    137 
    138         //setup pointers in file structure (used internally by ALSA)
    139         pHandle->file.f_dentry                  = &pHandle->d_entry;
    140         pHandle->file.f_dentry->d_inode = &pHandle->inode;
    141 
    142         pHandle->file.f_mode  = FMODE_WRITE;
    143         pHandle->inode.i_rdev = SNDRV_MINOR(deviceid, SNDRV_MINOR_CONTROL);
    144 
    145         ret = alsa_fops->open(&pHandle->inode, &pHandle->file);
    146         if(ret) {
    147                 goto failure;
    148         }
    149         //retrieve mixer information
    150         ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file,
    151                                                                         SNDRV_CTL_IOCTL_CARD_INFO,
    152                                                                         (ULONG)&pHandle->info);
    153         if(ret) {
    154                 goto failure;
    155         }
    156         //get the number of mixer elements
    157         pHandle->list.offset = 0;
    158         pHandle->list.space  = 0;
    159         ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file,
    160                                                                         SNDRV_CTL_IOCTL_ELEM_LIST,
    161                                                                         (ULONG)&pHandle->list);
    162         if(ret) {
    163                 goto failure;
    164         }
    165         //allocate memory for all mixer elements
    166         pHandle->pids = (struct snd_ctl_elem_id *)kmalloc(sizeof(struct snd_ctl_elem_id)*pHandle->list.count, GFP_KERNEL);
    167         if(pHandle->pids == NULL) {
    168                 goto failure;
    169         }
    170         //and retrieve all mixer elements
    171         pHandle->list.offset = 0;
    172         pHandle->list.space  = pHandle->list.count;
    173         pHandle->list.pids      = pHandle->pids;
    174         ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file,
    175                                                                         SNDRV_CTL_IOCTL_ELEM_LIST,
    176                                                                         (ULONG)&pHandle->list);
    177         if(ret) {
    178                 goto failure;
    179         }
     113  mixerhandle *pHandle = NULL;
     114  int      ret, i, j, sz;
     115
     116  if(pStreamId == NULL) {
     117    DebugInt3();
     118    return OSSERR_INVALID_PARAMETER;
     119  }
     120  *pStreamId = 0;
     121
     122  if(alsa_fops == NULL) {
     123    ret = OSSERR_NO_DEVICE_AVAILABLE;
     124    goto failure;
     125  }
     126
     127  sz = sizeof(mixerhandle);
     128  pHandle = kmalloc(sz, GFP_KERNEL);
     129  if(pHandle == NULL) {
     130    ret = OSSERR_OUT_OF_MEMORY;
     131    goto failure;
     132  }
     133  memset(pHandle, 0, sizeof(mixerhandle));
     134
     135  //set operation to non-blocking
     136  pHandle->file.f_flags = O_NONBLOCK;
     137
     138  //setup pointers in file structure (used internally by ALSA)
     139  pHandle->file.f_dentry      = &pHandle->d_entry;
     140  pHandle->file.f_dentry->d_inode = &pHandle->inode;
     141
     142  pHandle->file.f_mode  = FMODE_WRITE;
     143  pHandle->inode.i_rdev = SNDRV_MINOR(deviceid, SNDRV_MINOR_CONTROL);
     144
     145  ret = alsa_fops->open(&pHandle->inode, &pHandle->file);
     146  if(ret) {
     147    goto failure;
     148  }
     149  //retrieve mixer information
     150  ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file,
     151                  SNDRV_CTL_IOCTL_CARD_INFO,
     152                  (ULONG)&pHandle->info);
     153  if(ret) {
     154    goto failure;
     155  }
     156  //get the number of mixer elements
     157  pHandle->list.offset = 0;
     158  pHandle->list.space  = 0;
     159  ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file,
     160                  SNDRV_CTL_IOCTL_ELEM_LIST,
     161                  (ULONG)&pHandle->list);
     162  if(ret) {
     163    goto failure;
     164  }
     165  //allocate memory for all mixer elements
     166  pHandle->pids = (struct snd_ctl_elem_id *)kmalloc(sizeof(struct snd_ctl_elem_id)*pHandle->list.count, GFP_KERNEL);
     167  if(pHandle->pids == NULL) {
     168    goto failure;
     169  }
     170  //and retrieve all mixer elements
     171  pHandle->list.offset = 0;
     172  pHandle->list.space  = pHandle->list.count;
     173  pHandle->list.pids  = pHandle->pids;
     174  ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file,
     175                  SNDRV_CTL_IOCTL_ELEM_LIST,
     176                  (ULONG)&pHandle->list);
     177  if(ret) {
     178    goto failure;
     179  }
    180180
    181181#if 0
    182         dprintf(("Mixer name: %s", pHandle->info.mixername));
    183         dprintf(("List of mixer elements:"));
    184         for(i=0;i<pHandle->list.count;i++) {
    185                 dprintf(("index %d name %s id %d device %d subdevice %d", pHandle->pids[i].index, pHandle->pids[i].name, pHandle->pids[i].numid, pHandle->pids[i].device, pHandle->pids[i].subdevice));
    186         }
     182  dprintf(("Mixer name: %s", pHandle->info.mixername));
     183  dprintf(("List of mixer elements:"));
     184  for(i=0;i<pHandle->list.count;i++) {
     185    dprintf(("index %d name %s id %d device %d subdevice %d", pHandle->pids[i].index, pHandle->pids[i].name, pHandle->pids[i].numid, pHandle->pids[i].device, pHandle->pids[i].subdevice));
     186  }
    187187#endif
    188188
    189         //Extract standard mixer controls from array with control names
    190         for(j=0;j<OSS_MIXER_NRDEVICES;j++)
    191         {
    192                 int namelen = strlen(ossid[j].name);
    193 
    194                 pHandle->controls[j].idxVolume            = -1;
    195                 pHandle->controls[j].idxMute              = -1;
    196                 pHandle->controls[j].idxCustom            = -1;
    197                 pHandle->controls[j].idxCaptureSwitch = -1;
    198 
    199                 for(i=0;i<pHandle->list.count;i++) {
    200                         if (pHandle->pids[i].index == ossid[j].index && strncmp(pHandle->pids[i].name, ossid[j].name, namelen) == 0) {
    201                                 int controlnamelen = strlen(pHandle->pids[i].name);
    202 
    203                                 if(namelen == controlnamelen) { //control names are identical; found exact match
    204                                         pHandle->controls[j].idxVolume = i;
    205                                         break;
    206                                 } else { //first part of the control name is correct; now find out what is it exactly
    207                                         char *nextword = &pHandle->pids[i].name[namelen];
    208                                         while(*nextword && *nextword == ' ') nextword++;
    209 
    210                                         if(strncmp(nextword, MIXER_PLAYBACKVOLUME, sizeof(MIXER_PLAYBACKVOLUME)-1) == 0 ||
    211                                            strncmp(nextword, MIXER_VOLUME, sizeof(MIXER_VOLUME)-1) == 0)
    212                                         { //volume control
    213                                                 pHandle->controls[j].idxVolume = i;
    214                                         }
    215                                         else
    216                                         if(strncmp(nextword, MIXER_PLAYBACKSWITCH, sizeof(MIXER_PLAYBACKSWITCH)-1) == 0 ||
    217                                            strncmp(nextword, MIXER_SWITCH, sizeof(MIXER_SWITCH)-1) == 0)
    218                                         { //mute control
    219                                                 pHandle->controls[j].idxMute = i;
    220                                                 if (pHandle->controls[j].idxVolume == -1) pHandle->controls[j].idxVolume = i;
    221                                         }
    222                                         else
    223                                         if(strncmp(nextword, MIXER_SOURCE, sizeof(MIXER_SOURCE)-1) == 0)
    224                                         { //source control (e.g. recording source)
    225                                                 pHandle->controls[j].idxCustom = i;
    226                                         }
    227                                         else
    228                                         if(strncmp(nextword, MIXER_CAPTUREROUTE, sizeof(MIXER_CAPTUREROUTE)-1) == 0 ||
    229                                            strncmp(nextword, MIXER_CAPTURESWITCH, sizeof(MIXER_CAPTURESWITCH)-1) == 0)
    230                                         { //source control for recording (per input)
    231                                                 pHandle->controls[j].idxCaptureSwitch = i;
    232                                         }
    233                                         else
    234                                         if(i == OSS_MIXER_MIC) {
    235                                                 if(strncmp(nextword, MIXER_BOOST, sizeof(MIXER_BOOST)-1) == 0) { //mic boost switch
    236                                                         pHandle->controls[j].idxCustom = i;
    237                                                 }
    238                                         }
    239                                 }
    240                         }
    241                 }
    242         }
    243 
    244         pHandle->reccaps = 0;
    245         for (j=0;j<OSS32_MIX_RECSRC_MAX;j++) {
    246                 pHandle->idxRecCaps[j] = -1;
    247         }
    248 
    249         //request information about available capture sources
    250         if (pHandle->controls[OSS_MIXER_IGAIN].idxCustom != -1) {
    251                 struct snd_ctl_elem_info  *pElemInfo = NULL;
    252                 int idx, j;
    253 
    254                 idx = pHandle->controls[OSS_MIXER_IGAIN].idxCustom;
    255 
    256                 //set operation to non-blocking
    257                 pHandle->file.f_flags = O_NONBLOCK;
    258 
    259                 pHandle->rectype = RECTYPE_SELECTOR;
    260 
    261                 //too big to put on the stack
    262                 pElemInfo = (struct snd_ctl_elem_info *)kmalloc(sizeof(struct snd_ctl_elem_info), GFP_KERNEL);
    263                 if(pElemInfo == NULL) {
    264                         DebugInt3();
    265                         goto failure;
    266                 }
    267 
    268                 pElemInfo->value.enumerated.items = 1;
    269                 for(i=0;i<pElemInfo->value.enumerated.items;i++)
    270                 {
    271                         pElemInfo->value.enumerated.item = i;
    272                         pElemInfo->id.numid = pHandle->pids[idx].numid;
    273                         ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_CTL_IOCTL_ELEM_INFO, (ULONG)pElemInfo);
    274                         if(ret) {
    275                                 DebugInt3();
    276                                 break;
    277                         }
    278                         if(pElemInfo->type != SNDRV_CTL_ELEM_TYPE_ENUMERATED) {
    279                                 DebugInt3();
    280                                 break;
    281                         }
    282                         for(j=0;j<OSS32_MIX_RECSRC_MAX;j++) {
    283                                 if(!strcmp(pElemInfo->value.enumerated.name, szRecSources[j])) {
    284                                         pHandle->reccaps          |= OSS32_MIX_FLAG(j);
    285                                         pHandle->idxRecCaps[j] = i; //save alsa index
    286                                         break;
    287                                 }
    288                         }
    289                 }
    290                 kfree(pElemInfo);
    291         }
    292         else
    293         {//This card has no record source selection, but probably route switches for
    294         //each input source (SB mixers (also ALS4000), CMedia)
    295                 pHandle->rectype = RECTYPE_SWITCH;
    296                 for(j=0;j<OSS32_MIX_RECSRC_MAX;j++) {
    297                         pHandle->idxRecCaps[j] = -1;
    298                 }
    299                 for(j=0;j<OSS_MIXER_NRDEVICES;j++)
    300                 {
    301                         if(pHandle->controls[j].idxCaptureSwitch != -1) {
    302                                 pHandle->reccaps                                        |= OSS32_MIX_FLAG(ossid[j].recsrc);
    303                                 pHandle->idxRecCaps[ossid[j].recsrc] = pHandle->controls[j].idxCaptureSwitch; //save alsa index
    304                         }
    305                 }
    306         }
    307 
    308         pHandle->magic = MAGIC_MIXER_ALSA32;
    309         *pStreamId = (ULONG)pHandle;
    310         return OSSERR_SUCCESS;
     189  //Extract standard mixer controls from array with control names
     190  for(j=0;j<OSS_MIXER_NRDEVICES;j++)
     191  {
     192    int namelen = strlen(ossid[j].name);
     193
     194    pHandle->controls[j].idxVolume      = -1;
     195    pHandle->controls[j].idxMute      = -1;
     196    pHandle->controls[j].idxCustom      = -1;
     197    pHandle->controls[j].idxCaptureSwitch = -1;
     198
     199    for(i=0;i<pHandle->list.count;i++) {
     200      if (pHandle->pids[i].index == ossid[j].index && strncmp(pHandle->pids[i].name, ossid[j].name, namelen) == 0) {
     201        int controlnamelen = strlen(pHandle->pids[i].name);
     202
     203        if(namelen == controlnamelen) { //control names are identical; found exact match
     204          pHandle->controls[j].idxVolume = i;
     205          break;
     206        } else { //first part of the control name is correct; now find out what is it exactly
     207          char *nextword = &pHandle->pids[i].name[namelen];
     208          while(*nextword && *nextword == ' ') nextword++;
     209
     210          if(strncmp(nextword, MIXER_PLAYBACKVOLUME, sizeof(MIXER_PLAYBACKVOLUME)-1) == 0 ||
     211             strncmp(nextword, MIXER_VOLUME, sizeof(MIXER_VOLUME)-1) == 0)
     212          { //volume control
     213            pHandle->controls[j].idxVolume = i;
     214          }
     215          else
     216          if(strncmp(nextword, MIXER_PLAYBACKSWITCH, sizeof(MIXER_PLAYBACKSWITCH)-1) == 0 ||
     217             strncmp(nextword, MIXER_SWITCH, sizeof(MIXER_SWITCH)-1) == 0)
     218          { //mute control
     219            pHandle->controls[j].idxMute = i;
     220            if (pHandle->controls[j].idxVolume == -1) pHandle->controls[j].idxVolume = i;
     221          }
     222          else
     223          if(strncmp(nextword, MIXER_SOURCE, sizeof(MIXER_SOURCE)-1) == 0)
     224          { //source control (e.g. recording source)
     225            pHandle->controls[j].idxCustom = i;
     226          }
     227          else
     228          if(strncmp(nextword, MIXER_CAPTUREROUTE, sizeof(MIXER_CAPTUREROUTE)-1) == 0 ||
     229             strncmp(nextword, MIXER_CAPTURESWITCH, sizeof(MIXER_CAPTURESWITCH)-1) == 0)
     230          { //source control for recording (per input)
     231            pHandle->controls[j].idxCaptureSwitch = i;
     232          }
     233          else
     234          if(i == OSS_MIXER_MIC) {
     235            if(strncmp(nextword, MIXER_BOOST, sizeof(MIXER_BOOST)-1) == 0) { //mic boost switch
     236              pHandle->controls[j].idxCustom = i;
     237            }
     238          }
     239        }
     240      }
     241    }
     242  }
     243
     244  pHandle->reccaps = 0;
     245  for (j=0;j<OSS32_MIX_RECSRC_MAX;j++) {
     246    pHandle->idxRecCaps[j] = -1;
     247  }
     248
     249  //request information about available capture sources
     250  if (pHandle->controls[OSS_MIXER_IGAIN].idxCustom != -1) {
     251    struct snd_ctl_elem_info  *pElemInfo = NULL;
     252    int idx, j;
     253
     254    idx = pHandle->controls[OSS_MIXER_IGAIN].idxCustom;
     255
     256    //set operation to non-blocking
     257    pHandle->file.f_flags = O_NONBLOCK;
     258
     259    pHandle->rectype = RECTYPE_SELECTOR;
     260
     261    //too big to put on the stack
     262    pElemInfo = (struct snd_ctl_elem_info *)kmalloc(sizeof(struct snd_ctl_elem_info), GFP_KERNEL);
     263    if(pElemInfo == NULL) {
     264      DebugInt3();
     265      goto failure;
     266    }
     267
     268    pElemInfo->value.enumerated.items = 1;
     269    for(i=0;i<pElemInfo->value.enumerated.items;i++)
     270    {
     271      pElemInfo->value.enumerated.item = i;
     272      pElemInfo->id.numid = pHandle->pids[idx].numid;
     273      ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_CTL_IOCTL_ELEM_INFO, (ULONG)pElemInfo);
     274      if(ret) {
     275        DebugInt3();
     276        break;
     277      }
     278      if(pElemInfo->type != SNDRV_CTL_ELEM_TYPE_ENUMERATED) {
     279        DebugInt3();
     280        break;
     281      }
     282      for(j=0;j<OSS32_MIX_RECSRC_MAX;j++) {
     283        if(!strcmp(pElemInfo->value.enumerated.name, szRecSources[j])) {
     284          pHandle->reccaps    |= OSS32_MIX_FLAG(j);
     285          pHandle->idxRecCaps[j] = i; //save alsa index
     286          break;
     287        }
     288      }
     289    }
     290    kfree(pElemInfo);
     291  }
     292  else
     293  {//This card has no record source selection, but probably route switches for
     294  //each input source (SB mixers (also ALS4000), CMedia)
     295    pHandle->rectype = RECTYPE_SWITCH;
     296    for(j=0;j<OSS32_MIX_RECSRC_MAX;j++) {
     297      pHandle->idxRecCaps[j] = -1;
     298    }
     299    for(j=0;j<OSS_MIXER_NRDEVICES;j++)
     300    {
     301      if(pHandle->controls[j].idxCaptureSwitch != -1) {
     302        pHandle->reccaps          |= OSS32_MIX_FLAG(ossid[j].recsrc);
     303        pHandle->idxRecCaps[ossid[j].recsrc] = pHandle->controls[j].idxCaptureSwitch; //save alsa index
     304      }
     305    }
     306  }
     307
     308  pHandle->magic = MAGIC_MIXER_ALSA32;
     309  *pStreamId = (ULONG)pHandle;
     310  return OSSERR_SUCCESS;
    311311
    312312failure:
    313         if(pHandle) {
    314                 if(pHandle->pids) kfree(pHandle->pids);
    315                 kfree(pHandle);
    316         }
    317         DebugInt3();
    318         return OSSERR_OUT_OF_MEMORY;
     313  if(pHandle) {
     314    if(pHandle->pids) kfree(pHandle->pids);
     315    kfree(pHandle);
     316  }
     317  DebugInt3();
     318  return OSSERR_OUT_OF_MEMORY;
    319319}
    320320//******************************************************************************
     
    322322OSSRET OSS32_MixClose(OSSSTREAMID streamid)
    323323{
    324         mixerhandle *pHandle = (mixerhandle *)streamid;
    325         int              ret;
    326 
    327         if(pHandle == NULL || pHandle->magic != MAGIC_MIXER_ALSA32) {
    328                 DebugInt3();
    329                 return OSSERR_INVALID_STREAMID;
    330         }
    331         //set operation to non-blocking
    332         pHandle->file.f_flags = O_NONBLOCK;
    333         ret = pHandle->file.f_op->release(&pHandle->inode, &pHandle->file);
    334         kfree(pHandle->pids);  //free mixer element array
    335         kfree(pHandle);            //free handle data
    336 
    337         if(ret) {
    338                 DebugInt3();
    339                 return UNIXToOSSError(ret);
    340         }
    341         return OSSERR_SUCCESS;
     324  mixerhandle *pHandle = (mixerhandle *)streamid;
     325  int      ret;
     326
     327  if(pHandle == NULL || pHandle->magic != MAGIC_MIXER_ALSA32) {
     328    DebugInt3();
     329    return OSSERR_INVALID_STREAMID;
     330  }
     331  //set operation to non-blocking
     332  pHandle->file.f_flags = O_NONBLOCK;
     333  ret = pHandle->file.f_op->release(&pHandle->inode, &pHandle->file);
     334  kfree(pHandle->pids);  //free mixer element array
     335  kfree(pHandle);      //free handle data
     336
     337  if(ret) {
     338    DebugInt3();
     339    return UNIXToOSSError(ret);
     340  }
     341  return OSSERR_SUCCESS;
    342342}
    343343//******************************************************************************
     
    345345OSSRET OSS32_MixGetVolume(OSSSTREAMID streamid, ULONG line, ULONG *pVolume)
    346346{
    347         mixerhandle *pHandle = (mixerhandle *)streamid;
    348         //int            ret;
    349 
    350         if(pHandle == NULL || pHandle->magic != MAGIC_MIXER_ALSA32) {
    351                 DebugInt3();
    352                 return OSSERR_INVALID_STREAMID;
    353         }
    354         //set operation to non-blocking
    355         pHandle->file.f_flags = O_NONBLOCK;
    356 
    357         return OSSERR_NOT_SUPPORTED;
     347  mixerhandle *pHandle = (mixerhandle *)streamid;
     348  //int      ret;
     349
     350  if(pHandle == NULL || pHandle->magic != MAGIC_MIXER_ALSA32) {
     351    DebugInt3();
     352    return OSSERR_INVALID_STREAMID;
     353  }
     354  //set operation to non-blocking
     355  pHandle->file.f_flags = O_NONBLOCK;
     356
     357  return OSSERR_NOT_SUPPORTED;
    358358}
    359359//******************************************************************************
     
    361361OSSRET OSS32_MixSetVolume(OSSSTREAMID streamid, ULONG line, ULONG volume)
    362362{
    363         mixerhandle              *pHandle = (mixerhandle *)streamid;
    364         struct snd_ctl_elem_value *pElem = NULL;
    365         struct snd_ctl_elem_info  *pElemInfo;
    366         int                               ret, idx, lVol, rVol = 0, idxMute;
    367         //int cnt;
    368 
    369         //dprintf(("OSS32_MixSetVolume line=%d\n", line));
    370         if(pHandle == NULL || pHandle->magic != MAGIC_MIXER_ALSA32) {
    371                 printk("Invalid handle in OSS32_MixSetVolume\n");
    372                 DebugInt3();
    373                 return OSSERR_INVALID_STREAMID;
    374         }
    375         //set operation to non-blocking
    376         pHandle->file.f_flags = O_NONBLOCK;
    377 
    378         //too big to put on the stack
    379         pElem = (struct snd_ctl_elem_value *)kmalloc(sizeof(struct snd_ctl_elem_value) + sizeof(struct snd_ctl_elem_info), GFP_KERNEL);
    380         if(pElem == NULL) {
    381                 printk("Out of memory in OSS32_MixSetVolume\n");
    382                 DebugInt3();
    383                 return OSSERR_OUT_OF_MEMORY;
    384         }
    385         pElemInfo = (struct snd_ctl_elem_info *)(pElem+1);
    386 
    387         switch(line) {
    388         case OSS32_MIX_VOLUME_MASTER_FRONT:
    389                 idx = pHandle->controls[OSS_MIXER_VOLUME].idxVolume;
    390                 idxMute = pHandle->controls[OSS_MIXER_VOLUME].idxMute;
    391                 if (idx == -1)
    392                 {
    393                         /* HDA codecs workaround */
    394                         idx = pHandle->controls[OSS_MIXER_FRONT].idxVolume;
    395                         idxMute = pHandle->controls[OSS_MIXER_FRONT].idxMute;
    396                 }
    397                 break;
    398         case OSS32_MIX_VOLUME_MASTER_REAR: //TODO:
    399                 idx = pHandle->controls[OSS_MIXER_VOLUME].idxVolume;
    400                 idxMute = pHandle->controls[OSS_MIXER_VOLUME].idxMute;
    401                 break;
    402         case OSS32_MIX_VOLUME_PCM:
    403                 idx = pHandle->controls[OSS_MIXER_PCM].idxVolume;
    404                 idxMute = pHandle->controls[OSS_MIXER_PCM].idxMute;
    405                 if (idx == -1)
    406                 {
    407                         /* HDA codecs workaround */
    408                         idx = pHandle->controls[OSS_MIXER_FRONT].idxVolume;
    409                         idxMute = pHandle->controls[OSS_MIXER_FRONT].idxMute;
    410                 }
    411                 break;
    412         case OSS32_MIX_VOLUME_MIDI:
    413                 idx = pHandle->controls[OSS_MIXER_SYNTH].idxVolume;
    414                 idxMute = pHandle->controls[OSS_MIXER_SYNTH].idxMute;
    415                 break;
    416         case OSS32_MIX_VOLUME_LINEIN:
    417                 idx = pHandle->controls[OSS_MIXER_LINE].idxVolume;
    418                 idxMute = pHandle->controls[OSS_MIXER_LINE].idxMute;
    419                 break;
    420         case OSS32_MIX_VOLUME_MIC:
    421                 idx = pHandle->controls[OSS_MIXER_MIC].idxVolume;
    422                 idxMute = pHandle->controls[OSS_MIXER_MIC].idxMute;
    423                 break;
    424         case OSS32_MIX_VOLUME_CD:
    425                 idx = pHandle->controls[OSS_MIXER_CD].idxVolume;
    426                 idxMute = pHandle->controls[OSS_MIXER_CD].idxMute;
    427                 break;
    428         case OSS32_MIX_VOLUME_SPDIF:
    429                 idx = pHandle->controls[OSS_MIXER_DIGITAL1].idxVolume;
    430                 idxMute = pHandle->controls[OSS_MIXER_DIGITAL1].idxMute;
    431                 break;
    432         case OSS32_MIX_VOLUME_VIDEO:
    433                 idx = pHandle->controls[OSS_MIXER_VIDEO].idxVolume;
    434                 idxMute = pHandle->controls[OSS_MIXER_VIDEO].idxMute;
    435                 break;
    436         case OSS32_MIX_VOLUME_PCSPEAKER:
    437                 idx = pHandle->controls[OSS_MIXER_PCSPEAKER].idxVolume;
    438                 idxMute = pHandle->controls[OSS_MIXER_PCSPEAKER].idxMute;
    439                 break;
    440         case OSS32_MIX_VOLUME_PHONE:
    441                 idx = pHandle->controls[OSS_MIXER_PHONEOUT].idxVolume;
    442                 idxMute = pHandle->controls[OSS_MIXER_PHONEOUT].idxMute;
    443                 break;
    444         case OSS32_MIX_VOLUME_HEADPHONE:
    445                 idx = pHandle->controls[OSS_MIXER_HEADPHONE].idxVolume;
    446                 idxMute = pHandle->controls[OSS_MIXER_HEADPHONE].idxMute;
    447                 break;
    448         case OSS32_MIX_VOLUME_SPEAKER:
    449                 idx = pHandle->controls[OSS_MIXER_SPEAKER].idxVolume;
    450                 idxMute = pHandle->controls[OSS_MIXER_SPEAKER].idxMute;
    451                 break;
    452         case OSS32_MIX_VOLUME_AUX:
    453                 idx = pHandle->controls[OSS_MIXER_LINE1].idxVolume;
    454                 idxMute = pHandle->controls[OSS_MIXER_LINE1].idxMute;
    455                 break;
    456         case OSS32_MIX_VOLUME_CAPTURE:
    457                 idx = pHandle->controls[OSS_MIXER_IGAIN].idxVolume;
    458                 idxMute = pHandle->controls[OSS_MIXER_IGAIN].idxMute;
    459                 break;
    460 
    461         default:
    462                 DebugInt3();
    463                 ret = OSSERR_INVALID_PARAMETER;
    464                 goto fail;
    465         }
    466         if(idx == -1) {
    467                 rprintf(("Unknown control %d", line));
    468                 ret = OSSERR_INVALID_PARAMETER;
    469                 goto fail;
    470         }
    471 
    472         if(idxMute != -1 && volume != 0) {
    473                 //disable mute
    474                 pElem->id.numid = pHandle->pids[idxMute].numid;
    475                 pElem->indirect = 0;
    476 
    477                 pElem->value.integer.value[0] = TRUE;  //switch, not mute control (inversed)
    478                 pElem->value.integer.value[1] = TRUE;
    479                 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_CTL_IOCTL_ELEM_WRITE, (ULONG)pElem);
    480         }
    481         //request information about mixer control
    482         pElemInfo->id.numid = pHandle->pids[idx].numid;
    483         ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_CTL_IOCTL_ELEM_INFO, (ULONG)pElemInfo);
    484         if(ret) {
    485                 ret = UNIXToOSSError(ret);
    486                 DebugInt3();
    487                 goto fail;
    488         }
    489         if(pElemInfo->type != SNDRV_CTL_ELEM_TYPE_INTEGER) {
    490                 ret = OSSERR_INVALID_PARAMETER;
    491                 DebugInt3();
    492                 goto fail;
    493         }
    494         pElem->id.numid = pHandle->pids[idx].numid;
    495         pElem->indirect = 0;
    496 
    497         lVol = ConvertVolume(GET_VOLUME_L(volume), pElemInfo->value.integer.max);
    498         pElem->value.integer.value[0] = lVol;
    499 
    500         if(pElemInfo->count > 1) { //stereo
    501                 rVol = ConvertVolume(GET_VOLUME_R(volume), pElemInfo->value.integer.max);
    502                 pElem->value.integer.value[1] = rVol;
    503         }
    504 
    505         dprintf(("OSS32_MixSetVolume of %s streamid %X to (%d,%d)(%d,%d) caps %d",
    506                 pHandle->pids[idx].name, (ULONG)pHandle,
    507                 GET_VOLUME_L(volume), GET_VOLUME_R(volume), lVol, rVol, pElemInfo->value.integer.max));
     363  mixerhandle      *pHandle = (mixerhandle *)streamid;
     364  struct snd_ctl_elem_value *pElem = NULL;
     365  struct snd_ctl_elem_info  *pElemInfo;
     366  int           ret, idx, lVol, rVol = 0, idxMute;
     367  //int cnt;
     368
     369  //dprintf(("OSS32_MixSetVolume line=%d\n", line));
     370  if(pHandle == NULL || pHandle->magic != MAGIC_MIXER_ALSA32) {
     371    printk("Invalid handle in OSS32_MixSetVolume\n");
     372    DebugInt3();
     373    return OSSERR_INVALID_STREAMID;
     374  }
     375  //set operation to non-blocking
     376  pHandle->file.f_flags = O_NONBLOCK;
     377
     378  //too big to put on the stack
     379  pElem = (struct snd_ctl_elem_value *)kmalloc(sizeof(struct snd_ctl_elem_value) + sizeof(struct snd_ctl_elem_info), GFP_KERNEL);
     380  if(pElem == NULL) {
     381    printk("Out of memory in OSS32_MixSetVolume\n");
     382    DebugInt3();
     383    return OSSERR_OUT_OF_MEMORY;
     384  }
     385  pElemInfo = (struct snd_ctl_elem_info *)(pElem+1);
     386
     387  switch(line) {
     388  case OSS32_MIX_VOLUME_MASTER_FRONT:
     389    idx = pHandle->controls[OSS_MIXER_VOLUME].idxVolume;
     390    idxMute = pHandle->controls[OSS_MIXER_VOLUME].idxMute;
     391    if (idx == -1)
     392    {
     393      /* HDA codecs workaround */
     394      idx = pHandle->controls[OSS_MIXER_FRONT].idxVolume;
     395      idxMute = pHandle->controls[OSS_MIXER_FRONT].idxMute;
     396    }
     397    break;
     398  case OSS32_MIX_VOLUME_MASTER_REAR: //TODO:
     399    idx = pHandle->controls[OSS_MIXER_VOLUME].idxVolume;
     400    idxMute = pHandle->controls[OSS_MIXER_VOLUME].idxMute;
     401    break;
     402  case OSS32_MIX_VOLUME_PCM:
     403    idx = pHandle->controls[OSS_MIXER_PCM].idxVolume;
     404    idxMute = pHandle->controls[OSS_MIXER_PCM].idxMute;
     405    if (idx == -1)
     406    {
     407      /* HDA codecs workaround */
     408      idx = pHandle->controls[OSS_MIXER_FRONT].idxVolume;
     409      idxMute = pHandle->controls[OSS_MIXER_FRONT].idxMute;
     410    }
     411    /* HDA codecs workaround from Andy */
     412    if (idx == -1)
     413    {
     414      idx = pHandle->controls[OSS_MIXER_SPEAKER].idxVolume;
     415      idxMute = pHandle->controls[OSS_MIXER_SPEAKER].idxMute;
     416    }
     417    /* HDA codecs workaround from Andy */
     418    break;
     419  case OSS32_MIX_VOLUME_MIDI:
     420    idx = pHandle->controls[OSS_MIXER_SYNTH].idxVolume;
     421    idxMute = pHandle->controls[OSS_MIXER_SYNTH].idxMute;
     422    break;
     423  case OSS32_MIX_VOLUME_LINEIN:
     424    idx = pHandle->controls[OSS_MIXER_LINE].idxVolume;
     425    idxMute = pHandle->controls[OSS_MIXER_LINE].idxMute;
     426    break;
     427  case OSS32_MIX_VOLUME_MIC:
     428    idx = pHandle->controls[OSS_MIXER_MIC].idxVolume;
     429    idxMute = pHandle->controls[OSS_MIXER_MIC].idxMute;
     430    break;
     431  case OSS32_MIX_VOLUME_CD:
     432    idx = pHandle->controls[OSS_MIXER_CD].idxVolume;
     433    idxMute = pHandle->controls[OSS_MIXER_CD].idxMute;
     434    break;
     435  case OSS32_MIX_VOLUME_SPDIF:
     436    idx = pHandle->controls[OSS_MIXER_DIGITAL1].idxVolume;
     437    idxMute = pHandle->controls[OSS_MIXER_DIGITAL1].idxMute;
     438    break;
     439  case OSS32_MIX_VOLUME_VIDEO:
     440    idx = pHandle->controls[OSS_MIXER_VIDEO].idxVolume;
     441    idxMute = pHandle->controls[OSS_MIXER_VIDEO].idxMute;
     442    break;
     443  case OSS32_MIX_VOLUME_PCSPEAKER:
     444    idx = pHandle->controls[OSS_MIXER_PCSPEAKER].idxVolume;
     445    idxMute = pHandle->controls[OSS_MIXER_PCSPEAKER].idxMute;
     446    break;
     447  case OSS32_MIX_VOLUME_PHONE:
     448    idx = pHandle->controls[OSS_MIXER_PHONEOUT].idxVolume;
     449    idxMute = pHandle->controls[OSS_MIXER_PHONEOUT].idxMute;
     450    break;
     451  case OSS32_MIX_VOLUME_HEADPHONE:
     452    idx = pHandle->controls[OSS_MIXER_HEADPHONE].idxVolume;
     453    idxMute = pHandle->controls[OSS_MIXER_HEADPHONE].idxMute;
     454    break;
     455  case OSS32_MIX_VOLUME_SPEAKER:
     456    idx = pHandle->controls[OSS_MIXER_SPEAKER].idxVolume;
     457    idxMute = pHandle->controls[OSS_MIXER_SPEAKER].idxMute;
     458    break;
     459  case OSS32_MIX_VOLUME_AUX:
     460    idx = pHandle->controls[OSS_MIXER_LINE1].idxVolume;
     461    idxMute = pHandle->controls[OSS_MIXER_LINE1].idxMute;
     462    break;
     463  case OSS32_MIX_VOLUME_CAPTURE:
     464    idx = pHandle->controls[OSS_MIXER_IGAIN].idxVolume;
     465    idxMute = pHandle->controls[OSS_MIXER_IGAIN].idxMute;
     466    break;
     467
     468  default:
     469    DebugInt3();
     470    ret = OSSERR_INVALID_PARAMETER;
     471    goto fail;
     472  }
     473  if(idx == -1) {
     474    rprintf(("Unknown control %d", line));
     475    ret = OSSERR_INVALID_PARAMETER;
     476    goto fail;
     477  }
     478
     479  if(idxMute != -1 && volume != 0) {
     480    //disable mute
     481    pElem->id.numid = pHandle->pids[idxMute].numid;
     482    pElem->indirect = 0;
     483
     484    pElem->value.integer.value[0] = TRUE;  //switch, not mute control (inversed)
     485    pElem->value.integer.value[1] = TRUE;
     486    ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_CTL_IOCTL_ELEM_WRITE, (ULONG)pElem);
     487  }
     488  //request information about mixer control
     489  pElemInfo->id.numid = pHandle->pids[idx].numid;
     490  ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_CTL_IOCTL_ELEM_INFO, (ULONG)pElemInfo);
     491  if(ret) {
     492    ret = UNIXToOSSError(ret);
     493    DebugInt3();
     494    goto fail;
     495  }
     496  if(pElemInfo->type != SNDRV_CTL_ELEM_TYPE_INTEGER) {
     497    ret = OSSERR_INVALID_PARAMETER;
     498    DebugInt3();
     499    goto fail;
     500  }
     501  pElem->id.numid = pHandle->pids[idx].numid;
     502  pElem->indirect = 0;
     503
     504  lVol = ConvertVolume(GET_VOLUME_L(volume), pElemInfo->value.integer.max);
     505  pElem->value.integer.value[0] = lVol;
     506
     507  if(pElemInfo->count > 1) { //stereo
     508    rVol = ConvertVolume(GET_VOLUME_R(volume), pElemInfo->value.integer.max);
     509    pElem->value.integer.value[1] = rVol;
     510  }
     511
     512  dprintf(("OSS32_MixSetVolume of %s streamid %X to (%d,%d)(%d,%d) caps %d",
     513    pHandle->pids[idx].name, (ULONG)pHandle,
     514    GET_VOLUME_L(volume), GET_VOLUME_R(volume), lVol, rVol, pElemInfo->value.integer.max));
    508515
    509516#if 1
    510         ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_CTL_IOCTL_ELEM_WRITE, (ULONG)pElem);
     517  ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_CTL_IOCTL_ELEM_WRITE, (ULONG)pElem);
    511518#else
    512         // looking for more, then one opened streams to prevent of muting active stream
    513         cnt = 0;
    514         for (idx=0; idx < 8*256; idx++)
    515                 if (opened_handles[idx].handle != 0)
    516                         cnt++;
    517 
    518         dprintf(("OSS32_MixSetVolume old cnt=%X line=%x lVol=%x rVol=%x", cnt, line, lVol, rVol));
    519         //        if (((cnt == 1 && (lVol==0 && rVol==0)) || (lVol>0 && rVol>0)) ||
    520         if (cnt == 1 || line != OSS32_MIX_VOLUME_PCM)
    521         {
    522                 dprintf(("OSS32_MixSetVolume Ioctl"));
    523                 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_CTL_IOCTL_ELEM_WRITE, (ULONG)pElem);
    524 
    525                 if(idxMute != -1 && volume == 0) {
    526                         //enable mute
    527                         pElem->id.numid = pHandle->pids[idxMute].numid;
    528                         pElem->indirect = 0;
    529 
    530                         pElem->value.integer.value[0] = FALSE;  //switch, not mute control (inversed)
    531                         pElem->value.integer.value[1] = FALSE;
    532                         dprintf(("OSS32_MixSetVolume Ioctl mute"));
    533                         ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_CTL_IOCTL_ELEM_WRITE, (ULONG)pElem);
    534                 }
    535         }
     519  // looking for more, then one opened streams to prevent of muting active stream
     520  cnt = 0;
     521  for (idx=0; idx < 8*256; idx++)
     522    if (opened_handles[idx].handle != 0)
     523      cnt++;
     524
     525  dprintf(("OSS32_MixSetVolume old cnt=%X line=%x lVol=%x rVol=%x", cnt, line, lVol, rVol));
     526  //    if (((cnt == 1 && (lVol==0 && rVol==0)) || (lVol>0 && rVol>0)) ||
     527  if (cnt == 1 || line != OSS32_MIX_VOLUME_PCM)
     528  {
     529    dprintf(("OSS32_MixSetVolume Ioctl"));
     530    ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_CTL_IOCTL_ELEM_WRITE, (ULONG)pElem);
     531
     532    if(idxMute != -1 && volume == 0) {
     533      //enable mute
     534      pElem->id.numid = pHandle->pids[idxMute].numid;
     535      pElem->indirect = 0;
     536
     537      pElem->value.integer.value[0] = FALSE;  //switch, not mute control (inversed)
     538      pElem->value.integer.value[1] = FALSE;
     539      dprintf(("OSS32_MixSetVolume Ioctl mute"));
     540      ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_CTL_IOCTL_ELEM_WRITE, (ULONG)pElem);
     541    }
     542  }
    536543#endif
    537544
    538         kfree(pElem);
    539         pElem = NULL;
    540         if(ret) {
    541                 rprintf(("OSS32_MixSetVolume ret=%x", ret));
    542                 DebugInt3();
    543                 return UNIXToOSSError(ret);
    544         }
    545         return OSSERR_SUCCESS;
     545  kfree(pElem);
     546  pElem = NULL;
     547  if(ret) {
     548    rprintf(("OSS32_MixSetVolume ret=%x", ret));
     549    DebugInt3();
     550    return UNIXToOSSError(ret);
     551  }
     552  return OSSERR_SUCCESS;
    546553
    547554fail:
    548         if(pElem) kfree(pElem);
    549         return ret;
     555  if(pElem) kfree(pElem);
     556  return ret;
    550557}
    551558//******************************************************************************
     
    553560OSSRET OSS32_MixSetProperty(OSSSTREAMID streamid, ULONG ulLine, ULONG ulValue)
    554561{
    555         mixerhandle              *pHandle = (mixerhandle *)streamid;
    556         struct snd_ctl_elem_value *pElem = NULL;
    557         struct snd_ctl_elem_info  *pElemInfo;
    558         int                               ret, idx = -1, lVol, rVol = 0, j, i;
    559 
    560         if(pHandle == NULL || pHandle->magic != MAGIC_MIXER_ALSA32) {
    561                 DebugInt3();
    562                 return OSSERR_INVALID_STREAMID;
    563         }
    564         //set operation to non-blocking
    565         pHandle->file.f_flags = O_NONBLOCK;
    566 
    567         //too big to put on the stack
    568         pElem = (struct snd_ctl_elem_value *)kmalloc(sizeof(struct snd_ctl_elem_value) + sizeof(struct snd_ctl_elem_info), GFP_KERNEL);
    569         if(pElem == NULL) {
    570                 DebugInt3();
    571                 return OSSERR_OUT_OF_MEMORY;
    572         }
    573         pElemInfo = (struct snd_ctl_elem_info *)(pElem+1);
    574 
    575         switch(ulLine) {
    576         case OSS32_MIX_INPUTSRC:
    577                 idx = pHandle->controls[OSS_MIXER_IGAIN].idxCustom;
    578                 //is this capture source supported by the hardware??
    579                 if(!(pHandle->reccaps & OSS32_MIX_FLAG(ulValue))) {
    580                         DebugInt3();
    581                         ret = OSSERR_INVALID_PARAMETER;
    582                         goto fail;
    583                 }
    584                 if(pHandle->rectype == RECTYPE_SELECTOR) {//input source selector
    585                         //set left and right capture source
    586                         pElem->value.enumerated.item[0] = pHandle->idxRecCaps[ulValue];
    587                         pElem->value.enumerated.item[1] = pHandle->idxRecCaps[ulValue];
    588                 }
    589                 else {//capture switch for each input source
    590                         //first turn off all capture switches...
    591                         for(j=0;j<OSS32_MIX_RECSRC_MAX;j++)
    592                         {
    593                                 if(pHandle->idxRecCaps[j] != -1) {
    594                                         idx                                               = pHandle->idxRecCaps[j];
    595 
    596                                         //request information about mixer control
    597                                         pElemInfo->id.numid               = pHandle->pids[idx].numid;
    598                                         ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_CTL_IOCTL_ELEM_INFO, (ULONG)pElemInfo);
    599                                         if(ret) {
    600                                                 ret = UNIXToOSSError(ret);
    601                                                 DebugInt3();
    602                                                 goto fail;
    603                                         }
    604                                         if(pElemInfo->type != SNDRV_CTL_ELEM_TYPE_BOOLEAN) {
    605                                                 ret = OSSERR_INVALID_PARAMETER;
    606                                                 DebugInt3();
    607                                                 goto fail;
    608                                         }
    609 
    610                                         pElem->id.numid                           = pHandle->pids[idx].numid;
    611                                         pElem->indirect                           = 0;
    612                                         for(i=0;i<pElemInfo->count;i++) {
    613                                                 pElem->value.integer.value[i] = 0;
    614                                         }
    615 
    616                                         ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_CTL_IOCTL_ELEM_WRITE, (ULONG)pElem);
    617                                         if(ret) {
    618                                                 ret = UNIXToOSSError(ret);
    619                                                 DebugInt3();
    620                                                 goto fail;
    621                                         }
    622                                 }
    623                         }
    624                         //request information about mixer control
    625                         pElemInfo->id.numid = pHandle->pids[idx].numid;
    626                         ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_CTL_IOCTL_ELEM_INFO, (ULONG)pElemInfo);
    627                         if(ret) {
    628                                 ret = UNIXToOSSError(ret);
    629                                 DebugInt3();
    630                                 goto fail;
    631                         }
    632 
    633                         //and enable the capture switch for the selected input source
    634                         idx = pHandle->idxRecCaps[ulValue];
    635                         for(i=0;i<pElemInfo->count;i++) {
    636                                 pElem->value.integer.value[i] = 1;
    637                         }
    638                 }
    639 
    640                 break;
    641 
    642         case OSS32_MIX_SWITCH_MICBOOST:
    643                 idx = pHandle->controls[OSS_MIXER_MIC].idxCustom;
    644                 if(idx == -1) {
    645                         DebugInt3();
    646                         ret = OSSERR_INVALID_PARAMETER;
    647                         goto fail;
    648                 }
    649                 //set mic switch value (on/off)
    650                 pElem->value.integer.value[0] = ulValue;
    651                 break;
    652 
    653         case OSS32_MIX_LEVEL_BASS:
    654                 idx = pHandle->controls[OSS_MIXER_BASS].idxVolume;
    655                 goto levelcontinue;
    656         case OSS32_MIX_LEVEL_TREBLE:
    657                 idx = pHandle->controls[OSS_MIXER_TREBLE].idxVolume;
    658                 goto levelcontinue;
    659         case OSS32_MIX_LEVEL_3DCENTER:
    660                 idx = pHandle->controls[OSS_MIXER_3DCENTER].idxVolume;
    661                 goto levelcontinue;
    662         case OSS32_MIX_LEVEL_3DDEPTH:
    663                 idx = pHandle->controls[OSS_MIXER_3DDEPTH].idxVolume;
     562  mixerhandle      *pHandle = (mixerhandle *)streamid;
     563  struct snd_ctl_elem_value *pElem = NULL;
     564  struct snd_ctl_elem_info  *pElemInfo;
     565  int           ret, idx = -1, lVol, rVol = 0, j, i;
     566
     567  if(pHandle == NULL || pHandle->magic != MAGIC_MIXER_ALSA32) {
     568    DebugInt3();
     569    return OSSERR_INVALID_STREAMID;
     570  }
     571  //set operation to non-blocking
     572  pHandle->file.f_flags = O_NONBLOCK;
     573
     574  //too big to put on the stack
     575  pElem = (struct snd_ctl_elem_value *)kmalloc(sizeof(struct snd_ctl_elem_value) + sizeof(struct snd_ctl_elem_info), GFP_KERNEL);
     576  if(pElem == NULL) {
     577    DebugInt3();
     578    return OSSERR_OUT_OF_MEMORY;
     579  }
     580  pElemInfo = (struct snd_ctl_elem_info *)(pElem+1);
     581
     582  switch(ulLine) {
     583  case OSS32_MIX_INPUTSRC:
     584    idx = pHandle->controls[OSS_MIXER_IGAIN].idxCustom;
     585    //is this capture source supported by the hardware??
     586    if(!(pHandle->reccaps & OSS32_MIX_FLAG(ulValue))) {
     587      DebugInt3();
     588      ret = OSSERR_INVALID_PARAMETER;
     589      goto fail;
     590    }
     591    if(pHandle->rectype == RECTYPE_SELECTOR) {//input source selector
     592      //set left and right capture source
     593      pElem->value.enumerated.item[0] = pHandle->idxRecCaps[ulValue];
     594      pElem->value.enumerated.item[1] = pHandle->idxRecCaps[ulValue];
     595    }
     596    else {//capture switch for each input source
     597      //first turn off all capture switches...
     598      for(j=0;j<OSS32_MIX_RECSRC_MAX;j++)
     599      {
     600        if(pHandle->idxRecCaps[j] != -1) {
     601          idx               = pHandle->idxRecCaps[j];
     602
     603          //request information about mixer control
     604          pElemInfo->id.numid       = pHandle->pids[idx].numid;
     605          ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_CTL_IOCTL_ELEM_INFO, (ULONG)pElemInfo);
     606          if(ret) {
     607            ret = UNIXToOSSError(ret);
     608            DebugInt3();
     609            goto fail;
     610          }
     611          if(pElemInfo->type != SNDRV_CTL_ELEM_TYPE_BOOLEAN) {
     612            ret = OSSERR_INVALID_PARAMETER;
     613            DebugInt3();
     614            goto fail;
     615          }
     616
     617          pElem->id.numid         = pHandle->pids[idx].numid;
     618          pElem->indirect         = 0;
     619          for(i=0;i<pElemInfo->count;i++) {
     620            pElem->value.integer.value[i] = 0;
     621          }
     622
     623          ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_CTL_IOCTL_ELEM_WRITE, (ULONG)pElem);
     624          if(ret) {
     625            ret = UNIXToOSSError(ret);
     626            DebugInt3();
     627            goto fail;
     628          }
     629        }
     630      }
     631      //request information about mixer control
     632      pElemInfo->id.numid = pHandle->pids[idx].numid;
     633      ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_CTL_IOCTL_ELEM_INFO, (ULONG)pElemInfo);
     634      if(ret) {
     635        ret = UNIXToOSSError(ret);
     636        DebugInt3();
     637        goto fail;
     638      }
     639
     640      //and enable the capture switch for the selected input source
     641      idx = pHandle->idxRecCaps[ulValue];
     642      for(i=0;i<pElemInfo->count;i++) {
     643        pElem->value.integer.value[i] = 1;
     644      }
     645    }
     646
     647    break;
     648
     649  case OSS32_MIX_SWITCH_MICBOOST:
     650    idx = pHandle->controls[OSS_MIXER_MIC].idxCustom;
     651    if(idx == -1) {
     652      DebugInt3();
     653      ret = OSSERR_INVALID_PARAMETER;
     654      goto fail;
     655    }
     656    //set mic switch value (on/off)
     657    pElem->value.integer.value[0] = ulValue;
     658    break;
     659
     660  case OSS32_MIX_LEVEL_BASS:
     661    idx = pHandle->controls[OSS_MIXER_BASS].idxVolume;
     662    goto levelcontinue;
     663  case OSS32_MIX_LEVEL_TREBLE:
     664    idx = pHandle->controls[OSS_MIXER_TREBLE].idxVolume;
     665    goto levelcontinue;
     666  case OSS32_MIX_LEVEL_3DCENTER:
     667    idx = pHandle->controls[OSS_MIXER_3DCENTER].idxVolume;
     668    goto levelcontinue;
     669  case OSS32_MIX_LEVEL_3DDEPTH:
     670    idx = pHandle->controls[OSS_MIXER_3DDEPTH].idxVolume;
    664671levelcontinue:
    665672
    666                 if(idx == -1) {//supported?
    667                         DebugInt3();
    668                         ret = OSSERR_INVALID_PARAMETER;
    669                         goto fail;
    670                 }
    671                 //request information about mixer control
    672                 pElemInfo->id.numid = pHandle->pids[idx].numid;
    673                 ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_CTL_IOCTL_ELEM_INFO, (ULONG)pElemInfo);
    674                 if(ret) {
    675                         ret = UNIXToOSSError(ret);
    676                         DebugInt3();
    677                         goto fail;
    678                 }
    679                 if(pElemInfo->type != SNDRV_CTL_ELEM_TYPE_INTEGER) {
    680                         ret = OSSERR_INVALID_PARAMETER;
    681                         DebugInt3();
    682                         goto fail;
    683                 }
    684                 lVol = ConvertVolume(GET_VOLUME_L(ulValue), pElemInfo->value.integer.max);
    685                 pElem->value.integer.value[0] = lVol;
    686 
    687                 if(pElemInfo->count > 1) { //stereo
    688                         rVol = ConvertVolume(GET_VOLUME_R(ulValue), pElemInfo->value.integer.max);
    689                         pElem->value.integer.value[1] = rVol;
    690                 }
    691                 break;
    692 
    693         default:
    694                 DebugInt3();
    695                 ret = OSSERR_INVALID_PARAMETER;
    696                 goto fail;
    697         }
    698         pElem->id.numid = pHandle->pids[idx].numid;
    699         pElem->indirect = 0;
    700 
    701         dprintf(("OSS32_MixSetProperty of %s to %x", pHandle->pids[idx].name, ulValue));
    702         ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_CTL_IOCTL_ELEM_WRITE, (ULONG)pElem);
    703 
    704         kfree(pElem);
    705         pElem = NULL;
    706         if(ret) {
    707                 DebugInt3();
    708                 return UNIXToOSSError(ret);
    709         }
    710         return OSSERR_SUCCESS;
     673    if(idx == -1) {//supported?
     674      DebugInt3();
     675      ret = OSSERR_INVALID_PARAMETER;
     676      goto fail;
     677    }
     678    //request information about mixer control
     679    pElemInfo->id.numid = pHandle->pids[idx].numid;
     680    ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_CTL_IOCTL_ELEM_INFO, (ULONG)pElemInfo);
     681    if(ret) {
     682      ret = UNIXToOSSError(ret);
     683      DebugInt3();
     684      goto fail;
     685    }
     686    if(pElemInfo->type != SNDRV_CTL_ELEM_TYPE_INTEGER) {
     687      ret = OSSERR_INVALID_PARAMETER;
     688      DebugInt3();
     689      goto fail;
     690    }
     691    lVol = ConvertVolume(GET_VOLUME_L(ulValue), pElemInfo->value.integer.max);
     692    pElem->value.integer.value[0] = lVol;
     693
     694    if(pElemInfo->count > 1) { //stereo
     695      rVol = ConvertVolume(GET_VOLUME_R(ulValue), pElemInfo->value.integer.max);
     696      pElem->value.integer.value[1] = rVol;
     697    }
     698    break;
     699
     700  default:
     701    DebugInt3();
     702    ret = OSSERR_INVALID_PARAMETER;
     703    goto fail;
     704  }
     705  pElem->id.numid = pHandle->pids[idx].numid;
     706  pElem->indirect = 0;
     707
     708  dprintf(("OSS32_MixSetProperty of %s to %x", pHandle->pids[idx].name, ulValue));
     709  ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file, SNDRV_CTL_IOCTL_ELEM_WRITE, (ULONG)pElem);
     710
     711  kfree(pElem);
     712  pElem = NULL;
     713  if(ret) {
     714    DebugInt3();
     715    return UNIXToOSSError(ret);
     716  }
     717  return OSSERR_SUCCESS;
    711718
    712719fail:
    713         if(pElem) kfree(pElem);
    714         return ret;
     720  if(pElem) kfree(pElem);
     721  return ret;
    715722}
    716723//******************************************************************************
     
    718725OSSRET OSS32_MixGetProperty(OSSSTREAMID streamid, ULONG line, ULONG *pValue)
    719726{
    720         mixerhandle *pHandle = (mixerhandle *)streamid;
    721         //int            ret;
    722 
    723         if(pHandle == NULL || pHandle->magic != MAGIC_MIXER_ALSA32) {
    724                 DebugInt3();
    725                 return OSSERR_INVALID_STREAMID;
    726         }
    727         //set operation to non-blocking
    728         pHandle->file.f_flags = O_NONBLOCK;
    729 
    730         return OSSERR_NOT_SUPPORTED;
     727  mixerhandle *pHandle = (mixerhandle *)streamid;
     728  //int      ret;
     729
     730  if(pHandle == NULL || pHandle->magic != MAGIC_MIXER_ALSA32) {
     731    DebugInt3();
     732    return OSSERR_INVALID_STREAMID;
     733  }
     734  //set operation to non-blocking
     735  pHandle->file.f_flags = O_NONBLOCK;
     736
     737  return OSSERR_NOT_SUPPORTED;
    731738}
    732739//******************************************************************************
     
    734741ULONG OSSToALSAVolume(ULONG OSSVolIdx)
    735742{
    736         switch(OSSVolIdx) {
    737         case OSS_MIXER_VOLUME:
    738                 return OSS32_MIX_VOLUME_MASTER_FRONT;
     743  switch(OSSVolIdx) {
     744  case OSS_MIXER_VOLUME:
     745    return OSS32_MIX_VOLUME_MASTER_FRONT;
    739746#if 0
    740         case OSS_MIXER_VOLUME: //TODO:
    741                 return OSS32_MIX_VOLUME_MASTER_REAR;
     747  case OSS_MIXER_VOLUME: //TODO:
     748    return OSS32_MIX_VOLUME_MASTER_REAR;
    742749#endif
    743         case OSS_MIXER_PCM:
    744                 return OSS32_MIX_VOLUME_PCM;
    745         case OSS_MIXER_SYNTH:
    746                 return OSS32_MIX_VOLUME_MIDI;
    747         case OSS_MIXER_LINE:
    748                 return OSS32_MIX_VOLUME_LINEIN;
    749         case OSS_MIXER_MIC:
    750                 return OSS32_MIX_VOLUME_MIC;
    751         case OSS_MIXER_CD:
    752                 return OSS32_MIX_VOLUME_CD;
    753         case OSS_MIXER_DIGITAL1:
    754                 return OSS32_MIX_VOLUME_SPDIF;
    755         case OSS_MIXER_VIDEO:
    756                 return OSS32_MIX_VOLUME_VIDEO;
    757         case OSS_MIXER_PCSPEAKER:
    758                 return OSS32_MIX_VOLUME_PCSPEAKER;
    759         case OSS_MIXER_PHONEOUT:
    760                 return OSS32_MIX_VOLUME_PHONE;
    761         case OSS_MIXER_IGAIN:
    762                 return OSS32_MIX_VOLUME_CAPTURE;
    763         case OSS_MIXER_TREBLE:
    764                 return OSS32_MIX_LEVEL_TREBLE;
    765         case OSS_MIXER_BASS:
    766                 return OSS32_MIX_LEVEL_BASS;
    767         case OSS_MIXER_HEADPHONE:
    768                 return OSS32_MIX_VOLUME_HEADPHONE;
    769         case OSS_MIXER_SPEAKER:
    770                 return OSS32_MIX_VOLUME_SPEAKER;
    771         case OSS_MIXER_LINE1:
    772                 return OSS32_MIX_VOLUME_AUX;
    773         }
    774         return -1;
     750  case OSS_MIXER_PCM:
     751    return OSS32_MIX_VOLUME_PCM;
     752  case OSS_MIXER_SYNTH:
     753    return OSS32_MIX_VOLUME_MIDI;
     754  case OSS_MIXER_LINE:
     755    return OSS32_MIX_VOLUME_LINEIN;
     756  case OSS_MIXER_MIC:
     757    return OSS32_MIX_VOLUME_MIC;
     758  case OSS_MIXER_CD:
     759    return OSS32_MIX_VOLUME_CD;
     760  case OSS_MIXER_DIGITAL1:
     761    return OSS32_MIX_VOLUME_SPDIF;
     762  case OSS_MIXER_VIDEO:
     763    return OSS32_MIX_VOLUME_VIDEO;
     764  case OSS_MIXER_PCSPEAKER:
     765    return OSS32_MIX_VOLUME_PCSPEAKER;
     766  case OSS_MIXER_PHONEOUT:
     767    return OSS32_MIX_VOLUME_PHONE;
     768  case OSS_MIXER_IGAIN:
     769    return OSS32_MIX_VOLUME_CAPTURE;
     770  case OSS_MIXER_TREBLE:
     771    return OSS32_MIX_LEVEL_TREBLE;
     772  case OSS_MIXER_BASS:
     773    return OSS32_MIX_LEVEL_BASS;
     774  case OSS_MIXER_HEADPHONE:
     775    return OSS32_MIX_VOLUME_HEADPHONE;
     776  case OSS_MIXER_SPEAKER:
     777    return OSS32_MIX_VOLUME_SPEAKER;
     778  case OSS_MIXER_LINE1:
     779    return OSS32_MIX_VOLUME_AUX;
     780  }
     781  return -1;
    775782}
    776783//******************************************************************************
     
    778785OSSRET OSS32_MixQueryCaps(OSSSTREAMID streamid, POSS32_MIXCAPS pCaps)
    779786{
    780         mixerhandle *pHandle = (mixerhandle *)streamid;
    781         int i;
    782 
    783         if(pHandle == NULL || pHandle->magic != MAGIC_MIXER_ALSA32) {
    784                 DebugInt3();
    785                 return OSSERR_INVALID_STREAMID;
    786         }
    787 
    788         strncpy(pCaps->name, pHandle->info.mixername, sizeof(pCaps->name));
    789         pCaps->fuCtrlCaps = 0;
    790         pCaps->fuRecCaps  = 0;
    791 
    792         for(i=0;i<OSS_MIXER_NRDEVICES;i++)
    793         {
    794                 if(pHandle->controls[i].idxVolume != -1) {
    795                         ULONG volidx = OSSToALSAVolume(i);
    796                         if(volidx != -1)
    797                                 pCaps->fuCtrlCaps |= OSS32_MIX_FLAG(volidx);
    798                 }
    799         }
    800 
    801         //if it has a capture source control or the card has capture route switches,
    802         //then we support intput source selection
    803         if(pHandle->controls[OSS_MIXER_IGAIN].idxCustom != -1 ||
    804            pHandle->rectype == RECTYPE_SWITCH)
    805         {
    806                 pCaps->fuCtrlCaps |= OSS32_MIX_FLAG(OSS32_MIX_INPUTSRC);
    807                 pCaps->fuRecCaps   = pHandle->reccaps;
    808         }
    809         return OSSERR_SUCCESS;
     787  mixerhandle *pHandle = (mixerhandle *)streamid;
     788  int i;
     789
     790  if(pHandle == NULL || pHandle->magic != MAGIC_MIXER_ALSA32) {
     791    DebugInt3();
     792    return OSSERR_INVALID_STREAMID;
     793  }
     794
     795  strncpy(pCaps->name, pHandle->info.mixername, sizeof(pCaps->name));
     796  pCaps->fuCtrlCaps = 0;
     797  pCaps->fuRecCaps  = 0;
     798
     799  for(i=0;i<OSS_MIXER_NRDEVICES;i++)
     800  {
     801    if(pHandle->controls[i].idxVolume != -1) {
     802      ULONG volidx = OSSToALSAVolume(i);
     803      if(volidx != -1)
     804        pCaps->fuCtrlCaps |= OSS32_MIX_FLAG(volidx);
     805    }
     806  }
     807
     808  //if it has a capture source control or the card has capture route switches,
     809  //then we support intput source selection
     810  if(pHandle->controls[OSS_MIXER_IGAIN].idxCustom != -1 ||
     811     pHandle->rectype == RECTYPE_SWITCH)
     812  {
     813    pCaps->fuCtrlCaps |= OSS32_MIX_FLAG(OSS32_MIX_INPUTSRC);
     814    pCaps->fuRecCaps   = pHandle->reccaps;
     815  }
     816  return OSSERR_SUCCESS;
    810817}
    811818//******************************************************************************
     
    813820OSSRET OSS32_MixQueryName(ULONG deviceid, char *pszMixerName, ULONG cbMixerName)
    814821{
    815         mixerhandle *pHandle = NULL;
    816         int              ret;
    817         //int i, j;
    818 
    819         if(alsa_fops == NULL)
    820                 return OSSERR_NO_DEVICE_AVAILABLE;
    821 
    822         pHandle = kmalloc(sizeof(mixerhandle), GFP_KERNEL);
    823         if(pHandle == NULL) {
    824                 ret = OSSERR_OUT_OF_MEMORY;
    825                 goto failure;
    826         }
    827         memset(pHandle, 0, sizeof(mixerhandle));
    828 
    829         //set operation to non-blocking
    830         pHandle->file.f_flags = O_NONBLOCK;
    831 
    832         //setup pointers in file structure (used internally by ALSA)
    833         pHandle->file.f_dentry                  = &pHandle->d_entry;
    834         pHandle->file.f_dentry->d_inode = &pHandle->inode;
    835 
    836         pHandle->file.f_mode  = FMODE_WRITE;
    837         pHandle->inode.i_rdev = SNDRV_MINOR(deviceid, SNDRV_MINOR_CONTROL);
    838 
    839         ret = alsa_fops->open(&pHandle->inode, &pHandle->file);
    840         if(ret) {
    841                 goto failure;
    842         }
    843         //retrieve mixer information
    844         ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file,
    845                                                                         SNDRV_CTL_IOCTL_CARD_INFO,
    846                                                                         (ULONG)&pHandle->info);
    847         if(ret) {
    848                 goto failure;
    849         }
    850 
    851         strncpy(pszMixerName, pHandle->info.mixername, cbMixerName);
    852 
    853         pHandle->file.f_flags = O_NONBLOCK;
    854         ret = pHandle->file.f_op->release(&pHandle->inode, &pHandle->file);
    855         if(ret) {
    856                 goto failure;
    857         }
    858         kfree(pHandle);
    859         return OSSERR_SUCCESS;
     822  mixerhandle *pHandle = NULL;
     823  int      ret;
     824  //int i, j;
     825
     826  if(alsa_fops == NULL)
     827    return OSSERR_NO_DEVICE_AVAILABLE;
     828
     829  pHandle = kmalloc(sizeof(mixerhandle), GFP_KERNEL);
     830  if(pHandle == NULL) {
     831    ret = OSSERR_OUT_OF_MEMORY;
     832    goto failure;
     833  }
     834  memset(pHandle, 0, sizeof(mixerhandle));
     835
     836  //set operation to non-blocking
     837  pHandle->file.f_flags = O_NONBLOCK;
     838
     839  //setup pointers in file structure (used internally by ALSA)
     840  pHandle->file.f_dentry      = &pHandle->d_entry;
     841  pHandle->file.f_dentry->d_inode = &pHandle->inode;
     842
     843  pHandle->file.f_mode  = FMODE_WRITE;
     844  pHandle->inode.i_rdev = SNDRV_MINOR(deviceid, SNDRV_MINOR_CONTROL);
     845
     846  ret = alsa_fops->open(&pHandle->inode, &pHandle->file);
     847  if(ret) {
     848    goto failure;
     849  }
     850  //retrieve mixer information
     851  ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file,
     852                  SNDRV_CTL_IOCTL_CARD_INFO,
     853                  (ULONG)&pHandle->info);
     854  if(ret) {
     855    goto failure;
     856  }
     857
     858  strncpy(pszMixerName, pHandle->info.mixername, cbMixerName);
     859
     860  pHandle->file.f_flags = O_NONBLOCK;
     861  ret = pHandle->file.f_op->release(&pHandle->inode, &pHandle->file);
     862  if(ret) {
     863    goto failure;
     864  }
     865  kfree(pHandle);
     866  return OSSERR_SUCCESS;
    860867
    861868failure:
    862         if(pHandle) {
    863                 kfree(pHandle);
    864         }
    865         DebugInt3();
    866         return OSSERR_OUT_OF_MEMORY;
     869  if(pHandle) {
     870    kfree(pHandle);
     871  }
     872  DebugInt3();
     873  return OSSERR_OUT_OF_MEMORY;
    867874}
    868875//******************************************************************************
    869876//******************************************************************************
    870877OSSRET OSS32_QueryNames(ULONG deviceid, char *pszDeviceName, ULONG cbDeviceName,
    871                                                 char *pszMixerName, ULONG cbMixerName, BOOL fLongName)
    872 {
    873         mixerhandle *pHandle = NULL;
    874         int              ret;
    875         //int i, j;
    876 
    877         if(alsa_fops == NULL) {
    878                 ret = OSSERR_NO_DEVICE_AVAILABLE;
    879                 printk("ret = OSSERR_NO_DEVICE_AVAILABLE\n");
    880                 goto failure;
    881         }
    882 
    883         pHandle = kmalloc(sizeof(mixerhandle), GFP_KERNEL);
    884         if(pHandle == NULL) {
    885                 ret = OSSERR_OUT_OF_MEMORY;
    886                 goto failure;
    887         }
    888         memset(pHandle, 0, sizeof(mixerhandle));
    889 
    890         //set operation to non-blocking
    891         pHandle->file.f_flags = O_NONBLOCK;
    892 
    893         //setup pointers in file structure (used internally by ALSA)
    894         pHandle->file.f_dentry                  = &pHandle->d_entry;
    895         pHandle->file.f_dentry->d_inode = &pHandle->inode;
    896 
    897         pHandle->file.f_mode  = FMODE_WRITE;
    898         pHandle->inode.i_rdev = SNDRV_MINOR(deviceid, SNDRV_MINOR_CONTROL);
    899 
    900         ret = alsa_fops->open(&pHandle->inode, &pHandle->file);
    901         if(ret) {
    902                 printk("open ret = %i\n", ret);
    903                 goto failure;
    904         }
    905         //retrieve mixer information
    906         ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file,
    907                                                                         SNDRV_CTL_IOCTL_CARD_INFO,
    908                                                                         (ULONG)&pHandle->info);
    909         if(ret) {
    910                 printk("ioctl ret = %i\n", ret);
    911                 goto failure;
    912         }
    913 
    914         if(pszDeviceName) {
    915                 if(fLongName == TRUE) {
    916                         strncpy(pszDeviceName, pHandle->info.longname, cbDeviceName);
    917                 }
    918                 else strncpy(pszDeviceName, pHandle->info.name, cbDeviceName);
    919         }
    920         if(pszMixerName) {
    921                 strncpy(pszMixerName, pHandle->info.mixername, cbMixerName);
    922         }
    923 
    924 //        printk("Card: %s with mixer %s\n",pszDeviceName, pszMixerName);
    925 
    926         pHandle->file.f_flags = O_NONBLOCK;
    927         ret = pHandle->file.f_op->release(&pHandle->inode, &pHandle->file);
    928         if(ret) {
    929                 printk("release ret = %i\n", ret);
    930                 goto failure;
    931         }
    932         kfree(pHandle);
    933         return OSSERR_SUCCESS;
     878            char *pszMixerName, ULONG cbMixerName, BOOL fLongName)
     879{
     880  mixerhandle *pHandle = NULL;
     881  int      ret;
     882  //int i, j;
     883
     884  if(alsa_fops == NULL) {
     885    ret = OSSERR_NO_DEVICE_AVAILABLE;
     886    printk("ret = OSSERR_NO_DEVICE_AVAILABLE\n");
     887    goto failure;
     888  }
     889
     890  pHandle = kmalloc(sizeof(mixerhandle), GFP_KERNEL);
     891  if(pHandle == NULL) {
     892    ret = OSSERR_OUT_OF_MEMORY;
     893    goto failure;
     894  }
     895  memset(pHandle, 0, sizeof(mixerhandle));
     896
     897  //set operation to non-blocking
     898  pHandle->file.f_flags = O_NONBLOCK;
     899
     900  //setup pointers in file structure (used internally by ALSA)
     901  pHandle->file.f_dentry      = &pHandle->d_entry;
     902  pHandle->file.f_dentry->d_inode = &pHandle->inode;
     903
     904  pHandle->file.f_mode  = FMODE_WRITE;
     905  pHandle->inode.i_rdev = SNDRV_MINOR(deviceid, SNDRV_MINOR_CONTROL);
     906
     907  ret = alsa_fops->open(&pHandle->inode, &pHandle->file);
     908  if(ret) {
     909    printk("open ret = %i\n", ret);
     910    goto failure;
     911  }
     912  //retrieve mixer information
     913  ret = pHandle->file.f_op->ioctl(&pHandle->inode, &pHandle->file,
     914                  SNDRV_CTL_IOCTL_CARD_INFO,
     915                  (ULONG)&pHandle->info);
     916  if(ret) {
     917    printk("ioctl ret = %i\n", ret);
     918    goto failure;
     919  }
     920
     921  if(pszDeviceName) {
     922    if(fLongName == TRUE) {
     923      strncpy(pszDeviceName, pHandle->info.longname, cbDeviceName);
     924    }
     925    else strncpy(pszDeviceName, pHandle->info.name, cbDeviceName);
     926  }
     927  if(pszMixerName) {
     928    strncpy(pszMixerName, pHandle->info.mixername, cbMixerName);
     929  }
     930
     931//    printk("Card: %s with mixer %s\n",pszDeviceName, pszMixerName);
     932
     933  pHandle->file.f_flags = O_NONBLOCK;
     934  ret = pHandle->file.f_op->release(&pHandle->inode, &pHandle->file);
     935  if(ret) {
     936    printk("release ret = %i\n", ret);
     937    goto failure;
     938  }
     939  kfree(pHandle);
     940  return OSSERR_SUCCESS;
    934941
    935942failure:
    936         if(pHandle) {
    937                 kfree(pHandle);
    938         }
    939         DebugInt3();
    940         printk("OSS32_QueryNames() ret = %i\n", ret);
    941         return OSSERR_OUT_OF_MEMORY;
    942 }
    943 //******************************************************************************
    944 //******************************************************************************
    945 
     943  if(pHandle) {
     944    kfree(pHandle);
     945  }
     946  DebugInt3();
     947  printk("OSS32_QueryNames() ret = %i\n", ret);
     948  return OSSERR_OUT_OF_MEMORY;
     949}
     950//******************************************************************************
     951//******************************************************************************
     952
Note: See TracChangeset for help on using the changeset viewer.