All
I noticed this problem about 6 months ago and wrote a quick and dirty
kernel module to solve the problem then it slipped my mind.
Basically the pc speaker access from userspace is tied to having a valid
tty in the machine. When there is no tty in the computer the pc speaker
wont work. This of course means you need a video card in said machine.
See vt.c it is the only interface to the pc speaker in the entire
kernel. The ioctl and trying to echo magic characters to a tty thus both
interface there.
Anyway I dont think it would be a good idea to put this proc interface
(as proc interface is a quick hack) into the mainstream kernel but I do
think the pc speaker should be available irelevant of video card
presence.
I know this works on intel machines, havent tested it on non intel
machines. Heck I dont even know how the equivalent of the pc speaker
would be accessed on non intel or if there is one.
I distribute this module as part of some programs I wrote for use with
wireless networking equipment, see http://wibble.net/~sjh/wireless for
use in a computer I have in the roof with no video card.
the module code follows my signature.
I sent this note to Alan a few months back instead of lkml, oh well you
get the idea.
I tried sending this a few days ago to lkml, however I have not seen it
show up on the kernelnotes.org archive and thus suspect it was dropped
by vger, I have this itme set my mail server as my isp's mail server
rather than my behind masq internal mail server.
See You
Steve
--
sjh@wibble.net http://wibble.net/~sjh/
Look Up In The Sky
Is it a bird? No
Is it a plane? No
Is it a small blue banana?
YES
/*********************************************************************
* pcspeaker -- kernel module providing a proc interface allowing *
* you to use a pc speaker on a machine with no video *
* card *
* *
* Usage: insmod the module *
* echo "frequency duration" > /proc/pcspeaker *
* duration is measured in milliseconds *
* eg. echo "440 1000" > /proc/pcspeaker *
* will make the speaker beep at note A for a second *
* *
* Author: Steven Hanley *
* Date: 20/08/99 *
* Last Modified: See ChangeLog *
*********************************************************************/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <asm/string.h>
#include <asm/io.h>
EXPORT_NO_SYMBOLS;
/* following two functions taken from linux/drivers/char/vt.c
basically it is a broken thing about the kernel that you can not
use a pc speaker in the linxu kernel (ioctl or echo to a tty)
unless there is working tty (ie a video card in the machine)
*/
/*
* Generates sound of some frequency for some number of clock ticks
*
* If freq is 0, will turn off sound, else will turn it on for that
* time. If msec is 0, will return immediately, else will sleep for
* msec time, then turn sound off.
*
* We also return immediately, which is what was implied within
* the X comments - KDMKTONE doesn't put the process to sleep.
*/
static void kd_nosound(unsigned long ignored)
{
/* disable counter 2 */
outb(inb_p(0x61)&0xFC, 0x61);
return;
}
static void kd_mksound(unsigned int hz, unsigned int ticks)
{
static struct timer_list sound_timer = { NULL, NULL, 0, 0,
kd_nosound };
unsigned int count = 0;
if (hz > 20 && hz < 32767)
count = 1193180 / hz;
cli();
del_timer(&sound_timer);
if (count) {
/* enable counter 2 */
outb_p(inb_p(0x61)|3, 0x61);
/* set command for counter 2, 2 byte write */
outb_p(0xB6, 0x43);
/* select desired HZ */
outb_p(count & 0xff, 0x42);
outb((count >> 8) & 0xff, 0x42);
if (ticks) {
sound_timer.expires = jiffies+ticks;
add_timer(&sound_timer);
}
} else
kd_nosound(0);
sti();
return;
}
static int pcspeaker_write_proc(struct file *file,
const char *buffer,
unsigned long count, void *data)
{
char *str, *endptr;
int frequency, snd_dur;
if (! ((memchr (buffer, ' ', count)) &&
(memchr (buffer, '\n', count)))) {
return count;
}
frequency = (int) simple_strtoul (buffer, &endptr, 0);
if (*endptr != ' ') {
return count;
}
str = memchr (buffer, ' ', count) + 1;
snd_dur = (int) simple_strtoul (str, &endptr, 0);
if (*endptr != '\n') {
return count;
}
kd_mksound (frequency, (snd_dur * HZ / 1000));
return count;
}
static struct proc_dir_entry *proc_entry;
/* this function is called by the kernel when the module is
loaded */
int init_module(void)
{
int ret = 0;
proc_entry = create_proc_entry("pcspeaker",
S_IFREG | S_IRUGO,
&proc_root);
if (!proc_entry) {
printk("Failed to register /proc/pcspeaker\n");
return -1;
}
proc_entry->write_proc = pcspeaker_write_proc;
return ret;
}
/* this function is called by the kernel when the module is
removed */
void cleanup_module(void)
{
proc_unregister(&proc_root,proc_entry->low_ino);
}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/
This archive was generated by hypermail 2b29 : Wed Jun 07 2000 - 21:00:14 EST