目前在网络上查询java与usb的设备通信资源都非常的少大多都来自一个05年的文章,本人也摘取了网上的例子,例子中直接运行也出现了一些问题,经过debug还是可以直接在windows上直接使用java向usb设备发送指令并接受返回值的.接下来贴出代码供大家参考
import java.util.List;
import javax.usb.UsbConfiguration;
import javax.usb.UsbDevice;
import javax.usb.UsbDeviceDescriptor;
import javax.usb.UsbEndpoint;
import javax.usb.UsbHostManager;
import javax.usb.UsbHub;
import javax.usb.UsbInterface;
import javax.usb.UsbInterfacePolicy;
import javax.usb.UsbPipe;
public class UsbTest {
//下边两个参数为系统中usb设备的VID和PID 需要自行配置
private static short idVendor = (short)0xFFFF;
private static short idProduct = (short)0x0001;
public static void main(String[] args) {
try {
UsbPipe sendUsbPipe = new UsbTest().useUsb();
//本人测试时 是使用公司的一个读卡器主要对银行卡和身份证进行读取写等相关操作
//下边为发送的指令,目前大多usb硬件设备都是接受HEX 16进制指令
//那么如下指令为:363600028000000280 的16进制指令 注意2位为一组16进制字符
buff[0] = (byte)0x36;
buff[1] = (byte)0x36;
buff[2] = (byte)0x00;
buff[3] = (byte)0x02;
buff[4] = (byte)0x80;
buff[5] = (byte)0x00;
buff[6] = (byte)0x00;
buff[7] = (byte)0x02;
buff[8] = (byte)0x80;
sendMassge(sendUsbPipe, buff);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public UsbPipe useUsb() throws Exception{
UsbInterface iface = linkDevice();
if (iface == null) {
return null;
}
UsbEndpoint receivedUsbEndpoint,sendUsbEndpoint;
sendUsbEndpoint = (UsbEndpoint)iface.getUsbEndpoints().get(0);
if (!sendUsbEndpoint.getUsbEndpointDescriptor().toString().contains("OUT")) {
receivedUsbEndpoint = sendUsbEndpoint;
sendUsbEndpoint = (UsbEndpoint)iface.getUsbEndpoints().get(1);
} else {
receivedUsbEndpoint = (UsbEndpoint)iface.getUsbEndpoints().get(1);
}
//发送:
UsbPipe sendUsbPipe = sendUsbEndpoint.getUsbPipe();
sendUsbPipe.open();
//接收
final UsbPipe receivedUsbPipe = receivedUsbEndpoint.getUsbPipe();
receivedUsbPipe.open();
new Thread(new Runnable() {
public void run() {
try {
receivedMassge(receivedUsbPipe);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
return sendUsbPipe;
}
public UsbInterface linkDevice() throws Exception{
UsbDevice device = null;
if (device == null) {
device = findDevice(UsbHostManager.getUsbServices()
.getRootUsbHub());
}
if (device == null) {
System.out.println("设备未找到!");
return null;
}
UsbConfiguration configuration = device.getActiveUsbConfiguration();
UsbInterface iface = null;
if (configuration.getUsbInterfaces().size() > 0) {
//此处需要注意 本人在这个地方的时候是进行了debug来看设备到底在map中的key是多少
//各位如果在此处获取不到设备请自行进行debug看map中存储的设备key到底是多少
iface = configuration.getUsbInterface((byte) 0);
} else {
return null;
}
iface.claim(new UsbInterfacePolicy()
{
@Override
public boolean forceClaim(UsbInterface usbInterface)
{
return true;
}
});
return iface;
}
public void receivedMassge(UsbPipe usbPipe) throws Exception{
StringBuffer all = new StringBuffer();
byte[] b = new byte[64];
int length;
while (true) {
length = usbPipe.syncSubmit(b);//阻塞
System.out.println("接收长度:" + length);
for (int i = 0; i < length; i++) {
//此处会打印所有的返回值 注意返回值全部也都是16进制的
//比如读取卡号或者身份证号时需要自行转换回10进制
//并进行补0操作,比如01转换为10进制会变成1需要补0 变成01
//不然得到的10进制返回值会有问题
System.out.print(Byte.toUnsignedInt(b[i])+" ");
all.append(Byte.toUnsignedInt(b[i])+" ");
}
}
}
public static void sendMassge(UsbPipe usbPipe,byte[] buff) throws Exception{
//此处为阻塞和非阻塞 非常好理解和多线程一个道理不再解释
usbPipe.syncSubmit(buff);//阻塞
//usbPipe.asyncSubmit(buff);//非阻塞
}
public UsbDevice findDevice(UsbHub hub)
{
UsbDevice device = null;
List list = (List) hub.getAttachedUsbDevices();
for (int i = 0;i<list.size();i++)
{
device = (UsbDevice)list.get(i);
UsbDeviceDescriptor desc = device.getUsbDeviceDescriptor();
System.out.println(i+"___"+desc.idVendor()+"___"+desc.idProduct());
if (desc.idVendor() == idVendor && desc.idProduct() == idProduct) {return device;}
if (device.isUsbHub()){
device = findDevice((UsbHub) device);
if (device != null) return device;
}
}
return null;
}
}
PID和VIP如下图: 0458为VID 003A为PID
另外还需要在resources文件夹中添加配置文件 名称为:javax.usb.properties
配置文件中内容为:
javax.usb.services = org.usb4java.javax.Services
保险起见pom中添加如下配置:
<dependency>
<groupId>org.usb4java</groupId>
<artifactId>usb4java-javax</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>javax.usb</groupId>
<artifactId>usb-api</artifactId>
<version>1.0.2</version>
</dependency>
<dependency>
<groupId>javax.usb</groupId>
<artifactId>usb-api</artifactId>
<version>1.0.2</version>
<classifier>sources</classifier>
</dependency>
PS:这个java端的usb方法非常的老支持的usb2.0版本虽然现在的3.0版本也能用但是会发生插拔了之后不能使用,这方面我尝试了很久进行重连但是都失败了,所以非万不得已还是尽量不要使用这个在生产使用好一些,可以用C#来做很容易避免这样的问题java真的很不友好
在java端如果想做成插件可以使用servlet做一个启动类打一个jar包放入到jre中,之后我们在写一个bat脚本就可以实现javausb插件在windows中使用了