[OSX]ドライバについて（kext）

<p>Apple開発者のサイトでDarwinのソースコードが公開されているが、ドライバ関連では、文書とサンプルコードも付属しているので、開発したいものに近いサンプルコードを基に拡張していく方法もあるが、今回は、Xcodeの新規プロジェクトから製作してみようと思う。</p>

<a href="http://www.opensource.apple.com/">Open Source - Releases</a><br />
<a href="http://www.opensource.apple.com/release/mac-os-x-1075/">Mac OS X 10.7.5 - Source</a><br />

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

<table border="1">
	<tr>
		<th></th><th>Generic kernel extension template</th><th>IOKit driver template</th>
	</tr>
	<tr>
		<td>開発言語</td><td>C</td><td>Embedded C++</td>
	</tr>
	<tr>
		<td>実装方法</td><td>コールバック関数</td><td>I/O Kitクラスの派生クラス</td>
	</tr>
	<tr>
		<td>実行方法</td><td>明示的に起動と停止</td><td>自動</td>
	</tr>
</table>

<p>それでは、kext（generic kernel extension）を作ってみよう。</p>

<p>新規プロジェクトで、Generic kernel extension templateを選択する。</p>

![20130623_0.jpg](https://qiita-image-store.s3.amazonaws.com/0/12540/dd2fed1a-49d1-aaee-90e5-a500a3c46c31.jpeg)


<p>プロジェクト名は、<a href="http://tablet.wacom.co.jp/products/smartscroll/pdf/smartscroll_ds.pdf">Smart Scroll</a>という製品に対するプログラムを作成しようと思ったので、サンプルでは、SmartScrollKextとした。</p>

<p>TARGETSのArchitecturesのBuild Active Architecture Onlyは、NOを選択する。これを設定しておかないと、32bitカーネルで動作している開発機で、64bitドライバを生成し、テストに失敗してしまうなどのトラブルに遭遇する可能性がある。</p>

![20130623_1.jpg](https://qiita-image-store.s3.amazonaws.com/0/12540/a9297448-92f2-9ce7-550b-227da586996c.jpeg)


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

<pre><code>#include &lt;sys/systm.h&gt;
#include &lt;mach/mach_types.h&gt;
 
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;
}
</code></pre>

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

![20130623_2.jpg](https://qiita-image-store.s3.amazonaws.com/0/12540/3966f067-c808-d24e-3227-2a2b7281025f.jpeg)


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

<pre><code>cd Build/Products/Debug
</code></pre>

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

<pre><code>$ kextlibs -xml SmartScrollKext.kext
	&lt;key&gt;OSBundleLibraries&lt;/key&gt;
	&lt;dict&gt;
		&lt;key&gt;com.apple.kpi.libkern&lt;/key&gt;
		&lt;string&gt;11.4.2&lt;/string&gt;
	&lt;/dict&gt;
</code></pre>

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

![20130623_3.jpg](https://qiita-image-store.s3.amazonaws.com/0/12540/ef0ec991-6ffd-0e27-f869-6113a6e9f887.jpeg)


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

<pre><code>$ sudo cp -R SmartScrollKext.kext /tmp
</code></pre>

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

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

<p>ログ確認の準備を行う。</p>

<pre><code>$ cd /var/log
$ tail -f kernel.log
</code></pre>

<p>ロードする。</p>

<pre><code>$ sudo kextload /tmp/SmartScrollKext.kext
</code></pre>

<p>アンロードする。</p>

<pre><code>$ sudo kextunload /tmp/SmartScrollKext.kext
</code></pre>

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

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

関連情報
<a href="http://www.opensource.apple.com/release/mac-os-x-1075/">Mac OS X 10.7.5 - Source</a><br />
<a href="https://developer.apple.com/library/mac/#documentation/Darwin/Conceptual/KEXTConcept/KEXTConceptIntro/introduction.html">Kernel Extension Programming Topics</a><br />

【Cocoa練習帳】
<a href="http://www.bitz.co.jp/weblog/">http://www.bitz.co.jp/weblog/</a><br />
<a href="http://ameblo.jp/bitz/">http://ameblo.jp/bitz/</a>（ミラー・サイト）<br />