<SOLVED> xsetwacom Script for Cycling Ring-Modes

About writing shell scripts and making the most of your shell
Forum rules
Topics in this forum are automatically closed 6 months after creation.
User avatar
zorbama
Level 1
Level 1
Posts: 48
Joined: Tue Nov 20, 2012 5:20 pm
Contact:

Re: xsetwacom Script for Cycling Ring-Modes

Post by zorbama »

Favux wrote: Right. And sanette did some refinements to Karg's user land OLED app. All that's on the Intuos4 OLED thread: http://ubuntuforums.org/showthread.php?t=1380744 But having to remove the wacom.ko (usb kernel driver) module and restore it is why Eduardo Hasenleithner came up with the sysfs approach in the kernel. Actually he started with something different and the kernel maintainer suggested using sysfs instead.
This might seem silly to ask now, but... what exactly is sysfs? I tried to look for it online, and all I managed to understand is that it's a virtual filesystem. What exactly does it do, and how do we use it?

On the same note, I tried using your script. It created an empty file on my home folder called "3". I have no idea why. It also said that "0" is an unexpected operator and refused to work, and I'm really not sure why, as it doesn't seem too differently built from my own script.
There is one thing, though: the part:

Code: Select all

if [ $[MODE + 1] > 3 ]; then
        echo 0 > /tmp/mode_state
else
        echo $[MODE + 1] > /tmp/mode_state
fi
doesn't add 1 to the existing number in /tmp/mode_number, but rather replaces it with + 1.

I looked for the status_led0_select file and found two which could be fitting, however I couldn't edit any one of them, not even with sudo, and I couldn't open them with a text editor.

So I'm absolutely baffled now.
Favux wrote: This totally mystifies me. Sounds like something is being reset and I don't understand the button 5. According to my BambooPT HOW TO notes I guess that would be vertical scroll down wih 4 scroll up. Why can't you just use 5? But the key thing is you've shown the Wacom drivers are disabling the indended mode selection action of Button 1, i.e. the button in the center of the touch ring. To me that appears to be a bug the dev.s need to address. Of course there may be some way to handle it already and I am ignorant of it. You know, the kind of thing if you can just read through the C code is obvious.
Well, it's kinda hard to describe, but basically, what happens is that you use the same button names to point to which button you want to assign the keys, i.e., the middle button remains button 1, the bottom button is button 2, etc., but you can use the parameters 1, 2, 3, etc., to assign behaviors of those buttons, numbered from top to bottom.

For example, if my top button is configured to toggle touch capabalities, and I want to assign it to the fourth-to-top button (for whatever reason), I can do the following:

Code: Select all

xsetwacom set "Wacom Intuos5 touch M Pen pad Button 10 1
Since button 1 is the fifth-to-top, the parameter 5 stands for mode change, which cycles through the LED's.
Favux wrote: If scroll down makes Button 1 go through modes I don't see why that would mess with assigning vertical scroll to other buttons. Strange.
It's not scroll down. Rather, setting the parameter "button 5" isn't setting it to the X button 5, but to the tablet's fifth-to-top button.
Favux wrote: I think so too. This is fun. You're the first who's really been interested in exploring this so I'm learning a lot.
And me. This is really a very positive experience for me, as I'm quite a beginner in Linux (I've been using it for around a year and am still finding it difficult at some points).
"Inspiring quote" -Inspiring Person
Favux

Re: xsetwacom Script for Cycling Ring-Modes

Post by Favux »

You've got it. The sysfs is a temporary file system set up by the kernel at boot containing all the hardware. It's virtual in that it isn't permanently stored on the disk. And the idea is you can treat it just like it is a file system on a hard drive or whatever. It's to replace proc, because that got too messy. Suppose to have only one value per file, or else very simple data, to avoid the previous mess.

OK. I'll try to motivate myself to debug my script. At least with your script I now have valid examples of something for each of the 4 modes to do. :) I knew I should have used parenthesis in the counter.

So what is the full path to the two status_led0_select files? And you're sure they are files? Can't even cat a value out of them? Wonder what that is about?

We may be getting confused about button numbers. There is the physical and then the X button number. Because X reserves buttons 4 thru 7 for scroll there is a skip. So instead of:
2
3
4
5

1

6
7
8
9
It is:
2
3
8
9

1

10
11
12
13
Is that where you are coming from?
User avatar
zorbama
Level 1
Level 1
Posts: 48
Joined: Tue Nov 20, 2012 5:20 pm
Contact:

