■塩田紳二のPDAレポート■SL-C3000のUSBホスト機能を使う |
シャープ SL-C3000 |
SL-C3000で利用できるUSBホストケーブルを入手したので、いろいろとためしてみた。その結果、USBメモリの利用も可能であることがわかった。ただし、多少の設定が必要である。ここでは、その手順などを紹介したい。
SL-C3000に採用されているLinuxでは、USBのドライバはローダブルモジュールという形式でサポートされている。これは、必要に応じてドライバをあとから読み込む仕組みである。SL-C3000は、ミニAケーブルを装着した段階で、USBホスト機能が動作し、コア部分のモジュールが組み込まれる。さらにUSBデバイスを装着することで、必要なドライバが読み込まれる。
SL-C3000では、標準状態では、USBキーボードだけが利用できる状態になっている。USBメモリに関しては、必要なローダブルモジュールは用意されているが、ファイルシステムとして利用するためのプログラムがなく、手動でマウントすることで利用が可能になる。短いプログラム(スクリプト)を組み込むことで、自動的にファイルシステムとして利用することは可能である。ここでは、その方法を紹介する。
入手したUSBホストケーブル。一方がミニA(オス)、もう一方がシリーズA(メス)になっているもの | ミニAコネクタ部分。下側が狭まるような形になっている |
■■ 注意 ■■
Linuxのコマンドを使うため、ある程度はLinuxの知識が必要。たとえば、ファイルのコピーやリネームなど、ファイルを書き換えるときにバックアップするような作業ができないなら危険なのでやらないほうがよい。最悪の場合、Zaurusが起動し無くなる可能性もある。本文中では、記述が繁雑になることを避けるため、このような基本的なLinuxコマンドについては解説していないし、手順も省略してある(たとえばrootになる方法など)。 |
USBメモリ(USBマスストレージデバイス)は、Linuxでは、SCSIエミュレーションを介して利用する。つまり、USBメモリをSCSIドライブのようにみせかけ、これをLinuxのファイルシステムとして扱うわけである。
Linuxでは、こうした外部記憶デバイス(ブロックデバイス)は、単にドライバを組み込むだけでなく、マウントという作業を行ってはじめて、ファイルシステムとして見えるようになる。簡単にいえば、USBメモリは、接続しただけでは、マウントされていない状態のため、自動的にマウント、アンマウント(マウントしたものを取り外す処理)できるようにすれば、USBメモリが簡単に扱えるようになる。
Linuxのデバイスは、/dev/XXXXという名前で扱われる。これは、devファイルシステムと呼ばれ、デバイス名がファイルシステムと同じくディレクトリ構造になっている。具体的には、/devというディレクトリの下に各種のデバイスを表す特殊なファイルが置かれている。
SCSIデバイスには、/dev/sd?という名称が付けられ、?の部分は、a、b、c……となる。これが1つのSCSIチャネルに接続されるドライブに対応している。通常、HDDは、パーティションを設定して利用する。SCSIデバイス上のパーティションは、これに数字を付け、
/dev/sda1、sda2……
として表現する。デバイス自体を表す/dev/sdaと個々のパーティションを表す/dev/sda1を混同しないように注意してほしい。
さて、パーティションが1つしかないUSBメモリを1つだけ接続すると/dev/sda1となる。接続しているSCSIデバイスのパーティションを調べるには、以下のコマンドを使う。
fdisk -l /dev/sda
このコマンドを使えば、指定したデバイス上のすべてのパーティションが表示される。なお、後述するようにUSBメモリの中には、マスターブートレコードにあるパーティションテーブルがきちんと初期化されていないものがある。
パーティションが1つだけなので、Windowsでは、こうしたUSBメモリも認識してしまう。しかし、Linuxでは、さまざまなパーティション形式を扱うため、マスターブートレコードが正しくないと、きちんとデバイスを認識できない。
このSCSIエミュレーションは、該当のローダブルモジュールがロードされている間は、USBデバイスを外しても有効である。再度、同じUSBメモリを装着したときに同じ対応になるためだ。しかし、一度ローダブルモジュールを解放してやると、その対応関係が失われ、次に装着したUSBメモリが最初のSCSIデバイスである/dev/sdaとなる。
なので、一度でもUSBメモリをSL-C3000に接続した場合、ローダブルモジュールを解放しておかないと割当てが変わってしまう可能性がある。これには、SL-C3000を再起動させてもよい。
●USBを扱うためのコマンドなど
具体的な作業に入る前に、SL-C3000でUSBデバイスを扱う場合に必要になりそうなコマンドなどを簡単に解説しておこう。
・lsusb
lsusbコマンドは、接続されているUSBデバイスに関する情報を表示するためのもの。書式は、
lsusb lsusb -v lsusb -v -s デバイス番号
である。最初の形式は、すべてのUSBデバイスの簡単な表示を行なうもので、2番目のものは、詳細な表示を行なう。3番目の形式は、特定のデバイス(lsusbで表示されるDevice:以下の数字で特定)の情報を表示するためのもの。以下に実行例を示す。ここで行頭の#はrootの場合のプロンプトである(以後同様)。
[実行例]
# lsusb Bus 001 Device 001: ID 0000:0000 Bus 001 Device 008: ID 0451:2046 Texas Instruments, Inc. TUSB2046 Hub Bus 001 Device 013: ID 08ec:0010 M-Systems Flash Disk Pioneers DiskOnKey # lsusb -v -s 013 Bus 001 Device 013: ID 08ec:0010 M-Systems Flash Disk Pioneers DiskOnKey Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 1.10 bDeviceClass 0 Interface bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 64 idVendor 0x08ec M-Systems Flash Disk Pioneers idProduct 0x0010 DiskOnKey bcdDevice 2.00 : : 以下省略
・procファイルシステム
/proc/bus/usb /proc/scsi/procファイルシステムは、カーネル内部の情報などをファイルシステムとしてアクセスできるようにしてあるもの。このようにすることで多数のパラメータを専用のAPIではなく、ファイルシステムのアクセスで読み書きできる。
これには通常のファイル用コマンド(cdやls、moreなど)が利用できるし、プログラム中からはopenやreadなどのファイル用の関数が利用できる。Windowsでいえばレジストリみたいなものである。
このうち、USB関連としては、/proc/bus/usbディレクトリが対応し、SCSI関連の情報は、/proc/scsiにある。ディレクトリの表示には、lsコマンドが、ファイルの表示にはmoreまたはcatプログラムが利用できる。ただし、多くのファイルはテキストとして表示可能だが、中にはバイナリファイルもある。
USBデバイスを接続すると/proc/bus/usbには、以下のようなディレクトリ、ファイルが現れる。なお、テキスト形式のファイルは、moreコマンドで内容を表示できる。
/proc/bus/usb/001/ 最初のUSBインターフェイス /proc/bus/usb/001/001 最初のUSBデバイス(ホストコントローラ)バイナリファイル /proc/bus/usb/001/その他 他のUSBデバイス バイナリファイル /proc/bus/usb/devices デバイスの情報 テキスト /proc/bus/usb/drivers ドライバの情報 テキスト/prc/scsiのほうは、
/proc/scsi/scsi SCSIデバイスに関する情報 テキスト /proc/scsi/sg その他のさまざまな情報 テキスト /proc/scsi/usb-storage-0/ usb-storageデバイスのSCSIエミュレーション情報 /proc/scsi/usb-storage-0/0 最初のデバイス テキスト
となっている。
・マウント
Linuxで、パーティションをマウントするには、mountコマンドを使う。
mount [option] パーティション マウントポイント
パーティションの指定は、「/dev/sda1」などとして行なう。マウントポイントは、そのパーティション内のファイルシステム(ディレクトリツリー)をどのディレクトリに接続するのかを指定する。マウントポイントは、ディレクトリとしてあらかじめ作っておく必要がある。通常は、/mnt以下が使われる。
オプションは、ファイルシステムやファイルシステム固有のものを指定する。なお、手動で操作するときに毎回、オプションを指定するのは面倒なので、/etc/fstabというファイルにマウント方法を記述しておく。このようにすると、以後のマウント操作は、
mount マウントポイント
とするだけで行なえる。このfstabは、起動時にファイルシステムを構築するためのもので、これが壊れてしまうと、SL-C3000のHDDやフラッシュメモリがまったく見えなくなってしまう。作業する時には、既存の行を壊さないように十分注意されたい。
現在のマウント状態は、mountコマンドを引数なしで実行するかdfコマンドを使う。前者は、マウント状態などを表示し、後者は、マウントされたファイルシステムの容量などを表示できる。
[実行例]
# df Filesystem 1k-blocks Used Available Use% Mounted on rootfs 5120 5120 0 100% / /dev/root 5120 5120 0 100% / /dev/mtdblock3 4096 1936 2160 47% /home /dev/ram1 44 29 15 66% /dev none 1024 132 892 13% /dev/shm /dev/hda1 99521 50360 44022 53% /hdd1 /dev/hda2 398282 24412 353307 6% /hdd2 /dev/hda3 3478852 1301588 2177264 37% /hdd3 /dev/mmcda1 248960 78864 170096 32% /usr/mnt.rom/card /dev/sda1 31528 0 31528 0% /home/system/var/mnt/usbmem # mount rootfs on / type rootfs (rw) /dev/root on / type jffs2 (ro) /proc on /proc type proc (rw) /dev/mtdblock3 on /home type jffs2 (rw,noatime) /dev/ram1 on /dev type minix (rw) none on /dev/shm type tmpfs (rw) /dev/hda1 on /hdd1 type ext3 (ro,noatime) /dev/hda2 on /hdd2 type ext3 (rw,noatime) /dev/hda3 on /hdd3 type vfat (rw,noatime) none on /dev/pts type devpts (rw) /dev/mmcda1 on /usr/mnt.rom/card type vfat (rw,noatime) none on /proc/bus/usb type usbdevfs (rw) /dev/sda1 on /home/system/var/mnt/usbmem type vfat (rw,noatime) #
・ローダブルモジュール関連
現在ロードされているローダブルモジュールを表示させるには、lsmodコマンドを使う。また、ロードされているローダブルモジュールを解放(アンロード)するには、
rmmod モジュール名
とする。なお、現在稼働中のモジュールはアンロードすることができない。ローダブルモジュールの組み込みは、USBメモリ(USBマスストレージ)に関しては自動的に行なわれる(実際には、後述するusb.agentsプログラム内で行なわれる)。
●USBメモリについて
ここでUSBメモリについてちょっとした注意を述べておこう。筆者の手元にあったUSBメモリのうち、SL-C3000で正しく扱えなかったものがいくつかあった。原因は、マスターブートレコード(MBR)にあるパーティションテーブルに不正な値が書き込まれていることだった。
パーティションが1つしかない場合、Windowsは、こうしたUSBメモリでも認識してしまう。Windowsは、特定のパーティション形式にしか対応していないため、正規の方法を使わなくともパーティションの認識ができるからである。
しかし、非Microsoft系のパーティション形式にも対応しているLinuxでは、正しいパーティションテーブルがないとパーティションを認識できない。これを接続してしまうと最悪、mount時にプログラムが戻ってこなくなるなどの問題が発生する。なので、SL-C3000で使う前にほかのマシンで一度調べておいたほうがいいだろう。
パーティションテーブルを調べるには、Microsoftが提供しているdiskmapプログラムが利用できる(Windows用のコンソールコマンド)。これは、以下のURLから入手可能である。使い方は、付属のドキュメントを参照のこと。
□Diskmapプログラム
http://www.microsoft.com/windows2000/techinfo/reskit/tools/existing/diskmap-o.asp
このようなUSBメモリをSL-C3000に接続してしまうと最悪、プログラムが停止状態となり、再起動が必要になってしまうこともある。できれば、事前にMBRをチェックしておこう。以下に実行例を示す。
[実行例]MBRがおかしい場合
C:\Program Files\Resource Kit>diskmap /d5 Cylinders HeadsPerCylinder SectorsPerHead BytesPerSector MediaType 3 255 63 512 11 TrackSize = 32256, CylinderSize = 8225280, DiskSize = 24675840 (23MB) Signature = 0x00000001 StartingOffset PartitionLength StartingSector PartitionNumber 31981568 0 1 MBR: Starting Ending System Relative Total Cylinder Head Sector Cylinder Head Sector ID Sector Sectors 357 116 40 357 32 45 0x72 778135908 1141509631 288 115 43 367 114 50 0x65 168689522 1936028240 366 32 33 357 32 43 0x79 1869881465 1936028192 372 97 50 0 10 0 0x0d 0 3637226496
[実行例]MBRが正しい場合
C:\Program Files\Resource Kit>diskmap /d5 Cylinders HeadsPerCylinder SectorsPerHead BytesPerSector MediaType 3 255 63 512 11 TrackSize = 32256, CylinderSize = 8225280, DiskSize = 24675840 (23MB) Signature = 0x00000000 StartingOffset PartitionLength StartingSector PartitionNumber 16384 32555008 32 1 MBR: Starting Ending System Relative Total Cylinder Head Sector Cylinder Head Sector ID Sector Sectors 0 1 1 993 1 32 0x04 32 63584 0 0 0 0 0 0 0x00 0 0 0 0 0 0 0 0 0x00 0 0 0 0 0 0 0 0 0x00 0 0
なお、MBRがおかしい場合、パーティションを再度作り直せば大丈夫だったが、Windows XPでは、XPのインストールCDに入っているDISKPROBEなどが必要となる(\SUPPORT\TOOLSにある)。あるいはLinux側でパーティションを設定し、再度ファイルシステムを構築してもよい。
●手動でUSBメモリをマウントして使う
とりあえず、手動でUSBメモリをマウントする方法を試してみることにしよう。後述するスクリプトは、この手順を自動化するものである。なお、以後の操作は、rootで行なう。行頭の#はrootの場合のプロンプトである。
まず、マウントポイントを作る。手順は、
[実行例]
# cd /mnt # mkdir usbmem
である。/mntディレクトリを使うのは慣例的なもので、理論的にはどこでもよい。なお、SL-C3000では、このディレクトリは、/home/system/var/mntになる。SL-C3000では、ファイルシステムがリードオンリーのフラッシュメモリ、書き込み可能なフラッシュメモリと3つのHDD上のパーティションの3つから構成されているため、複雑なリンクが貼られている。このために、実際にファイルが存在するディレクトリが違っている場合がある。
ここで、SL-C3000にUSBメモリを接続してみる。USBメモリにインジケータがあるなら、光るはずである。
ローダブルモジュールが正しく動作していれば、/proc/scsi以下にusb-storage-0というディレクトリができているはずだ。
[実行例]
# ls /proc/scsi/ scsi sg usb-storage-0 #
この状態で、USBメモリは、/dev/sdaに割り当てられているはずだ。ではパーティションをみてみよう。
[実行例]
# fdisk -l /dev/sda Disk /dev/sda: 32 MB, 32587776 bytes 2 heads, 32 sectors/track, 994 cylinders Units = cylinders of 64 * 512 = 32768 bytes Device Boot Start End Blocks Id System /dev/sda1 1 994 31792 4 FAT16 <32M
この実行結果から、USBメモリのパーティションは1つで、それは/dev/sda1であることがわかる。
では、いよいよマウントしてみる。
[実行例]
# mount -t vfat /dev/sda1 /mnt/usbmem # df Filesystem 1k-blocks Used Available Use% Mounted on rootfs 5120 5120 0 100% / /dev/root 5120 5120 0 100% / /dev/mtdblock3 4096 1928 2168 47% /home /dev/ram1 44 29 15 66% /dev none 1024 124 900 12% /dev/shm /dev/hda1 99521 50360 44022 53% /hdd1 /dev/hda2 398282 24412 353307 6% /hdd2 /dev/hda3 3478852 1301588 2177264 37% /hdd3 /dev/mmcda1 248960 78864 170096 32% /usr/mnt.rom/card /dev/sda1 31528 0 31528 0% /home/system/var/mnt/usbmem
【写真01】USBメモリをマウントすると、Zaurusのホーム画面で/dev/sda1が見えるようになる |
一番最後の行に、/dev/sda1が/home/system/var/mnt/usbmemにマウントされていることが表示されている。この状態で、/mnt/usbmemの中をみれば、そこがUSBメモリとなる。なお、ここでは、細かいオプション指定をしていないので、日本語のファイル名は正しく表示されないし、root以外は書き込みもできない。オプション指定については後述する。
また、この時点で、SL-C3000のホーム画面のファイルタブには、(写真01)のように/dev/sda1が表示される。この状態では、SDカードなどと同じように利用できる。
USBメモリを取り外したい場合には、アンマウント処理を行なう。もし、何かエラーが表示されたら、USBメモリ内のファイルがオープン途中であったり、カレントディレクトリになっている可能性がある。プログラムを全部終了させるなどして、USBメモリを使っているプロセスがないようにする。
[実行例]
# cd / # umount /mnt/usbmem
最後にローダブルモジュールをアンロードする。これにより、USBメモリ用ドライバと/dev/sdaとの関係が無くなり、次回接続したUSBメモリに/dev/sdaが割り当てられるようになる。
[実行例]
# rmmod usb-storage #
以上が、USBメモリを手動で利用するための手順である。USBメモリを使うたびに、毎回、ターミナルを起動してこの手順を繰り返すのは大変である。しかし、Linuxには、こうした作業を自動化するための仕組みが用意されている。
●USBデバイスの管理
では、次に、SL-C3000のLinuxでUSBデバイスがどのように扱われるのかを見ていくことにしよう。
Linux 2.4では、hotplugという機構が組み込まれ、これを使ってUSBの抜き差しを管理している。多くのLinuxディストリビューションでは、このhotplug部分にmurasakiなどのマネージャを採用しているが、SL-C3000には、素のままのhotplug機構が使われている。なお、この機構は、ZaurusのUSBドライブ機能(ZaurusがUSB大容量ストレージクライアントとなる機能)でも使われている。このため、murasakiなどをインストールすると、USBドライブ機能が利用できなくなる可能性がある。
hotplugは、以下のような手順でUSBデバイスに必要なモジュールをロードし、関連プログラムを起動する。
1.USBデバイスの接続をカーネルが検出すると/sbin/hotplugが起動される。
設定としては、/proc/sys/kernel/hotplugで指定されているプログラムが起動される。また、標準の/sbin/hotplugプログラムは、シェルスクリプトである。
2./sbin/hotplugは、デバイスの種類を判別し/etc/hotplug/デバイス.agentを起動する
USBの場合には、/etc/hotplug/usb.agents
usb.agentsが、各種のUSBデバイスを判別し、必要に応じた処理を行なう。ただし、標準では、前述のようにUSBキーボードにしか対応していない。usb.agentsもシェルスクリプトで、以下のような動作を行なう。
1.デバイスを判定する
usb.distmap、usb.handmap、usb.usermapからデバイスの種類を判定する。
2.必要なローダブルモジュールをロードする(hotplug.functionのload_device)
3.デバイスに応じて/etc/hotplug/usb以下のSubsystemプログラムが起動される
USBメモリが接続された場合には、/etc/hotplug/usb/usb-storageが起動される
4.デバイスが切り離された場合には、REMOVERと呼ばれるプログラムが起動
これは、/etc/hotplug/usb以下のSubsystemプログラムで用意しておく
つまり、USBメモリを利用するためには、SubsystemプログラムとREMOVERを用意し、Subsystemプログラムの中でマウントの処理とREMOVERの登録を行なう。また、REMOVERでは、アンマウント処理とローダブルモジュールの解放を行なう。
事前の準備としては、マウントポイントを作成しておき、マウントオプションなどを指定した行をfstabに追加しておく。
USBメモリと対応するSCSIデバイスとの対応を判定するのが困難であるため、制限として同時に接続できるUSBメモリは1つだけにした。複数のUSBメモリを接続しても、このスクリプトで自動マウント/アンマウントできるのは、最初に接続したUSBメモリだけで、2個目からは無視される。
本来、実際のデバイスとエミュレーションされたSCSIデバイスの対応は、scsi_infoプログラムなどを使って判定できるはずだが、SL-C3000では、usb-storageでSCSIデバイスをエミュレーションさせたときにSCSI_IDの割当てがかならずゼロになってしまい、USBメモリとSCSIデバイスの対応を判定することができなかった。
どのUSBメモリもSCSI_IDがゼロになってしまうので、区別ができないのである。SCSI_IDは、1つのSCSIチャンネルに接続されるデバイスが持つ番号で、SCSIのHDDなどではDIPスイッチなどで設定するもの。つまり、デバイス側がSCSIドライバに報告するものであって、後から割り当てるものではない。このため、usb-storageによるSCSIエミュレーションでは、自分が何番目に装着されたのかがわからないと、SCSI_IDを報告できないため、ゼロになってしまうのだと思われる。
今回は、最初に装着したUSBメモリが必ず/dev/sdaになるように、アンマウントしたあとにローダブルモジュールをアンロード(メモリから削除)している。このようにしているため、2つ目のUSBメモリが接続されているとき、それがマウントされていなければ、1つ目のUSBメモリを抜いた段階でデバイスが見えなくなってしまう。
マウントされていないのでデータなどを失う危険はないが、USBメモリを使えるようにするには、抜き差しを行なう必要がある(insmodコマンドでローダブルモジュールをインストールしてもよい)。なお、2つ目のUSBメモリをマウントしているとデバイスがビジーとなるためにrmmodがエラーになり、アンロードは行なわれない。
アンロードが行なわれない限り、USBメモリとSCSIデバイス名との対応は固定されているため、一度/dev/sdbなどに割り当てられたUSBメモリは、再度装着しても同じSCSIデバイス名が使われてしまう。
とういわけなので、2つ以上のUSBメモリを同時に利用するのは、できれば避けたほうがよく、やむを得ない場合は、スクリプトの動作などを理解した上で行なって欲しい。使い勝手の点でいえば、SL-C3000はHDDを内蔵しているため、2つのUSBメモリを同時に装着してコピーをしなくても、一旦HDDにコピーすればすむ。というわけでこの仕様でも十分だと思われる。
●実際の作業
以下の作業は、rootで行なう。なお、root状態では、ほとんどのファイルを削除可能なので、非常に危険なため、注意すること。
また、ファイルの編集には、viエディタを利用する。Zaurus用のGUIエディタでも編集作業はできるが、ファイル所有者やグループなどの属性、行末コードなどが変わってしまう可能性があるので注意されたい。
・マウントポイントの作成
まず、マウントポイントを作成しておく。ここでは、usbmemとし、/mntディレクトリに作成した。このディレクトリには、“usbstorage”という名前のディレクトリがあるが、SL-C3000がどのような使い方をするかわからないので、別途マウントポイントを作成した。また、前項の「手動でUSBメモリをマウントして使う」ですでにマウントポイントを作った人は、再度作業をする必要はない。
cd /mnt mkdir usbmem
・Subsystemプログラム
【リスト01】のプログラムを/etc/hotplug/usbにusb-storageというファイル名で/etc/hotplug/usbに置く(viを使って入力する)。
【リスト01】
#!/bin/sh # Created by Shinji Shioda . /etc/hotplug/hotplug.functions if [ ! -L /var/run/usb/%proc%bus%usb%* ]; then mesg Try to Mount mount /mnt/usbmem if [ $? = 0 ]; then ln -s /etc/hotplug/usb/usb-storage.off $REMOVER mesg make REMOVER in $REMOVER fi fi
置いた後に以下の作業を行ない実行属性を付ける。
cd /etc/hotplug/usb chmod 755 usb-storage
・REMOVERプログラム
同様に【リスト02】のプログラムを/etc/hotplug/usb/usb-storage.offとして作成する。その後、同じように実行属性を付ける。
【リスト02】
#!/bin/sh # Created by Shinji Shioda . /etc/hotplug/hotplug.functions mesg Removing /mnt/usbmem umount /mnt/usbmem rmmod usb-storage
・fstabの記述
/etc/fstabに以下の行(1行)を追加する。後半はほとんどオプション指定である。noautoだけがfstab専用のオプションで、あとのオプションは、すべてmountコマンドをコマンドラインから実行する場合の引数として付けるもの。
/dev/sda1 /mnt/usbmem vfat noauto,umask=000,noatime,iocharset=utf8,codepage=932 0 0
この行と同等のことをコマンドラインで直接指定する場合には、
# mount -t vfat -o umask=000,noatime,iocharset=utf8,codepage=932 /dev/sda1 /mnt/usbmem
とする。これでは面倒なので、上記のようにfstabに予めマウント方法を指定しておくわけだ。
すべてが正しいことを確認したら、USBメモリを接続する。その後少し時間を置いてからdfコマンドもしくは、mountコマンドで/dev/sda1が/mnt/usbmemにマウントされているかどうかを確認する。マウントされていれば、
ls /mnt/usbmem
でUSBメモリのルートディレクトリの内容が表示できるはずである。
その後、/mnt/usbmem以下のファイルやディレクトリを利用しているプログラムがないことを確認して、USBメモリを抜く。ただしくアンマウントされたかどうかをdfやmountコマンドで確認する。
なお、間違いがないにも関わらずマウントできない場合には、前述のマスターブートレコードを調べたり、/proc/bus/usb、/proc/scsiなどを使って状態を確認する。まれにマウントやアンマウントがうまく行かないこともあるかもしれない。USBメモリが接続されていない状態で/var/run/usbにシンボリックリンク(%proc%bus%usb%001%0??というファイル名)が残っているとマウント処理が行なえないのでこれを削除する。
●プログラムの説明
ここでは、簡単にスクリプトの内容を解説しておく。プログラムは/bin/sh、つまりUnixオリジナルのBourne シェルで記述されている。
Subsystemプログラム【リスト01】は、環境変数で各種のパラメータを渡される。渡される引数は、【表01】のようなものである。また、このプログラムが呼び出される前の段階で、すでにローダブルモジュールが組み込まれており、デバイスのタイプ(キーボードなのか、USBメモリなのかなど)が判定されている。なので、/etc/hotplug/usb/usb-storageでは、USBメモリの処理だけを行なえばよい。
【表01】環境変数 | 値 | 注釈 |
---|---|---|
ACTION | add/remove | USBデバイスではaddまたはremoveのどちらか*1 |
PRODUCT | idVendor/idProduct/bdcDevice | 左記の値(16進)を/で区切ったもの |
TYPE | bDeviceClass/bDeviceSubClass/bDeviceProtocol | 左記の値(16進)を/で区切ったもの |
INTERFACE | bInterfaceClass/bInterfaceSubClass/bInterfaceProtocol | 左記の値(16進)を/で区切ったもの |
DEVFS | usbdevfsへのパス | /proc/bus/usbが渡される |
DEVICE | usbdevfs内のデバイスへのパス(/proc/bus/usb/00x/00x) | デバイスに対応する/porc/bus/usb内のファイルへのパス |
実際に行なうのは、マウント操作で、すでにfstabに設定が行なわれているため、
mount /mnt/usbmem
を実行する。これが成功したら、次のif文の内部が実行されることになる。
ここでは、/var/run/usb以下にREMOVERプログラムへのシンボリックリンクを作っている。/var/run/usb/以下にあるREMOVERプログラムは、USBメモリを抜いたときに自動的に実行され、その後、削除される。この処理は、/etc/hotplug/usg.agents内で行なわれるため、ここではリンクのみを作っている。
REMOVERプログラム(usb-storage.off。【リスト02】)は、アンマウントを行ない、ローダブルモジュールを解放する。rmmodは、デバイスがビジーであるときは失敗するが、これは、2つ目以降のUSBメモリが装着されてマウントされていることを意味する。なので、エラー処理は行なっていない。
なお、mesgは、3行目で読み込んでいる/etc/hotplug/hotplug.functionsで定義されているデバッグ用の関数である。
●新規にusb-storageを登録する
標準状態で多くのメーカーのUSBメモリが登録されているが、デジカメなどのUSBマスストレージはほとんど登録されていない。これらを使うには、/etc/hotplug/usb.distmapへの登録が必要である。
ここでは、筆者手持ちのカシオのQV-R4を接続してみることにした。まず、デジカメをUSBマスストレージになるようにしてSL-C3000に接続してみる。この状態で、dfもしくはmountコマンドでマウントされたかどうかを確認する。すでにデータが登録されているなら、マウントが行なわれているはずである。しかし、QV-R4は登録されていなかった。
まず、lsusbで情報を取得する。
[実行例]lsusb
# lsusb Bus 001 Device 001: ID 0000:0000 Bus 001 Device 027: ID 07cf:1001 Casio Computer Co., Ltd QV-8000SX/5700/3000EX Digicam
メーカー名などが表示されているので、2つ目がQV-R4のものだとわかる。プロダクツ名は、lsusbが表示しているので必ずしも正しくない(/usr/share/usb.idsファイルを元に表示を行なっている)。デバイスから取得したベンダー名文字列データなどを見るには/proc/bus/usb/devicesを表示させるといいだろう。
ここで必要なのは、ID以下の2つの16進数である。この出力では、07cfがメーカー名を表すベンダーコード、コロンの次が製品を表すプロダクツコード(1001)だ。表記は16進数になっている。
登録を行なうにはこの2つの値を使ってusb.distmapにデータを追加する。usb.dismapは、13個のフィールドをスペースで区切って1レコード分としたデータベースファイルである。行の先頭がデバイスのカテゴリで、USBマスストレージは、“usb-storage”である。
各フィールドの意味を【表02】に示す。先頭がusbモジュール名、2つ目がmatch_flagsと呼ばれ、後続のフィールドのうちどれを比較してどれを無視するのかを指定するもの。
【表02】フィールド名 | 意味 |
---|---|
usbmodule | USBモジュールの名称 |
match_flags | 判定に以後のどのフィールドを使うかの指定 |
idVendor | ベンダー(メーカー)コード |
idProduct | 製品コード |
bcdDevice_lo | デバイスバージョンの下限*1 |
bcdDevice_hi | デバイスバージョンの上限*1 |
bDeviceClass | デバイスクラス |
bDeviceSubClass | デバイスサブクラス |
bDeviceProtocol | プロトコルコード |
bInterfaceClass | インターフェイスクラス |
bInterfaceSubClass | インターフェイスサブクラス |
bInterfaceProtocol | インターフェイスプロトコル |
driver_info | デバイス固有の情報(通常は使われない) |
フィールドとの対応は、【表03】のようになっている。この値は、判定したいフィールドに対応する値を表から求め、それを足したものを使う。たとえば、idVendorとidProductsだけを使う場合には、0x0001+0x0002=0x0003を指定する。また、bcdDevice_loとbcdDevice_hiは、bcdDevice値の下限と上限を指定するもので、指定した場合、bcdDevice_lo <= bcdDevice < bcdDevice_hiとして判定が行なわれる。上限値の判定が“<”でのみ行なわれる点に注意。また、先頭フィールド以外はすべて16進数表記で先頭に0xを付ける。
【表03】フィールド | 対応する値(ビット) |
---|---|
idVendor | 0x0001 |
idProduct | 0x0002 |
bcdDevice_lo | 0x0004 |
bcdDevice_hi | 0x0008 |
bDeviceClass | 0x0010 |
bDeviceSubClass | 0x0020 |
bDeviceProtocol | 0x0040 |
bInterfaceClass | 0x0080 |
bInterfaceSubClass | 0x0100 |
bInterfaceProtocol | 0x0020 |
QV-R4では、ベンダーコード(idVendor)とプロダクツコード(idProducts)だけで判定するようにしてみた。なので、match_flagsとしては0x0003を使う。
具体的には、/etc/hotplug/usb.distmapに以下のような行を追加する。
usb-storage 0x0003 0x07cf 0x1001 0x0000 0x0000 0x00 0x00 0x00 0x08 0x06 0x50 0x00000000
作業としては、既存の行をコピーし、それを書き換えるほうがいいだろう。
なお、細かくフィールドを設定するには、lsusb -vコマンドを使えば、各フィールドに対応したデータが得られる。
usb.distmapを書き換えたら、デジカメを接続しなおす。追加データが正しければ、usb-storageとして認識され、マウントが行なわれるはずである。
●USBホスト対応といえないジレンマ
SL-C3000のコネクタは、USB On The Go(OTG)で規定されたミニABコネクタある。OTGでは、限定されたホスト機能を持つとされていて、すべてのUSBクライアントに対応する必要はない。だが、対象となるクライアント機器を公開しなければならないとされている。OTGは、デジカメなどがプリンタを接続して印刷するような場合を想定しているためだ。
また、OTGでの接続では、OTG独自のプロトコルが定義されていて、これをサポートする必要がある(これがSL-C3000に実装されているかどうかは不明)。
Zaurusのようなコンピュータ本体の場合、ドライバを組み込めばいくらでも対応が可能であり、PXA-270のホスト機能は、基本的にはPC用のものと同等だ。つまり、ハードウェア的にはフル機能のホストインターフェイスを持っているが、何が接続できるのかは、組み込まれたドライバ次第である。
こうした状況があるためにOTGともいえず、かといって完全なホストともいえない状態でり、メーカーとしても、ホスト機能があるとは言い難いのであろう。しかし、最低限必要なファイルやコマンドなどは用意されているので、ユーザーレベルでいろいろと検証していくことで今後はさまざまな機器が使えるようになるのではないかと思われる。
さて、USBメモリの使い心地だが、PCにそのまま装着できるので、カードリーダーが必要となるCFやSDカードに比べると便利である。ホーム画面からもデバイスが直接見えるのでGUIでのファイル操作も可能だ。なお、SL-C3000には、USBハブも接続できるため、電源容量が心配な場合に、ハブをセルフパワーにして接続すればいいだろう。
最後にくどいようだが、今回の記事の内容には、理解せずに実行するとZaurusが動作不能になる可能性があるものが含まれており、自己責任ということを理解したうえで、行なってほしい。なお、今回掲載したスクリプトなどは、短いものでもあり、自由に改変して使っていただいてかまわない。
□関連記事
【11月15日】【塩田】HDD内蔵PDA「シャープ SL-C3000」内部構造編
http://pc.watch.impress.co.jp/docs/2004/1115/pda38.htm
【11月12日】【塩田】初のHDD内蔵PDA「シャープ SL-C3000」を試す
http://pc.watch.impress.co.jp/docs/2004/1112/pda37.htm
(2004年11月22日)
[Text by 塩田紳二]