Implemented interfaces and alternate settings.

This commit is contained in:
Klaus Reimer 2011-02-03 00:01:44 +01:00 committed by k
parent d4a11ef16f
commit cf4dd66d31
3 changed files with 366 additions and 57 deletions

View File

@ -6,10 +6,14 @@
package de.ailis.usb4java.jsr80;
import static de.ailis.usb4java.USB.USB_DT_STRING;
import static de.ailis.usb4java.USB.usb_claim_interface;
import static de.ailis.usb4java.USB.usb_close;
import static de.ailis.usb4java.USB.usb_control_msg;
import static de.ailis.usb4java.USB.usb_get_descriptor;
import static de.ailis.usb4java.USB.usb_get_string;
import static de.ailis.usb4java.USB.usb_open;
import static de.ailis.usb4java.USB.usb_release_interface;
import static de.ailis.usb4java.USB.usb_set_configuration;
import static de.ailis.usb4java.USB.usb_strerror;
import java.io.UnsupportedEncodingException;
@ -19,6 +23,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.usb.UsbClaimException;
import javax.usb.UsbConfiguration;
import javax.usb.UsbConst;
import javax.usb.UsbControlIrp;
@ -64,7 +69,10 @@ abstract class AbstractDevice implements UsbDevice
private USB_Dev_Handle handle;
/** The number of the currently active configuration. */
private final byte activeConfigurationNumber = 0;
private byte activeConfigurationNumber = 0;
/** The number of the currently claimed interface. */
private Byte claimedInterfaceNumber = null;
/** The port this device is connected to. */
private UsbPort port;
@ -84,9 +92,21 @@ abstract class AbstractDevice implements UsbDevice
final USB_Config_Descriptor[] configs = device.config();
final List<UsbConfiguration> configurations =
new ArrayList<UsbConfiguration>(configs.length);
new ArrayList<UsbConfiguration>(configs.length);
for (final USB_Config_Descriptor config : configs)
configurations.add(new UsbConfigurationImpl(this, config));
{
final UsbConfiguration configuration = new UsbConfigurationImpl(
this, config);
configurations.add(configuration);
// TODO No idea how to find out the active configuration via
// libusb. So for now we use the first configuration.
if (this.activeConfigurationNumber == 0)
{
this.activeConfigurationNumber = (byte) config
.bConfigurationValue();
}
}
this.configurations = Collections.unmodifiableList(configurations);
}
@ -317,6 +337,117 @@ abstract class AbstractDevice implements UsbDevice
}
/**
* Sets the active USB configuration.
*
* @param number
* The number of the USB configuration to activate.
* @throws UsbException
* When configuration could not be activated.
*/
final void setActiveUsbConfigurationNumber(final byte number)
throws UsbException
{
if (number != this.activeConfigurationNumber)
{
if (this.claimedInterfaceNumber != null)
throw new UsbException("Can't change configuration while an "
+ "interface is still claimed");
USBLock.acquire();
try
{
final int result = usb_set_configuration(open(), number & 0xff);
if (result < 0) throw new UsbException(usb_strerror());
this.activeConfigurationNumber = number;
}
finally
{
USBLock.release();
}
}
}
/**
* Claims the specified interface.
*
* @param number
* The number of the interface to claim.
* @throws UsbException
* When interface could not be claimed.
* @throws UsbClaimException
* When an interface is already claimed.
*/
final void claimInterface(final byte number) throws UsbClaimException,
UsbException
{
if (this.claimedInterfaceNumber != null)
throw new UsbClaimException("A interface is already claimed");
USBLock.acquire();
try
{
final int result = usb_claim_interface(open(), number & 0xff);
if (result < 0) throw new UsbException(usb_strerror());
this.claimedInterfaceNumber = number;
}
finally
{
USBLock.release();
}
}
/**
* Releases a claimed interface.
*
* @param number
* The number of the interface to release.
* @throws UsbClaimException
* When the interface is not claimed.
* @throws UsbException
* When interface could not be claimed.
*/
final void releaseInterface(final byte number) throws UsbClaimException,
UsbException
{
if (this.claimedInterfaceNumber == null)
throw new UsbClaimException("No interface is claimed");
if (!Byte.valueOf(number).equals(this.claimedInterfaceNumber))
throw new UsbClaimException("Interface not claimed");
USBLock.acquire();
try
{
final int result = usb_release_interface(open(), number & 0xff);
if (result < 0) throw new UsbException(usb_strerror());
this.claimedInterfaceNumber = null;
}
finally
{
USBLock.release();
}
}
/**
* Checks if the specified interface is claimed.
*
* @param number
* The number of the interface to check.
* @return True if interface is claimed, false if not.
*/
final boolean isInterfaceClaimed(final byte number)
{
return Byte.valueOf(number).equals(this.claimedInterfaceNumber);
}
/**
* @see UsbDevice#getActiveUsbConfiguration()
*/
@ -437,8 +568,23 @@ abstract class AbstractDevice implements UsbDevice
@Override
public final void syncSubmit(final UsbControlIrp irp) throws UsbException
{
// TODO
throw new UnsupportedOperationException();
USBLock.acquire();
try
{
final ByteBuffer buffer = ByteBuffer
.allocateDirect(irp.getLength());
final USB_Dev_Handle handle = open();
final int len = usb_control_msg(handle, irp.bmRequestType(),
irp.bRequest(),
irp.wValue(), irp.wIndex(), buffer, 250);
if (len < 0) throw new UsbException(usb_strerror());
buffer.rewind();
buffer.get(irp.getData(), 0, len);
}
finally
{
USBLock.release();
}
}

