Skip to content

Commit

Permalink
evdev: fall back to SND_BELL if SND_TONE is unsupported
Browse files Browse the repository at this point in the history
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 <[email protected]>
from johnath#17 for spkr-beep.

No well-known devices names for those devices are known, so we
cannot try them by default.
  • Loading branch information
ndim committed Mar 10, 2020
1 parent 6947157 commit fd4cc0d
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 15 deletions.
3 changes: 2 additions & 1 deletion beep-driver-console.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,8 @@ beep_driver driver_data =
driver_begin_tone,
driver_end_tone,
0,
NULL
NULL,
0
};


Expand Down
78 changes: 69 additions & 9 deletions beep-driver-evdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
* \brief implement the beep evdev driver
* \author Copyright (C) 2000-2010 Johnathan Nightingale
* \author Copyright (C) 2010-2013 Gerfried Fuchs
* \author Copyright (C) 2019 Hans Ulrich Niedermann
* \author Copyright (C) 2019-2020 Hans Ulrich Niedermann
* \author Copyright (C) 2020 Bastian Krause
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand All @@ -27,6 +28,7 @@
*/


#include <stdbool.h>
#include <stddef.h>

#include <errno.h>
Expand All @@ -50,6 +52,12 @@
#define LOG_MODULE "evdev"


enum snd_api_type {
SND_API_TONE,
SND_API_BELL
};


static
int open_checked_device(const char *const device_name)
{
Expand Down Expand Up @@ -77,25 +85,60 @@ bool driver_detect(beep_driver *driver, const char *console_device)
LOG_VERBOSE("driver_detect %p %p",
(void *)driver, (const void *)console_device);
}

bool device_open = false;

if (console_device) {
const int fd = open_checked_device(console_device);
if (fd >= 0) {
driver->device_fd = fd;
driver->device_name = console_device;
return true;
device_open = true;
}
} else {
/* Make this a list of well-known device names when more
* well-known.device names become known to us.
*/
static
const char *const default_name =
"/dev/input/by-path/platform-pcspkr-event-spkr";
const int fd = open_checked_device(default_name);
if (fd >= 0) {
driver->device_fd = fd;
driver->device_name = default_name;
return true;
device_open = true;
}
}
return false;

if (!device_open) {
return false;
}

unsigned long evbit = 0;
if (-1 == ioctl(driver->device_fd,
EVIOCGBIT(EV_SND, sizeof(evbit)), &evbit)) {
LOG_VERBOSE("%d does not implement EVIOCGBIT",
driver->device_fd);
return false;
}

enum snd_api_type snd_api;
if (evbit & (1 << SND_TONE)) {
snd_api = SND_API_TONE;
LOG_VERBOSE("found SND_TONE support for fd=%d",
driver->device_fd);
} else if (evbit & (1 << SND_BELL)) {
snd_api = SND_API_BELL;
LOG_VERBOSE("falling back to SND_BELL support for fd=%d",
driver->device_fd);
} else {
LOG_VERBOSE("fd=%d supports neither SND_TONE nor SND_BELL",
driver->device_fd);
return false;
}

driver->device_flags = snd_api;
return true;
}


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

memset(&e, 0, sizeof(e));
e.type = EV_SND;
e.code = SND_TONE;
e.value = freq;
switch ((enum snd_api_type)(driver->device_flags)) {
case SND_API_TONE:
e.code = SND_TONE;
e.value = freq;
break;
case SND_API_BELL:
e.code = SND_BELL;
e.value = (0 == 0);
break;
}

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

memset(&e, 0, sizeof(e));
e.type = EV_SND;
e.code = SND_TONE;
e.value = 0;
switch ((enum snd_api_type)(driver->device_flags)) {
case SND_API_TONE:
e.code = SND_TONE;
e.value = 0;
break;
case SND_API_BELL:
e.code = SND_BELL;
e.value = (0 != 0);
break;
}

