6

Something that's always bothered me about Linux kernel configuration: the PC speaker as a source of generic beeps is considered a "miscellaneous input device". Why is this? I'd expect it to be in some output-related category, or perhaps "Misc. devices".

  │ CONFIG_INPUT_PCSPKR:
  │ 
  │ Say Y here if you want the standard PC Speaker to be used for
  │ bells and whistles.
  │
  │ Prompt: PC Speaker support
  │   Location:
  │     -> Device Drivers
  │       -> Input device support
  │         -> Generic input layer (needed for keyboard, mouse, ...) (INPUT [=y])
  │           -> Miscellaneous devices (INPUT_MISC [=y])

(Note: this is distinct from the use of the PC speaker as an ALSA/OSS sound card.)

Mark
  • 4,244

1 Answers1

8

Probably because it was convenient at the time, and the simplest way to make it accessible to the user using kernel structures already present.

It's not so well known that one can write to the /dev/input/eventX files, and in this way generate input-level events.

In the same way, one can write EV_SND events to the /dev/input/eventX file representing the speaker (or to one of the symlinks, usually /dev/input/by-path/platform-pcspkr-event-spkr), and in this way use the speaker to generate sound. This is even less known. :-)

Here is a perl oneliner for 32 bit systems that generates a note with specified pitch

perl -e 'print pack("qssl", 0, 0x12, 2, 2000)' > /dev/input/by-path/platform-pcspkr-event-spkr

and here's another onliner to turn it off

perl -e 'print pack("qssl", 0, 0x12, 2, 0)' > /dev/input/by-path/platform-pcspkr-event-spkr

For 64 bit systems, use

pack("qqssl", 0, 0, 0x12, 2, PITCH)

The actual layout depends on how the C header file defining the structure is compiled.

BTW, the plug events for HDA audio devices also show up in the input layer as /dev/input/eventX files. Though it's a bit more logical to classify those as actual input events.

dirkt
  • 32,309
  • 2
    Note that the exact binary format of the event is platform-specific (I guess?). On my x86-64 machine with Linux kernel 5.2, it is 24-bytes long, starting with 16 null bytes instead of 8. So for me the working format is pack("qqssl", 0, 0, 0x12, 2, PITCH). – Maëlan Aug 30 '19 at 17:32
  • 1
    @Maëlan: Yes, it depends on how the C struct which defines it is compiled. I edited the answer. – dirkt Aug 31 '19 at 06:55