[HOME] [玄箱PROでNTFSを使う] [玄箱PRO Debian化手順] [玄箱PROのUSB-シリアル接続] [玄箱インストールmemo]

miconapl互換コマンドの作成

Jun Mizutani 2007/08/18, 2008/08/30

玄箱PROの電源スイッチや温度取得、ファンコントロール機能を使うには、 ソースが公開されていない miconapl コマンドが必要です。このコマンドは EABI というシステムコールやライブラリの新しい呼び出し規約に基づいて いるため、Debian化 (普通のABI) した場合にchrootを使用したり、EABI の glibcを共存させたりと面倒なことが必要です。


そこで玄箱PROのCDにある「KUROBOX/PROマイコン通信仕様 Rev.1.0」を参考に オリジナルの miconapl とほぼ互換で使用できるマイコン制御プログラムを 書いてみました。

2008/08/30
micon の同時起動で問題が発生しないように排他ロックを組み込みました。

ファイル

micon20080830.tar.gz(20KB) は、以下のファイルで構成されています。

ファイル 説明
README.jp.txt このファイル
Makefile メイクファイル
micon.c micon コマンドのソース
micon 玄箱PRO の debian etch上でコンパイルしたバイナリ
COPYING GNU General Public License
rc.local /etc/rc.local スクリプト
Fand ファンコントロール用スクリプト
Keventd 電源ボタン監視用スクリプト

デバイスファイル

micon はデバイスファイルとして /dev/ttyS1 が必要です。 まず、/dev/ttyS1 が存在するか確認します。

  $ ls -lt /dev/ttyS1
  crw-rw-rw- 1 root root 4, 65 Jul 10 00:29 /dev/ttyS1

もし無い場合は /dev ディレクトリで次のように作成してください。

  # mknod ttyS1 c 4 65

/dev/ttyS1 のパーミッションを一般ユーザに与えるとリモートから電源OFFが 可能になるなどの危険性があります。玄箱PROを使用する環境によっては注意が 必要です。

コンパイルとインストール

まず適当なディレクトリで解凍(展開)します。

 kuro@KUROBOX-PRO:~$ tar zxf micon20080830.tar.gz

micon20070710 ディレクトリへ移動します。

 kuro@KUROBOX-PRO:~$ cd micon20080830

コンパイルは make を実行します。

 kuro@KUROBOX-PRO:~$ make

コマンドサイズを小さくする場合は(オプション):

 kuro@KUROBOX-PRO:~$ make strip

インストールはスーパユーザ(root)権限が普通必要です。 デフォルトでは /usr/local/bin にインストールされます。

 kuro@KUROBOX-PRO:~$ su -c 'make install' 

miconapl として使用する場合はシンボリックリンクを作成します。

 KUROBOX-PRO:/usr/local/bin# ln -s micon miconapl

/usr/local/bin 以外のディレクトリにインストールする場合は、 Makefile の INSTALL_DIR=/usr/local/bin を変更して下さい。 tar zxf micon20080830.tar.gz を展開した中の micon をPATHの 通ったディレクトリにコピーするだけでも使用できます。

rc.local を /etc にコピーし、Fand と Keventd を/usr/local/bin にコピーすることで、電源ボタンとファンコントロールが可能となります。 Fand と Keventd は /usr/local/bin/miconapl が /usr/local/bin/micon への シンボリックリンクになっている(またはmicon をmiconaplとしてコピー) していることを前提としています。

使用法

micon はデバイスファイルとして /dev/ttyS1 が必要です。 まず、/dev/ttyS1 が存在するか確認します。

 $ ls -lt /dev/ttyS1
 crw-rw-rw- 1 root root 4, 65 Jul 10 00:29 /dev/ttyS1

もし無い場合は /dev ディレクトリで次のように作成してください。

 # mknod ttyS1 c 4 65

/dev/ttyS1 のパーミッションを一般ユーザに与えるとリモートから電源OFFが 可能になるなどの危険性があります。玄箱PROを使用する環境によっては注意が 必要です。


