moshからEthernetパケットを送信する

next : http://d.hatena.ne.jp/mjt/20090413/p1
冷静に考えると既にskymoshはUSBデバイスを扱えるので、USB Ethernet NICを使えば(libpcapが無くても)普通にEthernetパケットが送信できるのであった。

MACアドレスとして、ASCIIで"MOSH"を入れたのでパケットダンプでそれを観察できる。
今回は、たまたま手元にLUA-KTXが余ってたのでそれを使った。
受信も多分問題なく出来る(skymoshには既にスレッドも有る)ので、今後、IPv4ARPTCPDNSと実装を進めてみることにする。

(import (rnrs)
        (skymosh usb-internals))

(define myaddr #vu8(#x02 #x00 #x4d #x4f #x53 #x48))
(define BCAST #vu8(#xff #xff #xff #xff #xff #xff))

(define (ether-packet to from type data)
  (define (ether-size data) (max 65 (+ (bytevector-length data) 6 6 2)))
  (let ((bv (make-bytevector (ether-size data))))
    (bytevector-copy! to 0 bv 0 6)
    (bytevector-copy! from 0 bv 6 6)
    (bytevector-u16-set! bv 12 type (endianness big))
    (bytevector-copy! data 0 bv 14 (bytevector-length data))
    bv))

(define (rtl8150-regwrite-8! d r b)
  (let ((bv (make-bytevector 1)))
    (bytevector-u8-set! bv 0 b)
    (%usb-control-msg! d #x40 5 r 0 bv 0 1)))

(define (rtl8150-regread-8 d r)
  (let ((bv (make-bytevector 1)))
    (%usb-control-msg! d #xc0 5 r 0 bv 0 1)
    (bytevector-u8-ref bv 0)))

(define (main)
  (define d (%usb-open-device0 #x411 #x12))
  (define (cmd-set-and-wait c)
    (rtl8150-regwrite-8! d #x12e c)
    (letrec ((myloop
               (lambda ()
                 (let ((b (rtl8150-regread-8 d #x12e)))
                   (cond ((not (= 0 (bitwise-and c b))) (myloop)))))))
      (myloop)))
  (define (wait-link)
    (define buf (make-bytevector 8))
    (%usb-interrupt-read! d #x83 buf 0 8)
    (let ((s (bytevector-u8-ref buf 2)))
      (if (= 0 (bitwise-and s 4)) (wait-link))))

  (%usb-set-configuration! d 1)
  (%usb-claim-interface! d 0)
  ;;NIC init
  (cmd-set-and-wait 16) ;RESET
  (cmd-set-and-wait 1)  ;AUTOLOAD
  (rtl8150-regwrite-8! d #x12e 12) ;RE+TE
  ;;send packet
  (let* ((type 0)
         (data #vu8(#x45 0 0 0 0 0 0 0 0 0))
         (p (ether-packet BCAST myaddr type data)))
    (letrec ((loop (lambda ()
                     (wait-link)
                     (%usb-bulk-write! d 2 p 0 (bytevector-length p))
                     (loop))))
      (loop))))

(main)