greybus: control: add bundle-version operation
authorJohan Hovold <johan@hovoldconsulting.com>
Tue, 19 Jan 2016 11:51:21 +0000 (12:51 +0100)
committerGreg Kroah-Hartman <gregkh@google.com>
Tue, 19 Jan 2016 20:17:13 +0000 (12:17 -0800)
Add bundle-version operation to fetch the version of the bundle class.

Retrieve the bundle version of all bundles when initialising the
interface in case the control-protocol version is greater than 0.1.

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

index 682ec327f8a36a402985d0b5547754029caabc5e..837682d91e5b16cd0c57f1e1a3f5af8add821b11 100644 (file)
 struct gb_bundle {
        struct device           dev;
        struct gb_interface     *intf;
+
        u8                      id;
        u8                      class;
+       u8                      class_major;
+       u8                      class_minor;
+
        struct list_head        connections;
        u8                      *state;
 
index 30779402b368af2ec3ac8693aaa0e683d9d73c28..0e50fd419f3a6e4f2d8d0c7f6848693b52b1a367 100644 (file)
@@ -54,6 +54,54 @@ int gb_control_get_version(struct gb_control *control)
        return 0;
 }
 
+static int gb_control_get_bundle_version(struct gb_control *control,
+                                               struct gb_bundle *bundle)
+{
+       struct gb_interface *intf = control->connection->intf;
+       struct gb_control_bundle_version_request request;
+       struct gb_control_bundle_version_response response;
+       int ret;
+
+       request.bundle_id = bundle->id;
+
+       ret = gb_operation_sync(control->connection,
+                               GB_CONTROL_TYPE_BUNDLE_VERSION,
+                               &request, sizeof(request),
+                               &response, sizeof(response));
+       if (ret) {
+               dev_err(&intf->dev,
+                               "failed to get bundle %u class version: %d\n",
+                               bundle->id, ret);
+               return ret;
+       }
+
+       bundle->class_major = response.major;
+       bundle->class_minor = response.minor;
+
+       dev_dbg(&intf->dev, "%s - %u: %u.%u\n", __func__, bundle->id,
+                       response.major, response.minor);
+
+       return 0;
+}
+
+int gb_control_get_bundle_versions(struct gb_control *control)
+{
+       struct gb_interface *intf = control->connection->intf;
+       struct gb_bundle *bundle;
+       int ret;
+
+       if (!control->has_bundle_version)
+               return 0;
+
+       list_for_each_entry(bundle, &intf->bundles, links) {
+               ret = gb_control_get_bundle_version(control, bundle);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
 /* Get Manifest's size from the interface */
 int gb_control_get_manifest_size_operation(struct gb_interface *intf)
 {
@@ -170,6 +218,9 @@ int gb_control_enable(struct gb_control *control)
        if (ret)
                goto err_disable_connection;
 
+       if (control->protocol_major > 0 || control->protocol_minor > 1)
+               control->has_bundle_version = true;
+
        return 0;
 
 err_disable_connection:
index dd0a2d79da20722e37eac74a0521ae5d52128d54..d31e7c6d866a653b501f18f353084c10baa5d5fb 100644 (file)
@@ -15,6 +15,8 @@ struct gb_control {
 
        u8 protocol_major;
        u8 protocol_minor;
+
+       bool has_bundle_version;
 };
 
 struct gb_control *gb_control_create(struct gb_interface *intf);
@@ -22,6 +24,7 @@ int gb_control_enable(struct gb_control *control);
 void gb_control_disable(struct gb_control *control);
 void gb_control_destroy(struct gb_control *control);
 
+int gb_control_get_bundle_versions(struct gb_control *control);
 int gb_control_connected_operation(struct gb_control *control, u16 cport_id);
 int gb_control_disconnected_operation(struct gb_control *control, u16 cport_id);
 int gb_control_get_manifest_size_operation(struct gb_interface *intf);
index abbb214863c9410d97b0f17397feec6dc005e832..84fb6ab6deca50d54e756e79d4d5c1ed3d1fa363 100644 (file)
@@ -123,6 +123,7 @@ struct gb_protocol_version_response {
 #define GB_CONTROL_TYPE_CONNECTED              0x05
 #define GB_CONTROL_TYPE_DISCONNECTED           0x06
 #define GB_CONTROL_TYPE_INTERFACE_VERSION      0x0a
+#define GB_CONTROL_TYPE_BUNDLE_VERSION         0x0b
 
 struct gb_control_version_request {
        __u8    major;
@@ -134,6 +135,15 @@ struct gb_control_version_response {
        __u8    minor;
 } __packed;
 
+struct gb_control_bundle_version_request {
+       __u8    bundle_id;
+} __packed;
+
+struct gb_control_bundle_version_response {
+       __u8    major;
+       __u8    minor;
+} __packed;
+
 /* Control protocol manifest get size request has no payload*/
 struct gb_control_get_manifest_size_response {
        __le16                  size;
index c3453502ae226a7a9be0ceecdfc09a4e31032622..9c05d8142d8b35e62fde31c8f46ea7ccad8c3d6c 100644 (file)
@@ -228,6 +228,10 @@ int gb_interface_init(struct gb_interface *intf, u8 device_id)
        if (ret)
                goto free_manifest;
 
+       ret = gb_control_get_bundle_versions(intf->control);
+       if (ret)
+               goto free_manifest;
+
        /* Register the interface and its bundles. */
        ret = device_add(&intf->dev);
        if (ret) {