micon を引数なしで実行すると使用可能なオプションを表示します。 オリジナルの miconapl とほぼ同じ動作をします。 初期化用の -b オプションは micon では不要なのでサポートしていません。 デバッグ用の -d もサポートしておりません。

  kuro@KUROBOX-PRO:~$ micon
  miconapl -a option
   option: boot_start
           boot_end
           power_off
           shutdown_wait
           shutdown_cancel
           reboot
           temp_get
           fan_set_speed [arg]
           fan_get_speed
           bz_on [arg]
           bz_set_freq [arg]
           bz_melody tempo note ..
           bz_imhere  tempo note ..
           int_get_switch_status [arg]
           led_set_bright [arg]
           led_set_cpu_mcon [arg]
           led_set_on_off [arg]
           led_set_blink [arg]
           led_set_code_error [arg]
           led_set_code_information [arg]
           mcon_get_status
           hdd_set_power [arg]
           mcon_get_version

使用例

micon コマンドの使用例です。オリジナルの miconapl とほぼ同じ結果を返します。

  $ micon -a temp_get
  temp=37
  $ micon -a fan_set_speed slow
  $ micon -a fan_get_speed
  fan_rpm=1770
  $ micon -a fan_set_speed stop
  $ micon -a fan_get_speed
  fan_rpm=0
  $ micon -a fan_set_speed
  fan_speed=slow
  $ micon -a fan_set_speed full
  $ micon -a fan_get_speed
  fan_rpm=3330
  $ micon -a bz_melody 240 C4 D4 E4
  $ micon -a bz_imhere 120 C4 D4 E4
  $ micon -a bz_on boot
  $ micon -a bz_on button
  $ micon -a bz_on finepix
  $ micon -a led_set_code_error 5
  $ micon -a led_set_code_error 0
  $ micon -a mcon_get_status
  mcon_status=on

ソース

miconapl互換コマンドのソースコードです。termios で通信条件を設定し、コマンドライン引数で指定された動作を /dev/ttyS1 経由でマイコンに伝えます。

/*-------------------------------------------------------------------------*/
/*  KURO-BOX/PRO Micon controll: micon.c                                   */
/*  2008/08/30                                                             */
/*  Copyright (C) 2007,2008  Jun Mizutani <[email protected]>       */
/*                      All rights reserved.                               */
/*                                                                         */
/* This file is covered under the terms of the GNU General Public License, */
/* version 2. This file has NO WARRANTY.                                   */
/*-------------------------------------------------------------------------*/

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <termios.h>


#define ncmd 23

typedef struct {
    char name[32];
    void (*func)(int);
} CMD;

void boot_start(int);
void boot_end(int);
void power_off(int);
void shutdown_wait(int);
void shutdown_cancel(int);
void reboot(int);
void temp_get(int);
void fan_set_speed(int);
void fan_get_speed(int);
void bz_on(int);
void bz_set_freq(int);
void bz_melody(int);
void bz_imhere(int);
void int_get_switch_status(int);
void led_set_bright(int);
void led_set_cpu_mcon(int);
void led_set_on_off(int);
void led_set_blink(int);
void led_set_code_error(int);
void led_set_code_information(int);
void mcon_get_status(int);
void hdd_set_power(int);
void mcon_get_version(int);

CMD command[ncmd] = {
    {"boot_start", boot_start},
    {"boot_end", boot_end},
    {"power_off", power_off},
    {"shutdown_wait", shutdown_wait},
    {"shutdown_cancel", shutdown_cancel},
    {"reboot", reboot},
    {"temp_get", temp_get},
    {"fan_set_speed", fan_set_speed},
    {"fan_get_speed", fan_get_speed},
    {"bz_on",bz_on},
    {"int_get_switch_status", int_get_switch_status},
    {"led_set_bright", led_set_bright},
    {"led_set_cpu_mcon", led_set_cpu_mcon},
    {"led_set_on_off", led_set_on_off},
    {"led_set_blink", led_set_blink},
    {"led_set_code_error", led_set_code_error},
    {"led_set_code_information", led_set_code_information},
    {"mcon_get_status", mcon_get_status},
    {"hdd_set_power", hdd_set_power},
    {"mcon_get_version", mcon_get_version},
    {"bz_set_freq", bz_set_freq},
    {"bz_melody", bz_melody},
    {"bz_imhere", bz_imhere}
};

