USBディバイスはMbed を使いました。
参考サイト:kshoji:自作のUSBデバイスを、Androidで動かす
参考サイトに詳細に解説されています。
参考サイトの一部必要な所だけ取り出してみました。
とりあえず、Mbed に送信してLED4を点灯させてみる。
点灯と消灯の二つのボタンを置いて操作する。
USBディバイスを接続した時に使うアプリを聞いてくる。
回路図:アンドロイドとUSBホストケーブルで接続する
Mbed のソースコード:参考サイトのソースコードをそのまま使いました。
#include "mbed.h" #include "USBHID.h" // device USBHID hid; // read HID_REPORT recv; BusOut leds(LED1, LED2, LED3, LED4); // write HID_REPORT send; AnalogIn input(p15); int main(void) { int lastData = 0; int currentData; send.length = 64; while (1) { // read hid.readNB(&recv); if (recv.length > 0) { leds = recv.data[0]; } currentData = input.read_u16(); if (currentData != lastData) { lastData = currentData; // write send.data[0] = (currentData >> 8) & 0xff; send.data[1] = currentData & 0xff; //hid.send(&send); } } }
アンドロイドアプリのソースコード
エラー処理や例外・終了処理は考慮していない。
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.hidtest002" android:installLocation="preferExternal" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="12" android:targetSdkVersion="17" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.example.hidtest002.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> </intent-filter> <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" android:resource="@xml/device_filter" /> </activity> </application> </manifest>
res/xml/device_filter.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <!-- Interface class: USB HID --> <usb-device class="3" subclass="0" protocol="0" /> </resources>
MainActivity.java
package com.example.hidtest002; import android.hardware.usb.UsbConstants; import android.hardware.usb.UsbDevice; import android.hardware.usb.UsbDeviceConnection; import android.hardware.usb.UsbEndpoint; import android.hardware.usb.UsbInterface; import android.hardware.usb.UsbManager; import android.os.Bundle; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class MainActivity extends Activity implements OnClickListener { private static final String TAG = "HidTest"; private TextView text; private UsbDeviceConnection deviceConnection = null; private UsbEndpoint outputEndpoint2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); text = (TextView) findViewById(R.id.textView1); // ボタンがクリックされた時の処理 Button btn1 = (Button) findViewById(R.id.button1); btn1.setOnClickListener(this); Button btn2 = (Button) findViewById(R.id.button2); btn2.setOnClickListener(this); // USB ディバイスが接続されていない時は終了 if (!UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(getIntent().getAction())) { finish(); } else { // USB ディバイスを接続 Intent intent = getIntent(); UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); if (device != null) { Log.v(TAG, "UsbDevice がある"); UsbInterface usbInterface = findUsbInterface(device); if (usbInterface != null) { // アタッチ UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE); deviceConnection = usbManager.openDevice(device); deviceConnection.claimInterface(usbInterface, true); } } } } /* * UsbInterface の確認 */ private UsbInterface findUsbInterface(UsbDevice device) { // TODO 自動生成されたメソッド・スタブ text.setText("UsbDevice.getDeviceName():" + device.getDeviceName() + "\n"); int count = device.getInterfaceCount();// 4 text.append("UsbDevice.getInterfaceCount():" + count + "\n"); for (int i = 0; i < count; i++) { UsbInterface usbInterface = device.getInterface(i); UsbEndpoint inputEndpoint = null; UsbEndpoint outputEndpoint = null; text.append("**************************" + "\n"); text.append(" UsbInterface.getEndpointCount():" + usbInterface.getEndpointCount() + "\n"); if (usbInterface.getEndpointCount() >= 1) { for (int endpointIndex = 0; endpointIndex < usbInterface.getEndpointCount(); endpointIndex++) { UsbEndpoint endpoint = usbInterface.getEndpoint(endpointIndex); text.append(endpointIndex + ":"); if ((endpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK || endpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_INT)) { if (endpoint.getDirection() == UsbConstants.USB_DIR_OUT) { outputEndpoint = outputEndpoint == null ? endpoint : outputEndpoint; outputEndpoint2 = endpoint; text.append(" UsbEndpoint:getDirection()" + endpoint.getDirection() + "\n");// USB_DIR_OUT } } } if (inputEndpoint != null || outputEndpoint != null) { return usbInterface; } } } return null; } /* * ボタンが押された時の処理 */ @Override public void onClick(View v) { // TODO 自動生成されたメソッド・スタブ byte data1 = 0; byte data2 = 0; byte data3 = 0; byte data4 = 0; switch (v.getId()) { case R.id.button1: Log.i("buttonTest", "点灯ボタンが押された"); data1 = 0; data2 = 0; data3 = 0; data4 = (byte) 8; break; case R.id.button2: Log.i("buttonTest", "消灯ボタンが押された"); data1 = 0; data2 = 0; data3 = 0; data4 = 0; break; } outPutMbed(new byte[] { (byte) (data1 | data2 | data3 | data4) }); } // Mbed に送信 private void outPutMbed(byte[] bytes) { // TODO 自動生成されたメソッド・スタブ final int maxPacketSize = outputEndpoint2.getMaxPacketSize(); for (int i = 0; i < bytes.length; i += maxPacketSize) { byte[] writeBuffer = new byte[maxPacketSize]; int length = (bytes.length - i) < writeBuffer.length ? bytes.length - i : writeBuffer.length; System.arraycopy(bytes, i, writeBuffer, 0, length); deviceConnection.bulkTransfer(outputEndpoint2, writeBuffer, writeBuffer.length, 0); } } /* * メニューの処理 */ @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.itemFinish: Log.v(TAG, "finish"); finish(); return true; } return false; } }
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="点灯" /> <Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="消灯" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" /> </LinearLayout> </LinearLayout> </RelativeLayout>