1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
//! # Kernel and Drivers
//!
//! Configure device drivers provided by the app.

use super::DefaultDictionary;
use serde::{Deserialize, Serialize};

/// Driver Personalities
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq)]
pub struct DriverPersonalities {
    /// One or more groups of attributes that tell the system about the devices your
    /// driver supports.
    ///
    /// This key contains a dictionary of driver personalities, each of which specifies
    /// how to pair the driver to a device. Each key in the dictionary is a string you
    /// designate as the name of a specific personality, and the system doesn’t use your
    /// key names internally. The value of each key is a dictionary of attributes that
    /// describe the specific device to match with the driver. Thus, each key and
    /// dictionary combination represents a single personality of the driver.
    /// The system uses these personalities to match the driver to an attached device.
    ///
    /// During the matching process, the system compares the attributes in each
    /// personality dictionary to data it obtained from the attached device.
    /// For example, if the personality dictionary includes the VendorID key, the system
    /// compares that key to the vendor information from the device. The system picks
    /// the driver that is compatible with the device and provides the best overall match.
    /// It then uses additional information from the personality dictionary to load and
    /// run the driver.
    ///
    /// All personality dictionaries must include the following keys:
    /// * CFBundleIdentifier
    /// * IOProviderClass
    /// * IOClass
    ///
    /// Include any of the following keys in your personality dictionary to customize the
    /// match criteria:
    /// * IOPropertyMatch
    /// * IONameMatch
    /// * IOResourceMatch
    /// * IOParentMatch
    /// * IOPathMatch
    /// * IOMatchCategory
    /// * Device-specific keys, such as DeviceUsagePairs, VendorID, or ProductID.
    /// See a specific IOService subclass for information about the keys it supports.
    ///
    /// Include one of more of the following keys to specify how to load your driver’s
    /// code:
    /// * IOUserClass
    /// * IOUserServerName
    /// * IOUserClientClass
    ///
    /// Use the following keys to further customize your driver’s behavior:
    /// * IOMatchDefer. Set the value of this key to true to defer the matching process
    ///   until after kextd starts.
    /// * IOUserServerOneProcess. Set the value of this key to true to run your DriverKit
    ///   services in one process.
    /// If the key is missing or its value is false, the system creates a separate process
    /// for each service.
    ///
    /// ## Availability
    /// * macOS 10.0+
    ///
    /// ## Framework
    /// * Kernel
    #[serde(rename = "IOKitPersonalities", skip_serializing_if = "Option::is_none")]
    pub kit_personalities: Option<KitPersonalities>,
}

/// Kit Personalities
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq)]
pub struct KitPersonalities {
    /// The name of your driver’s main class, which is the entry point for interacting
    /// with your driver’s code.
    ///
    /// Include this key only in the personality dictionary of a DriverKit extension, and
    /// use it to specify the name of the custom IOService subclass that provides your
    /// driver’s behavior. When it’s time to load your driver, the system instantiates
    /// the specified class and begins the initialization and startup processes.
    ///
    /// ## Availability
    /// * macOS 10.14+
    ///
    /// ## Framework
    /// * DriverKit
    #[serde(rename = "IOUserClass", skip_serializing_if = "Option::is_none")]
    pub user_class: Option<String>,
    /// The name of the class that your driver expects to provide the implementation for
    /// its provider object.
    ///
    /// The value of this key is a string that contains the name of an IOService subclass.
    /// This class corresponds to the provider object that the system passes to your
    /// IOService subclass at startup. (For a kernel extension, the system passes the
    /// provider object to the start method of your IOService subclass.
    /// For a DriverKit extension, the system passes it to the Start method of your
    /// IOService subclass.) Use the provider object in your driver you receive to
    /// communicate with the underlying device.
    ///
    /// ## Availability
    /// * macOS 10.0+
    ///
    /// ## Framework
    /// * Kernel
    #[serde(rename = "IOProviderClass", skip_serializing_if = "Option::is_none")]
    pub provider_class: Option<String>,
    /// The name of the class to instantiate from your driver.
    ///
    /// The value of this key is a string that contains the name of a custom IOService
    /// subclass in your driver. When the system successfully matches one of your
    /// driver’s personalities to a device, it instantiates the class in this key and
    /// calls its start method.
    ///
    /// For the personalities in a DriverKit extension, specify the value IOUserService
    /// unless otherwise directed by the documentation. For example, the
    /// IOUserHIDEventService class expects you to specify the value
    /// AppleUserHIDEventService.
    ///
    /// ## Availability
    /// * macOS 10.0+
    ///
    /// ## Framework
    /// * Kernel
    #[serde(rename = "IOClass", skip_serializing_if = "Option::is_none")]
    pub class: Option<String>,
    /// The name of the class to instantiate when the system requires a client connection
    /// to the driver.
    ///
    /// The value of this key is a string that contains the name of an IOService subclass
    /// in your driver.
    ///
    /// ## Availability
    /// * macOS 10.0+
    ///
    /// ## Framework
    /// * Kernel
    #[serde(rename = "IOUserClientClass", skip_serializing_if = "Option::is_none")]
    pub user_client_class: Option<String>,
    /// The name that the system uses to facilitate communication between your driver and
    /// other clients.
    ///
    /// Typically, you set the value of this key to your kext or DriverKit extension’s
    /// bundle identifier. The system registers your driver under the specified server
    /// name, and uses that name to facilitate communications between your driver and
    /// other clients, including the kernel itself.
    ///
    /// ## Availability
    /// * macOS 10.14+
    ///
    /// ## Framework
    /// * DriverKit
    #[serde(rename = "IOUserServerName", skip_serializing_if = "Option::is_none")]
    pub user_server_name: Option<String>,
    /// The device-specific keys the system must match in order to use your driver.
    ///
    /// The value of this key is a dictionary of device-specific keys and values to use
    /// during the matching process. For the system to match the driver personality to
    /// a device, all keys in the dictionary must be present in the device, and all values
    /// must exactly match the device-provided values.
    ///
    /// ## Availability
    /// * macOS 10.0+
    ///
    /// ## Framework
    /// * Kernel
    #[serde(rename = "IOPropertyMatch", skip_serializing_if = "Option::is_none")]
    pub property_match: Option<DefaultDictionary>,
    /// One or more strings that contain the names of possible provider objects in the
    /// system registry.
    ///
    /// The value of this key is a string or an array of strings.
    /// The system begins the matching process with a provider object, and looks for
    /// additional drivers or nubs that support that provider object. When this key is
    /// present, the system compares its values to the provider object’s name.
    /// (It also compares the strings to the provider’s compatible and device_type
    /// properties.) If it doesn’t find any matches, the system doesn’t match the
    /// driver to the provider object.
    ///
    /// The default name of a provider object is its class name, but providers may
    /// register a custom name. For more information about how to set or get
    /// information for registered services, see IORegistryEntry.
    ///
    /// ## Availability
    /// * macOS 10.0+
    ///
    /// ## Framework
    /// * Kernel
    #[serde(rename = "IONameMatch", skip_serializing_if = "Option::is_none")]
    pub name_match: Option<Vec<String>>,
    /// One or more system-specific or device-specific resources that your driver
    /// requires.
    ///
    /// The value of this key is a string or an array of strings.
    /// Each string contains the name of a resource that must be published in the global
    /// resource list before the system loads the driver. For example, specify IOBSD
    /// to prevent the system from loading your driver until after the BSD kernel is
    /// available.
    ///
    /// To access the list of global resources, call the getResourceService method of
    /// IOService. To publish custom resources from your driver, call the
    /// publishResource method.
    ///
    /// ## Availability
    /// * macOS 10.0+
    ///
    /// ## Framework
    /// * Kernel
    #[serde(rename = "IOResourceMatch", skip_serializing_if = "Option::is_none")]
    pub resource_match: Option<String>,
    /// ## Availability
    /// * macOS 10.0+
    ///
    /// ## Framework
    /// * Kernel
    #[serde(rename = "IOParentMatch", skip_serializing_if = "Option::is_none")]
    pub parent_match: Option<DefaultDictionary>,
    /// ## Availability
    /// * macOS 10.0+
    ///
    /// ## Framework
    /// * Kernel
    #[serde(rename = "IOPathMatch", skip_serializing_if = "Option::is_none")]
    pub path_match: Option<String>,
    /// ## Availability
    /// * macOS 10.0+
    ///
    /// ## Framework
    /// * Kernel
    #[serde(rename = "IOMatchCategory", skip_serializing_if = "Option::is_none")]
    pub match_category: Option<String>,
}

/// Kext Dependencies
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq)]
pub struct KextDependencies {
    /// The backward limit of compatibility for the current driver.
    ///
    /// Specify a previous version for the current driver, or the driver’s current
    /// version. Format this string the same way you format the value of the
    /// CFBundleVersion key. The combination of this value and the value in the
    /// CFBundleVersion key define the range of versions that offers the same level of
    /// compatibility. Dependent drivers use this information to determine if they are
    /// compatible with the driver. For example, if the driver’s current version is
    /// 10.0, and you set the value of this key to 5.0, a driver that depends on version
    /// 7.0 can successfully use the current driver.
    ///
    /// When you change your driver in a way that breaks compatibility with your old code,
    /// update the value of this key. At that time, set the new value to the current
    /// version of your driver.
    ///
    /// ## Availability
    /// * macOS 10.0+
    ///
    /// ## Framework
    /// * Kernel
    #[serde(
        rename = "OSBundleCompatibleVersion",
        skip_serializing_if = "Option::is_none"
    )]
    pub bundle_compatible_version: Option<String>,
    /// The drivers that the system must load before your driver.
    ///
    /// Use this key to specify other drivers that your driver depends on.
    /// For example, specify any drivers that contain symbols your driver creates or uses
    /// at startup. The system loads the drivers in this list before it attempts to
    /// load your driver. If the system fails to resolve the dependencies or load the
    /// corresponding libraries, the kernel doesn’t load your driver.
    ///
    /// Each key in the dictionary is the bundle identifier of another driver, and the
    /// value is a string that contains the minimum version of the driver you require.
    /// Your driver must be compatible with the specified version of the other driver.
    ///
    /// Don’t include this key for codeless kexts.
    ///
    /// ## Availability
    /// * macOS 10.0+
    ///
    /// ## Framework
    /// * Kernel
    #[serde(rename = "OSBundleLibraries", skip_serializing_if = "Option::is_none")]
    pub bundle_libraries: Option<DefaultDictionary>,
}

/// Thunderbolt Compatibility
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq)]
pub struct ThunderboltCompatibility {
    /// A Boolean value that indicates whether your driver supports Thunderbolt devices.
    ///
    /// Include this key in the personality dictionary of your driver if that personality
    /// supports Thunderbolt devices.
    ///
    /// ## Availability
    /// * macOS 10.0+
    ///
    /// ## Framework
    /// * PCIDriverKit
    #[serde(
        rename = "IOPCITunnelCompatible",
        skip_serializing_if = "Option::is_none"
    )]
    pub tunnel_compatible: Option<bool>,
}