typedef struct {
    char name[32];
    int val;
} OPTION;

#define POWER_SW        10
#define INIT_SW_FRONT   11
#define STOP            20
#define SLOW            21
#define FAST            22
#define FULL            23
#define BOOT            30
#define BUTTON          31
#define ON              32
#define ON3OFF3         33
#define ON5OFF3         34
#define FINEPIX         35
#define POWER           40
#define INFO            41
#define DIAG            42
#define LINK            43

#define nopt            16

OPTION option[nopt] = {
    {"power_sw", POWER_SW},
    {"init_sw_front", INIT_SW_FRONT},
    {"stop", STOP},
    {"slow", SLOW},
    {"fast", FAST},
    {"full", FULL},
    {"boot", BOOT},
    {"button", BUTTON},
    {"on", ON},
    {"on3off3", ON3OFF3},
    {"on5off3", ON5OFF3},
    {"finepix", FINEPIX},
    {"power", POWER},
    {"info" , INFO},
    {"diag" , DIAG},
    {"link" , LINK}
};

// A-G --> 0-10
int note2num[12] = { 0, 2, 3, 5, 7, 8, 10 };

// for i in range(0,72):
//   hex(int(round(4000000.0/(pow(2.0, i/12.0)*55))))
int period[72] = {
    0xffff, 0xffff, 0xfd19, 0xeee4, 0xe17c, 0xd4d4, // A1
    0xc8e2, 0xbd9c, 0xb2f7, 0xa8ec, 0x9f71, 0x967e, // DM1
    0x8e0c, 0x8613, 0x7e8c, 0x7772, 0x70be, 0x6a6a, // A2
    0x6471, 0x5ece, 0x597c, 0x5476, 0x4fb8, 0x4b3f, // DM2
    0x4706, 0x4309, 0x3f46, 0x3bb9, 0x385f, 0x3535, // A3
    0x3238, 0x2f67, 0x2cbe, 0x2a3b, 0x27dc, 0x259f, // DM3
    0x2383, 0x2185, 0x1fa3, 0x1ddd, 0x1c2f, 0x1a9a, // A4
    0x191c, 0x17b3, 0x165f, 0x151d, 0x13ee, 0x12d0, // DM4
    0x11c1, 0x10c2, 0x0fd2, 0x0eee, 0x0e18, 0x0d4d, // A5
    0x0c8e, 0x0bda, 0x0b2f, 0x0a8f, 0x09f7, 0x0968, // DM5
    0x08e1, 0x0861, 0x07e9, 0x0777, 0x070c, 0x06a7, // A6
    0x0647, 0x05ed, 0x0598, 0x0547, 0x04fc, 0x04b4  // DM6
};

unsigned char rbuf[32];
unsigned char wbuf[32];
struct termios save_term;
struct termios term;
int fd;

void usage() {
    printf("miconapl -a option\n");
    printf(" option: boot_start\n");
    printf("         boot_end\n");
    printf("         power_off\n");
    printf("         shutdown_wait\n");
    printf("         shutdown_cancel\n");
    printf("         reboot\n");
    printf("         temp_get\n");
    printf("         fan_set_speed [arg]\n");
    printf("         fan_get_speed\n");
    printf("         bz_on [arg]\n");
    printf("         bz_set_freq [arg]\n");
    printf("         bz_melody tempo note ..\n");
    printf("         bz_imhere  tempo note ..\n");
    printf("         int_get_switch_status [arg]\n");
    printf("         led_set_bright [arg]\n");
    printf("         led_set_cpu_mcon [arg]\n");
    printf("         led_set_on_off [arg]\n");
    printf("         led_set_blink [arg]\n");
    printf("         led_set_code_error [arg]\n");
    printf("         led_set_code_information [arg]\n");
    printf("         mcon_get_status\n");
    printf("         hdd_set_power [arg]\n");
    printf("         mcon_get_version\n");
}