Re: xsetwacom Script for Cycling Ring-Modes

Post by zorbama »

Well, now I think there are a lot more than two of those files, since I see them in:
/sys/bus/usb/devices/1-1.4:1.0/wacom_led
and
/sys/bus/usb/devices/1-1.4:1.1/wacom_led
But also in:
/sys/bus/usb/drivers/wacom/1-1.4:1.0
and
/sys/bus/usb/drivers/wacom/1-1.4:1.1
I did manage to cat a value out of them, using sudo, and that value is 0, so you're probably right, but I can't write to it, not even with sudo.
You're saying maybe they aren't files. That's possible, but then what exactly are they, and how do we work with them?

Well, that's kind of what I meant. I think that what happens when you unload and reload the module, it just doesn't use X buttons anymore. So what you get is that there are two names to every button: one name used to assign behaviors to that button, and one to assign that button as a behavior. So you have both:

13
12
11
10

1

9
8
3
2

and:

1
2
3
4

5

6
7
8
9

but I'm not sure it's very relevant, anyway, as long as we don't unload and reload the module.
Unless it is?
"Inspiring quote" -Inspiring Person
Favux

Re: xsetwacom Script for Cycling Ring-Modes

Post by Favux »

I bit the bullet and unboxed my Christmas present, an Inutous4. I had promised myself I would explore multitouch on the other Christmas present, a third generation BambooPT, first. Although I pretty much have multitouch doped out in Ubuntu I still haven't gotten around to trying to set up multitouch for it in Mint etc. Oh well, there goes discipline... :)

To read the file:

Code: Select all

gksudo gedit /sys/bus/usb/devices/3-2:1.0/wacom_led/status_led0_select
But that gives this warning:
There was a problem opening the file /sys/bus/usb/devices/3-2…om_led/status_led0_select.
The file you opened has some invalid characters. If you continue editing this file you could corrupt this document.
You can also choose another character encoding and try again.
Character Encoding: Current Locale (UTF-8)
Choosing the Western (ISO-8859-15) didn't help anything.

But since I'm able to read the contents anyway I went through the cycle.
Mode LED 1 lit
0\00
Press Button 1 - Mode LED 2 lit
1\00
Press Button 1 - Mode LED 3 lit
2\00
Press Button 1 - Mode LED 4 lit
3\00
Press Button 1 - Mode LED 1 lit
0\00

I'm not sure what character it is talking about or how to find out. So far my experience has been nothing bad happens if I ignore the warning but that's probably been dumb luck. Looking like we need to write the value with a trailing \00, which is a bit weird. Try that next.

Still not sure I understand what you are telling me about the button numbers. I'll stare at it a bit more.
Last edited by Favux on Wed Mar 06, 2013 8:05 pm, edited 1 time in total.
Favux

Re: xsetwacom Script for Cycling Ring-Modes

Post by Favux »

Cool. I'm able to switch the LED from the command line. Unfortunately I do have to use sudo. Example:

Code: Select all

sudo bash -c "echo 3 > /sys/bus/usb/devices/3-2:1.0/wacom_led/status_led0_select"
What we're doing is elevating the privilege of the shell, sudo in the current shell alone won't do it. And we just use the integers 0 to 3. My guess is \00 is the invalid encoding character it wasn't recognizing.

Does it work for you?

Then I took the chance that substituting a wildcard for the bus number etc. wouldn't blow anything up:

Code: Select all

sudo bash -c "echo 3 > /sys/bus/usb/devices/*/wacom_led/status_led0_select"
And it worked! :D That simplifies life for us as long as it doesn't break anything.

Or we could use tee insteading of escalating the shell privilege.

Code: Select all