View File

@ -5,7 +5,15 @@
package de.ailis.usb4java.jsr80;
import static de.ailis.usb4java.USB.usb_set_altinterface;
import static de.ailis.usb4java.USB.usb_strerror;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.usb.UsbConfiguration;
import javax.usb.UsbConfigurationDescriptor;
@ -13,7 +21,10 @@ import javax.usb.UsbDevice;
import javax.usb.UsbException;
import javax.usb.UsbInterface;
import de.ailis.usb4java.USBLock;
import de.ailis.usb4java.USB_Config_Descriptor;
import de.ailis.usb4java.USB_Interface;
import de.ailis.usb4java.USB_Interface_Descriptor;
/**
@ -24,14 +35,21 @@ import de.ailis.usb4java.USB_Config_Descriptor;
public final class UsbConfigurationImpl implements UsbConfiguration
{
/** The low-level USB configuration descriptor. */
private final USB_Config_Descriptor lowLevelDescriptor;
/** The JSR 80 USB configuration descriptor. */
private final UsbConfigurationDescriptor descriptor;
/** The USB device. */
private final UsbDevice device;
private final AbstractDevice device;
/**
* The interfaces. This is a map from interface number to a map of
* altsettings which maps setting numbers to actual interfaces.
*/
private final Map<Integer, Map<Integer, UsbInterface>> interfaces =
new HashMap<Integer, Map<Integer, UsbInterface>>();
/** This map contains the active USB interfaces. */
private final Map<Integer, UsbInterface> activeSettings = new HashMap<Integer, UsbInterface>();
/**
@ -43,13 +61,43 @@ public final class UsbConfigurationImpl implements UsbConfiguration
* The low-level USB configuration descriptor.
*/
public UsbConfigurationImpl(final UsbDevice device,
public UsbConfigurationImpl(final AbstractDevice device,
final USB_Config_Descriptor lowLevelDescriptor)
{
this.device = device;
this.lowLevelDescriptor = lowLevelDescriptor;
this.descriptor = new UsbConfigurationDescriptorImpl(
lowLevelDescriptor);
// Build interfaces
for (final USB_Interface iface : lowLevelDescriptor.iface())
{
for (final USB_Interface_Descriptor desc : iface.altsetting())
{
final int ifaceNumber = desc.bInterfaceNumber();
final int settingNumber = desc.bAlternateSetting();
Map<Integer, UsbInterface> settings = this.interfaces
.get(ifaceNumber);
if (settings == null)
{
settings = new HashMap<Integer, UsbInterface>();
this.interfaces.put(ifaceNumber, settings);
}
final UsbInterface usbInterface = new UsbInterfaceImpl(this,
desc);
// If we have no active setting for current interface number
// yet or the alternate setting number is 0 (which marks the
// default alternate setting) then set current interface as
// the active setting.
if (!this.activeSettings.containsKey(ifaceNumber) ||
desc.bAlternateSetting() == 0)
this.activeSettings.put(ifaceNumber, usbInterface);
// Add the interface to the settings list
settings.put(settingNumber, usbInterface);
}
}
}
@ -60,8 +108,8 @@ public final class UsbConfigurationImpl implements UsbConfiguration
@Override
public boolean isActive()
{
// TODO
throw new UnsupportedOperationException();
return this.device.getActiveUsbConfigurationNumber() == this.descriptor
.bConfigurationValue();
}
@ -72,8 +120,36 @@ public final class UsbConfigurationImpl implements UsbConfiguration
@Override
public List<UsbInterface> getUsbInterfaces()
{
// TODO
throw new UnsupportedOperationException();
return Collections.unmodifiableList(new ArrayList<UsbInterface>(
this.activeSettings.values()));
}
/**
* Returns the alternate settings for the specified interface.
*
* @param number
* The interface number.
* @return The alternate settings for the specified interface.
*/
Map<Integer, UsbInterface> getSettings(final byte number)
{
return this.interfaces.get(number);
}
/**
* Returns the number of alternate settings of the specified interface.
*
* @param number
* The interface number.
* @return The number of alternate settings.
*/
int getNumSettings(final byte number)
{
return this.interfaces.get(number).size();
}
@ -84,8 +160,39 @@ public final class UsbConfigurationImpl implements UsbConfiguration
@Override
public UsbInterface getUsbInterface(final byte number)
{
// TODO
throw new UnsupportedOperationException();
return this.activeSettings.get(number);
}
/**
* Sets the active USB interface setting.
*
* @param number
* THe interface number.
* @param iface
* The interface setting to activate.
* @throws UsbException
* When interface setting could not be set.
*/
void setUsbInterface(final byte number, final UsbInterface iface)
throws UsbException
{
if (this.activeSettings.get(number & 0xff) != iface)
{
USBLock.acquire();
try
{
final int result = usb_set_altinterface(this.device.open(),
iface.getUsbInterfaceDescriptor().bAlternateSetting());
if (result < 0) throw new UsbException(usb_strerror());
this.activeSettings.put(number & 0xff, iface);
}
finally
{
USBLock.release();
}
}
}
@ -96,7 +203,7 @@ public final class UsbConfigurationImpl implements UsbConfiguration
@Override
public boolean containsUsbInterface(final byte number)
{
return number >= 0 && number < this.lowLevelDescriptor.bNumInterfaces();
return this.activeSettings.containsKey(number);
}
@ -127,9 +234,11 @@ public final class UsbConfigurationImpl implements UsbConfiguration
*/
@Override
public String getConfigurationString() throws UsbException
public String getConfigurationString() throws UsbException,
UnsupportedEncodingException
{
// TODO
throw new UnsupportedOperationException();
final byte iConfiguration = this.descriptor.iConfiguration();
if (iConfiguration == 0) return null;
return this.device.getString(iConfiguration);
}
}