int getlock(int fd, int type, int sec)
{
    struct flock lockinfo;
    int i;

    lockinfo.l_type   = type;
    lockinfo.l_whence = SEEK_SET;
    lockinfo.l_start  = 0;
    lockinfo.l_len    = 0;

    for (i=0; i<sec; i++) {
        if (!fcntl(fd, F_SETLK, &lockinfo)) return 1;
        sleep(1);
    }
    return 0;
}

void unlock(int fd)
{
    struct flock lockinfo;

    lockinfo.l_type   = F_UNLCK;
    lockinfo.l_whence = SEEK_SET;
    lockinfo.l_start  = 0;
    lockinfo.l_len    = 0;

    fcntl(fd, F_SETLK, &lockinfo);
}

void init_sirial(void)
{
    tcgetattr(fd, &save_term);
    memset(&term, 0, sizeof(term));

    term.c_iflag |=IGNBRK;
    term.c_lflag &= ~(ISIG | ICANON | ECHO);
    term.c_cflag = (CS8 | CSTOPB | CLOCAL | CREAD | PARENB);
    term.c_cc[VMIN] = 1;
    term.c_cc[VTIME] = 0;
    cfsetospeed(&term, B38400);
    cfsetispeed(&term, B38400);

    if (tcsetattr(fd, TCSANOW, &term) < 0) {
        printf("set termios failed.\n");
        exit(1);
    }
}

int send_serial(int n, unsigned char* buf)
{
    unsigned char sum = 0;
    int len;
    int i;

    for (i=0; i<n; i++) {
        sum += buf[i];
        if ((len = write(fd, &buf[i], 1)) <= 0 ) {
            printf("write error! %X\n", buf[i]);
            exit(1);
        }
    }
    buf[n] = -sum;
    if ((len = write(fd, &buf[n], 1)) <= 0 ) {
            printf("write error! %X\n", len);
            exit(1);
    }
    return len;
}

int recv_serial(unsigned char* buf)
{
    fd_set fds;
    struct timeval tv;
    int len;

    FD_ZERO(&fds);
    FD_SET(fd, &fds);
    tv.tv_sec = 2;
    tv.tv_usec = 0;
    if (select(fd+1, &fds, NULL, NULL, &tv) < 0)
        exit(1);
    len = read(fd, buf, 32);
    if (len < 0) {
        printf("Read Error! %X\n", len);
        exit(1);
    }  
    return len;
}

void close_serial(void)
{
    tcsetattr(fd, TCSANOW, &save_term);
    close(fd);
}

void boot_start(int arg)
{
    int len;
    wbuf[0] = 0x00;
    wbuf[1] = 0x02;
    send_serial(2, wbuf);
    len = recv_serial(rbuf);
}

void boot_end(int arg)
{
    int len;
    wbuf[0] = 0x00;
    wbuf[1] = 0x03;
    send_serial(2, wbuf);
    len = recv_serial(rbuf);
}

void power_off(int arg)
{
    int len;
    wbuf[0] = 0x00;
    wbuf[1] = 0x06;
    send_serial(2, wbuf);
    len = recv_serial(rbuf);
}

void shutdown_wait(int arg)
{
    int len;
    wbuf[0] = 0x00;
    wbuf[1] = 0x0C;
    send_serial(2, wbuf);
    len = recv_serial(rbuf);
}

void shutdown_cancel(int arg)
{
    int len;
    wbuf[0] = 0x00;
    wbuf[1] = 0x0D;
    send_serial(2, wbuf);
    len = recv_serial(rbuf);
}

void reboot(int arg)
{
    int len;
    wbuf[0] = 0x00;
    wbuf[1] = 0x0E;
    send_serial(2, wbuf);
    len = recv_serial(rbuf);
}