echo 3 | sudo tee /sys/bus/usb/devices/*/wacom_led/status_led0_select
Anyway for the script it is clear I'll have to attempt a udev rule to change permissions on status_led0_select so the user, and not just root, can write to it. Don't see how that could be a security risk. This could take quite a while. :)
User avatar
zorbama
Level 1
Level 1
Posts: 48
Joined: Tue Nov 20, 2012 5:20 pm
Contact:

Re: xsetwacom Script for Cycling Ring-Modes

Post by zorbama »

Yes, that seems to work. It says one of the files is a "broken pipe", so I directed it only to the other file, and it works as well.

I don't know anything about udev, but maybe I'll try to find out. At any rate, this is fantastic progress. :mrgreen:
"Inspiring quote" -Inspiring Person
Favux

Re: xsetwacom Script for Cycling Ring-Modes

Post by Favux »

Not getting far with the udev rule. To get a match this is the attributes walk I did.

Code: Select all

~$ udevadm info -a -p /sys/bus/usb/devices/3-2:1.0/wacom_led

Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.

  looking at device '/bus/usb/devices/3-2/3-2:1.0/wacom_led':
    KERNEL=="wacom_led"
    SUBSYSTEM=="subsystem"
    DRIVER==""

  looking at parent device '/bus/usb/devices/3-2/3-2:1.0':
    KERNELS=="3-2:1.0"
    SUBSYSTEMS=="usb"
    DRIVERS=="wacom"
    ATTRS{bInterfaceNumber}=="00"
    ATTRS{bAlternateSetting}==" 0"
    ATTRS{bNumEndpoints}=="01"
    ATTRS{bInterfaceClass}=="03"
    ATTRS{bInterfaceSubClass}=="01"
    ATTRS{bInterfaceProtocol}=="02"
    ATTRS{supports_autosuspend}=="1"

  looking at parent device '/devices/pci0000:00/0000:00:12.0/usb3/3-2':
    KERNELS=="3-2"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{configuration}==""
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bmAttributes}=="80"
    ATTRS{bMaxPower}=="300mA"
    ATTRS{urbnum}=="25"
    ATTRS{idVendor}=="056a"
    ATTRS{idProduct}=="00b9"
    ATTRS{bcdDevice}=="0104"
    ATTRS{bDeviceClass}=="00"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="00"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{speed}=="12"
    ATTRS{busnum}=="3"
    ATTRS{devnum}=="2"
    ATTRS{devpath}=="2"
    ATTRS{version}==" 1.10"
    ATTRS{maxchild}=="0"
    ATTRS{quirks}=="0x0"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{authorized}=="1"
    ATTRS{manufacturer}=="Tablet"
    ATTRS{product}=="PTK-640"

  looking at parent device '/devices/pci0000:00/0000:00:12.0/usb3':
    KERNELS=="usb3"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{configuration}==""
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bmAttributes}=="e0"
    ATTRS{bMaxPower}=="  0mA"
    ATTRS{urbnum}=="51"
    ATTRS{idVendor}=="1d6b"
    ATTRS{idProduct}=="0001"
    ATTRS{bcdDevice}=="0302"
    ATTRS{bDeviceClass}=="09"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="00"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{speed}=="12"
    ATTRS{busnum}=="3"
    ATTRS{devnum}=="1"
    ATTRS{devpath}=="0"
    ATTRS{version}==" 1.10"
    ATTRS{maxchild}=="3"
    ATTRS{quirks}=="0x0"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{authorized}=="1"
    ATTRS{manufacturer}=="Linux 3.2.0-38-generic ohci_hcd"
    ATTRS{product}=="OHCI Host Controller"
    ATTRS{serial}=="0000:00:12.0"
    ATTRS{authorized_default}=="1"

  looking at parent device '/devices/pci0000:00/0000:00:12.0':
    KERNELS=="0000:00:12.0"
    SUBSYSTEMS=="pci"
    DRIVERS=="ohci_hcd"
    ATTRS{vendor}=="0x1002"
    ATTRS{device}=="0x4397"
    ATTRS{subsystem_vendor}=="0x103c"
    ATTRS{subsystem_device}=="0x2a92"
    ATTRS{class}=="0x0c0310"
    ATTRS{irq}=="16"
    ATTRS{local_cpus}=="00000000,00000000,00000000,00000000,00000000,00000000,00000000,0000000f"
    ATTRS{local_cpulist}=="0-3"
    ATTRS{numa_node}=="0"
    ATTRS{dma_mask_bits}=="32"
    ATTRS{consistent_dma_mask_bits}=="32"
    ATTRS{broken_parity_status}=="0"
    ATTRS{msi_bus}==""

  looking at parent device '/devices/pci0000:00':
    KERNELS=="pci0000:00"
    SUBSYSTEMS==""
    DRIVERS==""
This is the tutorial I use for writing udev rules: http://reactivated.net/writing_udev_rules.html Not quite sure how to change permissions on a file through udev. Didn't think MODE would do the trick so I've been trying something like:

Code: Select all

RUN+="/bin/chmod 666 /sys/bus/usb/devices/3-2:1.0/wacom_led/status_led0_select"
Using the explicit path to begin with. I think I've got the match so it's probably some problem with how I'm trying to change the permissions.

After thumping my head into the wall a few times I said to heck with it and added a command to rc.local that seems to work fine.

Code: Select all

gksudo gedit /etc/rc.local
Added before exit 0:

Code: Select all

# Change permissions on status_led0_select file so being root isn't
# required to switch Wacom Intuos mode status LEDs.
/bin/chmod 666 /sys/bus/usb/devices/*/wacom_led/status_led0_select
Now I'll go back and debug the script. Getting there. :)
Favux

