SlideShare a Scribd company logo
デバイスドライバを作ってみよう!




    第 4 回 カーネル/ VM 探検隊
           2010/05/08 @masami256
何でデバドラを作るの?
●
    愛用している OS にドライバがな
    い

●
    自作 OS でデバイスを使いたい
ドライバ作成の準備
●
    資料を揃える
     –   メジャーなデバイスだと、 TECH I が便利
●
    ドライバを書きたい OS の作法を調べる
     –   Linux, OpenBSD, Plan 9 and so forth
●
    ユーザランドで実装できる場合もある
     –   USB デバイスなら libusb が使える
●
    実装方法を考える
ATA デバイスの認識フロー概要
PCI デバイスの検索
●
    下記 3 個の組み合わせを総当たりで
      –   デバイス番号 0 〜 7
      –   バス番号 0 〜 31
      –   機能番号 0 〜 7
●
    機能番号が 0 のデバイスの場合の注意
      –   コンフィギュレーションレジスタからヘッダタ
           イプを読み込む
      –   マルチファンクションか調べる
      –   マルチファンクションで無ければ、機能番号
           1 〜 7 にはデバイスはなし
PCI デバイスの検索
●
    Config Address レジスタ( 0x0cf8 )に対して、どのデバ
    イス・バス・機能番号を使うかを書き込む
       –   bit0-1 : 0
       –   bit2-7 :レジスタアドレス
       –   bit8-10 :機能番号
       –   bit11-15 :デバイス番号
       –   bit16-23 :バス番号
       –   bit24-30 : 0
       –   bit31 :データを読み書きするときは 1 に
●
    レジスタアドレスに、読み出したいデータのアドレスを
    セット
PCI デバイスの検索
●
    Configuration レジスタからデータを読む
       –   レジスタの範囲は 0x0cfc 〜 0x0cff
       –   I/O ポートに 0x0cfc を指定して 32bit アクセスすれば
              OK
●
    主なデータ
       –   16 進数は Config Address で指定するレジスタアドレス
       –   ベンダ ID : 0x00 : bit0-15
       –   デバイス ID : 0x00:bit16-31
       –   クラスコード: 0x08 : bit8-31
       –   ヘッダタイプ :0x0c:bit16-23
               ●
                   bit23 :マルチファンクションデバイス
PCI でデバイス検索
HDD の初期化
initialize_ata()
  |--> initialize_common()
  | |--> get_device_type()
  | | |--> do_identify_device()
  | | | |--> do_device_selection_protocol()
  | | | | |--> wait_until_BSY_and_DRQ_are_zero()
  | | | |--> get_DRDY()
  | | | |--> write_command() コマンド 0xec の Write
  | | | |--> wait_until_BSY_is_zero()
  | | | |--> inb() Alternate Status レジスタの Read
  | | | |--> inb() Status レジスタの Read
  | | | |--> is_error()
  | | | |--> is_drq_active()
  | | | |--> is_device_fault()
  | | | |--> inw() データレジスタの Read
