Skip to content

Commit

Permalink
Fixed Usb4JavaUsbDeviceCommunication and cleaned up all the code
Browse files Browse the repository at this point in the history
- Usb4JavaUsbDeviceCommunication: changed some logging (from info to debug), and when we display data, we use Hex Converter
- Fixed example a little
- Fixed log types (to debug) in some underlaying classes
- Added getReadableDeviceName() to UsbCommunication
- extended README.md with more data
  • Loading branch information
andy.rozman committed Apr 14, 2024
1 parent 22482e3 commit a5155b0
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 49 deletions.
63 changes: 48 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,18 @@ You can find original disclaimer little bit down the page. My contribution is so
The library can be included into your project like this:

```
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependency>
<groupId>com.atech-software</groupId>
<artifactId>libaums-usb4java</artifactId>
<version>Tag</version>
</dependency>
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependency>
<groupId>com.atech-software</groupId>
<artifactId>libaums-usb4java</artifactId>
<version>Tag</version>
</dependency>
```
There are plenty examples inside the project how to use usb4java (copied from usb4java samples), and I will add some examples on how to use library itself, as soon as I am so far.

Expand Down Expand Up @@ -86,16 +86,49 @@ device.close();
When we are done with library we need to call this, to dispose of LibUsb instance (instance is created automatically, but needs to be disposed manually):

```java
UsbMassStorageLibrary.
UsbMassStorageLibrary.disposeLibrary()
```

If you intend to work with SCSI (only part that I tested so far, although everything else should work):

### Status
```java

ScsiBlockDevice blockDevice = device.getBlockDevice();

// when writing to device we have to know where to write (3=would be what some would asume lba3)
long deviceOffset = 3;

// write to block device (createPacket() will be your method that creates packet you wish to send)
byte[] packet = createPacket();

blockDevice.write(deviceOffset, buffer);

// read from block device (in this case expected answer is 10 bytes
ByteBuffer readBuffer = ByteBuffer.allocate(10);

blockDevice.read(deviceOffset, readBuffer);

```

You can see some basic examples in ExampleCreateScsiBlockDevice.

### Logging

Library has Slf4j (Simple Log Framework for Java) integrated. I would recommend that you enable following packages for DEBUG while you are developing, but turn them to INFO for production systems and set your own logging to follow slf4j.

Just started on this project in April 2024, and it will take me some time to get it to working state.
```
com.atech.library.usb.libaums=DEBUG
com.github.mjdev.libaums=DEBUG
```


### Status

This project was extended and changed (to usb4java), so everything that worked in original project should work here.
I have tested SCSI block reading and writing and it works, so 1st release (0.4.0) should be fully working. If you find something wrong open Issue or in worst case scenario fix it and create PR and I will merge it (if I think its OK) and make new release.

There is no plans at the moment to add extensions that were introduced in magnusja/libaums, although I started some work on that in next_gen branch.



### Original README
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*
*/

package com.atech.library.usb.libaums.usb4java.examples;
package com.atech.library.usb.libaums.examples;


