Миграция KEXT без кода на DEXT без кода

Я переношу KEXT без кода на DEXT без кода. Я просмотрел видео WWDC и прочитал большую часть информации на сайте разработчиков Apple. Моя трудность заключается не в том, что делать, а в том, как начать. Помогло бы хорошее руководство с примером проекта.

В моем KEXT без кода для 4 отдельных устройств у меня есть IOKitPersonalities для IOUSBDevice и IOUSBInterface для каждого устройства. KEXT позволил мне сопоставить мои устройства с моим "драйвером", чтобы драйвер Apple HID не захватил их. Я хочу сделать то же самое или что-то подобное в DEXT без кода.

Пока что я создал цель DriverKit (для DriverKit.framework) под названием MyUsbDriver в приложении и добавил USBDriverKit.framework. Это добавило в мой проект папку MyUsbDriver с файлами MyUsbDriver.cpp, MyUsbDriver.iig, Info.plist и MyUsbDriver.entitlements. Вот мои вопросы:

  1. Похоже, подкласс IOService по умолчанию подходит для USB - это то же самое, что и IOClass из KEXT. Это правда?

  2. Является ли IOUSBHostInterface в DEXT-мире эквивалентом IOUSBInterface в KEXT-мире?

  3. IOUSBHostDevice эквивалентен IOUSBDevice?

  4. Нужно ли мне что-то делать с.cpp или.iig для DEXT без кода? Разве большая часть моей работы не должна выполняться в файлах plist и прав?

  5. Нужен ли мне USBDriverKit.framework в моих фреймворках и библиотеках MyUsbDriver target?

  6. Где я могу найти достойный пример того, как завершить эту миграцию?

Любая помощь будет принята с благодарностью.

Обновить:

Используя пример и другие ссылки в ответе, я смог кое-что собрать. У меня действительно был момент "Doh": моим первоначальным типом тестового проекта был инструмент командной строки, и я никогда не мог заставить DEXT встроить. Я почти только что отредактировал файл pbxproj вручную. Однако, глядя на исходный пример USBApp от Скотта Найта, я понял, что тип проекта, который он использовал, был App. Оглядываясь назад, это имеет смысл, но в то время сбивало с толку.

Вот info.plist, который у меня есть на одном из устаревших устройств:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>CFBundleDevelopmentRegion</key>
    <string>$(DEVELOPMENT_LANGUAGE)</string>
    <key>CFBundleExecutable</key>
    <string>$(EXECUTABLE_NAME)</string>
    <key>CFBundleIdentifier</key>
    <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
    <key>CFBundleInfoDictionaryVersion</key>
    <string>6.0</string>
    <key>CFBundleName</key>
    <string>$(PRODUCT_NAME)</string>
    <key>CFBundlePackageType</key>
    <string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
    <key>CFBundleShortVersionString</key>
    <string>1.0</string>
    <key>CFBundleVersion</key>
    <string>1</string>
    <key>IOKitPersonalities</key>
    <dict>
        <key>MyUsbDrver</key>
        <dict>
            <key>CFBundleIdentifier</key>
            <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
            <key>CFBundleIdentifierKernel</key>
            <string>com.apple.kpi.iokit</string>
            <key>IOClass</key>
            <string>IOUserService</string>
            <key>IOMatchCategory</key>
            <string>com.apple.null.driver</string>
            <key>IOProviderClass</key>
            <string>IOUsbHostInterface</string>
            <key>IOResourceMatch</key>
            <string>IOKit</string>
            <key>IOUserClass</key>
            <string>MyUsbDrver</string>
            <key>IOUserServerName</key>
            <string>Home.MyUsbDrver</string>
            <key>bConfigurationValue</key>
            <integer>1</integer>
            <key>bInterfaceNumber</key>
            <integer>0</integer>
            <key>idProduct</key>
            <integer>2</integer>
            <key>idVendor</key>
            <integer>5843</integer>
        </dict>
    </dict>
    <key>OSBundleUsageDescription</key>
    <string>Codless DEXT to match on IOKit.</string>