HDD の R/W 共通部前半
static bool sector_rw_common(u_int8_t cmd, int device, u_int32_t sector)
{
      ...
      // nIEN bit should be enable and other bits are disable.
      outb(DEVICE_CONTROL_REGISTER, 0x02);

    // Features register should be 0.              LBA 方式で
    outb(FEATURES_REGISTER, 0x00);                アドレスを設定

    // Set Logical Sector.
    outb(SECTOR_NUMBER_REGISTER, sector & 0xff);
    outb(CYLINDER_LOW_REGISTER, (sector >> 8) & 0xff);
    outb(CYLINDER_HIGH_REGISTER, (sector >> 16) & 0xff);
    outb(DEVICE_HEAD_REGISTER, ((sector >> 24) & 0x1f) | 0x40);
    outb(SECTOR_COUNT_REGISTER, 1);
                                               Read:0x20
    // Execute command.                        Write:0x30
    outb(COMMAND_REGISTER, cmd);
HDD の R/W 共通部後半
    wait_loop_usec(4);
                                                  ちょっと待ってから、
inb(ALTERNATE_STATUS_REGISTER);                     データの空読み

read_status_register_again:
    status = inb(STATUS_REGISTER);

      if (is_error(status)) {
             ...
      }

      if (!is_drq_active(status)) {
             if (loop > 5) {                    DRQ ビットがアクティブに
                    ...
             }
                                                     なるまで実行
             loop++;
             goto read_status_register_again;
      }

      return true;
}
HDD の Read 処理
int read_sector(int device, u_int32_t sector,
              sector_t *buf, size_t buf_size)
{
...
      ret = sector_rw_common(PIO_SECTOR_READ_CMD, device, sector);
      if (!ret)
             return -1;

    for (i = 0; i < buf_size; i++)
           buf[i] = inw(DATA_REGISTER);

    finish_sector_rw();                      読み込みが終わったら
                                                終了処理
    return 0;
}
static inline void finish_sector_rw(void)
{
      inb(ALTERNATE_STATUS_REGISTER);
      inb(STATUS_REGISTER);
}
HDD からデータを読む
 00001580 a4 81 01 00 e8 03 e8 03 07 00 00 00 39 11 db 4b |............9..K|
 00001590 39 11 db 4b 39 11 db 4b dd 00 00 00 00 00 00 00 |9..K9..K........|
 000015a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|

 00036400   03 00 2e 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
 00036410   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
 00036420   02 00 2e 2e 00 00 00 00 00 00 00 00 00 00 00 00 |................|
 00036430   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
 00036440   07 00 66 6f 6f 62 61 72 2e 74 78 74 00 00 00 00 |..foobar.txt....|
 00036450   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
 *

 00037400 66 6f 6f 62 61 72 0a 00 00 00 00 00 00 00 00 00 |foobar..........|
 00037410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
mkfs.minix (バージョンは V2 )で作った HDD のイメージで、
 *

/dir_a/dir_b/foobar.txt を読みます。
ダンプの 00001580 が foobar.txt の inode で、
00036440 から始まっているのはディレクトリエントリ、
00037400 から始まっているのが実データです。
HDD からデータを読む
libusb + YUREX
最初に USB デバイスを探します
int Yurex::findDevices() throw (const char *)
{
    int cnt = 0;
    libusb_device **devs;

    cnt = libusb_get_device_list(NULL, &devs);
    if (cnt < 0)
         throw "There are no USB devices";

    setDevices(devs);

    return cnt;
}
libusb + YUREX
bool Yurex::checkYurexDevice() throw (const char *)
{
  libusb_device *dev;
  libusb_device **devs = getDevices();
  int i = 0;
  bool ret = false;

    while ((dev = devs[i++]) != NULL) {
      struct libusb_device_descriptor desc;
      int r = libusb_get_device_descriptor(dev, &desc);
      if (r < 0)
           throw ("failed to get device descriptor");

        if (desc.idVendor == YUREX_VENDOR_ID &&
            desc.idProduct == YUREX_PRODUCT_ID) {
             setDescriptor(desc);
             setDevice(dev);
             ret = true;
             break;
        }
    }                                                     見つかったデバイスから、
    return ret;                                           YUREX があるかをチェック
}
libusb + YUREX
bool Yurex::openYurex()
{
  libusb_device_handle *h;

    h = libusb_open_device_with_vid_pid(NULL,
                getDescriptor()->idVendor,
                getDescriptor()->idProduct);
    if (h)
           setHandle(h);

    clearDeviceList();


}
    return h ? true : false;   YUREX が見つかったら、
                               デバイスをオープン
libusb + YUREX
bool Yurex::claimToYurex()
{
  libusb_device_handle *handle = getHandle();
  int ret;

    ret = libusb_claim_interface(handle, 0);
    if(ret < 0)
         std::cout << "Cannot Claim Interface" << std::endl;

    return ret < 0 ? false : true;
}

                                 YUREX を使えるようにしていきます