if (sizeof(e) != write(driver->device_fd, &e, sizeof(e))) {
safe_error_exit("write EV_SND");
Expand All @@ -163,7 +222,8 @@ beep_driver driver_data =
driver_begin_tone,
driver_end_tone,
0,
NULL
NULL,
0
};


Expand Down
3 changes: 2 additions & 1 deletion beep-driver-noop.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ beep_driver driver_data =
driver_begin_tone,
driver_end_tone,
0,
NULL
NULL,
0
};


Expand Down
3 changes: 3 additions & 0 deletions beep-driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ struct _beep_driver {

/** device file name for this driver */
const char *device_name;

/** driver specific set of flags */
unsigned int device_flags;
};


Expand Down
5 changes: 3 additions & 2 deletions beep-main.c
Original file line number Diff line number Diff line change
Expand Up @@ -529,9 +529,10 @@ int main(const int argc, char *const argv[])
}
}

LOG_VERBOSE("using %s driver (fd=%d, dev=%s)",
LOG_VERBOSE("using %s driver (fd=%d, dev=%s, flags=0x%x)",
driver->name,
driver->device_fd, driver->device_name);
driver->device_fd, driver->device_name,
driver->device_flags);

/* At this time, we know what API to use on which device, and we do
* not have to fall back onto printing '\a' any more.
Expand Down
3 changes: 2 additions & 1 deletion tests/11-beep-default-logs.expected.0
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ beep-log: Verbose: drivers: beep_drivers_register <DRV2> (noop)
BEEP_EXECUTABLE: Verbose: noop: driver_detect <DRV2> (nil)
BEEP_EXECUTABLE: Verbose: evdev: driver_detect <DRV1> (nil)
BEEP_EXECUTABLE: Verbose: lib: opened /dev/input/by-path/platform-pcspkr-event-spkr as fd=<FD0>
BEEP_EXECUTABLE: Verbose: main: using evdev driver (fd=<FD0>, dev=/dev/input/by-path/platform-pcspkr-event-spkr)
BEEP_EXECUTABLE: Verbose: evdev: found SND_TONE support for fd=<FD0>
BEEP_EXECUTABLE: Verbose: main: using evdev driver (fd=<FD0>, dev=/dev/input/by-path/platform-pcspkr-event-spkr, flags=0x0)
BEEP_EXECUTABLE: Verbose: main: 1 times 200 ms beeps (100 ms delay between, 0 ms delay after) @ 440 Hz
BEEP_EXECUTABLE: Verbose: evdev: driver_begin_tone <DRV1> 440
BEEP_EXECUTABLE: Verbose: evdev: driver_end_tone <DRV1>
Expand Down
3 changes: 2 additions & 1 deletion tests/11-beep-default-logs.expected.1
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ beep-log: Verbose: evdev: beep_driver_evdev_constructor
beep-log: Verbose: drivers: beep_drivers_register <DRV1> (evdev)
BEEP_EXECUTABLE: Verbose: evdev: driver_detect <DRV1> (nil)
BEEP_EXECUTABLE: Verbose: lib: opened /dev/input/by-path/platform-pcspkr-event-spkr as fd=<FD0>
BEEP_EXECUTABLE: Verbose: main: using evdev driver (fd=<FD0>, dev=/dev/input/by-path/platform-pcspkr-event-spkr)
BEEP_EXECUTABLE: Verbose: evdev: found SND_TONE support for fd=<FD0>
BEEP_EXECUTABLE: Verbose: main: using evdev driver (fd=<FD0>, dev=/dev/input/by-path/platform-pcspkr-event-spkr, flags=0x0)
BEEP_EXECUTABLE: Verbose: main: 1 times 200 ms beeps (100 ms delay between, 0 ms delay after) @ 440 Hz
BEEP_EXECUTABLE: Verbose: evdev: driver_begin_tone <DRV1> 440
BEEP_EXECUTABLE: Verbose: evdev: driver_end_tone <DRV1>
Expand Down

0 comments on commit fd4cc0d

Please sign in to comment.