HarmonyOS 鸿蒙Next USB DDK 发送数据成功,但是无法接收数据
HarmonyOS 鸿蒙Next USB DDK 发送数据成功,但是无法接收数据
<markdown _ngcontent-ibh-c149="" class="markdownPreContainer">
USB DDK 发送数据成功,但是无法接收数据,接收的时候每次都是返回-7
使用步骤如下:
#define GET_DEV_HANDLE(busNum, devID) ((uint64_t)busNum << 32 | devID & 0xFFFFFFFF)
static napi_value Test(napi_env env, napi_callback_info info)
{
// 从arkts获取USB设备的busNum和devID
size_t argc = 2;
napi_value args[2] = {nullptr};
napi_get_cb_info(env, info, &argc, args , nullptr, nullptr);
int busNum;
napi_get_value_int32(env, args[0], &busNum);
int devID;
napi_get_value_int32(env, args[1], &devID);
<span class="hljs-comment">// 初始化USB DDK</span>
int32_t re = OH_Usb_Init();
LOGD(<span class="hljs-string">"OH_Usb_Init结果 : %{public}d"</span>, re);
<span class="hljs-comment">// 生成deviceId</span>
uint64_t deviceId = GET_DEV_HANDLE(value0, value1);
<span class="hljs-comment">// 获取设备描述符</span>
<span class="hljs-keyword">struct</span> UsbDeviceDescriptor devDesc = {};
int32_t re1 = OH_Usb_GetDeviceDescriptor(deviceId, &devDesc);
LOGD(<span class="hljs-string">"OH_Usb_GetDeviceDescriptor : %{public}d"</span>, re1);
LOGD(<span class="hljs-string">"OH_Usb_GetDeviceDescriptor : PID :%{public}d , VID: %{public}d"</span>, devDesc.idProduct, devDesc.idVendor);
<span class="hljs-comment">// 获取配置描述符</span>
<span class="hljs-keyword">struct</span> UsbDdkConfigDescriptor *config = <span class="hljs-keyword">nullptr</span>;
int32_t re2 = OH_Usb_GetConfigDescriptor(deviceId, <span class="hljs-number">1</span>, &config);
LOGD(<span class="hljs-string">"OH_Usb_GetConfigDescriptor : %{public}d"</span>, re2);
<span class="hljs-comment">// 获取发送端点</span>
<span class="hljs-keyword">auto</span> [res, interface, endpoint, maxPktSize] = GetInterfaceAndEndpoint(config);
LOGD(<span class="hljs-string">"GetInterfaceAndEndpoint ret %{public}d"</span>, res);
LOGD(<span class="hljs-string">"GetInterfaceAndEndpoint interface %{public}d"</span>, interface);
LOGD(<span class="hljs-string">"GetInterfaceAndEndpoint endpoint %{public}d"</span>, endpoint);
LOGD(<span class="hljs-string">"GetInterfaceAndEndpoint maxPktSize %{public}d"</span>, maxPktSize);
<span class="hljs-comment">// 获取接收端点</span>
<span class="hljs-keyword">auto</span> [resIn, interfaceIn, endpointIn, maxPktSizeIn] = GetInterfaceAndEndpointIn(config);
LOGD(<span class="hljs-string">"GetInterfaceAndEndpointIn ret %{public}d"</span>, resIn);
LOGD(<span class="hljs-string">"GetInterfaceAndEndpointIn interface %{public}d"</span>, interfaceIn);
LOGD(<span class="hljs-string">"GetInterfaceAndEndpointIn endpoint %{public}d"</span>, endpointIn);
LOGD(<span class="hljs-string">"GetInterfaceAndEndpointIn maxPktSize %{public}d"</span>, maxPktSizeIn);
<span class="hljs-comment">// 根据配置描述符,找到所需要通信的interfaceIndex</span>
<span class="hljs-comment">// 发送</span>
uint64_t interfaceHandle = <span class="hljs-number">0</span>;
int32_t re3 = OH_Usb_ClaimInterface(deviceId, interface, &interfaceHandle);
<span class="hljs-comment">// 接收</span>
uint64_t interfaceHandleIn = <span class="hljs-number">0</span>;
int32_t re3In = OH_Usb_ClaimInterface(deviceId, interfaceIn, &interfaceHandleIn);
<span class="hljs-comment">// 发送数据</span>
<span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> data[] = {<span class="hljs-number">0x01</span>, <span class="hljs-number">0x02</span>, <span class="hljs-number">0x03</span>, <span class="hljs-number">0x04</span>......};
size_t length = <span class="hljs-keyword">sizeof</span>(data) / <span class="hljs-keyword">sizeof</span>(data[<span class="hljs-number">0</span>]);
struct UsbDeviceMemMap *devMmap = nullptr;
// 创建用于存放数据的缓冲区
size_t bufferLen = length;
int32_t reMemMap = OH_Usb_CreateDeviceMemMap(deviceId, bufferLen, &devMmap);
LOGD(“OH_Usb_CreateDeviceMemMap : %{public}d”, reMemMap);
// 拷贝发送的数据
memcpy(devMmap->address, data, length);
struct UsbRequestPipe pipe;
pipe.interfaceHandle = interfaceHandle;
// 根据配置描述符找到所要通信的端点
pipe.endpoint = endpoint;
pipe.timeout = 3000;
// 发送请求
int32_t reRequest = OH_Usb_SendPipeRequest(&pipe, devMmap);
LOGD(“OH_Usb_SendPipeRequest : %{public}d”, reRequest);
LOGD(“OH_Usb_SendPipeRequest bufferLength : %{public}d”, devMmap->bufferLength);
LOGD(“OH_Usb_SendPipeRequest size : %{public}d”, devMmap->size);
LOGD(“OH_Usb_SendPipeRequest transferedLength : %{public}d”, devMmap->transferedLength);
// 释放资源
OH_Usb_DestroyDeviceMemMap(devMmap);
<span class="hljs-comment">// 接收数据</span>
struct UsbDeviceMemMap *devMmap1 = nullptr;
// 创建用于存放数据的缓冲区
size_t bufferLen1 = maxPktSizeIn;
int32_t reMemMap1 = OH_Usb_CreateDeviceMemMap(deviceId, bufferLen1, &devMmap1);
LOGD(“OH_Usb_CreateDeviceMemMap : %{public}d”, reMemMap1);
struct UsbRequestPipe pipe1;
pipe1.interfaceHandle = interfaceHandleIn;
// 根据配置描述符找到所要通信的端点
pipe1.endpoint = endpointIn;
pipe1.timeout = 3000;
// 发送请求
int32_t reRequest1 = OH_Usb_SendPipeRequest(&pipe1, devMmap1);
LOGD(“OH_Usb_ReadPipeRequest : %{public}d”, reRequest1);
LOGD(“OH_Usb_ReadPipeRequest bufferLength : %{public}d”, devMmap1->bufferLength);
LOGD(“OH_Usb_ReadPipeRequest size : %{public}d”, devMmap1->size);
LOGD(“OH_Usb_ReadPipeRequest transferedLength : %{public}d”, devMmap1->transferedLength);
OH_Usb_DestroyDeviceMemMap(devMmap1);
}
更多关于HarmonyOS 鸿蒙Next USB DDK 发送数据成功,但是无法接收数据的实战教程也可以访问 https://www.itying.com/category-93-b0.html
// 定义异步回调结构体
struct UsbTransferContext {
napi_ref callback;
napi_env env;
uint64_t deviceId;
uint8_t* buffer;
size_t bufferSize;
int32_t status;
};
// USB数据接收回调函数
void UsbReceiveCallback(struct UsbRequestPipe* pipe, struct UsbDeviceMemMap* memMap, void* context) {
UsbTransferContext* transferCtx = static_cast<UsbTransferContext*>(context);
<span class="hljs-keyword">if</span> (memMap->transferedLength > <span class="hljs-number">0</span>) {
<span class="hljs-comment">// 快速拷贝数据 </span>
memcpy(transferCtx->buffer, memMap->address, memMap->transferedLength);
transferCtx->status = memMap->transferedLength;
} <span class="hljs-keyword">else</span> {
transferCtx->status = -<span class="hljs-number">1</span>;
}
<span class="hljs-comment">// 触发JS回调 </span>
napi_handle_scope scope;
napi_open_handle_scope(transferCtx->env, &scope);
napi_value global, callback, result;
napi_get_global(transferCtx->env, &global);
napi_get_reference_value(transferCtx->env, transferCtx->callback, &callback);
<span class="hljs-comment">// 构造返回结果 </span>
napi_create_object(transferCtx->env, &result);
napi_value jsBuffer, jsLength;
napi_create_buffer_copy(
transferCtx->env,
transferCtx->status > <span class="hljs-number">0</span> ? transferCtx->status : <span class="hljs-number">0</span>,
transferCtx->buffer,
nullptr,
&jsBuffer
);
napi_create_int32(transferCtx->env, transferCtx->status, &jsLength);
napi_set_named_property(transferCtx->env, result, <span class="hljs-string">"data"</span>, jsBuffer);
napi_set_named_property(transferCtx->env, result, <span class="hljs-string">"length"</span>, jsLength);
<span class="hljs-comment">// 调用回调 </span>
napi_value <span class="hljs-literal">undefined</span>;
napi_get_undefined(transferCtx->env, &<span class="hljs-literal">undefined</span>);
napi_call_function(transferCtx->env, global, callback, <span class="hljs-number">1</span>, &result, nullptr);
napi_close_handle_scope(transferCtx->env, scope);
<span class="hljs-comment">// 释放资源 </span>
OH_Usb_DestroyDeviceMemMap(memMap);
<span class="hljs-keyword">delete</span>[] transferCtx->buffer;
<span class="hljs-keyword">delete</span> transferCtx;
}
// 高性能USB接收函数
static napi_value FastUsbReceive(napi_env env, napi_callback_info info) {
size_t argc = 4;
napi_value args[4];
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
<span class="hljs-comment">// 解析参数 </span>
int busNum, devID, interfaceIndex, endpointIndex;
napi_get_value_int32(env, args[<span class="hljs-number">0</span>], &busNum);
napi_get_value_int32(env, args[<span class="hljs-number">1</span>], &devID);
napi_get_value_int32(env, args[<span class="hljs-number">2</span>], &interfaceIndex);
napi_get_value_int32(env, args[<span class="hljs-number">3</span>], &endpointIndex);
<span class="hljs-comment">// 创建异步上下文 </span>
UsbTransferContext* transferCtx = <span class="hljs-keyword">new</span> UsbTransferContext();
transferCtx->env = env;
transferCtx->deviceId = GET_DEV_HANDLE(busNum, devID);
<span class="hljs-comment">// 获取JS回调 </span>
napi_create_reference(env, args[<span class="hljs-number">4</span>], <span class="hljs-number">1</span>, &transferCtx->callback);
<span class="hljs-comment">// 准备接收缓冲区 </span>
size_t bufferSize = <span class="hljs-number">1024</span>; <span class="hljs-comment">// 根据实际需求调整 </span>
transferCtx->buffer = <span class="hljs-keyword">new</span> uint8_t[bufferSize];
transferCtx->bufferSize = bufferSize;
<span class="hljs-comment">// 创建内存映射 </span>
struct UsbDeviceMemMap* devMmap = nullptr;
int32_t reMemMap = OH_Usb_CreateDeviceMemMap(
transferCtx->deviceId,
bufferSize,
&devMmap
);
<span class="hljs-keyword">if</span> (reMemMap != <span class="hljs-number">0</span>) {
<span class="hljs-comment">// 错误处理 </span>
<span class="hljs-keyword">delete</span>[] transferCtx->buffer;
<span class="hljs-keyword">delete</span> transferCtx;
<span class="hljs-keyword">return</span> nullptr;
}
<span class="hljs-comment">// 配置管道 </span>
struct UsbRequestPipe pipe;
pipe.interfaceHandle = OH_Usb_ClaimInterface(transferCtx->deviceId, interfaceIndex, nullptr);
pipe.endpoint = endpointIndex;
pipe.timeout = <span class="hljs-number">100</span>; <span class="hljs-comment">// 极短超时 </span>
<span class="hljs-comment">// 设置异步接收 </span>
OH_Usb_SetPipeCallback(&pipe, UsbReceiveCallback, transferCtx);
<span class="hljs-comment">// 发起异步读取 </span>
OH_Usb_ReadPipeRequestAsync(&pipe, devMmap);
<span class="hljs-keyword">return</span> nullptr;
}
写的比较快,可能有点小问题,你对照看看
更多关于HarmonyOS 鸿蒙Next USB DDK 发送数据成功,但是无法接收数据的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
帮你做了点优化,再次运行后可以把更详细的错误日志发给我看看:
#define GET_DEV_HANDLE(busNum, devID) ((uint64_t)busNum << 32 | devID & 0xFFFFFFFF)
// 错误码映射函数
const char* MapErrorCode(int32_t errorCode) {
switch(errorCode) {
case -1: return “USB_DDK_ERR_INVALID_PARAMETER”;
case -2: return “USB_DDK_ERR_MEMORY_ALLOC”;
case -3: return “USB_DDK_ERR_DEVICE_NOT_FOUND”;
case -4: return “USB_DDK_ERR_INTERFACE_CLAIM_FAILED”;
case -5: return “USB_DDK_ERR_PIPE_TRANSFER_FAILED”;
case -6: return “USB_DDK_ERR_DEVICE_BUSY”;
case -7: return “USB_DDK_ERR_TIMEOUT”;
default: return “UNKNOWN_ERROR”;
}
}
static napi_value Test(napi_env env, napi_callback_info info)
{
// 从arkts获取USB设备的busNum和devID
size_t argc = 2;
napi_value args[2] = {nullptr};
napi_get_cb_info(env, info, &argc, args , nullptr, nullptr);
int busNum;
napi_get_value_int32(env, args[0], &busNum);
int devID;
napi_get_value_int32(env, args[1], &devID);
<span class="hljs-comment">// 初始化USB DDK </span>
int32_t re = OH_Usb_Init();
<span class="hljs-keyword">if</span> (re != <span class="hljs-number">0</span>) {
LOGE(<span class="hljs-string">"USB初始化失败: %s"</span>, MapErrorCode(re));
<span class="hljs-keyword">return</span> nullptr;
}
<span class="hljs-comment">// 生成deviceId </span>
uint64_t deviceId = GET_DEV_HANDLE(busNum, devID);
<span class="hljs-comment">// 获取设备描述符 </span>
struct UsbDeviceDescriptor devDesc = {};
int32_t re1 = OH_Usb_GetDeviceDescriptor(deviceId, &devDesc);
<span class="hljs-keyword">if</span> (re1 != <span class="hljs-number">0</span>) {
LOGE(<span class="hljs-string">"获取设备描述符失败: %s"</span>, MapErrorCode(re1));
<span class="hljs-keyword">return</span> nullptr;
}
LOGD(<span class="hljs-string">"设备描述符 - PID: %d, VID: %d"</span>, devDesc.idProduct, devDesc.idVendor);
<span class="hljs-comment">// 获取配置描述符 </span>
struct UsbDdkConfigDescriptor *config = nullptr;
int32_t re2 = OH_Usb_GetConfigDescriptor(deviceId, <span class="hljs-number">1</span>, &config);
<span class="hljs-keyword">if</span> (re2 != <span class="hljs-number">0</span>) {
LOGE(<span class="hljs-string">"获取配置描述符失败: %s"</span>, MapErrorCode(re2));
<span class="hljs-keyword">return</span> nullptr;
}
<span class="hljs-comment">// 获取发送端点 </span>
auto [res, interface, endpoint, maxPktSize] = GetInterfaceAndEndpoint(config);
<span class="hljs-keyword">if</span> (res != <span class="hljs-number">0</span>) {
LOGE(<span class="hljs-string">"获取发送端点失败: %s"</span>, MapErrorCode(res));
<span class="hljs-keyword">return</span> nullptr;
}
<span class="hljs-comment">// 获取接收端点 </span>
auto [resIn, interfaceIn, endpointIn, maxPktSizeIn] = GetInterfaceAndEndpointIn(config);
<span class="hljs-keyword">if</span> (resIn != <span class="hljs-number">0</span>) {
LOGE(<span class="hljs-string">"获取接收端点失败: %s"</span>, MapErrorCode(resIn));
<span class="hljs-keyword">return</span> nullptr;
}
<span class="hljs-comment">// 声明接口 </span>
uint64_t interfaceHandle = <span class="hljs-number">0</span>;
int32_t re3 = OH_Usb_ClaimInterface(deviceId, interface, &interfaceHandle);
<span class="hljs-keyword">if</span> (re3 != <span class="hljs-number">0</span>) {
LOGE(<span class="hljs-string">"声明发送接口失败: %s"</span>, MapErrorCode(re3));
<span class="hljs-keyword">return</span> nullptr;
}
uint64_t interfaceHandleIn = <span class="hljs-number">0</span>;
int32_t re3In = OH_Usb_ClaimInterface(deviceId, interfaceIn, &interfaceHandleIn);
<span class="hljs-keyword">if</span> (re3In != <span class="hljs-number">0</span>) {
LOGE(<span class="hljs-string">"声明接收接口失败: %s"</span>, MapErrorCode(re3In));
<span class="hljs-keyword">return</span> nullptr;
}
<span class="hljs-comment">// 发送数据 </span>
unsigned char data[] = {<span class="hljs-number">0x01</span>, <span class="hljs-number">0x02</span>, <span class="hljs-number">0x03</span>, <span class="hljs-number">0x04</span>};
size_t length = sizeof(data) / sizeof(data[<span class="hljs-number">0</span>]);
struct UsbDeviceMemMap *devMmap = nullptr;
size_t bufferLen = length;
int32_t reMemMap = OH_Usb_CreateDeviceMemMap(deviceId, bufferLen, &devMmap);
<span class="hljs-keyword">if</span> (reMemMap != <span class="hljs-number">0</span>) {
LOGE(<span class="hljs-string">"创建发送内存映射失败: %s"</span>, MapErrorCode(reMemMap));
<span class="hljs-keyword">return</span> nullptr;
}
memcpy(devMmap->address, data, length);
struct UsbRequestPipe pipe;
pipe.interfaceHandle = interfaceHandle;
pipe.endpoint = endpoint;
pipe.timeout = <span class="hljs-number">5000</span>; <span class="hljs-comment">// 增加超时时间 </span>
int32_t reRequest = OH_Usb_SendPipeRequest(&pipe, devMmap);
<span class="hljs-keyword">if</span> (reRequest != <span class="hljs-number">0</span>) {
LOGE(<span class="hljs-string">"发送数据失败: %s"</span>, MapErrorCode(reRequest));
OH_Usb_DestroyDeviceMemMap(devMmap);
<span class="hljs-keyword">return</span> nullptr;
}
OH_Usb_DestroyDeviceMemMap(devMmap);
<span class="hljs-comment">// 接收数据 - 使用ReadPipeRequest </span>
struct UsbDeviceMemMap *devMmapIn = nullptr;
size_t bufferLenIn = maxPktSizeIn;
int32_t reMemMapIn = OH_Usb_CreateDeviceMemMap(deviceId, bufferLenIn, &devMmapIn);
<span class="hljs-keyword">if</span> (reMemMapIn != <span class="hljs-number">0</span>) {
LOGE(<span class="hljs-string">"创建接收内存映射失败: %s"</span>, MapErrorCode(reMemMapIn));
<span class="hljs-keyword">return</span> nullptr;
}
struct UsbRequestPipe pipeIn;
pipeIn.interfaceHandle = interfaceHandleIn;
pipeIn.endpoint = endpointIn;
pipeIn.timeout = <span class="hljs-number">5000</span>; <span class="hljs-comment">// 增加超时时间 </span>
<span class="hljs-comment">// 使用ReadPipeRequest替代SendPipeRequest </span>
int32_t reRequestIn = OH_Usb_ReadPipeRequest(&pipeIn, devMmapIn);
<span class="hljs-keyword">if</span> (reRequestIn != <span class="hljs-number">0</span>) {
LOGE(<span class="hljs-string">"接收数据失败: %s"</span>, MapErrorCode(reRequestIn));
OH_Usb_DestroyDeviceMemMap(devMmapIn);
<span class="hljs-keyword">return</span> nullptr;
}
<span class="hljs-comment">// 打印接收到的数据 </span>
LOGD(<span class="hljs-string">"接收数据长度: %zu"</span>, devMmapIn->transferedLength);
<span class="hljs-keyword">for</span> (size_t i = <span class="hljs-number">0</span>; i < devMmapIn->transferedLength; i++) {
LOGD(<span class="hljs-string">"接收数据[%zu]: 0x%02X"</span>, i, ((unsigned char*)devMmapIn->address)[i]);
}
OH_Usb_DestroyDeviceMemMap(devMmapIn);
<span class="hljs-comment">// 释放接口 </span>
OH_Usb_ReleaseInterface(interfaceHandle);
OH_Usb_ReleaseInterface(interfaceHandleIn);
<span class="hljs-keyword">return</span> nullptr;
}
有帮助的话帮忙点个关注哈
有要学HarmonyOS AI的同学吗,联系我:https://www.itying.com/goods-1206.html
补充一下:
指令的确下发了,从USB分析仪上抓到了下发的数据,且发送的是开灯指令,设备也开灯了;
然后用 [@ohos](/user/ohos).usbManager 接口也是能正常收发,但是接收数据实在是太慢了,从分析仪上看,设备立马回复了指令,但是app要等500ms后才收到数据,所以才考虑用USB DDK去开发。
针对您提出的HarmonyOS 鸿蒙Next USB DDK发送数据成功但无法接收数据的问题,以下是一些可能的原因及解决方案:
-
检查接收端配置:
- 确保接收端设备已正确配置并处于接收状态。
- 检查接收端设备的驱动程序是否正确安装且版本兼容。
-
验证数据格式与参数:
- 确认发送的数据格式与接收端期望的格式一致。
- 检查USB DDK使用的参数(如端点地址、超时时间等)是否正确。
-
检查连接稳定性:
- 确保USB连接稳定,无松动或接触不良现象。
- 检查是否存在其他设备干扰或冲突。
-
优化代码实现:
- 尝试使用异步回调机制优化数据接收过程。
- 确保内存映射和缓冲区管理正确无误。
如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html 。他们将为您提供更专业的技术支持和解决方案。