Package org.jnode.driver.input.usb

Source Code of org.jnode.driver.input.usb.USBKeyboardDriver

/*
* $Id$
*
* Copyright (C) 2003-2014 JNode.org
*
* 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 org.jnode.driver.input.usb;

import javax.naming.NameNotFoundException;

import org.apache.log4j.Logger;
import org.jnode.driver.Driver;
import org.jnode.driver.DriverException;
import org.jnode.driver.bus.usb.USBConfiguration;
import org.jnode.driver.bus.usb.USBConstants;
import org.jnode.driver.bus.usb.USBDataPipe;
import org.jnode.driver.bus.usb.USBDevice;
import org.jnode.driver.bus.usb.USBEndPoint;
import org.jnode.driver.bus.usb.USBException;
import org.jnode.driver.bus.usb.USBInterface;
import org.jnode.driver.bus.usb.USBPacket;
import org.jnode.driver.bus.usb.USBPipeListener;
import org.jnode.driver.bus.usb.USBRequest;
import org.jnode.driver.input.KeyboardAPI;
import org.jnode.driver.input.KeyboardAPIAdapter;
import org.jnode.driver.input.KeyboardInterpreter;
import org.jnode.driver.input.KeyboardInterpreterException;
import org.jnode.driver.input.KeyboardLayoutManager;
import org.jnode.naming.InitialNaming;
import org.jnode.util.ByteQueue;
import org.jnode.util.ByteQueueProcessor;
import org.jnode.util.ByteQueueProcessorThread;

/**
* @author Ewout Prangsma (epr@users.sourceforge.net)
*/
public class USBKeyboardDriver extends Driver implements USBPipeListener, USBConstants,
        ByteQueueProcessor {

    /** My logger */
    private static final Logger log = Logger.getLogger(USBKeyboardDriver.class);
    /** The endpoint we're communicating with */
    private USBEndPoint ep;
    /** The interrupt pipe */
    private USBDataPipe intPipe;
    /** The request data packet */
    private USBPacket intData;
    /** The keyboard API implementation */
    private final KeyboardAPIAdapter apiAdapter = new KeyboardAPIAdapter();
    private byte[] old;
    /** KeyEvent queue */
    private final ByteQueue keyCodeQueue = new ByteQueue();
    /** KeyEvent send thread */
    private ByteQueueProcessorThread keyEventThread;

    private static final char usb_kbd_keycode[] = {
        0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, 50, 49, 24, 25, 16, 19,
        31, 20, 22, 47, 17, 45, 21, 44, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57,
        12, 13, 26, 27, 43, 84, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64, 65, 66,
        67, 68, 87, 88, 99, 70, 119, 110, 102, 104, 111, 107, 109, 106, 105, 108, 103, 69,
        98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, 72, 73, 82, 83, 86, 127, 116, 117,
        85, 89, 90, 91, 92, 93, 94, 95, 120, 121, 122, 123, 134, 138, 130, 132, 128, 129,
        131, 137, 133, 135, 136, 113, 115, 114, 0, 0, 0, 124, 0, 181, 182, 183, 184, 185,
        186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 42, 56, 125, 97, 54, 100, 126, 164, 166, 165, 163,
        161, 115, 114, 113, 150, 158, 159, 128, 136, 177, 178, 176, 142, 152, 173, 140};

    /**
     * @throws NameNotFoundException
     * @see org.jnode.driver.Driver#startDevice()
     */
    protected void startDevice() throws DriverException {
        try {
            final USBDevice dev = (USBDevice) getDevice();
            final USBConfiguration conf = dev.getConfiguration(0);
            // dev.setConfiguration(conf);
            final USBInterface intf = conf.getInterface(0);
            this.ep = null;
            for (int i = 0; i < intf.getDescriptor().getNumEndPoints(); i++) {
                ep = intf.getEndPoint(i);
                if (((ep.getDescriptor().getAttributes() & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) &&
                        ((ep.getDescriptor().getEndPointAddress() & USB_DIR_IN) == 0))
                    break;
            }
            if (this.ep == null)
                throw new DriverException(
                        "Found no interrupt endpoint, HID specs required at least one.");

            //
            log.debug("Interval " + ep.getDescriptor().getInterval());

            // Create the interrupt request
            old = new byte[8];
            intData = new USBPacket(ep.getDescriptor().getMaxPacketSize());
            intPipe = (USBDataPipe) ep.getPipe();
            intPipe.addListener(this);
            intPipe.open();
            final USBRequest req = intPipe.createRequest(intData);
            intPipe.asyncSubmit(req);

            // Configure the default keyboard layout and register the KeyboardAPI
            KeyboardLayoutManager mgr = InitialNaming.lookup(KeyboardLayoutManager.NAME);
            apiAdapter.setKbInterpreter(mgr.createDefaultKeyboardInterpreter());
            dev.registerAPI(KeyboardAPI.class, apiAdapter);

            // Start the key event thread
            keyEventThread =
                    new ByteQueueProcessorThread(dev.getId() + "-daemon", keyCodeQueue, this);
            keyEventThread.start();
        } catch (USBException ex) {
            throw new DriverException(ex);
        } catch (NameNotFoundException ex) {
            throw new DriverException("Cannot find keyboard layout manager", ex);
        } catch (KeyboardInterpreterException ex) {
            throw new DriverException(ex);
        }
    }

    /**
     * @see org.jnode.driver.Driver#stopDevice()
     */
    protected void stopDevice() throws DriverException {
        // Stop the key event thread
        keyEventThread.stopProcessor();
        // Unregister API
        getDevice().unregisterAPI(KeyboardAPI.class);
        apiAdapter.clear();
        // Close the pipe
        if (intPipe != null) {
            intPipe.removeListener(this);
            intPipe.close();
            intPipe = null;
        }
        intData = null;
        ep = null;
    }

    /**
     * @see org.jnode.driver.bus.usb.USBPipeListener#requestCompleted(org.jnode.driver.bus.usb.USBRequest)
     */
    public void requestCompleted(USBRequest request) {
        // log.debug("Keyboard interrupt: " + intData);

        final byte[] cur = intData.getData();

        for (int i = 0; i < 8; i++) {
            final int bit = (1 << i);
            if ((old[0] & bit) != (cur[0] & bit)) {
                // Modifier changed
                final int keyCode = usb_kbd_keycode[i + 224];
                // It is an extended keycode
                keyCodeQueue.enQueue((byte) KeyboardInterpreter.XT_EXTENDED);
                if ((old[0] & bit) != 0) {
                    // Released
                    keyCodeQueue.enQueue((byte) (keyCode | KeyboardInterpreter.XT_RELEASE));
                } else {
                    // Pressed
                    keyCodeQueue.enQueue((byte) keyCode);
                }
            }
        }

        for (int i = 2; i < 8; i++) {
            if (((old[i] & 0xFF) > 3) && !contains(cur, 2, old[i])) {
                // Key released
                final int keyCode = usb_kbd_keycode[old[i] & 0xFF];
                if (keyCode > 0) {
                    keyCodeQueue.enQueue((byte) (keyCode | KeyboardInterpreter.XT_RELEASE));
                } else {
                    log.debug("Unknown scancode released " + (old[i] & 0xFF));
                }
            }
            if (((cur[i] & 0xFF) > 3) && !contains(old, 2, cur[i])) {
                // Key pressed
                final int keyCode = usb_kbd_keycode[cur[i] & 0xFF];
                if (keyCode > 0) {
                    keyCodeQueue.enQueue((byte) keyCode);
                } else {
                    log.debug("Unknown scancode pressed " + (cur[i] & 0xFF));
                }
            }

            System.arraycopy(cur, 0, old, 0, cur.length);
        }
    }

    /**
     * @see org.jnode.driver.bus.usb.USBPipeListener#requestFailed(org.jnode.driver.bus.usb.USBRequest)
     */
    public void requestFailed(USBRequest request) {
        log.debug("Keyboard interrupt error status:" + request.getStatus());
        intPipe.close();
    }

    /**
     * Process the given object from the queue.
     *
     * @param value
     */
    public void process(byte value) throws Exception {
        final int keyCode = value & 0xFF;
        final KeyboardInterpreter intp = apiAdapter.getKbInterpreter();
        apiAdapter.fireEvent(intp.interpretScancode(keyCode));
    }

    private final boolean contains(byte[] arr, int start, byte value) {
        final int max = arr.length;
        for (int i = start; i < max; i++) {
            if (arr[i] == value) {
                return true;
            }
        }
        return false;
    }

}
TOP

Related Classes of org.jnode.driver.input.usb.USBKeyboardDriver

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.