玄箱PROの電源スイッチや温度取得、ファンコントロール機能を使うには、 ソースが公開されていない miconapl コマンドが必要です。このコマンドは EABI というシステムコールやライブラリの新しい呼び出し規約に基づいて いるため、Debian化 (普通のABI) した場合にchrootを使用したり、EABI の glibcを共存させたりと面倒なことが必要です。
そこで玄箱PROのCDにある「KUROBOX/PROマイコン通信仕様 Rev.1.0」を参考に オリジナルの miconapl とほぼ互換で使用できるマイコン制御プログラムを 書いてみました。
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 <mizutani.jun@nifty.ne.jp> */ /* 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; }
電源ボタンの割込みを監視してシャットダウンするスクリプトです。カーネルを玄箱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
/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
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