void temp_get(int arg)
{
    int len;
    wbuf[0] = 0x80;
    wbuf[1] = 0x37;     // get temp
    send_serial(2, wbuf);
    len = recv_serial(rbuf);
    printf("temp=%d\n", rbuf[2]);
}

void fan_set_speed(int arg)
{
    int len;
    if (arg == -1) {
        wbuf[0] = 0x80;
        wbuf[1] = 0x33;
        send_serial(2, wbuf);
        len = recv_serial(rbuf);
        printf("fan_speed=");
        switch(rbuf[2]) {
            case 0 : printf("stop\n"); break;
            case 1 : printf("slow\n"); break;
            case 2 : printf("fast\n"); break;
            case 3 : printf("full\n"); break;
            default : printf("unknown\n");
        }
    } else {
        wbuf[0] = 0x01;
        wbuf[1] = 0x33;
        switch (arg) {
            case STOP : wbuf[2] = 0; break;
            case SLOW : wbuf[2] = 1; break;
            case FAST : wbuf[2] = 2; break;
            case FULL : wbuf[2] = 3; break;
            default : wbuf[2] = 3;
        }
        send_serial(3, wbuf);
        len = recv_serial(rbuf);
    }
}

void fan_get_speed(int arg)
{
    int len;
    wbuf[0] = 0x80;
    wbuf[1] = 0x38;
    send_serial(2, wbuf);
    len = recv_serial(rbuf);
    printf("fan_rpm=%d\n", rbuf[2]*30);
}

void bz_on(int arg)
{
    int len;
    wbuf[0] = 0x01;
    wbuf[1] = 0x30;
    switch (arg) {
       case STOP    : wbuf[2] = 0x00; break;
       case BOOT    : wbuf[2] = 0x01; break;
       case BUTTON  : wbuf[2] = 0x02; break;
       case ON      : wbuf[2] = 0x03; break;
       case ON3OFF3 : wbuf[2] = 0x04; break;
       case ON5OFF3 : wbuf[2] = 0x10; break;
       case FINEPIX : wbuf[2] = 0x20; break;
       default : wbuf[2] = 0x00;
    }
    send_serial(3, wbuf);
    len = recv_serial(rbuf);
}

void bz_set_freq(int arg)
{
    int len;
    if (arg == -1) {
        wbuf[0] = 0x80;
        wbuf[1] = 0x53;
        send_serial(2, wbuf);
        len = recv_serial(rbuf);
        printf ("%2X%2X\n", rbuf[2], rbuf[3]);
    } else {
        wbuf[0] = 0x02;
        wbuf[1] = 0x53;
        wbuf[2] = arg >> 8;
        wbuf[3] = arg & 0xFF;
        send_serial(4, wbuf);
        len = recv_serial(rbuf);
    }
}

// ./micon -a bz_melody 240 C4 D4 E4 E4 C4 D4 E4 E4 G4 E4 D4 C4 D4 E4 D4 D4
void bz_melody(int arg)
{
    // dummy
}
void bz_imhere(int arg)
{

}

void int_get_switch_status(int arg)
{
    int len;
    // get switch  (enable interupt)
    wbuf[0] = 0x80;
    wbuf[1] = 0x36;
    send_serial(2, wbuf);
    len = recv_serial(rbuf);
    if ((rbuf[2] & 0x01)== 0) {
        printf("int=power_sw\n");
    }
    if ((rbuf[2] & 0x08)== 0) {
        printf("int=init_sw_front\n");
    }
}

void led_set_bright(int arg)
{
    int len;
    if (arg == -1) {
        wbuf[0] = 0x80;
        wbuf[1] = 0x3A;
        send_serial(2, wbuf);
        len = recv_serial(rbuf);
        printf ("led_bright=%d\n", rbuf[2]);
    } else {
        wbuf[0] = 0x01;
        wbuf[1] = 0x3A;
        wbuf[2] = arg & 0x0F;
        send_serial(3, wbuf);
        len = recv_serial(rbuf);
    }
}

