@@ -8,21 +8,22 @@ cfg_if! {
88
99cfg_if !  { 
1010    if  #[ cfg( target_vendor = "apple" ) ]  { 
11-         use  core_foundation:: base:: CFType ; 
12-         use  core_foundation:: base:: TCFType ; 
13-         use  core_foundation:: dictionary:: CFDictionary ; 
14-         use  core_foundation:: dictionary:: CFMutableDictionary ; 
15-         use  core_foundation:: number:: CFNumber ; 
16-         use  core_foundation:: string:: CFString ; 
17-         use  core_foundation_sys:: base:: { kCFAllocatorDefault,  CFRetain } ; 
18-         use  io_kit_sys:: * ; 
19-         use  io_kit_sys:: keys:: * ; 
20-         use  io_kit_sys:: serial:: keys:: * ; 
21-         use  io_kit_sys:: types:: * ; 
22-         use  io_kit_sys:: usb:: lib:: * ; 
23-         use  core:: ffi:: { c_char,  c_int,  c_uint,  c_void,  CStr } ; 
11+         use  core:: ffi:: { c_char,  c_int,  c_uint,  CStr } ; 
2412        use  core:: mem:: MaybeUninit ; 
2513
14+         use  objc2_core_foundation:: { 
15+             kCFAllocatorDefault,  CFMutableDictionary ,  CFNumber ,  CFRetained ,  CFString ,  CFType , 
16+         } ; 
17+         #[ allow( deprecated) ] 
18+         use  objc2_io_kit:: { kIOMasterPortDefault,  IOMasterPort } ; 
19+         use  objc2_io_kit:: { 
20+             io_object_t,  io_registry_entry_t,  kIOServiceClass,  kIOUSBDeviceClassName, 
21+             kIOUSBHostInterfaceClassName,  IOIteratorNext ,  IOObjectGetClass ,  IOObjectRelease , 
22+             IORegistryEntryCreateCFProperties ,  IORegistryEntryCreateCFProperty , 
23+             IORegistryEntryGetParentEntry ,  IOServiceGetMatchingServices ,  IOServiceMatching , 
24+             kIOSerialBSDServiceValue,  kIOSerialBSDTypeKey,  kIOSerialBSDAllTypes, 
25+         } ; 
26+ 
2627        // NOTE: Do not use `mach` nor `mach2` crates, they're unmaintained, 
2728        // and don't work on tvOS/watchOS/visionOS. 
2829        // 
@@ -273,22 +274,24 @@ fn parse_modalias(moda: &str) -> Option<UsbPortInfo> {
273274#[ cfg( target_vendor = "apple" ) ]  
274275fn  get_parent_device_by_type ( 
275276    device :  io_object_t , 
276-     parent_type :  * const   c_char , 
277+     parent_type :  & CStr , 
277278)  -> Option < io_registry_entry_t >  { 
278-     let  parent_type = unsafe  {  CStr :: from_ptr ( parent_type)  } ; 
279279    let  mut  device = device; 
280280    loop  { 
281281        let  mut  class_name = MaybeUninit :: < [ c_char ;  128 ] > :: uninit ( ) ; 
282-         unsafe  {  IOObjectGetClass ( device,  class_name. as_mut_ptr ( )   as   * mut   c_char )  } ; 
282+         unsafe  {  IOObjectGetClass ( device,  class_name. as_mut_ptr ( ) )  } ; 
283283        let  class_name = unsafe  {  class_name. assume_init ( )  } ; 
284284        let  name = unsafe  {  CStr :: from_ptr ( & class_name[ 0 ] )  } ; 
285285        if  name == parent_type { 
286286            return  Some ( device) ; 
287287        } 
288288        let  mut  parent = MaybeUninit :: uninit ( ) ; 
289289        if  unsafe  { 
290-             IORegistryEntryGetParentEntry ( device,  kIOServiceClass,  parent. as_mut_ptr ( ) ) 
291-                 != KERN_SUCCESS 
290+             IORegistryEntryGetParentEntry ( 
291+                 device, 
292+                 kIOServiceClass. as_ptr ( )  as  _ , 
293+                 parent. as_mut_ptr ( ) , 
294+             )  != KERN_SUCCESS 
292295        }  { 
293296            return  None ; 
294297        } 
@@ -300,24 +303,17 @@ fn get_parent_device_by_type(
300303#[ allow( non_upper_case_globals) ]  
301304/// Returns a specific property of the given device as an integer. 
302305fn  get_int_property ( device_type :  io_registry_entry_t ,  property :  & str )  -> Result < u32 >  { 
303-     let  cf_property = CFString :: new ( property) ; 
304- 
305-     let  cf_type_ref = unsafe  { 
306-         IORegistryEntryCreateCFProperty ( 
307-             device_type, 
308-             cf_property. as_concrete_TypeRef ( ) , 
309-             kCFAllocatorDefault, 
310-             0 , 
311-         ) 
312-     } ; 
313-     if  cf_type_ref. is_null ( )  { 
314-         return  Err ( Error :: new ( ErrorKind :: Unknown ,  "Failed to get property" ) ) ; 
306+     let  cf_property = CFString :: from_str ( property) ; 
307+ 
308+     let  cf_type = unsafe  { 
309+         IORegistryEntryCreateCFProperty ( device_type,  Some ( & cf_property) ,  kCFAllocatorDefault,  0 ) 
315310    } 
311+     . ok_or_else ( || Error :: new ( ErrorKind :: Unknown ,  "Failed to get property" ) ) ?; 
316312
317-     let  cf_type = unsafe  {  CFType :: wrap_under_create_rule ( cf_type_ref)  } ; 
318313    cf_type
319314        . downcast :: < CFNumber > ( ) 
320-         . and_then ( |n| n. to_i64 ( ) ) 
315+         . ok ( ) 
316+         . and_then ( |n| n. as_i64 ( ) ) 
321317        . map ( |n| n as  u32 ) 
322318        . ok_or ( Error :: new ( 
323319            ErrorKind :: Unknown , 
@@ -328,23 +324,16 @@ fn get_int_property(device_type: io_registry_entry_t, property: &str) -> Result<
328324#[ cfg( target_vendor = "apple" ) ]  
329325/// Returns a specific property of the given device as a string. 
330326fn  get_string_property ( device_type :  io_registry_entry_t ,  property :  & str )  -> Result < String >  { 
331-     let  cf_property = CFString :: new ( property) ; 
332- 
333-     let  cf_type_ref = unsafe  { 
334-         IORegistryEntryCreateCFProperty ( 
335-             device_type, 
336-             cf_property. as_concrete_TypeRef ( ) , 
337-             kCFAllocatorDefault, 
338-             0 , 
339-         ) 
340-     } ; 
341-     if  cf_type_ref. is_null ( )  { 
342-         return  Err ( Error :: new ( ErrorKind :: Unknown ,  "Failed to get property" ) ) ; 
327+     let  cf_property = CFString :: from_str ( property) ; 
328+ 
329+     let  cf_type = unsafe  { 
330+         IORegistryEntryCreateCFProperty ( device_type,  Some ( & cf_property) ,  kCFAllocatorDefault,  0 ) 
343331    } 
332+     . ok_or_else ( || Error :: new ( ErrorKind :: Unknown ,  "Failed to get property" ) ) ?; 
344333
345-     let  cf_type = unsafe  {  CFType :: wrap_under_create_rule ( cf_type_ref)  } ; 
346334    cf_type
347335        . downcast :: < CFString > ( ) 
336+         . ok ( ) 
348337        . map ( |s| s. to_string ( ) ) 
349338        . ok_or ( Error :: new ( ErrorKind :: Unknown ,  "Failed to get string value" ) ) 
350339} 
@@ -353,8 +342,9 @@ fn get_string_property(device_type: io_registry_entry_t, property: &str) -> Resu
353342/// Determine the serial port type based on the service object (like that returned by 
354343/// `IOIteratorNext`). Specific properties are extracted for USB devices. 
355344fn  port_type ( service :  io_object_t )  -> SerialPortType  { 
356-     let  bluetooth_device_class_name = b"IOBluetoothSerialClient\0 " . as_ptr ( )  as  * const  c_char ; 
357-     let  usb_device_class_name = b"IOUSBHostInterface\0 " . as_ptr ( )  as  * const  c_char ; 
345+     let  bluetooth_device_class_name =
346+         CStr :: from_bytes_with_nul ( b"IOBluetoothSerialClient\0 " ) . unwrap ( ) ; 
347+     let  usb_device_class_name = kIOUSBHostInterfaceClassName; 
358348    let  legacy_usb_device_class_name = kIOUSBDeviceClassName; 
359349
360350    let  maybe_usb_device = get_parent_device_by_type ( service,  usb_device_class_name) 
@@ -388,29 +378,24 @@ cfg_if! {
388378    if  #[ cfg( target_vendor = "apple" ) ]  { 
389379        /// Scans the system for serial ports and returns a list of them. 
390380/// The `SerialPortInfo` struct contains the name of the port which can be used for opening it. 
381+ [ allow( deprecated) ] 
391382        pub  fn  available_ports( )  -> Result <Vec <SerialPortInfo >> { 
392383            let  mut  vec = Vec :: new( ) ; 
393384            unsafe  { 
394385                // Create a dictionary for specifying the search terms against the IOService 
395-                 let  classes_to_match = IOServiceMatching ( kIOSerialBSDServiceValue) ; 
396-                 if  classes_to_match. is_null( )  { 
397-                     return  Err ( Error :: new( 
398-                         ErrorKind :: Unknown , 
399-                         "IOServiceMatching returned a NULL dictionary." , 
400-                     ) ) ; 
401-                 } 
402-                 let  mut  classes_to_match = CFMutableDictionary :: wrap_under_create_rule( classes_to_match) ; 
386+                 let  classes_to_match = IOServiceMatching ( kIOSerialBSDServiceValue. as_ptr( ) ) 
387+                 . ok_or_else( || Error :: new( ErrorKind :: Unknown ,  "IOServiceMatching returned a NULL dictionary." ) ) ?; 
388+                 let  classes_to_match = classes_to_match. cast_unchecked:: <CFString ,  CFType >( ) ; 
403389
404390                // Populate the search dictionary with a single key/value pair indicating that we're 
405391                // searching for serial devices matching the RS232 device type. 
406-                 let  search_key = CStr :: from_ptr( kIOSerialBSDTypeKey) ; 
407-                 let  search_key = CFString :: from_static_string( search_key. to_str( ) . map_err( |_| Error :: new( ErrorKind :: Unknown ,  "Failed to convert search key string" ) ) ?) ; 
408-                 let  search_value = CStr :: from_ptr( kIOSerialBSDAllTypes) ; 
409-                 let  search_value = CFString :: from_static_string( search_value. to_str( ) . map_err( |_| Error :: new( ErrorKind :: Unknown ,  "Failed to convert search key string" ) ) ?) ; 
410-                 classes_to_match. set( search_key,  search_value) ; 
392+                 let  search_key = CFString :: from_static_str( kIOSerialBSDTypeKey. to_str( ) . map_err( |_| Error :: new( ErrorKind :: Unknown ,  "Failed to convert search key string" ) ) ?) ; 
393+                 let  search_value = CFString :: from_static_str( kIOSerialBSDAllTypes. to_str( ) . map_err( |_| Error :: new( ErrorKind :: Unknown ,  "Failed to convert search key string" ) ) ?) ; 
394+                 classes_to_match. set( & search_key,  & search_value) ; 
411395
412396                // Get an interface to IOKit 
413397                let  mut  master_port:  mach_port_t = MACH_PORT_NULL ; 
398+                 #[ allow( deprecated) ] 
414399                let  mut  kern_result = IOMasterPort ( MACH_PORT_NULL ,  & mut  master_port) ; 
415400                if  kern_result != KERN_SUCCESS  { 
416401                    return  Err ( Error :: new( 
@@ -419,17 +404,11 @@ cfg_if! {
419404                    ) ) ; 
420405                } 
421406
422-                 // Run the search. IOServiceGetMatchingServices consumes one reference count of 
423-                 // classes_to_match, so explicitly retain. 
424-                 // 
425-                 // TODO: We could also just mem::forget classes_to_match like in 
426-                 // TCFType::into_CFType. Is there a special reason that there is no 
427-                 // TCFType::into_concrete_TypeRef()? 
428-                 CFRetain ( classes_to_match. as_CFTypeRef( ) ) ; 
407+                 // Run the search. 
429408                let  mut  matching_services = MaybeUninit :: uninit( ) ; 
430409                kern_result = IOServiceGetMatchingServices ( 
431410                    kIOMasterPortDefault, 
432-                     classes_to_match. as_concrete_TypeRef ( ) , 
411+                     Some ( classes_to_match. as_opaque ( ) . into ( ) ) , 
433412                    matching_services. as_mut_ptr( ) , 
434413                ) ; 
435414                if  kern_result != KERN_SUCCESS  { 
@@ -467,15 +446,15 @@ cfg_if! {
467446                        // properties dict has been allocated and we as the caller are in charge of 
468447                        // releasing it. 
469448                        let  props = props. assume_init( ) ; 
470-                         let  props:  CFDictionary <CFString ,  * const  c_void> = CFDictionary :: wrap_under_create_rule( props) ; 
449+                         let  props:  CFRetained <CFMutableDictionary > = CFRetained :: from_raw( core:: ptr:: NonNull :: new( props) . unwrap( ) ) ; 
450+                         let  props = props. cast_unchecked:: <CFString ,  CFType >( ) ; 
471451
472452                        for  key in [ "IOCalloutDevice" ,  "IODialinDevice" ] . iter( )  { 
473-                             let  cf_key = CFString :: new ( key) ; 
453+                             let  cf_key = CFString :: from_str ( key) ; 
474454
475-                             if  let  Some ( cf_ref)  = props. find( cf_key)  { 
476-                                 let  cf_type = CFType :: wrap_under_get_rule( * cf_ref) ; 
455+                             if  let  Some ( cf_type)  = props. get( & cf_key)  { 
477456                                match  cf_type
478-                                      . downcast :: <CFString >( ) 
457+                                      . downcast_ref :: <CFString >( ) 
479458                                     . map( |s| s. to_string( ) ) 
480459                                { 
481460                                    Some ( path)  => { 
0 commit comments