LINUX.ORG.RU

Восстановление состояния светодиодов на клавиатуре

 ,


0

1

Мне было необходимо управлять индикацией светодиодов на клавиатуре, для этого я использовал следующий код:

void set_leds(int val) 
{
	int fd = open ("/dev/console", O_WRONLY);
	ioctl (fd, KDSETLED, val);
	close(fd);
} 
Но теперь у меня возник вопрос, как можно восстановить прежнее состояние светодиодов, уже после выполнения кода. Можно ли как-то узнать какие сейчас горят светодиоды, запустить set_leds (в соответствии с обстоятельствами их индикация поменяется), а после выполнения необходимого участка восстановить прежнее состояние?

Использование X11 рассматривается?

Маленький пример для Num Lock

См. ещё xkbvleds

beastie ★★★★★
()
Ответ на: комментарий от false

Спасибо. Это примерно то что мне нужно было. Но у меня теперь ещё один вопрос по KDGKBLED

char arg;
ioctl (fd, KDSETLED, &arg);
Если я правильно понял, то мне должно возвращаться состояние NumLock и т.д., но arg всегда равен 0, хотя должен 2 так как NumLock у меня активен.

MaysSpirit
() автор топика
Ответ на: комментарий от MaysSpirit

Если я правильно понял, то мне должно возвращаться состояние NumLock и т.д., но arg всегда равен 0, хотя должен 2 так как NumLock у меня активен.

errno/возвращаемое значение проверял?

theNamelessOne ★★★★★
()
Последнее исправление: theNamelessOne (всего исправлений: 1)
Ответ на: комментарий от MaysSpirit

Если я правильно понял, то мне должно возвращаться состояние NumLock и т.д.

KDSETLED только устанавливает, KDGETLED только получает. Операции «установить и получить предыдущее значение» нет.

i-rinat ★★★★★
()
Ответ на: комментарий от theNamelessOne

Я немного ошибся в коде, должен был стоять KDGKBLED вместо KDSETLED. Вот примерно как у меня все выглядит:

#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/kd.h>
#include <stdio.h>
#include <errno.h>

void set_leds(int val) 
{
	int fd = open ("/dev/console", O_WRONLY);
	ioctl (fd, KDSETLED, val);
	close(fd);
}
void flags_state(void) 
{
	int fd = open ("/dev/console", O_RDWR);
	char arg;
	ioctl (fd, KDGKBLED, &arg);
	printf ("%d\n", arg);
	printf ("%d\n%", errno);
	close(fd);
}
int main ()
{
set_leds (7); // загораются все светодиоды
flags_state (); //проверяется, что только Num Lock включен
return 0;
}
В ответ я получаю в качестве arg - 0 (если он char,если он long int\int\char* то какое-то просто огромное число, причем каждый раз разное), в качестве errno у меня приходит - 0. Может быть я не правильно выставляю тип данных?

MaysSpirit
() автор топика
Ответ на: комментарий от MaysSpirit

Читай ман CONSOLE_IOCTL(4): KDSETLED/KDGETLED включает/получает состояние светодиодов, а KDSKBLED/KDGKBLED включает/получает состояние соответствующих клавиатурных флагов. Т.е если тебе нужно лишь мигать светодиодами, а не писать капсом, то ты используешь связку KDSETLED/KDGETLED, в противном случае — связку KDSKBLED/KDGKBLED. Смешивать эти вызовы не стоит.

Вот такой код у меня работает:

#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/kd.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

char get_led() {
  char arg;
  int fd = open("/dev/console", O_RDONLY);

  if (fd == -1) {
    perror("open");
    exit(1);
  }

  if (ioctl(fd, KDGETLED, &arg) == -1) {
    perror("ioctl");
    exit(1);
  }

  if (close(fd) == -1) {
    perror("close");
    exit(1);
  }

  return arg;
}

void set_led(char arg) {
  int fd = open("/dev/console", O_WRONLY);

  if (fd == -1) {
    perror("open");
    exit(1);
  }

  if (ioctl(fd, KDSETLED, arg) == -1) {
    perror("ioctl");
    exit(1);
  }

  if (close(fd) == -1) {
    perror("close");
    exit(1);
  }
}

