greybus: interface: Fetch and expose version of interface's firmware
authorViresh Kumar <viresh.kumar@linaro.org>
Mon, 28 Dec 2015 06:29:01 +0000 (11:59 +0530)
committerGreg Kroah-Hartman <gregkh@google.com>
Wed, 30 Dec 2015 21:13:04 +0000 (13:13 -0800)
The version of the currently running firmware on the module is useful
for userspace as it can be used to find if an update is available or
not. This patch fetches interface's version with a new control operation
and exposes the same in userspace.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: Johan Hovold <johan@hovoldconsulting.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
drivers/staging/greybus/Documentation/sysfs-bus-greybus
drivers/staging/greybus/control.c
drivers/staging/greybus/control.h
drivers/staging/greybus/greybus_protocols.h
drivers/staging/greybus/interface.c
drivers/staging/greybus/interface.h

index 0d16d7649a5a58fe7624b7eb0d4f5c6c6c66b349..9ce36ddfb4da219bf0d32147930af34ce1d841f8 100644 (file)
@@ -73,6 +73,14 @@ Contact:     Greg Kroah-Hartman <greg@kroah.com>
 Description:
                Vendor ID string of a Greybus interface block.
 
+What:          /sys/bus/greybus/device/N-I/version
+Date:          October 2015
+KernelVersion: 4.XX
+Contact:       Greg Kroah-Hartman <greg@kroah.com>
+Description:
+               Interface version represented as <16 bit major number>.<16 bit
+               minor number>.
+
 What:          /sys/bus/greybus/device/N-I.B
 Date:          October 2015
 KernelVersion: 4.XX
index 09ff79753313a72d330fdbb994a05473fd59c300..4d65dbff6e93018a235bc387edad5d6808c71c78 100644 (file)
@@ -59,6 +59,35 @@ int gb_control_disconnected_operation(struct gb_control *control, u16 cport_id)
                                 sizeof(request), NULL, 0);
 }
 
+int gb_control_get_interface_version_operation(struct gb_interface *intf)
+{
+       struct gb_control_interface_version_response response;
+       struct gb_connection *connection = intf->control->connection;
+       int ret;
+
+       /* The ES3 bootrom fails to boot if this request it sent to it */
+       if (intf->boot_over_unipro)
+               return 0;
+
+       ret = gb_operation_sync(connection, GB_CONTROL_TYPE_INTERFACE_VERSION,
+                               NULL, 0, &response, sizeof(response));
+       if (ret) {
+               dev_err(&connection->intf->dev,
+                       "failed to get interface version: %d\n", ret);
+               /*
+                * FIXME: Return success until the time we bump version of
+                * control protocol. The interface-version is already set to
+                * 0.0, so no need to update that.
+                */
+               return 0;
+       }
+
+       intf->version_major = le16_to_cpu(response.major);
+       intf->version_minor = le16_to_cpu(response.minor);
+
+       return 0;
+}
+
 struct gb_control *gb_control_create(struct gb_interface *intf)
 {
        struct gb_control *control;
index da0fa6652dcaec5466ee9093d948b20c07ce94bf..7cb3dd2290d738d8799bfa0fcc30c2e2db3fbee8 100644 (file)
@@ -24,6 +24,7 @@ int gb_control_disconnected_operation(struct gb_control *control, u16 cport_id);
 int gb_control_get_manifest_size_operation(struct gb_interface *intf);
 int gb_control_get_manifest_operation(struct gb_interface *intf, void *manifest,
                                      size_t size);
+int gb_control_get_interface_version_operation(struct gb_interface *intf);
 
 int gb_control_protocol_init(void);
 void gb_control_protocol_exit(void);
index f66f4d784f279d63e94907a01e3f76c7921c3116..a0bddaa36629bf6552ad8a585190a8a04bdaa1ff 100644 (file)
@@ -125,6 +125,7 @@ struct gb_protocol_version_response {
 #define GB_CONTROL_TYPE_GET_MANIFEST           0x04
 #define GB_CONTROL_TYPE_CONNECTED              0x05
 #define GB_CONTROL_TYPE_DISCONNECTED           0x06
+#define GB_CONTROL_TYPE_INTERFACE_VERSION      0x0a
 
 /* Control protocol manifest get size request has no payload*/
 struct gb_control_get_manifest_size_response {
@@ -146,6 +147,12 @@ struct gb_control_disconnected_request {
 } __packed;
 /* Control protocol [dis]connected response has no payload */
 
+/* Control protocol interface version request has no payload */
+struct gb_control_interface_version_response {
+       __le16                  major;
+       __le16                  minor;
+} __packed;
+
 
 /* Firmware Protocol */
 
index 69eb7886ceae12d8aa4f7fbf565dd282bad3b4c9..edac2383e492a2471fd34fdc19549d4603b53c51 100644 (file)
@@ -29,6 +29,16 @@ gb_interface_attr(vendor_string, "%s");
 gb_interface_attr(product_string, "%s");
 gb_interface_attr(serial_number, "0x%016llx");
 
+static ssize_t version_show(struct device *dev, struct device_attribute *attr,
+                           char *buf)
+{
+       struct gb_interface *intf = to_gb_interface(dev);
+
+       return scnprintf(buf, PAGE_SIZE, "%u.%u\n", intf->version_major,
+                        intf->version_minor);
+}
+static DEVICE_ATTR_RO(version);
+
 static struct attribute *interface_attrs[] = {
        &dev_attr_ddbl1_manufacturer_id.attr,
        &dev_attr_ddbl1_product_id.attr,
@@ -38,6 +48,7 @@ static struct attribute *interface_attrs[] = {
        &dev_attr_vendor_string.attr,
        &dev_attr_product_string.attr,
        &dev_attr_serial_number.attr,
+       &dev_attr_version.attr,
        NULL,
 };
 ATTRIBUTE_GROUPS(interface);
@@ -214,6 +225,10 @@ int gb_interface_init(struct gb_interface *intf, u8 device_id)
                goto free_manifest;
        }
 
+       ret = gb_control_get_interface_version_operation(intf);
+       if (ret)
+               goto free_manifest;
+
        /* Register the interface and its bundles. */
        ret = device_add(&intf->dev);
        if (ret) {
index a1a1f9f5c2cb915024ffce0eef8dab49797d1f2c..4168a5752808996117f9859b18926facf4f37326 100644 (file)
@@ -32,6 +32,9 @@ struct gb_interface {
        u32 product_id;
        u64 serial_number;
 
+       u16 version_major;
+       u16 version_minor;
+
        struct gb_host_device *hd;
 
        /* The interface needs to boot over unipro */