JavaからUSBランプを光らせてみる(DL100B Dream Cheeky Generic Controller編)

2013/2/14追記: WindowsサービスでWebmail Notifierを制御するユーティリティを作ったけど半年以上忘れてたので紹介 - ka-ka_xyzの日記


前回、単色でしか発光しないWebMail Notifierを掴んでしまい、あわてて三色発光するタイプのものを買ったのですが、新たな問題が発生しました。

USBポートに接続すると、デバイス名が

DL100B Dream Cheeky Generic Controller

となっています。また、ベンダIDやプロダクトIDが前回使用したWebMail Notifierとは異なっていました、さらにlibusb-win32を使用してinfファイルを生成し、testlibusb-win.exe(libusb-win32の詳細と導入方法については前回の記事を参照)を実行してみると、USBデバイスの情報は下記のような結果となりました。

DLL version: 1.2.6.0
Driver version: 1.2.6.0

bus/device idVendor/idProduct
bus-0/\\.\libusb0-0001--0x1d34-0x0004 1D34/0004

  • Manufacturer : Dream Link
  • Product : DL100B Dream Cheeky Generic Controller

bLength: 18
bDescriptorType: 01h
bcdUSB: 0110h
bDeviceClass: 00h
bDeviceSubClass: 00h
bDeviceProtocol: 00h
bMaxPacketSize0: 08h
idVendor: 1D34h
idProduct: 0004h
bcdDevice: 0002h
iManufacturer: 1
iProduct: 2
iSerialNumber: 0
bNumConfigurations: 1
wTotalLength: 34
bNumInterfaces: 1
bConfigurationValue: 1
iConfiguration: 0
bmAttributes: 80h
MaxPower: 250
bInterfaceNumber: 0
bAlternateSetting: 0
bNumEndpoints: 1
bInterfaceClass: 3
bInterfaceSubClass: 0
bInterfaceProtocol: 0
iInterface: 0
bEndpointAddress: 81h
bmAttributes: 03h
wMaxPacketSize: 8
bInterval: 10
bRefresh: 0
bSynchAddress: 0

前回のUSBデバイスは、エンドポイント(bEndpointAddress)の情報を、入力用および出力用の2つについて取得できていたのですが、今回のデバイス(DL100B Dream Cheeky Generic Controller)ではエンドポイント(in)の情報しか取得できません。
また、前回のソースではUSBライトをOn/Offするためにエンドポイントの情報が必要でしたが、今回はエンドポイント自体が存在していないようなので、ちょっと別のメソッドを叩く必要があります。

とりあえずサンプルソース。

import ch.ntb.usb.Device;
import ch.ntb.usb.USB;
import ch.ntb.usb.USBException;

public class UsbMain {
	
	Device dev = null;
	
	public static void main(String[] args){
		UsbMain usbMain = new UsbMain();
		usbMain.firstLight();
	}
	
	public UsbMain(){
		/*
		 * testlibusb-win.exe実行結果にあるベンダIDとプロダクトIDでUSBデバイスを指定
		 * ベンダID: 0x1d34
		 * プロダクトID: 0x0004
		 * */
		dev = USB.getDevice((short) 0x1d34, (short) 0x0004);
	}
	
	public void firstLight(){
		if(dev == null){
			System.out.println("failed to open USB device!");
			System.exit(1);
		}
		try {
			dev.open(1, 0, -1);
			
			//初期化
			send(new byte[]{ 0x1f, 0x02, 0x00, 0x2e, 0x00, 0x00, 0x2b, 0x03 });
			send(new byte[]{ 0x00, 0x02, 0x00, 0x2e, 0x00, 0x00, 0x2b, 0x04 });
			
			
			//赤色
			send(new byte[]{0x0f,  0x00,  0x00,  0x00,  0x00,  0x00, 0x00, 0x05});
			sleep(1000);
			//緑色
			send(new byte[]{0x00,  0x0f,  0x00,  0x00,  0x00,  0x00, 0x00, 0x05});
			sleep(1000);
			//青緑〜黄色
			send(new byte[]{0x0f,  0x0f,  0x00,  0x00,  0x00,  0x00, 0x00, 0x05});
			sleep(1000);
			//青色
			send(new byte[]{0x00,  0x00,  0x0f,  0x00,  0x00,  0x00, 0x00, 0x05});
			sleep(1000);
			//紫色
			send(new byte[]{0x0f,  0x00,  0x0f,  0x00,  0x00,  0x00, 0x00, 0x05});
			sleep(1000);
			//水色
			send(new byte[]{0x00,  0x0f,  0x0f,  0x00,  0x00,  0x00, 0x00, 0x05});
			sleep(1000);
			//白
			send(new byte[]{0x0f,  0x0f,  0x0f,  0x00,  0x00,  0x00, 0x00, 0x05});
			sleep(1000);
			//Light Off
			send(new byte[]{0x00,  0x00,  0x00,  0x00,  0x00,  0x00, 0x00, 0x05});
			
			dev.close();
			
		} catch (USBException e) {
			e.printStackTrace();
		}
		
	}
	
	/**
	 * USBデバイスへ信号を送信
	 * @param signal 信号を表すバイト配列.
	 * */
	private void send(byte[] signal) throws USBException{
		dev.controlMsg(
			USB.REQ_TYPE_DIR_HOST_TO_DEVICE |  
                	USB.REQ_TYPE_TYPE_CLASS |  
                	USB.REQ_TYPE_RECIP_INTERFACE,  
			0x09, 0x0200, 0, 
			signal, signal.length, 2000, false);
	}

	/**
	 * 一定時間待機
	 * @param i 待機時間(ms).
	 * */
	private void sleep(long i){
		try {
			Thread.sleep(i);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

取り敢えず、長さ8のバイト配列の内先頭3つ分が各LEDランプに対応するようです。値は各LEDの発光強度を示しますが、"0xff"とかに設定しても"0x0f"と強度は同じのようです。天井がどのへんなのかは不明。