diff --git a/README.md b/README.md index 8b805e9..7300c16 100644 --- a/README.md +++ b/README.md @@ -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: ``` - - - jitpack.io - https://jitpack.io - - - - - com.atech-software - libaums-usb4java - Tag - + + + jitpack.io + https://jitpack.io + + + + + com.atech-software + libaums-usb4java + Tag + ``` 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. @@ -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 diff --git a/libaums/src/main/java/com/atech/library/usb/libaums/usb4java/examples/ExampleCreateScsiBlockDevice.java b/libaums/src/main/java/com/atech/library/usb/libaums/examples/ExampleCreateScsiBlockDevice.java similarity index 92% rename from libaums/src/main/java/com/atech/library/usb/libaums/usb4java/examples/ExampleCreateScsiBlockDevice.java rename to libaums/src/main/java/com/atech/library/usb/libaums/examples/ExampleCreateScsiBlockDevice.java index eafcf8c..019c207 100644 --- a/libaums/src/main/java/com/atech/library/usb/libaums/usb4java/examples/ExampleCreateScsiBlockDevice.java +++ b/libaums/src/main/java/com/atech/library/usb/libaums/examples/ExampleCreateScsiBlockDevice.java @@ -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; @@ -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) { @@ -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() @@ -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(); diff --git a/libaums/src/main/java/com/atech/library/usb/libaums/usb4java/Usb4JavaUsbDeviceCommunication.java b/libaums/src/main/java/com/atech/library/usb/libaums/usb4java/Usb4JavaUsbDeviceCommunication.java index c78d5da..0f44c2d 100644 --- a/libaums/src/main/java/com/atech/library/usb/libaums/usb4java/Usb4JavaUsbDeviceCommunication.java +++ b/libaums/src/main/java/com/atech/library/usb/libaums/usb4java/Usb4JavaUsbDeviceCommunication.java @@ -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.*; @@ -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; @@ -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 @@ -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()); @@ -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); @@ -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]; @@ -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; } @@ -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; } @@ -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 @@ -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(); + } } diff --git a/libaums/src/main/java/com/github/mjdev/libaums/UsbCommunication.java b/libaums/src/main/java/com/github/mjdev/libaums/UsbCommunication.java index 56096db..4c643af 100644 --- a/libaums/src/main/java/com/github/mjdev/libaums/UsbCommunication.java +++ b/libaums/src/main/java/com/github/mjdev/libaums/UsbCommunication.java @@ -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(); } diff --git a/libaums/src/main/java/com/github/mjdev/libaums/UsbMassStorageDevice.java b/libaums/src/main/java/com/github/mjdev/libaums/UsbMassStorageDevice.java index 5f65fbe..5fde469 100644 --- a/libaums/src/main/java/com/github/mjdev/libaums/UsbMassStorageDevice.java +++ b/libaums/src/main/java/com/github/mjdev/libaums/UsbMassStorageDevice.java @@ -213,18 +213,22 @@ public static UsbMassStorageDevice getMassStorageDevice(UsbMassStorageDeviceConf } public static List getListOfAttachedUsbMassStorageDevices() throws LibAumsException { + return getListOfAttachedUsbMassStorageDevices(null, null); + } + public static List getListOfAttachedUsbMassStorageDevices(Integer filterVendor, Integer filterProduct) throws LibAumsException { + // TODO add filtering List outList = new ArrayList<>(); List 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()) { @@ -233,7 +237,7 @@ public static List 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()); @@ -244,14 +248,14 @@ public static List 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; @@ -262,17 +266,21 @@ public static List 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); } } @@ -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(); } diff --git a/libaums/src/main/java/com/github/mjdev/libaums/driver/scsi/ScsiBlockDevice.java b/libaums/src/main/java/com/github/mjdev/libaums/driver/scsi/ScsiBlockDevice.java index 17f0763..afe801d 100644 --- a/libaums/src/main/java/com/github/mjdev/libaums/driver/scsi/ScsiBlockDevice.java +++ b/libaums/src/main/java/com/github/mjdev/libaums/driver/scsi/ScsiBlockDevice.java @@ -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) { @@ -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); } /** @@ -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); @@ -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); @@ -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); + } }