import com.atech.library.usb.libaums.UsbMassStorageLibrary;
Expand All @@ -41,11 +41,10 @@ public class ExampleCreateScsiBlockDevice {
public ExampleCreateScsiBlockDevice() {
String PATTERN = "%d{HH:mm:ss,SSS} %5p [%c{1}:%L] - %m%n";
UsbMassStorageLibrary.LOAD_PARTITIONS = false;
//createConsoleAppender(Level.ALL, PATTERN);
Logger.getRootLogger().removeAllAppenders();
Logger.getRootLogger().addAppender(createConsoleAppender(Level.ALL, PATTERN));
Logger.getLogger("com").setLevel(Level.DEBUG);
Logger.getLogger("github").setLevel(Level.DEBUG);
Logger.getLogger("com.atech.library.usb.libaums").setLevel(Level.DEBUG);
Logger.getLogger("com.github.mjdev.libaums").setLevel(Level.DEBUG);
}

public static ConsoleAppender createConsoleAppender(Level threshold, String pattern) {
Expand Down Expand Up @@ -74,8 +73,12 @@ private void findDevice() {
}
}

/**
* This is short example how to read data from Glucose Meter
*/
@SneakyThrows
public void connectToVerio() {
public void connectToOneTouchVerio() {
// TODO extend a little
UsbMassStorageDevice massStorageDevice = null;
try {
UsbMassStorageDeviceConfig config = UsbMassStorageDeviceConfig.builder()
Expand Down Expand Up @@ -149,7 +152,7 @@ public void dispose() {
public static void main(String[] args) {

ExampleCreateScsiBlockDevice flexi = new ExampleCreateScsiBlockDevice();
flexi.connectToVerio();
//flexi.connectToVerio();
//flexi.findDevice();
//flexi.readMicroSDreader();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.atech.library.usb.libaums.data.UsbMassStorageDeviceConfig;
import com.atech.library.usb.libaums.UsbMassStorageLibrary;
import com.github.mjdev.libaums.UsbCommunication;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.usb4java.*;

Expand All @@ -36,6 +37,7 @@ public class Usb4JavaUsbDeviceCommunication implements UsbCommunication {

private static final int TRANSFER_TIMEOUT = 5000; // 21000
DeviceHandle deviceHandle;
@Getter
UsbMassStorageDeviceConfig deviceConfig;
boolean deviceIsOpenAndClaimed = false;

Expand All @@ -50,7 +52,7 @@ public void openDevice() throws LibAumsException {
return;
}

log.info("openDevice: opening {}", deviceConfig.getReadableDeviceId());
log.debug("openDevice: opening {}", deviceConfig.getReadableDeviceId());
Context context = UsbMassStorageLibrary.initLibrary();

// Open device
Expand Down Expand Up @@ -86,7 +88,6 @@ public void openDevice() throws LibAumsException {
if (result3 != LibUsb.SUCCESS) {
throw LibAumsException.createWithLibUsbException("Unable to claim interface even after detaching kernel.", result3);
}

}

log.info("openDevice: Device {} opened and interface {} claimed.", deviceConfig.getReadableDeviceId(), deviceConfig.getInterfaceNumber());
Expand All @@ -96,7 +97,8 @@ public void openDevice() throws LibAumsException {

@Override
public int bulkOutTransfer(byte[] data, int length) throws LibAumsException {
log.debug("bulkOutTransfer (data={},length={})", data, length);

log.debug("bulkOutTransfer (data={},length={})", getAsHex(data), length);

ByteBuffer buffer = BufferUtils.allocateByteBuffer(data.length);
buffer.put(data);
Expand All @@ -120,7 +122,7 @@ public int bulkOutTransfer(byte[] data, int offset, int length) throws LibAumsE
return bulkOutTransfer(data, length);
}

log.debug("bulkOutTransfer(offset): (data={},length={},offset={})", data, length, offset);
log.debug("bulkOutTransfer(offset): (data={},length={},offset={})", getAsHex(data), length, offset);

int remaining = length-offset;
byte[] newData = new byte[length-offset];
Expand Down Expand Up @@ -167,7 +169,7 @@ public int bulkInTransfer(byte[] data, int length) throws LibAumsException {
buffer.get(data);
}

log.debug("bulkInTransfer: Data Returned: {}", data);
log.debug("bulkInTransfer: Data returned: {}", getAsHex(data));

return transferredCount;
}
Expand Down Expand Up @@ -200,7 +202,7 @@ public int bulkInTransfer(byte[] data, int offset, int length) throws LibAumsEx
buffer.get(data, offset, length);
}

log.debug("bulkInTransfer(offset): Data Returned: {}", data);
log.debug("bulkInTransfer(offset): Data returned: {}", getAsHex(data));

return transferredCount;
}
Expand All @@ -211,7 +213,7 @@ public void closeDevice() throws LibAumsException {
log.warn("closeDevice: device {} is already closed. Exiting.", deviceConfig.getReadableDeviceId());
return;
}
log.info("closeDevice: closing device {}", deviceConfig.getReadableDeviceId());
log.debug("closeDevice: closing device {}", deviceConfig.getReadableDeviceId());

if (deviceIsOpenAndClaimed) {
// Release interface
Expand All @@ -227,4 +229,16 @@ public void closeDevice() throws LibAumsException {
log.info("closeDevice: device {} closed and interface released", deviceConfig.getReadableDeviceId());
deviceHandle = null;
}

private String getAsHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("0x%02X ", b));
}
return sb.toString();
}

public String getReadableDeviceName() {
return this.deviceConfig.getReadableDeviceId();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,10 @@ public interface UsbCommunication {
* @see #bulkInTransfer(byte[], int)
*/
public int bulkInTransfer(byte[] buffer, int offset, int length) throws LibAumsException;

/**
* Returns readable device name in form xxxx:yyyy (needed just for information purposes)
* @return
*/
String getReadableDeviceName();
}
Original file line number Diff line number Diff line change
Expand Up @@ -213,18 +213,22 @@ public static UsbMassStorageDevice getMassStorageDevice(UsbMassStorageDeviceConf
}

public static List<UsbMassStorageDeviceConfig> getListOfAttachedUsbMassStorageDevices() throws LibAumsException {
return getListOfAttachedUsbMassStorageDevices(null, null);
}

public static List<UsbMassStorageDeviceConfig> getListOfAttachedUsbMassStorageDevices(Integer filterVendor, Integer filterProduct) throws LibAumsException {
// TODO add filtering
List<UsbMassStorageDeviceConfig> outList = new ArrayList<>();

List<ATUsbDevice> deviceList = Usb4JavaManager.getDeviceList();

for (ATUsbDevice device : deviceList) {
log.info("found usb device: " + device);
log.debug("Found usb device: " + device);

//int interfaceCount = device.getInterfaceCount();
//for (int i = 0; i < interfaceCount; i++) {
ATUsbInterface usbInterfaceRoot = device.getInterface(0); //read mass storage not HID interface. HID interface is 1
log.info( "found usb interface: " + usbInterfaceRoot);
//log.debug("found usb interface: " + usbInterfaceRoot);

for (ATUsbInterfaceDescriptor usbInterface : usbInterfaceRoot.altsettings()) {

Expand All @@ -233,7 +237,7 @@ public static List<UsbMassStorageDeviceConfig> getListOfAttachedUsbMassStorageDe
if (usbInterface.bInterfaceClass() != USB_CLASS_MASS_STORAGE ||
usbInterface.bInterfaceSubClass() != MASS_STORAGE_SUBCLASS_SCSI ||
usbInterface.bInterfaceProtocol() != MASS_STORAGE_PROTOCOL_BBB_BULK_ONLY) {
log.info("Device interface not suitable ! Found class={},subclass={},protocol={}), required=8/6/80 (Mass Storage/SCSI/Bulk-Only)",
log.debug(" Device interface not suitable ! Found class={},subclass={},protocol={}), required=8/6/80 (Mass Storage/SCSI/Bulk-Only)",
usbInterface.bInterfaceClass(),
usbInterface.bInterfaceSubClass(),
usbInterface.bInterfaceProtocol());
Expand All @@ -244,14 +248,14 @@ public static List<UsbMassStorageDeviceConfig> getListOfAttachedUsbMassStorageDe
// One IN and one OUT endpoint
int endpointCount = usbInterface.bNumEndpoints();
if (endpointCount != 2) {
log.warn("interface endpoint count != 2");
log.debug(" interface endpoint count != 2");
}

ATUsbEndpointDescriptor outEndpoint = null;
ATUsbEndpointDescriptor inEndpoint = null;
for (int j = 0; j < endpointCount; j++) {
ATUsbEndpointDescriptor endpoint = usbInterface.getEndpoint(j);
log.info( "found usb endpoint: " + endpoint);
log.debug(" found usb endpoint: " + endpoint);
if (endpoint.getTransferType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
if (endpoint.getDirection() == UsbConstants.USB_DIR_OUT) {
outEndpoint = endpoint;
Expand All @@ -262,17 +266,21 @@ public static List<UsbMassStorageDeviceConfig> getListOfAttachedUsbMassStorageDe
}

if (outEndpoint == null || inEndpoint == null) {
log.error("Not all needed endpoints found!");
log.debug(" Not all needed endpoints found!");
continue;
}

outList.add(UsbMassStorageDeviceConfig.builder()
.vendorId(device.getUsbDeviceDescriptor().idVendor())
.productId(device.getUsbDeviceDescriptor().idProduct())
.interfaceNumber(usbInterface.bInterfaceNumber())
.inEndpointAddress(inEndpoint.bEndpointAddress())
.outEndpointAddress(outEndpoint.bEndpointAddress())
.build());
UsbMassStorageDeviceConfig config = UsbMassStorageDeviceConfig.builder()
.vendorId(device.getUsbDeviceDescriptor().idVendor())
.productId(device.getUsbDeviceDescriptor().idProduct())
.interfaceNumber(usbInterface.bInterfaceNumber())
.inEndpointAddress(inEndpoint.bEndpointAddress())
.outEndpointAddress(outEndpoint.bEndpointAddress())
.build();

log.info(" Device is relevant: {}", config.getReadableDeviceId());

outList.add(config);
}
}

Expand Down Expand Up @@ -306,18 +314,18 @@ public void init() throws LibAumsException {
* @see #init()
*/
private void setupDevice() throws LibAumsException {
log.info("Init device {}", usbMassStorageDeviceConfig.getReadableDeviceId());
log.debug("Init device {}", usbMassStorageDeviceConfig.getReadableDeviceId());
communication = new Usb4JavaUsbDeviceCommunication(this.usbMassStorageDeviceConfig);
communication.openDevice();

this.connectedToDevice = true;

log.info("Create Block Device for {}", usbMassStorageDeviceConfig.getReadableDeviceId());
log.debug("Create Block Device for {}", usbMassStorageDeviceConfig.getReadableDeviceId());
blockDevice = BlockDeviceDriverFactory.createBlockDevice(communication);
blockDevice.init();

if (loadPartitionTable) {
log.info("Create Partition Table for {}", usbMassStorageDeviceConfig.getReadableDeviceId());
log.debug("Create Partition Table for {}", usbMassStorageDeviceConfig.getReadableDeviceId());
partitionTable = PartitionTableFactory.createPartitionTable(blockDevice);
initPartitions();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public void init() throws LibAumsException {
transferCommand(inquiry, inBuffer);
// TODO support multiple luns!
ScsiInquiryResponse inquiryResponse = ScsiInquiryResponse.read(inBuffer);
log.debug( "inquiry response: " + inquiryResponse);
log.debug("inquiry response: " + inquiryResponse);

if (inquiryResponse.getPeripheralQualifier() != 0
|| inquiryResponse.getPeripheralDeviceType() != 0) {
Expand All @@ -101,8 +101,8 @@ public void init() throws LibAumsException {
blockSize = readCapacityResponse.getBlockLength();
lastBlockAddress = readCapacityResponse.getLogicalBlockAddress();

log.info( "Block size: " + blockSize);
log.info( "Last block address: " + lastBlockAddress);
log.debug("Block size: " + blockSize);
log.debug("Last block address: " + lastBlockAddress);
}

/**
Expand Down Expand Up @@ -203,7 +203,7 @@ public synchronized void read(long devOffset, ByteBuffer dest) throws LibAumsExc
// blockSize and making it global
ByteBuffer buffer;
if (dest.remaining() % blockSize != 0) {
log.warn( "we have to round up size to next block sector");
log.debug("WARNING: we have to round up size to next block sector");
int rounded = blockSize - dest.remaining() % blockSize + dest.remaining();
buffer = ByteBuffer.allocate(rounded);
buffer.limit(rounded);
Expand Down Expand Up @@ -236,7 +236,7 @@ public synchronized void write(long devOffset, ByteBuffer src) throws LibAumsExc
// blockSize and making it global
ByteBuffer buffer;
if (src.remaining() % blockSize != 0) {
log.warn( "we have to round up size to next block sector");
log.debug("WARNING: we have to round up size to next block sector");
int rounded = blockSize - src.remaining() % blockSize + src.remaining();
buffer = ByteBuffer.allocate(rounded);
buffer.limit(rounded);
Expand All @@ -258,4 +258,11 @@ public synchronized void write(long devOffset, ByteBuffer src) throws LibAumsExc
public int getBlockSize() {
return blockSize;
}

public String toString() {
return String.format("ScsiBlockDevice [device=%s,blockSize=%d,lastBlockAddress=%d]",
this.usbCommunication.getReadableDeviceName(),
blockSize,
lastBlockAddress);
}
}

0 comments on commit a5155b0

Please sign in to comment.