xref: /linux/sound/virtio/virtio_kctl.c (revision d6568e3de42dd971a1356f7ba581e6600d53f0a0)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * virtio-snd: Virtio sound device
4  * Copyright (C) 2022 OpenSynergy GmbH
5  */
6 #include <sound/control.h>
7 #include <linux/virtio_config.h>
8 
9 #include "virtio_card.h"
10 
11 /* Map for converting VirtIO types to ALSA types. */
12 static const snd_ctl_elem_type_t g_v2a_type_map[] = {
13 	[VIRTIO_SND_CTL_TYPE_BOOLEAN] = SNDRV_CTL_ELEM_TYPE_BOOLEAN,
14 	[VIRTIO_SND_CTL_TYPE_INTEGER] = SNDRV_CTL_ELEM_TYPE_INTEGER,
15 	[VIRTIO_SND_CTL_TYPE_INTEGER64] = SNDRV_CTL_ELEM_TYPE_INTEGER64,
16 	[VIRTIO_SND_CTL_TYPE_ENUMERATED] = SNDRV_CTL_ELEM_TYPE_ENUMERATED,
17 	[VIRTIO_SND_CTL_TYPE_BYTES] = SNDRV_CTL_ELEM_TYPE_BYTES,
18 	[VIRTIO_SND_CTL_TYPE_IEC958] = SNDRV_CTL_ELEM_TYPE_IEC958
19 };
20 
21 /* Map for converting VirtIO access rights to ALSA access rights. */
22 static const unsigned int g_v2a_access_map[] = {
23 	[VIRTIO_SND_CTL_ACCESS_READ] = SNDRV_CTL_ELEM_ACCESS_READ,
24 	[VIRTIO_SND_CTL_ACCESS_WRITE] = SNDRV_CTL_ELEM_ACCESS_WRITE,
25 	[VIRTIO_SND_CTL_ACCESS_VOLATILE] = SNDRV_CTL_ELEM_ACCESS_VOLATILE,
26 	[VIRTIO_SND_CTL_ACCESS_INACTIVE] = SNDRV_CTL_ELEM_ACCESS_INACTIVE,
27 	[VIRTIO_SND_CTL_ACCESS_TLV_READ] = SNDRV_CTL_ELEM_ACCESS_TLV_READ,
28 	[VIRTIO_SND_CTL_ACCESS_TLV_WRITE] = SNDRV_CTL_ELEM_ACCESS_TLV_WRITE,
29 	[VIRTIO_SND_CTL_ACCESS_TLV_COMMAND] = SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND
30 };
31 
32 /* Map for converting VirtIO event masks to ALSA event masks. */
33 static const unsigned int g_v2a_mask_map[] = {
34 	[VIRTIO_SND_CTL_EVT_MASK_VALUE] = SNDRV_CTL_EVENT_MASK_VALUE,
35 	[VIRTIO_SND_CTL_EVT_MASK_INFO] = SNDRV_CTL_EVENT_MASK_INFO,
36 	[VIRTIO_SND_CTL_EVT_MASK_TLV] = SNDRV_CTL_EVENT_MASK_TLV
37 };
38 
39 /**
40  * virtsnd_kctl_info() - Returns information about the control.
41  * @kcontrol: ALSA control element.
42  * @uinfo: Element information.
43  *
44  * Context: Process context.
45  * Return: 0 on success, -errno on failure.
46  */
47 static int virtsnd_kctl_info(struct snd_kcontrol *kcontrol,
48 			     struct snd_ctl_elem_info *uinfo)
49 {
50 	struct virtio_snd *snd = kcontrol->private_data;
51 	struct virtio_kctl *kctl = &snd->kctls[kcontrol->private_value];
52 	struct virtio_snd_ctl_info *kinfo =
53 		&snd->kctl_infos[kcontrol->private_value];
54 	unsigned int i;
55 
56 	uinfo->type = g_v2a_type_map[le32_to_cpu(kinfo->type)];
57 	uinfo->count = le32_to_cpu(kinfo->count);
58 
59 	switch (uinfo->type) {
60 	case SNDRV_CTL_ELEM_TYPE_INTEGER:
61 		uinfo->value.integer.min =
62 			le32_to_cpu(kinfo->value.integer.min);
63 		uinfo->value.integer.max =
64 			le32_to_cpu(kinfo->value.integer.max);
65 		uinfo->value.integer.step =
66 			le32_to_cpu(kinfo->value.integer.step);
67 
68 		break;
69 	case SNDRV_CTL_ELEM_TYPE_INTEGER64:
70 		uinfo->value.integer64.min =
71 			le64_to_cpu(kinfo->value.integer64.min);
72 		uinfo->value.integer64.max =
73 			le64_to_cpu(kinfo->value.integer64.max);
74 		uinfo->value.integer64.step =
75 			le64_to_cpu(kinfo->value.integer64.step);
76 
77 		break;
78 	case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
79 		uinfo->value.enumerated.items =
80 			le32_to_cpu(kinfo->value.enumerated.items);
81 		i = uinfo->value.enumerated.item;
82 		if (i >= uinfo->value.enumerated.items)
83 			return -EINVAL;
84 
85 		strscpy(uinfo->value.enumerated.name, kctl->items[i].item,
86 			sizeof(uinfo->value.enumerated.name));
87 
88 		break;
89 	}
90 
91 	return 0;
92 }
93 
94 /**
95  * virtsnd_kctl_get() - Read the value from the control.
96  * @kcontrol: ALSA control element.
97  * @uvalue: Element value.
98  *
99  * Context: Process context.
100  * Return: 0 on success, -errno on failure.
101  */
102 static int virtsnd_kctl_get(struct snd_kcontrol *kcontrol,
103 			    struct snd_ctl_elem_value *uvalue)
104 {
105 	struct virtio_snd *snd = kcontrol->private_data;
106 	struct virtio_snd_ctl_info *kinfo =
107 		&snd->kctl_infos[kcontrol->private_value];
108 	unsigned int type = le32_to_cpu(kinfo->type);
109 	unsigned int count = le32_to_cpu(kinfo->count);
110 	struct virtio_snd_msg *msg;
111 	struct virtio_snd_ctl_hdr *hdr;
112 	struct virtio_snd_ctl_value *kvalue;
113 	size_t request_size = sizeof(*hdr);
114 	size_t response_size = sizeof(struct virtio_snd_hdr) + sizeof(*kvalue);
115 	unsigned int i;
116 	int rc;
117 
118 	msg = virtsnd_ctl_msg_alloc(request_size, response_size, GFP_KERNEL);
119 	if (!msg)
120 		return -ENOMEM;
121 
122 	virtsnd_ctl_msg_ref(msg);
123 
124 	hdr = virtsnd_ctl_msg_request(msg);
125 	hdr->hdr.code = cpu_to_le32(VIRTIO_SND_R_CTL_READ);
126 	hdr->control_id = cpu_to_le32(kcontrol->private_value);
127 
128 	rc = virtsnd_ctl_msg_send_sync(snd, msg);
129 	if (rc)
130 		goto on_failure;
131 
132 	kvalue = (void *)((u8 *)virtsnd_ctl_msg_response(msg) +
133 			  sizeof(struct virtio_snd_hdr));
134 
135 	switch (type) {
136 	case VIRTIO_SND_CTL_TYPE_BOOLEAN:
137 	case VIRTIO_SND_CTL_TYPE_INTEGER:
138 		for (i = 0; i < count; ++i)
139 			uvalue->value.integer.value[i] =
140 				le32_to_cpu(kvalue->value.integer[i]);
141 		break;
142 	case VIRTIO_SND_CTL_TYPE_INTEGER64:
143 		for (i = 0; i < count; ++i)
144 			uvalue->value.integer64.value[i] =
145 				le64_to_cpu(kvalue->value.integer64[i]);
146 		break;
147 	case VIRTIO_SND_CTL_TYPE_ENUMERATED:
148 		for (i = 0; i < count; ++i)
149 			uvalue->value.enumerated.item[i] =
150 				le32_to_cpu(kvalue->value.enumerated[i]);
151 		break;
152 	case VIRTIO_SND_CTL_TYPE_BYTES:
153 		memcpy(uvalue->value.bytes.data, kvalue->value.bytes, count);
154 		break;
155 	case VIRTIO_SND_CTL_TYPE_IEC958:
156 		memcpy(&uvalue->value.iec958, &kvalue->value.iec958,
157 		       sizeof(uvalue->value.iec958));
158 		break;
159 	}
160 
161 on_failure:
162 	virtsnd_ctl_msg_unref(msg);
163 
164 	return rc;
165 }
166 
167 /**
168  * virtsnd_kctl_put() - Write the value to the control.
169  * @kcontrol: ALSA control element.
170  * @uvalue: Element value.
171  *
172  * Context: Process context.
173  * Return: 0 on success, -errno on failure.
174  */
175 static int virtsnd_kctl_put(struct snd_kcontrol *kcontrol,
176 			    struct snd_ctl_elem_value *uvalue)
177 {
178 	struct virtio_snd *snd = kcontrol->private_data;
179 	struct virtio_snd_ctl_info *kinfo =
180 		&snd->kctl_infos[kcontrol->private_value];
181 	unsigned int type = le32_to_cpu(kinfo->type);
182 	unsigned int count = le32_to_cpu(kinfo->count);
183 	struct virtio_snd_msg *msg;
184 	struct virtio_snd_ctl_hdr *hdr;
185 	struct virtio_snd_ctl_value *kvalue;
186 	size_t request_size = sizeof(*hdr) + sizeof(*kvalue);
187 	size_t response_size = sizeof(struct virtio_snd_hdr);
188 	unsigned int i;
189 
190 	msg = virtsnd_ctl_msg_alloc(request_size, response_size, GFP_KERNEL);
191 	if (!msg)
192 		return -ENOMEM;
193 
194 	hdr = virtsnd_ctl_msg_request(msg);
195 	hdr->hdr.code = cpu_to_le32(VIRTIO_SND_R_CTL_WRITE);
196 	hdr->control_id = cpu_to_le32(kcontrol->private_value);
197 
198 	kvalue = (void *)((u8 *)hdr + sizeof(*hdr));
199 
200 	switch (type) {
201 	case VIRTIO_SND_CTL_TYPE_BOOLEAN:
202 	case VIRTIO_SND_CTL_TYPE_INTEGER:
203 		for (i = 0; i < count; ++i)
204 			kvalue->value.integer[i] =
205 				cpu_to_le32(uvalue->value.integer.value[i]);
206 		break;
207 	case VIRTIO_SND_CTL_TYPE_INTEGER64:
208 		for (i = 0; i < count; ++i)
209 			kvalue->value.integer64[i] =
210 				cpu_to_le64(uvalue->value.integer64.value[i]);
211 		break;
212 	case VIRTIO_SND_CTL_TYPE_ENUMERATED:
213 		for (i = 0; i < count; ++i)
214 			kvalue->value.enumerated[i] =
215 				cpu_to_le32(uvalue->value.enumerated.item[i]);
216 		break;
217 	case VIRTIO_SND_CTL_TYPE_BYTES:
218 		memcpy(kvalue->value.bytes, uvalue->value.bytes.data, count);
219 		break;
220 	case VIRTIO_SND_CTL_TYPE_IEC958:
221 		memcpy(&kvalue->value.iec958, &uvalue->value.iec958,
222 		       sizeof(kvalue->value.iec958));
223 		break;
224 	}
225 
226 	return virtsnd_ctl_msg_send_sync(snd, msg);
227 }
228 
229 /**
230  * virtsnd_kctl_tlv_op() - Perform an operation on the control's metadata.
231  * @kcontrol: ALSA control element.
232  * @op_flag: Operation code (SNDRV_CTL_TLV_OP_XXX).
233  * @size: Size of the TLV data in bytes.
234  * @utlv: TLV data.
235  *
236  * Context: Process context.
237  * Return: 0 on success, -errno on failure.
238  */
239 static int virtsnd_kctl_tlv_op(struct snd_kcontrol *kcontrol, int op_flag,
240 			       unsigned int size, unsigned int __user *utlv)
241 {
242 	struct virtio_snd *snd = kcontrol->private_data;
243 	struct virtio_snd_msg *msg;
244 	struct virtio_snd_ctl_hdr *hdr;
245 	unsigned int *tlv;
246 	struct scatterlist sg;
247 	int rc;
248 
249 	msg = virtsnd_ctl_msg_alloc(sizeof(*hdr), sizeof(struct virtio_snd_hdr),
250 				    GFP_KERNEL);
251 	if (!msg)
252 		return -ENOMEM;
253 
254 	tlv = kzalloc(size, GFP_KERNEL);
255 	if (!tlv) {
256 		virtsnd_ctl_msg_unref(msg);
257 		return -ENOMEM;
258 	}
259 
260 	sg_init_one(&sg, tlv, size);
261 
262 	hdr = virtsnd_ctl_msg_request(msg);
263 	hdr->control_id = cpu_to_le32(kcontrol->private_value);
264 
265 	switch (op_flag) {
266 	case SNDRV_CTL_TLV_OP_READ:
267 		hdr->hdr.code = cpu_to_le32(VIRTIO_SND_R_CTL_TLV_READ);
268 
269 		rc = virtsnd_ctl_msg_send(snd, msg, NULL, &sg, false);
270 		if (!rc) {
271 			if (copy_to_user(utlv, tlv, size))
272 				rc = -EFAULT;
273 		}
274 
275 		break;
276 	case SNDRV_CTL_TLV_OP_WRITE:
277 	case SNDRV_CTL_TLV_OP_CMD:
278 		if (op_flag == SNDRV_CTL_TLV_OP_WRITE)
279 			hdr->hdr.code = cpu_to_le32(VIRTIO_SND_R_CTL_TLV_WRITE);
280 		else
281 			hdr->hdr.code =
282 				cpu_to_le32(VIRTIO_SND_R_CTL_TLV_COMMAND);
283 
284 		if (copy_from_user(tlv, utlv, size))
285 			rc = -EFAULT;
286 		else
287 			rc = virtsnd_ctl_msg_send(snd, msg, &sg, NULL, false);
288 
289 		break;
290 	}
291 
292 	kfree(tlv);
293 
294 	return rc;
295 }
296 
297 /**
298  * virtsnd_kctl_get_enum_items() - Query items for the ENUMERATED element type.
299  * @snd: VirtIO sound device.
300  * @cid: Control element ID.
301  *
302  * This function is called during initial device initialization.
303  *
304  * Context: Any context that permits to sleep.
305  * Return: 0 on success, -errno on failure.
306  */
307 static int virtsnd_kctl_get_enum_items(struct virtio_snd *snd, unsigned int cid)
308 {
309 	struct virtio_device *vdev = snd->vdev;
310 	struct virtio_snd_ctl_info *kinfo = &snd->kctl_infos[cid];
311 	struct virtio_kctl *kctl = &snd->kctls[cid];
312 	struct virtio_snd_msg *msg;
313 	struct virtio_snd_ctl_hdr *hdr;
314 	unsigned int n = le32_to_cpu(kinfo->value.enumerated.items);
315 	struct scatterlist sg;
316 
317 	msg = virtsnd_ctl_msg_alloc(sizeof(*hdr),
318 				    sizeof(struct virtio_snd_hdr), GFP_KERNEL);
319 	if (!msg)
320 		return -ENOMEM;
321 
322 	kctl->items = devm_kcalloc(&vdev->dev, n, sizeof(*kctl->items),
323 				   GFP_KERNEL);
324 	if (!kctl->items) {
325 		virtsnd_ctl_msg_unref(msg);
326 		return -ENOMEM;
327 	}
328 
329 	sg_init_one(&sg, kctl->items, n * sizeof(*kctl->items));
330 
331 	hdr = virtsnd_ctl_msg_request(msg);
332 	hdr->hdr.code = cpu_to_le32(VIRTIO_SND_R_CTL_ENUM_ITEMS);
333 	hdr->control_id = cpu_to_le32(cid);
334 
335 	return virtsnd_ctl_msg_send(snd, msg, NULL, &sg, false);
336 }
337 
338 /**
339  * virtsnd_kctl_parse_cfg() - Parse the control element configuration.
340  * @snd: VirtIO sound device.
341  *
342  * This function is called during initial device initialization.
343  *
344  * Context: Any context that permits to sleep.
345  * Return: 0 on success, -errno on failure.
346  */
347 int virtsnd_kctl_parse_cfg(struct virtio_snd *snd)
348 {
349 	struct virtio_device *vdev = snd->vdev;
350 	u32 i;
351 	int rc;
352 
353 	virtio_cread_le(vdev, struct virtio_snd_config, controls,
354 			&snd->nkctls);
355 	if (!snd->nkctls)
356 		return 0;
357 
358 	snd->kctl_infos = devm_kcalloc(&vdev->dev, snd->nkctls,
359 				       sizeof(*snd->kctl_infos), GFP_KERNEL);
360 	if (!snd->kctl_infos)
361 		return -ENOMEM;
362 
363 	snd->kctls = devm_kcalloc(&vdev->dev, snd->nkctls, sizeof(*snd->kctls),
364 				  GFP_KERNEL);
365 	if (!snd->kctls)
366 		return -ENOMEM;
367 
368 	rc = virtsnd_ctl_query_info(snd, VIRTIO_SND_R_CTL_INFO, 0, snd->nkctls,
369 				    sizeof(*snd->kctl_infos), snd->kctl_infos);
370 	if (rc)
371 		return rc;
372 
373 	for (i = 0; i < snd->nkctls; ++i) {
374 		struct virtio_snd_ctl_info *kinfo = &snd->kctl_infos[i];
375 		unsigned int type = le32_to_cpu(kinfo->type);
376 
377 		if (type == VIRTIO_SND_CTL_TYPE_ENUMERATED) {
378 			rc = virtsnd_kctl_get_enum_items(snd, i);
379 			if (rc)
380 				return rc;
381 		}
382 	}
383 
384 	return 0;
385 }
386 
387 /**
388  * virtsnd_kctl_build_devs() - Build ALSA control elements.
389  * @snd: VirtIO sound device.
390  *
391  * Context: Any context that permits to sleep.
392  * Return: 0 on success, -errno on failure.
393  */
394 int virtsnd_kctl_build_devs(struct virtio_snd *snd)
395 {
396 	unsigned int cid;
397 
398 	for (cid = 0; cid < snd->nkctls; ++cid) {
399 		struct virtio_snd_ctl_info *kinfo = &snd->kctl_infos[cid];
400 		struct virtio_kctl *kctl = &snd->kctls[cid];
401 		struct snd_kcontrol_new kctl_new;
402 		unsigned int i;
403 		int rc;
404 
405 		memset(&kctl_new, 0, sizeof(kctl_new));
406 
407 		kctl_new.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
408 		kctl_new.name = kinfo->name;
409 		kctl_new.index = le32_to_cpu(kinfo->index);
410 
411 		for (i = 0; i < ARRAY_SIZE(g_v2a_access_map); ++i)
412 			if (le32_to_cpu(kinfo->access) & (1 << i))
413 				kctl_new.access |= g_v2a_access_map[i];
414 
415 		if (kctl_new.access & (SNDRV_CTL_ELEM_ACCESS_TLV_READ |
416 				       SNDRV_CTL_ELEM_ACCESS_TLV_WRITE |
417 				       SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND)) {
418 			kctl_new.access |= SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
419 			kctl_new.tlv.c = virtsnd_kctl_tlv_op;
420 		}
421 
422 		kctl_new.info = virtsnd_kctl_info;
423 		kctl_new.get = virtsnd_kctl_get;
424 		kctl_new.put = virtsnd_kctl_put;
425 		kctl_new.private_value = cid;
426 
427 		kctl->kctl = snd_ctl_new1(&kctl_new, snd);
428 		if (!kctl->kctl)
429 			return -ENOMEM;
430 
431 		rc = snd_ctl_add(snd->card, kctl->kctl);
432 		if (rc)
433 			return rc;
434 	}
435 
436 	return 0;
437 }
438 
439 /**
440  * virtsnd_kctl_event() - Handle the control element event notification.
441  * @snd: VirtIO sound device.
442  * @event: VirtIO sound event.
443  *
444  * Context: Interrupt context.
445  */
446 void virtsnd_kctl_event(struct virtio_snd *snd, struct virtio_snd_event *event)
447 {
448 	struct virtio_snd_ctl_event *kevent =
449 		(struct virtio_snd_ctl_event *)event;
450 	struct virtio_kctl *kctl;
451 	unsigned int cid = le16_to_cpu(kevent->control_id);
452 	unsigned int mask = 0;
453 	unsigned int i;
454 
455 	if (cid >= snd->nkctls)
456 		return;
457 
458 	for (i = 0; i < ARRAY_SIZE(g_v2a_mask_map); ++i)
459 		if (le16_to_cpu(kevent->mask) & (1 << i))
460 			mask |= g_v2a_mask_map[i];
461 
462 
463 	kctl = &snd->kctls[cid];
464 
465 	snd_ctl_notify(snd->card, mask, &kctl->kctl->id);
466 }
467