見出し画像

[macOS] ドライバについて(driver)

今回は、IOKit driver templateで生成したプロジェクトを使って開発だ。

新規プロジェクトで、IOKit driver templateを選択する。

プロジェクト名は、前回の流れからSmartScrollDriverとした。

今回も、前回と同様にTARGETSのArchitecturesのBuild Active Architecture Onlyは、NOを選択する。

SmartScrollDriver-Info.plistのCFBundleIdentifierをcom.MyCompany.driver.${PRODUCT_NAME:rfc1034identifier}に変更する。著者は、MyCompanyに自分の会社のものにしている。

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

- 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);
};
#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

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

$ 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.kext
No 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.kext
Password:
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.kext
jp.co.bitz.driver.SmartScrollDriver unloaded and personalities removed.

次は、対象のUSB機器が抜き差しされたらログが出力される事を確認する。

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

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

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.kext
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).

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

$ tail -f /var/log/kernel.log
Jul  1 22:30:56 mbc2d kernel[0]: [SmartScrollDriver]Initializing
Jul  1 22:30:56 mbc2d kernel[0]: [SmartScrollDriver]Probing
Jul  1 22:30:56 mbc2d kernel[0]: No interval found for . Using 8000000
Jul  1 22:30:56 mbc2d kernel[0]: [SmartScrollDriver]Starting
Jul  1 22:31:14 mbc2d kernel[0]: No interval found for . Using 8000000
Jul  1 22:31:14 mbc2d kernel[0]: [SmartScrollDriver]Stopping
Jul  1 22:31:14 mbc2d kernel[0]: [SmartScrollDriver]Freeing

アンロード。

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

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

参考情報
- Kernel Extension Programming Topics

この記事が気に入ったらサポートをしてみませんか?