Solved kbdcontrol pitch and duration

I'm new to FreeBSD, but I have managed to install 11.1-RELEASE onto my trusty Thinkpad T520. The only fancy thing I did was to install Links to more easily read the Handbook while testing out the commands in other virtual terminals.

The man page for kbdcontrol(1) says that I can change the duration and pitch of the bell, but I have been unable to achieve this. I've tried kbdcontrol -b 100.300 as well as several other values. kbdcontrol -b quiet.visual works for silencing the bell, but I would like to lower the pitch of the bell.

I checked out the source and edited kbdcontrol with some printf statements to see what is being done with those parameters in the program, and it seems to be utilizing them correctly. The magic happens with the following line:
Code:
// I did a print statement here to verify this was being executed
fprintf(stderr, "^[[=%d;%dB", pitch, duration);

I've tried this as a normal user in the wheel group and as the super user. I've installed beep(1) from ports to verify that I could issue a beep at different pitches, but I'm not clear about whether that is being issued from the system bell or the speakers.

What process is watching stderr for this line? How can I determine what the current value of the system bell pitch and duration are?
 
Hmm. First, if you are running Xwindows (including KDE, Gnome and such), it may take over control of the hardware bell; look at program xset and its options. Second: I can't test this on a Thinkpad T520 (my youngest Thinkpad is a T60, and none of my thinkpads run FreeBSD right now), but I just tested it on a small server motherboard, and kbdcontrol -b ... is simply ignored on my hardware.

Completely different set of questions: You added a print statement to kbdcontrol, and that didn't work. To begin with, are you sure you are really running your new version? To verify, try adding a print statement at the very beginning, or modify an existing printout (like the one that happens when you call kbdcontrol -i). Next: why are you using stderr, and not stdout? This is for debug only, and it prevents problems with having two separate output streams that can get confused. You asked where stderr goes: when you are running kbdcontrol from a shell (which is by definition from the console, since it doesn't work when logged in remotely), stderr goes to the terminal = console, unless you have done something silly like "kbdcontrol ... 2> /dev/null". But the weirdest thing is your print statement. You seem to be printing an ANSI control sequence for the terminal, namely CSI ... B 9 (which is equivalent to ESC [ ..., the pseudo-character CSI can be created from an escape sequence), which is one of the cursor control sequences for terminals. Except that you garbled it, by giving it two parameters (CSI dd;bb B), and I have no idea what the console implementation does when it gets a cursor movement command with two parameters. And after printing this, the shell will print the new prompt, which will implicitly move the cursor again. So the effect of your printing is invisible.

Here's what I would do:
Code:
printf("Hi this is the wesofwaco modified version of kbdcontrol.\n");
printf("About to set -b to pitch=%d duration=%d.\n", pitch, duration);
When debugging, verbose output is good!
 
ralphbsz , thanks for the information. I might not have been as clear as I could in the initial post.

I do not have X installed, because I want to walk through the Handbook without the distractions that would arise when using a gui. So, there is no possibility of any X process taking control of the bell.

I did previously insert some printf statements, make, and make install to test out what was being done with the pitch.duration parameters. These parameters are used appropriately by the kbdcontrol as evident by the printf statements' output to the console.

The line I have the question about is the one you were confused by.
Code:
fprintf(stderr, "^[[=%d;%dB", pitch, duration);
This line is from the source for kbdcontrol and has been there for at least 23 years. I did not add this, and I am confused about how printing something to stderr should change the system bell pitch or duration.

I kept looking for a way to tail stderr or something to see what happens when the vanilla kbdcontrol is run, but according to you stderr and stdout should both be coming through my tty. Is that correct?
 
Innnnterrresssting. It seems that kbdcontrol is implemented by sending that ANSI escape sequence (terminal control sequence) to the terminal. You do know that there are many interesting control sequences you can send to a terminal? For example "ESC [ 31 m" = "CSI [ 31 m" will cause all text to be printed in red from now on, and "ESC [ 7 m" causes it to be inverted. To check that theory: can you please read the source code for kbdcontrol, and make sure it doesn't use any other means to adjust the bell? In theory, there could be an ioctl() call against the console device, or a termios() call.

If that is correct, then a sensible guess is that the FreeBSD console simply doesn't implement that control sequence. You can actually easily test that: From a shell prompt, enter "echo ESC[=ppp;dddB" (for some suitable values of pitch and duration), and entering escape is done by ControlG", which is done again by control-v control-g. For a sanity check, enter "echo ESC[31m", and see all the text turn red, or ESC[7m and it will be black-on-white or the other way around (turn all those off with ESC[0m).

My theory is now (until new information proves it wrong and causes me to come up with a new theory) that the FreeBSD console simply doesn't implement that control sequence. Maybe it is commonly used on other hardware (old ANSI terminals, the Linux or Solaris console, who knows) and kbdcontrol hasn't been updated to know where it works and where it doesn't. That could be tested. Matter-of-fact, if you have infinite time and energy, you could download the source code for the kernel, and look at the implementation of the console (warning: there is lots of code there, because of virtual terminals and the VGA/frame buffer subsystem there are multiple layers), and see where control sequences are decoded, and whether/where that particular control sequence is handled.

Now, about how to see stderr: That's super easy. All you need is shell redirection. For example: "kbdcontrol ... 2> /tmp/foo" will run whatever kbdcontrol command you entered, display stdout in the usual place, and save stderr in the file /tmp/foo. Then you can view that file. Obviously it would be dumb to say "cat /tmp/foo", because that will copy the escape sequence directly to your console, where it will be promptly ignored. So instead use hexdump to view it. Matter-of-fact, I just tried this:
Code:
> kbdcontrol -b 100.300 2> /tmp/foo
> hexdump -C /tmp/foo
00000000  1b 5b 3d 33 39 37 37 3b  31 30 42                 |.[=3977;10B|
0000000b
kbdcontrol -b 200.400 2> /tmp/foo
> hexdump -C /tmp/foo
00000000  1b 5b 3d 32 39 38 32 3b  32 30 42                 |.[=2982;20B|
0000000b
Very strange. Indeed, it seems that kbdcontrol simply works by outputting an escape sequence. It also seems to take the parameters and garble them in an interesting fashion. With the source code or an hour of experimentation, you can make further headway.
 
Okay, I think I've come to understand why this is not working for me. It's not a solution, but it is an answer.

The friendly folks over at #freebsd on irc helped me to discover that I am using vt(4) rather than syscon (which is what the Handbook is written to cover). I did not select this during installation, but it was established on my system. vt(4) is meant to be a replacement of syscon, but apparently not all the features have been fleshed out yet.

Here is the wiki showing the features that have been implemented and those in progress. From there I found a link to Bugzilla for problem reports with the keyword vt. Earlier my searches were centered around kbdcontrol, so I didn't find this; because I didn't know to look for vt specifically. And within the list is PR204837 which is "kbdcontrol -b does not work with vt(4)". So there's the answer. Implementing the bell pitch change is probably out of my depth, but I'll take a look anyhow.
 
Back
Top