0

I'm new to android programming and my project needs serial communication with an arduino board. I began with building my very first project by importing the source code of ArduinoUSB.

In this code, I have use the android device in OTG mode and the arduino board is connected as a slave. It implements a pseudo serial device. I rather easily succeeded to communicate on a wiko smartphone (android 5.1), but I am unable to have it run on a ezeepad 785 tablet running android 4.1.1.

I initially thought the tablet did not support OTG, but actually this is not the case, for if I have connect a memory stick on the tablet through a OTG cable, I can see the files in the stick.

However, whereas on my wiko phone, when I have connect the arduino board for the first time, I got the dialog "open ArduinoUSB on connection of this usb device?", this never happens on my tablet.

To investigate, I added printout statements in the code to show what methods are activated on connection of the arduino board.

Here again, on the wiko phone I see on the screen my messages signalling that the broadcast message was received, the VID of the arduino board, etc. When I run the same code on the tablet, nothing happens. No evidence of a broadcast message on connection of the arduino board.

I have installed the USB OTG checker application from the play store, and again, this app shows my arduino board connected on the wiko phone, and nothing connected on the tablet.

Is it possible that the tablet implements a partial OTG function that only supports a memory stick, and even hide it to another application? for on my wiko phone, if I connect a memory stick, I can read the VID of the stick on the screen thanks to the extra prints I added in the code. This does not happen on the tablet.

I am at my wit's end...

Abhinav Gupta
  • 2,225
  • 1
  • 14
  • 30
Phono
  • 1
  • 3
  • Does your Arduino get power up when you connect it to the tablet? – TheEngineer Mar 03 '18 at 23:38
  • Yes it does ! as well as the memory stick. – Phono Mar 03 '18 at 23:55
  • Can you post your code when you check for your broadcast receiver and also the part that you check for USB id ? – TheEngineer Mar 03 '18 at 23:58
  • Th reason I am asking is that there should be a part in the code where you check for "Device Id" like this: "if (deviceVID != 0x1d6b && (devicePID != 0x0001 && devicePID != 0x0002 && devicePID != 0x0003)". I realized my device ID kept changing everytime so I got rid of that line and everything worked out. You can make a toast that print your device id when you connect the Arduino to see if the device id is what you are checking for. – TheEngineer Mar 04 '18 at 00:03

3 Answers3

0

Here is the code. Please do not mind its being "quick and dirty" ! :

private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { //Broadcast Receiver to automatically start and stop the Serial connection.
    @Override
    public void onReceive(Context context, Intent intent) {
            tvAppend(textView,"BROADCAST RECEIVER\r\n");
        if (intent.getAction().equals(ACTION_USB_PERMISSION)) {
            boolean granted = intent.getExtras().getBoolean(UsbManager.EXTRA_PERMISSION_GRANTED);
            if (granted) {
                connection = usbManager.openDevice(device);
                serialPort = UsbSerialDevice.createUsbSerialDevice(device, connection);
                if (serialPort != null) {
                    if (serialPort.open()) { //Set Serial Connection Parameters.
                        setUiEnabled(true);
                        serialPort.setBaudRate(9600);
                        serialPort.setDataBits(UsbSerialInterface.DATA_BITS_8);
                        serialPort.setStopBits(UsbSerialInterface.STOP_BITS_1);
                        serialPort.setParity(UsbSerialInterface.PARITY_NONE);
                        serialPort.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF);
                        serialPort.read(mCallback);
                        tvAppend(textView,"Serial Connection Opened!\n");

                    } else {
                        tvAppend(textView,"SERIAL PORT NOT OPEN");
                    }
                } else {
                    tvAppend(textView,"SERIAL PORT IS NULL");
                }
            } else {
                tvAppend(textView,"SERIAL PERM NOT GRANTED");
            }
        } else if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
            onClickStart(startButton);
        } else if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_DETACHED)) {
            onClickStop(stopButton);
        } else tvAppend(textView,"UNKNOWN ACTION");
    }

    ;
};

as you can see, on any broadcast message a sentence is printed in the textview component. If the message is a usb permission, this code calls in turn the following code:

public void onClickStart(View view) {

    HashMap<String, UsbDevice> usbDevices = usbManager.getDeviceList();
    if (!usbDevices.isEmpty()) {
        boolean keep = true;
        for (Map.Entry<String, UsbDevice> entry : usbDevices.entrySet()) {
            device = entry.getValue();
            int deviceVID = device.getVendorId();
            if (deviceVID == 0x1EAF)//Maple R3   Vendor ID
            {
                int devicePID = device.getProductId() ; // Le PID du BSL est 3
                if ( devicePID == 4 ) {                 // Le PID du port série émulé est 4
                    tvAppend(textView, "\ndevice PID : " + devicePID + "\n");

                    PendingIntent pi = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
                    usbManager.requestPermission(device, pi);
                    keep = false;
                }
            } else {
                tvAppend(textView, "\ndevice VID : " + deviceVID + "\n");
                connection = null;
                device = null;
            }

            if (!keep)
                break;
        }
    }
else
    tvAppend(textView, "\nPas de réponse" + "\n");


}

where the VID and the PID are checked and messages are printed accordingly. Please note that I said arduino for sake of simplicity, but the board is actually a Olimexino STM32 equivalent to a Maple R3, thus the different VID. All in all, the main problem is that in my tablet the broadcast receiver is never called when I connect a device on the OTG, whereas this works on my wiko phone. Again, the tablet sees a memory stick connected since the explorer can show its files. Could the USB traffic be fully intercepted in the tablet firmware in order to prevent a user from exploiting the OTG capability for other purposes?

At compile time, the Android Studio selects API 16 for the tablet and API 22 for the phone. Are there differences between API's that could explain this behavior?

Phono
  • 1
  • 3
  • Where you able to solve the problem? Did you add the necessary permissions and texts in manifest?! For broadcast and USB – TheEngineer Mar 06 '18 at 18:25
  • No, I am still at the same point. Do you mean that the permissions could be handled differently in API 16 and API 22? For I confirm that under API 22 this code works perfectly, and as soon as I insert the USB plug I get the popup menu "do you allow the application AndoidUSB to access the USB device" (or equivalent wording, my system is in french). This menu never shows on API 16. – Phono Mar 06 '18 at 20:04
  • No I mean do you have these ones in your manifest file? and this one goes inside the , – TheEngineer Mar 07 '18 at 04:18
0

Just to make it more clear:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.user.someApp">

    <uses-feature
        android:name="android.hardware.usb.host"
        android:required="true" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:theme="@style/Theme.AppCompat.Light.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>


        <service
            android:name=".UsbService"
            android:enabled="true" />



    </application>

</manifest>
TheEngineer
  • 792
  • 6
  • 18
0

TheEngineer, thanks for taking the time of examining my problem.

My manifest is:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.hariharan.arduinousb" >
<uses-feature android:name="android.hardware.usb.host" />

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name="com.hariharan.arduinousb.MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
        <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>

As you see: in uses-feature, the .required parameter is missing. I added it. The /service block is also missing. I try to add it, but got an "unresolved class reference" error. In the .zip of the project I downloaded (see link above) this statement is absent.

However, after this correction, the behavior is the same: the USB device is detected on API 22 and not on API 16.

Phono
  • 1
  • 3