libusb + YUREX
void Yurex::findEndPoint()
{
   libusb_config_descriptor *config = getConfig();
   const libusb_interface_descriptor *interdesc;
   const libusb_endpoint_descriptor *epdesc;
   const libusb_interface *inter;
    libusb_get_config_descriptor(getDevice(), 0, &config);
    // Actually, yulex may only have one endpoint.
    for(int i = 0; i < (int) config->bNumInterfaces; i++) {
       inter = &config->interface[i];
        for(int j = 0; j < inter->num_altsetting; j++) {
            interdesc = &inter->altsetting[j];
            for(int k = 0; k < (int) interdesc->bNumEndpoints; k++) {
                epdesc = &interdesc->endpoint[k];
                setEndPoint(epdesc);
            }
        }                               YUREX の設定はこれで終わりです
    }
}
libusb + YUREX
bool Yurex::readDataSync()
{
  unsigned char data[8] = { CMD_PADDING };
  int ret;
  int actual = 0;

    data[0] = CMD_READ;
    data[1] = CMD_EOF;

  ret = libusb_bulk_transfer(getHandle(), getEndPoint()->bEndpointAddress, data, sizeof(data), &actual,
2000);
  if(ret < 0) {
          std::cout << "Reading Error" << std::endl;
  } else {
          std::cout << "Reading Successful!" << std::endl;
          for (int i = 0; i < sizeof(data); i++)
             std::cout << std::hex << std::showbase << (int) data[i] << ":";
          std::cout << std::endl;
  }


    return true;
}

                                          YUREX からデータの読み込み
libusb + YUREX
[masami@moonlight:~/experiment/yurex]% sudo ./yurex
Yurex info
Vendor: 0xc45
Product: 0x1010
Open Yurex device is success
Kernel Driver Active
Kernel Driver Detached!
Claim to Yurex device
ret is 0
Start search endpoint
find endpoint
Number of alternate settings: 0x1 | Interface Number: 0 |
Number of endpoints: 0x1 | Descriptor Type: 0x5 | EP Address: 0x81 |
ret is 0 : actual is 0x8
Writing Successful!
ret is 0 : actual is 0x8
Reading Successful!
0x43:0:0:0:0:0x94:0xd:0:
Done.
ご清聴ありがとうございました
@yojiro さんのプレゼン資料「 OPENBSD
MEETS "YUREX" 」
http://groups.google.com/group/kernelvm
↑ の「第三回 カーネル/ VM 探検隊まとめ」

資料で使用したソースコード
http://github.com/masami256/miko
http://github.com/masami256/yurex
はてなダイアリー
http://d.hatena.ne.jp/masami256/

More Related Content

PDF
x86とコンテキストスイッチ
PDF
プロセスとコンテキストスイッチ
PDF
あるコンテキストスイッチの話
PDF
SystemV IPC
PDF
ラズパイでデバイスドライバを作ってみた。
PDF
Minix smp
PDF
Node-v0.12の新機能について
PDF
C/C++プログラマのための開発ツール
x86とコンテキストスイッチ
プロセスとコンテキストスイッチ
あるコンテキストスイッチの話
SystemV IPC
ラズパイでデバイスドライバを作ってみた。
Minix smp
Node-v0.12の新機能について
C/C++プログラマのための開発ツール

What's hot (20)

