~ubuntu-branches/ubuntu/oneiric/oss4/oneiric-proposed

« back to all changes in this revision

Viewing changes to setup/Linux/oss/cuckoo/cuckoo_mixer.c

  • Committer: Bazaar Package Importer
  • Author(s): Stefano Rivera
  • Date: 2011-06-16 20:37:48 UTC
  • mfrom: (5.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20110616203748-jbrxik6ql33z54co
Tags: 4.2-build2004-1ubuntu1
* Merge from Debian unstable.
  - Supports our current kernel (LP: #746048)
  Remaining changes:
  - debian/oss4-dkms.dkms.in: s/source/build/ in Kernel headers paths.
* ld-as-needed.patch: Re-order CC arguments to enable building with ld
  --as-needed (LP: #770972)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This software module makes it possible to use Open Sound System for Linux
 
3
 * (the _professional_ version) as a low level driver source for ALSA.
 
4
 *
 
5
 * Copyright (C) 2004 Hannu Savolainen (hannu@voimakentta.net).
 
6
 *
 
7
 * This library is free software; you can redistribute it and/or
 
8
 * modify it under the terms of the GNU Lesser General Public
 
9
 * License as published by the Free Software Foundation; either
 
10
 * version 2.1 of the License.
 
11
 *
 
12
 * This library is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
 * Lesser General Public License for more details.
 
16
 */
 
17
 
 
18
/*
 
19
 * !!!!!!!!!!!!!!!!!!!! Important  !!!!!!!!!!!!!!!!!!
 
20
 *
 
21
 * If this file doesn't compile, you must not try to resolve the problem
 
22
 * without perfect understanding of internals of Linux kernel, ALSA and
 
23
 * Open Sound System.
 
24
 *
 
25
 * Instead you need to check that you are using the version of this file
 
26
 * that matches the versions of ALSA, OSS and Linux you are currently using.
 
27
 */
 
28
 
 
29
#include "cuckoo.h"
 
30
 
 
31
MODULE_AUTHOR ("Hannu Savolainen <hannu@opensound.com>");
 
32
MODULE_LICENSE ("GPL v2");
 
33
MODULE_DESCRIPTION ("OSS mixer low level driver interface for ALSA");
 
34
 
 
35
typedef struct
 
36
{
 
37
  char *name, *data;
 
38
} enum_entry_t;
 
39
 
 
40
#if 0
 
41
static void
 
42
downshift (char *s)
 
43
{
 
44
  while (*s)
 
45
    {
 
46
      if (*s >= 'A' && *s <= 'Z')
 
47
        *s += 32;
 
48
      s++;
 
49
    }
 
50
}
 
51
#endif
 
52
 
 
53
static int
 
54
get_mixer_info (snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
 
55
{
 
56
  oss_mixext ext;
 
57
  int dev, ix;
 
58
 
 
59
  dev = ext.dev = kcontrol->private_value >> 16;
 
60
  ix = ext.ctrl = kcontrol->private_value & 0xffff;;
 
61
 
 
62
  oss_mixer_ext (dev, OSS_DEV_MIXER, SNDCTL_MIX_EXTINFO, (caddr_t) & ext);
 
63
 
 
64
  switch (ext.type)
 
65
    {
 
66
    case MIXT_STEREOSLIDER:
 
67
    case MIXT_STEREOVU:
 
68
      uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 
69
      uinfo->count = 2;
 
70
      uinfo->value.integer.min = ext.minvalue;
 
71
      uinfo->value.integer.max = ext.maxvalue;
 
72
      break;
 
73
 
 
74
    case MIXT_MONOSLIDER:
 
75
    case MIXT_MONOVU:
 
76
    case MIXT_SLIDER:
 
77
      uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 
78
      uinfo->count = 1;
 
79
      uinfo->value.integer.min = ext.minvalue;
 
80
      uinfo->value.integer.max = ext.maxvalue;
 
81
      break;
 
82
 
 
83
    case MIXT_ONOFF:
 
84
    case MIXT_MUTE:
 
85
      uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
 
86
      uinfo->count = 1;
 
87
      uinfo->value.integer.min = 0;
 
88
      uinfo->value.integer.max = 1;
 
89
      break;
 
90
 
 
91
    case MIXT_ENUM:
 
92
      {
 
93
        static const char *texts[] = {
 
94
          "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
 
95
          "10", "11", "12", "13", "14", "15", "16", "17", "18", "19",
 
96
          "20", "21", "22", "23", "24", "25", "26", "27", "28", "29",
 
97
          "30", "31", "32"
 
98
        };
 
99
        oss_mixer_enuminfo enumdef;
 
100
        uinfo->value.enumerated.items = ext.maxvalue;
 
101
 
 
102
        if (uinfo->value.enumerated.item < 0)
 
103
          uinfo->value.enumerated.item = 0;
 
104
        if (uinfo->value.enumerated.item >= ext.maxvalue)
 
105
          uinfo->value.enumerated.item = ext.maxvalue - 1;
 
106
        if (uinfo->value.enumerated.item > 31)
 
107
          uinfo->value.enumerated.item = 31;
 
108
        strcpy (uinfo->value.enumerated.name,
 
109
                texts[uinfo->value.enumerated.item]);
 
110
 
 
111
        enumdef.dev = ext.dev;
 
112
        enumdef.ctrl = ext.ctrl;
 
113
        if (oss_mixer_ext
 
114
            (dev, OSS_DEV_MIXER, SNDCTL_MIX_ENUMINFO,
 
115
             (caddr_t) & enumdef) >= 0)
 
116
          {
 
117
            char *text;
 
118
 
 
119
            text =
 
120
              &enumdef.strings[enumdef.
 
121
                               strindex[uinfo->value.enumerated.item]];
 
122
            strcpy (uinfo->value.enumerated.name, text);
 
123
          }
 
124
 
 
125
        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 
126
        uinfo->count = 1;
 
127
        uinfo->value.enumerated.items = ext.maxvalue;
 
128
      }
 
129
      break;
 
130
 
 
131
    default:
 
132
      printk ("cuckoo: mixer_info(%d/%d) - unknown type %d\n", dev, ix,
 
133
              ext.type);
 
134
      uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 
135
      uinfo->count = 1;
 
136
      uinfo->value.integer.min = ext.minvalue;
 
137
      uinfo->value.integer.max = ext.maxvalue;
 
138
      return 0;
 
139
    }
 
140
 
 
141
  return 0;
 
142
}
 
143
 
 
144
static int
 
145
mixer_get (snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 
146
{
 
147
  oss_mixext ext;
 
148
  oss_mixer_value val;
 
149
  int dev, ix, err;
 
150
 
 
151
  dev = ext.dev = kcontrol->private_value >> 16;
 
152
  ix = ext.ctrl = kcontrol->private_value & 0xffff;;
 
153
  if ((err =
 
154
       oss_mixer_ext (dev, OSS_DEV_MIXER, SNDCTL_MIX_EXTINFO,
 
155
                      (caddr_t) & ext)) < 0)
 
156
    return err;
 
157
 
 
158
  val.dev = dev;
 
159
  val.ctrl = ix;
 
160
  val.timestamp = ext.timestamp;
 
161
  if ((err =
 
162
       oss_mixer_ext (dev, OSS_DEV_MIXER, SNDCTL_MIX_READ,
 
163
                      (caddr_t) & val)) < 0)
 
164
    return err;
 
165
 
 
166
  switch (ext.type)
 
167
    {
 
168
    case MIXT_STEREOVU:
 
169
    case MIXT_STEREOSLIDER:
 
170
      ucontrol->value.integer.value[0] = val.value & 0xff;      // Left
 
171
      ucontrol->value.integer.value[1] = (val.value >> 8) & 0xff;       // Right
 
172
      break;
 
173
 
 
174
    case MIXT_MONOSLIDER:
 
175
    case MIXT_MONOVU:
 
176
    case MIXT_SLIDER:
 
177
      ucontrol->value.integer.value[0] = val.value & 0xff;
 
178
      break;
 
179
 
 
180
    case MIXT_ONOFF:
 
181
    case MIXT_MUTE:
 
182
      ucontrol->value.integer.value[0] = !!val.value;
 
183
      break;
 
184
 
 
185
    case MIXT_ENUM:
 
186
      ucontrol->value.integer.value[0] = val.value;
 
187
      break;
 
188
 
 
189
    default:
 
190
      printk ("cuckoo: mixer_get(%d/%d) - unknown type %d\n", dev, ix,
 
191
              ext.type);
 
192
      ucontrol->value.integer.value[0] = val.value & 0xff;
 
193
      return 0;
 
194
    }
 
195
 
 
196
  return 0;
 
197
}
 
198
 
 
199
static int
 
200
mixer_put (snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 
201
{
 
202
  oss_mixext ext;
 
203
  oss_mixer_value val;
 
204
  int dev, ix, err;
 
205
 
 
206
  dev = ext.dev = kcontrol->private_value >> 16;
 
207
  ix = ext.ctrl = kcontrol->private_value & 0xffff;;
 
208
  if ((err =
 
209
       oss_mixer_ext (dev, OSS_DEV_MIXER, SNDCTL_MIX_EXTINFO,
 
210
                      (caddr_t) & ext)) < 0)
 
211
    return err;
 
212
 
 
213
  val.dev = dev;
 
214
  val.ctrl = ix;
 
215
  val.timestamp = ext.timestamp;
 
216
 
 
217
  switch (ext.type)
 
218
    {
 
219
    case MIXT_STEREOSLIDER:
 
220
      val.value = ucontrol->value.integer.value[0] |    // Left
 
221
        ucontrol->value.integer.value[1] << 8;  // Right
 
222
      if ((err =
 
223
           oss_mixer_ext (dev, OSS_DEV_MIXER, SNDCTL_MIX_WRITE,
 
224
                          (caddr_t) & val)) < 0)
 
225
        return err;
 
226
      break;
 
227
 
 
228
    case MIXT_MONOSLIDER:
 
229
    case MIXT_SLIDER:
 
230
      val.value = ucontrol->value.integer.value[0];
 
231
      if ((err =
 
232
           oss_mixer_ext (dev, OSS_DEV_MIXER, SNDCTL_MIX_WRITE,
 
233
                          (caddr_t) & val)) < 0)
 
234
        return err;
 
235
      break;
 
236
 
 
237
    case MIXT_ONOFF:
 
238
    case MIXT_MUTE:
 
239
      val.value = !!ucontrol->value.integer.value[0];
 
240
      if ((err =
 
241
           oss_mixer_ext (dev, OSS_DEV_MIXER, SNDCTL_MIX_WRITE,
 
242
                          (caddr_t) & val)) < 0)
 
243
        return err;
 
244
      break;
 
245
 
 
246
    case MIXT_ENUM:
 
247
      val.value = ucontrol->value.integer.value[0];
 
248
      if ((err =
 
249
           oss_mixer_ext (dev, OSS_DEV_MIXER, SNDCTL_MIX_WRITE,
 
250
                          (caddr_t) & val)) < 0)
 
251
        return err;
 
252
      break;
 
253
 
 
254
    case MIXT_MONOVU:
 
255
    case MIXT_STEREOVU:
 
256
      return -EPERM;
 
257
 
 
258
    default:
 
259
      printk ("cuckoo: mixer_put(%d/%d) - unknown type %d\n", dev, ix,
 
260
              ext.type);
 
261
      val.value = ucontrol->value.integer.value[0];
 
262
      if ((err =
 
263
           oss_mixer_ext (dev, OSS_DEV_MIXER, SNDCTL_MIX_WRITE,
 
264
                          (caddr_t) & val)) < 0)
 
265
        return err;
 
266
    }
 
267
 
 
268
  return 0;
 
269
}
 
270
 
 
271
static void
 
272
add_control (cuckoo_t * chip, int dev, int ix, oss_mixext * ext, char *name)
 
273
{
 
274
  int i, ok, err = 0;
 
275
  snd_kcontrol_new_t my_control;
 
276
 
 
277
// Upshift the name if it's an single part one
 
278
 
 
279
  ok = 0;
 
280
  for (i = 0; i < strlen (name); i++)
 
281
    if (name[i] == '.')
 
282
      ok = 1;
 
283
  if (!ok)
 
284
    for (i = 0; i < strlen (name); i++)
 
285
      if (name[i] >= 'a' && name[i] <= 'z')
 
286
        name[i] -= 32;
 
287
 
 
288
// Add the control
 
289
 
 
290
  memset (&my_control, 0, sizeof (my_control));
 
291
 
 
292
  my_control.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
 
293
  my_control.name = name;
 
294
  my_control.index = 0;
 
295
  my_control.access = 0;
 
296
 
 
297
  if (ext->flags & MIXF_READABLE)
 
298
    my_control.access |= SNDRV_CTL_ELEM_ACCESS_READ;
 
299
  if (ext->flags & MIXF_WRITEABLE)
 
300
    my_control.access |= SNDRV_CTL_ELEM_ACCESS_WRITE;
 
301
  if ((ext->flags & 0x3) == MIXF_READABLE)      /* Read only */
 
302
    my_control.access |= SNDRV_CTL_ELEM_ACCESS_VOLATILE;
 
303
 
 
304
  my_control.private_value = (dev << 16) | ix;
 
305
  my_control.info = get_mixer_info;
 
306
  my_control.get = mixer_get;
 
307
  my_control.put = mixer_put;
 
308
 
 
309
  switch (ext->type)
 
310
    {
 
311
    case MIXT_ENUM:
 
312
    case MIXT_ONOFF:
 
313
    case MIXT_MUTE:
 
314
    case MIXT_STEREOSLIDER:
 
315
    case MIXT_SLIDER:
 
316
    case MIXT_MONOSLIDER:
 
317
    case MIXT_MONOVU:
 
318
    case MIXT_STEREOVU:
 
319
      if ((err =
 
320
           snd_ctl_add (chip->card, snd_ctl_new1 (&my_control, chip))) < 0)
 
321
        {
 
322
          printk ("cuckoo: snd_ctl_add(%s) failed, err=%d\n", ext->extname,
 
323
                  err);
 
324
          return;
 
325
        }
 
326
      break;
 
327
    }
 
328
}
 
329
 
 
330
int
 
331
install_mixer_instances (cuckoo_t * chip, int cardno)
 
332
{
 
333
  int dev;
 
334
  mixer_operations_t **cuckoo_mixer_devs = mixer_devs_p;
 
335
 
 
336
  for (dev = 0; dev < num_mixers; dev++)
 
337
    if (cuckoo_mixer_devs[dev]->card_number == cardno)
 
338
      {
 
339
        int nrext, i, sz;
 
340
 
 
341
        touch_mixer (dev);
 
342
 
 
343
        nrext = dev;
 
344
        oss_mixer_ext (dev, OSS_DEV_MIXER, SNDCTL_MIX_NREXT,
 
345
                       (ioctl_arg) & nrext);
 
346
 
 
347
        if (nrext == 0)
 
348
          continue;
 
349
 
 
350
        sz = nrext * (sizeof (char *) + 32);    // 32 characters / name (average)
 
351
 
 
352
        for (i = 0; i < nrext; i++)
 
353
          {
 
354
            oss_mixext ext;
 
355
            int parent = 0;
 
356
            oss_mixext_root *root = NULL;
 
357
 
 
358
            ext.dev = dev;
 
359
            ext.ctrl = i;
 
360
            oss_mixer_ext (dev, OSS_DEV_MIXER, SNDCTL_MIX_EXTINFO,
 
361
                           (caddr_t) & ext);
 
362
 
 
363
            switch (ext.type)
 
364
              {
 
365
              case MIXT_DEVROOT:
 
366
                root = (oss_mixext_root *) & ext.data;
 
367
                break;
 
368
 
 
369
              case MIXT_GROUP:
 
370
                parent = ext.parent;
 
371
                break;
 
372
 
 
373
              case MIXT_MARKER:
 
374
                break;
 
375
 
 
376
              default:
 
377
                add_control (chip, dev, i, &ext, ext.extname);
 
378
                break;
 
379
              }                 // Switch
 
380
 
 
381
          }                     // i
 
382
 
 
383
 
 
384
      }                         // dev
 
385
 
 
386
  return 0;
 
387
}
 
388
 
 
389
EXPORT_SYMBOL (install_mixer_instances);