</dict>
</plist>

Я не уверен насчет IOResourceMatch - значение IOKit, это направление, в котором я пытаюсь двигаться.

Обновление второе:

Прогресс!

В итоге мне пришлось вручную изменить условия подписи в моем файле pbxproj. Отключил SIP, настроил активацию / деактивацию системного расширения в моем приложении и выполнил подпись из командной строки. Я нашел этот репозиторий полезным с достойным примером Objective-C для кода активации - https://github.com/google/santa.git. Все сборки и подписи кода казались успешными. Получение забавной ошибки

SystemExtension "Home.MyUsbDrver" request did fail: Error Domain=OSSystemExtensionErrorDomain Code=8 "(null)"

Обновление 3:

Я проверил свои права на DEXT и приложения, и мне показалось, что их нужно обновить. Вот что у меня сейчас для приложения:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.security.app-sandbox</key>
    <true/>
    <key>com.apple.security.files.user-selected.read-only</key>
    <true/>
    <key>com.apple.developer.system-extension.install</key>
    <true/>
    <key>com.apple.developer.system-extension.uninstall</key>
    <true/>
</dict>
</plist>

Мне не хватало двух нижних. Мой проект почистил, построил, снова подписал. Когда я попытался запустить из Xcode, все равно получил ошибку. Когда я запустил свое приложение из Finder, у меня появилось диалоговое окно системных настроек. После этого все тот же результат от Xcode, и теперь ничего, кроме вспышки приложения при запуске из Finder. Перезагрузил - все те же результаты. Однако с терминала, когда я запускаю systemextensionsctl -list, я получаю:

3 extension(s)
--- com.apple.system_extension.driver_extension
enabled active  teamID  bundleID (version)  name    [state]
        <REDACTED>  Home.MyUsbDrver (1.0/1) Home.MyUsbDrver [terminated waiting to uninstall on reboot]
*   *   <REDACTED>  Home.MyUsbDrver (1.0/1) Home.MyUsbDrver [activated enabled]
        <REDACTED>  Home.MyUsbDrver (1.0/1) Home.MyUsbDrver [activated waiting to upgrade]

После перезагрузки получаю вот что:

1 extension(s)
--- com.apple.system_extension.driver_extension
enabled active  teamID  bundleID (version)  name    [state]
*   *   <REDACTED>  Home.MyUsbDrver (1.0/1) Home.MyUsbDrver [activated enabled]

Итак, похоже, что мое системное расширение на месте, но я на самом деле не уверен, почему, поскольку я только что сделал новую перезагрузку и не запустил свое приложение.

Обновление 4:

Я понял, что проблема с моими правами заключалась только в формате файла. Я изменил его в TextEdit, и теперь я могу общаться со своим устройством. Вот что у меня получилось:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.developer.driverkit</key>
    <true/>
    <key>com.apple.developer.driverkit.transport.usb</key>
    <array>
        <dict>
            <key>idVendor</key>
            <integer>VID0</integer>
            <key>idProductArray</key>
            <array>
                <integer>PID0</integer>
                <integer>PID1</integer>
                <integer>PID2</integer>
                <integer>PID3</integer>
                <integer>PID4</integer>
            </array>
        </dict>
    </array>
    <key>com.apple.security.app-sandbox</key>
    <true/>
</dict>
</plist>

1 ответ

Решение

Я сильно бился головой, чтобы заставить то же самое работать. В конце концов мне удалось получить рабочий DEXT, который отключает драйвер Apple HID для определенных комбинаций идентификатора поставщика / идентификатора продукта. Мы получили право на DriverKit для нашего идентификатора поставщика.

  1. Похоже, подкласс IOService по умолчанию подходит для USB - это то же самое, что и IOClass из KEXT. Это правда?

