2

我的问题是我想手动处理插入 USB 设备时的处理方式。我不希望操作系统对插入的 USB 设备做任何事情,除了在插入时通知我它们的类型和 ID从那里我可以选择适当的驱动程序来应用它,或者使用自定义代码手动对其进行操作。

我读过这篇关于 MacOS 如何处理 USB 的文章,它说:

如果您希望您的驱动程序高于其他驱动程序,您需要做的就是为您的驱动程序所针对的设备添加键值对,从而使您的驱动程序获得非常高的分数。通常只需为您的供应商 ID/型号输入密钥就足够了。但是,我认为您可以覆盖匹配方法(设备驱动程序是用一组受限制的 C++ 编写的)来给您的驱动程序一个非常高的分数。

我还找到了这 3 个库,用于获取有关 USB 驱动器中事物的通知:

我只是不确定这些库是否会在发生任何事情之前中断操作系统对所有 USB 设备的处理(在自动选择并应用任何设备驱动程序之前)。除了我可以在上述库之一中访问设备及其类型之外,我不希望任何事情发生,但我不确定他们是否会这样做。

除了这个,我还没有太多代码:

var usb = require('usb')
usb.getDeviceList()

但我想这会在操作系统已经选择并应用默认驱动程序解决插入的设备。我想做这样的事情:

usb.blockDefaultOSDeviceHandler()
usb.on('device:plugged_in', function(data){
  if (data.type == 'keyboard') {
    if (data.modelNumber == '123') {
      // allow
      usb.applyKeyboardDriver('abc', data.modelNumber)
      usb.on('keyboard:event', logKeyboardEvent)
    } else {
      throw new Error('Unrecognized device')
    }
  } 
})

我希望库会中断操作系统的所有默认行为,这样我就可以自己处理插入 USB 设备时应该做的事情。原因是因为 USB 设备可能是键盘,它会自动开始输入一些键。我想知道它是一个键盘,需要密码和我预先批准的特定驱动程序。像这样的东西。

我想在操作系统应用其默认处理规则之前访问任何新插入的 USB 设备。然后有能力编写代码来手动处理每个插入设备的操作。

如果它只能在 C 中实现,那么知道如何去做会比 node.js 更好。

4

1 回答 1

2

答案在有关 USB 设备的 Apple 文档中。基本上你想覆盖probe自定义驱动程序中的函数,让它返回最高分以覆盖所有其他驱动程序,并像平常一样实现驱动程序。以下是有关驱动程序选择和实例化过程的一些有用文档。

在使用设备或任何服务提供商之前,必须找到它的驱动程序并将其加载到内核中。I/O 套件定义了一个灵活的三阶段匹配过程,将候选驱动程序池缩小到一个或多个驱动程序。然后加载最终候选者(或者,如果有多个候选者,则最符合条件的候选者)并给予第一次机会来管理设备或服务提供商。

...

每个设备驱动程序,被认为是一个可加载内核扩展 (KEXT),必须定义一个或多个特性来指定它可以支持的设备类型。

...

因为驱动程序可以包含多个匹配的字典,每个字典都为驱动程序定义了不同的个性,所以可以为不同的设备加载相同的驱动程序代码。出于竞争目的,I/O 套件将每个人都视为车手。如果在任何单个个性中,该系列所需的所有属性都匹配,则加载驱动程序的代码并有机会为该设备运行。

...

人格的一个共同属性是探测分数。探测分数是一个整数,它反映了驱动程序对驱动特定设备的适用程度。驱动程序可能在其个性中具有初始探测分数值,并且它可以实现允许它根据驱动设备的适用性修改此默认值的探测功能。与其他匹配值一样,探测分数特定于每个家庭。那是因为一旦匹配进行到阶级匹配阶段,只有来自同一家庭的人物才能竞争。有关探测分数以及驱动程序在探测函数中的作用的更多信息,请参阅设备探测。

...

在启动时以及在任何时候添加或删除设备时,都会为每个检测到的设备(或其他服务提供商)进行驱动程序匹配过程。该进程动态地在 /System/Library/Extensions 中为设备或服务找到最合适的驱动程序。

...

如架构概述一章中的驱动程序匹配中所述,当总线控制器驱动程序扫描其总线并检测到连接到它的新设备时,将触发匹配过程。对于每个检测到的设备,控制器驱动程序都会创建一个小块。然后 I/O 套件启动匹配过程并从设备获取值以用于匹配(例如,检查 PCI 寄存器)。一旦为 nub 找到合适的驱动程序,就会注册并加载驱动程序。反过来,该驱动程序可能会创建自己的节点(可能通过从其家族继承的行为),从而启动匹配过程以找到合适的驱动程序。

...

匹配过程如下:

  1. 类匹配步骤中,I/O Kit 通过为提供者服务(即 nub)消除任何错误类的驱动程序来缩小潜在驱动程序的列表。例如,当搜索 USB 驱动程序时,可以排除所有来自 SCSI 类的驱动程序对象。
  2. 被动匹配步骤中,将检查驱动程序的个性(在驱动程序的 XML 信息属性列表中指定)以查找特定于提供者家族的属性。例如,个性可能会指定特定的供应商名称。
  3. 主动匹配步骤中,驱动程序的探测函数被调用,参考它正在匹配的小块。此功能允许驱动程序与设备通信并验证它实际上可以驱动它。驱动程序返回一个反映其驱动设备能力的探测分数。有关详细信息,请参阅设备探测。在主动匹配期间,I/O 套件会加载并探测所有候选驱动程序,然后按照探测分数从高到低的顺序对它们进行排序。

...

I/O 套件然后选择具有最高探测分数的剩余驱动程序并启动它。如果驱动程序成功启动,它将被添加到 I/O 注册表中,并且任何剩余的驱动程序候选者都将被丢弃。如果启动不成功,则启动探测分数第二高的驱动程序,以此类推。如果可能的候选者池中有多个驱动程序,如果两者都声称能够驱动设备,则更通用的驱动程序通常会输给更具体的驱动程序。

...

探测分数是一个有符号的 32 位整数,初始化为驱动程序个性中指定的值(如果未显式初始化,则为零)。

...

如果探测成功,则驱动程序在其探测函数中返回驱动程序对象 (IOService *),否则返回零。返回的对象通常是驱动程序本身,但驱动程序可以返回另一个更适合提供者的驱动程序。探针分数是一个输入输出参数,探针可以根据它对设备的发现进行修改。

...

在所有驱动程序探测完设备后,附加探测分数最高的设备,并调用必须由所有驱动程序实现的启动函数。启动函数初始化设备硬件并为运行做好准备。如果驱动启动成功,则返回true;剩余的候选驱动程序实例被丢弃,成功启动的驱动程序继续运行。如果驱动程序无法初始化硬件,它必须将硬件保持在调用 start 时的状态并返回 false。然后将失败的驱动程序分离并丢弃,并为具有下一个最高探测分数的候选驱动程序提供启动的机会。

这不能用 Node.js 完成,除非(可能)使用节点中的 C/C++ 扩展。

于 2019-01-10T03:57:07.527 回答