audio_route.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986
  1. /*
  2. * Copyright (C) 2013 The Android Open Source Project
  3. * Inspired by TinyHW, written by Mark Brown at Wolfson Micro
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. #define LOG_TAG "audio_route"
  18. /*#define LOG_NDEBUG 0*/
  19. #include <errno.h>
  20. #include <expat.h>
  21. #include <stdbool.h>
  22. #include <stdio.h>
  23. #include <string.h>
  24. #include <log/log.h>
  25. #include <tinyalsa/asoundlib.h>
  26. #define BUF_SIZE 1024
  27. #define MIXER_XML_PATH "/system/etc/mixer_paths.xml"
  28. #define INITIAL_MIXER_PATH_SIZE 8
  29. union ctl_values {
  30. int *enumerated;
  31. long *integer;
  32. void *ptr;
  33. unsigned char *bytes;
  34. };
  35. struct mixer_state {
  36. struct mixer_ctl *ctl;
  37. unsigned int num_values;
  38. union ctl_values old_value;
  39. union ctl_values new_value;
  40. union ctl_values reset_value;
  41. unsigned int active_count;
  42. };
  43. struct mixer_setting {
  44. unsigned int ctl_index;
  45. unsigned int num_values;
  46. unsigned int type;
  47. union ctl_values value;
  48. };
  49. struct mixer_value {
  50. unsigned int ctl_index;
  51. int index;
  52. long value;
  53. };
  54. struct mixer_path {
  55. char *name;
  56. unsigned int size;
  57. unsigned int length;
  58. struct mixer_setting *setting;
  59. };
  60. struct audio_route {
  61. struct mixer *mixer;
  62. unsigned int num_mixer_ctls;
  63. struct mixer_state *mixer_state;
  64. unsigned int mixer_path_size;
  65. unsigned int num_mixer_paths;
  66. struct mixer_path *mixer_path;
  67. };
  68. struct config_parse_state {
  69. struct audio_route *ar;
  70. struct mixer_path *path;
  71. int level;
  72. };
  73. /* path functions */
  74. static bool is_supported_ctl_type(enum mixer_ctl_type type)
  75. {
  76. switch (type) {
  77. case MIXER_CTL_TYPE_BOOL:
  78. case MIXER_CTL_TYPE_INT:
  79. case MIXER_CTL_TYPE_ENUM:
  80. case MIXER_CTL_TYPE_BYTE:
  81. return true;
  82. default:
  83. return false;
  84. }
  85. }
  86. /* as they match in alsa */
  87. static size_t sizeof_ctl_type(enum mixer_ctl_type type) {
  88. switch (type) {
  89. case MIXER_CTL_TYPE_BOOL:
  90. case MIXER_CTL_TYPE_INT:
  91. return sizeof(long);
  92. case MIXER_CTL_TYPE_ENUM:
  93. return sizeof(int);
  94. case MIXER_CTL_TYPE_BYTE:
  95. return sizeof(unsigned char);
  96. case MIXER_CTL_TYPE_INT64:
  97. case MIXER_CTL_TYPE_IEC958:
  98. case MIXER_CTL_TYPE_UNKNOWN:
  99. default:
  100. LOG_ALWAYS_FATAL("Unsupported mixer ctl type: %d, check type before calling", (int)type);
  101. return 0;
  102. }
  103. }
  104. static inline struct mixer_ctl *index_to_ctl(struct audio_route *ar,
  105. unsigned int ctl_index)
  106. {
  107. return ar->mixer_state[ctl_index].ctl;
  108. }
  109. #if 0
  110. static void path_print(struct audio_route *ar, struct mixer_path *path)
  111. {
  112. unsigned int i;
  113. unsigned int j;
  114. ALOGE("Path: %s, length: %d", path->name, path->length);
  115. for (i = 0; i < path->length; i++) {
  116. struct mixer_ctl *ctl = index_to_ctl(ar, path->setting[i].ctl_index);
  117. ALOGE(" id=%d: ctl=%s", i, mixer_ctl_get_name(ctl));
  118. if (mixer_ctl_get_type(ctl) == MIXER_CTL_TYPE_BYTE) {
  119. for (j = 0; j < path->setting[i].num_values; j++)
  120. ALOGE(" id=%d value=0x%02x", j, path->setting[i].value.bytes[j]);
  121. } else if (mixer_ctl_get_type(ctl) == MIXER_CTL_TYPE_ENUM) {
  122. for (j = 0; j < path->setting[i].num_values; j++)
  123. ALOGE(" id=%d value=%d", j, path->setting[i].value.enumerated[j]);
  124. } else {
  125. for (j = 0; j < path->setting[i].num_values; j++)
  126. ALOGE(" id=%d value=%ld", j, path->setting[i].value.integer[j]);
  127. }
  128. }
  129. }
  130. #endif
  131. static void path_free(struct audio_route *ar)
  132. {
  133. unsigned int i;
  134. for (i = 0; i < ar->num_mixer_paths; i++) {
  135. free(ar->mixer_path[i].name);
  136. if (ar->mixer_path[i].setting) {
  137. size_t j;
  138. for (j = 0; j < ar->mixer_path[i].length; j++) {
  139. free(ar->mixer_path[i].setting[j].value.ptr);
  140. }
  141. free(ar->mixer_path[i].setting);
  142. ar->mixer_path[i].size = 0;
  143. ar->mixer_path[i].length = 0;
  144. ar->mixer_path[i].setting = NULL;
  145. }
  146. }
  147. free(ar->mixer_path);
  148. ar->mixer_path = NULL;
  149. ar->mixer_path_size = 0;
  150. ar->num_mixer_paths = 0;
  151. }
  152. static struct mixer_path *path_get_by_name(struct audio_route *ar,
  153. const char *name)
  154. {
  155. unsigned int i;
  156. for (i = 0; i < ar->num_mixer_paths; i++)
  157. if (strcmp(ar->mixer_path[i].name, name) == 0)
  158. return &ar->mixer_path[i];
  159. return NULL;
  160. }
  161. static struct mixer_path *path_create(struct audio_route *ar, const char *name)
  162. {
  163. struct mixer_path *new_mixer_path = NULL;
  164. if (path_get_by_name(ar, name)) {
  165. ALOGE("Path name '%s' already exists", name);
  166. return NULL;
  167. }
  168. /* check if we need to allocate more space for mixer paths */
  169. if (ar->mixer_path_size <= ar->num_mixer_paths) {
  170. if (ar->mixer_path_size == 0)
  171. ar->mixer_path_size = INITIAL_MIXER_PATH_SIZE;
  172. else
  173. ar->mixer_path_size *= 2;
  174. new_mixer_path = realloc(ar->mixer_path, ar->mixer_path_size *
  175. sizeof(struct mixer_path));
  176. if (new_mixer_path == NULL) {
  177. ALOGE("Unable to allocate more paths");
  178. return NULL;
  179. } else {
  180. ar->mixer_path = new_mixer_path;
  181. }
  182. }
  183. /* initialise the new mixer path */
  184. ar->mixer_path[ar->num_mixer_paths].name = strdup(name);
  185. ar->mixer_path[ar->num_mixer_paths].size = 0;
  186. ar->mixer_path[ar->num_mixer_paths].length = 0;
  187. ar->mixer_path[ar->num_mixer_paths].setting = NULL;
  188. /* return the mixer path just added, then increment number of them */
  189. return &ar->mixer_path[ar->num_mixer_paths++];
  190. }
  191. static int find_ctl_index_in_path(struct mixer_path *path,
  192. unsigned int ctl_index)
  193. {
  194. unsigned int i;
  195. for (i = 0; i < path->length; i++)
  196. if (path->setting[i].ctl_index == ctl_index)
  197. return i;
  198. return -1;
  199. }
  200. static int alloc_path_setting(struct mixer_path *path)
  201. {
  202. struct mixer_setting *new_path_setting;
  203. int path_index;
  204. /* check if we need to allocate more space for path settings */
  205. if (path->size <= path->length) {
  206. if (path->size == 0)
  207. path->size = INITIAL_MIXER_PATH_SIZE;
  208. else
  209. path->size *= 2;
  210. new_path_setting = realloc(path->setting,
  211. path->size * sizeof(struct mixer_setting));
  212. if (new_path_setting == NULL) {
  213. ALOGE("Unable to allocate more path settings");
  214. return -1;
  215. } else {
  216. path->setting = new_path_setting;
  217. }
  218. }
  219. path_index = path->length;
  220. path->length++;
  221. return path_index;
  222. }
  223. static int path_add_setting(struct audio_route *ar, struct mixer_path *path,
  224. struct mixer_setting *setting)
  225. {
  226. int path_index;
  227. if (find_ctl_index_in_path(path, setting->ctl_index) != -1) {
  228. struct mixer_ctl *ctl = index_to_ctl(ar, setting->ctl_index);
  229. ALOGE("Control '%s' already exists in path '%s'",
  230. mixer_ctl_get_name(ctl), path->name);
  231. return -1;
  232. }
  233. if (!is_supported_ctl_type(setting->type)) {
  234. ALOGE("unsupported type %d", (int)setting->type);
  235. return -1;
  236. }
  237. path_index = alloc_path_setting(path);
  238. if (path_index < 0)
  239. return -1;
  240. path->setting[path_index].ctl_index = setting->ctl_index;
  241. path->setting[path_index].type = setting->type;
  242. path->setting[path_index].num_values = setting->num_values;
  243. size_t value_sz = sizeof_ctl_type(setting->type);
  244. path->setting[path_index].value.ptr = calloc(setting->num_values, value_sz);
  245. /* copy all values */
  246. memcpy(path->setting[path_index].value.ptr, setting->value.ptr,
  247. setting->num_values * value_sz);
  248. return 0;
  249. }
  250. static int path_add_value(struct audio_route *ar, struct mixer_path *path,
  251. struct mixer_value *mixer_value)
  252. {
  253. unsigned int i;
  254. int path_index;
  255. unsigned int num_values;
  256. struct mixer_ctl *ctl;
  257. /* Check that mixer value index is within range */
  258. ctl = index_to_ctl(ar, mixer_value->ctl_index);
  259. num_values = mixer_ctl_get_num_values(ctl);
  260. if (mixer_value->index >= (int)num_values) {
  261. ALOGE("mixer index %d is out of range for '%s'", mixer_value->index,
  262. mixer_ctl_get_name(ctl));
  263. return -1;
  264. }
  265. path_index = find_ctl_index_in_path(path, mixer_value->ctl_index);
  266. if (path_index < 0) {
  267. /* New path */
  268. enum mixer_ctl_type type = mixer_ctl_get_type(ctl);
  269. if (!is_supported_ctl_type(type)) {
  270. ALOGE("unsupported type %d", (int)type);
  271. return -1;
  272. }
  273. path_index = alloc_path_setting(path);
  274. if (path_index < 0)
  275. return -1;
  276. /* initialise the new path setting */
  277. path->setting[path_index].ctl_index = mixer_value->ctl_index;
  278. path->setting[path_index].num_values = num_values;
  279. path->setting[path_index].type = type;
  280. size_t value_sz = sizeof_ctl_type(type);
  281. path->setting[path_index].value.ptr = calloc(num_values, value_sz);
  282. if (path->setting[path_index].type == MIXER_CTL_TYPE_BYTE)
  283. path->setting[path_index].value.bytes[0] = mixer_value->value;
  284. else if (path->setting[path_index].type == MIXER_CTL_TYPE_ENUM)
  285. path->setting[path_index].value.enumerated[0] = mixer_value->value;
  286. else
  287. path->setting[path_index].value.integer[0] = mixer_value->value;
  288. }
  289. if (mixer_value->index == -1) {
  290. /* set all values the same */
  291. if (path->setting[path_index].type == MIXER_CTL_TYPE_BYTE) {
  292. for (i = 0; i < num_values; i++)
  293. path->setting[path_index].value.bytes[i] = mixer_value->value;
  294. } else if (path->setting[path_index].type == MIXER_CTL_TYPE_ENUM) {
  295. for (i = 0; i < num_values; i++)
  296. path->setting[path_index].value.enumerated[i] = mixer_value->value;
  297. } else {
  298. for (i = 0; i < num_values; i++)
  299. path->setting[path_index].value.integer[i] = mixer_value->value;
  300. }
  301. } else {
  302. /* set only one value */
  303. if (path->setting[path_index].type == MIXER_CTL_TYPE_BYTE)
  304. path->setting[path_index].value.bytes[mixer_value->index] = mixer_value->value;
  305. else if (path->setting[path_index].type == MIXER_CTL_TYPE_ENUM)
  306. path->setting[path_index].value.enumerated[mixer_value->index] = mixer_value->value;
  307. else
  308. path->setting[path_index].value.integer[mixer_value->index] = mixer_value->value;
  309. }
  310. return 0;
  311. }
  312. static int path_add_path(struct audio_route *ar, struct mixer_path *path,
  313. struct mixer_path *sub_path)
  314. {
  315. unsigned int i;
  316. for (i = 0; i < sub_path->length; i++)
  317. if (path_add_setting(ar, path, &sub_path->setting[i]) < 0)
  318. return -1;
  319. return 0;
  320. }
  321. static int path_apply(struct audio_route *ar, struct mixer_path *path)
  322. {
  323. unsigned int i;
  324. unsigned int ctl_index;
  325. struct mixer_ctl *ctl;
  326. enum mixer_ctl_type type;
  327. ALOGD("Apply path: %s", path->name != NULL ? path->name : "none");
  328. for (i = 0; i < path->length; i++) {
  329. ctl_index = path->setting[i].ctl_index;
  330. ctl = index_to_ctl(ar, ctl_index);
  331. type = mixer_ctl_get_type(ctl);
  332. if (!is_supported_ctl_type(type))
  333. continue;
  334. size_t value_sz = sizeof_ctl_type(type);
  335. memcpy(ar->mixer_state[ctl_index].new_value.ptr, path->setting[i].value.ptr,
  336. path->setting[i].num_values * value_sz);
  337. }
  338. return 0;
  339. }
  340. static int path_reset(struct audio_route *ar, struct mixer_path *path)
  341. {
  342. unsigned int i;
  343. unsigned int ctl_index;
  344. struct mixer_ctl *ctl;
  345. enum mixer_ctl_type type;
  346. ALOGV("Reset path: %s", path->name != NULL ? path->name : "none");
  347. for (i = 0; i < path->length; i++) {
  348. ctl_index = path->setting[i].ctl_index;
  349. ctl = index_to_ctl(ar, ctl_index);
  350. type = mixer_ctl_get_type(ctl);
  351. if (!is_supported_ctl_type(type))
  352. continue;
  353. size_t value_sz = sizeof_ctl_type(type);
  354. /* reset the value(s) */
  355. memcpy(ar->mixer_state[ctl_index].new_value.ptr,
  356. ar->mixer_state[ctl_index].reset_value.ptr,
  357. ar->mixer_state[ctl_index].num_values * value_sz);
  358. }
  359. return 0;
  360. }
  361. /* mixer helper function */
  362. static int mixer_enum_string_to_value(struct mixer_ctl *ctl, const char *string)
  363. {
  364. unsigned int i;
  365. unsigned int num_values = mixer_ctl_get_num_enums(ctl);
  366. if (string == NULL) {
  367. ALOGE("NULL enum value string passed to mixer_enum_string_to_value() for ctl %s",
  368. mixer_ctl_get_name(ctl));
  369. return 0;
  370. }
  371. /* Search the enum strings for a particular one */
  372. for (i = 0; i < num_values; i++) {
  373. if (strcmp(mixer_ctl_get_enum_string(ctl, i), string) == 0)
  374. break;
  375. }
  376. if (i == num_values) {
  377. ALOGE("unknown enum value string %s for ctl %s",
  378. string, mixer_ctl_get_name(ctl));
  379. return 0;
  380. }
  381. return i;
  382. }
  383. static void start_tag(void *data, const XML_Char *tag_name,
  384. const XML_Char **attr)
  385. {
  386. const XML_Char *attr_name = NULL;
  387. const XML_Char *attr_id = NULL;
  388. const XML_Char *attr_value = NULL;
  389. struct config_parse_state *state = data;
  390. struct audio_route *ar = state->ar;
  391. unsigned int i;
  392. unsigned int ctl_index;
  393. struct mixer_ctl *ctl;
  394. long value;
  395. unsigned int id;
  396. struct mixer_value mixer_value;
  397. enum mixer_ctl_type type;
  398. /* Get name, id and value attributes (these may be empty) */
  399. for (i = 0; attr[i]; i += 2) {
  400. if (strcmp(attr[i], "name") == 0)
  401. attr_name = attr[i + 1];
  402. if (strcmp(attr[i], "id") == 0)
  403. attr_id = attr[i + 1];
  404. else if (strcmp(attr[i], "value") == 0)
  405. attr_value = attr[i + 1];
  406. }
  407. /* Look at tags */
  408. if (strcmp(tag_name, "path") == 0) {
  409. if (attr_name == NULL) {
  410. ALOGE("Unnamed path!");
  411. } else {
  412. if (state->level == 1) {
  413. /* top level path: create and stash the path */
  414. state->path = path_create(ar, (char *)attr_name);
  415. if (state->path == NULL)
  416. ALOGE("path created failed, please check the path if existed");
  417. } else {
  418. /* nested path */
  419. struct mixer_path *sub_path = path_get_by_name(ar, attr_name);
  420. if (!sub_path) {
  421. ALOGE("unable to find sub path '%s'", attr_name);
  422. } else if (state->path != NULL) {
  423. path_add_path(ar, state->path, sub_path);
  424. }
  425. }
  426. }
  427. }
  428. else if (strcmp(tag_name, "ctl") == 0) {
  429. /* Obtain the mixer ctl and value */
  430. ctl = mixer_get_ctl_by_name(ar->mixer, attr_name);
  431. if (ctl == NULL) {
  432. ALOGE("Control '%s' doesn't exist - skipping", attr_name);
  433. goto done;
  434. }
  435. switch (mixer_ctl_get_type(ctl)) {
  436. case MIXER_CTL_TYPE_BOOL:
  437. case MIXER_CTL_TYPE_INT:
  438. value = strtol((char *)attr_value, NULL, 0);
  439. break;
  440. case MIXER_CTL_TYPE_BYTE:
  441. value = (unsigned char) strtol((char *)attr_value, NULL, 16);
  442. break;
  443. case MIXER_CTL_TYPE_ENUM:
  444. value = mixer_enum_string_to_value(ctl, (char *)attr_value);
  445. break;
  446. default:
  447. value = 0;
  448. break;
  449. }
  450. /* locate the mixer ctl in the list */
  451. for (ctl_index = 0; ctl_index < ar->num_mixer_ctls; ctl_index++) {
  452. if (ar->mixer_state[ctl_index].ctl == ctl)
  453. break;
  454. }
  455. if (state->level == 1) {
  456. /* top level ctl (initial setting) */
  457. type = mixer_ctl_get_type(ctl);
  458. if (is_supported_ctl_type(type)) {
  459. /* apply the new value */
  460. if (attr_id) {
  461. /* set only one value */
  462. id = atoi((char *)attr_id);
  463. if (id < ar->mixer_state[ctl_index].num_values)
  464. if (type == MIXER_CTL_TYPE_BYTE)
  465. ar->mixer_state[ctl_index].new_value.bytes[id] = value;
  466. else if (type == MIXER_CTL_TYPE_ENUM)
  467. ar->mixer_state[ctl_index].new_value.enumerated[id] = value;
  468. else
  469. ar->mixer_state[ctl_index].new_value.integer[id] = value;
  470. else
  471. ALOGE("value id out of range for mixer ctl '%s'",
  472. mixer_ctl_get_name(ctl));
  473. } else {
  474. /* set all values the same */
  475. for (i = 0; i < ar->mixer_state[ctl_index].num_values; i++)
  476. if (type == MIXER_CTL_TYPE_BYTE)
  477. ar->mixer_state[ctl_index].new_value.bytes[i] = value;
  478. else if (type == MIXER_CTL_TYPE_ENUM)
  479. ar->mixer_state[ctl_index].new_value.enumerated[i] = value;
  480. else
  481. ar->mixer_state[ctl_index].new_value.integer[i] = value;
  482. }
  483. }
  484. } else {
  485. /* nested ctl (within a path) */
  486. mixer_value.ctl_index = ctl_index;
  487. mixer_value.value = value;
  488. if (attr_id)
  489. mixer_value.index = atoi((char *)attr_id);
  490. else
  491. mixer_value.index = -1;
  492. if (state->path != NULL)
  493. path_add_value(ar, state->path, &mixer_value);
  494. }
  495. }
  496. done:
  497. state->level++;
  498. }
  499. static void end_tag(void *data, const XML_Char *tag_name)
  500. {
  501. struct config_parse_state *state = data;
  502. (void)tag_name;
  503. state->level--;
  504. }
  505. static int alloc_mixer_state(struct audio_route *ar)
  506. {
  507. unsigned int i;
  508. unsigned int num_values;
  509. struct mixer_ctl *ctl;
  510. enum mixer_ctl_type type;
  511. ar->num_mixer_ctls = mixer_get_num_ctls(ar->mixer);
  512. ar->mixer_state = calloc(ar->num_mixer_ctls, sizeof(struct mixer_state));
  513. if (!ar->mixer_state)
  514. return -1;
  515. for (i = 0; i < ar->num_mixer_ctls; i++) {
  516. ctl = mixer_get_ctl(ar->mixer, i);
  517. num_values = mixer_ctl_get_num_values(ctl);
  518. ar->mixer_state[i].ctl = ctl;
  519. ar->mixer_state[i].num_values = num_values;
  520. ar->mixer_state[i].active_count = 0;
  521. /* Skip unsupported types that are not supported yet in XML */
  522. type = mixer_ctl_get_type(ctl);
  523. if (!is_supported_ctl_type(type))
  524. continue;
  525. size_t value_sz = sizeof_ctl_type(type);
  526. ar->mixer_state[i].old_value.ptr = calloc(num_values, value_sz);
  527. ar->mixer_state[i].new_value.ptr = calloc(num_values, value_sz);
  528. ar->mixer_state[i].reset_value.ptr = calloc(num_values, value_sz);
  529. if (type == MIXER_CTL_TYPE_ENUM)
  530. ar->mixer_state[i].old_value.enumerated[0] = mixer_ctl_get_value(ctl, 0);
  531. else
  532. mixer_ctl_get_array(ctl, ar->mixer_state[i].old_value.ptr, num_values);
  533. memcpy(ar->mixer_state[i].new_value.ptr, ar->mixer_state[i].old_value.ptr,
  534. num_values * value_sz);
  535. }
  536. return 0;
  537. }
  538. static void free_mixer_state(struct audio_route *ar)
  539. {
  540. unsigned int i;
  541. enum mixer_ctl_type type;
  542. for (i = 0; i < ar->num_mixer_ctls; i++) {
  543. type = mixer_ctl_get_type(ar->mixer_state[i].ctl);
  544. if (!is_supported_ctl_type(type))
  545. continue;
  546. free(ar->mixer_state[i].old_value.ptr);
  547. free(ar->mixer_state[i].new_value.ptr);
  548. free(ar->mixer_state[i].reset_value.ptr);
  549. }
  550. free(ar->mixer_state);
  551. ar->mixer_state = NULL;
  552. }
  553. /* Update the mixer with any changed values */
  554. int audio_route_update_mixer(struct audio_route *ar)
  555. {
  556. unsigned int i;
  557. unsigned int j;
  558. struct mixer_ctl *ctl;
  559. for (i = 0; i < ar->num_mixer_ctls; i++) {
  560. unsigned int num_values = ar->mixer_state[i].num_values;
  561. enum mixer_ctl_type type;
  562. ctl = ar->mixer_state[i].ctl;
  563. /* Skip unsupported types */
  564. type = mixer_ctl_get_type(ctl);
  565. if (!is_supported_ctl_type(type))
  566. continue;
  567. /* if the value has changed, update the mixer */
  568. bool changed = false;
  569. if (type == MIXER_CTL_TYPE_BYTE) {
  570. for (j = 0; j < num_values; j++) {
  571. if (ar->mixer_state[i].old_value.bytes[j] != ar->mixer_state[i].new_value.bytes[j]) {
  572. changed = true;
  573. break;
  574. }
  575. }
  576. } else if (type == MIXER_CTL_TYPE_ENUM) {
  577. for (j = 0; j < num_values; j++) {
  578. if (ar->mixer_state[i].old_value.enumerated[j]
  579. != ar->mixer_state[i].new_value.enumerated[j]) {
  580. changed = true;
  581. break;
  582. }
  583. }
  584. } else {
  585. for (j = 0; j < num_values; j++) {
  586. if (ar->mixer_state[i].old_value.integer[j] != ar->mixer_state[i].new_value.integer[j]) {
  587. changed = true;
  588. break;
  589. }
  590. }
  591. }
  592. if (changed) {
  593. if (type == MIXER_CTL_TYPE_ENUM)
  594. mixer_ctl_set_value(ctl, 0, ar->mixer_state[i].new_value.enumerated[0]);
  595. else
  596. mixer_ctl_set_array(ctl, ar->mixer_state[i].new_value.ptr, num_values);
  597. size_t value_sz = sizeof_ctl_type(type);
  598. memcpy(ar->mixer_state[i].old_value.ptr, ar->mixer_state[i].new_value.ptr,
  599. num_values * value_sz);
  600. }
  601. }
  602. return 0;
  603. }
  604. /* saves the current state of the mixer, for resetting all controls */
  605. static void save_mixer_state(struct audio_route *ar)
  606. {
  607. unsigned int i;
  608. enum mixer_ctl_type type;
  609. for (i = 0; i < ar->num_mixer_ctls; i++) {
  610. type = mixer_ctl_get_type(ar->mixer_state[i].ctl);
  611. if (!is_supported_ctl_type(type))
  612. continue;
  613. size_t value_sz = sizeof_ctl_type(type);
  614. memcpy(ar->mixer_state[i].reset_value.ptr, ar->mixer_state[i].new_value.ptr,
  615. ar->mixer_state[i].num_values * value_sz);
  616. }
  617. }
  618. /* Reset the audio routes back to the initial state */
  619. void audio_route_reset(struct audio_route *ar)
  620. {
  621. unsigned int i;
  622. enum mixer_ctl_type type;
  623. /* load all of the saved values */
  624. for (i = 0; i < ar->num_mixer_ctls; i++) {
  625. type = mixer_ctl_get_type(ar->mixer_state[i].ctl);
  626. if (!is_supported_ctl_type(type))
  627. continue;
  628. size_t value_sz = sizeof_ctl_type(type);
  629. memcpy(ar->mixer_state[i].new_value.ptr, ar->mixer_state[i].reset_value.ptr,
  630. ar->mixer_state[i].num_values * value_sz);
  631. }
  632. }
  633. /* Apply an audio route path by name */
  634. int audio_route_apply_path(struct audio_route *ar, const char *name)
  635. {
  636. struct mixer_path *path;
  637. if (!ar) {
  638. ALOGE("invalid audio_route");
  639. return -1;
  640. }
  641. path = path_get_by_name(ar, name);
  642. if (!path) {
  643. ALOGE("unable to find path '%s'", name);
  644. return -1;
  645. }
  646. path_apply(ar, path);
  647. return 0;
  648. }
  649. /* Reset an audio route path by name */
  650. int audio_route_reset_path(struct audio_route *ar, const char *name)
  651. {
  652. struct mixer_path *path;
  653. if (!ar) {
  654. ALOGE("invalid audio_route");
  655. return -1;
  656. }
  657. path = path_get_by_name(ar, name);
  658. if (!path) {
  659. ALOGE("unable to find path '%s'", name);
  660. return -1;
  661. }
  662. path_reset(ar, path);
  663. return 0;
  664. }
  665. /*
  666. * Operates on the specified path .. controls will be updated in the
  667. * order listed in the XML file
  668. */
  669. static int audio_route_update_path(struct audio_route *ar, const char *name, bool reverse)
  670. {
  671. struct mixer_path *path;
  672. unsigned int j;
  673. if (!ar) {
  674. ALOGE("invalid audio_route");
  675. return -1;
  676. }
  677. path = path_get_by_name(ar, name);
  678. if (!path) {
  679. ALOGE("unable to find path '%s'", name);
  680. return -1;
  681. }
  682. for (size_t i = 0; i < path->length; ++i) {
  683. unsigned int ctl_index;
  684. enum mixer_ctl_type type;
  685. ctl_index = path->setting[reverse ? path->length - 1 - i : i].ctl_index;
  686. struct mixer_state * ms = &ar->mixer_state[ctl_index];
  687. type = mixer_ctl_get_type(ms->ctl);
  688. if (!is_supported_ctl_type(type)) {
  689. continue;
  690. }
  691. if (reverse && ms->active_count > 0) {
  692. ms->active_count--;
  693. } else if (!reverse) {
  694. ms->active_count++;
  695. }
  696. size_t value_sz = sizeof_ctl_type(type);
  697. /* if any value has changed, update the mixer */
  698. for (j = 0; j < ms->num_values; j++) {
  699. if (type == MIXER_CTL_TYPE_BYTE) {
  700. if (ms->old_value.bytes[j] != ms->new_value.bytes[j]) {
  701. if (reverse && ms->active_count > 0) {
  702. ALOGD("%s: skip to reset mixer control '%s' in path '%s' "
  703. "because it is still needed by other paths", __func__,
  704. mixer_ctl_get_name(ms->ctl), name);
  705. memcpy(ms->new_value.bytes, ms->old_value.bytes,
  706. ms->num_values * value_sz);
  707. break;
  708. }
  709. mixer_ctl_set_array(ms->ctl, ms->new_value.bytes, ms->num_values);
  710. memcpy(ms->old_value.bytes, ms->new_value.bytes, ms->num_values * value_sz);
  711. break;
  712. }
  713. } else if (type == MIXER_CTL_TYPE_ENUM) {
  714. if (ms->old_value.enumerated[j] != ms->new_value.enumerated[j]) {
  715. if (reverse && ms->active_count > 0) {
  716. ALOGD("%s: skip to reset mixer control '%s' in path '%s' "
  717. "because it is still needed by other paths", __func__,
  718. mixer_ctl_get_name(ms->ctl), name);
  719. memcpy(ms->new_value.enumerated, ms->old_value.enumerated,
  720. ms->num_values * value_sz);
  721. break;
  722. }
  723. mixer_ctl_set_value(ms->ctl, 0, ms->new_value.enumerated[0]);
  724. memcpy(ms->old_value.enumerated, ms->new_value.enumerated,
  725. ms->num_values * value_sz);
  726. break;
  727. }
  728. } else if (ms->old_value.integer[j] != ms->new_value.integer[j]) {
  729. if (reverse && ms->active_count > 0) {
  730. ALOGD("%s: skip to reset mixer control '%s' in path '%s' "
  731. "because it is still needed by other paths", __func__,
  732. mixer_ctl_get_name(ms->ctl), name);
  733. memcpy(ms->new_value.integer, ms->old_value.integer,
  734. ms->num_values * value_sz);
  735. break;
  736. }
  737. mixer_ctl_set_array(ms->ctl, ms->new_value.integer, ms->num_values);
  738. memcpy(ms->old_value.integer, ms->new_value.integer, ms->num_values * value_sz);
  739. break;
  740. }
  741. }
  742. }
  743. return 0;
  744. }
  745. int audio_route_apply_and_update_path(struct audio_route *ar, const char *name)
  746. {
  747. if (audio_route_apply_path(ar, name) < 0) {
  748. return -1;
  749. }
  750. return audio_route_update_path(ar, name, false /*reverse*/);
  751. }
  752. int audio_route_reset_and_update_path(struct audio_route *ar, const char *name)
  753. {
  754. if (audio_route_reset_path(ar, name) < 0) {
  755. return -1;
  756. }
  757. return audio_route_update_path(ar, name, true /*reverse*/);
  758. }
  759. struct audio_route *audio_route_init(unsigned int card, const char *xml_path)
  760. {
  761. struct config_parse_state state;
  762. XML_Parser parser;
  763. FILE *file;
  764. int bytes_read;
  765. void *buf;
  766. struct audio_route *ar;
  767. ar = calloc(1, sizeof(struct audio_route));
  768. if (!ar)
  769. goto err_calloc;
  770. ar->mixer = mixer_open(card);
  771. if (!ar->mixer) {
  772. ALOGE("Unable to open the mixer, aborting.");
  773. goto err_mixer_open;
  774. }
  775. ar->mixer_path = NULL;
  776. ar->mixer_path_size = 0;
  777. ar->num_mixer_paths = 0;
  778. /* allocate space for and read current mixer settings */
  779. if (alloc_mixer_state(ar) < 0)
  780. goto err_mixer_state;
  781. /* use the default XML path if none is provided */
  782. if (xml_path == NULL)
  783. xml_path = MIXER_XML_PATH;
  784. file = fopen(xml_path, "r");
  785. if (!file) {
  786. ALOGE("Failed to open %s: %s", xml_path, strerror(errno));
  787. goto err_fopen;
  788. }
  789. parser = XML_ParserCreate(NULL);
  790. if (!parser) {
  791. ALOGE("Failed to create XML parser");
  792. goto err_parser_create;
  793. }
  794. memset(&state, 0, sizeof(state));
  795. state.ar = ar;
  796. XML_SetUserData(parser, &state);
  797. XML_SetElementHandler(parser, start_tag, end_tag);
  798. for (;;) {
  799. buf = XML_GetBuffer(parser, BUF_SIZE);
  800. if (buf == NULL)
  801. goto err_parse;
  802. bytes_read = fread(buf, 1, BUF_SIZE, file);
  803. if (bytes_read < 0)
  804. goto err_parse;
  805. if (XML_ParseBuffer(parser, bytes_read,
  806. bytes_read == 0) == XML_STATUS_ERROR) {
  807. ALOGE("Error in mixer xml (%s)", MIXER_XML_PATH);
  808. goto err_parse;
  809. }
  810. if (bytes_read == 0)
  811. break;
  812. }
  813. /* apply the initial mixer values, and save them so we can reset the
  814. mixer to the original values */
  815. audio_route_update_mixer(ar);
  816. save_mixer_state(ar);
  817. XML_ParserFree(parser);
  818. fclose(file);
  819. return ar;
  820. err_parse:
  821. path_free(ar);
  822. XML_ParserFree(parser);
  823. err_parser_create:
  824. fclose(file);
  825. err_fopen:
  826. free_mixer_state(ar);
  827. err_mixer_state:
  828. mixer_close(ar->mixer);
  829. err_mixer_open:
  830. free(ar);
  831. ar = NULL;
  832. err_calloc:
  833. return NULL;
  834. }
  835. void audio_route_free(struct audio_route *ar)
  836. {
  837. free_mixer_state(ar);
  838. mixer_close(ar->mixer);
  839. path_free(ar);
  840. free(ar);
  841. }