2
* Purpose: OSS mixer core.
3
* Copyright (C) 4Front Technologies, 2002-2004. All rights reserved.
9
* This file is part of Open Sound System.
11
* Copyright (C) 4Front Technologies 1996-2008.
13
* This this source file is released under GPL v2 license (no other versions).
14
* See the COPYING file included in the main directory of this source
15
* distribution for the license terms and conditions.
19
#include <oss_config.h>
20
#include <midi_core.h>
22
oss_mutex_t oss_timing_mutex;
24
char *oss_license_string = OSS_LICENSE;
27
static int timing_is_active = 0; /* 1=The readtimings utility has been active */
30
void *mixer_devs_p = NULL;
34
mixer_operations_t **mixer_devs = NULL;
36
int mixer_port_number = 0;
37
int current_mixer_card = -1;
40
* mix_cvt is used for scaling mixer levels by various drivers.
43
0, 0, 3, 7, 10, 13, 16, 19, 21, 23, 26, 28, 30, 32, 34, 35, 37, 39, 40, 42,
44
43, 45, 46, 47, 49, 50, 51, 52, 53, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
46
65, 66, 67, 68, 69, 70, 70, 71, 72, 73, 73, 74, 75, 75, 76, 77, 77, 78, 79,
48
80, 81, 81, 82, 82, 83, 84, 84, 85, 85, 86, 86, 87, 87, 88, 88, 89, 89, 90,
50
91, 91, 92, 92, 93, 93, 94, 94, 95, 95, 96, 96, 96, 97, 97, 98, 98, 98, 99,
56
get_mixer_info (int dev, ioctl_arg arg)
58
mixer_info *info = (mixer_info *) arg;
60
memset(info, 0, sizeof(*info));
62
if (dev < 0 || dev >= num_mixers)
65
strcpy (info->id, mixer_devs[dev]->id);
66
strncpy (info->name, mixer_devs[dev]->name, 32);
67
info->name[31] = '\0';
68
info->modify_counter = mixer_devs[dev]->modify_counter;
74
* Legacy mixer handling
78
oss_legacy_mixer_ioctl (int mixdev, int audiodev, unsigned int cmd,
84
oss_timing_printf ("oss_legacy_mixer_ioctl(%d/%d, %08x) entered", mixdev,
88
if (!(cmd & SIOC_OUT) && !(cmd & SIOC_IN))
94
if (((cmd >> 8) & 0xff) != 'M') /* Not a mixer ioctl */
97
if (mixdev < 0 || mixdev >= num_mixers)
99
cmn_err (CE_WARN, "Bad mixer device %d\n", mixdev);
103
if (cmd == SOUND_MIXER_INFO)
104
return get_mixer_info (mixdev, arg);
106
if (!mixer_devs[mixdev]->enabled || mixer_devs[mixdev]->unloaded)
109
if (mixer_devs[mixdev]->d->ioctl == NULL)
112
if (IOC_IS_OUTPUT (cmd))
113
mixer_devs[mixdev]->modify_counter++;
115
ret = mixer_devs[mixdev]->d->ioctl (mixdev, audiodev, cmd, arg);
121
* Handling of initial mixer volumes
124
static int muted_mixer_levels[32] = {0};
126
static int default_mixer_levels[32] = {
127
0x3232, /* Master Volume */
132
0x1515, /* PC Speaker */
133
0x2020, /* Ext Line */
136
0x0000, /* Recording monitor */
137
0x4b4b, /* Second PCM */
138
0x4b4b, /* Recording level */
139
0x4b4b, /* Input gain */
140
0x4b4b, /* Output gain */
143
0x1515 /* Line3 (usually line in) */
147
* Table for configurable mixer volume handling
149
static mixer_vol_table mixer_vols[MAX_MIXER_DEV];
150
static int num_mixer_volumes = 0;
153
load_mixer_volumes (char *name, int *levels, int present)
156
extern int mixer_muted;
158
if (mixer_muted) /* Config setting from osscore.conf */
159
return muted_mixer_levels;
162
levels = default_mixer_levels;
164
for (i = 0; i < num_mixer_volumes; i++)
165
if (strcmp (name, mixer_vols[i].name) == 0)
168
mixer_vols[i].num = i;
169
return mixer_vols[i].levels;
172
if (num_mixer_volumes >= MAX_MIXER_DEV)
174
cmn_err (CE_WARN, "Too many mixers (%s/%d/%d)\n",
175
name, num_mixer_volumes, MAX_MIXER_DEV);
179
n = num_mixer_volumes++;
181
strcpy (mixer_vols[n].name, name);
184
mixer_vols[n].num = n;
186
mixer_vols[n].num = -1;
188
for (i = 0; i < 32; i++)
189
mixer_vols[n].levels[i] = levels[i];
190
return mixer_vols[n].levels;
194
* Mixer "extension" handling
198
oss_mixer_ext_info (oss_mixext * ent)
207
if (ent->dev < 0 || ent->dev >= num_mixers)
211
if (!mixer_devs[dev]->enabled || mixer_devs[dev]->unloaded)
216
if (ent->ctrl < 0 || ent->ctrl >= mixer_devs[dev]->nr_ext)
220
memcpy ((char *) ent, (char *) &mixer_devs[dev]->extensions[extnr].ext,
226
case MIXT_STEREOPEAK:
229
/* Peak meters will need to be polled */
230
ent->flags |= MIXF_POLL;
235
* Read-only controls are likely to change their value spontaneously so
236
* they should be polled.
238
if (!(ent->flags & MIXF_WRITEABLE))
239
ent->flags |= MIXF_POLL;
246
mixer_ext_get_enuminfo (oss_mixer_enuminfo * ent)
256
memset (ent, 0, sizeof (*ent));
258
if (dev < 0 || dev >= num_mixers)
265
if (ctrl < 0 || ctrl >= mixer_devs[dev]->nr_ext)
270
if (mixer_devs[dev]->extensions[ctrl].enum_info == NULL)
275
memcpy ((char *) ent,
276
(char *) mixer_devs[dev]->extensions[ctrl].enum_info,
283
mixer_ext_get_description (oss_mixer_enuminfo * ent)
294
memset (ent, 0, sizeof (*ent));
296
if (dev < 0 || dev >= num_mixers)
303
if (ctrl < 0 || ctrl >= mixer_devs[dev]->nr_ext)
308
if (mixer_devs[dev]->extensions[ctrl].description == NULL)
313
s = mixer_devs[dev]->extensions[ctrl].description;
315
strncpy (ent->strings, s, sizeof (ent->strings));
316
ent->strings [sizeof (ent->strings) - 1] = '\0';
322
mixer_ext_set_strings (int dev, int ctl, const char *s, int version)
325
* Note! The version parameter should usually be set to 0. However if the
326
* value set can change dynamically then it must be initially set to 1
327
* and later incremented every time the value set changes.
328
* This tells the applications to poll for updated values.
330
static oss_mixer_enuminfo ent;
332
memset (&ent, 0, sizeof (ent));
335
ent.version = version;
337
strcpy (ent.strings, s);
338
return mixer_ext_set_enum (&ent);
342
rebuild_list (oss_mixer_enuminfo * ent)
348
ent->strindex[0] = 0;
349
l = strlen (ent->strings);
351
for (i = 0; i < l; i++)
352
if (n < OSS_ENUM_MAXVALUE)
354
if (ent->strings[i] == ' ')
356
ent->strindex[n++] = i + 1;
366
mixer_ext_set_enum (oss_mixer_enuminfo * ent)
374
if (ent->dev < 0 || ent->dev >= num_mixers)
380
if (ent->ctrl < 0 || ent->ctrl >= mixer_devs[dev]->nr_ext)
384
if (mixer_devs[dev]->extensions[extnr].enum_info == NULL)
385
mixer_devs[dev]->extensions[extnr].enum_info =
386
PMALLOC (mixer_devs[dev]->osdev, sizeof (*ent));
388
if (mixer_devs[dev]->extensions[extnr].enum_info == NULL)
391
memcpy ((char *) mixer_devs[dev]->extensions[extnr].enum_info,
392
(char *) ent, sizeof (*ent));
394
ent = mixer_devs[dev]->extensions[extnr].enum_info;
396
if (ent->nvalues <= 0)
397
return rebuild_list (ent);
399
if (ent->nvalues >= OSS_ENUM_MAXVALUE)
401
mixer_devs[dev]->extensions[extnr].enum_info = NULL;
409
mixer_ext_set_description (int dev, int ctrl, const char *desc)
411
int l = strlen(desc);
413
if (dev < 0 || dev >= num_mixers)
418
if (ctrl < 0 || ctrl >= mixer_devs[dev]->nr_ext)
421
if (l > OSS_ENUM_STRINGSIZE) l = OSS_ENUM_STRINGSIZE;
423
mixer_devs[dev]->extensions[ctrl].description =
424
PMALLOC (mixer_devs[dev]->osdev, l);
426
if (mixer_devs[dev]->extensions[ctrl].description == NULL)
429
strncpy (mixer_devs[dev]->extensions[ctrl].description, desc, l);
430
mixer_devs[dev]->extensions[ctrl].description[l-1] = '\0';
432
mixer_devs[dev]->extensions[ctrl].ext.flags |= MIXF_DESCR;
438
mixer_ext_read (oss_mixer_value * val)
444
oss_mixext_desc *ext_desc;
450
if (val->dev < 0 || val->dev >= num_mixers)
455
if (!mixer_devs[dev]->enabled || mixer_devs[dev]->unloaded)
459
if (val->ctrl < 0 || val->ctrl >= mixer_devs[dev]->nr_ext)
463
ext_desc = &mixer_devs[dev]->extensions[extnr];
464
ext = &ext_desc->ext;
466
if (val->timestamp != ext->timestamp)
471
if (ext_desc->handler == NULL || !(ext->flags & MIXF_READABLE))
474
func = (mixer_ext_fn) ext_desc->handler;
475
return (val->value = func (dev, ext->ctrl, SNDCTL_MIX_READ, val->value));
479
mixer_ext_write (oss_mixer_value * val)
486
oss_mixext_desc *ext_desc;
491
cmn_err (CE_WARN, "NULL argument in mixer call\n");
495
if (val->dev < 0 || val->dev >= num_mixers)
499
if (!mixer_devs[dev]->enabled || mixer_devs[dev]->unloaded)
503
if (val->ctrl < 0 || val->ctrl >= mixer_devs[dev]->nr_ext)
507
ext_desc = &mixer_devs[dev]->extensions[extnr];
508
ext = &ext_desc->ext;
510
if (ext_desc->handler == NULL || !(ext->flags & MIXF_WRITEABLE))
512
cmn_err (CE_WARN, "NULL handler or control not writeable\n");
516
if (val->timestamp != ext->timestamp)
521
func = (mixer_ext_fn) ext_desc->handler;
522
mixer_devs[dev]->modify_counter++;
523
err = val->value = func (dev, ext->ctrl, SNDCTL_MIX_WRITE, val->value);
526
ext->update_counter++;
531
mixer_ext_create_device (int dev, int maxentries)
533
oss_mixext_root *mixroot;
535
oss_mixext_desc *mixext_desc;
536
char *name = mixer_devs[dev]->name;
537
char *id = mixer_devs[dev]->id;
540
maxentries++; /* Needs space for the device root node */
542
if (mixer_devs[dev]->max_ext == 0)
545
PMALLOC (mixer_devs[dev]->osdev, sizeof (*mixext_desc) * maxentries);
546
mixer_devs[dev]->max_ext = maxentries;
547
mixer_devs[dev]->extensions = mixext_desc;
551
mixext_desc = mixer_devs[dev]->extensions;
554
if (mixext_desc == NULL)
556
cmn_err (CE_CONT, "Not enough memory for mixer%d (ext)\n", dev);
560
mixer_devs[dev]->nr_ext = 1;
561
mixer_devs[dev]->timestamp = GET_JIFFIES ();
563
mixext = &mixext_desc->ext;
565
mixext->ctrl = -1; /* Undefined */
566
mixext->type = MIXT_DEVROOT;
567
mixext->maxvalue = 0;
568
mixext->minvalue = 0;
570
strcpy (mixext->id, "DEVROOT");
571
mixext->parent = 0; /* Link to itself */
572
mixext->timestamp = mixer_devs[dev]->timestamp;
573
mixext_desc->handler = NULL;
574
memset (mixext->data, 0, sizeof (mixext->data));
576
mixroot = (oss_mixext_root *) & mixext->data;
578
for (i = 0; i < 15 && id[i]; i++)
579
mixroot->id[i] = id[i];
582
for (i = 0; i < 47 && name[i]; i++)
583
mixroot->name[i] = name[i];
584
mixroot->name[47] = 0;
590
mixer_ext_create_group_flags (int dev, int parent, const char *id,
594
oss_mixext_desc *mixext_desc, *parent_desc;
597
flags &= ~MIXF_DESCR;
599
if (mixer_devs[dev]->extensions == NULL)
601
cmn_err (CE_WARN, "Mixer extensions not initialized for device %d\n",
607
* Ensure that the parent node number is valid.
609
if (parent < 0 || parent >= mixer_devs[dev]->nr_ext)
613
&mixer_devs[dev]->extensions[parent];
614
mixext = &parent_desc->ext;
616
if (mixext->type != MIXT_DEVROOT && mixext->type != MIXT_GROUP)
617
parent = 0; /* Point to the root group */
619
if (mixer_devs[dev]->nr_ext >= mixer_devs[dev]->max_ext)
621
cmn_err (CE_WARN, "Out of mixer controls for device %d/%s (%d)\n", dev,
622
mixer_devs[dev]->name, mixer_devs[dev]->max_ext);
627
&mixer_devs[dev]->extensions[(enumber = mixer_devs[dev]->nr_ext++)];
628
mixext = &mixext_desc->ext;
630
mixext->ctrl = -1; /* Undefined */
631
mixext->type = MIXT_GROUP;
632
mixext->maxvalue = 0;
633
mixext->minvalue = 0;
634
mixext->flags = flags | MIXF_FLAT; /* Will be unflattened later if required */
635
strcpy (mixext->id, id);
636
mixext->parent = parent;
637
mixext_desc->handler = NULL;
638
mixext_desc->enum_info = NULL;
639
memset (mixext->enum_present, 0xff, sizeof (mixext->enum_present));
640
mixext->timestamp = mixer_devs[dev]->timestamp;
641
mixext->control_no = -1;
643
memset (mixext->data, 0, sizeof (mixext->data));
649
mixer_ext_create_group (int dev, int parent, const char *id)
651
return mixer_ext_create_group_flags (dev, parent, id, 0);
655
mixer_ext_truncate (int dev, int index)
657
if (index < mixer_devs[dev]->nr_ext)
659
mixer_devs[dev]->nr_ext = index;
660
mixer_devs[dev]->modify_counter++;
661
mixer_devs[dev]->timestamp++;
666
static void expand_names (int dev);
667
static void unflatten_group (int dev, int group);
668
static void touch_parents (int dev, int group);
671
mixer_ext_create_control (int dev, int parent, int ctrl, mixer_ext_fn func,
672
int type, const char *id, int maxvalue, int flags)
675
oss_mixext_desc *mixext_desc, *parent_desc;
678
flags &= ~MIXF_DESCR;
680
if (mixer_devs[dev]->extensions == NULL)
682
cmn_err (CE_WARN, "Mixer extensions not initialized for device %d\n",
687
if (mixer_devs[dev]->nr_ext >= mixer_devs[dev]->max_ext)
689
cmn_err (CE_WARN, "Out of mixer controls for device %d/%s (%d)\n", dev,
690
mixer_devs[dev]->name, mixer_devs[dev]->max_ext);
694
if (func == NULL) /* No access function */
695
flags &= ~(MIXF_READABLE | MIXF_WRITEABLE);
698
* Ensure that the parent node number is valid.
700
if (parent < 0 || parent >= mixer_devs[dev]->nr_ext)
704
&mixer_devs[dev]->extensions[parent];
705
mixext = &parent_desc->ext;
707
if (mixext->type != MIXT_DEVROOT && mixext->type != MIXT_GROUP)
708
parent = 0; /* Point to the root group */
712
&mixer_devs[dev]->extensions[(enumber = mixer_devs[dev]->nr_ext++)];
713
mixext = &mixext_desc->ext;
717
mixext->maxvalue = maxvalue;
718
mixext->minvalue = 0;
719
mixext->flags = flags;
720
strncpy (mixext->id, id, sizeof (mixext->id));
721
mixext->id[sizeof (mixext->id) - 1] = 0;
722
mixext->parent = parent;
723
mixext->timestamp = mixer_devs[dev]->timestamp;
724
mixext_desc->handler = (mixer_ext_fn) func;
725
mixext_desc->enum_info = NULL;
726
memset (mixext->data, 0, sizeof (mixext->data));
727
memset (mixext->enum_present, 0xff, sizeof (mixext->enum_present));
728
mixext->control_no = -1;
732
* Perform name expansion too if it has already been done for the
733
* earlier controls. Note that this only gets done with rare devices
734
* that add/remove controls on fly.
736
* TODO: Optimize this to expand only the current control. Scanning through
737
* all the controls may be bit time consuming with future devices having 100s
740
if (mixer_devs[dev]->names_checked)
743
strcpy(mixext->extname, mixext->id);
746
* Mark groups with tall controls such as peak meters and sliders as
753
case MIXT_MONOSLIDER:
754
case MIXT_STEREOSLIDER:
755
case MIXT_MONOSLIDER16:
756
case MIXT_STEREOSLIDER16:
760
case MIXT_STEREOPEAK:
764
unflatten_group (dev, parent);
768
touch_parents(dev, parent);
775
mixer_find_ext (int dev, int enumber)
777
oss_mixext_desc *mixext;
779
if (dev < 0 || dev >= num_mixers)
785
if (enumber < 0 || enumber >= mixer_devs[dev]->nr_ext)
790
mixext = &mixer_devs[dev]->extensions[enumber];
796
* Default read/write access functions
799
mixer_ext_rw (int dev, int ctrl, unsigned int cmd, int value)
803
if (cmd == SNDCTL_MIX_READ)
806
oss_legacy_mixer_ioctl (dev, -1, MIXER_READ (ctrl),
807
(ioctl_arg) & value)) < 0)
812
if (cmd == SNDCTL_MIX_WRITE)
815
oss_legacy_mixer_ioctl (dev, -1, MIXER_WRITE (ctrl),
816
(ioctl_arg) & value)) < 0)
825
mixer_ext_recrw (int dev, int ctrl, unsigned int cmd, int value)
827
int caps, recmask, err;
830
oss_legacy_mixer_ioctl (dev, -1, SOUND_MIXER_READ_CAPS,
831
(ioctl_arg) & caps)) < 0)
832
caps = SOUND_CAP_EXCL_INPUT; /* Default */
835
oss_legacy_mixer_ioctl (dev, -1, SOUND_MIXER_READ_RECSRC,
836
(ioctl_arg) & recmask)) < 0)
839
if (cmd == SNDCTL_MIX_READ)
840
return (recmask & (1 << ctrl)) ? 1 : 0;
842
if (caps & SOUND_CAP_EXCL_INPUT) /* Single recording source */
846
recmask |= (1 << ctrl);
848
recmask &= ~(1 << ctrl);
851
return 1; /* Can't remove the only recording source */
854
oss_legacy_mixer_ioctl (dev, -1, SOUND_MIXER_WRITE_RECSRC,
855
(ioctl_arg) & recmask)) < 0)
859
return (recmask & (1 << ctrl)) ? 1 : 0;
863
* Mixer extension initialization
867
store_name (oss_mixext * thisrec, char *name)
873
strncpy (thisrec->extname, name, 32);
874
thisrec->extname[31] = '\0';
876
name = thisrec->extname;
877
for (i = 0; i < strlen (name); i++)
878
if (name[i] >= 'A' && name[i] <= 'Z')
883
cut_name (char *name)
896
#include "mixerdefs.h"
899
find_enum_defs (oss_mixext * thisrec, int dev, int ctl)
903
for (i = 0; mixer_defs[i].name != NULL; i++)
904
if (strcmp (thisrec->extname, mixer_defs[i].name) == 0)
906
mixer_ext_set_strings (dev, ctl, mixer_defs[i].strings, 0);
912
expand_names (int dev)
915
oss_mixext_desc *mixext_desc;
917
n = mixer_devs[dev]->nr_ext;
918
mixer_devs[dev]->names_checked = 1;
923
for (i = 0; i < n; i++)
925
char tmp[100], *name;
927
oss_mixext *thisrec = NULL, *parentrec = NULL;
929
mixext_desc = &mixer_devs[dev]->extensions[i];
930
thisrec = &mixext_desc->ext;
932
switch (thisrec->type)
935
thisrec->extname[0] = 0;
939
parent = thisrec->parent;
940
mixext_desc = &mixer_devs[dev]->extensions[parent];
941
parentrec = &mixext_desc->ext;
942
name = cut_name (thisrec->id);
943
if (parentrec->extname[0] == 0)
946
sprintf (tmp, "%s.%s", parentrec->extname, name);
947
store_name (thisrec, tmp);
950
case MIXT_STEREOSLIDER:
951
case MIXT_STEREOSLIDER16:
955
case MIXT_MONOSLIDER:
956
case MIXT_MONOSLIDER16:
960
case MIXT_STEREOPEAK:
967
parent = thisrec->parent;
968
mixext_desc = &mixer_devs[dev]->extensions[parent];
969
parentrec = &mixext_desc->ext;
970
name = cut_name (thisrec->id);
971
if (*thisrec->id == 0 || *thisrec->id == '-') /* Special (hidden) names */
972
strcpy (thisrec->extname, parentrec->extname);
975
sprintf (tmp, "%s.%s", parentrec->extname, name);
976
store_name (thisrec, tmp);
978
if (thisrec->type == MIXT_ENUM)
979
find_enum_defs (thisrec, dev, i);
990
* Fix duplicate names.
993
for (i = 0; i < n; i++)
997
oss_mixext *thisrec = NULL;
999
mixext_desc = &mixer_devs[dev]->extensions[i];
1000
thisrec = &mixext_desc->ext;
1002
if (thisrec->type == MIXT_GROUP)
1005
strcpy (tmp, thisrec->extname);
1007
for (j = i + 1; j < n; j++)
1009
oss_mixext_desc *mixext_desc2;
1010
oss_mixext *thisrec2 = NULL;
1011
mixext_desc2 = &mixer_devs[dev]->extensions[j];
1012
thisrec2 = &mixext_desc2->ext;
1014
if (thisrec2->type == MIXT_GROUP)
1017
if (strcmp (thisrec2->extname, tmp) == 0)
1021
if (dupes > 0) /* Need to fix duplicates */
1026
for (j = i; j < n; j++)
1028
oss_mixext_desc *mixext_desc2;
1029
oss_mixext *thisrec2 = NULL;
1030
mixext_desc2 = &mixer_devs[dev]->extensions[j];
1031
thisrec2 = &mixext_desc2->ext;
1033
if (thisrec2->type != MIXT_GROUP)
1034
if (strcmp (thisrec2->extname, tmp) == 0)
1036
sprintf (tmp2, "%d", count++);
1038
len = strlen (thisrec2->extname);
1039
if (len >= sizeof (thisrec2->extname) - strlen (tmp2))
1040
len = sizeof (thisrec2->extname) - strlen (tmp2) - 1;
1041
strcpy (thisrec2->extname + len, tmp2);
1049
unflatten_group (int dev, int group)
1052
* Clear the MIXF_FLAT flags from all parent groups (recursively):
1055
oss_mixext_desc *mixext_desc;
1056
oss_mixext *thisrec = NULL;
1058
n = mixer_devs[dev]->nr_ext;
1063
if (group <= 0 || group >= n)
1066
mixext_desc = &mixer_devs[dev]->extensions[group];
1067
thisrec = &mixext_desc->ext;
1069
if (thisrec->type != MIXT_GROUP) /* Not a group */
1072
if (!(thisrec->flags & MIXF_FLAT)) /* Already unflattened */
1075
thisrec->flags &= ~MIXF_FLAT;
1077
if (thisrec->parent >= group) /* Broken link */
1080
unflatten_group (dev, thisrec->parent); /* Unflatten the parent */
1084
touch_parents (int dev, int group)
1087
oss_mixext_desc *mixext_desc;
1088
oss_mixext *thisrec = NULL;
1090
n = mixer_devs[dev]->nr_ext;
1095
if (group <= 0 || group >= n)
1098
mixext_desc = &mixer_devs[dev]->extensions[group];
1099
thisrec = &mixext_desc->ext;
1101
while (thisrec->type != MIXT_DEVROOT)
1103
if (thisrec->type != MIXT_GROUP) /* Not a group */
1106
thisrec->update_counter++;
1108
if (thisrec->parent >= group) /* Broken link */
1111
unflatten_group (dev, thisrec->parent); /* Unflatten the parent */
1113
mixext_desc = &mixer_devs[dev]->extensions[thisrec->parent];
1114
thisrec = &mixext_desc->ext;
1117
thisrec->update_counter++;
1120
#define INPUT_MASK (SOUND_MASK_RECLEV|SOUND_MASK_IGAIN)
1121
#define OUTPUT_MASK (SOUND_MASK_PCM|SOUND_MASK_ALTPCM|SOUND_MASK_VOLUME| \
1122
SOUND_MASK_BASS|SOUND_MASK_TREBLE|SOUND_MASK_SYNTH| \
1123
SOUND_MASK_IMIX|SOUND_MASK_REARVOL|SOUND_MASK_CENTERVOL| \
1125
#define MONITOR_MASK (SOUND_MASK_SPEAKER|SOUND_MASK_LINE|SOUND_MASK_LINE| \
1126
SOUND_MASK_MIC|SOUND_MASK_CD|SOUND_MASK_LINE1|SOUND_MASK_LINE2| \
1127
SOUND_MASK_LINE3|SOUND_MASK_DIGITAL1|SOUND_MASK_DIGITAL2| \
1128
SOUND_MASK_DIGITAL3|SOUND_MASK_MONO|SOUND_MASK_PHONE| \
1129
SOUND_MASK_RADIO|SOUND_MASK_VIDEO)
1132
touch_mixer (int dev)
1134
int i, n, devmask, recmask, stereomask, grp, root = 0, caps = 0;
1135
static char *id[] = SOUND_DEVICE_NAMES;
1138
if (mixer_devs[dev] == NULL || mixer_devs[dev]->unloaded
1139
|| !mixer_devs[dev]->enabled)
1145
* Create default mixer extension records if required.
1147
if (mixer_devs[dev]->nr_ext > 0) /* Already initialized */
1151
* Compute number of required mixer extension entries
1154
n = mixer_devs[dev]->nr_extra_ext; /* Reserve space for the actual driver */
1158
if (oss_legacy_mixer_ioctl
1159
(dev, -1, SOUND_MIXER_READ_CAPS, (ioctl_arg) & caps) < 0)
1160
caps = 0; /* Error */
1162
if (oss_legacy_mixer_ioctl
1163
(dev, -1, SOUND_MIXER_READ_DEVMASK, (ioctl_arg) & devmask) < 0)
1164
goto skip; /* Error */
1166
/* Remove devices that are handled otherwise */
1167
devmask &= ~mixer_devs[dev]->ignore_mask;
1169
for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
1170
if (devmask & (1 << i)) /* This control is supported */
1175
if (oss_legacy_mixer_ioctl
1176
(dev, -1, SOUND_MIXER_READ_RECMASK, (ioctl_arg) & recmask) < 0)
1177
goto skip; /* Error */
1179
for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
1180
if (recmask & (1 << i)) /* This control is also recording device */
1186
n += 20; /* Space for OSSD use */
1189
n = n + 5; /* The marker entry and some spare space */
1190
if ((root = mixer_ext_create_device (dev, n)) < 0)
1194
if (oss_legacy_mixer_ioctl (dev, -1, SOUND_MIXER_READ_STEREODEVS,
1195
(ioctl_arg) & stereomask) < 0)
1196
stereomask = -1; /* Assume all stereo */
1198
if (!(caps & SOUND_CAP_NOLEGACY)) /* Don't (re)export the legacy mixer */
1199
for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
1200
if (devmask & (1 << i))
1203
mixer_ext_create_group_flags (dev, root, id[i],
1211
* Set the type hints for main and PCM volume controls
1216
case SOUND_MIXER_VOLUME:
1217
case SOUND_MIXER_MONO:
1218
case SOUND_MIXER_REARVOL:
1219
case SOUND_MIXER_CENTERVOL:
1220
case SOUND_MIXER_SIDEVOL:
1221
flags |= MIXF_MAINVOL;
1224
case SOUND_MIXER_PCM:
1225
case SOUND_MIXER_ALTPCM:
1226
flags |= MIXF_PCMVOL;
1229
case SOUND_MIXER_RECLEV:
1230
case SOUND_MIXER_IGAIN:
1231
flags |= MIXF_RECVOL;
1234
case SOUND_MIXER_SYNTH:
1235
case SOUND_MIXER_SPEAKER:
1236
case SOUND_MIXER_LINE:
1237
case SOUND_MIXER_LINE1:
1238
case SOUND_MIXER_LINE2:
1239
case SOUND_MIXER_LINE3:
1240
case SOUND_MIXER_MIC:
1241
case SOUND_MIXER_CD:
1242
case SOUND_MIXER_DIGITAL1:
1243
case SOUND_MIXER_DIGITAL2:
1244
case SOUND_MIXER_DIGITAL3:
1245
case SOUND_MIXER_PHONE:
1246
case SOUND_MIXER_VIDEO:
1247
case SOUND_MIXER_RADIO:
1248
flags |= MIXF_MONVOL;
1252
if (stereomask & (1 << i))
1253
cnum = mixer_ext_create_control (dev, grp, i, mixer_ext_rw,
1256
flags | MIXF_READABLE |
1259
cnum = mixer_ext_create_control (dev, grp, i, mixer_ext_rw,
1262
flags | MIXF_READABLE |
1265
if ((ent = mixer_find_ext (dev, cnum)) != NULL)
1267
ent->control_no = i;
1269
if ((1 << i) & INPUT_MASK)
1270
ent->desc &= MIXEXT_SCOPE_INPUT;
1271
if ((1 << i) & OUTPUT_MASK)
1272
ent->desc &= MIXEXT_SCOPE_OUTPUT;
1273
if ((1 << i) & MONITOR_MASK)
1274
ent->desc &= MIXEXT_SCOPE_MONITOR;
1277
* Set the RGB color for some of the controls
1278
* to match the usual jack color.
1283
case SOUND_MIXER_MIC: ent->rgbcolor=OSS_RGB_PINK; break;
1284
case SOUND_MIXER_LINE: ent->rgbcolor=OSS_RGB_BLUE; break;
1285
case SOUND_MIXER_VOLUME: ent->rgbcolor=OSS_RGB_GREEN; break;
1286
case SOUND_MIXER_REARVOL: ent->rgbcolor=OSS_RGB_BLACK; break;
1287
case SOUND_MIXER_SIDEVOL: ent->rgbcolor=OSS_RGB_GRAY; break;
1288
case SOUND_MIXER_CENTERVOL: ent->rgbcolor=OSS_RGB_ORANGE; break;
1292
if (recmask & (1 << i))
1295
mixer_ext_create_control (dev, grp, i, mixer_ext_recrw,
1296
MIXT_ONOFF, "REC", 1,
1297
MIXF_READABLE | MIXF_WRITEABLE | MIXF_RECVOL);
1298
if ((ent = mixer_find_ext (dev, cnum)) != NULL)
1300
ent->desc &= MIXEXT_SCOPE_RECSWITCH;
1308
if ((root = mixer_ext_create_device (dev, n)) < 0)
1310
mixer_ext_create_control (dev, root, 0, NULL, MIXT_MARKER, "", 0, 0);
1312
if (mixer_devs[dev]->create_controls != NULL)
1313
mixer_devs[dev]->create_controls (dev);
1318
mixer_ext_set_init_fn (int dev, mixer_create_controls_t func, int nextra)
1321
* Set device dependent mixer extension initialization function and
1322
* reserve some extension entries for device dependent use.
1324
* This initialization function will be called later when/if the
1325
* extended mixer is actually used.
1327
if (dev < 0 || dev >= num_mixers)
1330
mixer_devs[dev]->nr_extra_ext = nextra;
1331
mixer_devs[dev]->create_controls = func;
1336
mixer_ext_rebuild_all (int dev, mixer_create_controls_t func, int nextra)
1339
* Throw away all existing mixer controls and recreate the mixer.
1341
if (dev < 0 || dev >= num_mixers)
1343
mixer_devs[dev]->nr_ext = 0;
1345
mixer_devs[dev]->nr_extra_ext = nextra;
1346
mixer_devs[dev]->create_controls = func;
1349
if (mixer_devs[dev]->create_vmix_controls != NULL)
1351
mixer_devs[dev]->create_vmix_controls(dev);
1358
mixer_ext_set_vmix_init_fn (int dev, mixer_create_controls_t func, int nextra,
1362
* Set device dependent mixer extension initialization function and
1363
* reserve some extension entries for device dependent use.
1365
* This initialization function will be called later when/if the
1366
* extended mixer is actually used.
1368
if (dev < 0 || dev >= num_mixers)
1371
mixer_devs[dev]->nr_extra_ext += nextra;
1372
mixer_devs[dev]->create_vmix_controls = func;
1373
mixer_devs[dev]->vmix_devc = devc;
1382
ainfo_combine_caps (oss_audioinfo * ainfo, adev_p adev)
1384
if (!(adev->flags & ADEV_NOOUTPUT))
1385
ainfo->caps |= DSP_CAP_OUTPUT;
1387
ainfo->caps &= ~DSP_CAP_OUTPUT;
1389
if (!(adev->flags & ADEV_NOINPUT))
1390
ainfo->caps |= DSP_CAP_INPUT;
1392
ainfo->caps &= ~DSP_CAP_INPUT;
1394
if (adev->flags & ADEV_DUPLEX)
1395
ainfo->caps |= DSP_CAP_DUPLEX;
1397
ainfo->caps &= ~DSP_CAP_DUPLEX;
1399
#ifdef ALLOW_BUFFER_MAPPING
1400
if (!(adev->flags & ADEV_NOMMAP))
1401
ainfo->caps |= DSP_CAP_MMAP;
1408
* Device list support is currently not used
1411
check_list (oss_devlist_t * oldlist, oss_devlist_t * newlist)
1414
* Check that the same devices are present in both lists. Any difference
1415
* indicates that the device configuration has changed (invalidates the list).
1417
#if MAX_AUDIO_DEVFILES > 64
1418
#error Too many audio devices - fix this algorithm
1420
unsigned long long mask1, mask2;
1423
if (newlist->ndevs != oldlist->ndevs)
1429
for (i = 0; i < oldlist->ndevs; i++)
1430
mask1 |= 1LL << oldlist->devices[i];
1431
for (i = 0; i < newlist->ndevs; i++)
1432
mask1 |= 1LL << newlist->devices[i];
1442
get_engineinfo (int dev, oss_audioinfo * info, int combine_slaves)
1444
int dev_present = 0;
1446
oss_native_word flags;
1451
memset ((char *) info, 0, sizeof (*info));
1453
if (dev < 0 || dev >= num_audio_engines)
1456
adev = audio_engines[dev];
1459
cmn_err (CE_WARN, "Internal error - adev==NULL (%d)\n", dev);
1463
if (!adev->unloaded && adev->enabled)
1468
MUTEX_ENTER_IRQDISABLE (adev->mutex, flags);
1471
strcpy (info->name, adev->name);
1472
strcpy (info->handle, adev->handle);
1473
info->busy = adev->open_mode;
1474
info->caps = adev->caps;
1475
if (!(adev->flags & ADEV_NOINPUT))
1476
info->caps |= PCM_CAP_INPUT;
1477
if (!(adev->flags & ADEV_NOOUTPUT))
1478
info->caps |= PCM_CAP_OUTPUT;
1479
if (adev->flags & ADEV_SPECIAL)
1480
info->caps |= PCM_CAP_SPECIAL;
1481
if (adev->flags & ADEV_VIRTUAL)
1482
info->caps |= PCM_CAP_VIRTUAL;
1484
if (adev->flags & (ADEV_HIDDEN | ADEV_SHADOW))
1486
info->caps |= PCM_CAP_HIDDEN;
1489
if (adev->flags & ADEV_DUPLEX)
1491
info->caps |= PCM_CAP_DUPLEX;
1493
if (adev->d->adrv_trigger) /* Supports SETTRIGGER */
1494
info->caps |= PCM_CAP_TRIGGER;
1495
#ifdef ALLOW_BUFFER_MAPPING
1496
if (!(adev->flags & ADEV_NOMMAP))
1497
info->caps |= PCM_CAP_MMAP;
1500
info->oformats = adev->oformat_mask;
1501
info->iformats = adev->iformat_mask;
1502
info->pid = adev->pid;
1503
info->latency = adev->latency;
1505
strncpy (info->cmd, adev->cmd, sizeof (info->cmd));
1506
info->cmd[sizeof (info->cmd) - 1] = 0;
1508
strcpy (info->devnode, adev->devnode);
1510
if (!adev->unloaded && adev->enabled)
1512
if (audio_engines[dev]->d->adrv_ioctl (dev, SNDCTL_GETSONG,
1513
(ioctl_arg) info->song_name) ==
1515
strcpy (info->song_name, adev->song_name);
1516
if (audio_engines[dev]->d->adrv_ioctl (dev, SNDCTL_GETLABEL,
1517
(ioctl_arg) info->label) ==
1519
strcpy (info->label, adev->label);
1522
if (*info->label == 0)
1524
strncpy (info->label, info->cmd, sizeof (info->label));
1525
info->label[sizeof (info->label) - 1] = 0;
1528
info->magic = adev->magic;
1529
info->card_number = adev->card_number;
1530
info->port_number = adev->port_number;
1531
info->mixer_dev = adev->mixer_dev;
1532
info->legacy_device = adev->real_dev;
1533
info->rate_source = adev->rate_source;
1534
info->enabled = (adev->enabled && !adev->unloaded);
1535
info->flags = adev->flags;
1536
info->min_rate = adev->min_rate;
1537
info->max_rate = adev->max_rate;
1538
info->min_channels = adev->min_channels;
1539
info->max_channels = adev->max_channels;
1540
info->binding = adev->binding;
1541
info->nrates = adev->nrates;
1542
for (i = 0; i < info->nrates; i++)
1543
info->rates[i] = adev->rates[i];
1545
if (adev->next_out == NULL || !dev_present)
1546
info->next_play_engine = 0;
1549
info->next_play_engine = adev->next_out->engine_num;
1550
next = adev->next_out;
1554
while (combine_slaves && next != NULL && i++ < num_audio_engines)
1556
ainfo_combine_caps (info, next);
1557
next = next->next_out;
1562
if (adev->next_in == NULL || !dev_present)
1563
info->next_rec_engine = 0;
1566
info->next_rec_engine = adev->next_in->engine_num;
1567
next = adev->next_in;
1571
while (combine_slaves && next != NULL && i++ < num_audio_engines)
1573
ainfo_combine_caps (info, next);
1574
next = next->next_in;
1581
MUTEX_EXIT_IRQRESTORE (adev->mutex, flags);
1586
#ifdef CONFIG_OSS_VMIX
1588
vmixctl_attach(vmixctl_attach_t *att)
1591
oss_device_t *osdev;
1593
if (att->masterdev<0 || att->masterdev >= num_audio_engines)
1596
if (att->inputdev != -1)
1597
if (att->inputdev<0 || att->inputdev >= num_audio_engines)
1600
osdev=audio_engines[att->masterdev]->master_osdev;
1602
if ((err=vmix_attach_audiodev(osdev, att->masterdev, att->inputdev, att->attach_flags))<0)
1609
vmixctl_detach(vmixctl_attach_t *att)
1612
oss_device_t *osdev;
1614
if (att->masterdev<0 || att->masterdev >= num_audio_engines)
1617
osdev=audio_engines[att->masterdev]->master_osdev;
1619
if ((err=vmix_detach_audiodev(att->masterdev))<0)
1626
vmixctl_rate(vmixctl_rate_t *rate)
1630
if (rate->masterdev<0 || rate->masterdev >= num_audio_engines)
1633
if ((err=vmix_set_master_rate(rate->masterdev, rate->rate))<0)
1640
vmixctl_map_channels(vmixctl_map_t *map)
1644
if (map->masterdev < 0 || map->masterdev >= num_audio_engines)
1647
if ((err = vmix_set_channel_map (map->masterdev, &map->map)) < 0)
1655
oss_mixer_ext (int orig_dev, int class, unsigned int cmd, ioctl_arg arg)
1658
int combine_slaves = 0;
1659
#ifdef MANAGE_DEV_DSP
1661
extern void oss_combine_write_lists (void);
1667
case SNDCTL_SYSINFO: /* Formerly OSS_SYSINFO */
1669
oss_sysinfo *info = (oss_sysinfo *) arg;
1672
memset (info, 0, sizeof (*info));
1673
strcpy (info->product, "OSS");
1674
strncpy (info->version, OSS_VERSION_STRING, sizeof (info->version));
1675
info->version [sizeof (info->version) - 1] = '\0';
1676
strcpy (info->license, oss_license_string);
1677
info->versionnum = OSS_VERSION;
1680
/* Detailed Mercurial version */
1681
strncpy (info->revision_info, OSS_HG_INFO, sizeof(info->revision_info));
1682
info->revision_info[sizeof(info->revision_info)-1]=0;
1685
memset (info->options, 0, sizeof (info->options));
1687
info->numaudios = num_audio_devfiles;
1688
info->numaudioengines = num_audio_engines;
1689
for (i = 0; i < 8; i++)
1690
info->openedaudio[i] = 0;
1691
for (i = 0; i < num_audio_engines; i++)
1692
if (audio_engines[i] != NULL)
1694
if (audio_engines[i]->flags & ADEV_OPENED)
1695
if (audio_engines[i]->next_out != NULL)
1697
int x = audio_engines[i]->real_dev;
1698
info->openedaudio[x / 32] |= 1 << (x % 32);
1701
for (i = 0; i < 8; i++)
1702
info->openedmidi[i] = 0;
1703
for (i = 0; i < num_mididevs; i++)
1704
if (midi_devs[i]->open_mode != 0)
1705
info->openedmidi[i / 32] |= 1 << (i % 32);
1707
info->numsynths = 0;
1708
#ifdef CONFIG_OSS_MIDI
1709
info->nummidis = num_mididevs;
1711
info->numtimers = oss_num_timers;
1712
info->nummixers = num_mixers;
1713
info->numcards = oss_num_cards;
1719
case SNDCTL_MIX_NRMIX:
1720
return *arg = num_mixers;
1723
case SNDCTL_MIX_NREXT: /* Return # of mixer extensions for device */
1728
if (val < 0 || val >= num_mixers)
1730
if (mixer_devs[val] == NULL || mixer_devs[val]->unloaded
1731
|| !mixer_devs[val]->enabled)
1738
return *arg = mixer_devs[val]->nr_ext;
1741
case SNDCTL_MIX_EXTINFO:
1742
return oss_mixer_ext_info ((oss_mixext *) arg);
1745
case SNDCTL_MIX_ENUMINFO:
1746
return mixer_ext_get_enuminfo ((oss_mixer_enuminfo *) arg);
1749
case SNDCTL_MIX_DESCRIPTION:
1750
return mixer_ext_get_description ((oss_mixer_enuminfo *) arg);
1753
case SNDCTL_MIX_READ:
1754
return mixer_ext_read ((oss_mixer_value *) arg);
1757
case SNDCTL_MIX_WRITE:
1758
return mixer_ext_write ((oss_mixer_value *) arg);
1761
case OSS_GETVERSION:
1762
return *arg = OSS_VERSION;
1765
case SNDCTL_AUDIOINFO:
1766
case SNDCTL_AUDIOINFO_EX:
1769
oss_audioinfo *info = (oss_audioinfo *) arg;
1776
if (dev == -1) /* Request for the current device */
1778
oss_audio_set_error (orig_dev, E_PLAY,
1780
"SNDCTL_AUDIOINFO called with dev=-1.."),
1784
* Applications that try to obtain audio device information about
1785
* the current device should call SNDCTL_ENGINEINFO instead of
1788
* Audio file descriptors returned by open(2) are bound
1789
* directly to specific audio engine instead of the
1795
if (dev < 0 || dev >= num_audio_devfiles)
1800
if (audio_devfiles[dev] == NULL)
1807
dev = audio_devfiles[dev]->engine_num; /* Get the engine number */
1808
if (cmd == SNDCTL_AUDIOINFO && info->dev != -1)
1811
return get_engineinfo (dev, info, combine_slaves);
1815
case SNDCTL_ENGINEINFO:
1818
oss_audioinfo *info = (oss_audioinfo *) arg;
1825
if (dev == -1) /* Request for the current device */
1829
case OSS_DEV_DSP_ENGINE:
1834
cmn_err(CE_WARN, "Unrecognized device class %d for dev %d\n", class, orig_dev);
1838
if (dev < 0 || dev >= num_audio_engines)
1843
return get_engineinfo (dev, info, 0);
1847
#ifdef CONFIG_OSS_MIDI
1848
case SNDCTL_MIDIINFO:
1851
oss_native_word flags;
1852
extern int oss_num_midi_clients; /* midi.c */
1854
oss_midi_info *info = (oss_midi_info *) arg;
1859
if (dev == -1) /* Request for the current device */
1864
* Figure out the HW device connected to this client (orig_dev).
1867
if (dev < 0 || dev >= oss_num_midi_clients)
1869
if (oss_midi_clients[dev]->mididev == NULL)
1870
return OSS_EBUSY; /* No binding established (yet) */
1871
dev = oss_midi_clients[dev]->mididev->dev;
1878
if (dev < 0 || dev >= num_mididevs)
1883
memset ((char *) info, 0, sizeof (*info));
1885
mdev = midi_devs[dev];
1886
MUTEX_ENTER_IRQDISABLE (mdev->mutex, flags);
1888
strcpy (info->name, mdev->name);
1889
strcpy (info->handle, mdev->handle);
1890
info->pid = mdev->pid;
1891
info->busy = mdev->open_mode;
1893
strncpy (info->cmd, mdev->cmd, sizeof (info->cmd));
1894
info->cmd[sizeof (info->cmd) - 1] = 0;
1895
info->magic = mdev->magic;
1896
info->card_number = mdev->card_number;
1897
strcpy (info->devnode, mdev->devnode);
1898
info->legacy_device = mdev->real_dev;
1899
info->port_number = mdev->port_number;
1900
info->enabled = mdev->enabled;
1901
info->flags = mdev->flags;
1902
info->caps = mdev->caps;
1903
info->latency = mdev->latency;
1904
if (!(info->caps & MIDI_CAP_INOUT))
1905
info->caps |= MIDI_CAP_INOUT;
1906
if (mdev->flags & MFLAG_VIRTUAL)
1907
info->caps |= MIDI_CAP_VIRTUAL;
1908
if (mdev->flags & MFLAG_CLIENT)
1909
info->caps |= MIDI_CAP_CLIENT;
1910
if (mdev->flags & MFLAG_SERVER)
1911
info->caps |= MIDI_CAP_SERVER;
1912
if (mdev->flags & MFLAG_INTERNAL)
1913
info->caps |= MIDI_CAP_INTERNAL;
1914
if (mdev->flags & MFLAG_EXTERNAL)
1915
info->caps |= MIDI_CAP_EXTERNAL;
1916
if (mdev->flags & MFLAG_MTC)
1917
info->caps |= MIDI_CAP_MTC;
1918
if (midi_devs[dev]->enabled && !midi_devs[dev]->unloaded)
1919
if (midi_devs[dev]->d->ioctl)
1921
midi_devs[dev]->d->ioctl (dev, SNDCTL_GETSONG,
1922
(ioctl_arg) info->song_name);
1923
midi_devs[dev]->d->ioctl (dev, SNDCTL_GETLABEL,
1924
(ioctl_arg) info->label);
1926
if (*info->label == 0)
1928
strncpy (info->label, info->cmd, sizeof (info->label));
1929
info->label[sizeof (info->label) - 1] = 0;
1931
MUTEX_EXIT_IRQRESTORE (mdev->mutex, flags);
1937
case SNDCTL_CARDINFO:
1941
oss_card_info *info = (oss_card_info *) arg;
1944
if (card < 0 || card >= oss_num_cards)
1949
memset ((char *) info, 0, sizeof (*info));
1950
if ((err = oss_get_cardinfo (card, info)) < 0)
1957
case SNDCTL_MIXERINFO:
1961
oss_mixerinfo *info = (oss_mixerinfo *) arg;
1962
mixer_operations_t *mdev;
1966
if (dev == -1) /* Request for the current device */
1977
if (dev < 0 || dev >= num_mixers)
1982
if (mixer_devs[dev] == NULL)
1985
memset ((char *) info, 0, sizeof (*info));
1988
mdev = mixer_devs[dev];
1990
strncpy (info->name, mdev->name, sizeof (info->name));
1991
info->name[sizeof (info->name) - 1] = '\0';
1992
strcpy (info->id, mdev->id);
1993
strcpy (info->handle, mdev->handle);
1994
info->card_number = mdev->card_number;
1995
info->port_number = mdev->port_number;
1996
info->enabled = (mdev->enabled && !mdev->unloaded);
1997
info->magic = mdev->magic;
1998
info->caps = mdev->caps;
1999
info->flags = mdev->flags;
2000
info->modify_counter = mdev->modify_counter;
2001
info->nrext = mdev->nr_ext;
2002
info->priority = mdev->priority;
2003
strcpy (info->devnode, mdev->devnode);
2004
info->legacy_device = mdev->real_dev;
2009
case OSSCTL_RENUM_AUDIODEVS:
2011
oss_renumber_t *r = (oss_renumber_t *) arg;
2014
#ifdef GET_PROCESS_UID
2015
if (GET_PROCESS_UID () != 0) /* Not root */
2019
if (r->n != num_audio_devfiles) /* Wrong map size? */
2021
cmn_err (CE_NOTE, "Legacy audio map size mismatch %d/%d\n",
2022
r->n, num_audio_devfiles);
2026
for (i = 0; i < r->n; i++)
2028
adev_p adev = audio_devfiles[i];
2030
if (r->map[i] >= HARD_MAX_AUDIO_DEVFILES) /* May be unnecessary check */
2036
adev->real_dev = r->map[i];
2042
case OSSCTL_RENUM_MIXERDEVS:
2044
oss_renumber_t *r = (oss_renumber_t *) arg;
2047
#ifdef GET_PROCESS_UID
2048
if (GET_PROCESS_UID () != 0) /* Not root */
2052
if (r->n != num_mixers) /* Wrong map size? */
2055
for (i = 0; i < r->n; i++)
2057
mixdev_p mdev = mixer_devs[i];
2059
if (r->map[i] >= HARD_MAX_AUDIO_DEVFILES) /* May be unnecessary check */
2062
mdev->real_dev = r->map[i];
2068
case OSSCTL_RENUM_MIDIDEVS:
2070
oss_renumber_t *r = (oss_renumber_t *) arg;
2073
#ifdef GET_PROCESS_UID
2074
if (GET_PROCESS_UID () != 0) /* Not root */
2078
if (r->n != num_mididevs) /* Wrong map size? */
2081
for (i = 0; i < r->n; i++)
2083
mididev_p mdev = midi_devs[i];
2085
if (r->map[i] >= HARD_MAX_AUDIO_DEVFILES) /* May be unnecessary check */
2088
mdev->real_dev = r->map[i];
2094
#ifdef CONFIG_OSS_VMIX
2095
case VMIXCTL_ATTACH:
2096
#ifdef GET_PROCESS_UID
2097
if (GET_PROCESS_UID () != 0) /* Not root */
2100
return vmixctl_attach((vmixctl_attach_t*)arg);
2103
case VMIXCTL_DETACH:
2104
#ifdef GET_PROCESS_UID
2105
if (GET_PROCESS_UID () != 0) /* Not root */
2108
return vmixctl_detach((vmixctl_attach_t*)arg);
2112
#ifdef GET_PROCESS_UID
2113
if (GET_PROCESS_UID () != 0) /* Not root */
2116
return vmixctl_rate((vmixctl_rate_t*)arg);
2120
#ifdef GET_PROCESS_UID
2121
if (GET_PROCESS_UID () != 0) /* Not root */
2124
return vmixctl_map_channels((vmixctl_map_t *)arg);
2131
* These calls are obsolete and disabled in current OSS version.
2133
case OSSCTL_GET_REROUTE:
2135
oss_reroute_t *r = (oss_reroute_t *) arg;
2137
#ifdef GET_PROCESS_UID
2138
if (GET_PROCESS_UID () != 0) /* Not root */
2147
memcpy (&r->devlist, &dspinlist, sizeof (oss_devlist_t));
2151
#ifdef MANAGE_DEV_DSP
2153
oss_combine_write_lists ();
2156
memcpy (&r->devlist, &dspoutlist, sizeof (oss_devlist_t));
2159
case OPEN_WRITE | OPEN_READ:
2160
memcpy (&r->devlist, &dspinoutlist, sizeof (oss_devlist_t));
2171
case OSSCTL_SET_REROUTE:
2173
oss_reroute_t *r = (oss_reroute_t *) arg;
2176
#ifdef GET_PROCESS_UID
2177
if (GET_PROCESS_UID () != 0) /* Not root */
2181
for (i = 0; i < r->devlist.ndevs; i++)
2183
if ((d = r->devlist.devices[i]) < 0 || d >= num_audio_devfiles)
2190
/* Refuse if number of devices has changed */
2191
if (!check_list (&r->devlist, &dspinlist))
2195
memcpy (&dspinlist, &r->devlist, sizeof (oss_devlist_t));
2199
#ifdef MANAGE_DEV_DSP
2201
oss_combine_write_lists ();
2204
/* Refuse if number of devices has changed */
2205
if (!check_list (&r->devlist, &dspoutlist))
2209
memcpy (&dspoutlist, &r->devlist, sizeof (oss_devlist_t));
2210
dspoutlist2.ndevs = 0;
2213
case OPEN_WRITE | OPEN_READ:
2214
/* Refuse if number of devices has changed */
2215
if (!check_list (&r->devlist, &dspinoutlist))
2219
memcpy (&dspinoutlist, &r->devlist, sizeof (oss_devlist_t));
2230
#ifdef APPLIST_SUPPORT
2231
case OSSCTL_RESET_APPLIST:
2232
#ifdef GET_PROCESS_UID
2233
if (GET_PROCESS_UID () != 0) /* Not root */
2237
oss_applist_size = 0;
2241
case OSSCTL_ADD_APPLIST:
2243
app_routing_t *def, *parm = (app_routing_t *) arg;
2245
#ifdef GET_PROCESS_UID
2246
if (GET_PROCESS_UID () != 0) /* Not root */
2250
if (oss_applist_size >= APPLIST_SIZE)
2253
if (parm->dev < -1 || parm->dev >= num_audio_devfiles)
2256
def = &oss_applist[oss_applist_size];
2258
memset (def, 0, sizeof (*def));
2259
strcpy (def->name, parm->name);
2260
def->mode = parm->mode & (OPEN_READ | OPEN_WRITE);
2261
def->dev = parm->dev;
2262
def->open_flags = parm->open_flags;
2272
if (mixer_devs[orig_dev]->d->ioctl != NULL)
2273
return mixer_devs[orig_dev]->d->ioctl (orig_dev, -1, cmd, arg);
2282
oss_mixer_open (int dev, int dev_type, struct fileinfo *file, int recursive,
2283
int open_flags, int *newdev)
2286
* Permit opening nonexistent mixer so that certain mixer ioctl calls
2287
* can be called. Other code must check that the devices really exist
2288
* before permitting the calls.
2290
if (dev >= 0 && dev < num_mixers)
2293
if (mixer_devs == NULL)
2296
if (mixer_devs[dev]->unloaded)
2299
if (!mixer_devs[dev]->enabled)
2307
oss_mixer_release (int dev, struct fileinfo *file)
2313
oss_mixer_ioctl (int dev, struct fileinfo *bogus,
2314
unsigned int cmd, ioctl_arg arg)
2318
if (cmd == OSS_GETVERSION)
2319
return *arg = OSS_VERSION;
2322
* Handle SNDCTL_SYSINFO/CARDINFO/etc even if there are no mixer devices in the
2327
case OSS_GETVERSION:
2328
case SNDCTL_SYSINFO:
2329
case SNDCTL_CARDINFO:
2330
case SNDCTL_MIXERINFO:
2331
case SNDCTL_MIDIINFO:
2332
case SNDCTL_AUDIOINFO:
2333
case SNDCTL_AUDIOINFO_EX:
2334
case SNDCTL_ENGINEINFO:
2335
case OSSCTL_RENUM_AUDIODEVS:
2336
case OSSCTL_RENUM_MIXERDEVS:
2337
case OSSCTL_RENUM_MIDIDEVS:
2338
case SNDCTL_MIX_EXTINFO:
2339
case SNDCTL_MIX_ENUMINFO:
2340
case SNDCTL_MIX_READ:
2341
case SNDCTL_MIX_WRITE:
2342
case SNDCTL_MIX_NRMIX:
2343
case SNDCTL_MIX_MATRIX_WRITE:
2344
case SNDCTL_MIX_MATRIX_READ:
2345
case VMIXCTL_ATTACH:
2346
case VMIXCTL_DETACH:
2348
return oss_mixer_ext (dev, OSS_DEV_MIXER, cmd, arg);
2352
if (dev < 0 || dev >= num_mixers)
2357
if (mixer_devs == NULL)
2362
if (!mixer_devs[dev]->enabled || mixer_devs[dev]->unloaded)
2367
if ((ret = oss_legacy_mixer_ioctl (dev, -1, cmd, arg)) != OSS_EINVAL)
2372
return oss_mixer_ext (dev, OSS_DEV_MIXER, cmd, arg);
2377
static char timing_buf[256 * 1024] = { 0 }, *timing_ptr = timing_buf;
2378
static int timing_prev_time = 0;
2379
int timing_flags = 0x7fffffff;
2381
#define TM_SCALE 256
2382
static oss_timing_timer_func tmfunc = NULL;
2383
static void *tmfunc_arg = NULL;
2386
timing_install_timer (oss_timing_timer_func f, void *x)
2393
oss_do_timing_ (char *txt)
2395
int l = strlen (txt) + 20;
2396
oss_native_word flags;
2397
oss_native_word this_time;
2399
if (!timing_is_active) /* Nobody is listening */
2402
MUTEX_ENTER_IRQDISABLE (oss_timing_mutex, flags);
2403
if ((long) (&timing_buf[sizeof (timing_buf)] - timing_ptr - 8) <= l)
2405
MUTEX_EXIT_IRQRESTORE (oss_timing_mutex, flags);
2411
this_time = tmfunc (tmfunc_arg);
2415
this_time = 0; /* TODO: Get the actual audio pointer */
2418
this_time = GET_JIFFIES ();
2421
sprintf (timing_ptr, "%ld/%d: %s\n", this_time,
2422
this_time - timing_prev_time, txt);
2423
l = strlen (timing_ptr);
2425
timing_prev_time = this_time;
2426
MUTEX_EXIT_IRQRESTORE (oss_timing_mutex, flags);
2431
oss_native_word sum;
2432
oss_native_word open_time;
2436
static timing_entry timing_bins[DF_NRBINS];
2437
static oss_native_word timing_start = 0;
2439
static char *bin_names[DF_NRBINS] = {
2457
timing_start = tmfunc (tmfunc_arg) / TM_SCALE;
2459
for (i = 0; i < DF_NRBINS; i++)
2461
timing_bins[i].sum = 0;
2462
timing_bins[i].open_time = 0xffffffff;
2472
oss_native_word t, sum, pc;
2476
t = tmfunc (tmfunc_arg) / TM_SCALE - timing_start;
2478
sprintf (tmp, "Timing close, elapsed=%d", t);
2479
oss_do_timing2 (DFLAG_PROFILE, tmp);
2483
for (i = 0; i < DF_NRBINS; i++)
2485
sum += timing_bins[i].sum;
2486
pc = (timing_bins[i].sum * 1000) / t;
2487
sprintf (tmp, "Bin %s: %d/%d (%d.%d%%)", bin_names[i],
2488
timing_bins[i].sum, pc, pc / 10, pc % 10);
2489
oss_do_timing2 (DFLAG_PROFILE, tmp);
2492
/* sum = sum-timing_bins[DF_SLEEPWRITE].sum-timing_bins[DF_SLEEPREAD].sum; */
2493
pc = (sum * 10000) / t;
2495
sprintf (tmp, "OSS Total: %d (%d.%d%%)", sum, pc / 100, pc % 100);
2496
oss_do_timing2 (DFLAG_PROFILE, tmp);
2500
oss_timing_enter (int bin)
2505
timing_bins[bin].open_time = tmfunc (tmfunc_arg) / TM_SCALE;
2509
oss_timing_leave (int bin)
2516
if (timing_bins[bin].open_time >= 0xfffffffe)
2519
t = tmfunc (tmfunc_arg) / TM_SCALE - timing_bins[bin].open_time;
2520
timing_bins[bin].sum += t;
2521
timing_bins[bin].open_time = 0xfffffffe;
2525
oss_do_timing (char *txt)
2527
if (!timing_is_active) /* Nobody is listening */
2530
if (timing_flags & DFLAG_ALL)
2531
oss_do_timing_ (txt);
2535
oss_do_timing2 (int mask, char *txt)
2537
if (!timing_is_active) /* Nobody is listening */
2540
if ((timing_flags & DFLAG_ALL) || (timing_flags & mask))
2541
oss_do_timing_ (txt);
2545
oss_timing_printf (char *s, ...)
2547
char tmp[1024], *a[6];
2551
if (!timing_is_active) /* Nobody is listening */
2556
for (i = 0; i < strlen (s); i++)
2560
for (i = 0; i < n && i < 6; i++)
2561
a[i] = va_arg (ap, char *);
2563
for (i = n; i < 6; i++)
2566
sprintf (tmp, s, a[0], a[1], a[2], a[3], a[4], a[5], NULL,
2574
timing_read (int dev, struct fileinfo *file, uio_t * buf, int count)
2577
* Return at most 'count' bytes from the status_buf.
2580
oss_native_word flags;
2582
timing_is_active = 1;
2584
MUTEX_ENTER_IRQDISABLE (oss_timing_mutex, flags);
2586
l = timing_ptr - timing_buf;
2589
MUTEX_EXIT_IRQRESTORE (oss_timing_mutex, flags);
2596
timing_ptr = timing_buf;
2598
MUTEX_EXIT_IRQRESTORE (oss_timing_mutex, flags);
2600
if (uiomove (timing_buf, l, UIO_READ, buf) != 0)
2601
cmn_err (CE_WARN, "audio: uiomove(UIO_READ) failed\n");
2612
oss_timing_enter (int bin)
2618
oss_timing_leave (int bin)
2624
oss_do_timing (char *txt)
2630
oss_do_timing2 (int mask, char *txt)
2636
oss_timing_printf (char *s, ...)
2641
static oss_cdev_drv_t mixer_cdev_drv = {
2654
oss_install_mixer (int vers,
2655
oss_device_t * osdev,
2656
oss_device_t * master_osdev,
2658
mixer_driver_t * driver, int driver_size, void *devc)
2660
mixer_operations_t *op = NULL;
2666
if (master_osdev == NULL)
2667
master_osdev = osdev;
2669
if (mixer_devs == NULL)
2671
mixer_devs = PMALLOC (osdev, sizeof (mixdev_p) * MAX_MIXER_DEV);
2672
memset (mixer_devs, 0, sizeof (mixdev_p) * MAX_MIXER_DEV);
2673
mixer_devs_p = mixer_devs;
2676
if (num_mixers >= MAX_MIXER_DEV - 1)
2679
cmn_err (CE_WARN, "Too many mixer devices %d/%d (%s)\n",
2680
num_mixers, MAX_MIXER_DEV, name);
2682
* In some special situations a driver may keep trying to install a mixer
2683
* in infinite loop if the request fails. Stop this by panicking after
2684
* this has continued for more than 50 times. In this case we can get an
2685
* error message instead of having the system to lock up foreever.
2688
cmn_err (CE_PANIC, "Killing runaway system.\n");
2692
if (vers != OSS_MIXER_DRIVER_VERSION)
2694
cmn_err (CE_WARN, "Incompatible mixer driver for %s\n", name);
2698
if (driver_size > sizeof (mixer_driver_t))
2699
driver_size = sizeof (mixer_driver_t);
2702
* Check if this device was earlier unloaded and now returning back.
2705
for (i = 0; i < num_mixers; i++)
2707
if (mixer_devs[i]->unloaded
2708
&& mixer_devs[i]->os_id == oss_get_osid (osdev))
2716
if ((d = PMALLOC (osdev, sizeof (*d))) == NULL)
2718
cmn_err (CE_WARN, "Can't allocate mixer driver for (%s)\n", name);
2724
op = PMALLOC (osdev, sizeof (mixer_operations_t));
2727
cmn_err (CE_WARN, "Can't allocate mixer driver for (%s)\n", name);
2731
memset ((char *) op, 0, sizeof (mixer_operations_t));
2733
sprintf (handle, "%s-mx%02d", osdev->handle, osdev->num_mixerdevs+1);
2734
op->port_number = osdev->num_mixerdevs++;
2738
strcpy (handle, op->handle); /* Preserve the previous handle */
2741
memset ((char *) d, 0, sizeof (mixer_driver_t));
2742
memcpy ((char *) d, (char *) driver, driver_size);
2743
strcpy (op->handle, handle);
2744
strcpy (op->id, osdev->nick);
2747
strncpy (op->name, name, sizeof (op->name));
2748
op->name[sizeof (op->name) - 1] = 0;
2751
op->os_id = oss_get_osid (osdev);
2752
op->master_osdev = master_osdev;
2754
op->max_ext = op->nr_ext = 0;
2755
op->names_checked = 0;
2756
op->extensions = NULL;
2757
op->timestamp = GET_JIFFIES ();
2758
op->ignore_mask = 0;
2759
op->card_number = osdev->cardnum;
2764
op->priority = 0; /* Normal (low) priority */
2767
if (osdev->first_mixer == -1) /* Not defined yet */
2768
osdev->first_mixer = num;
2770
mixer_devs[num] = op;
2772
* Create the device node
2778
#ifdef NEW_DEVICE_NAMING
2779
# ifdef USE_DEVICE_SUBDIRS
2780
sprintf (name, "oss/%s/mix%d", osdev->nick, osdev->num_mixerdevs - 1);
2782
sprintf (name, "%s_mix%d", osdev->nick, osdev->num_mixerdevs - 1);
2785
sprintf (name, "mixer%d", num);
2787
oss_install_chrdev (osdev, name, OSS_DEV_MIXER, num, &mixer_cdev_drv, 0);
2788
sprintf (op->devnode, "/dev/%s", name);
2792
* Moved to install_dev_mixer()
2796
oss_install_chrdev (osdev, "mixer", OSS_DEV_MIXER, num,
2797
&mixer_cdev_drv, 0);
2806
install_dev_mixer (oss_device_t * osdev)
2809
* Install the default mixer node if necessary
2811
oss_install_chrdev (osdev, "mixer", OSS_DEV_MIXER, 0, &mixer_cdev_drv, 0);