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, &amp;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>, &amp;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, &amp;interfaceHandle);
<span class="hljs-comment">// 接收</span>
uint64_t interfaceHandleIn = <span class="hljs-number">0</span>;
int32_t re3In = OH_Usb_ClaimInterface(deviceId, interfaceIn, &amp;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); }

6 回复
这样的话优化方法有很多呀,可以使用异步回调机制,优化内存映射,我给你做个示例:
// 定义异步回调结构体  
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-&gt;transferedLength &gt; <span class="hljs-number">0</span>) {  
    <span class="hljs-comment">// 快速拷贝数据  </span>
    memcpy(transferCtx-&gt;buffer, memMap-&gt;address, memMap-&gt;transferedLength);  
    transferCtx-&gt;status = memMap-&gt;transferedLength;  
} <span class="hljs-keyword">else</span> {  
    transferCtx-&gt;status = -<span class="hljs-number">1</span>;  
}  

<span class="hljs-comment">// 触发JS回调  </span>
napi_handle_scope scope;  
napi_open_handle_scope(transferCtx-&gt;env, &amp;scope);  

napi_value global, callback, result;  
napi_get_global(transferCtx-&gt;env, &amp;global);  
napi_get_reference_value(transferCtx-&gt;env, transferCtx-&gt;callback, &amp;callback);  

<span class="hljs-comment">// 构造返回结果  </span>
napi_create_object(transferCtx-&gt;env, &amp;result);  
napi_value jsBuffer, jsLength;  
napi_create_buffer_copy(  
    transferCtx-&gt;env,   
    transferCtx-&gt;status &gt; <span class="hljs-number">0</span> ? transferCtx-&gt;status : <span class="hljs-number">0</span>,   
    transferCtx-&gt;buffer,   
    nullptr,   
    &amp;jsBuffer  
);  
napi_create_int32(transferCtx-&gt;env, transferCtx-&gt;status, &amp;jsLength);  

napi_set_named_property(transferCtx-&gt;env, result, <span class="hljs-string">"data"</span>, jsBuffer);  
napi_set_named_property(transferCtx-&gt;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-&gt;env, &amp;<span class="hljs-literal">undefined</span>);  
napi_call_function(transferCtx-&gt;env, global, callback, <span class="hljs-number">1</span>, &amp;result, nullptr);  

napi_close_handle_scope(transferCtx-&gt;env, scope);  

<span class="hljs-comment">// 释放资源  </span>
OH_Usb_DestroyDeviceMemMap(memMap);  
<span class="hljs-keyword">delete</span>[] transferCtx-&gt;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>], &amp;busNum);  
napi_get_value_int32(env, args[<span class="hljs-number">1</span>], &amp;devID);  
napi_get_value_int32(env, args[<span class="hljs-number">2</span>], &amp;interfaceIndex);  
napi_get_value_int32(env, args[<span class="hljs-number">3</span>], &amp;endpointIndex);  

<span class="hljs-comment">// 创建异步上下文  </span>
UsbTransferContext* transferCtx = <span class="hljs-keyword">new</span> UsbTransferContext();  
transferCtx-&gt;env = env;  
transferCtx-&gt;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>, &amp;transferCtx-&gt;callback);  

<span class="hljs-comment">// 准备接收缓冲区  </span>
size_t bufferSize = <span class="hljs-number">1024</span>;  <span class="hljs-comment">// 根据实际需求调整  </span>
transferCtx-&gt;buffer = <span class="hljs-keyword">new</span> uint8_t[bufferSize];  
transferCtx-&gt;bufferSize = bufferSize;  

<span class="hljs-comment">// 创建内存映射  </span>
struct UsbDeviceMemMap* devMmap = nullptr;  
int32_t reMemMap = OH_Usb_CreateDeviceMemMap(  
    transferCtx-&gt;deviceId,   
    bufferSize,   
    &amp;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-&gt;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-&gt;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(&amp;pipe, UsbReceiveCallback, transferCtx);  

<span class="hljs-comment">// 发起异步读取  </span>
OH_Usb_ReadPipeRequestAsync(&amp;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, &amp;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>, &amp;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, &amp;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, &amp;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, &amp;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-&gt;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(&amp;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, &amp;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(&amp;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-&gt;transferedLength);  
<span class="hljs-keyword">for</span> (size_t i = <span class="hljs-number">0</span>; i &lt; devMmapIn-&gt;transferedLength; i++) {  
    LOGD(<span class="hljs-string">"接收数据[%zu]: 0x%02X"</span>, i, ((unsigned char*)devMmapIn-&gt;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发送数据成功但无法接收数据的问题,以下是一些可能的原因及解决方案:

  1. 检查接收端配置

    • 确保接收端设备已正确配置并处于接收状态。
    • 检查接收端设备的驱动程序是否正确安装且版本兼容。
  2. 验证数据格式与参数

    • 确认发送的数据格式与接收端期望的格式一致。
    • 检查USB DDK使用的参数(如端点地址、超时时间等)是否正确。
  3. 检查连接稳定性

    • 确保USB连接稳定,无松动或接触不良现象。
    • 检查是否存在其他设备干扰或冲突。
  4. 优化代码实现

    • 尝试使用异步回调机制优化数据接收过程。
    • 确保内存映射和缓冲区管理正确无误。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html 。他们将为您提供更专业的技术支持和解决方案。

回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!