基于usb4java实现的java下的usb通信
项目地址:点击打开
使用java开发的好处就是跨平台,基本上java的开发的程序在linux、mac、MS上都可以运行,对应这java的那句经典名言:一次编写,到处运行。这个项目里面有两种包选择,一个是low-level(libus)一个是high-level(javax-usb),相关的优缺点在官方网站上已经说明了,我这里就不翻译了,不过前者好像基于libusb已经好久不更新了,所以还是选择后者。
配置:你需要在你包的根目录下新建一个名为:javax.usb.properties的文件,里面的内容是这样的:
javax.usb.services = org.usb4java.javax.Services
查找usb设备,其实通过usb通信流程大体上都是一致,之前我做过android与arduino通过usb通信,然后java通信走了一遍之后发现是一样的。USB 设备在一棵树上进行管理。这树的根是所有物理根集线器连接到一个虚拟的 USB集线器。更多的集线器可以连接到这些根集线器和任何集线器可以有大量的连接的 USB设备。
通常,您需要在使用它之前搜索特定设备,下面的是一个例子如何扫描与一个特定的供应商和产品 id 的第一个设备的设备:
public UsbDevice findDevice(UsbHub hub, short vendorId, short productId)
{
for (UsbDevice device : (List<UsbDevice>) hub.getAttachedUsbDevices())
{
UsbDeviceDescriptor desc = device.getUsbDeviceDescriptor();
if (desc.idVendor() == vendorId && desc.idProduct() == productId) return device;
if (device.isUsbHub())
{
device = findDevice((UsbHub) device, vendorId, productId);
if (device != null) return device;
}
}
return null;
}
接口
当你想要与一个接口或者这个接口的端点进行通信时,那么你在使用它之前必须要claim它,并且当你结束时你必须释放它。比如:下面的代码:
UsbConfiguration configuration = device.getActiveUsbConfiguration();
UsbInterface iface = configuration.getUsbInterface((byte) 1);
iface.claim();
try
{
... Communicate with the interface or endpoints ...
}
finally
{
iface.release();
}
可能出现的一种情况是你想要通信的接口已经被内核驱动使用,在这种情况下你可能需要通过传递一个接口策略到claim方法以此尝试强制claim:
iface.claim(new UsbInterfacePolicy()
{
@Override
public boolean forceClaim(UsbInterface usbInterface)
{
return true;
}
});
需要注意的是,接口策略只是为了实现基础USB的一个提示.接口策略在MS-Windows上将被忽略,因为libusb在windows上不支持分派驱动。
同步 I/O
这个example发送8个字节到端点0x03:
UsbEndpoint endpoint = iface.getUsbEndpoint(0x03);
UsbPipe pipe = endpoint.getUsbPipe();
pipe.open();
try
{
int sent = pipe.syncSubmit(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 });
System.out.println(sent + " bytes sent");
}
finally
{
pipe.close();
}
这个example是从端点0x83读取8个字节:
UsbEndpoint endpoint = iface.getUsbEndpoint((byte) 0x83);
UsbPipe pipe = endpoint.getUsbPipe();
pipe.open();
try
{
byte[] data = new byte[8];
int received = pipe.syncSubmit(data);
System.out.println(received + " bytes received");
}
finally
{
pipe.close();
}
异步 I/O
同步I/O操作与异步I/O操作类似,仅仅是使用asyncSubmint方法取代syncSubmit方法。syncSubmit方法将会阻塞直到请求完成,而asyncSubmit不会阻塞并且立即返回,为了接受请求的返回,你必须为Pipe添加一个监听器,像下面这样:
pipe.addUsbPipeListener(new UsbPipeListener()
{
@Override
public void errorEventOccurred(UsbPipeErrorEvent event)
{
UsbException error = event.getUsbException();
... Handle error ...
} @Override
public void dataEventOccurred(UsbPipeDataEvent event)
{
byte[] data = event.getData();
... Process received data ...
}
});
遇到的问题:在Linux上不能打开设备Device,其实是权限的问题导致的,你应该知道在Linux下权限分配是一门很重要的学问,其实该问题在官方网站的FAQ一栏已经提供了解决的办法,地址:点击打开
在Linux环境下,你需要给你想要通信的usb设备写一个许可文件。在此之前,你可以以root用户运行你的程序检查设备是否可以获取,如果有上述操作有作用,那么我推荐配置下udev以便当设备连接上后你的用户拥有对设备写的权限
SUBSYSTEM=="usb",ATTR{idVendor}=="89ab",ATTR{idProduct}=="4567",MODE="0660",GROUP="wheel"
需要该更改的就是PID、VID、GROUP,关于PID和VID信息以及查看相关的接口、端口信息的查看,linux下可以使用一个叫usbview的软件,软件安装很简单,仅仅一条命令:
sudo apt-get insall usbview
注意启动的时候需要权限,而且还需要以图形界面显示(sudo usbview在我的Linux Mint没有反应的):
sudo gksu usbview
参考官方写的一段简单的代码:
package nir.desktop.demo; import java.util.List; import javax.usb.UsbConfiguration;
import javax.usb.UsbConst;
import javax.usb.UsbControlIrp;
import javax.usb.UsbDevice;
import javax.usb.UsbDeviceDescriptor;
import javax.usb.UsbEndpoint;
import javax.usb.UsbException;
import javax.usb.UsbHostManager;
import javax.usb.UsbHub;
import javax.usb.UsbInterface;
import javax.usb.UsbInterfacePolicy;
import javax.usb.UsbPipe;
import javax.usb.event.UsbPipeDataEvent;
import javax.usb.event.UsbPipeErrorEvent;
import javax.usb.event.UsbPipeListener; public class UsbConn {
private static final short VENDOR_ID = 0x2341;
/** The product ID of the missile launcher. */
private static final short PRODUCT_ID = 0x43;
// private static final short VENDOR_ID = 0x10c4;
// // /** The product ID of the missile launcher. */
// private static final short PRODUCT_ID = -5536;
private static UsbPipe pipe81, pipe01; /**
* 依据VID和PID找到设备device
*
* @param hub
* @return
*/
@SuppressWarnings("unchecked")
public static UsbDevice findMissileLauncher(UsbHub hub) {
UsbDevice launcher = null; for (UsbDevice device : (List<UsbDevice>) hub.getAttachedUsbDevices()) {
if (device.isUsbHub()) {
launcher = findMissileLauncher((UsbHub) device);
if (launcher != null)
return launcher;
} else {
UsbDeviceDescriptor desc = device.getUsbDeviceDescriptor();
if (desc.idVendor() == VENDOR_ID
&& desc.idProduct() == PRODUCT_ID) {
System.out.println("找到设备:" + device);
return device;
}
}
}
return null;
} public static void sendMessage(UsbDevice device, byte[] message)
throws UsbException {
UsbControlIrp irp = device
.createUsbControlIrp(
(byte) (UsbConst.REQUESTTYPE_TYPE_CLASS | UsbConst.REQUESTTYPE_RECIPIENT_INTERFACE),
(byte) 0x09, (short) 2, (short) 1);
irp.setData(message);
device.syncSubmit(irp);
} /**
* 注意权限的配置问题,在linux下可能无法打开device,解决办法参考官方的FAQ
*
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
UsbDevice device;
try {
device = findMissileLauncher(UsbHostManager.getUsbServices()
.getRootUsbHub());
if (device == null) {
System.out.println("Missile launcher not found.");
System.exit(1);
return;
}
UsbConfiguration configuration = device.getActiveUsbConfiguration();//获取配置信息
UsbInterface iface = configuration.getUsbInterface((byte) 1);//接口
iface.claim(new UsbInterfacePolicy() { @Override
public boolean forceClaim(UsbInterface arg0) {
// TODO Auto-generated method stub
return true;
}
});
// for (UsbEndpoint endpoints : (List<UsbEndpoint>) iface
// .getUsbEndpoints()) {
// System.out.println("--->"+endpoints.getUsbEndpointDescriptor());
// }
UsbEndpoint endpoint81 = iface.getUsbEndpoint((byte) 0x83);//接受数据地址
UsbEndpoint endpoint01 = iface.getUsbEndpoint((byte)0x04);//发送数据地址
pipe81 = endpoint81.getUsbPipe();
pipe81.open();
pipe01 = endpoint01.getUsbPipe();
pipe01.open();
byte[] dataSend = { (byte) 0x00 };//需要发送的数据
pipe01.asyncSubmit(dataSend);
pipe81.addUsbPipeListener(new UsbPipeListener() { @Override
public void errorEventOccurred(UsbPipeErrorEvent arg0) {
// TODO Auto-generated method stub
System.out.println(arg0);
} @Override
public void dataEventOccurred(UsbPipeDataEvent arg0) {
// TODO Auto-generated method stub
System.out.println(new String(arg0.getData()));
}
});
// pipe81.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
//
}
}
}
其中的一些接口、端口都是依据usbview写的,数据是发成功了(RX灯亮了),但是因为我使用的是arduino,里面的代码不知道怎么写,如果有这方便的高手还请帮我一下,谢谢。翻墙看了下有的人用的是同步传输出现的问题,相关的解决办法,这里我就完全粘贴、复制了:Here is an abbreviated example. Note that I have removed from this, allchecks, error handling, and such.It is just the logic of creating two pipes for two endpoints. One IN andone OUT. Then using them to do a write and a read.It assumes that endpoint 2 is an OUT and endpoint 4 is an IN.Note also that the name of an IN endpoint is OR'd with 0x80:
import javax.usb.*; public class Example { public static void main(String[] args) throws Exception {
UsbDevice usbDevice = ...getUsbDevice by matching vID, pID, knowing
the path... or whatever works for you...
usbDevice.getUsbConfigurations();
UsbConfiguration config = usbDevice.getActiveUsbConfiguration();
UsbInterface xface = config.getUsbInterface((byte)0);
xface.claim(); UsbEndpoint endPt2 = xface.getUsbEndpoint((byte)2); //OUT
endpoint
UsbEndpoint endPt4 = xface.getUsbEndpoint((byte)(4 | 0x80) ); //IN
endpoint UsbPipe pipe2 = endPt2.getUsbPipe();
pipe2.open();
UsbPipe pipe4 = endPt4.getUsbPipe();
pipe4.open(); //Use the pipes:
byte[] bytesToSend = new byte[] {1,2,3}; //Going to send out these 3
bytes
UsbIrp irpSend = pipe2.createUsbIrp();
irpSend.setData(bytesToSend);
pipe2.asyncSubmit(irpSend); //Send out some bytes
irpSend.waitUntilComplete(1000); //Wait up to 1 second byte[] bytesToRead = new byte[3]; //Going to read 3 bytes into here
UsbIrp irpRead = pipe2.createUsbIrp();
irpRead.setData(bytesToRead);
pipe4.asyncSubmit(irpRead); //Read some bytes
irpRead.waitUntilComplete(1000); //Wait up to 1 second
}
}
下面是我监听数据返回点完整代码:
UsbConn.java:
package DemoMath; import java.util.List; import javax.usb.UsbConfiguration;
import javax.usb.UsbConst;
import javax.usb.UsbControlIrp;
import javax.usb.UsbDevice;
import javax.usb.UsbDeviceDescriptor;
import javax.usb.UsbEndpoint;
import javax.usb.UsbException;
import javax.usb.UsbHostManager;
import javax.usb.UsbHub;
import javax.usb.UsbInterface;
import javax.usb.UsbInterfacePolicy;
import javax.usb.UsbPipe;
import javax.usb.util.UsbUtil; public class UsbConn {
private static final short VENDOR_ID = 0x04b4;
private static final short PRODUCT_ID = 0x1004;
private static final byte INTERFACE_AD= 0x00;
private static final byte ENDPOINT_OUT= 0x02;
private static final byte ENDPOINT_IN= (byte) 0x86;
private static final byte[] COMMAND = {0x01,0x00}; @SuppressWarnings("unchecked")
public static UsbDevice findMissileLauncher(UsbHub hub) {
UsbDevice launcher = null; for (UsbDevice device : (List<UsbDevice>) hub.getAttachedUsbDevices()) {
if (device.isUsbHub()) {
launcher = findMissileLauncher((UsbHub) device);
if (launcher != null)
return launcher;
} else {
UsbDeviceDescriptor desc = device.getUsbDeviceDescriptor();
if (desc.idVendor() == VENDOR_ID
&& desc.idProduct() == PRODUCT_ID) {
System.out.println("发现设备" + device);
return device;
}
}
}
return null;
}
//command for controlTransfer
public static void sendMessage(UsbDevice device, byte[] message)
throws UsbException {
UsbControlIrp irp = device
.createUsbControlIrp(
(byte) (UsbConst.REQUESTTYPE_TYPE_CLASS | UsbConst.REQUESTTYPE_RECIPIENT_INTERFACE),
(byte) 0x09, (short) , (short) );
irp.setData(message);
device.syncSubmit(irp);
}
/**
* Class to listen in a dedicated Thread for data coming events.
* This really could be used for any HID device.
*/
public static class HidMouseRunnable implements Runnable
{
/* This pipe must be the HID interface's interrupt-type in-direction endpoint's pipe. */
public HidMouseRunnable(UsbPipe pipe) { usbPipe = pipe; }
public void run()
{
byte[] buffer = new byte[UsbUtil.unsignedInt(usbPipe.getUsbEndpoint().getUsbEndpointDescriptor().wMaxPacketSize())];
@SuppressWarnings("unused")
int length = ; while (running) {
try {
length = usbPipe.syncSubmit(buffer);
} catch ( UsbException uE ) {
if (running) {
System.out.println("Unable to submit data buffer to HID mouse : " + uE.getMessage());
break;
}
}
if (running) {
// System.out.print("Got " + length + " bytes of data from HID mouse :");
// for (int i=0; i<length; i++)
// System.out.print(" 0x" + UsbUtil.toHexString(buffer[i]));
try {
String result = DataFix.getHexString(buffer);
System.out.println(result);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
/**
* Stop/abort listening for data events.
*/
public void stop()
{
running = false;
usbPipe.abortAllSubmissions();
}
public boolean running = true;
public UsbPipe usbPipe = null;
}
/**
* get the correct Interface for USB
* @param device
* @return
* @throws UsbException
*/
public static UsbInterface readInit() throws UsbException{
UsbDevice device = findMissileLauncher(UsbHostManager.getUsbServices()
.getRootUsbHub());
if (device == null) {
System.out.println("Missile launcher not found.");
System.exit();
}
UsbConfiguration configuration = device.getActiveUsbConfiguration();
UsbInterface iface = configuration.getUsbInterface(INTERFACE_AD);//Interface Alternate Number
//if you using the MS os,may be you need judge,because MS do not need follow code,by tong
iface.claim(new UsbInterfacePolicy() {
@Override
public boolean forceClaim(UsbInterface arg0) {
// TODO Auto-generated method stub
return true;
}
});
return iface;
}
/**
* 异步bulk传输,by tong
* @param usbInterface
* @param data
*/
public static void syncSend(UsbInterface usbInterface,byte[] data) {
UsbEndpoint endpoint = usbInterface.getUsbEndpoint(ENDPOINT_OUT);
UsbPipe outPipe = endpoint.getUsbPipe();
try {
outPipe.open();
outPipe.syncSubmit(data);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
outPipe.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static HidMouseRunnable listenData(UsbInterface usbInterface) {
UsbEndpoint endpoint = usbInterface.getUsbEndpoint(ENDPOINT_IN);
UsbPipe inPipe = endpoint.getUsbPipe();
HidMouseRunnable hmR = null;
try {
inPipe.open();
hmR = new HidMouseRunnable(inPipe);
Thread t = new Thread(hmR);
t.start();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return hmR;
}
/**
* 主程序入口
*
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
UsbInterface iface;
try {
iface = readInit();
listenData(iface);
syncSend(iface, COMMAND);
} catch (UsbException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
基于usb4java实现的java下的usb通信的更多相关文章
- java下的串口通信-RXTX
关于java实现的串口通信,使用的是开源项目RXTX,之前sun公司也有JCL项目,不过已经很久没有更新了,RXTX项目地址:点击打开,但是两个项目的API用法是一样的,只是导入的包不一样而已.简单的 ...
- Java 下实现锁无关数据结构--转载
介绍 通常在一个多线程环境下,我们需要共享某些数据,但为了避免竞争条件引致数据出现不一致的情况,某些代码段需要变成原子操作去执行.这时,我们便需要利用各种同步机制如互斥(Mutex)去为这些代码段加锁 ...
- 基于ZedBoard的Webcam设计(一):USB摄像头(V4L2接口)的图片采集【转】
转自:http://www.cnblogs.com/surpassal/archive/2012/12/19/zed_webcam_lab1.html 一直想把USB摄像头接到Zedboard上,搭建 ...
- Delphi在Android下实现BroadcastReceiver功能(举例在Delphi下获取USB外设拔插消息)
在Android里,用java通过实现BroadcastReceiver接口,就可以获得Intent消息.可是Delphi程序不能直接实现JBroadcastReceiver,如何能够实现类似Java ...
- 基于AQS实现的Java并发工具类
本文主要介绍一下基于AQS实现的Java并发工具类的作用,然后简单谈一下该工具类的实现原理.其实都是AQS的相关知识,只不过在AQS上包装了一下而已.本文也是基于您在有AQS的相关知识基础上,进行讲解 ...
- Android 下的usb框架及功能点【转】
本文转载自:https://blog.csdn.net/tianruxishui/article/details/37902959 有关USB android框架的链接 http://blog.sin ...
- Java下好用的开源库推荐
作者:Jack47 转载请保留作者和原文出处 欢迎关注我的微信公众账号程序员杰克,两边的文章会同步,也可以添加我的RSS订阅源. 本文想介绍下自己在Java下做开发使用到的一些开源的优秀编程库,会不定 ...
- 基于jQuery的input输入框下拉提示层(自动邮箱后缀名)
基于jQuery的input输入框下拉提示层,方便用户输入邮箱时的提示信息,需要的朋友可以参考下 效果图 // JavaScript Document (function($){ $.fn ...
- Java下利用Jackson进行JSON解析和序列化
Java下利用Jackson进行JSON解析和序列化 Java下常见的Json类库有Gson.JSON-lib和Jackson等,Jackson相对来说比较高效,在项目中主要使用Jackson进行 ...
随机推荐
- swagger接口变动监控
版本与版本之间迭代,总会发生接口的变化,而这些变化开发不会都告诉测试,测试需要把全部接口检查一遍,这样就降低了测试效率. 为了解决这个问题,结合公司实际项目进行了以下设计: 1.对比测试环境swagg ...
- Python-读入json文件并进行解析及json基本操作
import json def resolveJson(path): file = open(path, "rb") fileJson = json.load(file) fi ...
- 联想yoga table2 1371f 进入bios 的巧妙方法
win8.1 的平板,无键盘,触屏失灵,接了个鼠标 我在这里向大家介绍最后一个方法<ignore_js_op>▲在metro界面下找到设置选项 <ignore_js_op> ...
- webuploader 多图片上传
WebUploader是由Baidu WebFE(FEX)团队开发的一个简单的以HTML5为主,FLASH为辅的现代文件上传组件. 具体接口参考 webuploader接口文档地址 一.图片上传功能 ...
- linux根文件系统 /etc/resolv.conf 文件详解(转)
大家好,今天51开源给大家介绍一个在配置文件,那就是/etc/resolv.conf.很多网友对此文件的用处不太了解.其实并不复杂,它是DNS客户机配置文件,用于设置DNS服务器的IP地址及DNS域名 ...
- [golang note] 变量常量
变量 • 变量声明 √ golang变量声明的关键字为var. √ golang变量声明时类型信息放置在变量名之后. ▶ 单个变量声明 ▪ 语法如下 var name type ▪ 示例如下 var ...
- 性能调优之MySQL篇四:MySQL配置定位以及优化
一.CPU最大性能模式 cpu利用特点 5.1 最高可用4个核 5.5 最高可用24核 5.6 最高可用64核心 一次query对应一个逻辑CPU 你仔细检查的话,有些服务器上会有的一个有趣的现象:你 ...
- C#小票打印机动态纸张尺寸
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- TOSCA自动化测试工具--Log defect
1.执行完用例后,对于失败的用例进行分析,如果有缺陷,可以提对应的缺陷 2.在issues模块, 右键创建自己需要的文件夹,然后在文件夹上右键找到虫子图形点下,就可以创建缺陷了,填上对应的内容 3.如 ...
- CSS3 Gradients(渐变)
CSS3 Gradients(渐变) 一.简介 CSS3 渐变(gradients)可以让你在两个或多个指定的颜色之间显示平稳的过渡. 以前,你必须使用图像来实现这些效果.但是,通过使用 CSS3 渐 ...