我正在开发一个单端口usb串行适配器的DriverKit驱动程序。我有一个简单的驱动程序代码如下:
class MyDriver: public IOUserUSBSerial
{
public:
virtual bool init() override;
virtual kern_return_t Start(IOService *provider) override;
virtual kern_return_t Stop(IOService *provider) override;
virtual void free() override;
};
bool
MyDriver::init()
{
Log("Entered %s", __FUNCTION__);
return super::init();
}
void
MyDriver::free()
{
Log("Entered %s", __FUNCTION__);
super::free();
}
kern_return_t
IMPL(MyDriver, Start)
{
kern_return_t ret;
Log("Entered %s", __FUNCTION__);
ret = Start(provider, SUPERDISPATCH);
if( ret!=kIOReturnSuccess ){
Log("Start returns Error: 0x%Xn", ret);
return ret;
}
ret = RegisterService();
if( ret!=kIOReturnSuccess ){
Log("IOReturn Error: 0x%X @ %d, %sn", ret, __LINE__, __FUNCTION__);
return ret;
}
Log("Hello MyDriver is started...");
return ret;
}
kern_return_t
IMPL(MyDriver, Stop)
{
kern_return_t ret = kIOReturnSuccess;
Log("Entered %s", __FUNCTION__);
ret = Stop(provider, SUPERDISPATCH);
if( ret!=kIOReturnSuccess ){
Log("IOReturn Error: 0x%X @ %d, %sn", ret, __LINE__, __FUNCTION__);
}
return ret;
}
<key>IOKitPersonalities</key>
<dict>
<key>MyDriver</key>
<dict>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleIdentifierKernel</key>
<string>com.apple.driver.driverkit.serial</string>
<key>IOClass</key>
<string>IOUserSerial</string>
<key>IOMatchCategory</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>IOProviderClass</key>
<string>IOUSBHostDevice</string>
<key>IOResourceMatch</key>
<string>IOKit</string>
<key>IOUserClass</key>
<string>MyDriver</string>
<key>IOUserServerName</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>idVendor</key>
<integer>1234</integer>
<key>idProduct</key>
<integer>5678</integer>
<key>IOTTYBaseName</key>
<string>USB</string>
<key>IOTTYSuffix</key>
<string>4</string>
</dict>
</dict>
我的USB设备被系统检测到,init和Start被成功调用。然而,当我调用Start(provider, SUPERDISPATCH)
时,它返回错误代码0xE00002C7
(kIOReturnUnsupported
)。
我已经提到了这个线程。如果我改变继承IOUserSerial
类,调用Start返回成功。我猜问题是由CFBundleIdentifierKernel
引起的,但我找不到任何有关的信息。
有没有专家能告诉我为什么Start返回错误?
我可以忽略对super::Start
的呼叫吗?
如果我想开发一些特定的功能,我可以使用IOUserSerial
子类吗?
我试着在网上阅读所有的文章,感到很沮丧。IOUserUSBSerial
示例代码也无法在线获取。
免责声明:我还没有使用IOUserUSBSerial
自己,但我有多年的经验与其他部分的DriverKit和IOKit和内核在那之前。在苹果的文档中,即使没有明确说明,你也必须从字里行间理解它所暗示的内容。
IOUserUSBSerial
主要问题:
总之,我怀疑问题是这样的:
您有一个非类兼容(非acm)设备,您想为其开发一个驱动程序,使其充当macOS的串行端口。然而,我相信IOUserUSBSerial
是专门用于在ACM设备上实现供应商特定行为的。
我从短语"这个类自动管理与设备的串行通信"中推断出这一点。IOUserUSBSerial
如何知道如何"自动管理串行通信"?如果你的设备实现了自定义协议?它肯定是在实现ACM USB协议。
因此,您的设备是USB这一事实与选择IOUserUSBSerial
与IOUserSerial
无关,实际上重要的是它是否是ACM兼容的设备。我同意你的观点,如果你的设备是基于USB的,但不遵循ACM,那么解决方案似乎是使用较低级别的IOUserSerial
。
对子问题的进一步评论和回答:
<key>IOMatchCategory</key> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
在匹配真实硬件时不要使用IOMatchCategory。(除非在非常罕见的情况下,您希望多个驱动程序连接到同一个节点。)
可以忽略呼叫
super::Start
吗
一般:绝对不。
我猜问题是由CFBundleIdentifierKernel引起的,但我找不到任何有关的信息。
IOUserUSBSerial
有点奇怪,因为它似乎完全在框架中实现,在DriverKit运行时内。与大多数DriverKit类不同,它没有内核类支持。因此,com.apple.driver.driverkit.serial
实际上似乎是正确的CFBundleIdentifierKernel
,而IOUserSerial
似乎是正确的IOClass
,这是不寻常的。