PDF
仮想記憶入門 BSD-4.3を例題に
PPTX
そうだったのか! よくわかる process.nextTick() node.jsのイベントループを理解する
PDF
Linuxのプロセススケジューラ(Reading the Linux process scheduler)
PDF
きつねさんでもわかるLlvm読書会 第2回
PDF
V6 unix in okinawa
PDF
PostgreSQL - C言語によるユーザ定義関数の作り方
PPTX
Stream2の基本
PDF
Haswellサーベイと有限体クラスの紹介
KEY
関東GPGPU勉強会 LLVM meets GPU
PDF
Effective modern-c++#9
PDF
effective modern c++ chapeter36
PDF
ゆるバグ
PDF
Deep Dive async/await in Unity with UniTask(UniRx.Async)
PDF
Memory sanitizer
PDF
Ylug 110th kpatch code reading
PDF
Async design with Unity3D
PDF
SpectreとMeltdown:最近のCPUの深い話
PDF
Boost Tour 1.48.0 diff
PDF
ラボユース最終成果報告会(Web公開版)
仮想記憶入門 BSD-4.3を例題に
そうだったのか! よくわかる process.nextTick() node.jsのイベントループを理解する
Linuxのプロセススケジューラ(Reading the Linux process scheduler)
きつねさんでもわかるLlvm読書会 第2回
V6 unix in okinawa
PostgreSQL - C言語によるユーザ定義関数の作り方
Stream2の基本
Haswellサーベイと有限体クラスの紹介
関東GPGPU勉強会 LLVM meets GPU
Effective modern-c++#9
effective modern c++ chapeter36
ゆるバグ
Deep Dive async/await in Unity with UniTask(UniRx.Async)
Memory sanitizer
Ylug 110th kpatch code reading
Async design with Unity3D
SpectreとMeltdown:最近のCPUの深い話
Boost Tour 1.48.0 diff
ラボユース最終成果報告会(Web公開版)
Ad

Viewers also liked (20)

PDF
πολλαπλασιασμοι ενοτητα 11
PDF
とある帽子の大蛇料理Ⅱ
PPTX
Bish Bash Bosh & Co
PDF
あなたの知らないネットワークプログラミングの世界
PDF
100Gbpsソフトウェアルータの実現可能性に関する論文
PDF
User-space Network Processing
PDF
xv6のコンテキストスイッチを読む
PDF
I/O仮想化最前線〜ネットワークI/Oを中心に〜
PDF
Disruptive IP Networking with Intel DPDK on Linux
PDF
クラウド環境におけるキャッシュメモリQoS制御の評価
PDF
クラウドの垣根を超えた高性能計算に向けて~AIST Super Green Cloudでの試み~
PDF
DPDKを拡張してみた話し
PDF
OSvの概要と実装
PDF
Xeon dとlagopusと、pktgen dpdk
PDF
Dpdk環境の話
PDF
OSv at Cassandra Summit
PDF
OSvのご紹介 in 
Java 8 HotSpot meeting
PDF
OSvのご紹介 in OSC2014 Tokyo/Fall
PDF
OSv噺
PPTX
Seastar:高スループットなサーバアプリケーションの為の新しいフレームワーク
πολλαπλασιασμοι ενοτητα 11
とある帽子の大蛇料理Ⅱ
Bish Bash Bosh & Co
あなたの知らないネットワークプログラミングの世界
100Gbpsソフトウェアルータの実現可能性に関する論文
User-space Network Processing
xv6のコンテキストスイッチを読む
I/O仮想化最前線〜ネットワークI/Oを中心に〜
Disruptive IP Networking with Intel DPDK on Linux
クラウド環境におけるキャッシュメモリQoS制御の評価
クラウドの垣根を超えた高性能計算に向けて~AIST Super Green Cloudでの試み~
DPDKを拡張してみた話し
OSvの概要と実装
Xeon dとlagopusと、pktgen dpdk
Dpdk環境の話
OSv at Cassandra Summit
OSvのご紹介 in 
Java 8 HotSpot meeting
OSvのご紹介 in OSC2014 Tokyo/Fall
OSv噺
Seastar:高スループットなサーバアプリケーションの為の新しいフレームワーク
Ad

Similar to デバドラを書いてみよう! (20)

