Linux - KernelThis forum is for all discussion relating to the Linux kernel.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
We had a class this week in which we got a simple 'kernel beep' driver working (but on 2.4), so now I'm trying to get kernel beep sounds in Ubuntu Gutsy Gibbon.
It seems the pcspkr driver is the driver I need to 'talk to', but I'm not sure how.
One normally has to do 'mknod /dev/foo c major minor', but I can't seem to find the major and minor device number. I tried looking in the source code of the driver itself, but didn't get any clues.
The documentation of the kernel (specifically, the devices.txt file) contained information on the 'fancy beep device' (major 10, minor 128), so I tried: 'mknod /dev/beep c 10 128', but 'sudo echo "a" > /dev/beep' gave me 'access denied'.
I'm kinda clueless now, I'm afraid.
Oh, and I'm pretty sure pcspkr is loaded, since I can do 'rmmod pcspkr' successfully. The 'fancy beep device' on the other hand, might not be loaded.
We had a class this week in which we got a simple 'kernel beep' driver working (but on 2.4), so now I'm trying to get kernel beep sounds in Ubuntu Gutsy Gibbon.
It seems the pcspkr driver is the driver I need to 'talk to', but I'm not sure how.
One normally has to do 'mknod /dev/foo c major minor', but I can't seem to find the major and minor device number. I tried looking in the source code of the driver itself, but didn't get any clues.
The documentation of the kernel (specifically, the devices.txt file) contained information on the 'fancy beep device' (major 10, minor 128), so I tried: 'mknod /dev/beep c 10 128', but 'sudo echo "a" > /dev/beep' gave me 'access denied'.
I'm kinda clueless now, I'm afraid.
Oh, and I'm pretty sure pcspkr is loaded, since I can do 'rmmod pcspkr' successfully. The 'fancy beep device' on the other hand, might not be loaded.
You can use the lsmod command to find out what modules are loaded. See:
man lsmod
You set up the relationships among /dev/beep, pcspkr, and your module in /etc/modules.conf. The setup for Ubuntu Gutsy Gibbon will be the same as however you set it up on the 2.4 kernel.
No, that's not what I mean. The module we used in class only compiled on 2.4 (it relies on a few kernel libraries that don't exist/changed in 2.6).
I basically just want to be able to work with pcspkr, by sending commands to it.
I know it should be possible to create a location like /dev/beep , to which I could send commands (so pcspkr receives them and produces a 'beep' sound). I just don't know how to do this ('mknod' requires knowing the major and minor device numbers, which I don't).
Does it make sense, what I'm asking, or am I being unclear?
I basically just want to be able to work with pcspkr, by sending commands to it.
I know it should be possible to create a location like /dev/beep , to which I could send commands (so pcspkr receives them and produces a 'beep' sound). I just don't know how to do this ('mknod' requires knowing the major and minor device numbers, which I don't).
Well, the driver is very different from the type you wrote before. A device node will be created, but it happens to be very different from what you’d expect. The device for pcspkr is (mainly for historical reasons) an “input device” (which means it provides a way to relay input events from the kernel to userspace, as well as process the events themselves). This is much like a mouse device or a keyboard device. Anyway the input event device will be provided with major number 13 and a dynamically-assigned minor number (starting at 64 and incrementing for each event device). You don’t have to worry about manually mknoding since udev will take care of it for you. For example, on my system it goes like this (after I’ve done “modprobe pcspkr”:
Code:
/dev/input/event0: AT Translated Set 2 keyboard
/dev/input/event1: ImPS/2 Logitech Wheel Mouse
/dev/input/event2: Power Button (FF)
/dev/input/event3: Power Button (CM)
/dev/input/event4: PC Speaker
Now each of these devices give you nice input events if you read them from userspace. As an example, you might try
Code:
od -tx1 -w32 /dev/input/event0
Since this is a keyboard, when I do any thing keyboardy (such as pressing or releasing a key), an nice 32-byte value is written to my screen. This value contains lots of information such as the timestamp, the event type, the event code, and the value associated with the event. Of course to really make sense of this information, it would be easiest to do something like this from a loop in a C program:
Anyway, that’s the only way you’re supposed to use input event devices from userspace (namely, you’re not supposed to write to them).
But you’re probably saying, “making a speaker beep obviously requires some sort of ‘write’ operation” and you’re correct. The only thing is that you don’t do it through the driver’s device node. Currently the way to do this is by using an ioctl() on the root console (i.e., on /dev/console). Basically, it goes like this:
Code:
#define DESIRED_FREQ 440 /* We want the frequency to be of note A */
int fd;
fd = open("/dev/console", O_WRONLY);
…
ioctl(fd, KIOCSOUND, CLOCK_TICK_RATE / DESIRED_FREQ) /* Now, the speaker is made to beep */
sleep(1);
ioctl(fd, KIOCSOUND, 0); /* Now, the speaker is silenced */
Note that there is also a different type of beep: the one implemented by the BIOS itself. I.e., if you do a rudimentary “putchar” of 0x7 (\a) to the BIOS you get an implementation-specific beep. This is not seen by the input event device at all.
Btw, there is a userspace program that uses those ioctls and makes them available in a nice scriptable form (much like your original intent with the kernel module): beep.
Here is also a (rather old) guide to making a device driver, one purpose of which is to intercept writes such as:
Code:
echo "uuull" > /dev/idiom
And to synthesize them into fake keyboard arrow movements. If you wanted to, you could do something similar and make a module whose sole purpose is to take input such as:
Code:
echo "440f1000d" > /dev/beeper
And translate it into a frequency and duration with which to beep the internal speaker using the pcspkr driver as a backend. This would eliminate any script-unfriendliness that comes from using an ioctl, but not resort to duplicating code.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.