USB-GEIGER を Linux で動かす

Pocket

やっとストロベリーリナックスのガイガーカウンターUSB-GEIGERを入手しました
Windows 用のUSB 経由で cpm と経過時間のデータは取得できるソフトはストロベリーリナックスで公開されています
しかし、Linux で動かしたいですよね

まずは、このガイガーを Linux マシンにつないでみます
/proc/bus/usb/devices をまず見てみます

T:  Bus=02 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=1.5 MxCh= 0
D:  Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
P:  Vendor=1774 ProdID=1002 Rev= 1.00
S:  Manufacturer=Strawberry Linux Co.,Ltd.
S:  Product=USB-Geiger Counter
C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=03(HID  ) Sub=00 Prot=00 Driver=usbhid
E:  Ad=81(I) Atr=03(Int.) MxPS=   8 Ivl=10ms

usbhid のドライバを使っているようです
次にdmesg も見てみます

usb 3-2: USB disconnect, address 2
usb 2-1: new low speed USB device using uhci_hcd and address 2
usb 2-1: New USB device found, idVendor=1774, idProduct=1002
usb 2-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
usb 2-1: Product: USB-Geiger Counter
usb 2-1: Manufacturer: Strawberry Linux Co.,Ltd.
generic-usb 0003:1774:1002.0002: hiddev96,hidraw0: USB HID v1.00 Device [Strawberry Linux Co.,Ltd. USB-Geiger Counter] on usb-0000:00:1d.0-1/input0

hidraw0 として認識されるみたいです

に、参考となるソース発見!
Linux 版は動かないけど、mac 版なら動くらしい。

SnoopyPro のデータを見て、GEIGERMAP のソースを参考に Linux 用のソース ichigo-gg.c を書く。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <getopt.h>

static const char short_options[] = "d:h";
static const struct option long_options [] = {
        { "device",     required_argument,      NULL,   'd' },
        { "help",       no_argument,            NULL,   'h' },
        { 0, 0, 0, 0 }
};

static int
usage()
{
        fprintf(stdout, "Usage: ichigo-gg [-d device] [-h]\n"
                        "Options are:\n"
                        " -d, --device=DEVICE Select Device File(default: /dev/hidraw0)\n"
                        " -h, --help          This Help\n"
                );
        return 0;
}

int main(int argc, char *argv[])
{
        int fd;
        int res = -1;
        unsigned char buf[65];
        char *dev_name = NULL;

        for(;;)
        {
                int index;
                int c;

                c = getopt_long( argc, argv,
                                 short_options, long_options,
                                 &index);

                if ( c == -1)
                        break;

                switch (c)
                {
                case 0:
                        break;
                case 'd':
                        dev_name = strdup(optarg);
                        break;
                case 'h':
                        usage();
                        exit(0);
                default:
                        ;
                }
        }

        if (!dev_name)
                dev_name = strdup("/dev/hidraw0");



        fd = open( dev_name, O_RDWR);
        if (fd < 0)
        {
                fprintf(stderr,"Can't find device(%s)\n", dev_name);
                exit(-1);
        }

        memset(buf,0,65);
        res = write(fd,buf,8);
        if ( res != 8)
        {
                fprintf(stderr, "Can't write device(%s)\n", dev_name);
                goto end;
        }

        res = read(fd,buf,sizeof(buf));
        if ( res < 0)
        {
                fprintf(stderr, "Can't read device(%s)\n", dev_name);
                goto end;
        }

        usleep(10000);

        unsigned int count, total;

        count = (buf[3] << 24) + (buf[2] << 16) + (buf[1] << 8) + buf[0];
        total = (buf[6] << 16) + (buf[5] << 8)  + buf[4];

        time_t timer;
        time(&timer);
#ifdef DEBUG
        int i;
        for(i=0;i<7;i++)
                fprintf(stdout,"buf[%d] => 0x%02x\n", i,buf[i]);

#endif
        fprintf(stdout,"%ld,%d,%d\n", timer, count, total);
end:
        free(dev_name);
        close(fd);

        exit(0);
}

