Driverについて

9

Click here to load reader

description

2013年7月のCocoa勉強会(関東)で発表した資料です。

Transcript of Driverについて

Page 1: Driverについて

Driverについて最近の状況の整理

2013.07.06Bitz Co., Ltd. 村上幸雄

1. はじめにApple開発者のサイトでDarwinのソースコードが公開されているが、ドライバ関連で

は、文書とサンプルコードも付属しているので、開発したいものに近いサンプルコードを基に拡張していう方法もあるが、今回は、Xcodeの新規プロジェクトから製作してみようと思う。

• Open Source - Releaseshttp://www.opensource.apple.com/• Mac OS X 10.7.5 - Sourcehttp://www.opensource.apple.com/release/mac-os-x-1075/"

Xcodeでドライバの新規プロジェクトを生成する場合、雛形としては、Generic Kernel ExtensionとIOKit Driverの二種類があるが、その違いについてまとめてみる。

Generic kernel extension template IOKit driver template

開発言語実装方法実行方法

C Embedded C++

コールバック関数 I/O Kitクラスの派生クラス

明示的に起動と停止 自動

2. kext(generic kernel extension)新規プロジェクトで、Generic kernel extension templateを選択する。

Page 2: Driverについて

プロジェクト名は、Smart Scrollという製品に対するプログラムを作成しようと思ったので、サンプルでは、SmartScrollKextとした。TARGETSのArchitecturesのBuild Active Architecture Onlyは、NOを選択する。

これを設定しておかないと、32bitカーネルで動作している開発機で、64bitドライバを生成し、テストに失敗してしまうなどのトラブルに遭遇する可能性がある。

SmartScrollKext.cにデバッグ出力を追加する。

#include <sys/systm.h>#include <mach/mach_types.h>

kern_return_t SmartScrollKext_start(kmod_info_t * ki, void *d);kern_return_t SmartScrollKext_stop(kmod_info_t *ki, void *d);

kern_return_t SmartScrollKext_start(kmod_info_t * ki, void *d){ printf("SmartScrollKext has started.\n"); return KERN_SUCCESS;}

kern_return_t SmartScrollKext_stop(kmod_info_t *ki, void *d){ printf("SmartScrollKext has stopped.\n"); return KERN_SUCCESS;}

SmartScrollKext-Info.plistのCFBundleIdentifierをcom.MyCompany.kext.${PRODUCT_NAME:rfc1034identifier}に変更する。下記の例では、MyCompanyは著者の会社のものにしている。

Page 3: Driverについて

一度、プロジェクトをビルドする。Show the Log NavigatorからSmartScrollKext.kextの出力先を調べて、ターミナル.appで、そのディレクトリに移動する。

$ cd Build/Products/Debug

そこで以下のコマンドを実行する。

$ kextlibs -xml SmartScrollKext.kext <key>OSBundleLibraries</key> <dict> <key>com.apple.kpi.libkern</key> <string>11.4.2</string> </dict>

この内容をSmartScrollKext-Info.plistのOSBundleLibrariesに設定する。

再度、ビルドし、生成されたSmartScrollKext.kextを/tmpにコピーする。

$ sudo cp -R SmartScrollKext.kext /tmp

以下のコマンドで、問題がないか確認する。

$ kextutil -n -print-diagnostics /tmp/SmartScrollKext.kextNo kernel file specified; using running kernel for linking./tmp/SmartScrollKext.kext appears to be loadable (including linkage for on-disk libraries).

ログ確認の準備を行う。

$ cd /var/log$ tail -f kernel.log

Page 4: Driverについて

ロードする。

$ sudo kextload /tmp/SmartScrollKext.kext

アンロードする。

$ sudo kextunload /tmp/SmartScrollKext.kext

ログにデバッグ出力が印字されている事を確認する。

Jun 24 00:31:39 マシン名 kernel[0]: SmartScrollKext has started.Jun 24 00:33:08 マシン名 kernel[0]: SmartScrollKext has stopped.

3. I/O Kitドライバ新規プロジェクトで、IOKit driver templateを選択する。

プロジェクト名は、前回の流れからSmartScrollDriverとした。今回も、前回と同様にTARGETSのArchitecturesのBuild Active Architecture Only

は、NOを選択する。SmartScrollDriver-Info.plistのCFBundleIdentifierをcom.MyCompany.driver.$

{PRODUCT_NAME:rfc1034identifier}に変更する。著者は、MyCompanyに自分の会社のものにしている。

Page 5: Driverについて

SmartScrollDriver-Info.plistのIOKitPersonalitiesにSmartScrollDriver辞書型を追加して、以下の内容に設定する。

Name Value

CFBundleIdentifier com.MyCompany.driver.${PRODUCT_NAME:rfc1034identifier}

IOClass com_MyCompany_driver_SmartScrollDriver

IOKitDebug 65535

IOProviderClass IOResources

IOMatchCategory com_MyCompany_driver_SmartScrollDriver

IOClassは、このドライバの起点となるクラス名の様だ。ようするに、この名前のクラスを実装する事になる。IOProviderClassは、ドライバがぶら下がるnubクラス名。テンプレートのSmartScrollDriver.hとSmartScrollDriver.cppは空なので中身を実装

する。メソッドが呼ばれたらにデバッグ出力するだけだ。

