📄 mixer_oss.c
字号:
return put_user(tmp, (int *)arg) ? -EFAULT : 0; } else if (cmd & IOC_OUT) { tmp = snd_mixer_oss_get_volume(fmixer, cmd & 0xff); if (tmp < 0) return tmp; return put_user(tmp, (int *)arg) ? -EFAULT : 0; } return -ENXIO;}int snd_mixer_oss_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ return snd_mixer_oss_ioctl1((snd_mixer_oss_file_t *) file->private_data, cmd, arg);}int snd_mixer_oss_ioctl_card(snd_card_t *card, unsigned int cmd, unsigned long arg){ snd_mixer_oss_file_t fmixer; snd_assert(card != NULL, return -ENXIO); if (card->mixer_oss == NULL) return -ENXIO; memset(&fmixer, 0, sizeof(fmixer)); fmixer.card = card; fmixer.mixer = card->mixer_oss; return snd_mixer_oss_ioctl1(&fmixer, cmd, arg);}/* * REGISTRATION PART */static struct file_operations snd_mixer_oss_f_ops ={#ifndef LINUX_2_2 owner: THIS_MODULE,#endif open: snd_mixer_oss_open, release: snd_mixer_oss_release, ioctl: snd_mixer_oss_ioctl,};static snd_minor_t snd_mixer_oss_reg ={ comment: "mixer", f_ops: &snd_mixer_oss_f_ops,};/* * utilities */static long snd_mixer_oss_conv(long val, long omin, long omax, long nmin, long nmax){ long orange = omax - omin, nrange = nmax - nmin; if (orange == 0) return 0; return ((nrange * (val - omin)) + (orange / 2)) / orange + nmin;}static long snd_mixer_oss_conv1(long val, long min, long max, int *old){ if (val == snd_mixer_oss_conv(*old, 0, 100, min, max)) return *old; return snd_mixer_oss_conv(val, min, max, 0, 100);}static long snd_mixer_oss_conv2(long val, long min, long max){ return snd_mixer_oss_conv(val, 0, 100, min, max);}#if 0static void snd_mixer_oss_recsrce_set(snd_card_t *card, int slot){ snd_mixer_oss_t *mixer = card->mixer_oss; if (mixer) mixer->mask_recsrc |= 1 << slot;}static int snd_mixer_oss_recsrce_get(snd_card_t *card, int slot){ snd_mixer_oss_t *mixer = card->mixer_oss; if (mixer && (mixer->mask_recsrc & (1 << slot))) return 1; return 0;}#endif#define SNDRV_MIXER_OSS_SIGNATURE 0x65999250#define SNDRV_MIXER_OSS_ITEM_GLOBAL 0#define SNDRV_MIXER_OSS_ITEM_GSWITCH 1#define SNDRV_MIXER_OSS_ITEM_GROUTE 2#define SNDRV_MIXER_OSS_ITEM_GVOLUME 3#define SNDRV_MIXER_OSS_ITEM_PSWITCH 4#define SNDRV_MIXER_OSS_ITEM_PROUTE 5#define SNDRV_MIXER_OSS_ITEM_PVOLUME 6#define SNDRV_MIXER_OSS_ITEM_CSWITCH 7#define SNDRV_MIXER_OSS_ITEM_CROUTE 8#define SNDRV_MIXER_OSS_ITEM_CVOLUME 9#define SNDRV_MIXER_OSS_ITEM_CAPTURE 10#define SNDRV_MIXER_OSS_ITEM_COUNT 11#define SNDRV_MIXER_OSS_PRESENT_GLOBAL (1<<0)#define SNDRV_MIXER_OSS_PRESENT_GSWITCH (1<<1)#define SNDRV_MIXER_OSS_PRESENT_GROUTE (1<<2)#define SNDRV_MIXER_OSS_PRESENT_GVOLUME (1<<3)#define SNDRV_MIXER_OSS_PRESENT_PSWITCH (1<<4)#define SNDRV_MIXER_OSS_PRESENT_PROUTE (1<<5)#define SNDRV_MIXER_OSS_PRESENT_PVOLUME (1<<6)#define SNDRV_MIXER_OSS_PRESENT_CSWITCH (1<<7)#define SNDRV_MIXER_OSS_PRESENT_CROUTE (1<<8)#define SNDRV_MIXER_OSS_PRESENT_CVOLUME (1<<9)#define SNDRV_MIXER_OSS_PRESENT_CAPTURE (1<<10)struct slot { unsigned int signature; unsigned int present; int channels; snd_kcontrol_t *kcontrol[SNDRV_MIXER_OSS_ITEM_COUNT]; unsigned int capture_item;};static snd_kcontrol_t *snd_mixer_oss_test_id(snd_mixer_oss_t *mixer, const char *name, int index){ snd_card_t * card = mixer->card; snd_ctl_elem_id_t id; memset(&id, 0, sizeof(id)); id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; strcpy(id.name, name); id.index = index; return snd_ctl_find_id(card, &id);}static void snd_mixer_oss_get_volume1_vol(snd_mixer_oss_file_t *fmixer, snd_mixer_oss_slot_t *pslot, snd_kcontrol_t *kctl, int *left, int *right){ snd_ctl_elem_info_t uinfo; snd_ctl_elem_value_t uctl; snd_runtime_check(kctl != NULL, return); memset(&uinfo, 0, sizeof(uinfo)); memset(&uctl, 0, sizeof(uctl)); snd_runtime_check(!kctl->info(kctl, &uinfo), return); snd_runtime_check(!kctl->get(kctl, &uctl), return); snd_runtime_check(uinfo.type != SNDRV_CTL_ELEM_TYPE_BOOLEAN || uinfo.value.integer.min != 0 || uinfo.value.integer.max != 1, return); *left = snd_mixer_oss_conv1(uctl.value.integer.value[0], uinfo.value.integer.min, uinfo.value.integer.max, &fmixer->volume[pslot->number][0]); if (uinfo.count > 1) *right = snd_mixer_oss_conv1(uctl.value.integer.value[1], uinfo.value.integer.min, uinfo.value.integer.max, &fmixer->volume[pslot->number][1]);}static void snd_mixer_oss_get_volume1_sw(snd_mixer_oss_file_t *fmixer, snd_mixer_oss_slot_t *pslot, snd_kcontrol_t *kctl, int *left, int *right, int route){ snd_ctl_elem_info_t uinfo; snd_ctl_elem_value_t uctl; snd_runtime_check(kctl != NULL, return); memset(&uinfo, 0, sizeof(uinfo)); memset(&uctl, 0, sizeof(uctl)); snd_runtime_check(!kctl->info(kctl, &uinfo), return); snd_runtime_check(!kctl->get(kctl, &uctl), return); if (!uctl.value.integer.value[0]) { *left = 0; if (uinfo.count == 1) *right = 0; } if (uinfo.count > 1 && !uctl.value.integer.value[route ? 3 : 1]) *right = 0;}static int snd_mixer_oss_get_volume1(snd_mixer_oss_file_t *fmixer, snd_mixer_oss_slot_t *pslot, int *left, int *right){ snd_card_t *card = fmixer->card; struct slot *slot = (struct slot *)pslot->private_data; *left = *right = 100; read_lock(&card->control_rwlock); if (slot->present & SNDRV_MIXER_OSS_PRESENT_PVOLUME) { snd_mixer_oss_get_volume1_vol(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_PVOLUME], left, right); } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GVOLUME) { snd_mixer_oss_get_volume1_vol(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_GVOLUME], left, right); } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GLOBAL) { snd_mixer_oss_get_volume1_vol(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_GLOBAL], left, right); } if (slot->present & SNDRV_MIXER_OSS_PRESENT_PSWITCH) { snd_mixer_oss_get_volume1_sw(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_PSWITCH], left, right, 0); } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GSWITCH) { snd_mixer_oss_get_volume1_sw(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_GSWITCH], left, right, 0); } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_PROUTE) { snd_mixer_oss_get_volume1_sw(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_PROUTE], left, right, 1); } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GROUTE) { snd_mixer_oss_get_volume1_sw(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_GROUTE], left, right, 1); } read_unlock(&card->control_rwlock); return 0;}static void snd_mixer_oss_put_volume1_vol(snd_mixer_oss_file_t *fmixer, snd_mixer_oss_slot_t *pslot, snd_kcontrol_t *kctl, int left, int right){ snd_ctl_elem_info_t uinfo; snd_ctl_elem_value_t uctl; int res; snd_runtime_check(kctl != NULL, return); memset(&uinfo, 0, sizeof(uinfo)); memset(&uctl, 0, sizeof(uctl)); snd_runtime_check(!kctl->info(kctl, &uinfo), return); snd_runtime_check(uinfo.type != SNDRV_CTL_ELEM_TYPE_BOOLEAN || uinfo.value.integer.min != 0 || uinfo.value.integer.max != 1, return); uctl.value.integer.value[0] = snd_mixer_oss_conv2(left, uinfo.value.integer.min, uinfo.value.integer.max); if (uinfo.count > 1) uctl.value.integer.value[1] = snd_mixer_oss_conv2(right, uinfo.value.integer.min, uinfo.value.integer.max); snd_runtime_check((res = kctl->put(kctl, &uctl)) >= 0, return); if (res > 0) snd_ctl_notify(fmixer->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);}static void snd_mixer_oss_put_volume1_sw(snd_mixer_oss_file_t *fmixer, snd_mixer_oss_slot_t *pslot, snd_kcontrol_t *kctl, int left, int right, int route){ snd_ctl_elem_info_t uinfo; snd_ctl_elem_value_t uctl; int res; snd_runtime_check(kctl != NULL, return); memset(&uinfo, 0, sizeof(uinfo)); memset(&uctl, 0, sizeof(uctl)); snd_runtime_check(!kctl->info(kctl, &uinfo), return); if (uinfo.count > 1) { uctl.value.integer.value[0] = left > 0 ? 1 : 0; uctl.value.integer.value[route ? 3 : 1] = right > 0 ? 1 : 0; if (route) { uctl.value.integer.value[1] = uctl.value.integer.value[2] = 0; } } else { uctl.value.integer.value[0] = (left > 0 || right > 0) ? 1 : 0; } snd_runtime_check((res = kctl->put(kctl, &uctl)) >= 0, return); if (res > 0) snd_ctl_notify(fmixer->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);}static int snd_mixer_oss_put_volume1(snd_mixer_oss_file_t *fmixer, snd_mixer_oss_slot_t *pslot, int left, int right){ snd_card_t *card = fmixer->card; struct slot *slot = (struct slot *)pslot->private_data; read_lock(&card->control_rwlock); if (slot->present & SNDRV_MIXER_OSS_PRESENT_PVOLUME) { snd_mixer_oss_put_volume1_vol(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_PVOLUME], left, right); if (slot->present & SNDRV_MIXER_OSS_PRESENT_CVOLUME) snd_mixer_oss_put_volume1_vol(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_CVOLUME], left, right); } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GVOLUME) { snd_mixer_oss_put_volume1_vol(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_GVOLUME], left, right); } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GLOBAL) { snd_mixer_oss_put_volume1_vol(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_GLOBAL], left, right); } if (left || right) { if (slot->present & SNDRV_MIXER_OSS_PRESENT_PSWITCH) snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_PSWITCH], left, right, 0); if (slot->present & SNDRV_MIXER_OSS_PRESENT_GSWITCH) snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_GSWITCH], left, right, 0); if (slot->present & SNDRV_MIXER_OSS_PRESENT_PROUTE) snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_PROUTE], left, right, 1); if (slot->present & SNDRV_MIXER_OSS_PRESENT_GROUTE) snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_GROUTE], left, right, 1); } else { if (slot->present & SNDRV_MIXER_OSS_PRESENT_PSWITCH) { snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_PSWITCH], left, right, 0); } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GSWITCH) { snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_GSWITCH], left, right, 0); } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_PROUTE) { snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_PROUTE], left, right, 1); } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GROUTE) { snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_GROUTE], left, right, 1); } } read_unlock(&card->control_rwlock); return 0;}static int snd_mixer_oss_get_recsrc1_sw(snd_mixer_oss_file_t *fmixer, snd_mixer_oss_slot_t *pslot, int *active){ snd_card_t *card = fmixer->card; struct slot *slot = (struct slot *)pslot->private_data; int left, right; left = right = 1; read_lock(&card->control_rwlock); snd_mixer_oss_get_volume1_sw(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_CSWITCH], &left, &right, 0); read_unlock(&card->control_rwlock); *active = (left || right) ? 1 : 0; return 0;}static int snd_mixer_oss_get_recsrc1_route(snd_mixer_oss_file_t *fmixer, snd_mixer_oss_slot_t *pslot, int *active){ snd_card_t *card = fmixer->card; struct slot *slot = (struct slot *)pslot->private_data; int left, right; left = right = 1; read_lock(&card->control_rwlock); snd_mixer_oss_get_volume1_sw(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_CROUTE], &left, &right, 1); read_unlock(&card->control_rwlock); *active = (left || right) ? 1 : 0; return 0;}static int snd_mixer_oss_put_recsrc1_sw(snd_mixer_oss_file_t *fmixer, snd_mixer_oss_slot_t *pslot, int active){ snd_card_t *card = fmixer->card; struct slot *slot = (struct slot *)pslot->private_data; read_lock(&card->control_rwlock); snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_CSWITCH], active, active, 0); read_unlock(&card->control_rwlock); return 0;}static int snd_mixer_oss_put_recsrc1_route(snd_mixer_oss_file_t *fmixer, snd_mixer_oss_slot_t *pslot,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -