Набор libkern и Контейнерные классы
Ваш водительский информационный список свойств содержит по крайней мере один словарь индивидуальности, указывающий тип устройства, которым может управлять Ваш драйвер. Словарь индивидуальности может также содержать информацию, подходящую для Вашей водительской конфигурации во время выполнения. Когда Ваш драйвер инстанцируют, он получает копию индивидуальности Набора I/O, для которой он был загружен, и он может использовать эту информацию, чтобы удостовериться, что это подходит, чтобы управлять устройством и, дополнительно, сконфигурировать себя для удовлетворения потребностей устройства.
Индивидуальность Набора I/O, которую получает Ваш драйвер, находится в форме OSDictionary, который является одним из libkern классов набора. libkern библиотека C++ определяет контейнерные классы, содержащие примитивные значения, такие как числа и строки и классы набора, содержащие группы из обоих контейнерных объектов и других объектов коллекции. Эта глава сначала описывает пути, которыми Ваш драйвер может использовать libkern набор и контейнерные классы, тогда это дает обзор этих классов и их методов. Глава заканчивается примерами кода, иллюстрирующими, как Ваш драйвер может использовать libkern классы для конфигурирования себя.
Для получения дополнительной информации о libkern библиотеке и как это поддерживает загружаемые модули ядра, посмотрите libkern Время выполнения C++ и Основные принципы IOKit. Для справочной документации API на libkern классах см. Документацию Драйверов устройств. На OS X можно найти libkern библиотеку в /System/Library/Frameworks/Kernel.framework/Headers/libkern/c++
.
libkern Классы и Ваш Драйвер
libkern набор и контейнерные классы предлагают мощные услуги, которые Ваш драйвер может использовать для конфигурирования его среды выполнения. Несмотря на то, что эти службы могут казаться совершенными для использования в Ваших водительских подпрограммах I/O, они являются слишком дорогостоящими для использования вне водительских динамических фаз конфигурации. Во время Вашего водительского init
, start
, и probe
подпрограммы, однако, компромисс между стоимостью и преимуществом делают libkern контейнер и классы набора привлекательными.
libkern классы предлагают много преимуществ, таких как объектный самоанализ, инкапсуляция и возможность сериализировать. Кроме того, libkern контейнер и классы набора близко соответствуют Базовым Фундаментальным классам и на имя и на поведение. Это позволяет системе автоматически переводить между libkern и Базовыми Фундаментальными классами того же типа. Например, libkern объект коллекции, OSDictionary преобразовывается в Базовую Основу, возражает CFDictionary при пересечении границы пользовательского ядра.
Для драйвера одно из самых больших преимуществ libkern классов находится в их возможности сделать водительский список свойств XML доступным для драйвера во время его продолжительности жизни. Существует три общих способа, которыми Ваш драйвер может использовать представление OSDictionary своей индивидуальности Набора I/O.
Драйвер может сконфигурировать себя для управления определенным типом устройства путем чтения содержания его списка свойств и выполнения надлежащей установки.
Драйвер может изменить свой список свойств (и, дополнительно, тот из его провайдера) на основе информации, которую это получает от устройства или других объектов службы в настоящее время в Реестре I/O. Это может тогда использовать ту информацию для настройки ее среды выполнения.
Процесс пространства пользователя может получить доступ к водительскому списку свойств и использовать его для отправки мелких сумм данных, которые драйвер может использовать для настройки его среды выполнения.
Несмотря на то, что информация этой главы о libkern наборе и контейнерных классах применима ко всем трем ситуациям, примерам кода в Конфигурировании Вашего Драйвера Используя libkern внимание Классов на первые два использования. Для получения дополнительной информации о коммуникации драйвера пространства пользователя с помощью списка свойств (включая пример кода), посмотрите Аппаратные средства Создания, Доступные для Приложений.
Важно различить управление представлением OSDictionary Вашей водительской индивидуальности Набора I/O и управление информационным списком свойств (или Info.plist
файл) сам. Обратите внимание на то, что все манипулирование списком свойств, которое обсуждает эта глава, касается представления OSDictionary Вашей водительской индивидуальности, не индивидуальности XML, определенной в Ваших водительских настройках пакета. Вы не можете изменить свое водительское Info.plist
файл всегда во время Вашей водительской продолжительности жизни. Когда Вы управляете своей водительской индивидуальностью во время start
или init
подпрограммы, Вы только управляете представлением ядра индивидуальности, существующей в родительском классе IORegistryEntry Вашего драйвера. Ваш драйвер (и другие объекты, в настоящее время находящиеся в Реестре I/O), может получить доступ к этому списку свойств и даже внести изменения в него, но те изменения будут потеряны, когда Ваш драйвер завершится, и Набор I/O удаляет соответствующий объект IORegistryEntry из Реестра I/O.
Набор libkern и Обзор Контейнерного класса
Несмотря на то, что libkern набор и контейнерные классы наследовались от OSMetaClassBase, более полезно думать о них как наследовавшийся от OSObject. OSObject определяет функции динамического контроля типов и выделения, в которых загружаемые модули ядра нуждаются и его виртуальные методы, и переопределенные операторы определяют, как объекты создают, сохраняют и избавляются в ядре. Для получения дополнительной информации о классе OSObject см. Основные принципы IOKit.
За исключением Даты (то, которое не используется в ядре из-за издержек, связанных с подпрограммами, должно было поддерживать форматы даты), XML-тэги Вы используете для указания типов данных в водительском Info.plist
файл имеет прямое, непосредственное отношение с libkern контейнером и классами набора аналогичных имен. Таблица 2-1 показывает это отношение.
XML-тэг | класс libkern |
---|---|
Массив | OSArray |
Булевская переменная | OSBoolean |
Данные | OSData |
Дата | Никакой libkern эквивалент |
Словарь | OSDictionary |
Число | OSNumber |
Строка | OSString |
Контейнерные классы libkern
libkern библиотека определяет контейнерные классы, содержащие примитивные значения или необработанные данные, подобные скалярным типам C. Таблица 2-2 показывает libkern контейнерные классы вместе с типами значений, которые они могут содержать.
Имя контейнерного класса | Содержание |
---|---|
OSBoolean | Булевы значения |
OSData | массивы байтов |
OSNumber | числовые значения |
OSString | массивы символов |
OSSymbol | ссылки на уникальные строки |
OSData, OSNumber и объекты OSString являются непостоянными объектами, однако, можно сделать их неизменными, объявив, что они const
. Это полезно, если Вы знаете, что Ваш код никогда не должен изменять определенный объект: Объявите объект быть const
и компилятор поймает любые попытки изменить его.
OSSymbol и OSBoolean отличаются от других контейнерных классов. Объект OSSymbol является неизменным объектом, представляющим значение уникальной строки, обычно находящееся в Пуле OSSymbol. Несмотря на то, что создание OSSymbols не является дешевым, они обеспечивают большую эффективность, когда необходимо получить доступ к тем же строкам много раз. Например, при исследовании Реестра I/O Вы будете видеть те же строки, используемые много раз, такие как «IOProviderClass» и «IOProbeScore». Фактически, все эти строки являются объектами OSSymbol. Поскольку пространство ядра ограничивается, эффективно сохранить пул обычно используемых строк для свободного доступа, а не потратить впустую пространство, хранящее те же строки несколько раз. Для получения дополнительной информации о том, как создать и использовать объекты OSSymbol, видит Самоанализ Инициализации и Создания и Контейнерного объекта Контейнерного объекта и Доступ.
OSBoolean является изменением OSSymbol. Поскольку существует только два значения, связанные с объектом OSBoolean, true
и false
, нет никакой потребности создать многократные копии тех же значений.
Каждый контейнерный класс определяет несколько методов для управления данными, которые он содержит. Распространенный среди них методы, чтобы инициализировать экземпляр с определенным значением, возвратить текущую стоимость и сравнить текущую стоимость с переданным - в значении. Используя libkern Набор и Контейнерные классы описывает некоторые из этих методов более подробно.
Классы Набора libkern
libkern классы набора управляют группами OSObject-производных-объектов, включая оба контейнерных объекта и другие объекты коллекции. Наследовав от libkern класса OSCollection, классы набора делают свое содержание доступным через позиционный или ассоциативный ключ и предоставляют итеративные услуги, позволяющие Вам просматривать их содержание один элемент за один раз. Все объекты класса набора являются непостоянными. Таблица 2-3 показывает libkern классы набора вместе с типами объектов, которые они могут содержать.
Имя класса набора | Содержание |
---|---|
OSArray | Список ссылок на OSObject-производные-объекты, каждый доступный позиционным индексом |
OSDictionary | Список OSObject-производных-объектов, каждый доступный уникальным ассоциативным ключом |
OSOrderedSet | Сортированный список уникальных OSObject-производных-объектов, каждый доступный согласно числовому порядку или функции членства |
OSSet | Несортированный список уникальных OSObject-производных-объектов, каждый доступный функцией членства |
Несмотря на то, что можно использовать OSSet и OSOrderedSet в драйвере (для сбора статистики, возможно), Вы будете, вероятно, больше интересоваться OSArray и OSDictionary, потому что они - прямые дубликаты XML-тэгов Массив и Словарь, который Вы используете в своем водительском списке свойств.
libkern классы набора имеют в общих методах, получающих объекты, проверяющих на присутствие объектов и создающих экземпляры с предопределенными группами объектов. Создание Объекта коллекции и Самоанализ Инициализации и Объекта коллекции и Доступ описывают некоторые из этих методов более подробно.
Поскольку они наследовались от OSCollection, libkern классы набора также обеспечивают доступ к своему содержанию через итератор. OSCollectionIterator определяет непротиворечивый механизм, выполняющий итерации по любому данному набору. При инстанцировании OSCollectionIterator для определенного объекта коллекции у Вас автоматически есть доступ к каждому элементу набора, не имея необходимость касаться тем, как объект коллекции организует свое содержание.
Используя libkern Набор и Контейнерные классы
libkern набор и контейнерные классы реализуют множество методов, создающих, инициализирующих, получающих доступ и исследующих экземпляры. Этот раздел представляет обзор этих методов, вместе с информацией о libkern подсчете ссылок класса и потокобезопасности.
Создание контейнерного объекта и инициализация
Все контейнерные классы реализуют один или несколько статических методов для создания экземпляров. Эти имена методов следуют за формой with
Параметры, где Параметры описывает параметры инициализации. Например, OSData определяет статический метод создания withBytes
это создает экземпляр OSData и инициализирует его с предоставленным буфером данных.
Этот пример использует OSData’s withCapacity
метод создания создать пустой объект OSData, инициализированный к данному размеру:
OSData *tmpData; |
int size = 16; //Initial capacity of tmpData in bytes. |
tmpData = OSData::withCapacity( size ); |
Некоторые статические методы создания не указывают “копию” вариант, такой как OSData’s withBytesNoCopy
и OSString’s withCStringNoCopy
. Эти методы создания создают экземпляр контейнерного объекта, но фактически не копируют предоставленные данные инициализации в него. Вместо этого метод дает контейнерному объекту ссылку на предоставленные данные.
Для наблюдения, почему это полезно предположите потребности драйвера использовать строку device_type
. Вы инстанцируете объекта OSString содержать строку с методом создания withCString
, как в следующем
OSString * myString; |
myString = OSString::withCString("device_type"); |
Но потому что Вы определяете device_type
как литеральная строка в Вашем водительском исполняемом коде, байты уже соединены проводом вниз для него и создание объекта OSString содержать, это просто тратит впустую пространство ядра. Поэтому, если Вам нужно к справочным данным, которые Вы определяете в своем водительском исполняемом коде, таком как строка device_type
, и никому не будут нужны те данные после того, как Ваш драйвер разгрузится, Вы не должны использовать “копию” методы создания. При создании libkern контейнерных объектов с “никакой копией” метод создания полученные объекты являются неизменными, потому что они содержат только указатель на данные, не сами данные.
При создании объекта OSSymbol Вы передаете строку (или объект OSString или простая струна до) к одному из статических методов создания OSSYMBOL. Если Ваша строка уже существует в Пуле OSSymbol, Вы получаете ссылку на исходную строку. Представление OSSymbol, которые представляют в виде строки тогда инкременты сохранять количество для отслеживания дополнительную ссылку на строку. Если Ваша строка уже не существует в пуле символа, Вы получаете указатель на новый объект OSSymbol, и Ваша строка добавляется к пулу.
Если Ваш драйвер определяет строку, которая будет необходима другим объектам IORegistryEntry после того, как Ваш драйвер завершится, можно создать OSSymbol для него с помощью OSSymbol’s withCStringNoCopy
метод создания. Если Ваша строка уже не существует в Пуле OSSymbol, withCStringNoCopy
метод сразу не добавляет его. Вместо этого ОССИМБОЛ использует строку в Вашем драйвере как его собственный, уникальный пул столько, сколько Ваш драйвер остается загруженным. В это время, если другие объекты IORegistryEntry создают тот же символ, они получают указатель на Вашу строку. Когда Ваш драйвер собирается разгрузиться, ОССИМБОЛ тогда копирует Вашу строку в генерала Оссимбола Пула, таким образом, это остается доступным другим объектам, имеющим ссылки на него.
OSData контейнерных классов, OSString и OSNumber также реализуют методы инициализации, инициализирующие существующие экземпляры контейнерных объектов с предоставленными данными. Например, OSString реализует три метода инициализации. Первые два, initWithCString
и initWithString
, скопируйте предоставленную струну до или объект OSString, соответственно, в экземпляр OSString. Третье, initWithCStringNoCopy
, не “никакая копия” вариант, инициализирующий экземпляр OSString, но не копирующий предоставленную струну до в нее. Точно так же OSData реализует несколько методов инициализации, инициализирующих объект OSData с блоком данных, включая вариант initWithBytesNoCopy
это инициализирует объект OSData, но не копирует байты в него.
OSBoolean и OSSymbol не реализуют init
методы. OSBoolean может только быть одним из двух предопределенных значений, и OSSymbol никогда не инстанцируют, не относясь к определенному строковому значению.
Самоанализ контейнерного объекта и доступ
Все контейнерные объекты реализуют различные методы, обеспечивающие доступ к значениям, которые они содержат. Например, все контейнерные классы реализуют по крайней мере один isEqualTo
метод, тестирующий равенство содержания контейнера и значение предоставленного объекта. Каждый isEqualTo
метод обрабатывает одни из различных типов данных, которые может содержать контейнерный объект. OSString, например, реализует четыре isEqualTo
методы, тестирующие равенство с простыми струнами до, другими объектами OSString, объектами OSData и неизвестными OSObject-производными-объектами.
OSSymbol реализует три isEqualTo
методы, два, что тестовое равенство со строкой или OSObject-производными-объектами и той, тестирующей равенство с другими объектами OSSymbol. Поскольку два объекта OSSymbol равны, только если они ссылаются на ту же строку в пуле OSSymbol, этом isEqualTo
метод просто выполняет экономичное сравнение указателя.
Большая часть реализации контейнерных классов get
методы, возвращающие и информацию об их содержании и содержание саму. OSString, например, реализации getLength
, который возвращает длину строки, и getChar
, который возвращает символ в предоставленной позиции в строке. Это также реализует getCStringNoCopy
, который возвращает указатель на внутреннее строковое представление, а не саму строку.
OSData реализует несколько get
методы, которые можно использовать для обнаружения размера внутреннего буфера данных объекта и сколько это увеличит, и получить указатель на буфер данных.
Создание объекта коллекции и инициализация
Как с контейнерными классами, libkern классы набора каждая реализация много методов создания формы with
Параметры. Каждый метод создания использует переданный - в объекте, описанном Параметрами для инициализации нового объекта. OSArray, например, реализует три метода создания, withArray
, withCapacity
, и withObjects
. Поскольку его имя предлагает, withArray
метод создает новый объект OSArray и заполняет его с предоставленным объектом OSArray. withCapacity
метод создает объект OSArray, который может содержать данное число ссылок и withObjects
метод создает объект OSArray и заполняет его с элементами статического массива OSObjects.
OSDictionary withCapacity
и withDictionary
методы создания подобны OSArray’s, но его два withObjects
методы создания требуют немного большего количества объяснения. Поскольку объект OSDictionary содержит набор пар ключ/значение, необходимо предоставить и ключи и значения для заполнения нового объекта OSDictionary. withObjects
методы создания каждый требует двух статических массивов, одного из значений OSObject и одного из любого OSString или OSSymbol ключи. Оба метода тогда создают новый OSDictionary, возражают и заполняют его с парами ключ/значение, состоящими из элемента ключевого массива и элемента массива значения в том же индексе.
Методы инициализации зеркально отражают методы создания за исключением того, что они воздействуют на существующие объекты коллекции вместо того, чтобы создать новые сначала.
Самоанализ объекта коллекции и доступ
Все классы набора реализуют несколько методов, дающих Вам информацию об их содержании и позволяющих Вам получать ссылки на определенные элементы. Кроме того, libkern библиотека обеспечивает класс OSCollectionIterator, реализующий методы, позволяющие Вам выполнять итерации по любому объекту коллекции и получать доступ к его элементам. Поскольку классы набора наследовались от OSCollection, объект OSCollectionIterator автоматически знает, как выполнить итерации по всем типам объектов коллекции.
Классы набора каждая реализация несколько get
методы, дающие Вам информацию о самом наборе или о конкретных объектах в наборе. OSDictionary, например, реализует шесть get
методы, три из которых связали значение с ключом типа OSString, OSSymbol, или const char
. Другие три информации о возврате о самом словаре, таком как его емкость памяти, размер инкремента, которым это растет, и текущее число объектов, которые это содержит.
Классы набора реализуют методы для и установки объекта в и удаляют объект из набора. Каждый класс набора реализует по крайней мере один set
метод, вставляющий переданный - в объект в объект коллекции. Кроме того, каждый класс набора реализует a setCapacityIncrement
метод, устанавливающий инкрементный размер, которым будет расти набор. Каждый класс набора также реализует по крайней мере один removeObject
метод, удаляющий указанный объект и автоматически выпускающий его. В случае OSArray содержание смещается для заполнения освобожденного спота.
Подсчет ссылок для набора и контейнерных классов
OSObject обеспечивает механизм сохранять-выпуска libkern использование контейнерных объектов и объектов коллекции. Общий источник проблем в разработке драйвера является несопоставленным подсчетом ссылок.
При первом создании объекта libkern его подсчет ссылок равен одному. Поэтому при создании объекта необходимо также выпустить его, когда Вам больше не нужен он. Вы делаете это путем вызова release
метод и затем установка указателя объекта на NULL
таким образом, Вы не можете случайно обратиться к выпущенному объекту снова. Если у Вас есть указатель на объект, который Вы не создавали, необходимо сохранить тот объект, только если необходимо полагаться на его присутствие и выпустить его, когда Вам больше не нужен он.
Некоторый беспорядок возникает с использованием get
иset
методы, характерные для всех libkern классов набора. Когда Вы используете a get
метод для получения задействованного объекта от набора тот задействованный подсчет ссылок объекта не постепенно увеличивается. Если Вы также не сохраняете объект, Вы не должны выпускать объект, который Вы получаете от a get
метод. Несмотря на то, что это не общая функция словарей, это - функция объектов IORegistryEntry.
Классы набора также реализуют диапазон set
методы, позволяющие Вам помещать объект в набор. set
методы действительно постепенно увеличивают новый задействованный подсчет ссылок объекта. Если, например, Вы создаете объект OSString и затем используете setObject
для установки его в объект OSDictionary объект OSString будет иметь подсчет ссылок 2, один от его создания и один от OSDictionary’s setObject
метод.
Таблица 2-4 суммирует сохранить поведение методов классов набора.
Метод | Сохраните поведение |
---|---|
добраться | Никогда не сохраняет |
набор | Всегда сохраняет |
| Всегда выпуски |
Потокобезопасность и классы контейнера и набора
Ни один из libkern контейнера и методов класса набора не ориентирован на многопотоковое исполнение. Если, например, Вы используете a get
метод для получения объекта от словаря и затем Вы вызываете retain
на нем нет никакой гарантии, что объект все еще допустим к тому времени, когда Вы выполняете retain
. Это вызвано тем, что объект, который Вы получили, только допустим, пока существует набор, содержащий его. Если Вы также не содержите ссылку на набор, Вы не можете быть уверены, что он не будет выпущен, прежде чем Вы получите шанс сохранить объект в нем.
В большинстве случаев, однако, Вы будете изменять свои собственные словари, и можно использовать водительский механизм блокировки для защиты их, при необходимости. Если Вы содержите ссылку на набор, элемент которого возражает, что Вы изменяете, можно быть довольно уверены, что те объекты будут продолжать существовать, пока Вы не выпускаете набор. Поскольку Набор I/O не освободит ни одного из Ваших объектов, пока Ваш драйвер не завершится (реализует free
метод), Вы ответственны за поддержание Ваших объектов коллекции и не выпуск их преждевременно.
Объекты libkern и XML
Все контейнерные объекты и объекты коллекции, за исключением OSSymbol и OSOrderedSet, реализуют a serialize
метод. Когда Вы хотите представлять произвольно сложную структуру данных независимым от расположения способом, Вы используете метод сериализации. Каждый раз Вы вызываете serialize
на объекте libkern объект OSSerialize создается, который содержит обоих XML (в массиве байтов) и состояние сериализации.
Хорошим примером сериализации является вывод ioreg
инструмент. Реестр I/O является набором соединенных словарей. Когда Вы вводите ioreg
на командной строке весь набор сериализируется для вывода на Вашем экране.
Конфигурирование Драйвера Используя libkern Классы
Как описано в libkern Классах и Вашем Драйвере, лучшее использование для libkern классов находится в Вашей водительской динамической фазе конфигурации, во время подпрограмм такой как init
, probe
, и start
. Этот раздел представляет примеры кода, иллюстрирующие, как можно использовать libkern контейнер и классы набора для конфигурирования водительской среды выполнения.
Конфигурирование подкласса IOAudioDevice
PhantomAudioDevice является подклассом в качестве примера IOAudioDevice (проект PhantomAudioDriver доступен в /Developer/Examples/Kernel/IOKit/Audio/PhantomAudioDriver
и на CVSWeb в http://developer .apple.com/darwin/tools/cvs). В createAudioEngines
метод, PhantomAudioDevice использует объекты libkern и методы, чтобы получить доступ к его списку свойств и создать новый аудио механизм для каждого аудио массива механизма в его индивидуальности. createAudioEngines
метод показан в Перечислении 2-1.
Перечисление 2-1 Используя объекты libkern и методы в создании аудио механизма
bool PhantomAudioDevice::createAudioEngine() |
{ |
bool result = false; |
OSArray *audioEngineArray; |
audioEngineArray = OSDynamicCast(OSArray, |
getProperty(AUDIO_ENGINES_KEY)); |
if (audioEngineArray) { |
OSCollectionIterator *audioEngineIterator; |
audioEngineIterator = |
OSCollectionIterator::withCollection(audioEngineArray); |
if (audioEngineIterator) { |
OSDictionary *audioEngineDict; |
while (audioEngineDict = (OSDictionary*) |
audioEngineIterator->getNextObject()) { |
if (OSDynamicCast(OSDictionary, audioEngineDict) != NULL) { |
PhantomAudioEngine *audioEngine; |
audioEngine = new PhantomAudioEngine; |
if (audioEngine) { |
if (audioEngine->init(audioEngineDict)) { |
activateAudioEngine(audioEngine); |
} |
audioEngine->release(); |
} |
} |
} |
audioEngineIterator->release(); |
} |
} else { |
IOLog("PhantomAudioDevice[%p]::createAudioEngine() - Error: |
no AudioEngine array in personality.\n", this); |
goto Done; |
} |
result = true; |
Done: |
return result; |
} |
Конфигурирование подкласса IOUSBMassStorageClass
Драйвер IOUSBMassStorageClass соответствует на массовом хранении совместимые классом интерфейсы USB-устройств, объявляющих, что их класс устройства составной объект. Иногда, однако, USB-устройства, имеющие массовое хранение совместимые классом интерфейсы, объявляют, что их класс устройства специфичен для поставщика вместо составного объекта. Драйвер IOUSBMassStorageClass может все еще управлять этими интерфейсами, но потому что тип класса устройства, о котором сообщают, специфичен для поставщика, драйвер IOUSBMassStorageClass не будет соответствовать на них.
Решение состоит в том, чтобы обеспечить KEXT, состоящий из только Info.plist
файл, содержащий индивидуальность для устройства. Эта индивидуальность действует как своего рода мост между интерфейсом и драйвером IOUSBMassStorageClass: Это соответствует в интерфейсе и заставляет Набор I/O инстанцировать драйвера IOUSBMassStorageClass. Драйвер IOUSBMassStorageClass тогда исследует индивидуальность на специальный словарь, названный “Характеристики Массового хранения USB”, который содержит интерфейсный подкласс и значения протокола. Если словарь присутствует, драйвер IOUSBMassStorageClass использует эти значения вместо соответствующих значений, о которых сообщает устройство.
Перечисление 2-2 показывает часть IOUSBMassStorageClass start
метод, определяющий местоположение словаря Характеристик Массового хранения USB и получающий его содержание.
Перечисление 2-2 Частичное перечисление IOUSBMassStorageClass запускает метод
bool IOUSBMassStorageClass::start( IOService * provider ) |
{ |
// Code calling super::start, opening the interface, |
// and initializing some member variables not shown here. |
// Make sure provider is an IOUSBInterface object. |
SetInterfaceReference(OSDynamicCast(IOUSBInterface, provider)); |
if (GetInterfaceReference() == NULL) |
return false; |
// Check if the personality for this device specifies a preferred |
// protocol. |
if (getProperty(kIOUSBMassStorageCharacteristics) == NULL) |
{ |
// This device does not specify a preferred protocol, use the |
// protocol defined in the descriptor. |
// fPreferredProtocol and fPreferredSubclass are private member |
// variables of the IOUSBMassStorageClass class. |
fPreferredProtocol = |
GetInterfaceReference()->GetInterfaceProtocol(); |
fPreferredSubclass = |
GetInterfaceReference()->GetInterfaceSubClass(); |
} else { |
OSDictionary * characterDict; |
characterDict = OSDynamicCast(OSDictionary, |
getProperty(kIOUSBMassStorageCharacteristics)); |
// Check if the personality for this device specifies a preferred |
protocol |
if (characterDict->getObject(kIOUSBMassStoragePreferredProtocol) |
== NULL) |
{ |
// This device does not specify a preferred protocol, use the |
// protocol defined in the descriptor. |
fPreferredProtocol = |
GetInterfaceReference()->GetInterfaceProtocol(); |
} else { |
OSNumber * preferredProtocol; |
preferredProtocol = OSDynamicCast(OSNumber, characterDict-> |
getObject(kIOUSBMassStoragePreferredProtocol); |
// This device has a preferred protocol, use that. |
fPreferredProtocol = preferredProtocol->unsigned32BitValue(); |
} |
// Check if the personality for this device specifies a preferred |
// subclass. |
if (characterDict->getObject(kIOUSBMassStoragePreferredSubclass) |
== NULL) |
{ |
// This device does not specify a preferred subclass, use the |
// subclass defined in the descriptor. |
fPreferredSubclass = |
GetInterfaceReference()->GetInterfaceSubClass(); |
} else { |
OSNumber * preferredSubclass; |
preferredSubclass = OSDynamicCast(OSNumber, characterDict-> |
getObject(kIOUSBMassStoragePreferredSubclass)); |
// This device has a preferred subclass, use that. |
fPreferredSubclass = preferredSubclass->unsigned32BitValue(); |
} |
} |