USB批量传输数据为端点最大数据包(比如512字节)整数倍时接收端收不到数据
USB 协议明确规定:批量传输中,当发送数据量为端点最大包大小的整数倍时,必须通过 ZLP 标记传输结束。这是应用层需要遵守的协议规范。
USB 协议规定,对于批量传输(Bulk Transfer) 模式:
- 当发送的数据量小于端点最大包大小(如 511 字节) 时,接收端会默认 “此包为完整数据”(因未填满一包),无需额外标记。
- 当发送的数据量大于端点最大包大小(如 513 字节) 时,数据会被拆分为多个包(如 512 字节 + 1 字节),接收端通过 “最后一个非满包” 判断传输结束。
- 当发送的数据量等于端点最大包大小(如 512 字节) 时,接收端无法区分 “这是完整数据” 还是 “后续仍有数据”(因刚好填满一包),此时必须通过零长度包(ZLP) 明确标记 “传输结束”。
解决方案:
比如原来发送数据的代码如下:
private void sendMessage(String msg) {byte[] bytes = msg.getBytes();Log.d(TAG, "mUsbConnection-->msg length: " + bytes.length + ";" + mEndpointOUT.getMaxPacketSize());if (mUsbConnection != null) {int result = mUsbConnection.bulkTransfer(mEndpointOUT, bytes, bytes.length, 100);if (result < 0) {Log.d(TAG, "发送失败");} else {Log.d(TAG, "发送成功" + msg);}} else {Log.d(TAG, "mUsbConnection-->null");}
增加ZLP(零长度数据包)发送代码后接收端即可正常接收512整数倍的数据包了。
private void sendMessage(String msg) {byte[] bytes = msg.getBytes();Log.d(TAG, "mUsbConnection-->msg length: " + bytes.length + ";" + mEndpointOUT.getMaxPacketSize());if (mUsbConnection != null) {int result = mUsbConnection.bulkTransfer(mEndpointOUT, bytes, bytes.length, 100);
if (bytes.length % 512 == 0) { // 若正好发送了最大包大小的整数倍,则再发送一个ZLP(零长度包),作为数据包结束标记。result = mUsbConnection.bulkTransfer(mEndpointOUT, new byte[0], 0, 100);}if (result < 0) {Log.d(TAG, "发送失败");} else {Log.d(TAG, "发送成功" + msg);}} else {Log.d(TAG, "mUsbConnection-->null");}