Andrew Benton wrote:
> Hello Everyone,
>
> I have a boot script which sets the numlock key so I can use the number
> keypad on the end of my keyboard without thinking about having to press
> the numlock key. I think I got the code from the setleds man page and
> it goes like this:
>
> for tty in /dev/tty{1..6}
> do setleds -D +num < ${tty}
> done
>
> It runs in init 3, at the console. I've had it for years, it's always
> run fine without causing me any problems, until recently. With the 3.4
> kernel (currently 3.4-rc4) I get an error message printed on the screen
> 6 times:
> KDSKBLED: Invalid argument
> and then a big red error message 'cos the bootscript failed as setleds
> exited with a non zero return value of 1. Oddly, despite
> this, setleds works, it sets the numlock key :/ so I can work around
> the error messages by adding a little to the script:
>
> for tty in /dev/tty{1..6}
> do setleds -D +num < ${tty} &> /dev/null || true
> done
Sometimes the numlock can be jsut set in the bios. I wouldn't think the kernel
would reset that.
> Which works, does the job, sets the numlock and doesn't complain.
> However, I'd rather get to the bottom of it and fix it properly rather
> than muffle the error message. Does anyone know what has changed in the
> 3.4 kernel that is causing this? setleds comes from kbd-1.15.2. I've
> also tried kbd-1.15.3 and current git with the same results. Digging in
> the kernel, it seems that this commit is the culprit:
>
> http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blobdiff;f=drivers/tty/vt/keyboard.c;h=70d0593d3bc66331f942632130c7ddd802a65fbb;hp=898e359c54240dfa10a9c3c0dfbea5dde77f6cf3;hb=079c9534a96da9a85a2a2f9715851050fbfbf749;hpb=0fb8379dab9f97e4c56de8f9ea772c10eda27561
>
> Specifically this bit:
>
> +int vt_do_kdskled(int console, int cmd, unsigned long arg, int perm)
> +{
> + struct kbd_struct * kbd = kbd_table + console;
> + unsigned long flags;
> + unsigned char ucval;
> +
> + switch(cmd) {
> + /* the ioctls below read/set the flags usually shown in the leds */
> + /* don't use them - they will go away without warning */
> + case KDGKBLED:
> + spin_lock_irqsave(&kbd_event_lock, flags);
> + ucval = kbd->ledflagstate | (kbd->default_ledflagstate << 4);
> + spin_unlock_irqrestore(&kbd_event_lock, flags);
> + return put_user(ucval, (char __user *)arg);
> +
> + case KDSKBLED:
> + if (!perm)
> + return -EPERM;
> + if (arg & ~0x77)
> + return -EINVAL;
> + spin_lock_irqsave(&kbd_event_lock, flags);
> + kbd->ledflagstate = (arg & 7);
> + kbd->default_ledflagstate = ((arg >> 4) & 7);
> + set_leds();
> + spin_unlock_irqrestore(&kbd_event_lock, flags);
> + break; // <<<<< change to return 0;
> +
> + /* the ioctls below only set the lights, not the functions */
> + /* for those, see KDGKBLED and KDSKBLED above */
> + case KDGETLED:
> + ucval = getledstate();
> + return put_user(ucval, (char __user *)arg);
> +
> + case KDSETLED:
> + if (!perm)
> + return -EPERM;
> + setledstate(kbd, arg);
> + return 0;
> + }
> + return -ENOIOCTLCMD;
> +}
It looks like an error in the code. The only case that doesn't return is
KDSKBLED. The break then goes to return -ENOIOCTLCMD which doesn't seem right.
Try changing the break to return 0;
-- Bruce
--
http://linuxfromscratch.org/mailman/listinfo/blfs-support
FAQ: http://www.linuxfromscratch.org/blfs/faq.html
Unsubscribe: See the above information page