void print_led(char arg) {
  printf("  CAPS is %s\n", arg & LED_CAP ? "on" : "off");
  printf("  NUM is %s\n", arg & LED_NUM ? "on" : "off");
  printf("  SCROLL is %s\n", arg & LED_SCR ? "on" : "off");
}

int main(void) {
  char led;

  puts("Before setting LEDs");
  led = get_led();
  printf("Current state (%#x):\n", led);
  print_led(led);

  char old_led = led;

  /* Turn on all LEDs */
  set_led(0x7);

  puts("\nAfter setting LEDs");
  led = get_led();
  printf("Current state (%#x):\n", led);
  print_led(led);

  /* Restore LED state */
  set_led(old_led);

  return 0;
}

Результат:

λ nameless@desktop /tmp → sudo ./led
Before setting LEDs
Current state (0x2):
  CAPS is off
  NUM is on
  SCROLL is off

After setting LEDs
Current state (0x7):
  CAPS is on
  NUM is on
  SCROLL is on
λ nameless@desktop /tmp →

theNamelessOne ★★★★★
()
Последнее исправление: theNamelessOne (всего исправлений: 2)
Ответ на: комментарий от theNamelessOne

А вот если тебе надо самими флагами рулить:

#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/kd.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

char get_led_flags() {
  char arg;
  int fd = open("/dev/console", O_RDONLY);

  if (fd == -1) {
    perror("open");
    exit(1);
  }

  if (ioctl(fd, KDGKBLED, &arg) == -1) {
    perror("ioctl");
    exit(1);
  }

  if (close(fd) == -1) {
    perror("close");
    exit(1);
  }

  return arg;
}

void set_led_flags(char arg) {
  int fd = open("/dev/console", O_WRONLY);

  if (fd == -1) {
    perror("open");
    exit(1);
  }

  if (ioctl(fd, KDSKBLED, arg) == -1) {
    perror("ioctl");
    exit(1);
  }

  if (close(fd) == -1) {
    perror("close");
    exit(1);
  }
}

/* Fancy colors! */
#define ON "\033[1;32mon\033[0m"
#define OFF "\033[1;31moff\033[0m"

void print_led(char arg) {
  printf("  CAPS is %s\n", arg & LED_CAP ? ON : OFF);
  printf("  NUM is %s\n", arg & LED_NUM ? ON : OFF);
  printf("  SCROLL is %s\n", arg & LED_SCR ? ON : OFF);
}

void describe_led_flags(char led) {
  printf("Current state (%#x):\n", led & 0x7);
  print_led(led & 0x7);

  led >>= 4;                    /* next nibble */

  printf("\nDefault state (%#x):\n", led & 0x7);
  print_led(led & 0x7);
}

int main(void) {
  char led, old_led;

  puts("Before setting LED flags\n====================\n");
  old_led = led = get_led_flags();
  describe_led_flags(led);

  /* Set the current flags state */
  led |= 0x7;

  /* Turn on all LEDs */
  set_led_flags(led);

  puts("\nAfter setting LED flags\n====================\n");

  led = get_led_flags();
  describe_led_flags(led);

  /* Restore LED state */
  set_led_flags(old_led);

  return 0;
}

Результат:

λ nameless@desktop /tmp → sudo ./led
Before setting LED flags
====================

Current state (0x2):
  CAPS is off
  NUM is on
  SCROLL is off

Default state (0x2):
  CAPS is off
  NUM is on
  SCROLL is off

After setting LED flags
====================

Current state (0x7):
  CAPS is on
  NUM is on
  SCROLL is on

Default state (0x2):
  CAPS is off
  NUM is on
  SCROLL is off
λ nameless@desktop /tmp →
theNamelessOne ★★★★★
()
Ответ на: комментарий от theNamelessOne

Предполагаю, что есть проблема в моей системе (виртуалка VMware - OpenSuse), потому что мой результат:

linux-noeh: /home/user/Документы # gcc leds.c
linux-noeh: /home/user/Документы # ./a.out
Before setting LEDs
Current state (0):
  CAPS is off
  NUM is off
  SCROLL is off

After setting LEDs
Current state (0x7):
  CAPS is on
  NUM is on
  SCROLL is on
впечатление, что KDGETLED получает значения только те, которые были отправлены KDSETLED.

MaysSpirit
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.