외부 USB 키보드에 특정 신호를 보내시겠습니까? 아니면 fdopen()을 수정하는 방법은 무엇입니까?

외부 USB 키보드에 특정 신호를 보내시겠습니까? 아니면 fdopen()을 수정하는 방법은 무엇입니까?

배경 정보: 명령줄에서 명령을 실행할 때 명령에 따라 외부 키보드의 Caps Lock 표시등이 켜지도록 하려고 합니다. 이상적으로는 스크립트가 가능하여 알람 및 기타 용도로 사용할 수 있습니다(키보드를 분해했습니다).

작동할 것 같은 다음 명령을 받았습니다.

fd=fdopen("/dev/console"); ioctl(fd, 0x4B32, 0x04);

OS X 또는 기존 Ubuntu 서버에서 이 명령을 실행하려고 하면 이런 일이 발생합니다.

me@server1:~$ fd=fdopen("/dev/console"); ioctl(fd, 0x4B32, 0x04);
-bash: syntax error near unexpected token `('
me@server1:~$ fd=fdopen(/dev/console);
-bash: syntax error near unexpected token `('

그래서 문제는 첫 번째 부분에 있는 것 같습니다. 소프트웨어/유틸리티 세트를 설치해야 합니까? 외부 키보드의 Caps Lock 표시등을 수동으로 제어하는 ​​방법은 무엇입니까?

답변1

문제는 쉘 프롬프트에 C 코드를 입력하려고 시도했지만 명백한 이유로 이것이 작동하지 않는다는 것입니다. 이를 올바른 C 파일에 넣고 컴파일한 후 실행할 수 있는 작동 바이너리를 얻을 수 있습니다.

#include <linux/kd.h>

#include <sys/ioctl.h>

#include <fcntl.h>
#include <unistd.h>

#include <err.h>
#include <stdio.h>
#include <stdlib.h>

static void
usage(char *argv0)
{
    fprintf(stderr, "Usage: %s <on|off>\n", argv0);
    exit(EXIT_FAILURE);
}

int
main(int argc, char *argv[])
{
    int fd;
    int on;
    unsigned char state;

    if (argc != 2)
        usage(argv[0]);

    if (strcmp(argv[1], "on") == 0)
        on = 1;
    else if(strcmp(argv[1], "off") == 0)
        on = 0;
    else
        usage(argv[0]);


    fd = open("/dev/console", O_RDWR);
    if (fd == -1)
        err(EXIT_FAILURE, "open /dev/console");

    if (ioctl(fd, KDGETLED, &state) == -1)
        err(EXIT_FAILURE, "KDGETLED");

    if (on)
        state |= LED_CAP;
    else
        state &= ~LED_CAP;

    if (ioctl(fd, KDSETLED, state) == -1)
        err(EXIT_FAILURE, "KDSETLED");

    close(fd);

    return 0;
}

eg라는 파일에 넣고 caps.c컴파일하세요.

$ gcc -o caps caps.c

그런 다음 실행하면 됩니다.

$ ./caps on

LED를 켜거나

$ ./caps off

끄십시오(전환은 독자의 연습 문제로 남겨 둡니다).

노트:열려면 /dev/console슈퍼유저 권한이 필요합니다.

한 가지 더 참고사항:이는 또한 터미널이나 X 서버가 때때로 CapsLock LED를 변경하는 것을 방지하지 못합니다(예: Caps누를 때). 이는 OS X에서도 작동하지 않고 Linux에서만 작동합니다. 이를 수행하는 표준화된 방법이 없기 때문입니다. 마침내 당신할 수 없다여러 키보드의 LED를 개별적으로 변경합니다.

답변2

이 C 코드는 어쨌든 작동하지 않습니다. fdopen()여러 인수를 사용하고 파일 설명자가 아닌 파일 스트림을 반환합니다.

몇 년 전에 Xlib를 통해 이 작업을 수행한 것을 기억하지만 이전 코드를 찾을 수 없지만(때때로 컬렉션이 지워짐) 누군가가 github 등에 간단한 앱을 가지고 있어야 한다고 생각합니다. 그런데 제가 발견한 첫 번째 페이지는 다음과 같습니다.이것게시한 기억은 없지만 4년 전에 썼습니다("akashiraffee"는 당시 온라인에서 많이 사용했던 이름이었습니다).

실제로는 Xlib를 사용하지 않습니다. ioctl()여러분이 하려는 일처럼 Xlib를 사용하므로 GUI 없이 작동해야 합니다. 정리해서 여기에 5개의 LED 키보드를 사용해 보았습니다.

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

int main (void) {
    int tty = open("/dev/console", 0), led;
    unsigned long int arg;

    if (tty < 3) {
        perror("open: ");
        return -1;
    }

    if (ioctl(tty,KDGKBTYPE, &arg) > 0) perror("ioctl: ");
    if (arg == KB_101) puts("You have a 101 key keyboard.");

    for (led = 1; led < 9; led++) {
        if (ioctl(tty,KDSETLED, led) > 0) perror("ioctl led on: ");
        printf("LED %d on...hit enter", led);
        getchar();
        if (ioctl(tty,KDSETLED, led+0xff) > 0) perror("ioctl led off: ");
        printf("off (hit enter)\n");
        getchar();
    }

    close(tty);

    return 0;
} 

gcc whatever.c -o testleds그런 다음 컴파일합니다 ./testleds(참고슈퍼유저 권한이 필요합니다). 처음 7개는 저에게 효과적이었습니다. 그 중 일부는 개별 LED이고 일부는 조합입니다.

키보드를 분해했어요

물론 테스트하려면 Enter 키를 눌러야 합니다. 그렇지 않은 경우 댓글을 남겨주시면 지연된 자동 테스트를 사용하도록 변경하겠습니다. 만약 작동하게 된다면 숫자로 조명을 전환하는 데 사용할 수 있는 것으로 바꾸고 싶습니다(예: toggleLED 3).

답변3

리눅스

귀하가 게시한 내용은 C 코드의 작은 조각일 뿐입니다. (실행되지도 않습니다.) 쉘 프롬프트에서는 실행되지 않습니다.

쉘 인터페이스는 없지만 ioctlPerl을 사용할 수 있습니다.

#!/usr/bin/perl
require "sys/ioctl.ph";
if (@ARGV) {
    $ioctl = 0x4b32; # KDSETLED
    $ARGV[0] =~ /^[0-8]+$/ or die "$0: $ARGV[0]: invalid argument";
    $arg = int($ARGV[0]);
} else {
    $ioctl = 0x4b31; # KDGETLED
    $arg = "?";
}
sysopen CONSOLE, "/dev/console", "r" or die "$0: /dev/console: $!\n";
ioctl CONSOLE, $ioctl, $arg or die "$0: ioctl: $!\n";
print ord($arg), "\n" unless @ARGV;

또는 파이썬:

#!/usr/bin/env python
import array, fcntl, os, sys
console = open("/dev/console", "r")
if len(sys.argv) > 1:
    fcntl.ioctl(console, 0x4b32, int(sys.argv[1])) # KDSETLED
else:
    arg = array.array('B', [0xff]) # KDGETLED
    fcntl.ioctl(console, 0x4b31, arg, True)
    print arg[0]

두 프로그램 모두 인수 없이 실행되면 현재 LED 설정을 인쇄합니다. 인수가 전달되면 LED가 변경됩니다. LED 설정은 1(Scroll Lock), 2(Num Lock), 4(Caps Lock)의 합으로 표현됩니다. 매개변수 8을 전달하여 LED를 운영 체제의 잠금 설정에 맞게 재설정할 수 있습니다.

자신의 프로그램을 호출하는 것 외에도 다음을 호출할 수도 있습니다.setleds표준 유틸리티콘솔 도구.

텍스트 모드 콘솔(X 아래나 원격이 아닌)에 로그인하거나 루트로 실행해야 합니다.

Linux, 특정 키보드

콘솔 장치 대신 해당 장치에 액세스하여 특정 입력 장치의 LED를 켜고 끌 수도 있습니다. ioctl은 다릅니다. 다음을 사용해야 합니다.EV개발 인터페이스그리고 보내다EV_LED이벤트.

이 인터페이스를 사용하는 가장 쉬운 방법은 다음을 설치하는 것입니다.evdev파이썬 패키지( pip install evdev).

</dev/input/by-id/usb-_USB_Keyboard-event-kbd \
python -c 'import evdev; dev = evdev.InputDevice("/dev/stdin"); print dev.leds()'

"LED 상태 가져오기 및 설정"을 참조하십시오.지도 시간더 많은 예시를 알아보세요.

OSX

Mac OS X에서는 다음을 통해 키보드 LED에 액세스할 수 있습니다.HID 인터페이스. 예제와 설명을 찾을 수 있습니다.존재하다Mac OS X 내부또는심령 종이접기.

관련 정보