blob: b57c90aec1aace14426240e9a620ce1d547bcea5 [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,
Laxminath Kasam82252432015-05-29 18:37:11 +053052 TZ_NAME,
Ravi Kumar Alamanda14b0f2d2015-06-28 21:04:09 -070053 CONFIG_PARAMS,
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -070054} section_t;
55
56typedef void (* section_process_fn)(const XML_Char **attr);
57
58static void process_acdb_id(const XML_Char **attr);
Amit Shekhar5a39c912014-10-14 15:39:30 -070059static void process_bit_width(const XML_Char **attr);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -080060static void process_native_support(const XML_Char **attr);
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -070061static void process_pcm_id(const XML_Char **attr);
62static void process_backend_name(const XML_Char **attr);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -080063static void process_interface_name(const XML_Char **attr);
Laxminath Kasam82252432015-05-29 18:37:11 +053064static void process_tz_name(const XML_Char **attr);
Ravi Kumar Alamanda14b0f2d2015-06-28 21:04:09 -070065static void process_config_params(const XML_Char **attr);
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -070066static void process_root(const XML_Char **attr);
67
68static section_process_fn section_table[] = {
69 [ROOT] = process_root,
70 [ACDB] = process_acdb_id,
Amit Shekhar5a39c912014-10-14 15:39:30 -070071 [BITWIDTH] = process_bit_width,
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -080072 [NATIVESUPPORT] = process_native_support,
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -070073 [PCM_ID] = process_pcm_id,
74 [BACKEND_NAME] = process_backend_name,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -080075 [INTERFACE_NAME] = process_interface_name,
Laxminath Kasam82252432015-05-29 18:37:11 +053076 [TZ_NAME] = process_tz_name,
Ravi Kumar Alamanda14b0f2d2015-06-28 21:04:09 -070077 [CONFIG_PARAMS] = process_config_params,
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -070078};
79
80static section_t section;
81
Ravi Kumar Alamanda14b0f2d2015-06-28 21:04:09 -070082struct platform_info {
83 void *platform;
84 struct str_parms *kvpairs;
85};
86
87static struct platform_info my_data;
88
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -070089/*
90 * <audio_platform_info>
91 * <acdb_ids>
92 * <device name="???" acdb_id="???"/>
93 * ...
94 * ...
95 * </acdb_ids>
96 * <backend_names>
97 * <device name="???" backend="???"/>
98 * ...
99 * ...
100 * </backend_names>
101 * <pcm_ids>
102 * <usecase name="???" type="in/out" id="???"/>
103 * ...
104 * ...
105 * </pcm_ids>
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800106 * <interface_names>
Karthik Reddy Katta508eca42015-05-11 13:43:18 +0530107 * <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 -0800108 * ...
109 * ...
110 * </interface_names>
Laxminath Kasam82252432015-05-29 18:37:11 +0530111 * <tz_names>
112 * <device name="???" spkr_1_tz_name="???" spkr_2_tz_name="???"/>
113 * ...
114 * ...
115 * </tz_names>
Ravi Kumar Alamanda14b0f2d2015-06-28 21:04:09 -0700116 * <config_params>
117 * <param key="snd_card_name" value="msm8994-tomtom-mtp-snd-card"/>
118 * ...
119 * ...
120 * </config_params>
121 *
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -0700122 * </audio_platform_info>
123 */
124
125static void process_root(const XML_Char **attr __unused)
126{
127}
128
129/* mapping from usecase to pcm dev id */
130static void process_pcm_id(const XML_Char **attr)
131{
132 int index;
133
134 if (strcmp(attr[0], "name") != 0) {
Ravi Kumar Alamanda14b0f2d2015-06-28 21:04:09 -0700135 ALOGE("%s: 'name' not found, no pcm_id set!", __func__);
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -0700136 goto done;
137 }
138
139 index = platform_get_usecase_index((char *)attr[1]);
140 if (index < 0) {
141 ALOGE("%s: usecase %s not found!",
142 __func__, attr[1]);
143 goto done;
144 }
145
146 if (strcmp(attr[2], "type") != 0) {
147 ALOGE("%s: usecase type not mentioned", __func__);
148 goto done;
149 }
150
151 int type = -1;
152
153 if (!strcasecmp((char *)attr[3], "in")) {
154 type = 1;
155 } else if (!strcasecmp((char *)attr[3], "out")) {
156 type = 0;
157 } else {
158 ALOGE("%s: type must be IN or OUT", __func__);
159 goto done;
160 }
161
162 if (strcmp(attr[4], "id") != 0) {
163 ALOGE("%s: usecase id not mentioned", __func__);
164 goto done;
165 }
166
167 int id = atoi((char *)attr[5]);
168
169 if (platform_set_usecase_pcm_id(index, type, id) < 0) {
170 ALOGE("%s: usecase %s type %d id %d was not set!",
171 __func__, attr[1], type, id);
172 goto done;
173 }
174
175done:
176 return;
177}
178
179/* backend to be used for a device */
180static void process_backend_name(const XML_Char **attr)
181{
182 int index;
183
184 if (strcmp(attr[0], "name") != 0) {
185 ALOGE("%s: 'name' not found, no ACDB ID set!", __func__);
186 goto done;
187 }
188
189 index = platform_get_snd_device_index((char *)attr[1]);
190 if (index < 0) {
191 ALOGE("%s: Device %s not found, no ACDB ID set!",
192 __func__, attr[1]);
193 goto done;
194 }
195
196 if (strcmp(attr[2], "backend") != 0) {
197 ALOGE("%s: Device %s has no backend set!",
198 __func__, attr[1]);
199 goto done;
200 }
201
202 if (platform_set_snd_device_backend(index, attr[3]) < 0) {
203 ALOGE("%s: Device %s backend %s was not set!",
204 __func__, attr[1], attr[3]);
205 goto done;
206 }
207
208done:
209 return;
210}
211
212static void process_acdb_id(const XML_Char **attr)
Ben Romberger55886882014-01-10 13:49:02 -0800213{
Ben Romberger61764e32014-01-10 13:49:02 -0800214 int index;
Ben Romberger55886882014-01-10 13:49:02 -0800215
Ben Romberger61764e32014-01-10 13:49:02 -0800216 if (strcmp(attr[0], "name") != 0) {
217 ALOGE("%s: 'name' not found, no ACDB ID set!", __func__);
Ben Romberger55886882014-01-10 13:49:02 -0800218 goto done;
Ben Romberger61764e32014-01-10 13:49:02 -0800219 }
Ben Romberger55886882014-01-10 13:49:02 -0800220
Ben Romberger61764e32014-01-10 13:49:02 -0800221 index = platform_get_snd_device_index((char *)attr[1]);
222 if (index < 0) {
Helen Zeng6a16ad72014-02-23 22:04:44 -0800223 ALOGE("%s: Device %s in platform info xml not found, no ACDB ID set!",
224 __func__, attr[1]);
Ben Romberger55886882014-01-10 13:49:02 -0800225 goto done;
226 }
227
228 if (strcmp(attr[2], "acdb_id") != 0) {
Helen Zeng6a16ad72014-02-23 22:04:44 -0800229 ALOGE("%s: Device %s in platform info xml has no acdb_id, no ACDB ID set!",
230 __func__, attr[1]);
Ben Romberger55886882014-01-10 13:49:02 -0800231 goto done;
232 }
233
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -0700234 if (platform_set_snd_device_acdb_id(index, atoi((char *)attr[3])) < 0) {
235 ALOGE("%s: Device %s, ACDB ID %d was not set!",
Helen Zeng6a16ad72014-02-23 22:04:44 -0800236 __func__, attr[1], atoi((char *)attr[3]));
Ben Romberger55886882014-01-10 13:49:02 -0800237 goto done;
Ben Romberger61764e32014-01-10 13:49:02 -0800238 }
Ben Romberger55886882014-01-10 13:49:02 -0800239
Ben Romberger55886882014-01-10 13:49:02 -0800240done:
241 return;
242}
243
Amit Shekhar5a39c912014-10-14 15:39:30 -0700244static void process_bit_width(const XML_Char **attr)
245{
246 int index;
247
248 if (strcmp(attr[0], "name") != 0) {
249 ALOGE("%s: 'name' not found, no ACDB ID set!", __func__);
250 goto done;
251 }
252
253 index = platform_get_snd_device_index((char *)attr[1]);
254 if (index < 0) {
255 ALOGE("%s: Device %s in platform info xml not found, no ACDB ID set!",
256 __func__, attr[1]);
257 goto done;
258 }
259
260 if (strcmp(attr[2], "bit_width") != 0) {
261 ALOGE("%s: Device %s in platform info xml has no bit_width, no ACDB ID set!",
262 __func__, attr[1]);
263 goto done;
264 }
265
266 if (platform_set_snd_device_bit_width(index, atoi((char *)attr[3])) < 0) {
267 ALOGE("%s: Device %s, ACDB ID %d was not set!",
268 __func__, attr[1], atoi((char *)attr[3]));
269 goto done;
270 }
271
272done:
273 return;
274}
275
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800276static void process_interface_name(const XML_Char **attr)
277{
278 int ret;
279
280 if (strcmp(attr[0], "name") != 0) {
281 ALOGE("%s: 'name' not found, no Audio Interface set!", __func__);
282
283 goto done;
284 }
285
286 if (strcmp(attr[2], "interface") != 0) {
287 ALOGE("%s: Device %s has no Audio Interface set!",
288 __func__, attr[1]);
289
290 goto done;
291 }
292
Karthik Reddy Katta508eca42015-05-11 13:43:18 +0530293 if (strcmp(attr[4], "codec_type") != 0) {
294 ALOGE("%s: Device %s has no codec type set!",
295 __func__, attr[1]);
296
297 goto done;
298 }
299
300 ret = platform_set_audio_device_interface((char *)attr[1], (char *)attr[3],
301 (char *)attr[5]);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800302 if (ret < 0) {
303 ALOGE("%s: Audio Interface not set!", __func__);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800304 goto done;
305 }
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800306
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800307done:
308 return;
309}
310
311static void process_native_support(const XML_Char **attr)
312{
313 int index;
314
315 if (strcmp(attr[0], "name") != 0) {
316 ALOGE("%s: 'name' not found, no NATIVE_AUDIO_44.1 set!", __func__);
317 goto done;
318 }
319
320 if (strcmp(attr[2], "codec_support") != 0) {
321 ALOGE("%s: NATIVE_AUDIO_44.1 in platform info xml has no codec_support set!",
322 __func__);
323 goto done;
324 }
325
326 if (platform_set_native_support(atoi((char *)attr[3])) < 0) {
327 ALOGE("%s: Device %s, ACDB ID %d was not set!",
328 __func__, attr[1], atoi((char *)attr[3]));
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800329 goto done;
330 }
331
332done:
333 return;
334}
335
Laxminath Kasam82252432015-05-29 18:37:11 +0530336static void process_tz_name(const XML_Char **attr)
337{
338 int ret, index;
339
340 if (strcmp(attr[0], "name") != 0) {
341 ALOGE("%s: 'name' not found, no Audio Interface set!", __func__);
342 goto done;
343 }
344
345 index = platform_get_snd_device_index((char *)attr[1]);
346 if (index < 0) {
347 ALOGE("%s: Device %s not found, no snd device set!",
348 __func__, attr[1]);
349 goto done;
350 }
351
352 if (strcmp(attr[2], "spkr_1_tz_name") != 0) {
353 ALOGE("%s: Device %s has no spkr_1_tz_name set!",
354 __func__, attr[1]);
355 }
356
357 if (strcmp(attr[4], "spkr_2_tz_name") != 0) {
358 ALOGE("%s: Device %s has no spkr_2_tz_name set!",
359 __func__, attr[1]);
360 }
361
362 ret = platform_set_spkr_device_tz_names(index, (char *)attr[3], (char *)attr[5]);
363 if (ret < 0) {
364 ALOGE("%s: Audio Interface not set!", __func__);
365 goto done;
366 }
367
368done:
369 return;
370}
371
Ravi Kumar Alamanda14b0f2d2015-06-28 21:04:09 -0700372static void process_config_params(const XML_Char **attr)
373{
374 if (strcmp(attr[0], "key") != 0) {
375 ALOGE("%s: 'key' not found", __func__);
376 goto done;
377 }
378
379 if (strcmp(attr[2], "value") != 0) {
380 ALOGE("%s: 'value' not found", __func__);
381 goto done;
382 }
383
384 str_parms_add_str(my_data.kvpairs, (char*)attr[1], (char*)attr[3]);
385done:
386 return;
387}
388
389
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -0700390static void start_tag(void *userdata __unused, const XML_Char *tag_name,
Ben Romberger55886882014-01-10 13:49:02 -0800391 const XML_Char **attr)
392{
393 const XML_Char *attr_name = NULL;
394 const XML_Char *attr_value = NULL;
395 unsigned int i;
396
Amit Shekhar5a39c912014-10-14 15:39:30 -0700397 if (strcmp(tag_name, "bit_width_configs") == 0) {
398 section = BITWIDTH;
399 } else if (strcmp(tag_name, "acdb_ids") == 0) {
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -0700400 section = ACDB;
401 } else if (strcmp(tag_name, "pcm_ids") == 0) {
402 section = PCM_ID;
403 } else if (strcmp(tag_name, "backend_names") == 0) {
404 section = BACKEND_NAME;
Ravi Kumar Alamanda14b0f2d2015-06-28 21:04:09 -0700405 } else if (strcmp(tag_name, "config_params") == 0) {
406 section = CONFIG_PARAMS;
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800407 } else if (strcmp(tag_name, "interface_names") == 0) {
408 section = INTERFACE_NAME;
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800409 } else if (strcmp(tag_name, "native_configs") == 0) {
410 section = NATIVESUPPORT;
Laxminath Kasam82252432015-05-29 18:37:11 +0530411 } else if (strcmp(tag_name, "tz_names") == 0) {
412 section = TZ_NAME;
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -0700413 } else if (strcmp(tag_name, "device") == 0) {
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800414 if ((section != ACDB) && (section != BACKEND_NAME) && (section != BITWIDTH) &&
Laxminath Kasam82252432015-05-29 18:37:11 +0530415 (section != INTERFACE_NAME) && (section != TZ_NAME)) {
416 ALOGE("device tag only supported for acdb/backend names/bitwitdh/interface/tz names");
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -0700417 return;
418 }
419
420 /* call into process function for the current section */
421 section_process_fn fn = section_table[section];
422 fn(attr);
423 } else if (strcmp(tag_name, "usecase") == 0) {
424 if (section != PCM_ID) {
425 ALOGE("usecase tag only supported with PCM_ID section");
426 return;
427 }
428
429 section_process_fn fn = section_table[PCM_ID];
430 fn(attr);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800431 } else if (strcmp(tag_name, "feature") == 0) {
432 if (section != NATIVESUPPORT) {
433 ALOGE("usecase tag only supported with NATIVESUPPORT section");
434 return;
435 }
436
437 section_process_fn fn = section_table[NATIVESUPPORT];
438 fn(attr);
Ravi Kumar Alamanda14b0f2d2015-06-28 21:04:09 -0700439 } else if (strcmp(tag_name, "param") == 0) {
440 if (section != CONFIG_PARAMS) {
441 ALOGE("param tag only supported with CONFIG_PARAMS section");
442 return;
443 }
444
445 section_process_fn fn = section_table[section];
446 fn(attr);
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -0700447 }
Ben Romberger55886882014-01-10 13:49:02 -0800448
449 return;
450}
451
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -0700452static void end_tag(void *userdata __unused, const XML_Char *tag_name)
Ben Romberger55886882014-01-10 13:49:02 -0800453{
Amit Shekhar5a39c912014-10-14 15:39:30 -0700454 if (strcmp(tag_name, "bit_width_configs") == 0) {
455 section = ROOT;
456 } else if (strcmp(tag_name, "acdb_ids") == 0) {
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -0700457 section = ROOT;
458 } else if (strcmp(tag_name, "pcm_ids") == 0) {
459 section = ROOT;
460 } else if (strcmp(tag_name, "backend_names") == 0) {
461 section = ROOT;
Ravi Kumar Alamanda14b0f2d2015-06-28 21:04:09 -0700462 } else if (strcmp(tag_name, "config_params") == 0) {
463 section = ROOT;
464 platform_set_parameters(my_data.platform, my_data.kvpairs);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800465 } else if (strcmp(tag_name, "interface_names") == 0) {
466 section = ROOT;
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800467 } else if (strcmp(tag_name, "native_configs") == 0) {
468 section = ROOT;
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -0700469 }
Ben Romberger55886882014-01-10 13:49:02 -0800470}
471
Ravi Kumar Alamanda14b0f2d2015-06-28 21:04:09 -0700472int platform_info_init(const char *filename, void *platform)
Ben Romberger55886882014-01-10 13:49:02 -0800473{
474 XML_Parser parser;
475 FILE *file;
476 int ret = 0;
477 int bytes_read;
Ben Romberger55886882014-01-10 13:49:02 -0800478 void *buf;
479
Helen Zeng6a16ad72014-02-23 22:04:44 -0800480 file = fopen(filename, "r");
Haynes Mathew Georgef4da6fe2014-06-20 19:14:25 -0700481 section = ROOT;
482
Ben Romberger55886882014-01-10 13:49:02 -0800483 if (!file) {
484 ALOGD("%s: Failed to open %s, using defaults.",
Helen Zeng6a16ad72014-02-23 22:04:44 -0800485 __func__, filename);
Ben Romberger55886882014-01-10 13:49:02 -0800486 ret = -ENODEV;
487 goto done;
488 }
489
490 parser = XML_ParserCreate(NULL);
491 if (!parser) {
492 ALOGE("%s: Failed to create XML parser!", __func__);
493 ret = -ENODEV;
494 goto err_close_file;
495 }
496
Ravi Kumar Alamanda14b0f2d2015-06-28 21:04:09 -0700497 my_data.platform = platform;
498 my_data.kvpairs = str_parms_create();
499
Ben Romberger55886882014-01-10 13:49:02 -0800500 XML_SetElementHandler(parser, start_tag, end_tag);
501
502 while (1) {
503 buf = XML_GetBuffer(parser, BUF_SIZE);
504 if (buf == NULL) {
505 ALOGE("%s: XML_GetBuffer failed", __func__);
506 ret = -ENOMEM;
507 goto err_free_parser;
508 }
509
510 bytes_read = fread(buf, 1, BUF_SIZE, file);
511 if (bytes_read < 0) {
512 ALOGE("%s: fread failed, bytes read = %d", __func__, bytes_read);
513 ret = bytes_read;
514 goto err_free_parser;
515 }
516
517 if (XML_ParseBuffer(parser, bytes_read,
518 bytes_read == 0) == XML_STATUS_ERROR) {
519 ALOGE("%s: XML_ParseBuffer failed, for %s",
Helen Zeng6a16ad72014-02-23 22:04:44 -0800520 __func__, filename);
Ben Romberger55886882014-01-10 13:49:02 -0800521 ret = -EINVAL;
522 goto err_free_parser;
523 }
524
525 if (bytes_read == 0)
526 break;
527 }
528
Ben Romberger55886882014-01-10 13:49:02 -0800529err_free_parser:
530 XML_ParserFree(parser);
531err_close_file:
532 fclose(file);
533done:
534 return ret;
535}