Android support

Questions and answers about 3Dconnexion devices on UNIX and Linux.

Moderator: Moderators

robert_ugo
Posts: 6
Joined: Mon Jun 18, 2012 3:06 pm

Android support

Post by robert_ugo » Mon Jun 18, 2012 3:13 pm

Is there any sollution to plug 3dconnexion to android or iOS tablet? Im working on remote controler for robot and it would be nice to use it in my project.
On android im thinking about build custom kelner with build-in drivers and then in some way comunicate with driver from aplication.
Its good way or there is other (better) solution?

jwick
Moderator
Moderator
Posts: 2462
Joined: Wed Dec 20, 2006 2:25 pm
Location: USA
Contact:

Re: Android support

Post by jwick » Tue Jun 19, 2012 6:30 am

Our devices are standard HID USB devices. You can read directly from them in the latest version of Android.
I don't know much about iOS.

robert_ugo
Posts: 6
Joined: Mon Jun 18, 2012 3:06 pm

Re: Android support

Post by robert_ugo » Tue Jun 19, 2012 7:05 am

Thanks for answer! Its easier than i thought.
But there is any API how can i talk with 3dconnexion via USB?

jwick
Moderator
Moderator
Posts: 2462
Joined: Wed Dec 20, 2006 2:25 pm
Location: USA
Contact:

Re: Android support

Post by jwick » Tue Jun 19, 2012 7:37 am

You need to use the Usb* classes.
Here is some code I cut out of a demo we created.
It reads the data but doesn't do anything more than log it.
Expect to find some cut and paste errors in here. If you are an Android developer, it should get you started.
As I recall, this code originated in a USBTest example.

Code: Select all

    private UsbManager mManager;
    private UsbDevice mDevice;
    private UsbDeviceConnection mDeviceConnection;
    private UsbInterface mInterface;
    private UsbEndpoint mEndpointIn;
    private PendingIntent mPermissionIntent;

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

    private final WaiterThread mWaiterThread = new WaiterThread();
    
    public long[] t = new long[3];
	public long[] r = new long[3];

    @Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		
        mManager = (UsbManager)getSystemService(Context.USB_SERVICE);
        mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);

        // listen for new devices
        IntentFilter filter = new IntentFilter();
        filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
        filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
        filter.addAction(ACTION_USB_PERMISSION);
        registerReceiver(mUsbReceiver, filter);

        // check for existing devices

        for (UsbDevice device :  mManager.getDeviceList().values()) {
            mInterface = findInterface(device);
            if (findEndPoints(mInterface)) {
            	setUsbInterface(device, mInterface);
                break;
            }
        }		
	}

    private UsbInterface findInterface(UsbDevice device) {        
        int count = device.getInterfaceCount();
        for (int i = 0; i < count; i++) {
            UsbInterface intf = device.getInterface(i);
            if (device.getVendorId() == 1133) // 3Dx devices
            {
                return intf;
            }
        }
        return null;
    }


	protected boolean findEndPoints(UsbInterface intf) {
		int nEndPoints = intf.getEndpointCount();
        for (int i = 0; i < intf.getEndpointCount(); i++) {
            UsbEndpoint ep = intf.getEndpoint(i);
            int eptype = ep.getType();
              if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_INT) {
                if (ep.getDirection() == UsbConstants.USB_DIR_OUT) {
                } else {
                	mEndpointIn = ep;
                	return true;
                }
            }
        }
        return false;
	}
    
    // Sets the current USB device and interface
    private boolean setUsbInterface(UsbDevice device, UsbInterface intf) {
        if (mDeviceConnection != null) {
            if (mInterface != null) {
                mDeviceConnection.releaseInterface(mInterface);
                mInterface = null;
            }
            mDeviceConnection.close();
            mDevice = null;
            mDeviceConnection = null;
        }

        if (device != null && intf != null) {
        	mManager.requestPermission(device, mPermissionIntent);
            UsbDeviceConnection connection = mManager.openDevice(device);
            if (connection != null) {
                if (connection.claimInterface(intf, true)) {
                    mDevice = device;
                    mDeviceConnection = connection;
                    
                    mInterface = intf;
                    
                    mWaiterThread.start();
                    return true;
                } else {
                    connection.close();
                }
            } else {
            }
        }

        return false;
    }
    

    public int bytesToInt(byte lsb, byte msb)
    {
		int x = (((int)(msb) << 8) & 0xff00) | (((int)lsb) & 0x00ff);
		
		// Negative?
		if ((x & 0x8000) != 0) x |= 0xffff0000;
		
    	return x;
    }
    
    private class WaiterThread extends Thread {
        public boolean mStop;

        public void run() {
        	
        	while(true) {
        	 byte[] bytes = new byte[7];
        	  int TIMEOUT = 0;
        	  int length = 7;
        	  int result;

        	  result = mDeviceConnection.bulkTransfer(mEndpointIn, bytes, length, TIMEOUT);
        	  
        	  // Translation packet comes in before rotation packet.  Wait until you have both before
        	  // doing anything with the data
        	  
        	  if (bytes[0] == 1)  // Translation packet
        	  {
        		  t[0] = bytesToInt(bytes[1], bytes[2]);
        		  t[1] = bytesToInt(bytes[3], bytes[4]);
        		  t[2] = bytesToInt(bytes[5], bytes[6]);
        	  }
        	
        	  else if (bytes[0] == 2)  // Rotation packet
        	  {
        		  r[0] = bytesToInt(bytes[1], bytes[2]);
        		  r[1] = bytesToInt(bytes[3], bytes[4]);
        		  r[2] = bytesToInt(bytes[5], bytes[6]);
        		  
        		  String dataString = new String();
        		  dataString = String.format("t:%d %d %d   r: %d %d %d ", t[0],t[1],t[2],r[0],r[1],r[2]);
        		  log(dataString);
        	  }
        	
        	  else if (bytes[0] == 3)  // Button packet
        	  {
        	  }
        	}

        }
    }

    
    BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();

            if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
                UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
            } else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
                UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                String deviceName = device.getDeviceName();
                if (mDevice != null && mDevice.equals(deviceName)) {
                }
            } else 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){
                       }
                    } 
                    else {
                    }
                }
            }   
        }
    };
        
	}
}