Re: xsetwacom Script for Cycling Ring-Modes

Post by Favux »

I think we're there! :)

I debugged and tested the script and it is working fine for me. Call it touchring-toggle.sh or whatever you want:

Code: Select all

#!/bin/bash

## Touch ring toggle script
##
## Bind Button 1 (button center of touch ring) to the script.
##
## To allow script to select mode status LEDs edit rc.local to change root
## only permissions on the sysfs status_led0_select file:
##   gksudo gedit /etc/rc.local
## Add the following comment and command (before 'exit 0'):
##   # Change permissions on status_led0_select file so being root isn't
##   # required to switch Wacom touch ring mode status LEDs.
##   /bin/chmod 666 /sys/bus/usb/devices/*/wacom_led/status_led0_select
##
## Intuos - status_led0_select file = the left (only) ring status LEDs.
## Cintiq - status_led1_select = the left ring; status_led0_select =
## the right ring status LEDs.  Same for the touchstrips.
##
## For mode state notification use:
##   sudo apt-get install libnotify-bin
## Otherwise comment (#) out the notify-send lines.  If libnotify-bin
## installed see 'man notify-send' for details.

# check if mode_state file exists, if not create it and set to 0
if [ ! -f /tmp/mode_state ]; then
        echo 0 > /tmp/mode_state
fi

# read mode state value from temporary file
MODE=`cat /tmp/mode_state`

# select touch ring mode status LED for current mode state
echo $MODE > /sys/bus/usb/devices/*/wacom_led/status_led0_select

# for DEVICE use the pad "device name" from 'xinput list'
DEVICE="Wacom Intuos4 6x9 pad"
#DEVICE="Wacom Intuos5 touch M Pen pad"

# set touch ring function option and notification for the 4 toggled modes
if [ "$MODE" == 0 ]; then
        xsetwacom set  "$DEVICE" AbsWheelUp 4  # scroll up
        xsetwacom set  "$DEVICE" AbsWheelDown 5  # scroll down
        notify-send -t 1500 "Mode 1:  Scroll up or down."
elif [ "$MODE" == 1 ]; then
        xsetwacom set  "$DEVICE" AbsWheelUp key alt up  # increase brush radius (must be mapped in GIMP)
        xsetwacom set  "$DEVICE" AbsWheelDown key alt down  # decrease brush radius (must be mapped in GIMP)
        notify-send -t 1500 "Mode 2:  Increase or decrease brush size in Gimp"
elif [ "$MODE" == 2 ]; then
        xsetwacom set  "$DEVICE" AbsWheelUp key shift plus  # zoom in
        xsetwacom set  "$DEVICE" AbsWheelDown key minus  # zoom out
        notify-send -t 1500 "Mode 3:  Zoom in or out in Gimp."
elif [ "$MODE" == 3 ]; then
        xsetwacom set  "$DEVICE" AbsWheelUp key PgUp  # select previous layer
        xsetwacom set  "$DEVICE" AbsWheelDown key PgDn  # select next layer
        notify-send -t 1500 "Mode 4:  Select previous or next layer in Gimp"
fi

# toggle button increment counter
MODE=$((MODE += 1))

# set next mode state
if (( "$MODE" > 3 )); then  # roll over to 0, only 4 mode states available
        echo 0 > /tmp/mode_state
else
        echo $MODE > /tmp/mode_state
fi
Make the script executable with chmod +x /path/to/script or right click on the script file and choose Properties and in the Permissions tab check 'Allow executing file as program'.

I added the rc.local LED stuff to the comments. So the bottom of the rc.local file should end up looking like:

Code: Select all

# bits.
#
# By default this script does nothing.

# Change permissions on status_led0_select file so being root isn't
# required to switch Wacom Intuos mode status LEDs.
/bin/chmod 666 /sys/bus/usb/devices/*/wacom_led/status_led0_select

exit 0
If you use the comments I added that is.