無事、それらしきデータは取得できた。

$ gcc -c ichigo-gg.c
$ gcc -o ichigo-gg ichigo-gg.o

速いマシンだと usleep() なくても動きます。
遅いマシンだと usleep() ないと変なデータになります
controlからinterrupt でデータがやってくるのに処理が間に合わないのでしょうか・・・

でコンパイルできます。
実行は下記のようにお願いします

# ichigo-gg -d /dev/hidraw0

/dev/hidraw0 は自分の環境にあったものに書き換えてくださいね

[2011/09/30 追記]
read だけだと値が取得できずに固まってしまうときがありました
Sizka だからかもしれませんが・・・。
なので、select 使うようにしてます

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <getopt.h>
static const char short_options[] = "d:h";
static const struct option long_options [] = {
	{ "device",     required_argument,      NULL,   'd' },
	{ "help",       no_argument,            NULL,   'h' },
	{ 0, 0, 0, 0 }
};

static int
usage()
{
	fprintf(stdout, "Usage: ichigo-gg [-d device] [-h]\n"
		"Options are:\n"
		" -d, --device=DEVICE Select Device File(default: /dev/hidraw0)\n"
		" -h, --help          This Help\n"
	);
	return 0;
}

int main(int argc, char *argv[])
{
	int fd;
	int res = -1;
	unsigned char buf[65];
	char *dev_name = NULL;

	for(;;)
	{
		int index;
		int c;

		c = getopt_long( argc, argv,
			 short_options, long_options,
			 &index);

		if ( c == -1)
			break;

		switch (c)
		{
		case 0:
			break;
		case 'd':
			dev_name = strdup(optarg);
			break;
		case 'h':
			usage();
			exit(0);
		default:
			;
		}
	}


	if (!dev_name)
		dev_name = strdup("/dev/hidraw0");


	fd = open( dev_name, O_RDWR);
	if (fd < 0)
	{
		fprintf(stderr,"Can't find device(%s)\n", dev_name);
		exit(-1);
	}
	memset(buf,0,65);

	res = write(fd,buf,8);
	if ( res != 8) 
	{     
		fprintf(stderr, "Can't write device(%s)\n", dev_name);
		goto end;   
	}     

	struct timeval stv;

	stv.tv_usec = 500000; // 0.5 sec 
	stv.tv_sec  = 0;  

	fd_set fds;
	FD_ZERO(&fds);
	FD_SET (fd, &fds);
	r = select ( fd + 1, &fds, NULL, NULL, &stv);

	switch(r)
	{
	case -1:
	case 0:
		goto end;   
		break;      
	default:
		;           
	}     

	res = read(fd,buf,sizeof(buf));
	if ( res < 0)
	{     
		fprintf(stderr, "Can't read device(%s)\n", dev_name);
		goto end;   
	}     

	unsigned int count, total;
	count = (buf[3] << 24) + (buf[2] << 16) + (buf[1] << 8) + buf[0];
	total = (buf[6] << 16) + (buf[5] << 8)  + buf[4];

	time_t timer;
	time(&timer);
#ifdef DEBUG
	int i;
	for(i=0;i<7;i++)
		fprintf(stdout,"buf[%d] => 0x%02x\n", i,buf[i]);

#endif
	snprintf(ostring,sizeof(ostring)-1,"%ld,%d,%d\n", timer, count, total);
	write(fp,ostring,strlen(ostring));
end:
	free(dev_name);
	close(fd);
	close(fp);

	exit(0);
}

[/2011/09/30 追記]

3件のコメント

  1. ピンバック:USB-RH + ZABBIXで室温・湿度のモニタリングを行う | blog::dameningen

  2. ピンバック:USB-RH + ZABBIXで室温・湿度のモニタリングを行う » blog::dameningen | blog::dameningen

  3. ピンバック:USB-RH + ZABBIXで室温・湿度のモニタリングを行う

コメントを残す