Use Case

This sort of implementation should be used when you want to communicate using USB, and you are not able to use either Neonode Workbench or the zForce SDK to configure the sensor, due to system requirements.


The zForce AIR sensor supports communication over I2C and USB. Both the Neonode Workbench, and the zForce SDK uses USB hidpipe to communicate with the sensor, but unfortunately not all systems can use the SDK or the Workbench application. This might be the case if you are planning to connect the sensor to (for example) an Android device, and need to change some settings, which is also why this example will be in Java using the Android SDK.

What is HID?

HID stands for Human Interface Device, and is generally a device that takes input from humans and delivers it to a host system. The zForce AIR sensor has two different modes for the USB connection, which are the HID Digitizer mode, and the Raw HID mode.

Raw HID mode

When the sensor is connected to a system it is automatically put into the HID Digitizer mode, but in order to communicate with it, and send/read messages from it in a program, it has to be put into (also known as hidpipe) Raw HID mode. This is done by enumerating the sensor in your program, and sending a command to it.

Connecting to the sensor


The first thing you have to do in your program, is to make sure that the sensor is talking to your program instead of communicating with the OS. This is done by enumerating the sensor, and the code can look a bit different depending on which OS or SDK you are using, but the general idea is still the same, and usually follows the USB standard.

In Java, using the Android SDK, the code looks like this:

manager = (UsbManager) getSystemService(Context.USB_SERVICE); // Create a UsbManager
Map<String, UsbDevice> connectedDevices = manager.getDeviceList(); // Get all the connected USB devices and save them in a map

for (UsbDevice device : connectedDevices.values()) // Loop through all the connected devices
    if(device.getVendorId() == 0x1536 && device.getProductId() == 0x0101) // If a zForce AIR Sensor is found, 
        mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
        IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
        registerReceiver(NmUsbReceiver, filter);
        manager.requestPermission(device, mPermissionIntent);

        Nintf = device.getInterface(0);
        // NEONODE 0=IN, no out
        Nendpoint = Nintf.getEndpoint(0);
        Nconnection = manager.openDevice(device);
        Nconnection.claimInterface(Nintf, forceClaim);

 public void SetOperationMode () 
    byte[] sendArray = new byte[257];
    byte[] detectionMode = {
            (byte) 0x01,(byte) 0x17,(byte) 0xEE,(byte) 0x15,(byte) 0x40,(byte) 0x02,(byte) 0x02,
            (byte) 0x00,(byte) 0x67,(byte) 0x0F,(byte) 0x80,(byte) 0x01,
            (byte) 0xFF,(byte) 0x81,(byte) 0x01,(byte) 0x00,(byte) 0x82,
            (byte) 0x01,(byte) 0x00,(byte) 0x83,(byte) 0x01,(byte) 0x00,
            (byte) 0x84,(byte) 0x01,(byte) 0x00
    System.arraycopy(detectionMode, 0, sendArray, 0, detectionMode.length);
    int requestType = UsbConstants.USB_DIR_OUT | UsbConstants.USB_TYPE_CLASS | UsbConstants.USB_INTERFACE_SUBCLASS_BOOT;
    int request = 0x09;
    int value = 0x0301;
    int index = 0x0000;

    // write to device to set it in detectionMode, 0x01 for feature report 1
    int read_response = sendFeatureReport(0x01, sendArray, sendArray.length);

    String responseString = "Request";
    Log.i(responseString, Integer.toString(read_response));
    String byteString = byteArrayToHex(detectionMode);
    Log.i(responseString, byteString);
    //Read the response of the previous request
    byte readBuffer[] = new byte[258];

    // read from the device, 0x02 for feature report 2
    read_response = getFeatureReport(0x02, readBuffer, readBuffer.length);

    responseString = "Response";
    Log.i(responseString, Integer.toString(read_response));
    byteString = byteArrayToHex(readBuffer);
    Log.i(responseString, byteString);
    public int SendFeatureReport(int reportId, byte[] data, int length) {
        if ((reportId & 0xFF) != reportId)
            throw new IllegalArgumentException("reportId may only set the lowest 8 bits");
        return zForceAirConnection.controlTransfer(
                UsbConstants.USB_DIR_OUT | UsbConstants.USB_TYPE_CLASS | UsbConstants.USB_INTERFACE_SUBCLASS_BOOT,
                reportId | 0x0300,
                0x0000, data, length, 0);

    public int GetFeatureReport(int reportId, byte[] data, int length) {
        if ((reportId & 0xFF) != reportId)
            throw new IllegalArgumentException("reportId may only set the lowest 8 bits");
        return zForceAirConnection.controlTransfer(
                UsbConstants.USB_DIR_IN | UsbConstants.USB_TYPE_CLASS | UsbConstants.USB_INTERFACE_SUBCLASS_BOOT,
                reportId | 0x0300,
                0x0000, data, length, 0);

  • No labels