robert_ugo
Posts: 6
Joined: Mon Jun 18, 2012 3:06 pm

Re: Android support

Post by robert_ugo » Tue Jun 19, 2012 7:44 am

Thanks a lot again! It will be very helpfull.
You are a great support!

robert_ugo
Posts: 6
Joined: Mon Jun 18, 2012 3:06 pm

Re: Android support

Post by robert_ugo » Wed Oct 03, 2012 2:04 pm

It's me again.
I have been working with this code, but i can't get it working. My app can't find 3dconnexion device. I have some questions:
- Can i get a manifest.xml? It can be problem with permissions, but i can't find it.
- Did you connect 3dconnexion via any addition device or kit?
It would be great if you can share the whole source code of this example app (of course if you can do this).
I hope you can help me one more time.

jwick
Moderator
Moderator
Posts: 2462
Joined: Wed Dec 20, 2006 2:25 pm
Location: USA
Contact:

Re: Android support

Post by jwick » Mon Oct 08, 2012 1:52 am

robert_ugo wrote: - Can i get a manifest.xml? It can be problem with permissions, but i can't find it.

Code: Select all

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.adb">

    <uses-feature android:name="android.hardware.usb.host" />
    <uses-sdk android:minSdkVersion="12" />

    <application>
        <activity android:name="AdbTestActivity" android:label="ADB Test">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.DEFAULT" />
                <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>
robert_ugo wrote:- Did you connect 3dconnexion via any addition device or kit?
Plugged it directly into an ASUS Slider.
robert_ugo wrote:It would be great if you can share the whole source code of this example app
I need to do an Android SDK. The code I have now is an experimental mess. I'll email it to you. Caveat Emptor.

robert_ugo
Posts: 6
Joined: Mon Jun 18, 2012 3:06 pm

Re: Android support

Post by robert_ugo » Mon Oct 08, 2012 3:41 am

Thanks for your help! Finally it was problem with tablet. I had to replace some system files and from now everything works :)

ligi
Posts: 6
Joined: Mon Oct 22, 2012 1:26 pm

Re: Android support

Post by ligi » Mon Oct 22, 2012 1:30 pm

just wanted to say thanks for the Question and the provided code snipped - used that at a hackathon to control a AR.Drone with a SpaceNavigator attached to a Nexus 7 - you can find the source here:
https://github.com/ligi/SpaceAR.Drone
and some more info here:
https://docs.google.com/presentation/d/ ... edit#slide

jwick
Moderator
Moderator
Posts: 2462
Joined: Wed Dec 20, 2006 2:25 pm
Location: USA
Contact:

Re: Android support

Post by jwick » Tue Oct 23, 2012 1:55 am

Excellent. Let's see some video.

ngomes
Moderator
Moderator
Posts: 1934
Joined: Mon Nov 27, 2006 7:22 am
Contact:

Re: Android support

Post by ngomes » Tue Oct 23, 2012 9:13 am

Too cool! Video, please.

In your presentation, you may want to change the link to this topic to:
viewtopic.php?f=22&t=5339

ligi
Posts: 6
Joined: Mon Oct 22, 2012 1:26 pm

Re: Android support

Post by ligi » Sat Oct 27, 2012 4:33 am

@ngomes: thanks - I just updated the link

@jwick @ngomes - will post a link to the videos once they are uploaded - we recorded with a HD-Cam - some small phone-videos are already in this stream: https://plus.google.com/u/0/events/c6dp ... cpufftkqtk - but I would wait for the HD-Videos

PS: any idea on how I could trigger the blue light inside the SpaceNavigator on Android?

jwick
Moderator
Moderator
Posts: 2462
Joined: Wed Dec 20, 2006 2:25 pm
Location: USA
Contact:

Re: Android support

Post by jwick » Mon Oct 29, 2012 2:22 am

ligi wrote:PS: any idea on how I could trigger the blue light inside the SpaceNavigator on Android?
You can turn the LEDs on by sending the packet: 0x04 0x01. Turn them off with 0x04 0x00.

ligi
Posts: 6
Joined: Mon Oct 22, 2012 1:26 pm

Re: Android support

Post by ligi » Thu Nov 01, 2012 4:57 pm

thanks for the hint with 0x04 0x01, but I cannot find an endopoint to write to (ep.getDirection() == UsbConstants.USB_DIR_OUT)

ligi
Posts: 6
Joined: Mon Oct 22, 2012 1:26 pm

Re: Android support

Post by ligi » Thu Nov 01, 2012 5:04 pm

intf.getEndpointCount() returns 1 and this is UsbConstants.USB_DIR_IN - how can I send to the Device?

Post Reply