⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 endpoint.java

📁 JAVA 访问USB JAVA 访问USB JAVA 访问USB JAVA 访问USB JAVA 访问USB JAVA 访问USB
💻 JAVA
字号:
/*
 * Java USB Library
 * Copyright (C) 2000 by David Brownell
 *
 * This program 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 program 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 program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package usb.core;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;


/**
 * Provides access to a USB endpoint descriptor, structuring device
 * data input or output in a given device configuration.
 * Only one thread at a time may use an endpoint for I/O.
 *
 * <p> Bulk endpoints look like standard byte I/O streams.
 * Interrupt endpoints send and receive short buffers directly; at this
 * writing there is no asynchronous notification framework.
 * ISO endpoints are not currently supported here.
 * ({@link ControlMessage}s are effectively device methods.)
 *
 * <p> Most fields of this descriptor are specified in section 9.6.4 of
 * the USB 1.1 specification.
 *
 * @version $Id: Endpoint.java,v 1.9 2000/11/20 17:07:18 dbrownell Exp $
 */
final public class Endpoint extends Descriptor
{
    /** Interface to which this endpoint belongs */
    private Interface		iface;

    private transient DeviceSPI	spi;

    // package private
    Endpoint (Interface intf, byte buf [])
    {
	super (buf);
	iface = intf;
	if (getDescriptorType () != TYPE_ENDPOINT)
	    throw new IllegalArgumentException ();
    }

    // package private
    Endpoint (Interface intf, int offset)
    {
	super (intf, offset);
	iface = intf;
	if (getDescriptorType () != TYPE_ENDPOINT)
	    throw new IllegalArgumentException ();
    }

    // ACCESS TO ALL DESCRIPTOR FIELDS

    /** Returns the endpoint address (a number from 0 to 15). */
    public int getEndpointAddress ()
	{ return 0x0f & getEndpoint (); }
    
    /**
     * Returns true if this is an input endpoint (data flows to host),
     * false if it is instead an output endpoint (data flows to device).
     */
    public boolean isInput ()
	{ return (getEndpoint () & 0x80) != 0; }
    
    /**
     * Returns an identifier composing the endpoint address
     * and the flag controlling its input.
     */
    public int getEndpoint () { return getU8 (2); }

    /** Returns the endpoint attributes (a bitmask describing its type). */
    public int getAttributes ()
	{ return getU8 (3); }
    
    /**
     * Returns the type of endpoint ("bulk", "iso", or "interrupt";
     * "control" won't normally be seen).
     */
    public String getType ()
    {
	switch (getAttributes () & 0x03) {
	    case 0: return "control";
	    case 1: return "iso";
	    case 2: return "bulk";
	    case 3: return "interrupt";
	}
	// "can't happen"
	return null;
    }

    /** Maximum packet size this endpoint can send or receive. */
    public int getMaxPacketSize ()
	{ return getU16 (4); }
    
    /** Returns interrupt polling interval (in milliseconds).  */
    public int getInterval ()
	{ return getU8 (6); }
    

    // NOTE:  audio endpoint descriptors have 2 extra bytes.


    /** Returns the interface with which the endpoint is associated */
    public Interface getInterface ()
    {
	return iface;
    }

    public Device getDevice ()
    {
	return iface.getDevice ();
    }

    /**
     * Endpoint feature selector that sets or clears the halt state.
     * This is also used as the bit position in the status word which
     * indicates the halted state.
     */
    public static final int ENDPOINT_HALT = 0;


    /**
     * Returns an input stream used to read from this bulk input stream.
     * This stream has a {@link Endpoint#getMaxPacketSize maximum
     * packet size}, which application protocols may rely on.
     */
    public InputStream getInputStream ()
    {
	if ("bulk" != getType () || !isInput ())
	    throw new IllegalArgumentException ();
	spi = getDevice ().getSPI ();
	return new BulkInputStream (spi, getEndpoint ());
    }

    // local-only: not serializable
    private static final class BulkInputStream extends InputStream
    {
	private int		ep;
	private DeviceSPI	spi;

