1 // SPDX-License-Identifier: BSD-3-Clause
2 //
3 // Copyright(c) 2019 Intel Corporation. All rights reserved.
4 //
5 // Author: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
6
7 /* Topology parser */
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <stdint.h>
12 #include <stddef.h>
13 #include <errno.h>
14 #include <string.h>
15 #include <ipc/topology.h>
16 #include <sof/lib/uuid.h>
17 #include <sof/ipc/topology.h>
18 #include <tplg_parser/topology.h>
19 #include <tplg_parser/tokens.h>
20
tplg_get_single_control(struct tplg_context * ctx,struct snd_soc_tplg_ctl_hdr ** ctl,struct snd_soc_tplg_private ** priv_data)21 int tplg_get_single_control(struct tplg_context *ctx,
22 struct snd_soc_tplg_ctl_hdr **ctl,
23 struct snd_soc_tplg_private **priv_data)
24 {
25 struct snd_soc_tplg_ctl_hdr *ctl_hdr;
26 struct snd_soc_tplg_mixer_control *mixer_ctl = NULL;
27 struct snd_soc_tplg_enum_control *enum_ctl = NULL;
28 struct snd_soc_tplg_bytes_control *bytes_ctl = NULL;
29
30 /* These are set if success */
31 *ctl = NULL;
32 *priv_data = NULL;
33
34 ctl_hdr = tplg_get(ctx);
35
36 /* load control based on type */
37 switch (ctl_hdr->ops.info) {
38 case SND_SOC_TPLG_CTL_VOLSW:
39 case SND_SOC_TPLG_CTL_STROBE:
40 case SND_SOC_TPLG_CTL_VOLSW_SX:
41 case SND_SOC_TPLG_CTL_VOLSW_XR_SX:
42 case SND_SOC_TPLG_CTL_RANGE:
43 case SND_SOC_TPLG_DAPM_CTL_VOLSW:
44 /* load mixer type control */
45 mixer_ctl = (struct snd_soc_tplg_mixer_control *)ctl_hdr;
46 if (priv_data)
47 *priv_data = &mixer_ctl->priv;
48 /* ctl is after private data */
49 *ctl = tplg_get_object_priv(ctx, mixer_ctl, mixer_ctl->priv.size);
50 break;
51
52 case SND_SOC_TPLG_CTL_ENUM:
53 case SND_SOC_TPLG_CTL_ENUM_VALUE:
54 case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE:
55 case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT:
56 case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE:
57 /* load enum type control */
58 enum_ctl = (struct snd_soc_tplg_enum_control *)ctl_hdr;
59 if (priv_data)
60 *priv_data = &enum_ctl->priv;
61 /* ctl is after private data */
62 *ctl = tplg_get_object_priv(ctx, enum_ctl, enum_ctl->priv.size);
63 break;
64 case SND_SOC_TPLG_CTL_BYTES:
65 /* load bytes type control */
66 bytes_ctl = (struct snd_soc_tplg_bytes_control *)ctl_hdr;
67 if (priv_data)
68 *priv_data = &bytes_ctl->priv;
69 /* ctl is after private data */
70 *ctl = tplg_get_object_priv(ctx, bytes_ctl, bytes_ctl->priv.size);
71 break;
72
73 default:
74 printf("info: control type %d not supported\n",
75 ctl_hdr->ops.info);
76 return -EINVAL;
77 }
78
79 return 0;
80 }
81
82 /* load dapm widget kcontrols
83 * we don't use controls in the fuzzer atm.
84 * so just skip to the next dapm widget
85 */
tplg_create_controls(struct tplg_context * ctx,int num_kcontrols,struct snd_soc_tplg_ctl_hdr * rctl,size_t max_ctl_size,void * object)86 int tplg_create_controls(struct tplg_context *ctx, int num_kcontrols,
87 struct snd_soc_tplg_ctl_hdr *rctl,
88 size_t max_ctl_size, void *object)
89 {
90 struct snd_soc_tplg_ctl_hdr *ctl_hdr = NULL;
91 struct snd_soc_tplg_mixer_control *mixer_ctl;
92 struct snd_soc_tplg_enum_control *enum_ctl;
93 struct snd_soc_tplg_bytes_control *bytes_ctl;
94 int j, ret = 0;
95
96 for (j = 0; j < num_kcontrols; j++) {
97
98 ctl_hdr = tplg_get(ctx);
99
100 /* load control based on type */
101 switch (ctl_hdr->ops.info) {
102 case SND_SOC_TPLG_CTL_VOLSW:
103 case SND_SOC_TPLG_CTL_STROBE:
104 case SND_SOC_TPLG_CTL_VOLSW_SX:
105 case SND_SOC_TPLG_CTL_VOLSW_XR_SX:
106 case SND_SOC_TPLG_CTL_RANGE:
107 case SND_SOC_TPLG_DAPM_CTL_VOLSW:
108 /* load mixer type control */
109 mixer_ctl = (struct snd_soc_tplg_mixer_control *)ctl_hdr;
110 /* ctl is after private data */
111 tplg_get_object_priv(ctx, mixer_ctl, mixer_ctl->priv.size);
112 break;
113
114 case SND_SOC_TPLG_CTL_ENUM:
115 case SND_SOC_TPLG_CTL_ENUM_VALUE:
116 case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE:
117 case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT:
118 case SND_SOC_TPLG_DAPM_CTL_ENUM_VALUE:
119 /* load enum_ctl type control */
120 enum_ctl = (struct snd_soc_tplg_enum_control *)ctl_hdr;
121 /* ctl is after private data */
122 tplg_get_object_priv(ctx, enum_ctl, enum_ctl->priv.size);
123 break;
124
125 case SND_SOC_TPLG_CTL_BYTES:
126 /* load bytes_ctl type control */
127 bytes_ctl = (struct snd_soc_tplg_bytes_control *)ctl_hdr;
128 /* ctl is after private data */
129 tplg_get_object_priv(ctx, bytes_ctl, bytes_ctl->priv.size);
130 break;
131 default:
132 printf("info: control type %d not supported\n",
133 ctl_hdr->ops.info);
134 return -EINVAL;
135 }
136
137 if (ctx->ctl_cb && object)
138 ctx->ctl_cb(ctl_hdr, object, ctx->ctl_arg);
139 }
140
141 if (rctl && ctl_hdr) {
142 /* make sure the CTL will fit if we need to copy it for others */
143 if (ctl_hdr->size > max_ctl_size) {
144 fprintf(stderr, "error: failed control control copy\n");
145 ret = -EINVAL;
146 goto err;
147 }
148 memcpy(rctl, ctl_hdr, ctl_hdr->size);
149 }
150 err:
151 return ret;
152 }
153