Note: In the past I had heard that sonypi was incompatible with ACPI, but APM was okay. This is no longer entirely true: sonypi can work in an ACPI-enabled kernel, but trying to use ACPI functions can sometimes disable the device. A related question is whether it's possible to get the jog dial working as an ACPI device (which might be important for more recent ACPI-only Sony SR laptops). On my SR17, I don't see any hint of the device using a 2.4.21pre3 ACPI kernel. I'd be interested to hear whether it does show up in the newer ACPI-dependant SR models.
Module, or compiled in? It's better to build sonypi as a module if you can get away with it. It means that the module isn't loaded until you actually use it, and you can turn on options like fnkeysinit (see Documentation/sonypi.txt for the lines to add to modules.conf, but be sure to change them for the minor device number used by your system, or use modprobe to insert the module).
sonypi: device allocated minor is 61(I see 61 on my SR17 when sonypi is a module, 63 when it's built in; I think the 505 series uses 250.) Now, substituting the right minor device number:
mknod /dev/sonypi c 10 61
If you're running an older kernel, you'll need a user-space driver to monitor the sonypi device and turn jogdial events into simulated mouse events (or whatever else you want to do with them). Go to Stelian Pop's site to get the user-space drivers; pick up both sonypid and spicctrl, as they're small and there's useful stuff in both.
Type make to build the utilities. I had to #ifdef out the SONYPI_EVENT_PKEY* events in the switch statement in sonypid.c, because those symbols aren't defined in the 2.4.7 kernel. Now run sonypid in your X initialization script (.xinitrc on most systems, .Xclients on Redhat 7.1) and the jog dial will scroll like a mouse wheel, assuming you've set up X to handle that.
ZAxisMapping 4 5(thanks to Colas Nahaboo X mouse wheel scroll page for that tip). Do that and make sure the appropriate kernel modules are loaded, and add "sonypid &" or "jog_scroll &" or whatever to your X startup script (.Xclients on Redhat, .xinitrc everywhere else) and you'll be all set.
If you aren't comfortable making modifications to the programs yourself (or just want something that works), you can download a tarball of the programs I use here. Extract the tarball (tar xzvf akkjog.tgz), cd into the directory and type make. It will make two programs, called bright and sonypid. Copy these programs to some directory that's in your path (/usr/local/bin, $HOME/bin or somewhere like that).
Bright just changes the arguments to the spicctrl program; I could never keep -b and -B straight, so typing "bright" tells me the screen brightness while "bright nn" sets the screen brightness. With my version of sonypid, clicking the wheel is like a middle mouse push, rolling the wheel does scrolling (simulating a mouse wheel), and rolling the wheel while pushing adjusts screen brightness. The F4 and F5 keys also control screen brightness, if you have them enabled in the driver (which I don't since it interferes with power management). Also, if you're not sure the driver is working, you can run with -d to get debug messages.
(Note that if sonypid is running, running bright at the same time will shut out sonypid's access to the device; don't mix them. I run sonypid from my .Xclients, and only use bright when I'm in the console.)
First, it sounded like a fun idea to have jog-dial-press be like middle-mouse press (i.e., paste the selection). That's easy:
case SONYPI_EVENT_JOGDIAL_RELEASED: simulateButton(disp, 2); verboseEvent("Jogdial Released"); break;
Then I noticed SONYPI_EVENT_JOGDIAL_DOWN_PRESSED, and had the idea that it would be neat if pressing the jog dial brought up a context menu in whatever app I was in, and turning it while pressed moved the selection in the context menu. This was also pretty easy:
static int ctxtMenuUp = 0; static int ctxtMenuChanged = 0; [ ... ] case SONYPI_EVENT_JOGDIAL_DOWN_PRESSED: ctxtMenuChanged = 1; simulateKeyPress(disp, "Down"); verboseEvent("Jogdial Down & Pressed"); break; case SONYPI_EVENT_JOGDIAL_UP_PRESSED: ctxtMenuChanged = 1; simulateKeyPress(disp, "Up"); verboseEvent("Jogdial Up & Pressed"); break; case SONYPI_EVENT_JOGDIAL_PRESSED: ctxtMenuUp = 1; simulateButton(disp, 3); //simulateKeyRelease(disp, "Return"); verboseEvent("Jogdial Pressed"); break; case SONYPI_EVENT_JOGDIAL_RELEASED: if (ctxtMenuUp) { if (ctxtMenuChanged) simulateKeyPress(disp, "Return"); else simulateButton(disp, 3); ctxtMenuUp = 0; ctxtMenuChanged = 0; } else { simulateButton(disp, 2); } verboseEvent("Jogdial Released"); break;(The theory is that if you just press, it'll still paste, but if you turn it while it's pressed, it'll navigate the menu and so won't paste.) But it turned out I didn't like this much. It works great in apps that have context menus and allow up/down arrows to navigate them, but lots of Linux apps don't, and I don't like what it does in rxvt (I middlemouse paste in rxvt a lot more than I use context menus in any app) so I gave up on this idea.
Finally, wouldn't it be nice if your Fn keys controlled brightness like they do on Windows? The following code goes brighter when you press Fn-F5, dimmer when you press Fn-F6. (But I'm not running this myself; I leave my function keys disabled because they interfere with power management, i.e. the machine won't sleep when I toggle the power key, and that's more important to me.)
#include <sys/ioctl.h> [ ... ] static int spic_ioctl(int, __u8 *); void changeBrightness(int incr); [ ... ] case SONYPI_EVENT_FNKEY_F5: changeBrightness(15); verboseEvent("Fn-F5 Pressed"); break; case SONYPI_EVENT_FNKEY_F6: changeBrightness(-15); verboseEvent("Fn-F6 Pressed"); break; [ ... ] void changeBrightness(int incr) { __u8 value8; if (spic_ioctl(SONYPI_IOCGBRT, &value8) < 0) return; value8 += incr; spic_ioctl(SONYPI_IOCSBRT, &value8); } /* * Sends a ioctl command to the SPIC driver. * * Return: 0 if success, -1 if an error occured. */ static int spic_ioctl(int ioctlno, __u8 *param) { int fd; if ( (fd = open("/dev/sonypi", O_RDWR)) == -1) { fprintf(stderr, "Failed to open /dev/sonypi: %s\n", strerror(errno)); return -1; } if (ioctl(fd, ioctlno, param) < 0) { fprintf(stderr, "ioctl failed: %s\n", strerror(errno)); return -1; } close(fd); return 0; }(Note, spic_ioctl and the knowledge of how to do this is lifted from the spicctrl.c program, by the nice people at Alcove Labs.)
But after I disabled my function keys, I needed another way to do that (command line is fine with me, but running a command-line program that opens sonypi disturbs sonypid so it stops working). So now I have brightness on the wheel-move-when-pressed:
static int pressed = 0; [ ... ] case SONYPI_EVENT_JOGDIAL_DOWN_PRESSED: changeBrightness(-12); pressed = 1; break; case SONYPI_EVENT_JOGDIAL_UP_PRESSED: changeBrightness(12); pressed = 1; break; [ ... ] case SONYPI_EVENT_JOGDIAL_RELEASED: if (!pressed) simulateButton(disp, 2); pressed = 0;
These ideas should get you started making your own sonypid configuration -- have fun!
Stay tuned for other hacks! I'll be updating this page as I discover new things I can do.
jogdiald looks like a nifty, highly configurable way to make your jogdial do virtually whatever you want it to. It may make all my hacks obsolete. I haven't checked it out yet, but I will. Also check out the S-Jog project at Sourceforge for another more jog dial controller, or see the SJog home page)
Before I discovered that sonypi was built in to 2.4.7, I was using Takaya Kinjo's spicdriver driver for the Jog Dial wheel on his PictureBook. (I suspect the spicdriver code was later folded into the sonypi code.) It works fine with the SR17, though it was written for a 505, and was very easy to install. John Heidemann has written a program which uses Kinjo's driver to emulate a mouse scroll wheel. Heidemann's tarball includes the basic driver as well as the jog_scroll control. It can drive other things besides just mouse scrolling. The README file explains how to compile and install it.