void led_set_cpu_mcon(int arg)
{
    int len;
    if (arg == -1) {
        wbuf[0] = 0x80;
        wbuf[1] = 0x50;
        send_serial(2, wbuf);
        len = recv_serial(rbuf);
        printf ("%d\n", rbuf[2]);
    } else {
        wbuf[0] = 0x02;
        wbuf[1] = 0x50;
        wbuf[2] = arg & 0x0F;
        wbuf[3] = 0;
        send_serial(4, wbuf);
        len = recv_serial(rbuf);
    }
}

void led_set_on_off(int arg)
{
    int len;
    if (arg == -1) {
        wbuf[0] = 0x80;
        wbuf[1] = 0x51;
        send_serial(2, wbuf);
        len = recv_serial(rbuf);
        printf ("%d\n", rbuf[2]);
    } else {
        wbuf[0] = 0x02;
        wbuf[1] = 0x51;
        wbuf[2] = arg & 0x0F;
        wbuf[3] = 0;
        send_serial(4, wbuf);
        len = recv_serial(rbuf);
    }
}

void led_set_blink(int arg)
{
    int len;
    if (arg == -1) {
        wbuf[0] = 0x80;
        wbuf[1] = 0x52;
        send_serial(2, wbuf);
        len = recv_serial(rbuf);
        printf ("%d %d\n", rbuf[2], rbuf[3]);
    } else {
        wbuf[0] = 0x02;
        wbuf[1] = 0x52;
        wbuf[2] = arg & 0x0F;
        wbuf[3] = 0;
        send_serial(4, wbuf);
        len = recv_serial(rbuf);
    }
}

void led_set_code_error(int arg)
{
    int len;
    if (arg == -1) {
        wbuf[0] = 0x80;
        wbuf[1] = 0x54;
        send_serial(2, wbuf);
        len = recv_serial(rbuf);
        printf ("%d %d\n", rbuf[2], rbuf[3]);
    } else {
        wbuf[0] = 0x80;
        wbuf[1] = 0x54;
        send_serial(2, wbuf);
        len = recv_serial(rbuf);
        wbuf[0] = 0x02;
        wbuf[1] = 0x54;
        wbuf[2] = rbuf[2];
        wbuf[3] = arg;
        send_serial(4, wbuf);
        len = recv_serial(rbuf);
    }
}

void led_set_code_information(int arg)
{
    int len;
    if (arg == -1) {
        wbuf[0] = 0x80;
        wbuf[1] = 0x54;
        send_serial(2, wbuf);
        len = recv_serial(rbuf);
        printf ("%d\n", rbuf[3]);
    } else {
        wbuf[0] = 0x80;
        wbuf[1] = 0x54;
        send_serial(2, wbuf);
        len = recv_serial(rbuf);
        wbuf[0] = 0x02;
        wbuf[1] = 0x54;
        wbuf[2] = arg;
        wbuf[3] = rbuf[3];
        send_serial(4, wbuf);
        len = recv_serial(rbuf);
    }
}

void mcon_get_status(int arg)
{
    int len;
    wbuf[0] = 0x80;
    wbuf[1] = 0x3C;
    send_serial(2, wbuf);
    len = recv_serial(rbuf);
    if (rbuf[2]&0x20) {
        printf("mcon_status=on\n");
    } else {
        printf("mcon_status=off\n");
    }
}

void hdd_set_power(int arg)
{
    int len;
    if (arg == -1) {
        wbuf[0] = 0x80;
        wbuf[1] = 0x3B;
        send_serial(2, wbuf);
        len = recv_serial(rbuf);
        if (rbuf[2]&0x01) {
            printf("hdd12_power=on\n");
        } else {
            printf("hdd12_power=off\n");
        }
        if (rbuf[2]&0x02) {
            printf("hdd34_power=on\n");
        } else {
            printf("hdd34_power=off\n");
        }
    } else {
        wbuf[0] = 0x01;
        wbuf[1] = 0x3B;
        wbuf[2] = arg & 0x0F;
        send_serial(4, wbuf);
        len = recv_serial(rbuf);
    }
}

