blob: 4a788ab8102bacbeb08a8b8a9458e3a321380fc4 [file] [log] [blame]
Ben Romberger55886882014-01-10 13:49:02 -08001/*
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002 * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
Ben Romberger55886882014-01-10 13:49:02 -08003 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution.
13 * * Neither the name of The Linux Foundation nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
Ben Romberger61764e32014-01-10 13:49:02 -080030#define LOG_TAG "platform_info"
Ben Romberger55886882014-01-10 13:49:02 -080031#define LOG_NDDEBUG 0
32
33#include <errno.h>
34#include <stdio.h>
35#include <expat.h>
36#include <cutils/log.h>
Ravi Kumar Alamanda14b0f2d2015-06-28 21:04:09 -070037#include <cutils/str_parms.h>
Ben Romberger55886882014-01-10 13:49:02 -080038#include <audio_hw.h>
Ben Romberger61764e32014-01-10 13:49:02 -080039#include "platform_api.h"
40#include <platform.h>
Ben Romberger55886882014-01-10 13:49:02 -080041
Ben Romberger55886882014-01-10 13:49:02 -080042#define BUF_SIZE 1024
43
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -070044typedef enum {
45 ROOT,
46 ACDB,
Amit Shekhar5a39c912014-10-14 15:39:30 -070047 BITWIDTH,
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -080048 NATIVESUPPORT,
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -070049 PCM_ID,
50 BACKEND_NAME,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -080051 INTERFACE_NAME,
Ravi Kumar Alamanda14b0f2d2015-06-28 21:04:09 -070052 CONFIG_PARAMS,
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -070053} section_t;
54
55typedef void (* section_process_fn)(const XML_Char **attr);
56
57static void process_acdb_id(const XML_Char **attr);
Amit Shekhar5a39c912014-10-14 15:39:30 -070058static void process_bit_width(const XML_Char **attr);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -080059static void process_native_support(const XML_Char **attr);
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -070060static void process_pcm_id(const XML_Char **attr);
61static void process_backend_name(const XML_Char **attr);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -080062static void process_interface_name(const XML_Char **attr);
Ravi Kumar Alamanda14b0f2d2015-06-28 21:04:09 -070063static void process_config_params(const XML_Char **attr);
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -070064static void process_root(const XML_Char **attr);
65
66static section_process_fn section_table[] = {
67 [ROOT] = process_root,
68 [ACDB] = process_acdb_id,
Amit Shekhar5a39c912014-10-14 15:39:30 -070069 [BITWIDTH] = process_bit_width,
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -080070 [NATIVESUPPORT] = process_native_support,
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -070071 [PCM_ID] = process_pcm_id,
72 [BACKEND_NAME] = process_backend_name,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -080073 [INTERFACE_NAME] = process_interface_name,
Ravi Kumar Alamanda14b0f2d2015-06-28 21:04:09 -070074 [CONFIG_PARAMS] = process_config_params,
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -070075};
76
77static section_t section;
78
Ravi Kumar Alamanda14b0f2d2015-06-28 21:04:09 -070079struct platform_info {
80 void *platform;
81 struct str_parms *kvpairs;
82};
83
84static struct platform_info my_data;
85
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -070086/*
87 * <audio_platform_info>
88 * <acdb_ids>
89 * <device name="???" acdb_id="???"/>
90 * ...
91 * ...
92 * </acdb_ids>
93 * <backend_names>
94 * <device name="???" backend="???"/>
95 * ...
96 * ...
97 * </backend_names>
98 * <pcm_ids>
99 * <usecase name="???" type="in/out" id="???"/>
100 * ...
101 * ...
102 * </pcm_ids>
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800103 * <interface_names>
Karthik Reddy Katta508eca42015-05-11 13:43:18 +0530104 * <device name="Use audio device name here, not sound device name" interface="PRIMARY_I2S" codec_type="external/internal"/>
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800105 * ...
106 * ...
107 * </interface_names>
Ravi Kumar Alamanda14b0f2d2015-06-28 21:04:09 -0700108 * <config_params>
109 * <param key="snd_card_name" value="msm8994-tomtom-mtp-snd-card"/>
110 * ...
111 * ...
112 * </config_params>
113 *
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -0700114 * </audio_platform_info>
115 */
116
117static void process_root(const XML_Char **attr __unused)
118{
119}
120
121/* mapping from usecase to pcm dev id */
122static void process_pcm_id(const XML_Char **attr)
123{
124 int index;
125
126 if (strcmp(attr[0], "name") != 0) {
Ravi Kumar Alamanda14b0f2d2015-06-28 21:04:09 -0700127 ALOGE("%s: 'name' not found, no pcm_id set!", __func__);
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -0700128 goto done;
129 }
130
131 index = platform_get_usecase_index((char *)attr[1]);
132 if (index < 0) {
133 ALOGE("%s: usecase %s not found!",
134 __func__, attr[1]);
135 goto done;
136 }
137
138 if (strcmp(attr[2], "type") != 0) {
139 ALOGE("%s: usecase type not mentioned", __func__);
140 goto done;
141 }
142
143 int type = -1;
144
145 if (!strcasecmp((char *)attr[3], "in")) {
146 type = 1;
147 } else if (!strcasecmp((char *)attr[3], "out")) {
148 type = 0;
149 } else {
150 ALOGE("%s: type must be IN or OUT", __func__);
151 goto done;
152 }
153
154 if (strcmp(attr[4], "id") != 0) {
155 ALOGE("%s: usecase id not mentioned", __func__);
156 goto done;
157 }
158
159 int id = atoi((char *)attr[5]);
160
161 if (platform_set_usecase_pcm_id(index, type, id) < 0) {
162 ALOGE("%s: usecase %s type %d id %d was not set!",
163 __func__, attr[1], type, id);
164 goto done;
165 }
166
167done:
168 return;
169}
170
171/* backend to be used for a device */
172static void process_backend_name(const XML_Char **attr)
173{
174 int index;
175
176 if (strcmp(attr[0], "name") != 0) {
177 ALOGE("%s: 'name' not found, no ACDB ID set!", __func__);
178 goto done;
179 }
180
181 index = platform_get_snd_device_index((char *)attr[1]);
182 if (index < 0) {
183 ALOGE("%s: Device %s not found, no ACDB ID set!",
184 __func__, attr[1]);
185 goto done;
186 }
187
188 if (strcmp(attr[2], "backend") != 0) {
189 ALOGE("%s: Device %s has no backend set!",
190 __func__, attr[1]);
191 goto done;
192 }
193
194 if (platform_set_snd_device_backend(index, attr[3]) < 0) {
195 ALOGE("%s: Device %s backend %s was not set!",
196 __func__, attr[1], attr[3]);
197 goto done;
198 }
199
200done:
201 return;
202}
203
204static void process_acdb_id(const XML_Char **attr)
Ben Romberger55886882014-01-10 13:49:02 -0800205{
Ben Romberger61764e32014-01-10 13:49:02 -0800206 int index;
Ben Romberger55886882014-01-10 13:49:02 -0800207
Ben Romberger61764e32014-01-10 13:49:02 -0800208 if (strcmp(attr[0], "name") != 0) {
209 ALOGE("%s: 'name' not found, no ACDB ID set!", __func__);
Ben Romberger55886882014-01-10 13:49:02 -0800210 goto done;
Ben Romberger61764e32014-01-10 13:49:02 -0800211 }
Ben Romberger55886882014-01-10 13:49:02 -0800212
Ben Romberger61764e32014-01-10 13:49:02 -0800213 index = platform_get_snd_device_index((char *)attr[1]);
214 if (index < 0) {
Helen Zeng6a16ad72014-02-23 22:04:44 -0800215 ALOGE("%s: Device %s in platform info xml not found, no ACDB ID set!",
216 __func__, attr[1]);
Ben Romberger55886882014-01-10 13:49:02 -0800217 goto done;
218 }
219
220 if (strcmp(attr[2], "acdb_id") != 0) {
Helen Zeng6a16ad72014-02-23 22:04:44 -0800221 ALOGE("%s: Device %s in platform info xml has no acdb_id, no ACDB ID set!",
222 __func__, attr[1]);
Ben Romberger55886882014-01-10 13:49:02 -0800223 goto done;
224 }
225
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -0700226 if (platform_set_snd_device_acdb_id(index, atoi((char *)attr[3])) < 0) {
227 ALOGE("%s: Device %s, ACDB ID %d was not set!",
Helen Zeng6a16ad72014-02-23 22:04:44 -0800228 __func__, attr[1], atoi((char *)attr[3]));
Ben Romberger55886882014-01-10 13:49:02 -0800229 goto done;
Ben Romberger61764e32014-01-10 13:49:02 -0800230 }
Ben Romberger55886882014-01-10 13:49:02 -0800231
Ben Romberger55886882014-01-10 13:49:02 -0800232done:
233 return;
234}
235
Amit Shekhar5a39c912014-10-14 15:39:30 -0700236static void process_bit_width(const XML_Char **attr)
237{
238 int index;
239
240 if (strcmp(attr[0], "name") != 0) {
241 ALOGE("%s: 'name' not found, no ACDB ID set!", __func__);
242 goto done;
243 }
244
245 index = platform_get_snd_device_index((char *)attr[1]);
246 if (index < 0) {
247 ALOGE("%s: Device %s in platform info xml not found, no ACDB ID set!",
248 __func__, attr[1]);
249 goto done;
250 }
251
252 if (strcmp(attr[2], "bit_width") != 0) {
253 ALOGE("%s: Device %s in platform info xml has no bit_width, no ACDB ID set!",
254 __func__, attr[1]);
255 goto done;
256 }
257
258 if (platform_set_snd_device_bit_width(index, atoi((char *)attr[3])) < 0) {
259 ALOGE("%s: Device %s, ACDB ID %d was not set!",
260 __func__, attr[1], atoi((char *)attr[3]));
261 goto done;
262 }
263
264done:
265 return;
266}
267
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800268static void process_interface_name(const XML_Char **attr)
269{
270 int ret;
271
272 if (strcmp(attr[0], "name") != 0) {
273 ALOGE("%s: 'name' not found, no Audio Interface set!", __func__);
274
275 goto done;
276 }
277
278 if (strcmp(attr[2], "interface") != 0) {
279 ALOGE("%s: Device %s has no Audio Interface set!",
280 __func__, attr[1]);
281
282 goto done;
283 }
284
Karthik Reddy Katta508eca42015-05-11 13:43:18 +0530285 if (strcmp(attr[4], "codec_type") != 0) {
286 ALOGE("%s: Device %s has no codec type set!",
287 __func__, attr[1]);
288
289 goto done;
290 }
291
292 ret = platform_set_audio_device_interface((char *)attr[1], (char *)attr[3],
293 (char *)attr[5]);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800294 if (ret < 0) {
295 ALOGE("%s: Audio Interface not set!", __func__);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800296 goto done;
297 }
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800298
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800299done:
300 return;
301}
302
303static void process_native_support(const XML_Char **attr)
304{
305 int index;
306
307 if (strcmp(attr[0], "name") != 0) {
308 ALOGE("%s: 'name' not found, no NATIVE_AUDIO_44.1 set!", __func__);
309 goto done;
310 }
311
312 if (strcmp(attr[2], "codec_support") != 0) {
313 ALOGE("%s: NATIVE_AUDIO_44.1 in platform info xml has no codec_support set!",
314 __func__);
315 goto done;
316 }
317
318 if (platform_set_native_support(atoi((char *)attr[3])) < 0) {
319 ALOGE("%s: Device %s, ACDB ID %d was not set!",
320 __func__, attr[1], atoi((char *)attr[3]));
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800321 goto done;
322 }
323
324done:
325 return;
326}
327
Ravi Kumar Alamanda14b0f2d2015-06-28 21:04:09 -0700328static void process_config_params(const XML_Char **attr)
329{
330 if (strcmp(attr[0], "key") != 0) {
331 ALOGE("%s: 'key' not found", __func__);
332 goto done;
333 }
334
335 if (strcmp(attr[2], "value") != 0) {
336 ALOGE("%s: 'value' not found", __func__);
337 goto done;
338 }
339
340 str_parms_add_str(my_data.kvpairs, (char*)attr[1], (char*)attr[3]);
341done:
342 return;
343}
344
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -0700345static void start_tag(void *userdata __unused, const XML_Char *tag_name,
Ben Romberger55886882014-01-10 13:49:02 -0800346 const XML_Char **attr)
347{
348 const XML_Char *attr_name = NULL;
349 const XML_Char *attr_value = NULL;
350 unsigned int i;
351
Amit Shekhar5a39c912014-10-14 15:39:30 -0700352 if (strcmp(tag_name, "bit_width_configs") == 0) {
353 section = BITWIDTH;
354 } else if (strcmp(tag_name, "acdb_ids") == 0) {
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -0700355 section = ACDB;
356 } else if (strcmp(tag_name, "pcm_ids") == 0) {
357 section = PCM_ID;
358 } else if (strcmp(tag_name, "backend_names") == 0) {
359 section = BACKEND_NAME;
Ravi Kumar Alamanda14b0f2d2015-06-28 21:04:09 -0700360 } else if (strcmp(tag_name, "config_params") == 0) {
361 section = CONFIG_PARAMS;
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800362 } else if (strcmp(tag_name, "interface_names") == 0) {
363 section = INTERFACE_NAME;
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800364 } else if (strcmp(tag_name, "native_configs") == 0) {
365 section = NATIVESUPPORT;
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -0700366 } else if (strcmp(tag_name, "device") == 0) {
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800367 if ((section != ACDB) && (section != BACKEND_NAME) && (section != BITWIDTH) &&
Vidyakumar Athotab3cfd132015-08-17 14:07:59 -0700368 (section != INTERFACE_NAME)) {
369 ALOGE("device tag only supported for acdb/backend names/bitwitdh/interface names");
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -0700370 return;
371 }
372
373 /* call into process function for the current section */
374 section_process_fn fn = section_table[section];
375 fn(attr);
376 } else if (strcmp(tag_name, "usecase") == 0) {
377 if (section != PCM_ID) {
378 ALOGE("usecase tag only supported with PCM_ID section");
379 return;
380 }
381
382 section_process_fn fn = section_table[PCM_ID];
383 fn(attr);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800384 } else if (strcmp(tag_name, "feature") == 0) {
385 if (section != NATIVESUPPORT) {
386 ALOGE("usecase tag only supported with NATIVESUPPORT section");
387 return;
388 }
389
390 section_process_fn fn = section_table[NATIVESUPPORT];
391 fn(attr);
Ravi Kumar Alamanda14b0f2d2015-06-28 21:04:09 -0700392 } else if (strcmp(tag_name, "param") == 0) {
393 if (section != CONFIG_PARAMS) {
394 ALOGE("param tag only supported with CONFIG_PARAMS section");
395 return;
396 }
397
398 section_process_fn fn = section_table[section];
399 fn(attr);
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -0700400 }
Ben Romberger55886882014-01-10 13:49:02 -0800401
402 return;
403}
404
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -0700405static void end_tag(void *userdata __unused, const XML_Char *tag_name)
Ben Romberger55886882014-01-10 13:49:02 -0800406{
Amit Shekhar5a39c912014-10-14 15:39:30 -0700407 if (strcmp(tag_name, "bit_width_configs") == 0) {
408 section = ROOT;
409 } else if (strcmp(tag_name, "acdb_ids") == 0) {
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -0700410 section = ROOT;
411 } else if (strcmp(tag_name, "pcm_ids") == 0) {
412 section = ROOT;
413 } else if (strcmp(tag_name, "backend_names") == 0) {
414 section = ROOT;
Ravi Kumar Alamanda14b0f2d2015-06-28 21:04:09 -0700415 } else if (strcmp(tag_name, "config_params") == 0) {
416 section = ROOT;
417 platform_set_parameters(my_data.platform, my_data.kvpairs);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800418 } else if (strcmp(tag_name, "interface_names") == 0) {
419 section = ROOT;
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800420 } else if (strcmp(tag_name, "native_configs") == 0) {
421 section = ROOT;
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -0700422 }
Ben Romberger55886882014-01-10 13:49:02 -0800423}
424
Ravi Kumar Alamanda14b0f2d2015-06-28 21:04:09 -0700425int platform_info_init(const char *filename, void *platform)
Ben Romberger55886882014-01-10 13:49:02 -0800426{
427 XML_Parser parser;
428 FILE *file;
429 int ret = 0;
430 int bytes_read;
Ben Romberger55886882014-01-10 13:49:02 -0800431 void *buf;
432
Helen Zeng6a16ad72014-02-23 22:04:44 -0800433 file = fopen(filename, "r");
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -0700434 section = ROOT;
435
Ben Romberger55886882014-01-10 13:49:02 -0800436 if (!file) {
437 ALOGD("%s: Failed to open %s, using defaults.",
Helen Zeng6a16ad72014-02-23 22:04:44 -0800438 __func__, filename);
Ben Romberger55886882014-01-10 13:49:02 -0800439 ret = -ENODEV;
440 goto done;
441 }
442
443 parser = XML_ParserCreate(NULL);
444 if (!parser) {
445 ALOGE("%s: Failed to create XML parser!", __func__);
446 ret = -ENODEV;
447 goto err_close_file;
448 }
449
Ravi Kumar Alamanda14b0f2d2015-06-28 21:04:09 -0700450 my_data.platform = platform;
451 my_data.kvpairs = str_parms_create();
452
Ben Romberger55886882014-01-10 13:49:02 -0800453 XML_SetElementHandler(parser, start_tag, end_tag);
454
455 while (1) {
456 buf = XML_GetBuffer(parser, BUF_SIZE);
457 if (buf == NULL) {
458 ALOGE("%s: XML_GetBuffer failed", __func__);
459 ret = -ENOMEM;
460 goto err_free_parser;
461 }
462
463 bytes_read = fread(buf, 1, BUF_SIZE, file);
464 if (bytes_read < 0) {
465 ALOGE("%s: fread failed, bytes read = %d", __func__, bytes_read);
466 ret = bytes_read;
467 goto err_free_parser;
468 }
469
470 if (XML_ParseBuffer(parser, bytes_read,
471 bytes_read == 0) == XML_STATUS_ERROR) {
472 ALOGE("%s: XML_ParseBuffer failed, for %s",
Helen Zeng6a16ad72014-02-23 22:04:44 -0800473 __func__, filename);
Ben Romberger55886882014-01-10 13:49:02 -0800474 ret = -EINVAL;
475 goto err_free_parser;
476 }
477
478 if (bytes_read == 0)
479 break;
480 }
481
Ben Romberger55886882014-01-10 13:49:02 -0800482err_free_parser:
483 XML_ParserFree(parser);
484err_close_file:
485 fclose(file);
486done:
487 return ret;
488}