View File

@ -5,15 +5,22 @@
package de.ailis.usb4java.jsr80;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.usb.UsbClaimException;
import javax.usb.UsbConfiguration;
import javax.usb.UsbEndpoint;
import javax.usb.UsbException;
import javax.usb.UsbInterface;
import javax.usb.UsbInterfaceDescriptor;
import javax.usb.UsbInterfacePolicy;
import javax.usb.UsbNotActiveException;
import de.ailis.usb4java.USB_Interface;
import de.ailis.usb4java.USBLock;
import de.ailis.usb4java.USB_Interface_Descriptor;
/**
@ -25,10 +32,10 @@ import de.ailis.usb4java.USB_Interface;
public final class UsbInterfaceImpl implements UsbInterface
{
/** The USB configuration. */
private final UsbConfiguration configuration;
private final UsbConfigurationImpl configuration;
/** The low-level USB interface. */
private final USB_Interface iface;
/** The interface descriptor. */
private final UsbInterfaceDescriptor descriptor;
/**
@ -36,15 +43,39 @@ public final class UsbInterfaceImpl implements UsbInterface
*
* @param configuration
* The USB configuration.
* @param iface
* The low-level USB-interface.
* @param lowLevelDescriptor
* The low-level USB interface descriptor.
*/
public UsbInterfaceImpl(final UsbConfiguration configuration,
final USB_Interface iface)
public UsbInterfaceImpl(final UsbConfigurationImpl configuration,
final USB_Interface_Descriptor lowLevelDescriptor)
{
this.configuration = configuration;
this.iface = iface;
this.descriptor = new UsbInterfaceDescriptorImpl(lowLevelDescriptor);
}
/**
* Checks if the configuration is active. If not then an
* UsbNotActiveException is thrown.
*/
private void checkConfigurationActive()
{
if (!this.configuration.isActive())
throw new UsbNotActiveException("Configuration is not active");
}
/**
* Checks if setting is active. Throws an UsbNotActiveException if not.
*/
private void checkSettingActive()
{
checkConfigurationActive();
if (!isActive())
throw new UsbNotActiveException("Setting is not active");
}
@ -53,22 +84,36 @@ public final class UsbInterfaceImpl implements UsbInterface
*/
@Override
public void claim()
public void claim() throws UsbException
{
// TODO
throw new UnsupportedOperationException();
claim(null);
}
/**
* @see UsbInterface#claim(UsbInterfacePolicy)
*
* TODO Policy is ignored
*/
@Override
public void claim(final UsbInterfacePolicy policy)
throws UsbClaimException, UsbException
{
// TODO
throw new UnsupportedOperationException();
final AbstractDevice device = (AbstractDevice) this.configuration
.getUsbDevice();
USBLock.acquire();
try
{
device.setActiveUsbConfigurationNumber(this.configuration
.getUsbConfigurationDescriptor().bConfigurationValue());
device.claimInterface(this.descriptor.bInterfaceNumber());
this.configuration.setUsbInterface(this.descriptor.bInterfaceNumber(), this);
}
finally
{
USBLock.release();
}
}
@ -77,10 +122,10 @@ public final class UsbInterfaceImpl implements UsbInterface
*/
@Override
public void release()
public void release() throws UsbClaimException, UsbException
{
// TODO
throw new UnsupportedOperationException();
((AbstractDevice) this.configuration.getUsbDevice())
.releaseInterface(this.descriptor.bInterfaceNumber());
}
@ -91,8 +136,8 @@ public final class UsbInterfaceImpl implements UsbInterface
@Override
public boolean isClaimed()
{
// TODO
throw new UnsupportedOperationException();
return ((AbstractDevice) this.configuration.getUsbDevice())
.isInterfaceClaimed(this.descriptor.bInterfaceNumber());
}
@ -103,8 +148,8 @@ public final class UsbInterfaceImpl implements UsbInterface
@Override
public boolean isActive()
{
// TODO
throw new UnsupportedOperationException();
return this.configuration.getUsbInterface(this.descriptor
.bInterfaceNumber()) == this;
}
@ -115,7 +160,8 @@ public final class UsbInterfaceImpl implements UsbInterface
@Override
public int getNumSettings()
{
return this.iface.num_altsetting();
return ((this.configuration)
.getNumSettings(this.descriptor.bInterfaceNumber()));
}
@ -126,8 +172,11 @@ public final class UsbInterfaceImpl implements UsbInterface
@Override
public byte getActiveSettingNumber()
{
// TODO
throw new UnsupportedOperationException();
checkConfigurationActive();
checkSettingActive();
return this.configuration
.getUsbInterface(this.descriptor.bInterfaceNumber())
.getUsbInterfaceDescriptor().bAlternateSetting();
}
@ -138,8 +187,10 @@ public final class UsbInterfaceImpl implements UsbInterface
@Override
public UsbInterface getActiveSetting()
{
// TODO
throw new UnsupportedOperationException();
checkConfigurationActive();
checkSettingActive();
return this.configuration.getUsbInterface(this.descriptor
.bInterfaceNumber());
}
@ -150,8 +201,8 @@ public final class UsbInterfaceImpl implements UsbInterface
@Override
public UsbInterface getSetting(final byte number)
{
// TODO
throw new UnsupportedOperationException();
return (this.configuration).getSettings(
this.descriptor.bInterfaceNumber()).get(number);
}
@ -162,7 +213,8 @@ public final class UsbInterfaceImpl implements UsbInterface
@Override
public boolean containsSetting(final byte number)
{
return number >= 0 && number < this.iface.num_altsetting();
return (this.configuration).getSettings(
this.descriptor.bInterfaceNumber()).containsKey(number);
}
@ -173,8 +225,9 @@ public final class UsbInterfaceImpl implements UsbInterface
@Override
public List<UsbInterface> getSettings()
{
// TODO
throw new UnsupportedOperationException();
return Collections.unmodifiableList(new ArrayList<UsbInterface>(
(this.configuration).getSettings(
this.descriptor.bInterfaceNumber()).values()));
}
@ -232,8 +285,7 @@ public final class UsbInterfaceImpl implements UsbInterface
@Override
public UsbInterfaceDescriptor getUsbInterfaceDescriptor()
{
// TODO
throw new UnsupportedOperationException();
return this.descriptor;
}
@ -242,9 +294,11 @@ public final class UsbInterfaceImpl implements UsbInterface
*/
@Override
public String getInterfaceString()
public String getInterfaceString() throws UsbException,
UnsupportedEncodingException
{
// TODO
throw new UnsupportedOperationException();
final byte iInterface = this.descriptor.iInterface();
if (iInterface == 0) return null;
return this.configuration.getUsbDevice().getString(iInterface);
}
}