You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 05:23:12