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); }
// 定义异步回调结构体 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 。他们将为您提供更专业的技术支持和解决方案。