- 主机通过HID协议与USB设备通信,Google提供了controlTransfer和bulkTransfer的方式
frameworks/base/core/java/android/hardware/usb/UsbDeviceConnection.java
bulkTransfer是通过筛选endpoint的方式,controlTransfer 则是根据协议定义好的这三个参数
(int requestType, int request, int value, int index)
public int controlTransfer(int requestType, int request, int value, int index,
byte[] buffer, int offset, int length, int timeout) {
checkBounds(buffer, offset, length);
return native_control_request(requestType, request, value, index,
buffer, offset, length, timeout);
}
public int bulkTransfer(UsbEndpoint endpoint,
byte[] buffer, int length, int timeout) {
return bulkTransfer(endpoint, buffer, 0, length, timeout);
}
- 每个usb pidvid提供好几个interface通道 ,每个interface提供最多俩endpoint
06-28 12:55:36.964 D/UsbHostManager( 1580): UsbConfiguration[mId=1,mName=USB-3.0,mAttributes=224,mMaxPower=112,mInterfaces=[
06-28 12:55:36.964 D/UsbHostManager( 1580): UsbInterface[mId=0,mAlternateSetting=0,mName=null,mClass=14,mSubclass=1,mProtocol=0,mEndpoints=[
06-28 12:55:36.964 D/UsbHostManager( 1580): UsbEndpoint[mAddress=130,mAttributes=3,mMaxPacketSize=64,mInterval=4]]
06-28 12:55:36.964 D/UsbHostManager( 1580): UsbInterface[mId=1,mAlternateSetting=0,mName=null,mClass=14,mSubclass=2,mProtocol=0,mEndpoints=[]
06-28 12:55:36.964 D/UsbHostManager( 1580): UsbInterface[mId=1,mAlternateSetting=1,mName=null,mClass=14,mSubclass=2,mProtocol=0,mEndpoints=[
06-28 12:55:36.964 D/UsbHostManager( 1580): UsbEndpoint[mAddress=131,mAttributes=5,mMaxPacketSize=1024,mInterval=1
public static final int USB_DIR_OUT = ServiceProtoEnums.USB_ENDPOINT_DIR_OUT; // 0
public static final int USB_DIR_IN = ServiceProtoEnums.USB_ENDPOINT_DIR_IN; // 0x80
所以mAddress值表示in还是out
大于128 是 1 in
小于128 是 0 out
上面两种方式都可以读写数据。今天我们重点讲另外一种读取数据的方式,这种方式是阻塞式的,就是没有数据的时候等待,有数据的时候读取数据。
USBREQUEST 实现异步接收数据
简单写个例子
ByteBuffer buffer = ByteBuffer.allocate(4096);
buffer.order(ByteOrder.LITTLE_ENDIAN);
UsbRequest request = new UsbRequest();
request.initialize(mConnection, mEndpointIn);
request.queue(buffer, 4096);
if (mConnection.requestWait() == request) {
byte[] data = buffer.array();
}
它提供的API如下
20210928224938.png
-
下面我们看看读取数据的接口 public boolean queue(@Nullable ByteBuffer buffer)
我把核心代码挑出来
request->client_data = (void *)env->NewGlobalRef(thiz); //为了waitRequest能找到我们int err = usb_request_queue(request); // 调用到libusb的实现
frameworks/base/core/java/android/hardware/usb/UsbRequest.java
public boolean queue(@Nullable ByteBuffer buffer) {
// Request need to be initialized
Preconditions.checkState(mNativeContext != 0, "request is not initialized");
// Request can not be currently queued
Preconditions.checkState(!mIsUsingNewQueue, "this request is currently queued");
boolean isSend = (mEndpoint.getDirection() == UsbConstants.USB_DIR_OUT);
boolean wasQueued;
synchronized (mLock) {
mBuffer = buffer;
if (buffer == null) {
// Null buffers enqueue empty USB requests which is supported
mIsUsingNewQueue = true;
wasQueued = native_queue(null, 0, 0);
} else {
if (mConnection.getContext().getApplicationInfo().targetSdkVersion
< Build.VERSION_CODES.P) {
// Can only send/receive MAX_USBFS_BUFFER_SIZE bytes at once
Preconditions.checkArgumentInRange(buffer.remaining(), 0, MAX_USBFS_BUFFER_SIZE,
"number of remaining bytes");
}
// Can not receive into read-only buffers.
Preconditions.checkArgument(!(buffer.isReadOnly() && !isSend), "buffer can not be "
+ "read-only when receiving data");
if (!buffer.isDirect()) {
mTempBuffer = ByteBuffer.allocateDirect(mBuffer.remaining());
if (isSend) {
// Copy buffer into temporary buffer
mBuffer.mark();
mTempBuffer.put(mBuffer);
mTempBuffer.flip();
mBuffer.reset();
}
// Send/Receive into the temp buffer instead
buffer = mTempBuffer;
}
mIsUsingNewQueue = true;
wasQueued = native_queue(buffer, buffer.position(), buffer.remaining());
}
}
if (!wasQueued) {
mIsUsingNewQueue = false;
mTempBuffer = null;
mBuffer = null;
}
return wasQueued;
}
//private native boolean native_queue(ByteBuffer buffer, int offset, int length);
//接着看native方法的实现
frameworks/base/core/jni/android_hardware_UsbRequest.cpp
static jboolean
android_hardware_UsbRequest_queue(JNIEnv *env, jobject thiz, jobject buffer, jint offset,
jint length)
{
struct usb_request* request = get_request_from_object(env, thiz);
if (!request) {
ALOGE("request is closed in native_queue");
return JNI_FALSE;
}
if (buffer == NULL) {
request->buffer = NULL;
request->buffer_length = 0;
} else {
request->buffer = (void *)((char *)env->GetDirectBufferAddress(buffer) + offset);
request->buffer_length = length;
}
// Save a reference to ourselves so UsbDeviceConnection.waitRequest() can find us.
// We also need this to make sure our native buffer is not deallocated while IO is active.
request->client_data = (void *)env->NewGlobalRef(thiz);
int err = usb_request_queue(request);
if (err != 0) {
request->buffer = NULL;
env->DeleteGlobalRef((jobject)request->client_data);
return JNI_FALSE;
}
return JNI_TRUE;
}
- 从usb_request_queue 继续往下看代码,看到这个while循环是不是理解了,没有数据的时候就会在这等着。
有数据了就会往 req->buffer 也就是 queue(@Nullable ByteBuffer buffer) buffer里塞数据了。
\system\core\libusbhost\usbhost.c
int usb_request_queue(struct usb_request *req)
{
struct usbdevfs_urb *urb = (struct usbdevfs_urb*)req->private_data;
int res;
urb->status = -1;
urb->buffer = req->buffer;
urb->buffer_length = req->buffer_length;
do {
res = ioctl(req->dev->fd, USBDEVFS_SUBMITURB, urb);//这里就往驱动发明了
} while((res < 0) && (errno == EINTR));
return res;
}
网友评论