Changeset 604 for GPL/trunk/lib32


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

Incorporated changes from Andy.
Added limited MSI support.

Location:
GPL/trunk/lib32
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • GPL/trunk/lib32/Makefile

    r598 r604  
    1010!if "$(IBM_BUILD)" == "1"
    1111CDEFINES += -DIBM_BUILD
     12!endif
     13
     14!ifdef %DRV32KIT
     15CDEFINES+= -DUSE_MSI
    1216!endif
    1317
  • GPL/trunk/lib32/irq.c

    r577 r604  
    4242//******************************************************************************
    4343
    44 static IRQ_SLOT         arSlots[MAX_IRQ_SLOTS] = { 0 };
    45 static ULONG               eoiIrq[255] = {0};
     44static IRQ_SLOT   arSlots[MAX_IRQ_SLOTS] = { 0 };
     45static ULONG       eoiIrq[255] = {0};
    4646
    4747
     
    5050static IRQ_SLOT *FindSlot(unsigned irq)
    5151{
    52         IRQ_SLOT          *pSlot;
    53 
    54         for( pSlot = arSlots; pSlot != &arSlots[MAX_IRQ_SLOTS]; pSlot++ )
    55         {
    56                 if( pSlot->irqNo == irq )       return pSlot;
    57         }
    58 
    59         return NULL;
     52  IRQ_SLOT    *pSlot;
     53
     54  for( pSlot = arSlots; pSlot != &arSlots[MAX_IRQ_SLOTS]; pSlot++ )
     55  {
     56    if( pSlot->irqNo == irq ) return pSlot;
     57  }
     58
     59  return NULL;
    6060}
    6161
     
    6565
    6666int request_irq(unsigned irq, irq_handler_t handler,
    67                         unsigned long ulSharedFlag, const char *pchName, void *pUserData)
    68 {
    69         IRQ_SLOT        *pSlot = FindSlot(irq & 0xff);
    70         unsigned        u, uSlotNo = (unsigned)-1;
    71         ULONG hRes;
    72 
    73         rprintf(("request_irq: irq %d", irq & 0xff ));
    74         if ( !pSlot ) {
    75                 // find empty slot
    76                 for( uSlotNo = 0; uSlotNo < MAX_IRQ_SLOTS; uSlotNo++ ) {
    77                         if( arSlots[uSlotNo].flHandlers == 0 ) {
    78                                 pSlot = &arSlots[uSlotNo];
    79                                 break;
    80                         }
    81                 }
    82         }
    83 
    84         if ( pSlot ) {
    85                 hRes = 0;
    86                 if (RMRequestIRQ(irq, (ulSharedFlag & SA_SHIRQ) != 0, &hRes) == FALSE) {
    87                         rprintf(("RMRequestIRQ failed for irq %d", irq));
    88                         return 1;
    89                 }
    90                 pSlot->irqNo = irq & 0xff;
    91                 pSlot->hRes = hRes;
    92 
    93                 for ( u = 0; u < MAX_SHAREDIRQS; u++ ) {
    94                         if ( pSlot->irqHandlers[u].handler == NULL ) {
    95                                 pSlot->irqHandlers[u].handler = handler;
    96                                 pSlot->irqHandlers[u].x0 = ulSharedFlag;
    97                                 pSlot->irqHandlers[u].x1 = (char *)pchName;
    98                                 pSlot->irqHandlers[u].x2 = pUserData;
    99 
    100                                 if( pSlot->flHandlers != 0 || ALSA_SetIrq( irq & 0xff, uSlotNo, (ulSharedFlag & SA_SHIRQ) != 0) ) {
    101                                         pSlot->flHandlers |= 1 << u;
    102                                         return 0;
    103                                 }
    104 
    105                                 break;
    106                         }
    107                 }
    108         }
    109 
    110         rprintf(("request_irq: Unable to register irq handler for irq %d", irq & 0xff ));
    111         return 1;
     67      unsigned long ulSharedFlag, const char *pchName, void *pUserData)
     68{
     69  IRQ_SLOT  *pSlot = FindSlot(irq & 0xff);
     70  unsigned  u, uSlotNo = (unsigned)-1;
     71  ULONG hRes;
     72
     73  rprintf(("request_irq: irq %d", irq & 0xff ));
     74  if ( !pSlot )
     75  {
     76    // find empty slot
     77    for( uSlotNo = 0; uSlotNo < MAX_IRQ_SLOTS; uSlotNo++ )
     78    {
     79      if( arSlots[uSlotNo].flHandlers == 0 )
     80      {
     81        pSlot = &arSlots[uSlotNo];
     82        break;
     83      }
     84    }
     85  }
     86
     87  if ( pSlot )
     88  {
     89    hRes = 0;
     90    if (RMRequestIRQ(irq, (ulSharedFlag & SA_SHIRQ) != 0, &hRes) == FALSE)
     91    {
     92      rprintf(("RMRequestIRQ failed for irq %d", irq));
     93      return 1;
     94    }
     95    pSlot->irqNo = irq & 0xff;
     96    pSlot->hRes = hRes;
     97
     98    for ( u = 0; u < MAX_SHAREDIRQS; u++ )
     99    {
     100      if ( pSlot->irqHandlers[u].handler == NULL )
     101      {
     102        pSlot->irqHandlers[u].handler = handler;
     103        pSlot->irqHandlers[u].x0 = ulSharedFlag;
     104        pSlot->irqHandlers[u].x1 = (char *)pchName;
     105        pSlot->irqHandlers[u].x2 = pUserData;
     106
     107        if( pSlot->flHandlers != 0 || ALSA_SetIrq( irq & 0xff, uSlotNo, (ulSharedFlag & SA_SHIRQ) != 0) )
     108        {
     109          pSlot->flHandlers |= 1 << u;
     110          return 0;
     111        }
     112
     113        break;
     114      }
     115    }
     116  }
     117
     118  rprintf(("request_irq: Unable to register irq handler for irq %d", irq & 0xff ));
     119  return 1;
    112120}
    113121
     
    117125void free_irq(unsigned int irq, void *userdata)
    118126{
    119         unsigned        u;
    120         IRQ_SLOT        *pSlot;
    121 
    122         if( (pSlot = FindSlot(irq&0xff)) != NULL ) {
    123                 for( u = 0; u < MAX_SHAREDIRQS; u++ ) {
    124                         if( pSlot->irqHandlers[u].x2 == userdata ) {
    125                                 pSlot->flHandlers &= ~(1 << u);
    126                                 if( pSlot->flHandlers == 0 ) {
    127                                         rprintf(("free_irq: irq %d", irq & 0xff ));
    128                                         ALSA_FreeIrq(pSlot->irqNo);
    129                                         pSlot->irqNo = 0;
    130                                         RMDeallocateIRQ(pSlot->hRes);
    131                                         pSlot->hRes = 0;
    132                                         // pSlot->fEOI = 0;
    133                                 }
    134 
    135                                 pSlot->irqHandlers[u].handler = NULL;
    136                                 pSlot->irqHandlers[u].x0 = 0;
    137                                 pSlot->irqHandlers[u].x1 = NULL;
    138                                 pSlot->irqHandlers[u].x2 = NULL;
    139 
    140                                 return;
    141 
    142                         }
    143                 }
    144         }
     127  unsigned  u;
     128  IRQ_SLOT  *pSlot;
     129
     130  if( (pSlot = FindSlot(irq&0xff)) != NULL ) {
     131    for( u = 0; u < MAX_SHAREDIRQS; u++ ) {
     132      if( pSlot->irqHandlers[u].x2 == userdata ) {
     133        pSlot->flHandlers &= ~(1 << u);
     134        if( pSlot->flHandlers == 0 ) {
     135          rprintf(("free_irq: irq %d", irq & 0xff ));
     136          ALSA_FreeIrq(pSlot->irqNo);
     137          pSlot->irqNo = 0;
     138          RMDeallocateIRQ(pSlot->hRes);
     139          pSlot->hRes = 0;
     140          // pSlot->fEOI = 0;
     141        }
     142
     143        pSlot->irqHandlers[u].handler = NULL;
     144        pSlot->irqHandlers[u].x0 = 0;
     145        pSlot->irqHandlers[u].x1 = NULL;
     146        pSlot->irqHandlers[u].x2 = NULL;
     147
     148        return;
     149
     150      }
     151    }
     152  }
    145153}
    146154
     
    150158void eoi_irq(unsigned int irq)
    151159{
    152         /*(void)irq; */
    153         /*
    154          IRQ_SLOT       *pSlot = FindSlot(irq);
    155 
    156          if( pSlot )    pSlot->fEOI = 1;
    157         */
    158         eoiIrq[irq & 0xff]++;
     160  /*(void)irq; */
     161  /*
     162   IRQ_SLOT *pSlot = FindSlot(irq);
     163
     164   if( pSlot )  pSlot->fEOI = 1;
     165  */
     166  eoiIrq[irq & 0xff]++;
    159167}
    160168
     
    164172BOOL process_interrupt(ULONG ulSlotNo, ULONG *pulIrq)
    165173{
    166         unsigned        u;
    167         int rc;
    168         IRQ_SLOT        *pSlot;
    169 
    170         //dprintf(("enter int proc %d %d",ulSlotNo, *pulIrq));
    171 
    172         if( ulSlotNo < MAX_IRQ_SLOTS )
    173         {
    174                 pSlot = &arSlots[ulSlotNo];
    175 
    176                 for( u = 0; u < MAX_SHAREDIRQS; u++ )
    177                 {
    178                         if(pSlot && pSlot->irqHandlers[u].handler )
    179                         {
    180                                 fInInterrupt = TRUE;
     174  unsigned  u;
     175  int rc;
     176  IRQ_SLOT  *pSlot;
     177
     178  //dprintf(("enter int proc %d %d",ulSlotNo, *pulIrq));
     179
     180  if( ulSlotNo < MAX_IRQ_SLOTS )
     181  {
     182    pSlot = &arSlots[ulSlotNo];
     183
     184    for( u = 0; u < MAX_SHAREDIRQS; u++ )
     185    {
     186      if(pSlot && pSlot->irqHandlers[u].handler )
     187      {
     188        fInInterrupt = TRUE;
    181189#if 0
    182                                 rc = pSlot->irqHandlers[u].handler(pSlot->irqNo,
    183                                                                                                    pSlot->irqHandlers[u].x2, 0);
     190        rc = pSlot->irqHandlers[u].handler(pSlot->irqNo,
     191                           pSlot->irqHandlers[u].x2, 0);
    184192#else
    185                                 rc = pSlot->irqHandlers[u].handler(pSlot->irqNo,
    186                                                                                                    pSlot->irqHandlers[u].x2);
     193        rc = pSlot->irqHandlers[u].handler(pSlot->irqNo,
     194                           pSlot->irqHandlers[u].x2);
    187195#endif
    188196
    189                                 // HDA Hardware generates controller interrupts and stream interrupts
    190                                 // the uniaud16 driver only cares about stream interrupts.
    191                                 // azx_interrupt in alsa-kernel/pci/hda/hda_intel.c will return rc 2 if
    192                                 // the interrupt is from the  controller. There is no need to call uniaud16
    193                                 // for these interrupts
    194                                 if ( rc == 2 ) {
    195                                         fInInterrupt = FALSE;
    196                                         *pulIrq = pSlot->irqNo;
    197                                         eoiIrq[pSlot->irqNo] = 0;
    198                                         return TRUE;
    199                                 }
    200 
    201                                 if (rc == 1) eoi_irq(pSlot->irqNo);
    202                                 rc = (eoiIrq[pSlot->irqNo] > 0);
    203                                 fInInterrupt = FALSE;
    204 
    205                                 if( rc /*== 1 || pSlot->fEOI*/ ) {
    206 
    207                                         *pulIrq = pSlot->irqNo;
    208                                         //              pSlot->fEOI = 0;
    209 
    210                                         //ok, this interrupt was intended for us; notify the 16 bits MMPM/2 driver
    211                                         OSS32_ProcessIRQ();
    212                                         //dprintf(("exit(1) int proc %d %d",ulSlotNo, *pulIrq));
    213                                         eoiIrq[pSlot->irqNo] = 0;
    214                                         return TRUE;
    215                                 }
    216                         }
    217                 }
    218         }
    219         //dprintf(("exit(0) int proc %d %d",ulSlotNo, *pulIrq));
    220 
    221         return FALSE;
     197        // HDA Hardware generates controller interrupts and stream interrupts
     198        // the uniaud16 driver only cares about stream interrupts.
     199        // azx_interrupt in alsa-kernel/pci/hda/hda_intel.c will return rc 2 if
     200        // the interrupt is from the  controller. There is no need to call uniaud16
     201        // for these interrupts
     202        if ( rc == 2 ) {
     203          fInInterrupt = FALSE;
     204          *pulIrq = pSlot->irqNo;
     205          eoiIrq[pSlot->irqNo] = 0;
     206          return TRUE;
     207        }
     208
     209        if (rc == 1) eoi_irq(pSlot->irqNo);
     210        rc = (eoiIrq[pSlot->irqNo] > 0);
     211        fInInterrupt = FALSE;
     212
     213        if( rc /*== 1 || pSlot->fEOI*/ ) {
     214
     215          *pulIrq = pSlot->irqNo;
     216          //    pSlot->fEOI = 0;
     217
     218          //ok, this interrupt was intended for us; notify the 16 bits MMPM/2 driver
     219          OSS32_ProcessIRQ();
     220          //dprintf(("exit(1) int proc %d %d",ulSlotNo, *pulIrq));
     221          eoiIrq[pSlot->irqNo] = 0;
     222          return TRUE;
     223        }
     224      }
     225    }
     226  }
     227  //dprintf(("exit(0) int proc %d %d",ulSlotNo, *pulIrq));
     228
     229  return FALSE;
    222230}
    223231
     
    227235int in_interrupt()
    228236{
    229         return fInInterrupt;
     237  return fInInterrupt;
    230238}
    231239
     
    235243void disable_irq(int irq)
    236244{
    237         dprintf(("disable_irq %d NOT implemented", irq));
    238 }
    239 
    240 //******************************************************************************
    241 //******************************************************************************
    242 
     245  dprintf(("disable_irq %d NOT implemented", irq));
     246}
     247
     248//******************************************************************************
     249//******************************************************************************
     250
  • GPL/trunk/lib32/pci.c

    r602 r604  
    245245          pcidev->irq_resource[0].start = pcidev->irq_resource[0].end   = ulTmp1 & 0xffff;
    246246          pcidev->irq = (u8)ulTmp1; // This is the interrupt used for init time processing
     247          pcidev->irq_pin = ulTmp1>>8;
    247248        }
    248249
     
    10151016}
    10161017
     1018#ifdef USE_MSI
     1019extern int __syscall UniMsiAlloc(USHORT usBusDevFunc, ULONG *pulCount, UCHAR *pucIrq);
     1020int snd_pci_enable_msi(struct pci_dev *dev)
     1021{
     1022  ULONG p;
     1023  UCHAR irq;
     1024
     1025  if (dev->irq_pin)
     1026  {
     1027    p = 1; /* int count */
     1028    if (UniMsiAlloc((dev->bus->number<<8) | dev->devfn, &p, &irq)) return -1;
     1029    /* we have an msi interrupt */
     1030    dev->irq = irq;
     1031    dev->irq_pin = 0;
     1032  }
     1033  return 0;
     1034}
     1035#else
     1036int snd_pci_enable_msi(struct pci_dev *dev)
     1037{
     1038  return -1;
     1039}
     1040#endif
     1041
  • GPL/trunk/lib32/sound.c

    r598 r604  
    976976        _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_RATE,
    977977                                                   pHwParams->ulSampleRate, 0);
     978                                               
     979  /* Change from Andy. If statement added around 5 statements.
     980   * Andy says: TODO:  determine why small buffers are a problem for this code
     981   * DAZ: This change is questionable.
     982   */
     983  if (periodsize > 6 * minperiodsize)
     984  {
    978985        _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
    979986                                                   periodsize, 0);
     
    986993        _snd_pcm_hw_param_set(&params, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
    987994                                                   periodbytes*nrperiods, 0);
    988 
     995  }
    989996
    990997        dprintf(("HWP: SR rate %ld, BPS %ld, CH %ld, PRSZ %lx, periods %lx",
  • 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.