東京ビックサイトで5/14-16で行われているESEC2008(組込システム開発技術展)にちょっとだけ用事があったので行ってきた。名前の通り、様々な組込系のボードや技術に関係しているベンダーがいろいろな製品やサービスを展示する展示会なんだが、いくつかのブースでは展示&会場限定で即売、みたいな事もやっていることがある。
2008年5月15日木曜日
2008年5月13日火曜日
OpenBSDでEmobile D02HWを使う(1)
縁あってOpenBSDの開発者の人たちと一緒にhackする機会があったので、なにかコントリビューションできることはないかなと考えたところ、OpenBSDの3Gモデムのサポートを拡張することにした。
特にD02HWは、本当の名前はE220といって世界各地で使われているメジャーなモデムなので、これがまともに使えるようになるとうれしい人がそれなりにいるだろうから、ちょうど良い。
OpenBSDもNetBSDと同様に、FreeBSD由来のUSBサブシステムを採用しているので、usbデバイスドライバは大きな差異は存在しない。NetBSD用につくったuhmodem(4)をそのまま移植するという手もあったのだけど、OpenBSDにはHSDPAモデム用のドライバとしてumsm(4)がすでに存在していたので、それを拡張する形で実装してみることにした。
umsm(4)(拡張前)
dev/usb/umsm.c(rev.1.21)を眺めてみると、非常にシンプルなドライバになっていた。具体的に言うと、
struct ucom_methods umsm_methods = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
};
となっていた。struct ucom_methods は、上位ドライバとなるucom(4)のopen/closeなどの各処理におけるデバイス依存コードへの関数ポインタを渡すための構造体なので、この状態ではシリアルに関する処理はucomでのデフォルト動作だけで実行されることを意味している。
どうしてこれで他のドライバが動作しているのだろうか?と「???」と思いながらざっくりとコードを追ってみたところ、シリアルデバイスのinterrupt endpointに関する処理がざっくりと抜け落ちていることに気がついた。単なるin/out endpointを処理するだけなら、確かにucom(4)における特別な処理は必要ないが、モデムで通信を行う際には自分から始めるだけではなく割り込み処理が必要である。
近くにいたOpenBSD開発者に聞いてみたら「おれが使っているE220で昔だれかが作ったパッチで試した見たところ、たしかにPPPまでは張れることもあるがうまく動かなかった。つながるけど切れたり通信できなかったりしてね。それから使ってない」と言われた。さもありなん、ということでinterrupt endpointの処理を拡張するところから始めることにする。D02HW(E220)以外でも役にたつだろう。
interrupt endpoint処理の追加
endpointの割り当て処理はumsm_attach()の中で行われる。data用のbulk in/out endpointしか処理していなかった部分を、以下のように変更する。また、struct umsm_softcにもinterrupt endpoint周りの状態を保持するための変数を拡張しておく。
if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
sc->sc_intr_number = ed->bEndpointAddress;
sc->sc_isize = UGETW(ed->wMaxPacketSize);
DPRINTF(("%s: find interrupt endpoint for %s\n",
__func__, sc->sc_dev.dv_xname));
} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
uca.bulkin = ed->bEndpointAddress;
else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
uca.bulkout = ed->bEndpointAddress;
これで、interrupt endpointを持っているinterfaceがあったら、interrupt endpointを正しく扱うための準備ができる。
次に、ucomをopenしたときに検出したinterrupt endpointをucom割り込みとして利用するためのコードを追加しなければならない。まずucomをopenしたときにusb的にinterrupt endpointを登録するコード(usbd_open_pipe_intr()を呼ぶ)と、closeしたときに後始末(usbd_about_pipe() & usbd_close_pipe()を呼ぶ)をするデバイス依存の関数を追加する。それぞれubsa(4)から持ってきて、umsm_open(), umsm_close()ということにしておく。ucomがopen/closeされるタイミングで呼ばれるデバイス依存関数は、前述のstruct ucom_methodsで指定しておけばよい。
さらに割り込み発生時に呼び出されるデバイス依存関数とその補助関数として、同じくubsa(4)からumsm_intr(), umsm_get_status()を持ってくる。同様にstruct ucom_methodsに指定する。
これで、interrupt endpoint周りの処理は完了。普通のHSDPAモデムのDoCoMo A2502をつなげて試してPPPセッションが正しく張れるようになっていることを確認。とりあえずここまでで半分くらい終了。
ここまでのコードの差分は、OpenBSD CVSwebで確認できる。
次回のエントリーでは、D02HWのモード遷移のための関数の統合について書く予定。
2008年5月12日月曜日
2008年4月28日月曜日
PSoC書き込み器またまたあらわる


2008年4月12日土曜日
100ccで100g (転載というか移動)
2008年4月11日金曜日
Power Gainer (またまたGainer 互換機)


Gainerとrubyとtwitter (あるいはタンジブルなtwitter)


#!/usr/bin/ruby
#
# Twitter Button
#
require 'rubygems'
gem 'twitter'
require 'twitter'
gem 'gainer'
require 'gainer'
## setting for User account
id = "UserName"
pass = "password"
tc0 = Time.now - 80
tc1 = tc0
tc2 = tc0
tc3 = tc0
tcb = tc0
twit = Twitter::Base.new(id,pass)
gainer = Gainer::Serial.new(ARGV.shift)
puts "Ready.\n waiting buttun..."
gainer.on_pressed = proc do
puts 'Button pressed'
if (Time.now - tcb > 60 ) then
tcb = Time.now
fri = twit.followers()
fnum = fri.size
friend = fri[rand(fnum)].screen_name
puts "#{friend} SUGOI..."
twit.update("@#{friend} スゲー!w by XXX ")
end
end
loop do
sleep(0.1)
gainer.peek_digital_input
case gainer.digital_input[0]
when 1
puts "GET 1"
if (Time.now - tc0 > 60 ) then
tc0 = Time.now
puts "Give me COFFEE..."
twit.update("珈琲プリーズ だれかプリーズ")
end
when 2
puts "GET 2"
if (Time.now - tc1 > 60 ) then
tc1 = Time.now
# fri = twit.friends()
fri = twit.followers()
fnum = fri.size
friend = fri[rand(fnum)].screen_name
puts "#{friend} SUGOI..."
twit.update("@#{friend} スゲーョ!")
end
when 4
puts "GET 3"
if (Time.now - tc2 > 60 ) then
tc2 = Time.now
puts "I'm Sleepy..."
twit.update("ねむい中")
end
when 8
puts "GET 4"
if (Time.now - tc3 > 60 ) then
tc3 = Time.now
puts "Give me FOOODDDD..."
twit.update("はらへり、ヘリハラ")
end
else
## puts "NODATA"
end
end
ということで、ジャンパピンがでっぱってケースに入らないことがあるので、