0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/init.h>
0009 #include <linux/slab.h>
0010 #include <linux/compat.h>
0011 #include <linux/nospec.h>
0012 #include <sound/core.h>
0013 #include <sound/hda_codec.h>
0014 #include "hda_local.h"
0015 #include <sound/hda_hwdep.h>
0016 #include <sound/minors.h>
0017
0018
0019
0020
0021 static int verb_write_ioctl(struct hda_codec *codec,
0022 struct hda_verb_ioctl __user *arg)
0023 {
0024 u32 verb, res;
0025
0026 if (get_user(verb, &arg->verb))
0027 return -EFAULT;
0028 res = snd_hda_codec_read(codec, verb >> 24, 0,
0029 (verb >> 8) & 0xffff, verb & 0xff);
0030 if (put_user(res, &arg->res))
0031 return -EFAULT;
0032 return 0;
0033 }
0034
0035 static int get_wcap_ioctl(struct hda_codec *codec,
0036 struct hda_verb_ioctl __user *arg)
0037 {
0038 u32 verb, res;
0039
0040 if (get_user(verb, &arg->verb))
0041 return -EFAULT;
0042
0043 verb >>= 24;
0044 if (verb < codec->core.start_nid ||
0045 verb >= codec->core.start_nid + codec->core.num_nodes) {
0046 res = 0;
0047 } else {
0048 verb -= codec->core.start_nid;
0049 verb = array_index_nospec(verb, codec->core.num_nodes);
0050 res = codec->wcaps[verb];
0051 }
0052 if (put_user(res, &arg->res))
0053 return -EFAULT;
0054 return 0;
0055 }
0056
0057
0058
0059
0060 static int hda_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
0061 unsigned int cmd, unsigned long arg)
0062 {
0063 struct hda_codec *codec = hw->private_data;
0064 void __user *argp = (void __user *)arg;
0065
0066 switch (cmd) {
0067 case HDA_IOCTL_PVERSION:
0068 return put_user(HDA_HWDEP_VERSION, (int __user *)argp);
0069 case HDA_IOCTL_VERB_WRITE:
0070 return verb_write_ioctl(codec, argp);
0071 case HDA_IOCTL_GET_WCAP:
0072 return get_wcap_ioctl(codec, argp);
0073 }
0074 return -ENOIOCTLCMD;
0075 }
0076
0077 #ifdef CONFIG_COMPAT
0078 static int hda_hwdep_ioctl_compat(struct snd_hwdep *hw, struct file *file,
0079 unsigned int cmd, unsigned long arg)
0080 {
0081 return hda_hwdep_ioctl(hw, file, cmd, (unsigned long)compat_ptr(arg));
0082 }
0083 #endif
0084
0085 static int hda_hwdep_open(struct snd_hwdep *hw, struct file *file)
0086 {
0087 #ifndef CONFIG_SND_DEBUG_VERBOSE
0088 if (!capable(CAP_SYS_RAWIO))
0089 return -EACCES;
0090 #endif
0091 return 0;
0092 }
0093
0094 int snd_hda_create_hwdep(struct hda_codec *codec)
0095 {
0096 char hwname[16];
0097 struct snd_hwdep *hwdep;
0098 int err;
0099
0100 sprintf(hwname, "HDA Codec %d", codec->addr);
0101 err = snd_hwdep_new(codec->card, hwname, codec->addr, &hwdep);
0102 if (err < 0)
0103 return err;
0104 codec->hwdep = hwdep;
0105 sprintf(hwdep->name, "HDA Codec %d", codec->addr);
0106 hwdep->iface = SNDRV_HWDEP_IFACE_HDA;
0107 hwdep->private_data = codec;
0108 hwdep->exclusive = 1;
0109
0110 hwdep->ops.open = hda_hwdep_open;
0111 hwdep->ops.ioctl = hda_hwdep_ioctl;
0112 #ifdef CONFIG_COMPAT
0113 hwdep->ops.ioctl_compat = hda_hwdep_ioctl_compat;
0114 #endif
0115
0116
0117 hwdep->dev.groups = snd_hda_dev_attr_groups;
0118 dev_set_drvdata(&hwdep->dev, codec);
0119
0120 return 0;
0121 }