	BulkInputStream (DeviceSPI spi, int e)
	    { this.spi = spi; ep = e; }

	public int read ()
	throws IOException
	{
	    byte temp [] = spi.readBulk (ep, 1);
	    return 0xff & temp [0];
	}

	public int read (byte buf [], int off, int len)
	throws IOException
	{
	    if (len < 0)
		throw new IllegalArgumentException ();

	    // extra copy forced by RMI

	    byte temp [] = spi.readBulk (ep, len);
	    System.arraycopy (temp, 0, buf, off, temp.length);
	    return temp.length;
	}
    }

    /**
     * Returns the output stream used to write to this bulk output stream.
     * This stream has a {@link Endpoint#getMaxPacketSize maximum
     * packet size}, which application protocols may rely on.
     */
    public OutputStream getOutputStream ()
    {
	if ("bulk" != getType () || isInput ())
	    throw new IllegalArgumentException ();
	spi = getDevice ().getSPI ();
	return new BulkOutputStream (spi, getEndpoint ());
    }
    
    // local-only: not serializable
    private static final class BulkOutputStream extends OutputStream
    {
	private int		ep;
	private DeviceSPI	spi;

	BulkOutputStream (DeviceSPI spi, int e)
	    { this.spi = spi; ep = e; }

	public void write (int value)
	throws IOException
	{
	    byte temp [] = new byte [] { (byte) value };
	    spi.writeBulk (ep, temp);
	}

	public void write (byte buf [], int off, int len)
	throws IOException
	{
	    if (off == 0 && len == buf.length)
		spi.writeBulk (ep, buf);
	    else {
		// extra copy forced by RMI
		byte temp [] = new byte [len];
		System.arraycopy (buf, off, temp, 0, len);
		spi.writeBulk (ep, temp);
	    }
	}
    }

    /**
     * Blocks until an interrupt message is sent from device to host, and
     * then returns that message.  You must allocate a thread to poll
     * for such interrupts every {@link Endpoint#getInterval} milliseconds.
     * Examples of such messages include mouse,
     * keyboard, and joystick events.  (Hub events too, but the kernel
     * driver will always claim those.)
     *
     * <p> <em>Note:  not yet known to work on Linux; this starts with
     * the implementation model that's supposed to work. </em>
     *
     * @return the number of bytes actually read, or negative errno
     */
    public byte [] recvInterrupt ()
    throws IOException
    {
	if ("interrupt" != getType ())
	    throw new IllegalArgumentException ();
	if (spi == null)
	    spi = iface.getDevice ().getSPI ();
	// FIXME getInterval() ms timeout (caller guarantees periodicity)
	return spi.readIntr (getU8 (2), getMaxPacketSize ());
    }

    /**
     * Sends interrupt message from host to device.  The data, with a
     * {@link Endpoint#getMaxPacketSize maximum size},
     * is written in the next available
     * interrupt slot for this endpoint.  (Note that Interrupt "out"
     * capabilities were added in the 1.1 revision of the USB spec.)
     * An example of such interrupts:  at least one force-feedback
     * joystick uses them for the feedback.
     */
    public void sendInterrupt (byte buf [])
    throws IOException
    {
	if ("interrupt" != getType () || buf.length > getMaxPacketSize ())
	    throw new IllegalArgumentException ();
	if (spi == null)
	    spi = iface.getDevice ().getSPI ();
	// FIXME getInterval() ms timeout (caller guarantees periodicity)
	spi.writeIntr (getU8 (2), buf);
    }

    /**
     * Clears a halt status (stall) on the bulk endpoint.
     */
    public void clearHalt () throws IOException
    {
	if ("bulk" != getType ())
	    throw new IllegalArgumentException ();
	
	// this affects the USB data toggle and other HCD state,
	// otherwise we could issue control requests directly
	if (spi == null)
	    spi = iface.getDevice ().getSPI ();
	spi.clearHalt ((byte) (0x8f & getU8 (2)));
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -