c++ - 如何访问CompleteAsyncIO中的IOMemoryBufferDescriptor,它是通过中断EP上的AsyncIO发送的

标签 c++ macos driverkit macos-system-extension

我正在尝试使用AsyncIO发送中断EP请求,对于AsyncIO我已经创建了IOMemoryBufferDescriptor,一旦IOMemoryBufferDescriptor,创建成功我使用了GetAddressRange并将Address存储在dext的ivars结构中。对于这个请求完成(CompleteAsyncIO)是使用action-> GetReference()调用的,我得到了ivars结构,我期待从USB设备接收到中断完成的数据,不幸的是我没有看到相关数据。在wireshark中,我尝试调试收到的数据是16个字节,CompleteAsyncIO实际字节也是16个。

使用 IOMemoryBufferDescriptor 获取从设备接收的中断数据的正确方法是什么?

为 CompleteAsyncIO 创建 OSAction

ret = OSAction::Create(this,
                       Data_interruptComplete_ID,
                       IOUSBHostPipe_CompleteAsyncIO_ID,
                       sizeof(IntActRef),
                       &ivars->interruptComplete);

USB 中断 EP 的 IOMemoryBufferDescriptor 分配:

IOBufferMemoryDescriptor*       fCommPipeMDP; 

ivars->fCommPipeMDP->Create(kIOMemoryDirectionIn,
                            ivars->fcomBuffSize,
                            0,
                            &ivars->fCommPipeMDP);

    ivars->fCommPipeMDP->SetLength(ivars->fcomBuffSize); 
    ivars->fCommPipeMDP->GetAddressRange(&aRange);
    ivars->fCommPipeBuffer = (uint8_t*)&aRange.address;

发送 AsyncIO 请求以中断 EP

ret = ivars->fCommPipe->AsyncIO(ivars->fCommPipeMDP,
                                ivars->fcomBuffSize,
                                ivars->interruptComplete,
                                0);

框架调用的CompleteAsyncIO

void
IMPL (ClassData,interruptComplete)
{
struct interruptActionRef *actionref = (struct interruptActionRef*)action->GetReference();
Data_IVars * livars = actionref->interruptactionref;

  for(tmp = 0; tmp < actualByteCount; tmp++)
  os_log(OS_LOG_DEFAULT, "%x",livars->fCommPipeBuffer[tmp]); 
  //TRYING PRINT DATA RECEIVED FROM USB DEVICE IN INTERRUPT COMPLETION(CompleteAsyncIO)
  //UNFORTUNATELY DATA IS NOT MATCHING
}

如何使用我使用 AsyncIO 发送的 IOBufferMemoryDe​​scriptor 获取从 USB 设备接收的实际数据以完成中断?我需要将地址映射到当前进程地址空间吗?

我看到带有USB过滤器的wireshark仅实际数据长度匹配。

Wireshark 日志 a1 20 00 00 01 00 02 00 03 00 00 00 00 00 00 00(16 字节数据) “3029”、“32.105745”、“64.16.4”、“主机”、“USB”、“40”、“URB_INTERRUPT(已提交)” "3030","32.169565","64.16.4","主机","USB","56","URB_INTERRUPT 中(已完成)"

0000   01 01 28 01 10 00 00 00 00 00 00 00 00 00 00 00   ..(.............
0010   31 d8 05 00 00 00 00 00 00 00 40 14 02 10 84 03   1.........@.....
0020   ff 02 01 00 04 10 3e 63 a1 20 00 00 01 00 02 00   ......>c. ......
0030   03 00 00 00 00 00 00 00 

最佳答案

问题出在这一行:

ivars->fCommPipeBuffer = (uint8_t*)&aRange.address;

这将保存指向 IOAddressSegment 的地址字段的指针。结构变量,而不是指向缓冲区本身的指针。你想要:

ivars->fCommPipeBuffer = (uint8_t*)aRange.address;

或者,更不容易出错且更惯用的 C++:

ivars->fCommPipeBuffer = reinterpret_cast<uint8_t*>(aRange.address);

(尽管公平地说,类型检查器仍然无法捕获该错误;但是静态分析可能会捕获该错误。)

有了正确的缓冲区指针,它应该开始输出正确的数据。

关于c++ - 如何访问CompleteAsyncIO中的IOMemoryBufferDescriptor,它是通过中断EP上的AsyncIO发送的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62476424/

相关文章:

iphone - 如何将日期格式化为包含毫秒的字符串?

C++如何编写通用结构来保存任何枚举

c++ - 用 forkpty 和 execvp fork bash 后,bash 不响应 SIGINT

objective-c - 10.4 中的内部和外部 IP 地址

xcode - Xcode 编辑器中不再有快速帮助

macos - 如何在 MSFT 的 Azure Sphere Kit 上使用 IOKit/DriverKit for MT6320 编写驱动程序?

xcode - 在没有应用程序的情况下为遗留无代码 kext 创建 Dext?

c++ - 编译 Thrift 服务器时出错

具有未定义行为的 C++ 代码,编译器生成 std​​::exception