PDF
V6 unix vol.2 in okinawa
PDF
あるmmapの話
PDF
Androidの入力システム
PDF
cdev_write and_comwrite
PPTX
あなたのAppleにもEFIモンスターはいませんか? by Pedro Vilaça - CODE BLUE 2015
PDF
PDF
【学習メモ#3rd】12ステップで作る組込みOS自作入門
PDF
2011.06.11 v7から始めるunix まとめ
PDF
Altera SDK for OpenCL解体新書 : ホストとデバイスの関係
PDF
Python physicalcomputing
PPTX
イチからはじめるUSB Host API
PDF
[Basic 7] OS の基本 / 割り込み / システム コール / メモリ管理
KEY
DE0でラジコンカー作ってみた 関西de0 fpga勉強会20120519
PDF
PF部第19回資料 poor man's JTAG
PDF
BHyVeでOSvを起動したい
〜BIOSがなくてもこの先生きのこるには〜
PPTX
Androidとfpgaを高速fifo通信させちゃう
PDF
2011.09.18 v7から始めるunix まとめ
PDF
Bluetooth通信の 仕組みと活用法紹介
PDF
retrobsd-2012-JUL-07 at JNUG BSD BoF
PDF
FPGA startup 第一回 LT
V6 unix vol.2 in okinawa
あるmmapの話
Androidの入力システム
cdev_write and_comwrite
あなたのAppleにもEFIモンスターはいませんか? by Pedro Vilaça - CODE BLUE 2015
【学習メモ#3rd】12ステップで作る組込みOS自作入門
2011.06.11 v7から始めるunix まとめ
Altera SDK for OpenCL解体新書 : ホストとデバイスの関係
Python physicalcomputing
イチからはじめるUSB Host API
[Basic 7] OS の基本 / 割り込み / システム コール / メモリ管理
DE0でラジコンカー作ってみた 関西de0 fpga勉強会20120519
PF部第19回資料 poor man's JTAG
BHyVeでOSvを起動したい
〜BIOSがなくてもこの先生きのこるには〜
Androidとfpgaを高速fifo通信させちゃう
2011.09.18 v7から始めるunix まとめ
Bluetooth通信の 仕組みと活用法紹介
retrobsd-2012-JUL-07 at JNUG BSD BoF
FPGA startup 第一回 LT

More from Masami Ichikawa (6)

PPTX
Linux debug
PDF
Linux Namespaces
PDF
Slub alloc and free
PDF
Slub data structure
PDF
Linux Namespace
PDF
Gnomeとdogtai
Linux debug
Linux Namespaces
Slub alloc and free
Slub data structure
Linux Namespace
Gnomeとdogtai

