1 // Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <deque>
6 #include <linux/input.h>
7 #include <map>
8 #include <poll.h>
9 #include <stdio.h>
10 #include <sys/param.h>
11 #include <gtest/gtest.h>
12 #include <string>
13 #include <syslog.h>
14 #include <vector>
15
16 extern "C" {
17 #include "cras_alsa_jack.h"
18 #include "cras_alsa_ucm_section.h"
19 #include "cras_gpio_jack.h"
20 #include "cras_tm.h"
21 #include "cras_types.h"
22 #include "cras_util.h"
23 }
24
25 namespace {
26
27 #define BITS_PER_BYTE (8)
28 #define BITS_PER_LONG (sizeof(long) * BITS_PER_BYTE)
29 #define NBITS(x) ((((x) - 1) / BITS_PER_LONG) + 1)
30 #define OFF(x) ((x) % BITS_PER_LONG)
31 #define BIT(x) (1UL << OFF(x))
32 #define LONG(x) ((x) / BITS_PER_LONG)
33 #define IS_BIT_SET(bit, array) !!((array[LONG(bit)]) & (1UL << OFF(bit)))
34
35 static int fake_jack_cb_plugged;
36 static void *fake_jack_cb_data;
37 static size_t fake_jack_cb_called;
38 unsigned int snd_hctl_elem_get_device_return_val;
39 unsigned int snd_hctl_elem_get_device_called;
40 static size_t snd_hctl_first_elem_called;
41 static snd_hctl_elem_t *snd_hctl_first_elem_return_val;
42 static size_t snd_hctl_elem_next_called;
43 std::deque<snd_hctl_elem_t *> snd_hctl_elem_next_ret_vals;
44 std::deque<snd_hctl_elem_t *> snd_hctl_elem_next_ret_vals_poped;
45 static size_t snd_hctl_elem_get_name_called;
46 static size_t snd_hctl_elem_set_callback_called;
47 static snd_hctl_elem_t *snd_hctl_elem_set_callback_obj;
48 static snd_hctl_elem_callback_t snd_hctl_elem_set_callback_value;
49 static size_t snd_hctl_find_elem_called;
50 static std::vector<snd_hctl_elem_t *> snd_hctl_find_elem_return_vals;
51 static std::map<std::string, size_t> snd_ctl_elem_id_set_name_map;
52 static size_t cras_system_add_select_fd_called;
53 static std::vector<int> cras_system_add_select_fd_values;
54 static size_t cras_system_rm_select_fd_called;
55 static std::vector<int> cras_system_rm_select_fd_values;
56 static size_t snd_hctl_elem_set_callback_private_called;
57 static void *snd_hctl_elem_set_callback_private_value;
58 static size_t snd_hctl_elem_get_hctl_called;
59 static snd_hctl_t *snd_hctl_elem_get_hctl_return_value;
60 static size_t snd_ctl_elem_value_get_boolean_called;
61 static int snd_ctl_elem_value_get_boolean_return_value;
62 static void *fake_jack_cb_arg;
63 static struct cras_alsa_mixer *fake_mixer;
64 static size_t cras_alsa_mixer_get_output_matching_name_called;
65 static size_t cras_alsa_mixer_get_input_matching_name_called;
66 static size_t cras_alsa_mixer_get_control_for_section_called;
67 static struct mixer_control *
68 cras_alsa_mixer_get_output_matching_name_return_value;
69 static struct mixer_control *
70 cras_alsa_mixer_get_input_matching_name_return_value;
71 static struct mixer_control *
72 cras_alsa_mixer_get_control_for_section_return_value;
73 static size_t gpio_switch_list_for_each_called;
74 static std::vector<std::string> gpio_switch_list_for_each_dev_paths;
75 static std::vector<std::string> gpio_switch_list_for_each_dev_names;
76 static size_t gpio_switch_open_called;
77 static size_t gpio_switch_eviocgsw_called;
78 static size_t gpio_switch_eviocgbit_called;
79 static unsigned ucm_get_dev_for_jack_called;
80 static unsigned ucm_get_cap_control_called;
81 static char *ucm_get_cap_control_value;
82 static bool ucm_get_dev_for_jack_return;
83 static int ucm_set_enabled_value;
84 static unsigned long eviocbit_ret[NBITS(SW_CNT)];
85 static int gpio_switch_eviocgbit_fd;
86 static const char *edid_file_ret;
87 static size_t ucm_get_dsp_name_called;
88 static unsigned ucm_get_override_type_name_called;
89 static char *ucm_get_device_name_for_dev_value;
90 static snd_hctl_t *fake_hctl = (snd_hctl_t *)2;
91
ResetStubData()92 static void ResetStubData() {
93 gpio_switch_list_for_each_called = 0;
94 gpio_switch_list_for_each_dev_paths.clear();
95 gpio_switch_list_for_each_dev_paths.push_back("/dev/input/event3");
96 gpio_switch_list_for_each_dev_paths.push_back("/dev/input/event2");
97 gpio_switch_list_for_each_dev_names.clear();
98 gpio_switch_open_called = 0;
99 gpio_switch_eviocgsw_called = 0;
100 gpio_switch_eviocgbit_called = 0;
101 snd_hctl_elem_get_device_return_val = 0;
102 snd_hctl_elem_get_device_called = 0;
103 snd_hctl_first_elem_called = 0;
104 snd_hctl_first_elem_return_val = reinterpret_cast<snd_hctl_elem_t *>(0x87);
105 snd_hctl_elem_next_called = 0;
106 snd_hctl_elem_next_ret_vals.clear();
107 snd_hctl_elem_next_ret_vals_poped.clear();
108 snd_hctl_elem_get_name_called = 0;
109 snd_hctl_elem_set_callback_called = 0;
110 snd_hctl_elem_set_callback_obj = NULL;
111 snd_hctl_elem_set_callback_value = NULL;
112 snd_hctl_find_elem_called = 0;
113 snd_hctl_find_elem_return_vals.clear();
114 snd_ctl_elem_id_set_name_map.clear();
115 cras_system_add_select_fd_called = 0;
116 cras_system_add_select_fd_values.clear();
117 cras_system_rm_select_fd_called = 0;
118 cras_system_rm_select_fd_values.clear();
119 snd_hctl_elem_set_callback_private_called = 0;
120 snd_hctl_elem_get_hctl_called = 0;
121 snd_ctl_elem_value_get_boolean_called = 0;
122 fake_jack_cb_called = 0;
123 fake_jack_cb_plugged = 0;
124 fake_jack_cb_arg = reinterpret_cast<void *>(0x987);
125 fake_mixer = reinterpret_cast<struct cras_alsa_mixer *>(0x789);
126 cras_alsa_mixer_get_output_matching_name_called = 0;
127 cras_alsa_mixer_get_input_matching_name_called = 0;
128 cras_alsa_mixer_get_control_for_section_called = 0;
129 cras_alsa_mixer_get_output_matching_name_return_value =
130 reinterpret_cast<struct mixer_control *>(0x456);
131 cras_alsa_mixer_get_input_matching_name_return_value = NULL;
132 cras_alsa_mixer_get_control_for_section_return_value =
133 reinterpret_cast<struct mixer_control *>(0x456);
134 ucm_get_dev_for_jack_called = 0;
135 ucm_get_cap_control_called = 0;
136 ucm_get_cap_control_value = NULL;
137 ucm_get_dev_for_jack_return = false;
138 edid_file_ret = NULL;
139 ucm_get_dsp_name_called = 0;
140 ucm_get_override_type_name_called = 0;
141 ucm_get_device_name_for_dev_value = NULL;
142
143 memset(eviocbit_ret, 0, sizeof(eviocbit_ret));
144 }
145
fake_jack_cb(const struct cras_alsa_jack * jack,int plugged,void * data)146 static void fake_jack_cb(const struct cras_alsa_jack *jack,
147 int plugged,
148 void *data)
149 {
150 fake_jack_cb_called++;
151 fake_jack_cb_plugged = plugged;
152 fake_jack_cb_data = data;
153
154 // Check that jack enable callback is called if there is a ucm device.
155 ucm_set_enabled_value = !plugged;
156 cras_alsa_jack_enable_ucm(jack, plugged);
157 EXPECT_EQ(ucm_get_dev_for_jack_return ? plugged : !plugged,
158 ucm_set_enabled_value);
159 }
160
TEST(AlsaJacks,CreateNullHctl)161 TEST(AlsaJacks, CreateNullHctl) {
162 struct cras_alsa_jack_list *jack_list;
163 ResetStubData();
164 jack_list = cras_alsa_jack_list_create(0, "c1", 0, 1,
165 fake_mixer,
166 NULL, NULL,
167 CRAS_STREAM_OUTPUT,
168 fake_jack_cb,
169 fake_jack_cb_arg);
170 ASSERT_NE(static_cast<struct cras_alsa_jack_list *>(NULL), jack_list);
171 EXPECT_EQ(0, cras_alsa_jack_list_find_jacks_by_name_matching(jack_list));
172 EXPECT_EQ(1, gpio_switch_list_for_each_called);
173 EXPECT_EQ(0, gpio_switch_open_called);
174 EXPECT_EQ(0, gpio_switch_eviocgsw_called);
175 EXPECT_EQ(0, gpio_switch_eviocgbit_called);
176
177 cras_alsa_jack_list_destroy(jack_list);
178 }
179
TEST(AlsaJacks,CreateNoElements)180 TEST(AlsaJacks, CreateNoElements) {
181 struct cras_alsa_jack_list *jack_list;
182
183 ResetStubData();
184 snd_hctl_first_elem_return_val = NULL;
185 jack_list = cras_alsa_jack_list_create(0, "c1", 0, 1,
186 fake_mixer,
187 NULL, fake_hctl,
188 CRAS_STREAM_OUTPUT,
189 fake_jack_cb,
190 fake_jack_cb_arg);
191 ASSERT_NE(static_cast<struct cras_alsa_jack_list *>(NULL), jack_list);
192 EXPECT_EQ(0, cras_alsa_jack_list_find_jacks_by_name_matching(jack_list));
193 EXPECT_EQ(1, gpio_switch_list_for_each_called);
194 EXPECT_EQ(0, gpio_switch_open_called);
195 EXPECT_EQ(0, gpio_switch_eviocgsw_called);
196 EXPECT_EQ(0, gpio_switch_eviocgbit_called);
197 EXPECT_EQ(1, snd_hctl_first_elem_called);
198 EXPECT_EQ(0, snd_hctl_elem_next_called);
199
200 cras_alsa_jack_list_destroy(jack_list);
201 }
202
run_test_with_elem_list(CRAS_STREAM_DIRECTION direction,std::string * elems,unsigned int device_index,struct cras_use_case_mgr * ucm,size_t nelems,size_t nhdmi_jacks,size_t njacks)203 static struct cras_alsa_jack_list *run_test_with_elem_list(
204 CRAS_STREAM_DIRECTION direction,
205 std::string *elems,
206 unsigned int device_index,
207 struct cras_use_case_mgr *ucm,
208 size_t nelems,
209 size_t nhdmi_jacks,
210 size_t njacks) {
211 struct cras_alsa_jack_list *jack_list;
212
213 snd_hctl_first_elem_return_val =
214 reinterpret_cast<snd_hctl_elem_t *>(&elems[0]);
215 for (unsigned int i = 1; i < nelems; i++)
216 snd_hctl_elem_next_ret_vals.push_front(
217 reinterpret_cast<snd_hctl_elem_t *>(&elems[i]));
218
219 jack_list = cras_alsa_jack_list_create(0,
220 "card_name",
221 device_index,
222 1,
223 fake_mixer,
224 ucm, fake_hctl,
225 direction,
226 fake_jack_cb,
227 fake_jack_cb_arg);
228 if (jack_list == NULL)
229 return jack_list;
230 EXPECT_EQ(0, cras_alsa_jack_list_find_jacks_by_name_matching(jack_list));
231 EXPECT_EQ(ucm ? njacks : 0, ucm_get_dev_for_jack_called);
232 EXPECT_EQ(ucm ? njacks : 0, ucm_get_override_type_name_called);
233 EXPECT_EQ(1 + nhdmi_jacks, snd_hctl_first_elem_called);
234 EXPECT_EQ(njacks, snd_hctl_elem_set_callback_called);
235
236 /* For some functions, the number of calls to them could
237 * be larger then expected count if there is ELD control
238 * in given elements. */
239 EXPECT_GE(snd_hctl_elem_next_called, nelems + nhdmi_jacks);
240 EXPECT_GE(snd_hctl_elem_get_name_called, nelems + njacks);
241
242 if (direction == CRAS_STREAM_OUTPUT) {
243 EXPECT_EQ(njacks, cras_alsa_mixer_get_output_matching_name_called);
244 }
245 if (direction == CRAS_STREAM_INPUT && ucm_get_dev_for_jack_return) {
246 EXPECT_EQ(njacks, ucm_get_cap_control_called);
247 }
248
249 return jack_list;
250 }
251
run_test_with_section(CRAS_STREAM_DIRECTION direction,std::string * elems,size_t nelems,unsigned int device_index,struct cras_use_case_mgr * ucm,struct ucm_section * ucm_section,int add_jack_rc,size_t njacks)252 static struct cras_alsa_jack_list *run_test_with_section(
253 CRAS_STREAM_DIRECTION direction,
254 std::string *elems,
255 size_t nelems,
256 unsigned int device_index,
257 struct cras_use_case_mgr *ucm,
258 struct ucm_section *ucm_section,
259 int add_jack_rc,
260 size_t njacks) {
261 struct cras_alsa_jack_list *jack_list;
262 struct cras_alsa_jack *jack;
263
264 for (size_t i = 0; i < nelems; i++) {
265 snd_ctl_elem_id_set_name_map[elems[i]] = i;
266 snd_hctl_find_elem_return_vals.push_back(
267 reinterpret_cast<snd_hctl_elem_t*>(&elems[i]));
268 }
269
270 jack_list = cras_alsa_jack_list_create(0,
271 "card_name",
272 device_index,
273 1,
274 fake_mixer,
275 ucm, fake_hctl,
276 direction,
277 fake_jack_cb,
278 fake_jack_cb_arg);
279 if (jack_list == NULL)
280 return jack_list;
281 EXPECT_EQ(add_jack_rc,
282 cras_alsa_jack_list_add_jack_for_section(jack_list, ucm_section, &jack));
283 if (add_jack_rc == 0) {
284 EXPECT_EQ(njacks, ucm_get_dsp_name_called);
285 EXPECT_NE(jack, reinterpret_cast<struct cras_alsa_jack *>(NULL));
286 } else {
287 EXPECT_EQ(jack, reinterpret_cast<struct cras_alsa_jack *>(NULL));
288 }
289 if (add_jack_rc != 0 || njacks != ucm_get_dsp_name_called) {
290 cras_alsa_jack_list_destroy(jack_list);
291 return NULL;
292 }
293 EXPECT_EQ(njacks, snd_hctl_elem_set_callback_called);
294 EXPECT_EQ(njacks, cras_alsa_mixer_get_control_for_section_called);
295
296 return jack_list;
297 }
298
TEST(AlsaJacks,ReportNull)299 TEST(AlsaJacks, ReportNull) {
300 cras_alsa_jack_list_report(NULL);
301 }
302
TEST(AlsaJacks,CreateNoJacks)303 TEST(AlsaJacks, CreateNoJacks) {
304 static std::string elem_names[] = {
305 "Mic Jack",
306 "foo",
307 "bar",
308 };
309 struct cras_alsa_jack_list *jack_list;
310
311 ResetStubData();
312 jack_list = run_test_with_elem_list(CRAS_STREAM_OUTPUT,
313 elem_names,
314 0,
315 NULL,
316 ARRAY_SIZE(elem_names),
317 0,
318 0);
319 ASSERT_NE(static_cast<struct cras_alsa_jack_list *>(NULL), jack_list);
320
321 cras_alsa_jack_list_destroy(jack_list);
322 EXPECT_EQ(0, cras_system_rm_select_fd_called);
323 }
324
TEST(AlsaJacks,CreateGPIOHp)325 TEST(AlsaJacks, CreateGPIOHp) {
326 struct cras_alsa_jack_list *jack_list;
327
328 ResetStubData();
329 gpio_switch_list_for_each_dev_names.push_back("some-other-device");
330 gpio_switch_list_for_each_dev_names.push_back("c1 Headphone Jack");
331 eviocbit_ret[LONG(SW_HEADPHONE_INSERT)] |= 1 << OFF(SW_HEADPHONE_INSERT);
332 gpio_switch_eviocgbit_fd = 2;
333 snd_hctl_first_elem_return_val = NULL;
334 jack_list = cras_alsa_jack_list_create(0, "c1", 0, 1,
335 fake_mixer,
336 NULL, fake_hctl,
337 CRAS_STREAM_OUTPUT,
338 fake_jack_cb,
339 fake_jack_cb_arg);
340 ASSERT_NE(static_cast<struct cras_alsa_jack_list *>(NULL), jack_list);
341 EXPECT_EQ(0, cras_alsa_jack_list_find_jacks_by_name_matching(jack_list));
342 cras_alsa_jack_list_destroy(jack_list);
343 EXPECT_EQ(1, gpio_switch_list_for_each_called);
344 EXPECT_GT(gpio_switch_open_called, 1);
345 EXPECT_EQ(1, gpio_switch_eviocgsw_called);
346 EXPECT_GT(gpio_switch_eviocgbit_called, 1);
347 EXPECT_EQ(1, cras_system_add_select_fd_called);
348 EXPECT_EQ(1, cras_system_rm_select_fd_called);
349 }
350
TEST(AlsaJacks,CreateGPIOMic)351 TEST(AlsaJacks, CreateGPIOMic) {
352 struct cras_alsa_jack_list *jack_list;
353 ResetStubData();
354 ucm_get_dev_for_jack_return = true;
355 gpio_switch_list_for_each_dev_names.push_back("c1 Mic Jack");
356 gpio_switch_list_for_each_dev_names.push_back("c1 Headphone Jack");
357 eviocbit_ret[LONG(SW_MICROPHONE_INSERT)] |= 1 << OFF(SW_MICROPHONE_INSERT);
358 gpio_switch_eviocgbit_fd = 3;
359 snd_hctl_first_elem_return_val = NULL;
360 ucm_get_cap_control_value = reinterpret_cast<char *>(0x1);
361
362 cras_alsa_mixer_get_input_matching_name_return_value =
363 reinterpret_cast<struct mixer_control *>(malloc(1));
364
365 jack_list = cras_alsa_jack_list_create(
366 0,
367 "c1",
368 0,
369 1,
370 fake_mixer,
371 reinterpret_cast<struct cras_use_case_mgr *>(0x55),
372 fake_hctl,
373 CRAS_STREAM_INPUT,
374 fake_jack_cb,
375 fake_jack_cb_arg);
376 ASSERT_NE(static_cast<struct cras_alsa_jack_list *>(NULL), jack_list);
377 EXPECT_EQ(0, cras_alsa_jack_list_find_jacks_by_name_matching(jack_list));
378 EXPECT_EQ(ucm_get_cap_control_called, 1);
379 EXPECT_EQ(cras_alsa_mixer_get_input_matching_name_called, 1);
380 cras_alsa_jack_list_destroy(jack_list);
381 // Mixer will be free by alsa_card_destroy, we should free it explicitly here
382 free(cras_alsa_mixer_get_input_matching_name_return_value);
383 }
384
TEST(AlsaJacks,CreateGPIOHdmi)385 TEST(AlsaJacks, CreateGPIOHdmi) {
386 struct cras_alsa_jack_list *jack_list;
387
388 ResetStubData();
389 gpio_switch_list_for_each_dev_names.push_back("c1 HDMI Jack");
390 gpio_switch_list_for_each_dev_names.push_back("c1 Mic Jack");
391 eviocbit_ret[LONG(SW_LINEOUT_INSERT)] |= 1 << OFF(SW_LINEOUT_INSERT);
392 gpio_switch_eviocgbit_fd = 3;
393 snd_hctl_first_elem_return_val = NULL;
394 jack_list = cras_alsa_jack_list_create(0, "c1", 0, 1,
395 fake_mixer,
396 NULL, fake_hctl,
397 CRAS_STREAM_OUTPUT,
398 fake_jack_cb,
399 fake_jack_cb_arg);
400 ASSERT_NE(static_cast<struct cras_alsa_jack_list *>(NULL), jack_list);
401 EXPECT_EQ(0, cras_alsa_jack_list_find_jacks_by_name_matching(jack_list));
402 EXPECT_EQ(1, gpio_switch_eviocgsw_called);
403
404 fake_jack_cb_called = 0;
405 cras_alsa_jack_list_report(jack_list);
406 EXPECT_EQ(1, fake_jack_cb_plugged);
407 EXPECT_EQ(1, fake_jack_cb_called);
408
409 cras_alsa_jack_list_destroy(jack_list);
410 EXPECT_EQ(1, gpio_switch_list_for_each_called);
411 EXPECT_GT(gpio_switch_open_called, 1);
412 EXPECT_GT(gpio_switch_eviocgbit_called, 1);
413 EXPECT_EQ(1, cras_system_add_select_fd_called);
414 EXPECT_EQ(1, cras_system_rm_select_fd_called);
415 }
416
run_gpio_jack_test(int device_index,int is_first_device,enum CRAS_STREAM_DIRECTION direction,int should_create_jack,const char * jack_name)417 void run_gpio_jack_test(
418 int device_index,
419 int is_first_device,
420 enum CRAS_STREAM_DIRECTION direction,
421 int should_create_jack,
422 const char* jack_name)
423 {
424 struct cras_alsa_jack_list *jack_list;
425 struct cras_use_case_mgr *ucm =
426 reinterpret_cast<struct cras_use_case_mgr *>(0x55);
427
428 gpio_switch_list_for_each_dev_names.push_back("some-other-device one");
429 gpio_switch_eviocgbit_fd = 2;
430 if (direction == CRAS_STREAM_OUTPUT) {
431 eviocbit_ret[LONG(SW_HEADPHONE_INSERT)] |= 1 << OFF(SW_HEADPHONE_INSERT);
432 } else {
433 eviocbit_ret[LONG(SW_MICROPHONE_INSERT)] |= 1 << OFF(SW_MICROPHONE_INSERT);
434 }
435 gpio_switch_list_for_each_dev_names.push_back(jack_name);
436 snd_hctl_first_elem_return_val = NULL;
437
438 jack_list = cras_alsa_jack_list_create(0, "c1", device_index,
439 is_first_device,
440 fake_mixer,
441 ucm, fake_hctl,
442 direction,
443 fake_jack_cb,
444 fake_jack_cb_arg);
445 ASSERT_NE(static_cast<struct cras_alsa_jack_list *>(NULL), jack_list);
446 EXPECT_EQ(0, cras_alsa_jack_list_find_jacks_by_name_matching(jack_list));
447
448 cras_alsa_jack_list_report(jack_list);
449 EXPECT_EQ(should_create_jack, fake_jack_cb_plugged);
450 EXPECT_EQ(should_create_jack, fake_jack_cb_called);
451
452 cras_alsa_jack_list_destroy(jack_list);
453 }
454
TEST(AlsaJacks,CreateGPIOHpUCMPlaybackPCMMatched)455 TEST(AlsaJacks, CreateGPIOHpUCMPlaybackPCMMatched) {
456 int device_index = 1;
457 int is_first_device = 0;
458 enum CRAS_STREAM_DIRECTION direction = CRAS_STREAM_OUTPUT;
459 int should_create_jack = 1;
460
461 ResetStubData();
462
463 /* PlaybackPCM matched, so create jack even if this is not the first device.*/
464 ucm_get_dev_for_jack_return = true;
465 ucm_get_device_name_for_dev_value = strdup("hw:c1,1");
466
467 run_gpio_jack_test(
468 device_index, is_first_device, direction, should_create_jack,
469 "c1 Headset Jack");
470 }
471
TEST(AlsaJacks,CreateGPIOHpUCMCapturePCMMatched)472 TEST(AlsaJacks, CreateGPIOHpUCMCapturePCMMatched) {
473 int device_index = 1;
474 int is_first_device = 0;
475 enum CRAS_STREAM_DIRECTION direction = CRAS_STREAM_INPUT;
476 int should_create_jack = 1;
477
478 ResetStubData();
479
480 /* CapturePCM matched, so create jack even if this is not the first device.*/
481 ucm_get_dev_for_jack_return = true;
482 ucm_get_device_name_for_dev_value = strdup("hw:c1,1");
483
484 run_gpio_jack_test(
485 device_index, is_first_device, direction, should_create_jack,
486 "c1 Mic Jack");
487 }
488
TEST(AlsaJacks,CreateGPIOHpUCMPlaybackPCMNotMatched)489 TEST(AlsaJacks, CreateGPIOHpUCMPlaybackPCMNotMatched) {
490 int device_index = 0;
491 int is_first_device = 1;
492 enum CRAS_STREAM_DIRECTION direction = CRAS_STREAM_OUTPUT;
493 int should_create_jack = 0;
494
495 ResetStubData();
496
497 /* PlaybackPCM not matched, do not create jack. */
498 ucm_get_dev_for_jack_return = true;
499 ucm_get_device_name_for_dev_value = strdup("hw:c1,2");
500
501 run_gpio_jack_test(
502 device_index, is_first_device, direction, should_create_jack,
503 "c1 Headset Jack");
504 }
505
TEST(AlsaJacks,CreateGPIOHpUCMPlaybackPCMNotSpecifiedFirstDevice)506 TEST(AlsaJacks, CreateGPIOHpUCMPlaybackPCMNotSpecifiedFirstDevice) {
507 int device_index = 1;
508 int is_first_device = 1;
509 enum CRAS_STREAM_DIRECTION direction = CRAS_STREAM_OUTPUT;
510 int should_create_jack = 1;
511
512 ResetStubData();
513
514 /* PlaybackPCM not specified, create jack for the first device. */
515 ucm_get_dev_for_jack_return = true;
516 ucm_get_device_name_for_dev_value = NULL;
517
518 run_gpio_jack_test(
519 device_index, is_first_device, direction, should_create_jack,
520 "c1 Headset Jack");
521 }
522
TEST(AlsaJacks,CreateGPIOHpUCMPlaybackPCMNotSpecifiedSecondDevice)523 TEST(AlsaJacks, CreateGPIOHpUCMPlaybackPCMNotSpecifiedSecondDevice) {
524 int device_index = 1;
525 int is_first_device = 0;
526 enum CRAS_STREAM_DIRECTION direction = CRAS_STREAM_OUTPUT;
527 int should_create_jack = 0;
528
529 ResetStubData();
530
531 /* PlaybackPCM not specified, do not create jack for the second device. */
532 ucm_get_dev_for_jack_return = true;
533 ucm_get_device_name_for_dev_value = NULL;
534
535 run_gpio_jack_test(
536 device_index, is_first_device, direction, should_create_jack,
537 "c1 Headset Jack");
538 }
539
TEST(AlsaJacks,CreateGPIOHpNoUCMFirstDevice)540 TEST(AlsaJacks, CreateGPIOHpNoUCMFirstDevice) {
541 int device_index = 1;
542 int is_first_device = 1;
543 enum CRAS_STREAM_DIRECTION direction = CRAS_STREAM_OUTPUT;
544 int should_create_jack = 1;
545
546 ResetStubData();
547
548 /* No UCM for this jack, create jack for the first device. */
549 ucm_get_dev_for_jack_return = false;
550 ucm_get_device_name_for_dev_value = NULL;
551
552 run_gpio_jack_test(
553 device_index, is_first_device, direction, should_create_jack,
554 "c1 Headset Jack");
555 }
556
TEST(AlsaJacks,CreateGPIOHpNoUCMSecondDevice)557 TEST(AlsaJacks, CreateGPIOHpNoUCMSecondDevice) {
558 int device_index = 1;
559 int is_first_device = 0;
560 enum CRAS_STREAM_DIRECTION direction = CRAS_STREAM_OUTPUT;
561 int should_create_jack = 0;
562
563 ResetStubData();
564
565 /* No UCM for this jack, dot not create jack for the second device. */
566 ucm_get_dev_for_jack_return = false;
567 ucm_get_device_name_for_dev_value = NULL;
568
569 run_gpio_jack_test(
570 device_index, is_first_device, direction, should_create_jack,
571 "c1 Headset Jack");
572 }
573
TEST(AlsaJacks,CreateGPIOMicNoUCMFirstDeviceMicJack)574 TEST(AlsaJacks, CreateGPIOMicNoUCMFirstDeviceMicJack) {
575 int device_index = 1;
576 int is_first_device = 1;
577 enum CRAS_STREAM_DIRECTION direction = CRAS_STREAM_INPUT;
578 int should_create_jack = 1;
579
580 ResetStubData();
581
582 // No UCM for this jack, create jack for the first device.
583 ucm_get_dev_for_jack_return = false;
584 ucm_get_device_name_for_dev_value = NULL;
585
586 // Mic Jack is a valid name for microphone jack.
587 run_gpio_jack_test(
588 device_index, is_first_device, direction, should_create_jack,
589 "c1 Mic Jack");
590 }
591
TEST(AlsaJacks,CreateGPIOMicNoUCMFirstDeviceHeadsetJack)592 TEST(AlsaJacks, CreateGPIOMicNoUCMFirstDeviceHeadsetJack) {
593 int device_index = 1;
594 int is_first_device = 1;
595 enum CRAS_STREAM_DIRECTION direction = CRAS_STREAM_INPUT;
596 int should_create_jack = 1;
597
598 ResetStubData();
599
600 // No UCM for this jack, create jack for the first device.
601 ucm_get_dev_for_jack_return = false;
602 ucm_get_device_name_for_dev_value = NULL;
603
604 // Headset Jack is a valid name for microphone jack.
605 run_gpio_jack_test(
606 device_index, is_first_device, direction, should_create_jack,
607 "c1 Headset Jack");
608 }
609
TEST(AlsaJacks,GPIOHdmiWithEdid)610 TEST(AlsaJacks, GPIOHdmiWithEdid) {
611 cras_alsa_jack_list* jack_list;
612
613 ResetStubData();
614 ucm_get_dev_for_jack_return = 1;
615 edid_file_ret = static_cast<char*>(calloc(1, 1)); // Freed in destroy.
616 gpio_switch_list_for_each_dev_names.push_back("c1 HDMI Jack");
617 eviocbit_ret[LONG(SW_LINEOUT_INSERT)] |= 1 << OFF(SW_LINEOUT_INSERT);
618 gpio_switch_eviocgbit_fd = 3;
619 snd_hctl_first_elem_return_val = NULL;
620 jack_list = cras_alsa_jack_list_create(
621 0,
622 "c1",
623 0,
624 1,
625 fake_mixer,
626 reinterpret_cast<struct cras_use_case_mgr *>(0x55),
627 fake_hctl,
628 CRAS_STREAM_OUTPUT,
629 fake_jack_cb,
630 fake_jack_cb_arg);
631 ASSERT_NE(static_cast<cras_alsa_jack_list*>(NULL), jack_list);
632 EXPECT_EQ(0, cras_alsa_jack_list_find_jacks_by_name_matching(jack_list));
633 EXPECT_EQ(1, gpio_switch_eviocgsw_called);
634
635 // EDID shouldn't open, callback should be skipped until re-try.
636 fake_jack_cb_called = 0;
637 cras_alsa_jack_list_report(jack_list);
638 EXPECT_EQ(0, fake_jack_cb_called);
639
640 cras_alsa_jack_list_destroy(jack_list);
641 EXPECT_EQ(1, gpio_switch_list_for_each_called);
642 EXPECT_GT(gpio_switch_open_called, 1);
643 EXPECT_GT(gpio_switch_eviocgbit_called, 1);
644 EXPECT_EQ(1, cras_system_add_select_fd_called);
645 EXPECT_EQ(1, cras_system_rm_select_fd_called);
646 }
647
TEST(AlsaJacks,CreateGPIOHpNoNameMatch)648 TEST(AlsaJacks, CreateGPIOHpNoNameMatch) {
649 struct cras_alsa_jack_list *jack_list;
650
651 ResetStubData();
652 gpio_switch_list_for_each_dev_names.push_back("some-other-device one");
653 gpio_switch_list_for_each_dev_names.push_back("some-other-device two");
654 snd_hctl_first_elem_return_val = NULL;
655 jack_list = cras_alsa_jack_list_create(0, "c2", 0, 1,
656 fake_mixer,
657 NULL, fake_hctl,
658 CRAS_STREAM_OUTPUT,
659 fake_jack_cb,
660 fake_jack_cb_arg);
661 ASSERT_NE(static_cast<struct cras_alsa_jack_list *>(NULL), jack_list);
662 EXPECT_EQ(0, cras_alsa_jack_list_find_jacks_by_name_matching(jack_list));
663
664 cras_alsa_jack_list_destroy(jack_list);
665 EXPECT_EQ(1, gpio_switch_list_for_each_called);
666 EXPECT_EQ(0, gpio_switch_open_called);
667 EXPECT_EQ(0, cras_system_add_select_fd_called);
668 EXPECT_EQ(0, cras_system_rm_select_fd_called);
669 }
670
TEST(AlsaJacks,CreateOneHpJack)671 TEST(AlsaJacks, CreateOneHpJack) {
672 std::string elem_names[] = {
673 "asdf",
674 "Headphone Jack, klasdjf",
675 "Mic Jack",
676 };
677 struct cras_alsa_jack_list *jack_list;
678
679 ResetStubData();
680 jack_list = run_test_with_elem_list(CRAS_STREAM_OUTPUT,
681 elem_names,
682 0,
683 NULL,
684 ARRAY_SIZE(elem_names),
685 0,
686 1);
687 ASSERT_NE(static_cast<struct cras_alsa_jack_list *>(NULL), jack_list);
688 ASSERT_NE(reinterpret_cast<snd_hctl_elem_callback_t>(NULL),
689 snd_hctl_elem_set_callback_value);
690 EXPECT_EQ(1, snd_hctl_elem_set_callback_called);
691
692 snd_hctl_elem_get_hctl_return_value = reinterpret_cast<snd_hctl_t *>(0x33);
693 snd_hctl_elem_get_name_called = 0;
694 snd_ctl_elem_value_get_boolean_return_value = 1;
695 snd_hctl_elem_set_callback_value(
696 reinterpret_cast<snd_hctl_elem_t *>(&elem_names[1]), 0);
697 EXPECT_EQ(1, snd_hctl_elem_get_name_called);
698 EXPECT_EQ(1, fake_jack_cb_plugged);
699 EXPECT_EQ(1, fake_jack_cb_called);
700 EXPECT_EQ(fake_jack_cb_arg, fake_jack_cb_data);
701 EXPECT_EQ(reinterpret_cast<snd_hctl_elem_t *>(&elem_names[1]),
702 snd_hctl_elem_set_callback_obj);
703
704 fake_jack_cb_called = 0;
705 cras_alsa_jack_list_report(jack_list);
706 EXPECT_EQ(1, fake_jack_cb_plugged);
707 EXPECT_EQ(1, fake_jack_cb_called);
708
709 cras_alsa_jack_list_destroy(jack_list);
710 EXPECT_EQ(2, snd_hctl_elem_set_callback_called);
711 EXPECT_EQ(reinterpret_cast<snd_hctl_elem_callback_t>(NULL),
712 snd_hctl_elem_set_callback_value);
713 }
714
TEST(AlsaJacks,CreateOneMicJack)715 TEST(AlsaJacks, CreateOneMicJack) {
716 static std::string elem_names[] = {
717 "asdf",
718 "Headphone Jack",
719 "HDMI/DP,pcm=5 Jack",
720 "HDMI/DP,pcm=6 Jack",
721 "Mic Jack",
722 };
723 struct cras_alsa_jack_list *jack_list;
724
725 ResetStubData();
726 jack_list = run_test_with_elem_list(CRAS_STREAM_INPUT,
727 elem_names,
728 0,
729 NULL,
730 ARRAY_SIZE(elem_names),
731 0,
732 1);
733 ASSERT_NE(static_cast<struct cras_alsa_jack_list *>(NULL), jack_list);
734 ASSERT_NE(reinterpret_cast<snd_hctl_elem_callback_t>(NULL),
735 snd_hctl_elem_set_callback_value);
736 EXPECT_EQ(1, snd_hctl_elem_set_callback_called);
737
738 cras_alsa_jack_list_destroy(jack_list);
739 EXPECT_EQ(0, cras_system_rm_select_fd_called);
740 EXPECT_EQ(2, snd_hctl_elem_set_callback_called);
741 EXPECT_EQ(reinterpret_cast<snd_hctl_elem_callback_t>(NULL),
742 snd_hctl_elem_set_callback_value);
743 }
744
TEST(AlsaJacks,CreateHDMIJacksWithELD)745 TEST(AlsaJacks, CreateHDMIJacksWithELD) {
746 std::string elem_names[] = {
747 "asdf",
748 "HDMI/DP,pcm=3 Jack",
749 "ELD",
750 "HDMI/DP,pcm=4 Jack"
751 };
752 struct cras_alsa_jack_list *jack_list;
753
754 ResetStubData();
755 snd_hctl_elem_get_device_return_val = 3;
756
757 jack_list = run_test_with_elem_list(
758 CRAS_STREAM_OUTPUT,
759 elem_names,
760 3,
761 NULL,
762 ARRAY_SIZE(elem_names),
763 1,
764 1);
765 ASSERT_NE(static_cast<struct cras_alsa_jack_list *>(NULL), jack_list);
766
767 /* Assert get device is called for the ELD control */
768 EXPECT_EQ(1, snd_hctl_elem_get_device_called);
769 cras_alsa_jack_list_destroy(jack_list);
770 }
771
TEST(AlsaJacks,CreateOneHpTwoHDMIJacks)772 TEST(AlsaJacks, CreateOneHpTwoHDMIJacks) {
773 std::string elem_names[] = {
774 "asdf",
775 "Headphone Jack, klasdjf",
776 "HDMI/DP,pcm=5 Jack",
777 "HDMI/DP,pcm=6 Jack",
778 "Mic Jack",
779 };
780 struct cras_alsa_jack_list *jack_list;
781
782 ResetStubData();
783 ucm_get_dev_for_jack_return = true;
784 jack_list = run_test_with_elem_list(
785 CRAS_STREAM_OUTPUT,
786 elem_names,
787 5,
788 reinterpret_cast<struct cras_use_case_mgr *>(0x55),
789 ARRAY_SIZE(elem_names),
790 1,
791 1);
792 ASSERT_NE(static_cast<struct cras_alsa_jack_list *>(NULL), jack_list);
793
794 snd_hctl_elem_get_hctl_return_value = reinterpret_cast<snd_hctl_t *>(0x33);
795 snd_hctl_elem_get_name_called = 0;
796 snd_ctl_elem_value_get_boolean_return_value = 1;
797 snd_hctl_elem_set_callback_value(
798 reinterpret_cast<snd_hctl_elem_t *>(&elem_names[2]), 0);
799 EXPECT_EQ(1, snd_hctl_elem_get_name_called);
800 EXPECT_EQ(1, fake_jack_cb_plugged);
801 EXPECT_EQ(1, fake_jack_cb_called);
802 EXPECT_EQ(fake_jack_cb_arg, fake_jack_cb_data);
803 EXPECT_EQ(reinterpret_cast<snd_hctl_elem_t *>(&elem_names[2]),
804 snd_hctl_elem_set_callback_obj);
805
806 fake_jack_cb_called = 0;
807 cras_alsa_jack_list_report(jack_list);
808 EXPECT_EQ(1, fake_jack_cb_plugged);
809 EXPECT_EQ(1, fake_jack_cb_called);
810
811 cras_alsa_jack_list_destroy(jack_list);
812 }
813
TEST(AlsaJacks,CreateHCTLHeadphoneJackFromUCM)814 TEST(AlsaJacks, CreateHCTLHeadphoneJackFromUCM) {
815 std::string elem_names[] = {
816 "HP/DP,pcm=5 Jack",
817 "Headphone Jack",
818 };
819 struct cras_alsa_jack_list *jack_list;
820 struct ucm_section *section;
821
822 section = ucm_section_create("Headphone", 0, CRAS_STREAM_OUTPUT,
823 "Headphone Jack", "hctl");
824
825 ResetStubData();
826 ucm_get_dev_for_jack_return = true;
827
828 jack_list = run_test_with_section(
829 CRAS_STREAM_OUTPUT,
830 elem_names,
831 ARRAY_SIZE(elem_names),
832 5,
833 reinterpret_cast<struct cras_use_case_mgr *>(0x55),
834 section,
835 0,
836 1);
837 ASSERT_NE(reinterpret_cast<struct cras_alsa_jack_list *>(NULL), jack_list);
838
839 snd_hctl_elem_get_hctl_return_value = reinterpret_cast<snd_hctl_t *>(0x33);
840 snd_ctl_elem_value_get_boolean_return_value = 1;
841 snd_hctl_elem_set_callback_value(
842 reinterpret_cast<snd_hctl_elem_t *>(&elem_names[1]), 0);
843 EXPECT_EQ(1, snd_hctl_elem_get_name_called);
844 EXPECT_EQ(1, fake_jack_cb_plugged);
845 EXPECT_EQ(1, fake_jack_cb_called);
846 EXPECT_EQ(fake_jack_cb_arg, fake_jack_cb_data);
847 EXPECT_EQ(reinterpret_cast<snd_hctl_elem_t *>(&elem_names[1]),
848 snd_hctl_elem_set_callback_obj);
849
850 fake_jack_cb_called = 0;
851 cras_alsa_jack_list_report(jack_list);
852 EXPECT_EQ(1, fake_jack_cb_plugged);
853 EXPECT_EQ(1, fake_jack_cb_called);
854
855 ucm_section_free_list(section);
856 cras_alsa_jack_list_destroy(jack_list);
857 }
858
TEST(AlsaJacks,CreateGPIOHeadphoneJackFromUCM)859 TEST(AlsaJacks, CreateGPIOHeadphoneJackFromUCM) {
860 struct cras_alsa_jack_list *jack_list;
861 struct cras_alsa_jack *jack;
862 struct ucm_section *section;
863
864 section = ucm_section_create("Headphone", 0, CRAS_STREAM_OUTPUT,
865 "c1 Headphone Jack", "gpio");
866
867 ResetStubData();
868 gpio_switch_list_for_each_dev_names.push_back("some-other-device");
869 gpio_switch_list_for_each_dev_names.push_back("c1 Headphone Jack");
870 eviocbit_ret[LONG(SW_HEADPHONE_INSERT)] |= 1 << OFF(SW_HEADPHONE_INSERT);
871 gpio_switch_eviocgbit_fd = 2;
872 snd_hctl_first_elem_return_val = NULL;
873 jack_list = cras_alsa_jack_list_create(0, "c1", 0, 1,
874 fake_mixer,
875 NULL, fake_hctl,
876 CRAS_STREAM_OUTPUT,
877 fake_jack_cb,
878 fake_jack_cb_arg);
879 ASSERT_NE(static_cast<struct cras_alsa_jack_list *>(NULL), jack_list);
880 EXPECT_EQ(0, cras_alsa_jack_list_add_jack_for_section(
881 jack_list, section, &jack));
882 EXPECT_EQ(1, gpio_switch_list_for_each_called);
883 EXPECT_GT(gpio_switch_open_called, 1);
884 EXPECT_EQ(1, gpio_switch_eviocgsw_called);
885 EXPECT_GT(gpio_switch_eviocgbit_called, 1);
886 EXPECT_EQ(1, cras_system_add_select_fd_called);
887 EXPECT_EQ(1, cras_alsa_mixer_get_control_for_section_called);
888
889 fake_jack_cb_called = 0;
890 ucm_get_dev_for_jack_return = true;
891 cras_alsa_jack_list_report(jack_list);
892 EXPECT_EQ(1, fake_jack_cb_plugged);
893 EXPECT_EQ(1, fake_jack_cb_called);
894 EXPECT_EQ(fake_jack_cb_arg, fake_jack_cb_data);
895
896 ucm_section_free_list(section);
897 cras_alsa_jack_list_destroy(jack_list);
898 EXPECT_EQ(1, cras_system_rm_select_fd_called);
899 }
900
TEST(AlsaJacks,BadJackTypeFromUCM)901 TEST(AlsaJacks, BadJackTypeFromUCM) {
902 std::string elem_names[] = {
903 "HP/DP,pcm=5 Jack",
904 "Headphone Jack",
905 };
906 struct cras_alsa_jack_list *jack_list;
907 struct ucm_section *section;
908
909 section = ucm_section_create("Headphone", 0, CRAS_STREAM_OUTPUT,
910 "Headphone Jack", "badtype");
911
912 ResetStubData();
913 ucm_get_dev_for_jack_return = true;
914
915 jack_list = run_test_with_section(
916 CRAS_STREAM_OUTPUT,
917 elem_names,
918 ARRAY_SIZE(elem_names),
919 5,
920 reinterpret_cast<struct cras_use_case_mgr *>(0x55),
921 section,
922 -22,
923 1);
924 EXPECT_EQ(reinterpret_cast<struct cras_alsa_jack_list *>(NULL), jack_list);
925
926 ucm_section_free_list(section);
927 }
928
TEST(AlsaJacks,NoJackTypeFromUCM)929 TEST(AlsaJacks, NoJackTypeFromUCM) {
930 std::string elem_names[] = {
931 "HP/DP,pcm=5 Jack",
932 "Headphone Jack",
933 };
934 struct cras_alsa_jack_list *jack_list;
935 struct ucm_section *section;
936
937 section = ucm_section_create("Headphone", 0, CRAS_STREAM_OUTPUT,
938 "Headphone Jack", NULL);
939
940 ResetStubData();
941 ucm_get_dev_for_jack_return = true;
942
943 jack_list = run_test_with_section(
944 CRAS_STREAM_OUTPUT,
945 elem_names,
946 ARRAY_SIZE(elem_names),
947 5,
948 reinterpret_cast<struct cras_use_case_mgr *>(0x55),
949 section,
950 -22,
951 1);
952 EXPECT_EQ(reinterpret_cast<struct cras_alsa_jack_list *>(NULL), jack_list);
953
954 ucm_section_free_list(section);
955 }
956
957 /* Stubs */
958
959 extern "C" {
960
961 // From cras_system_state
cras_system_add_select_fd(int fd,void (* callback)(void * data),void * callback_data)962 int cras_system_add_select_fd(int fd,
963 void (*callback)(void *data),
964 void *callback_data)
965 {
966 cras_system_add_select_fd_called++;
967 cras_system_add_select_fd_values.push_back(fd);
968 return 0;
969 }
cras_system_rm_select_fd(int fd)970 void cras_system_rm_select_fd(int fd)
971 {
972 cras_system_rm_select_fd_called++;
973 cras_system_rm_select_fd_values.push_back(fd);
974 }
975
976 // From alsa-lib hcontrol.c
snd_hctl_elem_get_device(const snd_hctl_elem_t * obj)977 unsigned int snd_hctl_elem_get_device(const snd_hctl_elem_t *obj) {
978 snd_hctl_elem_get_device_called = 1;
979 return snd_hctl_elem_get_device_return_val;
980 }
snd_hctl_first_elem(snd_hctl_t * hctl)981 snd_hctl_elem_t *snd_hctl_first_elem(snd_hctl_t *hctl) {
982 snd_hctl_first_elem_called++;
983
984 /* When first elem is called, restored the poped ret values */
985 while (!snd_hctl_elem_next_ret_vals_poped.empty()) {
986 snd_hctl_elem_t *tmp = snd_hctl_elem_next_ret_vals_poped.back();
987 snd_hctl_elem_next_ret_vals_poped.pop_back();
988 snd_hctl_elem_next_ret_vals.push_back(tmp);
989 }
990 return snd_hctl_first_elem_return_val;
991 }
snd_hctl_elem_next(snd_hctl_elem_t * elem)992 snd_hctl_elem_t *snd_hctl_elem_next(snd_hctl_elem_t *elem) {
993 snd_hctl_elem_next_called++;
994 if (snd_hctl_elem_next_ret_vals.empty())
995 return NULL;
996 snd_hctl_elem_t *ret_elem = snd_hctl_elem_next_ret_vals.back();
997 snd_hctl_elem_next_ret_vals.pop_back();
998 snd_hctl_elem_next_ret_vals_poped.push_back(ret_elem);
999 return ret_elem;
1000 }
snd_hctl_elem_get_name(const snd_hctl_elem_t * obj)1001 const char *snd_hctl_elem_get_name(const snd_hctl_elem_t *obj) {
1002 snd_hctl_elem_get_name_called++;
1003 const std::string *name = reinterpret_cast<const std::string *>(obj);
1004 return name->c_str();
1005 }
snd_hctl_elem_get_interface(const snd_hctl_elem_t * obj)1006 snd_ctl_elem_iface_t snd_hctl_elem_get_interface(const snd_hctl_elem_t *obj) {
1007 return SND_CTL_ELEM_IFACE_CARD;
1008 }
snd_hctl_elem_set_callback(snd_hctl_elem_t * obj,snd_hctl_elem_callback_t val)1009 void snd_hctl_elem_set_callback(snd_hctl_elem_t *obj,
1010 snd_hctl_elem_callback_t val) {
1011 snd_hctl_elem_set_callback_called++;
1012 snd_hctl_elem_set_callback_obj = obj;
1013 snd_hctl_elem_set_callback_value = val;
1014 }
snd_hctl_elem_set_callback_private(snd_hctl_elem_t * obj,void * val)1015 void snd_hctl_elem_set_callback_private(snd_hctl_elem_t *obj, void * val) {
1016 snd_hctl_elem_set_callback_private_called++;
1017 snd_hctl_elem_set_callback_private_value = val;
1018 }
snd_hctl_elem_get_callback_private(const snd_hctl_elem_t * obj)1019 void *snd_hctl_elem_get_callback_private(const snd_hctl_elem_t *obj) {
1020 return snd_hctl_elem_set_callback_private_value;
1021 }
snd_hctl_elem_get_hctl(snd_hctl_elem_t * elem)1022 snd_hctl_t *snd_hctl_elem_get_hctl(snd_hctl_elem_t *elem) {
1023 snd_hctl_elem_get_hctl_called++;
1024 return snd_hctl_elem_get_hctl_return_value;
1025 }
snd_hctl_elem_read(snd_hctl_elem_t * elem,snd_ctl_elem_value_t * value)1026 int snd_hctl_elem_read(snd_hctl_elem_t *elem, snd_ctl_elem_value_t * value) {
1027 return 0;
1028 }
snd_hctl_find_elem(snd_hctl_t * hctl,const snd_ctl_elem_id_t * id)1029 snd_hctl_elem_t *snd_hctl_find_elem(snd_hctl_t *hctl,
1030 const snd_ctl_elem_id_t *id) {
1031 const size_t* index = reinterpret_cast<const size_t*>(id);
1032 snd_hctl_find_elem_called++;
1033 if (*index < snd_hctl_find_elem_return_vals.size())
1034 return snd_hctl_find_elem_return_vals[*index];
1035 return NULL;
1036 }
snd_ctl_elem_id_set_interface(snd_ctl_elem_id_t * obj,snd_ctl_elem_iface_t val)1037 void snd_ctl_elem_id_set_interface(snd_ctl_elem_id_t *obj,
1038 snd_ctl_elem_iface_t val) {
1039 }
snd_ctl_elem_id_set_device(snd_ctl_elem_id_t * obj,unsigned int val)1040 void snd_ctl_elem_id_set_device(snd_ctl_elem_id_t *obj, unsigned int val) {
1041 }
snd_ctl_elem_id_set_name(snd_ctl_elem_id_t * obj,const char * val)1042 void snd_ctl_elem_id_set_name(snd_ctl_elem_id_t *obj, const char *val) {
1043 size_t *obj_id = reinterpret_cast<size_t*>(obj);
1044 std::map<std::string, size_t>::iterator id_name_it =
1045 snd_ctl_elem_id_set_name_map.find(val);
1046 if (id_name_it != snd_ctl_elem_id_set_name_map.end())
1047 *obj_id = id_name_it->second;
1048 else
1049 *obj_id = INT_MAX;
1050 }
1051
1052 // From alsa-lib control.c
snd_ctl_elem_value_get_boolean(const snd_ctl_elem_value_t * obj,unsigned int idx)1053 int snd_ctl_elem_value_get_boolean(const snd_ctl_elem_value_t *obj,
1054 unsigned int idx) {
1055 snd_ctl_elem_value_get_boolean_called++;
1056 return snd_ctl_elem_value_get_boolean_return_value;
1057 }
1058
1059 // From cras_alsa_mixer
cras_alsa_mixer_get_output_matching_name(const struct cras_alsa_mixer * cras_mixer,size_t device_index,const char * const name)1060 struct mixer_control *cras_alsa_mixer_get_output_matching_name(
1061 const struct cras_alsa_mixer *cras_mixer,
1062 size_t device_index,
1063 const char * const name)
1064 {
1065 cras_alsa_mixer_get_output_matching_name_called++;
1066 return cras_alsa_mixer_get_output_matching_name_return_value;
1067 }
1068
cras_alsa_mixer_get_input_matching_name(struct cras_alsa_mixer * cras_mixer,const char * control_name)1069 struct mixer_control *cras_alsa_mixer_get_input_matching_name(
1070 struct cras_alsa_mixer *cras_mixer,
1071 const char *control_name)
1072 {
1073 cras_alsa_mixer_get_input_matching_name_called++;
1074 return cras_alsa_mixer_get_input_matching_name_return_value;
1075 }
1076
cras_alsa_mixer_get_control_for_section(struct cras_alsa_mixer * cras_mixer,struct ucm_section * section)1077 struct mixer_control *cras_alsa_mixer_get_control_for_section(
1078 struct cras_alsa_mixer *cras_mixer,
1079 struct ucm_section *section)
1080 {
1081 cras_alsa_mixer_get_control_for_section_called++;
1082 return cras_alsa_mixer_get_control_for_section_return_value;
1083 }
1084
gpio_switch_eviocgbit(int fd,void * buf,size_t n_bytes)1085 int gpio_switch_eviocgbit(int fd, void *buf, size_t n_bytes)
1086 {
1087 unsigned char *p = (unsigned char *)buf;
1088
1089 /* Returns >= 0 if 'sw' is supported, negative if not.
1090 *
1091 * Set the bit corresponding to 'sw' in 'buf'. 'buf' must have
1092 * been allocated by the caller to accommodate this.
1093 */
1094 if (fd == gpio_switch_eviocgbit_fd)
1095 memcpy(p, eviocbit_ret, n_bytes);
1096 else
1097 memset(p, 0, n_bytes);
1098
1099 gpio_switch_eviocgbit_called++;
1100 return 1;
1101 }
1102
gpio_switch_eviocgsw(int fd,void * bits,size_t n_bytes)1103 int gpio_switch_eviocgsw(int fd, void *bits, size_t n_bytes)
1104 {
1105 /* Bits set to '1' indicate a switch is enabled.
1106 * Bits set to '0' indicate a switch is disabled
1107 */
1108 gpio_switch_eviocgsw_called++;
1109 memset(bits, 0xff, n_bytes);
1110 return 1;
1111 }
1112
gpio_switch_read(int fd,void * buf,size_t n_bytes)1113 int gpio_switch_read(int fd, void *buf, size_t n_bytes)
1114 {
1115 /* This function is only invoked when the 'switch has changed'
1116 * callback is invoked. That code is not exercised by this
1117 * unittest.
1118 */
1119 assert(0);
1120 return 0;
1121 }
1122
gpio_switch_open(const char * pathname)1123 int gpio_switch_open(const char *pathname)
1124 {
1125 ++gpio_switch_open_called;
1126 if (strstr(pathname, "event2"))
1127 return 2;
1128 if (strstr(pathname, "event3"))
1129 return 3;
1130 return 0;
1131 }
1132
gpio_switch_list_for_each(gpio_switch_list_callback callback,void * arg)1133 void gpio_switch_list_for_each(gpio_switch_list_callback callback, void *arg)
1134 {
1135 size_t i = 0;
1136
1137 ++gpio_switch_list_for_each_called;
1138
1139 while (i < gpio_switch_list_for_each_dev_names.size() &&
1140 i < gpio_switch_list_for_each_dev_paths.size()) {
1141 callback(gpio_switch_list_for_each_dev_paths[i].c_str(),
1142 gpio_switch_list_for_each_dev_names[i].c_str(),
1143 arg);
1144 i++;
1145 }
1146 }
1147
ucm_set_enabled(struct cras_use_case_mgr * mgr,const char * dev,int enable)1148 int ucm_set_enabled(
1149 struct cras_use_case_mgr *mgr, const char *dev, int enable) {
1150 ucm_set_enabled_value = enable;
1151 return 0;
1152 }
1153
ucm_get_cap_control(struct cras_use_case_mgr * mgr,const char * ucm_dev)1154 char *ucm_get_cap_control(struct cras_use_case_mgr *mgr, const char *ucm_dev) {
1155 ++ucm_get_cap_control_called;
1156 return ucm_get_cap_control_value;
1157 }
1158
ucm_get_dev_for_jack(struct cras_use_case_mgr * mgr,const char * jack,CRAS_STREAM_DIRECTION direction)1159 char *ucm_get_dev_for_jack(struct cras_use_case_mgr *mgr, const char *jack,
1160 CRAS_STREAM_DIRECTION direction) {
1161 ++ucm_get_dev_for_jack_called;
1162 if (ucm_get_dev_for_jack_return)
1163 return static_cast<char*>(malloc(1)); // Will be freed in jack_list_destroy.
1164 return NULL;
1165 }
1166
ucm_get_dsp_name(struct cras_use_case_mgr * mgr,const char * ucm_dev,int direction)1167 const char *ucm_get_dsp_name(struct cras_use_case_mgr *mgr, const char *ucm_dev,
1168 int direction) {
1169 ++ucm_get_dsp_name_called;
1170 return NULL;
1171 }
1172
ucm_get_edid_file_for_dev(struct cras_use_case_mgr * mgr,const char * dev)1173 const char *ucm_get_edid_file_for_dev(struct cras_use_case_mgr *mgr,
1174 const char *dev) {
1175 return edid_file_ret;
1176 }
1177
ucm_get_override_type_name(struct cras_use_case_mgr * mgr,const char * ucm_dev)1178 const char *ucm_get_override_type_name(struct cras_use_case_mgr *mgr,
1179 const char *ucm_dev)
1180 {
1181 ++ucm_get_override_type_name_called;
1182 return NULL;
1183 }
1184
ucm_get_device_name_for_dev(struct cras_use_case_mgr * mgr,const char * dev,enum CRAS_STREAM_DIRECTION direction)1185 const char *ucm_get_device_name_for_dev(struct cras_use_case_mgr *mgr,
1186 const char *dev,
1187 enum CRAS_STREAM_DIRECTION direction)
1188 {
1189 return ucm_get_device_name_for_dev_value;
1190 }
1191
cras_tm_create_timer(cras_tm * tm,unsigned int ms,void (* cb)(cras_timer * t,void * data),void * cb_data)1192 cras_timer *cras_tm_create_timer(
1193 cras_tm *tm,
1194 unsigned int ms,
1195 void (*cb)(cras_timer *t, void *data),
1196 void *cb_data) {
1197 return reinterpret_cast<cras_timer*>(0x55);
1198 }
1199
cras_tm_cancel_timer(cras_tm * tm,cras_timer * t)1200 void cras_tm_cancel_timer(cras_tm *tm, cras_timer *t) {
1201 }
1202
cras_system_state_get_tm()1203 cras_tm *cras_system_state_get_tm() {
1204 return reinterpret_cast<cras_tm*>(0x66);
1205 }
1206
edid_valid(const unsigned char * edid_data)1207 int edid_valid(const unsigned char *edid_data) {
1208 return 0;
1209 }
1210
edid_lpcm_support(const unsigned char * edid_data,int ext)1211 int edid_lpcm_support(const unsigned char *edid_data, int ext) {
1212 return 0;
1213 }
1214
edid_get_monitor_name(const unsigned char * edid_data,char * buf,unsigned int buf_size)1215 int edid_get_monitor_name(const unsigned char *edid_data,
1216 char *buf,
1217 unsigned int buf_size) {
1218 return 0;
1219 }
1220
1221 // Overwrite this function so unittest can run without 2 seconds of wait
1222 // in find_gpio_jacks.
wait_for_dev_input_access()1223 int wait_for_dev_input_access() {
1224 return 0;
1225 }
1226
1227 } /* extern "C" */
1228
1229 } // namespace
1230
main(int argc,char ** argv)1231 int main(int argc, char **argv) {
1232 ::testing::InitGoogleTest(&argc, argv);
1233 openlog(NULL, LOG_PERROR, LOG_USER);
1234 return RUN_ALL_TESTS();
1235 }
1236