外部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

Linux

あなたが投稿したものは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;

またはPython:

#!/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の下またはリモートではない)にログインするか、rootとして実行する必要があります。

Linux、特定のキーボード

コンソールデバイスの代わりにそのデバイスにアクセスして、特定の入力デバイスのLEDをオン/オフすることもできます。 ioctlは違います。以下を使用する必要があります。EV開発インターフェースそして送るEV_LEDイベント

このインターフェースを使用する最も簡単な方法は、以下をインストールすることです。evdevPythonパッケージ(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の内部または心霊折り紙

関連情報