デバドラを書いてみよう!

  • 1. デバイスドライバを作ってみよう! 第 4 回 カーネル/ VM 探検隊 2010/05/08 @masami256
  • 2. 何でデバドラを作るの? ● 愛用している OS にドライバがな い ● 自作 OS でデバイスを使いたい
  • 3. ドライバ作成の準備 ● 資料を揃える – メジャーなデバイスだと、 TECH I が便利 ● ドライバを書きたい OS の作法を調べる – Linux, OpenBSD, Plan 9 and so forth ● ユーザランドで実装できる場合もある – USB デバイスなら libusb が使える ● 実装方法を考える
  • 5. PCI デバイスの検索 ● 下記 3 個の組み合わせを総当たりで – デバイス番号 0 〜 7 – バス番号 0 〜 31 – 機能番号 0 〜 7 ● 機能番号が 0 のデバイスの場合の注意 – コンフィギュレーションレジスタからヘッダタ イプを読み込む – マルチファンクションか調べる – マルチファンクションで無ければ、機能番号 1 〜 7 にはデバイスはなし
  • 6. PCI デバイスの検索 ● Config Address レジスタ( 0x0cf8 )に対して、どのデバ イス・バス・機能番号を使うかを書き込む – bit0-1 : 0 – bit2-7 :レジスタアドレス – bit8-10 :機能番号 – bit11-15 :デバイス番号 – bit16-23 :バス番号 – bit24-30 : 0 – bit31 :データを読み書きするときは 1 に ● レジスタアドレスに、読み出したいデータのアドレスを セット
  • 7. PCI デバイスの検索 ● Configuration レジスタからデータを読む – レジスタの範囲は 0x0cfc 〜 0x0cff – I/O ポートに 0x0cfc を指定して 32bit アクセスすれば OK ● 主なデータ – 16 進数は Config Address で指定するレジスタアドレス – ベンダ ID : 0x00 : bit0-15 – デバイス ID : 0x00:bit16-31 – クラスコード: 0x08 : bit8-31 – ヘッダタイプ :0x0c:bit16-23 ● bit23 :マルチファンクションデバイス
  • 9. HDD の初期化 initialize_ata() |--> initialize_common() | |--> get_device_type() | | |--> do_identify_device() | | | |--> do_device_selection_protocol() | | | | |--> wait_until_BSY_and_DRQ_are_zero() | | | |--> get_DRDY() | | | |--> write_command() コマンド 0xec の Write | | | |--> wait_until_BSY_is_zero() | | | |--> inb() Alternate Status レジスタの Read | | | |--> inb() Status レジスタの Read | | | |--> is_error() | | | |--> is_drq_active() | | | |--> is_device_fault() | | | |--> inw() データレジスタの Read
  • 10. HDD の R/W 共通部前半 static bool sector_rw_common(u_int8_t cmd, int device, u_int32_t sector) { ... // nIEN bit should be enable and other bits are disable. outb(DEVICE_CONTROL_REGISTER, 0x02); // Features register should be 0. LBA 方式で outb(FEATURES_REGISTER, 0x00); アドレスを設定 // Set Logical Sector. outb(SECTOR_NUMBER_REGISTER, sector & 0xff); outb(CYLINDER_LOW_REGISTER, (sector >> 8) & 0xff); outb(CYLINDER_HIGH_REGISTER, (sector >> 16) & 0xff); outb(DEVICE_HEAD_REGISTER, ((sector >> 24) & 0x1f) | 0x40); outb(SECTOR_COUNT_REGISTER, 1); Read:0x20 // Execute command. Write:0x30 outb(COMMAND_REGISTER, cmd);
  • 11. HDD の R/W 共通部後半 wait_loop_usec(4); ちょっと待ってから、 inb(ALTERNATE_STATUS_REGISTER); データの空読み read_status_register_again: status = inb(STATUS_REGISTER); if (is_error(status)) { ... } if (!is_drq_active(status)) { if (loop > 5) { DRQ ビットがアクティブに ... } なるまで実行 loop++; goto read_status_register_again; } return true; }
  • 12. HDD の Read 処理 int read_sector(int device, u_int32_t sector, sector_t *buf, size_t buf_size) { ... ret = sector_rw_common(PIO_SECTOR_READ_CMD, device, sector); if (!ret) return -1; for (i = 0; i < buf_size; i++) buf[i] = inw(DATA_REGISTER); finish_sector_rw(); 読み込みが終わったら 終了処理 return 0; } static inline void finish_sector_rw(void) { inb(ALTERNATE_STATUS_REGISTER); inb(STATUS_REGISTER); }
  • 13. HDD からデータを読む 00001580 a4 81 01 00 e8 03 e8 03 07 00 00 00 39 11 db 4b |............9..K| 00001590 39 11 db 4b 39 11 db 4b dd 00 00 00 00 00 00 00 |9..K9..K........| 000015a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00036400 03 00 2e 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00036410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00036420 02 00 2e 2e 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00036430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00036440 07 00 66 6f 6f 62 61 72 2e 74 78 74 00 00 00 00 |..foobar.txt....| 00036450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00037400 66 6f 6f 62 61 72 0a 00 00 00 00 00 00 00 00 00 |foobar..........| 00037410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| mkfs.minix (バージョンは V2 )で作った HDD のイメージで、 * /dir_a/dir_b/foobar.txt を読みます。 ダンプの 00001580 が foobar.txt の inode で、 00036440 から始まっているのはディレクトリエントリ、 00037400 から始まっているのが実データです。
  • 15. libusb + YUREX 最初に USB デバイスを探します int Yurex::findDevices() throw (const char *) { int cnt = 0; libusb_device **devs; cnt = libusb_get_device_list(NULL, &devs); if (cnt < 0)   throw "There are no USB devices"; setDevices(devs); return cnt; }
  • 16. libusb + YUREX bool Yurex::checkYurexDevice() throw (const char *) { libusb_device *dev; libusb_device **devs = getDevices(); int i = 0; bool ret = false; while ((dev = devs[i++]) != NULL) { struct libusb_device_descriptor desc; int r = libusb_get_device_descriptor(dev, &desc); if (r < 0) throw ("failed to get device descriptor"); if (desc.idVendor == YUREX_VENDOR_ID && desc.idProduct == YUREX_PRODUCT_ID) { setDescriptor(desc); setDevice(dev); ret = true; break; } } 見つかったデバイスから、 return ret; YUREX があるかをチェック }
  • 17. libusb + YUREX bool Yurex::openYurex() { libusb_device_handle *h; h = libusb_open_device_with_vid_pid(NULL, getDescriptor()->idVendor, getDescriptor()->idProduct); if (h)     setHandle(h); clearDeviceList(); } return h ? true : false; YUREX が見つかったら、 デバイスをオープン
  • 18. libusb + YUREX bool Yurex::claimToYurex() { libusb_device_handle *handle = getHandle(); int ret; ret = libusb_claim_interface(handle, 0); if(ret < 0) std::cout << "Cannot Claim Interface" << std::endl; return ret < 0 ? false : true; } YUREX を使えるようにしていきます
  • 19. libusb + YUREX void Yurex::findEndPoint() { libusb_config_descriptor *config = getConfig(); const libusb_interface_descriptor *interdesc; const libusb_endpoint_descriptor *epdesc; const libusb_interface *inter; libusb_get_config_descriptor(getDevice(), 0, &config); // Actually, yulex may only have one endpoint. for(int i = 0; i < (int) config->bNumInterfaces; i++) { inter = &config->interface[i]; for(int j = 0; j < inter->num_altsetting; j++) { interdesc = &inter->altsetting[j]; for(int k = 0; k < (int) interdesc->bNumEndpoints; k++) { epdesc = &interdesc->endpoint[k]; setEndPoint(epdesc); } } YUREX の設定はこれで終わりです } }
  • 20. libusb + YUREX bool Yurex::readDataSync() { unsigned char data[8] = { CMD_PADDING }; int ret; int actual = 0; data[0] = CMD_READ; data[1] = CMD_EOF; ret = libusb_bulk_transfer(getHandle(), getEndPoint()->bEndpointAddress, data, sizeof(data), &actual, 2000); if(ret < 0) {    std::cout << "Reading Error" << std::endl; } else {    std::cout << "Reading Successful!" << std::endl; for (int i = 0; i < sizeof(data); i++) std::cout << std::hex << std::showbase << (int) data[i] << ":"; std::cout << std::endl; } return true; } YUREX からデータの読み込み
  • 21. libusb + YUREX [masami@moonlight:~/experiment/yurex]% sudo ./yurex Yurex info Vendor: 0xc45 Product: 0x1010 Open Yurex device is success Kernel Driver Active Kernel Driver Detached! Claim to Yurex device ret is 0 Start search endpoint find endpoint Number of alternate settings: 0x1 | Interface Number: 0 | Number of endpoints: 0x1 | Descriptor Type: 0x5 | EP Address: 0x81 | ret is 0 : actual is 0x8 Writing Successful! ret is 0 : actual is 0x8 Reading Successful! 0x43:0:0:0:0:0x94:0xd:0: Done.
  • 22. ご清聴ありがとうございました @yojiro さんのプレゼン資料「 OPENBSD MEETS "YUREX" 」 http://groups.google.com/group/kernelvm ↑ の「第三回 カーネル/ VM 探検隊まとめ」 資料で使用したソースコード http://github.com/masami256/miko http://github.com/masami256/yurex はてなダイアリー http://d.hatena.ne.jp/masami256/