From: Stas Sergeev Added SND_SILENT event that allows to disable (and enable) the driver, either to grant the hardware access to some other driver, or to disable the annoying beeps. Signed-off-by: Stas Sergeev Cc: Vojtech Pavlik Signed-off-by: Andrew Morton --- drivers/input/misc/pcspkr.c | 62 +++++++++++++++++++++++++++++++------------- include/linux/input.h | 1 2 files changed, 46 insertions(+), 17 deletions(-) diff -puN drivers/input/misc/pcspkr.c~pc-speaker-add-snd_silent drivers/input/misc/pcspkr.c --- devel/drivers/input/misc/pcspkr.c~pc-speaker-add-snd_silent 2005-09-13 18:47:45.000000000 -0700 +++ devel-akpm/drivers/input/misc/pcspkr.c 2005-09-13 18:47:45.000000000 -0700 @@ -27,25 +27,16 @@ static char pcspkr_name[] = "PC Speaker" static char pcspkr_phys[] = "isa0061/input0"; static struct input_dev pcspkr_dev; +/* Please replace this with i8253_lock to properly serialize an + * accesses to port 0x43 */ static DEFINE_SPINLOCK(i8253_beep_lock); -static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) +enum { PCSPKR_NORMAL, PCSPKR_SUSPENDED }; + +static void pcspkr_do_sound(unsigned int count) { - unsigned int count = 0; unsigned long flags; - if (type != EV_SND) - return -1; - - switch (code) { - case SND_BELL: if (value) value = 1000; - case SND_TONE: break; - default: return -1; - } - - if (value > 20 && value < 32767) - count = PIT_TICK_RATE / value; - spin_lock_irqsave(&i8253_beep_lock, flags); if (count) { @@ -62,6 +53,40 @@ static int pcspkr_event(struct input_dev } spin_unlock_irqrestore(&i8253_beep_lock, flags); +} + +static int pcspkr_event(struct input_dev *dev, unsigned int type, + unsigned int code, int value) +{ + unsigned int count = 0; + + switch (type) { + case EV_SND: + switch (code) { + case SND_BELL: + if (value) + value = 1000; + case SND_TONE: + break; + case SND_SILENT: + dev->state = value ? PCSPKR_SUSPENDED : PCSPKR_NORMAL; + return 0; + default: + return -1; + } + break; + + default: + return -1; + } + + if (dev->state == PCSPKR_SUSPENDED) + return 0; + + if (value > 20 && value < 32767) + count = PIT_TICK_RATE / value; + + pcspkr_do_sound(count); return 0; } @@ -69,7 +94,7 @@ static int pcspkr_event(struct input_dev static int __init pcspkr_init(void) { pcspkr_dev.evbit[0] = BIT(EV_SND); - pcspkr_dev.sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE); + pcspkr_dev.sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE) | BIT(SND_SILENT); pcspkr_dev.event = pcspkr_event; pcspkr_dev.name = pcspkr_name; @@ -78,6 +103,7 @@ static int __init pcspkr_init(void) pcspkr_dev.id.vendor = 0x001f; pcspkr_dev.id.product = 0x0001; pcspkr_dev.id.version = 0x0100; + pcspkr_dev.state = PCSPKR_NORMAL; input_register_device(&pcspkr_dev); @@ -88,9 +114,11 @@ static int __init pcspkr_init(void) static void __exit pcspkr_exit(void) { + if (pcspkr_dev.state == PCSPKR_NORMAL) { + /* turn off the speaker */ + pcspkr_do_sound(0); + } input_unregister_device(&pcspkr_dev); - /* turn off the speaker */ - pcspkr_event(NULL, EV_SND, SND_BELL, 0); } module_init(pcspkr_init); diff -puN include/linux/input.h~pc-speaker-add-snd_silent include/linux/input.h --- devel/include/linux/input.h~pc-speaker-add-snd_silent 2005-09-13 18:47:45.000000000 -0700 +++ devel-akpm/include/linux/input.h 2005-09-13 18:47:45.000000000 -0700 @@ -617,6 +617,7 @@ struct input_absinfo { #define SND_CLICK 0x00 #define SND_BELL 0x01 #define SND_TONE 0x02 +#define SND_SILENT 0x06 #define SND_MAX 0x07 /* _