[alsa-devel] [PATCH 03/24] ALSA: ctl: add serializer/deserializer of 'elem_info' structure for 32bit ABI compatibility
Takashi Sakamoto
o-takashi at sakamocchi.jp
Sat Nov 25 10:19:45 CET 2017
A 'snd_ctl_elem_info' structure includes a member of 'integer long' type.
A machine type for the type is known to have different size and alignment
between System V ABIs for architectures which adopts 'ILP32' or 'LP64'
data model.
This commit adds a pair of serializer and deserializer to convert data
between different layout of the structure on the ABIs.
Signed-off-by: Takashi Sakamoto <o-takashi at sakamocchi.jp>
---
sound/core/control_compat.c | 94 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 94 insertions(+)
diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c
index 3bd04ef5d221..7ebae996804a 100644
--- a/sound/core/control_compat.c
+++ b/sound/core/control_compat.c
@@ -105,6 +105,100 @@ static int serialize_to_elem_list_32(struct snd_ctl_file *ctl_file, void *dst,
return 0;
}
+/*
+ * In this structure, '.value' member includes double-word (= 64 bits) member
+ * ('.integer64'). System V ABI for i386 architecture adopts different byte
+ * alignment for this type (4 bytes) than the ones in the other architectures
+ * (8 bytes). Fortunately, the total size of '.id', '.type', '.access', '.count'
+ * and '.owner' is multiples of 8, and there's no issue for offset of the
+ * '.value' member.
+ */
+struct snd_ctl_elem_info_32 {
+ struct snd_ctl_elem_id id;
+ s32 type;
+ u32 access;
+ u32 count;
+ s32 owner;
+ union {
+ struct {
+ s32 min; /* long on ILP32. */
+ s32 max; /* long on ILP32. */
+ s32 step; /* long on ILP32. */
+ } integer;
+ struct {
+ u64 min;
+ u64 max;
+ u64 step;
+ } integer64;
+ struct {
+ u32 items;
+ u32 item;
+ s8 name[64];
+ u64 names_ptr;
+ u32 names_length;
+ } enumerated;
+ u8 reserved[128];
+ } value;
+ u16 dimen[4];
+ u8 reserved[64 - 4 * sizeof(u16)];
+} __packed;
+
+static int deserialize_from_elem_info_32(struct snd_ctl_file *ctl_file,
+ void *dst, void *src)
+{
+ struct snd_ctl_elem_info *data = dst;
+ struct snd_ctl_elem_info_32 *data32 = src;
+
+ data->id = data32->id;
+ data->type = data32->type;
+ data->access = data32->access;
+ data->count = data32->count;
+ data->owner = data32->owner;
+
+ if (data->type == SNDRV_CTL_ELEM_TYPE_INTEGER) {
+ data->value.integer.min = (s64)data32->value.integer.min;
+ data->value.integer.max = (s64)data32->value.integer.max;
+ data->value.integer.step = (s64)data32->value.integer.step;
+ /* Drop the rest of this field. */
+ } else {
+ /* Copy whole space of this field. */
+ memcpy(&data->value, &data32->value, sizeof(data->value));
+ }
+
+ memcpy(&data->dimen, &data32->dimen, sizeof(data->dimen));
+ memcpy(&data->reserved, &data32->reserved, sizeof(data->reserved));
+
+ return 0;
+}
+
+static int serialize_to_elem_info_32(struct snd_ctl_file *ctl_file, void *dst,
+ void *src)
+{
+ struct snd_ctl_elem_info_32 *data32 = dst;
+ struct snd_ctl_elem_info *data = src;
+
+ data32->id = data->id;
+ data32->type = data->type;
+ data32->access = data->access;
+ data32->count = data->count;
+ data32->owner = data->owner;
+
+ if (data->type == SNDRV_CTL_ELEM_TYPE_INTEGER) {
+ data32->value.integer.min = (s32)data->value.integer.min;
+ data32->value.integer.max = (s32)data->value.integer.max;
+ data32->value.integer.step = (s32)data->value.integer.step;
+ /* Drop rest of this field. */
+ } else {
+ /* Copy whole space of this field. */
+ memcpy(&data32->value, &data->value, sizeof(data32->value));
+ }
+
+ memcpy(&data32->dimen, &data->dimen, sizeof(data32->dimen));
+ memcpy(&data32->reserved, &data->reserved, sizeof(data32->reserved));
+
+ return 0;
+}
+
struct snd_ctl_elem_list32 {
u32 offset;
u32 space;
--
2.14.1
More information about the Alsa-devel
mailing list