Does it work for you?

Not sure how much more effort I want to put into a udev rule. I don't know if a udev rule would be technically more "correct" than using rc.local. I suspect it probably is. But the rub is I don't know the technically "correct" way to modify permissions on a sysfs file owned by the device. Permissions on the device itself, i.e. its node, sure but not a file associated with the device.

Edit: 3-31-13 minor update of script
Last edited by Favux on Sun Mar 31, 2013 7:58 pm, edited 1 time in total.
User avatar
zorbama
Level 1
Level 1
Posts: 48
Joined: Tue Nov 20, 2012 5:20 pm
Contact:

Re: xsetwacom Script for Cycling Ring-Modes

Post by zorbama »

Well, your script still isn't working for me (and it's still creating a file called "3" in my home folder...), but after editing the rc.local file as you instructed and adding to my own script rules to change the LEDs, it seems to work just fine.
And unless there are some security issues or I don't know what else (and you say there aren't), then I believe we're done! My tablet is now working exactly as I want it to work.
Again, thank you very much for your help! This was very fun and highly educational.

I suppose I should see that it's still working tomorrow, just in case anything doesn't work, but for now, I'm marking this thread as SOLVED! :D

Also, here is what my script looks like now:

Code: Select all

#!/bin/bash

CHECK=`cat /tmp/mode_state`

if [ "$CHECK" == 0 ]
then
echo 1 > /tmp/mode_state
echo 1 > /sys/bus/usb/devices/1-1.4:1.0/wacom_led/status_led0_select
xsetwacom set "Wacom Intuos5 touch M Pen pad" AbsWheelUp "key d"
xsetwacom set "Wacom Intuos5 touch M Pen pad" AbsWheelDown "key f"
notify-send -t 1500 "Brush Size"
elif [ "$CHECK" == 1 ]
then
echo 2 > /tmp/mode_state
echo 2 > /sys/bus/usb/devices/1-1.4:1.0/wacom_led/status_led0_select
xsetwacom set "Wacom Intuos5 touch M Pen pad" AbsWheelUp "key comma"
xsetwacom set "Wacom Intuos5 touch M Pen pad" AbsWheelDown "key period"
notify-send -t 1500 "Zoom"
elif [ "$CHECK" == 2 ]
then
echo 3 > /tmp/mode_state
echo 3 > /sys/bus/usb/devices/1-1.4:1.0/wacom_led/status_led0_select
xsetwacom set "Wacom Intuos5 touch M Pen pad" AbsWheelUp "key PgUp"
xsetwacom set "Wacom Intuos5 touch M Pen pad" AbsWheelDown "key PgDn"
notify-send -t 1500 "Browse Layers"
else
echo 0 > /tmp/mode_state
echo 0 > /sys/bus/usb/devices/1-1.4:1.0/wacom_led/status_led0_select
xsetwacom set "Wacom Intuos5 touch M Pen pad" AbsWheelUp 4
xsetwacom set "Wacom Intuos5 touch M Pen pad" AbsWheelDown 5
notify-send -t 1500 "Scroll"
fi
"Inspiring quote" -Inspiring Person
Favux

Re: <SOLVED> xsetwacom Script for Cycling Ring-Modes

Post by Favux »

Good, and thanks for sharing your current script.

The file labeled 3 is from a permission problem I think. Change directory into the directory the touchring-toggle.sh script is in. The run the script in a terminal with:

Code: Select all

./touchring-toggle.sh
You should see an error message that will have the line number of the line causing the error. Please post that error message so I can see what's wrong and fix it.

In terms of security the only file(s) being affected should be status_led0_select. It goes from read write by root only:

Code: Select all

~$ ls -l /sys/bus/usb/devices/3-2:1.0/wacom_led/status_led0_select
-rw------- 1 root root 4096 Mar  6 12:10 /sys/bus/usb/devices/3-2:1.0/wacom_led/status_led0_select
to read write by everyone:

Code: Select all

~/Desktop$ ls -l /sys/bus/usb/devices/3-2:1.0/wacom_led/status_led0_select
-rw-rw-rw- 1 root root 4096 Mar  7 10:13 /sys/bus/usb/devices/3-2:1.0/wacom_led/status_led0_select
I can't see how it matters if anyone can change the status LED on a tablet. Otherwise we have to go through adding a group besides root to the file permissions. And then add the user to the new group. Seems like a fair amount of work for no apparent gain.
Locked

Return to “Scripts & Bash”