如何访问 CompleteAsyncIO 中的 IOMemoryBufferDescriptor,它是在中断 EP 上通过 AsyncIO 发送的
How to access the IOMemoryBufferDescriptor in CompleteAsyncIO, which is sent through AsyncIO on Interrupt EP
我正在尝试使用 AsyncIO 为中断 EP 发送请求,对于 AsyncIO 我已经创建了 IOMemoryBufferDescriptor,一旦 IOMemoryBufferDescriptor,创建成功我使用了 GetAddressRange 并将地址存储在 dext 的 ivars 结构中。对于此请求完成(CompleteAsyncIO),使用 action-> GetReference() 调用我得到了 ivars 结构,我期待从 USB 设备接收到中断完成数据,不幸的是我没有看到相关数据。在 wireshark 中,我尝试调试接收到的数据是 16 个字节,而 CompleteAsyncIO actualbytes 也是 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 发送的 IOBufferMemoryDescriptor 获取从 USB 设备接收的实际数据以完成中断?我是否需要将地址映射到当前进程地址 space?
我看到带有 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","host","USB","40","URB_INTERRUPT in (submitted)"
"3030","32.169565","64.16.4","host","USB","56","URB_INTERRUPT in (completed)"
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);
(尽管公平起见,类型检查器仍未发现错误;但是,静态分析可能已经发现。)
有了正确的缓冲区指针,它应该开始输出正确的数据。
我正在尝试使用 AsyncIO 为中断 EP 发送请求,对于 AsyncIO 我已经创建了 IOMemoryBufferDescriptor,一旦 IOMemoryBufferDescriptor,创建成功我使用了 GetAddressRange 并将地址存储在 dext 的 ivars 结构中。对于此请求完成(CompleteAsyncIO),使用 action-> GetReference() 调用我得到了 ivars 结构,我期待从 USB 设备接收到中断完成数据,不幸的是我没有看到相关数据。在 wireshark 中,我尝试调试接收到的数据是 16 个字节,而 CompleteAsyncIO actualbytes 也是 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 发送的 IOBufferMemoryDescriptor 获取从 USB 设备接收的实际数据以完成中断?我是否需要将地址映射到当前进程地址 space?
我看到带有 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","host","USB","40","URB_INTERRUPT in (submitted)" "3030","32.169565","64.16.4","host","USB","56","URB_INTERRUPT in (completed)"
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);
(尽管公平起见,类型检查器仍未发现错误;但是,静态分析可能已经发现。)
有了正确的缓冲区指针,它应该开始输出正确的数据。