Android Open Source - p1keyboard H I D Reader Base






From Project

Back to project page p1keyboard.

License

The source code is released under:

GNU Lesser General Public License

If you think the Android project p1keyboard listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/* Copyright (C) 2011, Kenneth Skovhede
 * http://www.hexad.dk, opensource@hexad.dk
 * /*  ww w . j a v  a2  s . c  om*/
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/
package mobi.omegacentauri.p1keyboard;

import java.io.IOException;
import java.io.OutputStream;
import java.util.Hashtable;

import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.util.Log;

public abstract class HIDReaderBase extends RfcommReader {

  private static final boolean D = false;
  private static final String LOG_NAME = "HID Reader - ";
  
  private static final int HIDP_CONTROL_CHANNEL = 0x11; 
  private static final int HIDP_INTERRUPT_CHANNEL = 0x13; 
  
  protected BluetoothSocket m_controlSocket;
  protected OutputStream m_control;

  //A list of buffers, used to send HID reports
  protected Hashtable<Integer, byte[]> m_readBuffers;
  
  public HIDReaderBase(String address, String sessionId, Context context, boolean startnotification) throws Exception {
    super(address, sessionId, context, false, startnotification);
    
    m_readBuffers = new Hashtable<Integer, byte[]>();
  }

  @Override
  protected int setupConnection(ImprovedBluetoothDevice device, byte[] readBuffer) throws Exception {
    
    boolean isSecure = false;

    if (m_controlSocket != null) {
      if (D) Log.d(LOG_NAME, "Closing control socket on retry, " + m_controlSocket);
      try { m_controlSocket.close(); }
      catch (Exception ex) { }
      finally { m_controlSocket = null; }
    }

    if (m_socket != null) {
      if (D) Log.d(LOG_NAME, "Closing data socket on retry, " + m_socket);
      try { m_socket.close(); }
      catch (Exception ex) { }
      finally { m_socket = null; }
    }
    
    if (!m_useInsecureChannel) {
      try {
        m_controlSocket = device.createLCAPSocket(HIDP_CONTROL_CHANNEL);
        m_controlSocket.connect();
        isSecure = true;
      } catch (Exception ex) {
        m_controlSocket = null;
      }
    }
    
    if (m_controlSocket == null) {
      m_controlSocket = device.createInsecureLCAPSocket(HIDP_CONTROL_CHANNEL);
      m_controlSocket.connect();
    }
    
    m_control = m_controlSocket.getOutputStream();
    
        m_socket = isSecure ? device.createLCAPSocket(HIDP_INTERRUPT_CHANNEL) : device.createInsecureLCAPSocket(HIDP_INTERRUPT_CHANNEL);
        m_socket.connect();

        if (D) Log.d(LOG_NAME, "Connected to " + m_address);
      
      m_input = m_socket.getInputStream();
      
      verifyHIDDevice();
      
      return 0;    
  }
  
  protected void verifyHIDDevice() throws Exception {
  }
  
  @Override
  protected int parseInputData(byte[] data, int read) {
    
    int offset = 0;
    int remaining = read;

    Hashtable<Byte, Integer> supportedReports = getSupportedReportCodes();

    if (remaining <= 2)
      return remaining;

    //If we get a HID A or C data package, process it
    if (data[offset] == (byte)0xa1 || data[offset] == (byte)0xb1) {
      
      if (supportedReports.containsKey(data[offset + 1]))
      {
        int neededBytes = supportedReports.get(data[offset + 1]);
        
        //Safeguard, if we get too little data, wait for some more
        if (neededBytes > remaining - 2) {
          if (D) Log.w(getDriverName(), "Got " + (remaining - 2) + " bytes for report " + data[offset + 1] + ", but need " + neededBytes);
          return remaining;
        }
        
        if (!m_readBuffers.containsKey(neededBytes))
          m_readBuffers.put(neededBytes, new byte[neededBytes]);
        
        byte[] buffer = m_readBuffers.get(neededBytes);
        System.arraycopy(data, offset + 2, buffer, 0, neededBytes);
        
        try {
          handleHIDMessage(data[offset], data[offset + 1], buffer);
        } catch (Exception ex) {
          Log.e(getDriverName(), "Handling HID message " + data[offset + 1] + " failed: " + ex.toString());
        }
      }
      else
      {
        if (D) Log.w(getDriverName(), "Got an unsupported HID report: " + data[offset + 1] + ", length: " + (remaining - 2) + ", data: " + getHexString(data, offset, offset + (remaining)));
      }
    }
    
    //Since we cannot get the underlying L2CAP "field length", we
    // *assume* that a single read delivers a single package
    //As "an error is the result of an assumption" this may break :( 
    return 0;
  }

  @Override
  protected void validateWelcomeMessage(byte[] data, int read) {
  }
  
  @Override
  public void stop() {
    if (m_controlSocket != null) {
      
      if (m_control != null) {
        try {
          m_control.close();
        } catch (IOException e) {
        }
        
        m_control = null;
      }
      
      try {
        m_controlSocket.close();
      } catch (IOException e) {
      }
      m_controlSocket = null;
    }
    
    super.stop();
  }
  
  protected abstract void handleHIDMessage(byte hidType, byte reportId, byte[] data) throws Exception;

  protected abstract Hashtable<Byte, Integer> getSupportedReportCodes();
  
}




Java Source Code List

mobi.omegacentauri.p1keyboard.BGP100Reader.java
mobi.omegacentauri.p1keyboard.BluezDriverInterface.java
mobi.omegacentauri.p1keyboard.BluezForegroundService.java
mobi.omegacentauri.p1keyboard.BluezIMESettings.java
mobi.omegacentauri.p1keyboard.BluezIME.java
mobi.omegacentauri.p1keyboard.BluezService.java
mobi.omegacentauri.p1keyboard.ButtonConfiguration.java
mobi.omegacentauri.p1keyboard.DataDumpReader.java
mobi.omegacentauri.p1keyboard.DeviceScanActivity.java
mobi.omegacentauri.p1keyboard.FutureKeyCodes.java
mobi.omegacentauri.p1keyboard.GameStopReader.java
mobi.omegacentauri.p1keyboard.HIDKeyboard.java
mobi.omegacentauri.p1keyboard.HIDReaderBase.java
mobi.omegacentauri.p1keyboard.HIDipega.java
mobi.omegacentauri.p1keyboard.ImprovedBluetoothDevice.java
mobi.omegacentauri.p1keyboard.PalmOneWirelessKeyboardReader.java
mobi.omegacentauri.p1keyboard.PhonejoyReader.java
mobi.omegacentauri.p1keyboard.Preferences.java
mobi.omegacentauri.p1keyboard.RfcommReader.java
mobi.omegacentauri.p1keyboard.WiimoteReader.java
mobi.omegacentauri.p1keyboard.ZeemoteReader.java
mobi.omegacentauri.p1keyboard.iCadeReader.java
mobi.omegacentauri.p1keyboard.iControlPadReader.java