* RFC: minimalistic TLV implementation
@ 2006-05-31 13:10 Jaroslav Kysela
2006-06-01 11:25 ` Takashi Iwai
0 siblings, 1 reply; 14+ messages in thread
From: Jaroslav Kysela @ 2006-05-31 13:10 UTC (permalink / raw)
To: ALSA development
Hi,
I've created a minimalistic TLV implemetation for the driver side.
Please, review and comment it. We can add more TLV funcionality in future.
It is essential that user space will handle SNDRV_CTL_TLVT_LEVEL type
immediately (altough it is not used in the kernel space now), otherwise we
cannot group and level TLVs in future.
Jaroslav
diff -r 96e63842ba5d core/control.c
--- a/core/control.c Wed May 31 11:55:17 2006 +0200
+++ b/core/control.c Wed May 31 15:02:38 2006 +0200
@@ -241,6 +241,7 @@ struct snd_kcontrol *snd_ctl_new1(const
kctl.info = ncontrol->info;
kctl.get = ncontrol->get;
kctl.put = ncontrol->put;
+ kctl.tlv = ncontrol->tlv;
kctl.private_value = ncontrol->private_value;
kctl.private_data = private_data;
return snd_ctl_new(&kctl, access);
@@ -1067,6 +1068,44 @@ static int snd_ctl_subscribe_events(stru
return 0;
}
+static int snd_ctl_tlv(struct snd_card *card, struct snd_ctl_tlv __user *_tlv)
+{
+ struct snd_ctl_tlv tlv;
+ struct snd_kcontrol *kctl;
+ unsigned int len;
+ int err = 0;
+
+ if (copy_to_user(&tlv, _tlv, sizeof(tlv)))
+ return -EFAULT;
+ if (tlv.length < sizeof(unsigned int) * 3)
+ return -EINVAL;
+ if (tlv.flags & SNDRV_CTL_TLV_NUMID) {
+ down_read(&card->controls_rwsem);
+ kctl = snd_ctl_find_numid(card, tlv.value);
+ if (kctl == NULL) {
+ err = -ENOENT;
+ goto __kctl_end;
+ }
+ if (kctl->tlv == NULL) {
+ err = -EIO;
+ goto __kctl_end;
+ }
+ len = *((unsigned int *)kctl->tlv);
+ if (tlv.length < len) {
+ err = -ENOMEM;
+ goto __kctl_end;
+ }
+ if (copy_to_user(tlv.ptr, kctl->tlv, len))
+ err = -EFAULT;
+ __kctl_end:
+ up_read(&card->controls_rwsem);
+ } else {
+ /* not implemented */
+ err = -EINVAL;
+ }
+ return err;
+}
+
static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct snd_ctl_file *ctl;
@@ -1086,11 +1125,11 @@ static long snd_ctl_ioctl(struct file *f
case SNDRV_CTL_IOCTL_CARD_INFO:
return snd_ctl_card_info(card, ctl, cmd, argp);
case SNDRV_CTL_IOCTL_ELEM_LIST:
- return snd_ctl_elem_list(ctl->card, argp);
+ return snd_ctl_elem_list(card, argp);
case SNDRV_CTL_IOCTL_ELEM_INFO:
return snd_ctl_elem_info_user(ctl, argp);
case SNDRV_CTL_IOCTL_ELEM_READ:
- return snd_ctl_elem_read_user(ctl->card, argp);
+ return snd_ctl_elem_read_user(card, argp);
case SNDRV_CTL_IOCTL_ELEM_WRITE:
return snd_ctl_elem_write_user(ctl, argp);
case SNDRV_CTL_IOCTL_ELEM_LOCK:
@@ -1105,6 +1144,8 @@ static long snd_ctl_ioctl(struct file *f
return snd_ctl_elem_remove(ctl, argp);
case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
return snd_ctl_subscribe_events(ctl, ip);
+ case SNDRV_CTL_IOCTL_TLV:
+ return snd_ctl_tlv(card, argp);
case SNDRV_CTL_IOCTL_POWER:
return -ENOPROTOOPT;
case SNDRV_CTL_IOCTL_POWER_STATE:
diff -r 96e63842ba5d include/asound.h
--- a/include/asound.h Wed May 31 11:55:17 2006 +0200
+++ b/include/asound.h Wed May 31 15:02:38 2006 +0200
@@ -818,6 +818,26 @@ struct snd_ctl_elem_value {
unsigned char reserved[128-sizeof(struct timespec)];
};
+#define SNDRV_CTL_TLV_NUMID (1<<0) /* value is numid, otherwise request global TLV info */
+
+#define SNDRV_CTL_TLVT_LEVEL 0 /* one level down - group of TLVs */
+#define SNDRV_CTL_TLVT_DB_SCALE 1 /* dB scale */
+
+struct snd_ctl_tlv {
+ unsigned int flags;
+ unsigned int length;
+ unsigned int value;
+ /*
+ * TLV structure is:
+ * unsigned int length
+ * unsigned int type - see SNDRV_CTL_TLVT_*
+ * .... data aligned to sizeof(unsigned int), use
+ * block_length = (length + (sizeof(unsigned int) - 1)) &
+ * ~(sizeof(unsigned int) - 1)) ....
+ */
+ void *ptr;
+};
+
enum {
SNDRV_CTL_IOCTL_PVERSION = _IOR('U', 0x00, int),
SNDRV_CTL_IOCTL_CARD_INFO = _IOR('U', 0x01, struct snd_ctl_card_info),
@@ -831,6 +851,7 @@ enum {
SNDRV_CTL_IOCTL_ELEM_ADD = _IOWR('U', 0x17, struct snd_ctl_elem_info),
SNDRV_CTL_IOCTL_ELEM_REPLACE = _IOWR('U', 0x18, struct snd_ctl_elem_info),
SNDRV_CTL_IOCTL_ELEM_REMOVE = _IOWR('U', 0x19, struct snd_ctl_elem_id),
+ SNDRV_CTL_IOCTL_TLV = _IOWR('U', 0x1a, struct snd_ctl_tlv),
SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE = _IOWR('U', 0x20, int),
SNDRV_CTL_IOCTL_HWDEP_INFO = _IOR('U', 0x21, struct snd_hwdep_info),
SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE = _IOR('U', 0x30, int),
diff -r 96e63842ba5d include/control.h
--- a/include/control.h Wed May 31 11:55:17 2006 +0200
+++ b/include/control.h Wed May 31 15:02:38 2006 +0200
@@ -42,6 +42,7 @@ struct snd_kcontrol_new {
snd_kcontrol_info_t *info;
snd_kcontrol_get_t *get;
snd_kcontrol_put_t *put;
+ unsigned int *tlv;
unsigned long private_value;
};
@@ -58,6 +59,7 @@ struct snd_kcontrol {
snd_kcontrol_info_t *info;
snd_kcontrol_get_t *get;
snd_kcontrol_put_t *put;
+ unsigned int *tlv;
unsigned long private_value;
void *private_data;
void (*private_free)(struct snd_kcontrol *kcontrol);
diff -r 96e63842ba5d pci/ca0106/ca0106_mixer.c
--- a/pci/ca0106/ca0106_mixer.c Wed May 31 11:55:17 2006 +0200
+++ b/pci/ca0106/ca0106_mixer.c Wed May 31 15:02:38 2006 +0200
@@ -70,8 +70,11 @@
#include <sound/pcm.h>
#include <sound/ac97_codec.h>
#include <sound/info.h>
+#include <sound/tlv.h>
#include "ca0106.h"
+
+static DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale, -5150, 75, 1);
static int snd_ca0106_shared_spdif_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
@@ -472,6 +475,7 @@ static int snd_ca0106_i2c_volume_put(str
.info = snd_ca0106_volume_info, \
.get = snd_ca0106_volume_get, \
.put = snd_ca0106_volume_put, \
+ .tlv = snd_ca0106_db_scale, \
.private_value = ((chid) << 8) | (reg) \
}
diff -r 96e63842ba5d include/tlv.h
--- /dev/null Thu Jan 1 00:00:00 1970 +0000
+++ b/include/tlv.h Wed May 31 15:02:38 2006 +0200
@@ -0,0 +1,31 @@
+#ifndef __SOUND_TLV_H
+#define __SOUND_TLV_H
+
+/*
+ * Advanced Linux Sound Architecture - ALSA - Driver
+ * Copyright (c) 2006 by Jaroslav Kysela <perex@suse.cz>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#define DECLARE_TLV_DB_SCALE(name, min, step, mute) \
+unsigned int name[] = { \
+ 4 * sizeof(unsigned int), SNDRV_CTL_TLVT_DB_SCALE, \
+ (min), (step & 0xffff) | (mute ? 0x10000 : 0) \
+}
+
+#endif /* __SOUND_TLV_H */
-----
Jaroslav Kysela <perex@suse.cz>
Linux Kernel Sound Maintainer
ALSA Project, SUSE Labs
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: RFC: minimalistic TLV implementation
2006-05-31 13:10 RFC: minimalistic TLV implementation Jaroslav Kysela
@ 2006-06-01 11:25 ` Takashi Iwai
2006-06-01 13:12 ` Jaroslav Kysela
0 siblings, 1 reply; 14+ messages in thread
From: Takashi Iwai @ 2006-06-01 11:25 UTC (permalink / raw)
To: Jaroslav Kysela; +Cc: ALSA development
At Wed, 31 May 2006 15:10:21 +0200 (CEST),
Jaroslav Kysela wrote:
>
> Hi,
>
> I've created a minimalistic TLV implemetation for the driver side.
> Please, review and comment it. We can add more TLV funcionality in future.
> It is essential that user space will handle SNDRV_CTL_TLVT_LEVEL type
> immediately (altough it is not used in the kernel space now), otherwise we
> cannot group and level TLVs in future.
Please never ever include pointers in the ioctl struct.
That's to be avoided as much as possible.
Takashi
>
> Jaroslav
>
> diff -r 96e63842ba5d core/control.c
> --- a/core/control.c Wed May 31 11:55:17 2006 +0200
> +++ b/core/control.c Wed May 31 15:02:38 2006 +0200
> @@ -241,6 +241,7 @@ struct snd_kcontrol *snd_ctl_new1(const
> kctl.info = ncontrol->info;
> kctl.get = ncontrol->get;
> kctl.put = ncontrol->put;
> + kctl.tlv = ncontrol->tlv;
> kctl.private_value = ncontrol->private_value;
> kctl.private_data = private_data;
> return snd_ctl_new(&kctl, access);
> @@ -1067,6 +1068,44 @@ static int snd_ctl_subscribe_events(stru
> return 0;
> }
>
> +static int snd_ctl_tlv(struct snd_card *card, struct snd_ctl_tlv __user *_tlv)
> +{
> + struct snd_ctl_tlv tlv;
> + struct snd_kcontrol *kctl;
> + unsigned int len;
> + int err = 0;
> +
> + if (copy_to_user(&tlv, _tlv, sizeof(tlv)))
> + return -EFAULT;
> + if (tlv.length < sizeof(unsigned int) * 3)
> + return -EINVAL;
> + if (tlv.flags & SNDRV_CTL_TLV_NUMID) {
> + down_read(&card->controls_rwsem);
> + kctl = snd_ctl_find_numid(card, tlv.value);
> + if (kctl == NULL) {
> + err = -ENOENT;
> + goto __kctl_end;
> + }
> + if (kctl->tlv == NULL) {
> + err = -EIO;
> + goto __kctl_end;
> + }
> + len = *((unsigned int *)kctl->tlv);
> + if (tlv.length < len) {
> + err = -ENOMEM;
> + goto __kctl_end;
> + }
> + if (copy_to_user(tlv.ptr, kctl->tlv, len))
> + err = -EFAULT;
> + __kctl_end:
> + up_read(&card->controls_rwsem);
> + } else {
> + /* not implemented */
> + err = -EINVAL;
> + }
> + return err;
> +}
> +
> static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
> {
> struct snd_ctl_file *ctl;
> @@ -1086,11 +1125,11 @@ static long snd_ctl_ioctl(struct file *f
> case SNDRV_CTL_IOCTL_CARD_INFO:
> return snd_ctl_card_info(card, ctl, cmd, argp);
> case SNDRV_CTL_IOCTL_ELEM_LIST:
> - return snd_ctl_elem_list(ctl->card, argp);
> + return snd_ctl_elem_list(card, argp);
> case SNDRV_CTL_IOCTL_ELEM_INFO:
> return snd_ctl_elem_info_user(ctl, argp);
> case SNDRV_CTL_IOCTL_ELEM_READ:
> - return snd_ctl_elem_read_user(ctl->card, argp);
> + return snd_ctl_elem_read_user(card, argp);
> case SNDRV_CTL_IOCTL_ELEM_WRITE:
> return snd_ctl_elem_write_user(ctl, argp);
> case SNDRV_CTL_IOCTL_ELEM_LOCK:
> @@ -1105,6 +1144,8 @@ static long snd_ctl_ioctl(struct file *f
> return snd_ctl_elem_remove(ctl, argp);
> case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
> return snd_ctl_subscribe_events(ctl, ip);
> + case SNDRV_CTL_IOCTL_TLV:
> + return snd_ctl_tlv(card, argp);
> case SNDRV_CTL_IOCTL_POWER:
> return -ENOPROTOOPT;
> case SNDRV_CTL_IOCTL_POWER_STATE:
> diff -r 96e63842ba5d include/asound.h
> --- a/include/asound.h Wed May 31 11:55:17 2006 +0200
> +++ b/include/asound.h Wed May 31 15:02:38 2006 +0200
> @@ -818,6 +818,26 @@ struct snd_ctl_elem_value {
> unsigned char reserved[128-sizeof(struct timespec)];
> };
>
> +#define SNDRV_CTL_TLV_NUMID (1<<0) /* value is numid, otherwise request global TLV info */
> +
> +#define SNDRV_CTL_TLVT_LEVEL 0 /* one level down - group of TLVs */
> +#define SNDRV_CTL_TLVT_DB_SCALE 1 /* dB scale */
> +
> +struct snd_ctl_tlv {
> + unsigned int flags;
> + unsigned int length;
> + unsigned int value;
> + /*
> + * TLV structure is:
> + * unsigned int length
> + * unsigned int type - see SNDRV_CTL_TLVT_*
> + * .... data aligned to sizeof(unsigned int), use
> + * block_length = (length + (sizeof(unsigned int) - 1)) &
> + * ~(sizeof(unsigned int) - 1)) ....
> + */
> + void *ptr;
> +};
> +
> enum {
> SNDRV_CTL_IOCTL_PVERSION = _IOR('U', 0x00, int),
> SNDRV_CTL_IOCTL_CARD_INFO = _IOR('U', 0x01, struct snd_ctl_card_info),
> @@ -831,6 +851,7 @@ enum {
> SNDRV_CTL_IOCTL_ELEM_ADD = _IOWR('U', 0x17, struct snd_ctl_elem_info),
> SNDRV_CTL_IOCTL_ELEM_REPLACE = _IOWR('U', 0x18, struct snd_ctl_elem_info),
> SNDRV_CTL_IOCTL_ELEM_REMOVE = _IOWR('U', 0x19, struct snd_ctl_elem_id),
> + SNDRV_CTL_IOCTL_TLV = _IOWR('U', 0x1a, struct snd_ctl_tlv),
> SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE = _IOWR('U', 0x20, int),
> SNDRV_CTL_IOCTL_HWDEP_INFO = _IOR('U', 0x21, struct snd_hwdep_info),
> SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE = _IOR('U', 0x30, int),
> diff -r 96e63842ba5d include/control.h
> --- a/include/control.h Wed May 31 11:55:17 2006 +0200
> +++ b/include/control.h Wed May 31 15:02:38 2006 +0200
> @@ -42,6 +42,7 @@ struct snd_kcontrol_new {
> snd_kcontrol_info_t *info;
> snd_kcontrol_get_t *get;
> snd_kcontrol_put_t *put;
> + unsigned int *tlv;
> unsigned long private_value;
> };
>
> @@ -58,6 +59,7 @@ struct snd_kcontrol {
> snd_kcontrol_info_t *info;
> snd_kcontrol_get_t *get;
> snd_kcontrol_put_t *put;
> + unsigned int *tlv;
> unsigned long private_value;
> void *private_data;
> void (*private_free)(struct snd_kcontrol *kcontrol);
> diff -r 96e63842ba5d pci/ca0106/ca0106_mixer.c
> --- a/pci/ca0106/ca0106_mixer.c Wed May 31 11:55:17 2006 +0200
> +++ b/pci/ca0106/ca0106_mixer.c Wed May 31 15:02:38 2006 +0200
> @@ -70,8 +70,11 @@
> #include <sound/pcm.h>
> #include <sound/ac97_codec.h>
> #include <sound/info.h>
> +#include <sound/tlv.h>
>
> #include "ca0106.h"
> +
> +static DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale, -5150, 75, 1);
>
> static int snd_ca0106_shared_spdif_info(struct snd_kcontrol *kcontrol,
> struct snd_ctl_elem_info *uinfo)
> @@ -472,6 +475,7 @@ static int snd_ca0106_i2c_volume_put(str
> .info = snd_ca0106_volume_info, \
> .get = snd_ca0106_volume_get, \
> .put = snd_ca0106_volume_put, \
> + .tlv = snd_ca0106_db_scale, \
> .private_value = ((chid) << 8) | (reg) \
> }
>
> diff -r 96e63842ba5d include/tlv.h
> --- /dev/null Thu Jan 1 00:00:00 1970 +0000
> +++ b/include/tlv.h Wed May 31 15:02:38 2006 +0200
> @@ -0,0 +1,31 @@
> +#ifndef __SOUND_TLV_H
> +#define __SOUND_TLV_H
> +
> +/*
> + * Advanced Linux Sound Architecture - ALSA - Driver
> + * Copyright (c) 2006 by Jaroslav Kysela <perex@suse.cz>
> + *
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> + *
> + */
> +
> +#define DECLARE_TLV_DB_SCALE(name, min, step, mute) \
> +unsigned int name[] = { \
> + 4 * sizeof(unsigned int), SNDRV_CTL_TLVT_DB_SCALE, \
> + (min), (step & 0xffff) | (mute ? 0x10000 : 0) \
> +}
> +
> +#endif /* __SOUND_TLV_H */
>
> -----
> Jaroslav Kysela <perex@suse.cz>
> Linux Kernel Sound Maintainer
> ALSA Project, SUSE Labs
>
>
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/alsa-devel
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: RFC: minimalistic TLV implementation
2006-06-01 11:25 ` Takashi Iwai
@ 2006-06-01 13:12 ` Jaroslav Kysela
2006-06-01 13:38 ` Takashi Iwai
0 siblings, 1 reply; 14+ messages in thread
From: Jaroslav Kysela @ 2006-06-01 13:12 UTC (permalink / raw)
To: Takashi Iwai; +Cc: ALSA development
[-- Attachment #1: Type: TEXT/PLAIN, Size: 1500 bytes --]
On Thu, 1 Jun 2006, Takashi Iwai wrote:
> At Wed, 31 May 2006 15:10:21 +0200 (CEST),
> Jaroslav Kysela wrote:
> >
> > Hi,
> >
> > I've created a minimalistic TLV implemetation for the driver side.
> > Please, review and comment it. We can add more TLV funcionality in future.
> > It is essential that user space will handle SNDRV_CTL_TLVT_LEVEL type
> > immediately (altough it is not used in the kernel space now), otherwise we
> > cannot group and level TLVs in future.
>
> Please never ever include pointers in the ioctl struct.
> That's to be avoided as much as possible.
> > +struct snd_ctl_tlv {
> > + unsigned int flags;
> > + unsigned int length;
> > + unsigned int value;
> > + /*
> > + * TLV structure is:
> > + * unsigned int length
> > + * unsigned int type - see SNDRV_CTL_TLVT_*
> > + * .... data aligned to sizeof(unsigned int), use
> > + * block_length = (length + (sizeof(unsigned int) - 1)) &
> > + * ~(sizeof(unsigned int) - 1)) ....
> > + */
> > + void *ptr;
> > +};
So what you suggest? Something like 'struct dm_ioctl'
(include/linux/dm-ioctl.h) does? Data are stored after ioctl struct.
It's nearly similar.
Jaroslav
-----
InterNet přes WIFI bez limitu dat, České Budějovice a okolí
Pokryté lokality: Šindlovy Dvory, Mokré, Litvínovice, Pekárenská, Srubec
Perex @ InterNet <internet@perex.cz>
[-- Attachment #2: Type: text/plain, Size: 0 bytes --]
[-- Attachment #3: Type: text/plain, Size: 161 bytes --]
_______________________________________________
Alsa-devel mailing list
Alsa-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/alsa-devel
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: RFC: minimalistic TLV implementation
2006-06-01 13:12 ` Jaroslav Kysela
@ 2006-06-01 13:38 ` Takashi Iwai
2006-06-01 14:08 ` Jaroslav Kysela
0 siblings, 1 reply; 14+ messages in thread
From: Takashi Iwai @ 2006-06-01 13:38 UTC (permalink / raw)
To: Jaroslav Kysela; +Cc: ALSA development
At Thu, 1 Jun 2006 15:12:05 +0200 (CEST),
Jaroslav Kysela wrote:
>
> On Thu, 1 Jun 2006, Takashi Iwai wrote:
>
> > At Wed, 31 May 2006 15:10:21 +0200 (CEST),
> > Jaroslav Kysela wrote:
> > >
> > > Hi,
> > >
> > > I've created a minimalistic TLV implemetation for the driver side.
> > > Please, review and comment it. We can add more TLV funcionality in future.
> > > It is essential that user space will handle SNDRV_CTL_TLVT_LEVEL type
> > > immediately (altough it is not used in the kernel space now), otherwise we
> > > cannot group and level TLVs in future.
> >
> > Please never ever include pointers in the ioctl struct.
> > That's to be avoided as much as possible.
>
> > > +struct snd_ctl_tlv {
> > > + unsigned int flags;
> > > + unsigned int length;
> > > + unsigned int value;
> > > + /*
> > > + * TLV structure is:
> > > + * unsigned int length
> > > + * unsigned int type - see SNDRV_CTL_TLVT_*
> > > + * .... data aligned to sizeof(unsigned int), use
> > > + * block_length = (length + (sizeof(unsigned int) - 1)) &
> > > + * ~(sizeof(unsigned int) - 1)) ....
> > > + */
> > > + void *ptr;
> > > +};
>
> So what you suggest? Something like 'struct dm_ioctl'
> (include/linux/dm-ioctl.h) does? Data are stored after ioctl struct.
> It's nearly similar.
Yes. It's similar but a really big difference if you consider about
32/64bit compatibility.
Also, the order of "TLV" is type-length-value.
Takashi
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: RFC: minimalistic TLV implementation
2006-06-01 13:38 ` Takashi Iwai
@ 2006-06-01 14:08 ` Jaroslav Kysela
2006-06-01 14:40 ` Takashi Iwai
0 siblings, 1 reply; 14+ messages in thread
From: Jaroslav Kysela @ 2006-06-01 14:08 UTC (permalink / raw)
To: Takashi Iwai; +Cc: ALSA development
On Thu, 1 Jun 2006, Takashi Iwai wrote:
> Yes. It's similar but a really big difference if you consider about
> 32/64bit compatibility.
>
> Also, the order of "TLV" is type-length-value.
Ok, the second version of my patch. Note: in the ca0106 driver, only
three lines (if I don't count one empty line) are required to add
the dB scale information.
Jaroslav
diff -r 96e63842ba5d core/control.c
--- a/core/control.c Wed May 31 11:55:17 2006 +0200
+++ b/core/control.c Thu Jun 1 16:04:37 2006 +0200
@@ -241,6 +241,7 @@ struct snd_kcontrol *snd_ctl_new1(const
kctl.info = ncontrol->info;
kctl.get = ncontrol->get;
kctl.put = ncontrol->put;
+ kctl.tlv = ncontrol->tlv;
kctl.private_value = ncontrol->private_value;
kctl.private_data = private_data;
return snd_ctl_new(&kctl, access);
@@ -1067,6 +1068,46 @@ static int snd_ctl_subscribe_events(stru
return 0;
}
+static int snd_ctl_tlv_read(struct snd_card *card, struct snd_ctl_tlv __user *_tlv)
+{
+ struct snd_ctl_tlv tlv;
+ struct snd_kcontrol *kctl;
+ unsigned int len;
+ int err = 0;
+
+ if (copy_to_user(&tlv, _tlv, sizeof(tlv)))
+ return -EFAULT;
+ if (tlv.length < sizeof(unsigned int) * 3)
+ return -EINVAL;
+ if (tlv.flags & SNDRV_CTL_TLV_NUMID) {
+ down_read(&card->controls_rwsem);
+ kctl = snd_ctl_find_numid(card, tlv.ident);
+ if (kctl == NULL) {
+ err = -ENOENT;
+ goto __kctl_end;
+ }
+ if (kctl->tlv == NULL) {
+ err = -EIO;
+ goto __kctl_end;
+ }
+ len = *(((unsigned int *)kctl->tlv) + 1) +
+ 2 * sizeof(unsigned int);
+ if (tlv.length < len) {
+ err = -ENOMEM;
+ goto __kctl_end;
+ }
+ if (copy_to_user((unsigned char *)_tlv + tlv.data_offset,
+ kctl->tlv, len))
+ err = -EFAULT;
+ __kctl_end:
+ up_read(&card->controls_rwsem);
+ } else {
+ /* not implemented */
+ err = -EINVAL;
+ }
+ return err;
+}
+
static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct snd_ctl_file *ctl;
@@ -1086,11 +1127,11 @@ static long snd_ctl_ioctl(struct file *f
case SNDRV_CTL_IOCTL_CARD_INFO:
return snd_ctl_card_info(card, ctl, cmd, argp);
case SNDRV_CTL_IOCTL_ELEM_LIST:
- return snd_ctl_elem_list(ctl->card, argp);
+ return snd_ctl_elem_list(card, argp);
case SNDRV_CTL_IOCTL_ELEM_INFO:
return snd_ctl_elem_info_user(ctl, argp);
case SNDRV_CTL_IOCTL_ELEM_READ:
- return snd_ctl_elem_read_user(ctl->card, argp);
+ return snd_ctl_elem_read_user(card, argp);
case SNDRV_CTL_IOCTL_ELEM_WRITE:
return snd_ctl_elem_write_user(ctl, argp);
case SNDRV_CTL_IOCTL_ELEM_LOCK:
@@ -1105,6 +1146,8 @@ static long snd_ctl_ioctl(struct file *f
return snd_ctl_elem_remove(ctl, argp);
case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
return snd_ctl_subscribe_events(ctl, ip);
+ case SNDRV_CTL_IOCTL_TLV_READ:
+ return snd_ctl_tlv_read(card, argp);
case SNDRV_CTL_IOCTL_POWER:
return -ENOPROTOOPT;
case SNDRV_CTL_IOCTL_POWER_STATE:
diff -r 96e63842ba5d include/asound.h
--- a/include/asound.h Wed May 31 11:55:17 2006 +0200
+++ b/include/asound.h Thu Jun 1 16:04:37 2006 +0200
@@ -818,6 +818,26 @@ struct snd_ctl_elem_value {
unsigned char reserved[128-sizeof(struct timespec)];
};
+#define SNDRV_CTL_TLV_NUMID (1<<0) /* ident is numid, otherwise request global TLV info */
+
+#define SNDRV_CTL_TLVT_LEVEL 0 /* one level down - group of TLVs */
+#define SNDRV_CTL_TLVT_DB_SCALE 1 /* dB scale */
+
+struct snd_ctl_tlv {
+ unsigned int flags;
+ unsigned int length;
+ unsigned int ident;
+ /*
+ * TLV structure is:
+ * unsigned int type - see SNDRV_CTL_TLVT_*
+ * unsigned int length
+ * .... data aligned to sizeof(unsigned int), use
+ * block_length = (length + (sizeof(unsigned int) - 1)) &
+ * ~(sizeof(unsigned int) - 1)) ....
+ */
+ unsigned int data_offset; /* offset to data in bytes behind ioctl structure */
+};
+
enum {
SNDRV_CTL_IOCTL_PVERSION = _IOR('U', 0x00, int),
SNDRV_CTL_IOCTL_CARD_INFO = _IOR('U', 0x01, struct snd_ctl_card_info),
@@ -831,6 +851,7 @@ enum {
SNDRV_CTL_IOCTL_ELEM_ADD = _IOWR('U', 0x17, struct snd_ctl_elem_info),
SNDRV_CTL_IOCTL_ELEM_REPLACE = _IOWR('U', 0x18, struct snd_ctl_elem_info),
SNDRV_CTL_IOCTL_ELEM_REMOVE = _IOWR('U', 0x19, struct snd_ctl_elem_id),
+ SNDRV_CTL_IOCTL_TLV_READ = _IOWR('U', 0x1a, struct snd_ctl_tlv),
SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE = _IOWR('U', 0x20, int),
SNDRV_CTL_IOCTL_HWDEP_INFO = _IOR('U', 0x21, struct snd_hwdep_info),
SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE = _IOR('U', 0x30, int),
diff -r 96e63842ba5d include/control.h
--- a/include/control.h Wed May 31 11:55:17 2006 +0200
+++ b/include/control.h Thu Jun 1 16:04:37 2006 +0200
@@ -42,6 +42,7 @@ struct snd_kcontrol_new {
snd_kcontrol_info_t *info;
snd_kcontrol_get_t *get;
snd_kcontrol_put_t *put;
+ unsigned int *tlv;
unsigned long private_value;
};
@@ -58,6 +59,7 @@ struct snd_kcontrol {
snd_kcontrol_info_t *info;
snd_kcontrol_get_t *get;
snd_kcontrol_put_t *put;
+ unsigned int *tlv;
unsigned long private_value;
void *private_data;
void (*private_free)(struct snd_kcontrol *kcontrol);
diff -r 96e63842ba5d pci/ca0106/ca0106_mixer.c
--- a/pci/ca0106/ca0106_mixer.c Wed May 31 11:55:17 2006 +0200
+++ b/pci/ca0106/ca0106_mixer.c Thu Jun 1 16:04:37 2006 +0200
@@ -70,8 +70,11 @@
#include <sound/pcm.h>
#include <sound/ac97_codec.h>
#include <sound/info.h>
+#include <sound/tlv.h>
#include "ca0106.h"
+
+static DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale, -5150, 75, 1);
static int snd_ca0106_shared_spdif_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
@@ -472,6 +475,7 @@ static int snd_ca0106_i2c_volume_put(str
.info = snd_ca0106_volume_info, \
.get = snd_ca0106_volume_get, \
.put = snd_ca0106_volume_put, \
+ .tlv = snd_ca0106_db_scale, \
.private_value = ((chid) << 8) | (reg) \
}
diff -r 96e63842ba5d include/tlv.h
--- /dev/null Thu Jan 1 00:00:00 1970 +0000
+++ b/include/tlv.h Thu Jun 1 16:04:37 2006 +0200
@@ -0,0 +1,31 @@
+#ifndef __SOUND_TLV_H
+#define __SOUND_TLV_H
+
+/*
+ * Advanced Linux Sound Architecture - ALSA - Driver
+ * Copyright (c) 2006 by Jaroslav Kysela <perex@suse.cz>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#define DECLARE_TLV_DB_SCALE(name, min, step, mute) \
+unsigned int name[] = { \
+ SNDRV_CTL_TLVT_DB_SCALE, 2 * sizeof(unsigned int), \
+ (min), ((step) & 0xffff) | ((mute) ? 0x10000 : 0) \
+}
+
+#endif /* __SOUND_TLV_H */
-----
Jaroslav Kysela <perex@suse.cz>
Linux Kernel Sound Maintainer
ALSA Project, SUSE Labs
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: RFC: minimalistic TLV implementation
2006-06-01 14:08 ` Jaroslav Kysela
@ 2006-06-01 14:40 ` Takashi Iwai
2006-06-01 15:00 ` Jaroslav Kysela
0 siblings, 1 reply; 14+ messages in thread
From: Takashi Iwai @ 2006-06-01 14:40 UTC (permalink / raw)
To: Jaroslav Kysela; +Cc: ALSA development
At Thu, 1 Jun 2006 16:08:13 +0200 (CEST),
Jaroslav Kysela wrote:
>
> On Thu, 1 Jun 2006, Takashi Iwai wrote:
>
> > Yes. It's similar but a really big difference if you consider about
> > 32/64bit compatibility.
> >
> > Also, the order of "TLV" is type-length-value.
>
> Ok, the second version of my patch. Note: in the ca0106 driver, only
> three lines (if I don't count one empty line) are required to add
> the dB scale information.
The existence of flag makes the things complicated.
I prefer removing flag and make the ioctl numid-specific.
Also, I don't think data_offset is necessary in the practical use.
struct snd_ctl_tlv {
u32 length;
u32 numid;
/* TLV data is stored in the following like the format below */
};
/* TLV data:
u32 type;
u32 length;
u32 values[];
length is always aligned to 4 bytes
*/
>
> Jaroslav
>
> diff -r 96e63842ba5d core/control.c
> --- a/core/control.c Wed May 31 11:55:17 2006 +0200
> +++ b/core/control.c Thu Jun 1 16:04:37 2006 +0200
> @@ -241,6 +241,7 @@ struct snd_kcontrol *snd_ctl_new1(const
> kctl.info = ncontrol->info;
> kctl.get = ncontrol->get;
> kctl.put = ncontrol->put;
> + kctl.tlv = ncontrol->tlv;
> kctl.private_value = ncontrol->private_value;
> kctl.private_data = private_data;
> return snd_ctl_new(&kctl, access);
> @@ -1067,6 +1068,46 @@ static int snd_ctl_subscribe_events(stru
> return 0;
> }
>
> +static int snd_ctl_tlv_read(struct snd_card *card, struct snd_ctl_tlv __user *_tlv)
Too long line :)
> +{
> + struct snd_ctl_tlv tlv;
> + struct snd_kcontrol *kctl;
> + unsigned int len;
> + int err = 0;
> +
> + if (copy_to_user(&tlv, _tlv, sizeof(tlv)))
copy_from_user()
> + return -EFAULT;
> + if (tlv.length < sizeof(unsigned int) * 3)
> + return -EINVAL;
> + if (tlv.flags & SNDRV_CTL_TLV_NUMID) {
> + down_read(&card->controls_rwsem);
> + kctl = snd_ctl_find_numid(card, tlv.ident);
> + if (kctl == NULL) {
> + err = -ENOENT;
> + goto __kctl_end;
> + }
> + if (kctl->tlv == NULL) {
> + err = -EIO;
-ENXIO sounds better to me.
> + goto __kctl_end;
> + }
> + len = *(((unsigned int *)kctl->tlv) + 1) +
> + 2 * sizeof(unsigned int);
len = kctl->tlv[1] + 4;
> + if (tlv.length < len) {
> + err = -ENOMEM;
> + goto __kctl_end;
> + }
> + if (copy_to_user((unsigned char *)_tlv + tlv.data_offset,
> + kctl->tlv, len))
> + err = -EFAULT;
> + __kctl_end:
> + up_read(&card->controls_rwsem);
> + } else {
> + /* not implemented */
> + err = -EINVAL;
> + }
> + return err;
> +}
> +
> static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
> {
> struct snd_ctl_file *ctl;
> @@ -1086,11 +1127,11 @@ static long snd_ctl_ioctl(struct file *f
> case SNDRV_CTL_IOCTL_CARD_INFO:
> return snd_ctl_card_info(card, ctl, cmd, argp);
> case SNDRV_CTL_IOCTL_ELEM_LIST:
> - return snd_ctl_elem_list(ctl->card, argp);
> + return snd_ctl_elem_list(card, argp);
> case SNDRV_CTL_IOCTL_ELEM_INFO:
> return snd_ctl_elem_info_user(ctl, argp);
> case SNDRV_CTL_IOCTL_ELEM_READ:
> - return snd_ctl_elem_read_user(ctl->card, argp);
> + return snd_ctl_elem_read_user(card, argp);
> case SNDRV_CTL_IOCTL_ELEM_WRITE:
> return snd_ctl_elem_write_user(ctl, argp);
> case SNDRV_CTL_IOCTL_ELEM_LOCK:
> @@ -1105,6 +1146,8 @@ static long snd_ctl_ioctl(struct file *f
> return snd_ctl_elem_remove(ctl, argp);
> case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
> return snd_ctl_subscribe_events(ctl, ip);
> + case SNDRV_CTL_IOCTL_TLV_READ:
> + return snd_ctl_tlv_read(card, argp);
> case SNDRV_CTL_IOCTL_POWER:
> return -ENOPROTOOPT;
> case SNDRV_CTL_IOCTL_POWER_STATE:
> diff -r 96e63842ba5d include/asound.h
> --- a/include/asound.h Wed May 31 11:55:17 2006 +0200
> +++ b/include/asound.h Thu Jun 1 16:04:37 2006 +0200
> @@ -818,6 +818,26 @@ struct snd_ctl_elem_value {
> unsigned char reserved[128-sizeof(struct timespec)];
> };
>
> +#define SNDRV_CTL_TLV_NUMID (1<<0) /* ident is numid, otherwise request global TLV info */
> +
> +#define SNDRV_CTL_TLVT_LEVEL 0 /* one level down - group of TLVs */
CONTAINER?
> +#define SNDRV_CTL_TLVT_DB_SCALE 1 /* dB scale */
> +
> +struct snd_ctl_tlv {
> + unsigned int flags;
> + unsigned int length;
> + unsigned int ident;
> + /*
> + * TLV structure is:
> + * unsigned int type - see SNDRV_CTL_TLVT_*
> + * unsigned int length
> + * .... data aligned to sizeof(unsigned int), use
> + * block_length = (length + (sizeof(unsigned int) - 1)) &
> + * ~(sizeof(unsigned int) - 1)) ....
> + */
> + unsigned int data_offset; /* offset to data in bytes behind ioctl structure */
> +};
> +
> enum {
> SNDRV_CTL_IOCTL_PVERSION = _IOR('U', 0x00, int),
> SNDRV_CTL_IOCTL_CARD_INFO = _IOR('U', 0x01, struct snd_ctl_card_info),
> @@ -831,6 +851,7 @@ enum {
> SNDRV_CTL_IOCTL_ELEM_ADD = _IOWR('U', 0x17, struct snd_ctl_elem_info),
> SNDRV_CTL_IOCTL_ELEM_REPLACE = _IOWR('U', 0x18, struct snd_ctl_elem_info),
> SNDRV_CTL_IOCTL_ELEM_REMOVE = _IOWR('U', 0x19, struct snd_ctl_elem_id),
> + SNDRV_CTL_IOCTL_TLV_READ = _IOWR('U', 0x1a, struct snd_ctl_tlv),
> SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE = _IOWR('U', 0x20, int),
> SNDRV_CTL_IOCTL_HWDEP_INFO = _IOR('U', 0x21, struct snd_hwdep_info),
> SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE = _IOR('U', 0x30, int),
> diff -r 96e63842ba5d include/control.h
> --- a/include/control.h Wed May 31 11:55:17 2006 +0200
> +++ b/include/control.h Thu Jun 1 16:04:37 2006 +0200
> @@ -42,6 +42,7 @@ struct snd_kcontrol_new {
> snd_kcontrol_info_t *info;
> snd_kcontrol_get_t *get;
> snd_kcontrol_put_t *put;
> + unsigned int *tlv;
> unsigned long private_value;
> };
>
> @@ -58,6 +59,7 @@ struct snd_kcontrol {
> snd_kcontrol_info_t *info;
> snd_kcontrol_get_t *get;
> snd_kcontrol_put_t *put;
> + unsigned int *tlv;
> unsigned long private_value;
> void *private_data;
> void (*private_free)(struct snd_kcontrol *kcontrol);
> diff -r 96e63842ba5d pci/ca0106/ca0106_mixer.c
> --- a/pci/ca0106/ca0106_mixer.c Wed May 31 11:55:17 2006 +0200
> +++ b/pci/ca0106/ca0106_mixer.c Thu Jun 1 16:04:37 2006 +0200
> @@ -70,8 +70,11 @@
> #include <sound/pcm.h>
> #include <sound/ac97_codec.h>
> #include <sound/info.h>
> +#include <sound/tlv.h>
>
> #include "ca0106.h"
> +
> +static DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale, -5150, 75, 1);
>
> static int snd_ca0106_shared_spdif_info(struct snd_kcontrol *kcontrol,
> struct snd_ctl_elem_info *uinfo)
> @@ -472,6 +475,7 @@ static int snd_ca0106_i2c_volume_put(str
> .info = snd_ca0106_volume_info, \
> .get = snd_ca0106_volume_get, \
> .put = snd_ca0106_volume_put, \
> + .tlv = snd_ca0106_db_scale, \
> .private_value = ((chid) << 8) | (reg) \
> }
>
> diff -r 96e63842ba5d include/tlv.h
> --- /dev/null Thu Jan 1 00:00:00 1970 +0000
> +++ b/include/tlv.h Thu Jun 1 16:04:37 2006 +0200
> @@ -0,0 +1,31 @@
> +#ifndef __SOUND_TLV_H
> +#define __SOUND_TLV_H
> +
> +/*
> + * Advanced Linux Sound Architecture - ALSA - Driver
> + * Copyright (c) 2006 by Jaroslav Kysela <perex@suse.cz>
> + *
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> + *
> + */
> +
> +#define DECLARE_TLV_DB_SCALE(name, min, step, mute) \
> +unsigned int name[] = { \
> + SNDRV_CTL_TLVT_DB_SCALE, 2 * sizeof(unsigned int), \
> + (min), ((step) & 0xffff) | ((mute) ? 0x10000 : 0) \
> +}
> +
> +#endif /* __SOUND_TLV_H */
Should be in control.h if we define TLVT_DB_SCALE there.
Or, all tlv type and data definition should go to tlv.h.
Takashi
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: RFC: minimalistic TLV implementation
2006-06-01 14:40 ` Takashi Iwai
@ 2006-06-01 15:00 ` Jaroslav Kysela
2006-06-01 15:13 ` Takashi Iwai
0 siblings, 1 reply; 14+ messages in thread
From: Jaroslav Kysela @ 2006-06-01 15:00 UTC (permalink / raw)
To: Takashi Iwai; +Cc: ALSA development
[-- Attachment #1: Type: TEXT/PLAIN, Size: 1252 bytes --]
On Thu, 1 Jun 2006, Takashi Iwai wrote:
> At Thu, 1 Jun 2006 16:08:13 +0200 (CEST),
> Jaroslav Kysela wrote:
> >
> > On Thu, 1 Jun 2006, Takashi Iwai wrote:
> >
> > > Yes. It's similar but a really big difference if you consider about
> > > 32/64bit compatibility.
> > >
> > > Also, the order of "TLV" is type-length-value.
> >
> > Ok, the second version of my patch. Note: in the ca0106 driver, only
> > three lines (if I don't count one empty line) are required to add
> > the dB scale information.
>
> The existence of flag makes the things complicated.
> I prefer removing flag and make the ioctl numid-specific.
It might be. It's really small work for the user space and we may use
flags in future to determine ioctl version or some other extension at the
ioctl level.
> Also, I don't think data_offset is necessary in the practical use.
To separate ioctl and data in the user space? But it might be that
the 32bit->64bit conversion layer won't handle the non-continuous memory
in a right way. I'll remove it.
Jaroslav
-----
InterNet přes WIFI bez limitu dat, České Budějovice a okolí
Pokryté lokality: Šindlovy Dvory, Mokré, Litvínovice, Pekárenská, Srubec
Perex @ InterNet <internet@perex.cz>
[-- Attachment #2: Type: text/plain, Size: 0 bytes --]
[-- Attachment #3: Type: text/plain, Size: 161 bytes --]
_______________________________________________
Alsa-devel mailing list
Alsa-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/alsa-devel
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: RFC: minimalistic TLV implementation
2006-06-01 15:00 ` Jaroslav Kysela
@ 2006-06-01 15:13 ` Takashi Iwai
2006-06-01 15:16 ` Jaroslav Kysela
0 siblings, 1 reply; 14+ messages in thread
From: Takashi Iwai @ 2006-06-01 15:13 UTC (permalink / raw)
To: Jaroslav Kysela; +Cc: ALSA development
At Thu, 1 Jun 2006 17:00:30 +0200 (CEST),
Jaroslav Kysela wrote:
>
> On Thu, 1 Jun 2006, Takashi Iwai wrote:
>
> > At Thu, 1 Jun 2006 16:08:13 +0200 (CEST),
> > Jaroslav Kysela wrote:
> > >
> > > On Thu, 1 Jun 2006, Takashi Iwai wrote:
> > >
> > > > Yes. It's similar but a really big difference if you consider about
> > > > 32/64bit compatibility.
> > > >
> > > > Also, the order of "TLV" is type-length-value.
> > >
> > > Ok, the second version of my patch. Note: in the ca0106 driver, only
> > > three lines (if I don't count one empty line) are required to add
> > > the dB scale information.
> >
> > The existence of flag makes the things complicated.
> > I prefer removing flag and make the ioctl numid-specific.
>
> It might be. It's really small work for the user space and we may use
> flags in future to determine ioctl version or some other extension at the
> ioctl level.
Well, but this ioctl is damn simple. Just query a control element for
its TLV data.
It's supposed to be the one containing all. If we need a filter of
returned data, the query header should contain a type field rather
than flags.
Takashi
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: RFC: minimalistic TLV implementation
2006-06-01 15:13 ` Takashi Iwai
@ 2006-06-01 15:16 ` Jaroslav Kysela
2006-06-01 15:18 ` Takashi Iwai
0 siblings, 1 reply; 14+ messages in thread
From: Jaroslav Kysela @ 2006-06-01 15:16 UTC (permalink / raw)
To: Takashi Iwai; +Cc: ALSA development
On Thu, 1 Jun 2006, Takashi Iwai wrote:
> Well, but this ioctl is damn simple. Just query a control element for
> its TLV data.
>
> It's supposed to be the one containing all. If we need a filter of
> returned data, the query header should contain a type field rather
> than flags.
Sure, but this ioctl can handle global data (not numid dependant) as well.
If we decide to have two ioctls then it's also ok to me.
Jaroslav
-----
Jaroslav Kysela <perex@suse.cz>
Linux Kernel Sound Maintainer
ALSA Project, SUSE Labs
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: RFC: minimalistic TLV implementation
2006-06-01 15:16 ` Jaroslav Kysela
@ 2006-06-01 15:18 ` Takashi Iwai
2006-06-01 15:28 ` Jaroslav Kysela
0 siblings, 1 reply; 14+ messages in thread
From: Takashi Iwai @ 2006-06-01 15:18 UTC (permalink / raw)
To: Jaroslav Kysela; +Cc: ALSA development
At Thu, 1 Jun 2006 17:16:13 +0200 (CEST),
Jaroslav Kysela wrote:
>
> On Thu, 1 Jun 2006, Takashi Iwai wrote:
>
> > Well, but this ioctl is damn simple. Just query a control element for
> > its TLV data.
> >
> > It's supposed to be the one containing all. If we need a filter of
> > returned data, the query header should contain a type field rather
> > than flags.
>
> Sure, but this ioctl can handle global data (not numid dependant) as well.
> If we decide to have two ioctls then it's also ok to me.
Yeah, I prefer two ioctls now, too.
(But we don't need to add the global ioctl yet unless we really need
it...)
Takashi
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: RFC: minimalistic TLV implementation
2006-06-01 15:18 ` Takashi Iwai
@ 2006-06-01 15:28 ` Jaroslav Kysela
2006-06-01 15:40 ` Takashi Iwai
0 siblings, 1 reply; 14+ messages in thread
From: Jaroslav Kysela @ 2006-06-01 15:28 UTC (permalink / raw)
To: Takashi Iwai; +Cc: ALSA development
On Thu, 1 Jun 2006, Takashi Iwai wrote:
> Yeah, I prefer two ioctls now, too.
> (But we don't need to add the global ioctl yet unless we really need
> it...)
Fine. Here is the third version of patch.
Jaroslav
diff -r 96e63842ba5d core/control.c
--- a/core/control.c Wed May 31 11:55:17 2006 +0200
+++ b/core/control.c Thu Jun 1 17:25:38 2006 +0200
@@ -241,6 +241,7 @@ struct snd_kcontrol *snd_ctl_new1(const
kctl.info = ncontrol->info;
kctl.get = ncontrol->get;
kctl.put = ncontrol->put;
+ kctl.tlv = ncontrol->tlv;
kctl.private_value = ncontrol->private_value;
kctl.private_data = private_data;
return snd_ctl_new(&kctl, access);
@@ -1067,6 +1068,40 @@ static int snd_ctl_subscribe_events(stru
return 0;
}
+static int snd_ctl_tlv_read(struct snd_card *card,
+ struct snd_ctl_tlv __user *_tlv)
+{
+ struct snd_ctl_tlv tlv;
+ struct snd_kcontrol *kctl;
+ unsigned int len;
+ int err = 0;
+
+ if (copy_from_user(&tlv, _tlv, sizeof(tlv)))
+ return -EFAULT;
+ if (tlv.length < sizeof(unsigned int) * 3)
+ return -EINVAL;
+ down_read(&card->controls_rwsem);
+ kctl = snd_ctl_find_numid(card, tlv.numid);
+ if (kctl == NULL) {
+ err = -ENOENT;
+ goto __kctl_end;
+ }
+ if (kctl->tlv == NULL) {
+ err = -ENXIO;
+ goto __kctl_end;
+ }
+ len = kctl->tlv[1] + 2 * sizeof(unsigned int);
+ if (tlv.length < len) {
+ err = -ENOMEM;
+ goto __kctl_end;
+ }
+ if (copy_to_user(_tlv->tlv, kctl->tlv, len))
+ err = -EFAULT;
+ __kctl_end:
+ up_read(&card->controls_rwsem);
+ return err;
+}
+
static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct snd_ctl_file *ctl;
@@ -1086,11 +1121,11 @@ static long snd_ctl_ioctl(struct file *f
case SNDRV_CTL_IOCTL_CARD_INFO:
return snd_ctl_card_info(card, ctl, cmd, argp);
case SNDRV_CTL_IOCTL_ELEM_LIST:
- return snd_ctl_elem_list(ctl->card, argp);
+ return snd_ctl_elem_list(card, argp);
case SNDRV_CTL_IOCTL_ELEM_INFO:
return snd_ctl_elem_info_user(ctl, argp);
case SNDRV_CTL_IOCTL_ELEM_READ:
- return snd_ctl_elem_read_user(ctl->card, argp);
+ return snd_ctl_elem_read_user(card, argp);
case SNDRV_CTL_IOCTL_ELEM_WRITE:
return snd_ctl_elem_write_user(ctl, argp);
case SNDRV_CTL_IOCTL_ELEM_LOCK:
@@ -1105,6 +1140,8 @@ static long snd_ctl_ioctl(struct file *f
return snd_ctl_elem_remove(ctl, argp);
case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
return snd_ctl_subscribe_events(ctl, ip);
+ case SNDRV_CTL_IOCTL_TLV_READ:
+ return snd_ctl_tlv_read(card, argp);
case SNDRV_CTL_IOCTL_POWER:
return -ENOPROTOOPT;
case SNDRV_CTL_IOCTL_POWER_STATE:
diff -r 96e63842ba5d include/asound.h
--- a/include/asound.h Wed May 31 11:55:17 2006 +0200
+++ b/include/asound.h Thu Jun 1 17:25:38 2006 +0200
@@ -688,7 +688,7 @@ struct snd_timer_tread {
* *
****************************************************************************/
-#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 3)
+#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 4)
struct snd_ctl_card_info {
int card; /* card number */
@@ -818,6 +818,20 @@ struct snd_ctl_elem_value {
unsigned char reserved[128-sizeof(struct timespec)];
};
+struct snd_ctl_tlv {
+ unsigned int numid; /* control element numeric identification */
+ unsigned int length; /* in bytes aligned to 4 */
+ /*
+ * TLV structure is right behind the struct snd_ctl_tlv:
+ * unsigned int type - see SNDRV_CTL_TLVT_*
+ * unsigned int length
+ * .... data aligned to sizeof(unsigned int), use
+ * block_length = (length + (sizeof(unsigned int) - 1)) &
+ * ~(sizeof(unsigned int) - 1)) ....
+ */
+ unsigned int tlv[0];
+};
+
enum {
SNDRV_CTL_IOCTL_PVERSION = _IOR('U', 0x00, int),
SNDRV_CTL_IOCTL_CARD_INFO = _IOR('U', 0x01, struct snd_ctl_card_info),
@@ -831,6 +845,7 @@ enum {
SNDRV_CTL_IOCTL_ELEM_ADD = _IOWR('U', 0x17, struct snd_ctl_elem_info),
SNDRV_CTL_IOCTL_ELEM_REPLACE = _IOWR('U', 0x18, struct snd_ctl_elem_info),
SNDRV_CTL_IOCTL_ELEM_REMOVE = _IOWR('U', 0x19, struct snd_ctl_elem_id),
+ SNDRV_CTL_IOCTL_TLV_READ = _IOWR('U', 0x1a, struct snd_ctl_tlv),
SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE = _IOWR('U', 0x20, int),
SNDRV_CTL_IOCTL_HWDEP_INFO = _IOR('U', 0x21, struct snd_hwdep_info),
SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE = _IOR('U', 0x30, int),
diff -r 96e63842ba5d include/control.h
--- a/include/control.h Wed May 31 11:55:17 2006 +0200
+++ b/include/control.h Thu Jun 1 17:25:38 2006 +0200
@@ -42,6 +42,7 @@ struct snd_kcontrol_new {
snd_kcontrol_info_t *info;
snd_kcontrol_get_t *get;
snd_kcontrol_put_t *put;
+ unsigned int *tlv;
unsigned long private_value;
};
@@ -58,6 +59,7 @@ struct snd_kcontrol {
snd_kcontrol_info_t *info;
snd_kcontrol_get_t *get;
snd_kcontrol_put_t *put;
+ unsigned int *tlv;
unsigned long private_value;
void *private_data;
void (*private_free)(struct snd_kcontrol *kcontrol);
diff -r 96e63842ba5d pci/ca0106/ca0106_mixer.c
--- a/pci/ca0106/ca0106_mixer.c Wed May 31 11:55:17 2006 +0200
+++ b/pci/ca0106/ca0106_mixer.c Thu Jun 1 17:25:38 2006 +0200
@@ -70,8 +70,11 @@
#include <sound/pcm.h>
#include <sound/ac97_codec.h>
#include <sound/info.h>
+#include <sound/tlv.h>
#include "ca0106.h"
+
+static DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale, -5150, 75, 1);
static int snd_ca0106_shared_spdif_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
@@ -472,6 +475,7 @@ static int snd_ca0106_i2c_volume_put(str
.info = snd_ca0106_volume_info, \
.get = snd_ca0106_volume_get, \
.put = snd_ca0106_volume_put, \
+ .tlv = snd_ca0106_db_scale, \
.private_value = ((chid) << 8) | (reg) \
}
diff -r 96e63842ba5d include/tlv.h
--- /dev/null Thu Jan 1 00:00:00 1970 +0000
+++ b/include/tlv.h Thu Jun 1 17:25:38 2006 +0200
@@ -0,0 +1,34 @@
+#ifndef __SOUND_TLV_H
+#define __SOUND_TLV_H
+
+/*
+ * Advanced Linux Sound Architecture - ALSA - Driver
+ * Copyright (c) 2006 by Jaroslav Kysela <perex@suse.cz>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#define SNDRV_CTL_TLVT_CONTAINER 0 /* one level down - group of TLVs */
+#define SNDRV_CTL_TLVT_DB_SCALE 1 /* dB scale */
+
+#define DECLARE_TLV_DB_SCALE(name, min, step, mute) \
+unsigned int name[] = { \
+ SNDRV_CTL_TLVT_DB_SCALE, 2 * sizeof(unsigned int), \
+ (min), ((step) & 0xffff) | ((mute) ? 0x10000 : 0) \
+}
+
+#endif /* __SOUND_TLV_H */
-----
Jaroslav Kysela <perex@suse.cz>
Linux Kernel Sound Maintainer
ALSA Project, SUSE Labs
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: RFC: minimalistic TLV implementation
2006-06-01 15:28 ` Jaroslav Kysela
@ 2006-06-01 15:40 ` Takashi Iwai
2006-06-01 16:36 ` Jaroslav Kysela
0 siblings, 1 reply; 14+ messages in thread
From: Takashi Iwai @ 2006-06-01 15:40 UTC (permalink / raw)
To: Jaroslav Kysela; +Cc: ALSA development
At Thu, 1 Jun 2006 17:28:41 +0200 (CEST),
Jaroslav Kysela wrote:
>
> diff -r 96e63842ba5d include/asound.h
> --- a/include/asound.h Wed May 31 11:55:17 2006 +0200
> +++ b/include/asound.h Thu Jun 1 17:25:38 2006 +0200
> @@ -688,7 +688,7 @@ struct snd_timer_tread {
> * *
> ****************************************************************************/
>
> -#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 3)
> +#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 4)
>
> struct snd_ctl_card_info {
> int card; /* card number */
> @@ -818,6 +818,20 @@ struct snd_ctl_elem_value {
> unsigned char reserved[128-sizeof(struct timespec)];
> };
>
> +struct snd_ctl_tlv {
> + unsigned int numid; /* control element numeric identification */
> + unsigned int length; /* in bytes aligned to 4 */
> + /*
> + * TLV structure is right behind the struct snd_ctl_tlv:
> + * unsigned int type - see SNDRV_CTL_TLVT_*
> + * unsigned int length
> + * .... data aligned to sizeof(unsigned int), use
> + * block_length = (length + (sizeof(unsigned int) - 1)) &
> + * ~(sizeof(unsigned int) - 1)) ....
> + */
I'd put this detailed comment in tlv.h, and here shows a short comment
like:
"TLV data is put right behind the struct snd_ctl_tlv.
See tlv.h for definition of TLV data".
Takashi
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: RFC: minimalistic TLV implementation
2006-06-01 15:40 ` Takashi Iwai
@ 2006-06-01 16:36 ` Jaroslav Kysela
2006-06-06 14:01 ` Takashi Iwai
0 siblings, 1 reply; 14+ messages in thread
From: Jaroslav Kysela @ 2006-06-01 16:36 UTC (permalink / raw)
To: Takashi Iwai; +Cc: ALSA development
On Thu, 1 Jun 2006, Takashi Iwai wrote:
> I'd put this detailed comment in tlv.h, and here shows a short comment
Done. I've commited the patch to HG.
Jaroslav
-----
Jaroslav Kysela <perex@suse.cz>
Linux Kernel Sound Maintainer
ALSA Project, SUSE Labs
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: RFC: minimalistic TLV implementation
2006-06-01 16:36 ` Jaroslav Kysela
@ 2006-06-06 14:01 ` Takashi Iwai
0 siblings, 0 replies; 14+ messages in thread
From: Takashi Iwai @ 2006-06-06 14:01 UTC (permalink / raw)
To: Jaroslav Kysela; +Cc: ALSA development
At Thu, 1 Jun 2006 18:36:15 +0200 (CEST),
Jaroslav Kysela wrote:
>
> On Thu, 1 Jun 2006, Takashi Iwai wrote:
>
> > I'd put this detailed comment in tlv.h, and here shows a short comment
>
> Done. I've commited the patch to HG.
What about the alsa-lib part? Did you already work on it?
Takashi
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2006-06-06 14:01 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-05-31 13:10 RFC: minimalistic TLV implementation Jaroslav Kysela
2006-06-01 11:25 ` Takashi Iwai
2006-06-01 13:12 ` Jaroslav Kysela
2006-06-01 13:38 ` Takashi Iwai
2006-06-01 14:08 ` Jaroslav Kysela
2006-06-01 14:40 ` Takashi Iwai
2006-06-01 15:00 ` Jaroslav Kysela
2006-06-01 15:13 ` Takashi Iwai
2006-06-01 15:16 ` Jaroslav Kysela
2006-06-01 15:18 ` Takashi Iwai
2006-06-01 15:28 ` Jaroslav Kysela
2006-06-01 15:40 ` Takashi Iwai
2006-06-01 16:36 ` Jaroslav Kysela
2006-06-06 14:01 ` Takashi Iwai
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.