Skip to content

Commit 3a6dbd0

Browse files
committed
evdev: fall back to SND_BELL if SND_TONE is unsupported
The gpio-beeper driver does not support SND_TONE, but SND_BELL. So we send SND_BELL instead when SND_TONE is not supported. Adapted the pull request from Bastian Krause <bst@pengutronix.de> from johnath#17 for spkr-beep. No well-known devices names for those devices are known, so we cannot try them by default.
1 parent 0bd5314 commit 3a6dbd0

File tree

5 files changed

+79
-13
lines changed

5 files changed

+79
-13
lines changed

beep-driver-console.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,8 @@ beep_driver driver_data =
164164
driver_begin_tone,
165165
driver_end_tone,
166166
0,
167-
NULL
167+
NULL,
168+
0
168169
};
169170

170171

beep-driver-evdev.c

Lines changed: 69 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
* \brief implement the beep evdev driver
33
* \author Copyright (C) 2000-2010 Johnathan Nightingale
44
* \author Copyright (C) 2010-2013 Gerfried Fuchs
5-
* \author Copyright (C) 2019 Hans Ulrich Niedermann
5+
* \author Copyright (C) 2019-2020 Hans Ulrich Niedermann
6+
* \author Copyright (C) 2020 Bastian Krause
67
*
78
* This program is free software; you can redistribute it and/or modify
89
* it under the terms of the GNU General Public License as published by
@@ -27,6 +28,7 @@
2728
*/
2829

2930

31+
#include <stdbool.h>
3032
#include <stddef.h>
3133

3234
#include <errno.h>
@@ -50,6 +52,12 @@
5052
#define LOG_MODULE "evdev"
5153

5254

55+
enum snd_api_type {
56+
SND_API_TONE,
57+
SND_API_BELL
58+
};
59+
60+
5361
static
5462
int open_checked_device(const char *const device_name)
5563
{
@@ -77,25 +85,60 @@ bool driver_detect(beep_driver *driver, const char *console_device)
7785
LOG_VERBOSE("driver_detect %p %p",
7886
(void *)driver, (const void *)console_device);
7987
}
88+
89+
bool device_open = false;
90+
8091
if (console_device) {
8192
const int fd = open_checked_device(console_device);
8293
if (fd >= 0) {
8394
driver->device_fd = fd;
8495
driver->device_name = console_device;
85-
return true;
96+
device_open = true;
8697
}
8798
} else {
99+
/* Make this a list of well-known device names when more
100+
* well-known.device names become known to us.
101+
*/
88102
static
89103
const char *const default_name =
90104
"/dev/input/by-path/platform-pcspkr-event-spkr";
91105
const int fd = open_checked_device(default_name);
92106
if (fd >= 0) {
93107
driver->device_fd = fd;
94108
driver->device_name = default_name;
95-
return true;
109+
device_open = true;
96110
}
97111
}
98-
return false;
112+
113+
if (!device_open) {
114+
return false;
115+
}
116+
117+
unsigned long evbit = 0;
118+
if (-1 == ioctl(driver->device_fd,
119+
EVIOCGBIT(EV_SND, sizeof(evbit)), &evbit)) {
120+
LOG_VERBOSE("%d does not implement EVIOCGBIT",
121+
driver->device_fd);
122+
return false;
123+
}
124+
125+
enum snd_api_type snd_api;
126+
if (evbit & (1 << SND_TONE)) {
127+
snd_api = SND_API_TONE;
128+
LOG_VERBOSE("found SND_TONE support for fd=%d",
129+
driver->device_fd);
130+
} else if (evbit & (1 << SND_BELL)) {
131+
snd_api = SND_API_BELL;
132+
LOG_VERBOSE("falling back to SND_BELL support for fd=%d",
133+
driver->device_fd);
134+
} else {
135+
LOG_VERBOSE("fd=%d supports neither SND_TONE nor SND_BELL",
136+
driver->device_fd);
137+
return false;
138+
}
139+
140+
driver->device_flags = snd_api;
141+
return true;
99142
}
100143

101144

@@ -124,8 +167,16 @@ void driver_begin_tone(beep_driver *driver, const uint16_t freq)
124167

125168
memset(&e, 0, sizeof(e));
126169
e.type = EV_SND;
127-
e.code = SND_TONE;
128-
e.value = freq;
170+
switch ((enum snd_api_type)(driver->device_flags)) {
171+
case SND_API_TONE:
172+
e.code = SND_TONE;
173+
e.value = freq;
174+
break;
175+
case SND_API_BELL:
176+
e.code = SND_BELL;
177+
e.value = (0 == 0);
178+
break;
179+
}
129180

130181
if (sizeof(e) != write(driver->device_fd, &e, sizeof(e))) {
131182
/* If we cannot use the sound API, we cannot silence the sound either */
@@ -143,8 +194,16 @@ void driver_end_tone(beep_driver *driver)
143194

144195
memset(&e, 0, sizeof(e));
145196
e.type = EV_SND;
146-
e.code = SND_TONE;
147-
e.value = 0;
197+
switch ((enum snd_api_type)(driver->device_flags)) {
198+
case SND_API_TONE:
199+
e.code = SND_TONE;
200+
e.value = 0;
201+
break;
202+
case SND_API_BELL:
203+
e.code = SND_BELL;
204+
e.value = (0 != 0);
205+
break;
206+
}
148207

149208
if (sizeof(e) != write(driver->device_fd, &e, sizeof(e))) {
150209
safe_error_exit("write EV_SND");
@@ -163,7 +222,8 @@ beep_driver driver_data =
163222
driver_begin_tone,
164223
driver_end_tone,
165224
0,
166-
NULL
225+
NULL,
226+
0
167227
};
168228

169229

beep-driver-noop.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,8 @@ beep_driver driver_data =
8989
driver_begin_tone,
9090
driver_end_tone,
9191
0,
92-
NULL
92+
NULL,
93+
0
9394
};
9495

9596

beep-driver.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ struct _beep_driver {
104104

105105
/** device file name for this driver */
106106
const char *device_name;
107+
108+
/** driver specific set of flags */
109+
unsigned int device_flags;
107110
};
108111

109112

beep-main.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -529,9 +529,10 @@ int main(const int argc, char *const argv[])
529529
}
530530
}
531531

532-
LOG_VERBOSE("using %s driver (fd=%d, dev=%s)",
532+
LOG_VERBOSE("using %s driver (fd=%d, dev=%s, flags=0x%x)",
533533
driver->name,
534-
driver->device_fd, driver->device_name);
534+
driver->device_fd, driver->device_name,
535+
driver->device_flags);
535536

536537
/* At this time, we know what API to use on which device, and we do
537538
* not have to fall back onto printing '\a' any more.

0 commit comments

Comments
 (0)