Это сработало для меня. Я попытался удалить.iig а также .cppфайлы полностью, но, в отличие от KEXT, кажется, что для правильной работы подписи требуется скомпилировать некоторый код. Итак, у меня остался только пустой подклассIOService.

  1. Является ли IOUSBHostInterface в DEXT-мире эквивалентом IOUSBInterface в KEXT-мире?

Я так считаю. я использовалIOUSBHostInterface и у нас было IOUSBInterface в нашем KEXT.

  1. IOUSBHostDevice эквивалентен IOUSBDevice?

Не знаю, но я так считаю.

  1. Нужно ли мне что-то делать с.cpp или.iig для DEXT без кода? Разве большая часть моей работы не должна выполняться в файлах plist и прав?

Мне не нужно было ничего менять в .cpp а также .iigфайлы. Вы можете удалитьos_log(OS_LOG_DEFAULT, "Hello World"); линия в .cppфайл перед выпуском. Но во время отладки мне было полезно узнать, действительно ли загружается DEXT или нет. Вы можете запуститьlog stream --source | grep 'HELLO' в терминале искать журнал.

  1. Нужен ли мне USBDriverKit.framework в моих фреймворках и библиотеках MyUsbDriver target?

Мои DEXT ссылки на DriverKit.framework. Не знаю, нужно это или нет.

  1. Где я могу найти достойный пример того, как завершить эту миграцию?

Может быть, это поможет:

Некоторые заметки, которые я сделал для себя и будущих разработчиков

Во время разработки расширения DriverKit (dext) сделайте следующее:

  • Отключить защиту целостности системы (SIP): https://apple.stackexchange.com/a/208481/21491. (Перезагрузитесь в режиме восстановления, запуститеcsrutil disable). Не забудьте снова включить его!

  • Включите режим разработки системных расширений, запустив systemextensionsctl developer on

  • Убедитесь, что у вас не установлен старый KEXT без кода. (Удалить его из/Library/Extensions и / или /System/Library/Extensions. Не забудьте после этого перезагрузиться)

Советы и предостережения

  • Вам может потребоваться профиль ручной подготовки, содержащий права DriverKit. Я думаю, что моя проблема заключалась в том, что я получил право на DriverKit в команде корпоративных разработчиков, а не в команде общественной разработки.

  • Приложению, которое загружает расширение, требуется право "Расширение системы", но не требуется профиль предоставления вручную.

  • Остерегайтесь глупой ошибки в системных настройках. Вам нужно дать согласие на загрузку декста каждый раз, когда он загружается. Однако, если панель "Безопасность и конфиденциальность" уже открыта, на ней не будет отображаться кнопка для предоставления согласия. Вам необходимо перезапустить Системные настройки, чтобы он появился. Я использовал командуpkill -9 "System Preferences"; open /System/Library/PreferencePanes/Security.prefPane от Терминала, чтобы обойти это.

  • Вы можете использовать systemextensionsctlчтобы удалить декст или сбросить состояние системы. Однако на самом деле это не меняет соответствие драйвера, поэтому вам необходимо перезагрузить компьютер. Щедро. Я использовал эту команду терминала, потому что мне лень:osascript -e 'tell app "System Events" to restart'.

  • Вы можете использовать ioreg чтобы проверить, сопоставляются ли устройства с добавочным номером: ioreg -lirc IOUSBHostInterface.

  • Ключ к тому, чтобы расширение заработало, - это установить IOProviderClass кIOUSBHostInterface вместо того IOResourcesв файле Info.plist. (Для справки, KEXT используетIOUSBInterface который является одним из классов, которые Apple устарела)

  • Возможно, вы захотите поднять версию в Info.plistкаждый раз, когда вы вносите изменения в свой DEXT, чтобы убедиться, что вы действительно используете правильный. (systemextensionsctl покажет загруженную версию).

Другие вопросы по тегам