5 years, 6 months ago.

mbedのUSB CDCクラスとAndroidのUSBシリアルドライバとの通信について

Androidのusb-serial-for-androidライブラリhttps://github.com/mik3y/usb-serial-for-androidと、 Mbed(STM32F303REボード改)のUSB CDCを組み合わせた通信がうまくいきません。 当初はAndroid側のポートオープン時のパーミッション取得ができておらず、オープンに失敗していたのですが、 これをクリアしたもののAndroid側でwriteするとwriteが失敗します。 (numBytesWrite に-1が返る)

下記、汚い初心者テストコードで申し訳ないのですが、test_send()中、writeに失敗する原因は何が考えられますか? (write中、bulkTransferが失敗します。タイムアウトしているようです。)

Android側コード:

wrong code

public class DeviceWaiting extends AppCompatActivity {

    private final String TAG = MainActivity.class.getSimpleName();

    private UsbManager mUsbManager;
    private TextView mProgressBarTitle;
    private ProgressBar mProgressBar;
    private List<UsbSerialDriver> drivers;

    private static String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";

    PendingIntent mPermissionIntent;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_devicewaiting);

        mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
        mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
        mProgressBarTitle = (TextView) findViewById(R.id.progressBarTitle);

        mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(
                ACTION_USB_PERMISSION), 0);
        IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);

        registerReceiver(UsbReciever, filter);

        waitDevice();
    }

    @Override
    protected void onResume() {
        super.onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
    }

    private void waitDevice() {
        showProgressBar();

        new AsyncTask<Void, Void, Integer>() {
            @Override
            protected Integer doInBackground(Void... params) {

                while(true) {
                    SystemClock.sleep(1000);

                    drivers = UsbSerialProber.getDefaultProber().findAllDrivers(mUsbManager);

                    if (!drivers.isEmpty()) {
                        return 0;
                    }
                }
            }

            @Override
            protected void onPostExecute(Integer dummy) {
                mProgressBarTitle.setText(
                        String.format("USBが接続されました"));
                hideProgressBar();
                getPermission();
            }

        }.execute((Void) null);
    }

    private void showProgressBar() {
        mProgressBar.setVisibility(View.VISIBLE);
        mProgressBarTitle.setText("USBの接続を待っています...");
    }

    private void hideProgressBar() {
        mProgressBar.setVisibility(View.INVISIBLE);
    }

    private void showMainActivity() {
//            MainActivity.show(this, port);
        MainActivity.show(this);
    }

    private void getPermission() {
        List<UsbSerialDriver> availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(mUsbManager);

        UsbSerialDriver driver = availableDrivers.get(0);

        mUsbManager.requestPermission(driver.getDevice(), mPermissionIntent);
    }

    private final BroadcastReceiver UsbReciever = new BroadcastReceiver() {

        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (ACTION_USB_PERMISSION.equals(action)) {
                synchronized (this) {
                    UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);

                    if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                        if(device != null){
                            //showMainActivity();
                            test_send();
                        }
                    }
                    else {
                        Log.d(TAG, "permission denied for device " + device);
                    }
                }
            }
        }
    };

    private void test_send()
    {
        UsbSerialDriver driver = drivers.get(0);
        UsbDeviceConnection connection = mUsbManager.openDevice(driver.getDevice());
        if (connection == null) {
            return;
        }

        UsbSerialPort port = driver.getPorts().get(0);
        try {
            port.open(connection);
            port.setParameters(9600, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);  //ここまではエラー無し
            port.setDTR(true);  //これはmbed側に伝わっており、mbed側のusb_serial.connected()はtrueになります

            String buffer = "test\r\n";
            int numBytesWrite = port.write(buffer.getBytes(), 1000); //numBytesWriteは-1が返ります

        } catch (IOException e) {
        } finally {
        }

    }
}

試したこと:

  • Android上で動くターミナルソフト(Serial USB Terminal)でデータ送信、Mbed側で受信OK。
  • FT232が載ったUSBシリアルアダプタでは、このソフトでwrite成功。
  • Windows10(TeraTerm)→MbedはOK。
  • macOS10.13.5(screen)→MbedはOK。

→これらより、何が悪いのかサッパリわかりません・・・

遅くなりましたが、自己解決です。 ライブラリ内でエンドポイントに書き込むときに、対象のエンドポイントが間違えていました。 暫定的にライブラリ直したらうまく通信できました。

posted by Jun Yamaguchi 02 Mar 2019
Be the first to answer this question.