Миграция 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. Вот мои вопросы:
Похоже, подкласс IOService по умолчанию подходит для USB - это то же самое, что и IOClass из KEXT. Это правда?
Является ли IOUSBHostInterface в DEXT-мире эквивалентом IOUSBInterface в KEXT-мире?
IOUSBHostDevice эквивалентен IOUSBDevice?
Нужно ли мне что-то делать с.cpp или.iig для DEXT без кода? Разве большая часть моей работы не должна выполняться в файлах plist и прав?
Нужен ли мне USBDriverKit.framework в моих фреймворках и библиотеках MyUsbDriver target?
Где я могу найти достойный пример того, как завершить эту миграцию?
Любая помощь будет принята с благодарностью.
Обновить:
Используя пример и другие ссылки в ответе, я смог кое-что собрать. У меня действительно был момент "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 для нашего идентификатора поставщика.
- Похоже, подкласс IOService по умолчанию подходит для USB - это то же самое, что и IOClass из KEXT. Это правда?
Это сработало для меня. Я попытался удалить.iig
а также .cpp
файлы полностью, но, в отличие от KEXT, кажется, что для правильной работы подписи требуется скомпилировать некоторый код. Итак, у меня остался только пустой подклассIOService
.
- Является ли IOUSBHostInterface в DEXT-мире эквивалентом IOUSBInterface в KEXT-мире?
Я так считаю. я использовалIOUSBHostInterface
и у нас было IOUSBInterface
в нашем KEXT.
- IOUSBHostDevice эквивалентен IOUSBDevice?
Не знаю, но я так считаю.
- Нужно ли мне что-то делать с.cpp или.iig для DEXT без кода? Разве большая часть моей работы не должна выполняться в файлах plist и прав?
Мне не нужно было ничего менять в .cpp
а также .iig
файлы. Вы можете удалитьos_log(OS_LOG_DEFAULT, "Hello World");
линия в .cpp
файл перед выпуском. Но во время отладки мне было полезно узнать, действительно ли загружается DEXT или нет. Вы можете запуститьlog stream --source | grep 'HELLO'
в терминале искать журнал.
- Нужен ли мне USBDriverKit.framework в моих фреймворках и библиотеках MyUsbDriver target?
Мои DEXT ссылки на DriverKit.framework
. Не знаю, нужно это или нет.
- Где я могу найти достойный пример того, как завершить эту миграцию?
Может быть, это поможет:
- https://github.com/stuartlynne/USBApp-updated
- Переход с KEXT без кода на DEXT. USB интерфейсы исчезли
- Проблема с производительностью после перехода с KEXT без кода на DEXT
Некоторые заметки, которые я сделал для себя и будущих разработчиков
Во время разработки расширения 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
покажет загруженную версию).