#include <IOKit/IOService.h>class jp_co_bitz_driver_SmartScrollDriver : public IOService { OSDeclareDefaultStructors(jp_co_bitz_driver_SmartScrollDriver)public: virtual bool init(OSDictionary *dictionary = 0); virtual void free(void); virtual IOService *probe(IOService *provider, SInt32 *score); virtual bool start(IOService *provider); virtual void stop(IOService *provider);};

Page 6: Driverについて

#include <IOKit/IOLib.h>#include "SmartScrollDriver.h"

OSDefineMetaClassAndStructors(jp_co_bitz_driver_SmartScrollDriver, IOService)

#define super IOService

bool jp_co_bitz_driver_SmartScrollDriver::init(OSDictionary *dict){ bool result = super::init(dict); IOLog("Initializing\n"); return result;}

void jp_co_bitz_driver_SmartScrollDriver::free(void){ IOLog("Freeing\n"); super::free();}

IOService *jp_co_bitz_driver_SmartScrollDriver::probe(IOService *provider, SInt32 *score){ IOService *result = super::probe(provider, score); IOLog("Probing\n"); return result;}

bool jp_co_bitz_driver_SmartScrollDriver::start(IOService *provider){ bool result = super::start(provider); IOLog("Starting\n"); return result;}

void jp_co_bitz_driver_SmartScrollDriver::stop(IOService *provider){ IOLog("Stopping\n"); super::stop(provider);}

一度、プロジェクトをビルドする。Show the Log NavigatorからSmartScrollDriver.kextの出力先を調べて、ターミナル.appで、そのディレクトリに移動する。

$ cd Build/Products/Debug

そこで以下のコマンドを実行する。

Page 7: Driverについて

$ kextlibs -xml SmartScrollDriver.kext <key>OSBundleLibraries</key> <dict> <key>com.apple.kpi.iokit</key> <string>11.4.2</string> <key>com.apple.kpi.libkern</key> <string>11.4.2</string> </dict>

この内容をSmartScrollKext-Info.plistのOSBundleLibrariesに設定する。再度、ビルドし、生成されたSmartScrollDriver.kextを/tmpにコピーする。

$ sudo cp -R SmartScrollDriver.kext /tmp

以下のコマンドで、問題がないか確認する。

$ kextutil -n -t /tmp/SmartScrollDriver.kextNo kernel file specified; using running kernel for linking.Notice: /tmp/SmartScrollDriver.kext has debug properties set./tmp/SmartScrollDriver.kext appears to be loadable (including linkage for on-disk libraries).

ロードしてみる。

$ sudo kextutil -v /tmp/SmartScrollDriver.kextPassword:Notice: /tmp/SmartScrollDriver.kext has debug properties set./tmp/SmartScrollDriver.kext appears to be loadable (not including linkage for on-disk libraries).Loading /tmp/SmartScrollDriver.kext./tmp/SmartScrollDriver.kext successfully loaded (or already loaded).

確認する。

$ kextstat | grep jp.co.bitz 162 0 0xb97000 0x4000 0x3000 jp.co.bitz.driver.SmartScrollDriver (1) <4 3>

アンロード。

$ sudo kextunload -v /tmp/SmartScrollDriver.kextjp.co.bitz.driver.SmartScrollDriver unloaded and personalities removed.

次は、対象と鳴るUSB機器(SmartScroll)が抜き差しされたら、ドライバが反応する事を確認してみる。

Page 8: Driverについて

DarwinのソースコードのIOUSBFamily-(バージョン番号).tar.gzのExamplesにあるVendorSpecific Driverのプロジェクトを開いて、Info.plistを確認する。

IOProviderClassをIOUSBDeviceにして、bcdDeviceとiDProduct、idVendorを対象機器の値にすれば、抜き差しに反応しそうだ!以前の開発環境に含まれていたUSB Proberを持っていたら、それを使って、

SmartScrollの情報を確認する。

Page 9: Driverについて

VendorIDが0x056A、ProductIDが0x0050、DeviceVersionNumberが0x0007なので、SmartScrollDriver-Info.plistのIOKitPersonalitiesのSmartScrollDriverにbcdDeviceとidProduct、idVendorを追加して、7と80、1386を入力する。

この内容でビルドしてドライバーを前回の方法でロードする。

$ sudo cp -R SmartScrollDriver.kext /tmp$ sudo kextutil -v /tmp/SmartScrollDriver.kextNotice: /tmp/SmartScrollDriver.kext has debug properties set./tmp/SmartScrollDriver.kext appears to be loadable (not including linkage for on-disk libraries).Loading /tmp/SmartScrollDriver.kext./tmp/SmartScrollDriver.kext successfully loaded (or already loaded).

kernel.logをtailし、USB機器を差し込んで、抜く。

$ tail -f /var/log/kernel.logJul 1 22:30:56 mbc2d kernel[0]: [SmartScrollDriver]InitializingJul 1 22:30:56 mbc2d kernel[0]: [SmartScrollDriver]ProbingJul 1 22:30:56 mbc2d kernel[0]: No interval found for . Using 8000000Jul 1 22:30:56 mbc2d kernel[0]: [SmartScrollDriver]StartingJul 1 22:31:14 mbc2d kernel[0]: No interval found for . Using 8000000Jul 1 22:31:14 mbc2d kernel[0]: [SmartScrollDriver]StoppingJul 1 22:31:14 mbc2d kernel[0]: [SmartScrollDriver]Freeing

アンロード。

$ sudo kextunload -v /tmp/SmartScrollDriver.kextjp.co.bitz.driver.SmartScrollDriver unloaded and personalities removed.

抜き差しした際に、ログが出力されている事が分かるはずだ。