void mcon_get_version(int arg)
{
    printf("mcon_version=%s\n", "micon by jm 20080830");
}

int parse_freq(char* arg)
{
    int n, note;
    int octave;
    int half;

    n = toupper(arg[0]) - 'A';
    if ((n >= 0) && (n <= 6)) {
        note = note2num[n];
    } else {
        note = 3; // C
    }
    if ('M' == toupper(arg[1])) {
        octave = (int)(arg[2]) - '1';
        half = +1;
    } else {
        octave = (int)(arg[1]) - '1';
        half = 0;
    }
    note = note + half + octave*12;
    if ((note >= 72) || (note < 0)) note = 24;
    return period[note];
}

int main(int argc, char* argv[])
{
    int i, j, k;
    int num;
    int f;
    long int tempo;

    f = 0;
    if (argc == 1) {
        usage();
        return 0;
    }
    if (strcmp(argv[1], "-a") == 0) {
        i = 0;
        while (i < ncmd) {
            if (strcmp(argv[2], command[i].name) == 0) { // found
                if ((fd = open("/dev/ttyS1" , O_RDWR)) < 0) {
                    printf("open failed.\n");
                    exit(1);
                }
                if (!getlock(fd, F_WRLCK, 3)) { // lock
                    printf("lock failed.\n");
                    close(fd);
                    exit(1);
                }
                init_sirial();
                if (argc < 4) {
                    f = 1;
                    command[i].func(-1);
                } else {
                    if (strcmp(command[i].name, "bz_set_freq") == 0) {
                        f = 1;
                        // printf("%X\n", parse_freq(argv[3]));
                        bz_set_freq(parse_freq(argv[3]));
                    } else if (strcmp(command[i].name, "bz_melody") == 0) {
                        f = 1;
                        tempo = 60000000/atoi(argv[3]);
                        num = argc - 4;
                        bz_on(ON);
                        for(k=0;k<num;k++) {
                            bz_set_freq(parse_freq(argv[k+4]));
                            usleep(tempo);
                        }
                        bz_on(STOP);
                    } else if (strcmp(command[i].name, "bz_imhere") == 0) {
                        f = 1;
                        led_set_blink(15);
                        tempo = 60000000/atoi(argv[3]);
                        num = argc - 4;
                        bz_on(ON);
                        for(k=0;k<num;k++) {
                            bz_set_freq(parse_freq(argv[k+4]));
                            usleep(tempo);
                        }
                        bz_on(STOP);
                        led_set_blink(0);
                    } else {
                        k = argv[3][0] - '0';
                        if ((k >= 0) && (k <= 9)) {
                            f = 1;
                            command[i].func(atoi(argv[3]));
                        } else {
                            j = 0;
                            while (j < nopt) {
                                if (strcmp(argv[3], option[j].name) == 0) {
                                    f = 1;
                                    command[i].func(option[j].val);
                                }
                                j++;
                            }
                        }
                    }
                } // if (argc < 4)
                close_serial();
                unlock(fd);
            }
            i++;
        } // while
        if (f == 0) usage();
    } else usage();
    return 0;
}

Keventd

電源ボタンの割込みを監視してシャットダウンするスクリプトです。カーネルを玄箱PROのオリジナルと入れ替えた場合には /proc/buffalo/kernevnt が使用できないため2秒ごとにスイッチの状態を確認しています。

#!/bin/sh

# /usr/local/kpro/bin/Keventd 20080721

GET_SW="/usr/local/bin/miconapl -a int_get_switch_status"
BEEP="/usr/local/bin/miconapl -a bz_melody 960 E4 C4"
BEEP2="/usr/local/bin/miconapl -a bz_melody 120 C5"
COUNT=4

while :
do
    SW=`$GET_SW |grep "int=" |sed -e "s/int=//"`
    case ${SW} in
    power_sw)
        COUNT=`expr ${COUNT} - 1`
        if [ ${COUNT} -eq 0 ]
        then
            ${BEEP2}
            /sbin/shutdown -hP now
        else
            ${BEEP}
        fi
        sleep 1
        ;;
    init_sw_front)
        ;;
    *)
        COUNT=4
        sleep 2
        ;;
    esac
