Implement support for getting utsname info on iOS (#239)

* Implement support for getting utsname info on iOS

* Fix typo

* Add dartdoc and update version no

* Add missing newline

* Review feedback

* Move utsname wrapping to IosUtsname class

* Fix caps per name convention

* Fix format

* Review feedback

* Complete merge
diff --git a/packages/device_info/CHANGELOG.md b/packages/device_info/CHANGELOG.md
index 171b5f9..75159de 100644
--- a/packages/device_info/CHANGELOG.md
+++ b/packages/device_info/CHANGELOG.md
@@ -1,4 +1,8 @@
-## 0.0.2 - Oct 20, 2017
+## 0.0.3 - October 24, 2017
+
+* Add support for utsname
+
+## 0.0.2 - October 20, 2017
 
 * Fixed broke type comparison
 * Added "isPhysicaldevice" field, detecting emulators/simulators
diff --git a/packages/device_info/README.md b/packages/device_info/README.md
index 5652697..8ccbeb5 100644
--- a/packages/device_info/README.md
+++ b/packages/device_info/README.md
@@ -18,7 +18,7 @@
 print('Running on ${androidInfo.model}');  // e.g. "Moto G (4)"
 
 IosDeviceInfo iosInfo = await deviceInfo.iosInfo;
-print('Running on ${iosInfo.model}');  // e.g. "iPhone 6"
+print('Running on ${iosInfo.utsname.machine}');  // e.g. "iPod7,1"
 ```
 
 You will find links to the API docs on the [pub page](https://pub.dartlang.org/packages/device_info).
diff --git a/packages/device_info/example/lib/main.dart b/packages/device_info/example/lib/main.dart
index f01e3d9..0cbde1e 100644
--- a/packages/device_info/example/lib/main.dart
+++ b/packages/device_info/example/lib/main.dart
@@ -94,6 +94,11 @@
       'localizedModel': data.localizedModel,
       'identifierForVendor': data.identifierForVendor,
       'isPhysicalDevice': data.isPhysicalDevice,
+      'utsname.sysname:': data.utsname.sysname,
+      'utsname.nodename:': data.utsname.nodename,
+      'utsname.release:': data.utsname.release,
+      'utsname.version:': data.utsname.version,
+      'utsname.machine:': data.utsname.machine,
     };
   }
 
diff --git a/packages/device_info/ios/Classes/DeviceInfoPlugin.m b/packages/device_info/ios/Classes/DeviceInfoPlugin.m
index 9a0d2b5..4c8cf63 100644
--- a/packages/device_info/ios/Classes/DeviceInfoPlugin.m
+++ b/packages/device_info/ios/Classes/DeviceInfoPlugin.m
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #import "DeviceInfoPlugin.h"
+#import <sys/utsname.h>
 
 @implementation DeviceInfoPlugin
 + (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
@@ -16,6 +17,8 @@
 - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
   if ([@"getIosDeviceInfo" isEqualToString:call.method]) {
     UIDevice* device = [UIDevice currentDevice];
+    struct utsname un;
+    uname(&un);
 
     result(@{
       @"name" : [device name],
@@ -25,6 +28,13 @@
       @"localizedModel" : [device localizedModel],
       @"identifierForVendor" : [[device identifierForVendor] UUIDString],
       @"isPhysicalDevice" : [self isDevicePhysical],
+      @"utsname" : @{
+        @"sysname" : @(un.sysname),
+        @"nodename" : @(un.nodename),
+        @"release" : @(un.release),
+        @"version" : @(un.version),
+        @"machine" : @(un.machine),
+      }
     });
   } else {
     result(FlutterMethodNotImplemented);
diff --git a/packages/device_info/lib/device_info.dart b/packages/device_info/lib/device_info.dart
index 5f870f6..16634a6 100644
--- a/packages/device_info/lib/device_info.dart
+++ b/packages/device_info/lib/device_info.dart
@@ -208,6 +208,7 @@
     this.localizedModel,
     this.identifierForVendor,
     this.isPhysicalDevice,
+    this.utsname,
   });
 
   /// Device name.
@@ -231,8 +232,11 @@
   /// `false` if the application is running in a simulator, `true` otherwise.
   final bool isPhysicalDevice;
 
+  /// Operating system information derived from `sys/utsname.h`.
+  final IosUtsname utsname;
+
   /// Deserializes from the JSON message received from [_kChannel].
-  static IosDeviceInfo _fromJson(Map<String, Object> json) {
+  static IosDeviceInfo _fromJson(Map<String, dynamic> json) {
     return new IosDeviceInfo._(
       name: json['name'],
       systemName: json['systemName'],
@@ -241,6 +245,45 @@
       localizedModel: json['localizedModel'],
       identifierForVendor: json['identifierForVendor'],
       isPhysicalDevice: json['isPhysicalDevice'] == 'true',
+      utsname: IosUtsname._fromJson(json['utsname']),
+    );
+  }
+}
+
+/// Information derived from `utsname`.
+/// See http://pubs.opengroup.org/onlinepubs/7908799/xsh/sysutsname.h.html for details.
+class IosUtsname {
+  IosUtsname._({
+    this.sysname,
+    this.nodename,
+    this.release,
+    this.version,
+    this.machine,
+  });
+
+  /// Operating system name.
+  final String sysname;
+
+  /// Network node name.
+  final String nodename;
+
+  /// Release level.
+  final String release;
+
+  /// Version level.
+  final String version;
+
+  /// Hardware type (e.g. 'iPhone7,1' for iPhone 6 Plus).
+  final String machine;
+
+  /// Deserializes from the JSON message received from [_kChannel].
+  static IosUtsname _fromJson(Map<String, dynamic> json) {
+    return new IosUtsname._(
+      sysname: json['sysname'],
+      nodename: json['nodename'],
+      release: json['release'],
+      version: json['version'],
+      machine: json['machine'],
     );
   }
 }
diff --git a/packages/device_info/pubspec.yaml b/packages/device_info/pubspec.yaml
index 9fa8c40..e4c69f2 100644
--- a/packages/device_info/pubspec.yaml
+++ b/packages/device_info/pubspec.yaml
@@ -1,6 +1,6 @@
 name: device_info
 description: Provides detailed information about the device the Flutter app is running on.
-version: 0.0.2
+version: 0.0.3
 author: Flutter Team <flutter-dev@googlegroups.com>
 homepage: https://github.com/flutter/plugins/tree/master/packages/device_info