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