From b807aa7aa51129b1754e7d17f6a2e30e3c6f7a4b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 19 Jan 2016 12:51:21 +0100 Subject: [PATCH] greybus: control: add bundle-version operation 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 Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/bundle.h | 4 +++ drivers/staging/greybus/control.c | 51 +++++++++++++++++++++++++++++ drivers/staging/greybus/control.h | 3 ++ drivers/staging/greybus/greybus_protocols.h | 10 ++++++ drivers/staging/greybus/interface.c | 4 +++ 5 files changed, 72 insertions(+) diff --git a/drivers/staging/greybus/bundle.h b/drivers/staging/greybus/bundle.h index 682ec32..837682d 100644 --- a/drivers/staging/greybus/bundle.h +++ b/drivers/staging/greybus/bundle.h @@ -16,8 +16,12 @@ 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; diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index 3077940..0e50fd4 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -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: diff --git a/drivers/staging/greybus/control.h b/drivers/staging/greybus/control.h index dd0a2d7..d31e7c6 100644 --- a/drivers/staging/greybus/control.h +++ b/drivers/staging/greybus/control.h @@ -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); diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index abbb214..84fb6ab 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -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; diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index c345350..9c05d81 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -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) { -- 2.7.4