done

Fand

/etc/fan.prof の値にしたがってファンスピードをコントロールします。この例では20度以下でファンを停止します。

stop    -     20
slow    20    25
fast    25    35
full    35

温度を監視して /etc/fan.prof の値にしたがってファンスピードをコントロールするスクリプトです。オリジナルの miconapl でも 互換コマンドの micon でも同じ動作をします。

#!/bin/sh

# /usr/local/kpro/bin/Fand 20080818 jm

CONF_FILE=/etc/fan.prof
MICONAPL=/usr/local/bin/miconapl
GET_TEMP="${MICONAPL} -a temp_get"
SET_FAN_SPEED="${MICONAPL} -a fan_set_speed"

${MICONAPL} -a fan_set_speed full

while :
do
    sleep 60
    TEMP=`${GET_TEMP}|grep temp=| sed -e "s/.*=//"`
    CUR_SPEED=`${SET_FAN_SPEED}|grep fan_speed=|sed -e "s/.*=//"`
    if [ -f ${CONF_FILE} ] ; then
        L_LIMIT=`grep ${CUR_SPEED} ${CONF_FILE}| awk '{print $2}'`
        H_LIMIT=`grep ${CUR_SPEED} ${CONF_FILE}| awk '{print $3}'`
        if [ ${TEMP} -lt ${L_LIMIT} ] ; then
            DIRECT=DOWN
        elif [ ${TEMP} -gt ${H_LIMIT} ] ; then
            DIRECT=UP
        else
            DIRECT=NO
        fi

        NEW_SPEED=${CUR_SPEED}
        case ${DIRECT} in
        DOWN)
            case ${CUR_SPEED} in
                slow) NEW_SPEED=stop ;;
                fast) NEW_SPEED=slow ;;
                full) NEW_SPEED=fast ;;
            esac
            ;;
        UP)
            case ${CUR_SPEED} in
                stop) NEW_SPEED=slow ;;
                slow) NEW_SPEED=fast ;;
                fast) NEW_SPEED=full ;;
            esac
            ;;
        esac
        ${SET_FAN_SPEED} ${NEW_SPEED}
    fi
done

/etc/rc.local

Debianの場合、/etc/rc.local に以下のように記述すると Fand と Keventdをブート直後に起動して、電源ボタンのチェックと温度によってファンスピードをコントロールすることができます。

#!/bin/sh -e
#
# rc.local

/usr/local/bin/miconapl -a boot_end

if [ -x /usr/local/bin/Keventd ] ; then
    /usr/local/bin/Keventd &
fi

if [ -x /usr/local/bin/Fand ] ; then
        /usr/local/bin/Fand &
fi

/usr/local/bin/miconapl -a bz_on boot

exit 0

動作例

起動後に徐々に温度が上昇して36度でファンスピードが「full」になることが確認できます。

kuro@KUROBOX-PRO:~$ micon -a temp_get
temp=28
kuro@KUROBOX-PRO:~$ micon -a fan_set_speed
fan_speed=fast
kuro@KUROBOX-PRO:~$ micon -a fan_get_speed
fan_rpm=2460
kuro@KUROBOX-PRO:~$ micon -a temp_get
temp=33
kuro@KUROBOX-PRO:~$ micon -a temp_get
temp=34
kuro@KUROBOX-PRO:~$ micon -a temp_get
temp=35
kuro@KUROBOX-PRO:~$ micon -a fan_set_speed
fan_speed=fast
kuro@KUROBOX-PRO:~$ micon -a temp_get
temp=36
kuro@KUROBOX-PRO:~$ micon -a fan_set_speed
fan_speed=full
kuro@KUROBOX-PRO:~$ micon -a fan_get_speed
fan_rpm=3300



ご意見・ご感想は,こちらの掲示板まで.