IOUserSerial子类串行缓冲区配置异常:TX缓冲区数据全为0求助
关于DriverKit中IOUserSerial驱动TX缓冲区读取全0的问题
正在学习DriverKit框架下的IOUserSerial驱动,当前驱动可检测指定USB设备(未使用IOUserUSBSerial是因为之前遇到Start返回0xe00002c7的问题)。参考苹果开发者论坛的帖子制作了一个回环串口实践项目,使串口程序发送的数据能被自身接收,因此暂时忽略了UART设置和底层USB配置。
/dev目录下已生成tty和cu设备,可通过以下终端命令打开串口:
screen /dev/cu.serial-xxx
系统控制台打印的日志表明串口启动流程正常:
17:27:09.635215+0800 kernel IOUserSerial::allocResources: 904 <== 17:27:09.635230+0800 kernel IOUserSerial::allocResources: 904 locklevel = 1 17:27:09.635389+0800 kernel IOUserSerial::ConnectQueues_Impl: 59 0x600001560058 17:27:09.635519+0800 kernel IOUserSerial::allocResources: 904 ==>0 17:27:09.635524+0800 kernel IOUserSerial::hwProgramMCR: 1115 <== 17:27:09.635525+0800 kernel IOUserSerial::hwProgramMCR: 1115 locklevel = 1 17:27:09.635571+0800 kernel IOUserSerial::hwProgramMCR: 1115 ==>0 17:27:09.635605+0800 kernel IOUserSerial::HwActivate_Impl: 130 0x600001560058 17:27:09.635683+0800 kernel IOUserSerial::hwResetFIFO: 1076 ==>0 17:27:09.635727+0800 kernel IOUserSerial::hwResetFIFO: 1076 ==>0 : (Ignored) : 17:27:09.647165+0800 kernel IOUserSerial::hwGetModemStatus: 1122 <== 17:27:09.647177+0800 kernel IOUserSerial::hwGetModemStatus: 1122 locklevel = 1 17:27:09.647277+0800 kernel IOUserSerial::hwGetModemStatus: 1122 ==>0
随后按照ConnectQueues文档在Start()中配置中断、TX和RX缓冲区。当在screen程序中按键尝试向驱动发送字节时,重载的TxDataAvailable方法会被调用,但打印TX数据对应的缓冲区内容时,所有值均为0:
void IMPL(MyDriver, TxDataAvailable) { kern_return_t ret = kIOReturnSuccess; Log("Entered %s", __FUNCTION__); // Some code is ignored to focus on TX buffer unsigned char * ptr = reinterpret_cast<unsigned char *>(ivars->tx_buf); static uint32_t idx; for( idx=0; idx<16; idx++ ){ Log("[%02X]", ptr[idx]); } }
尝试了ConnectQueues提供的两种方式,但均无效:
方式1:使用系统创建的缓冲区
// 1. Use system created buffer IOMemoryMap * pMap; ConnectQueues(&ivars->ifmd, &ivars->rxqmd, &ivars->txqmd, NULL, NULL, 0, 0, 0, 0, SUPERDISPATCH); // I have tried different options ivars->txqmd->CreateMapping(kIOMemoryMapCacheModeDefault, 0, 0, 0, 0, &pMap); ivars->tx_buf = pMap->GetAddress();
方式2:使用手动创建的缓冲区
// 2. Use manually created buffer // I have tried different buffer size, change the alignment to 0, 8, 4096 to fit the page alignment. IOBufferMemoryDescriptor::Create(kIOMemoryDirectionInOut, 8192, 4096, &ivars->in_txqmd); ivars->in_txqmd->GetAddressRange(&ioaddrseg); ivars->tx_buf = ioaddrseg.address; IOBufferMemoryDescriptor::Create(kIOMemoryDirectionInOut, 8192, 4096, &ivars->in_rxqmd); ivars->in_rxqmd->GetAddressRange(&ioaddrseg); ivars->rx_buf = ioaddrseg.address; ret = ConnectQueues(&ivars->ifmd, &ivars->rxqmd, &ivars->txqmd, ivars->in_rxqmd, ivars->in_txqmd, 0, 0, 13, 13, SUPERDISPATCH); if (ret != kIOReturnSuccess) { Log("ERR: @ %d, %s", __LINE__, __FUNCTION__); return ret; }
尝试过不同的缓冲区大小,也回顾了IOKit内存管理知识,了解到IOUserSerial::ConnectQueues()中应有内核-用户空间内存映射,但因封装无法深入排查,且所有函数调用均返回成功。
发现苹果内置驱动均继承自IOUserUSBSerial而非IOUserSerial,现询问是否有人成功子类化IOUserSerial,恳请提供建议或提示。
内容的提问来源于stack exchange,提问作者Jason
相关产品推荐
相关产品推荐

