[libcamera-devel] [PATCH 6/9] utils: ipc: Add support for Flags

Paul Elder paul.elder at ideasonboard.com
Wed Aug 3 13:21:47 CEST 2022


Add Flags<E> as a supported type in the IPA interface.

It is defined and used in mojom as "Flags_E_t", and the code generator
will convert it to "Flags<E>". It is usable and has been tested in
struct members, function input and output parameters, and Signal
parameters.

This does not add support for returning Flags as direct return values.

Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>
---
 .../core_ipa_interface.h.tmpl                 |  4 +++
 .../definition_functions.tmpl                 | 13 +++++++
 .../module_ipa_interface.h.tmpl               |  4 +++
 .../libcamera_templates/proxy_functions.tmpl  | 10 ++++--
 .../libcamera_templates/serializer.tmpl       |  4 +++
 .../generators/mojom_libcamera_generator.py   | 35 ++++++++++++++++++-
 6 files changed, 66 insertions(+), 4 deletions(-)

diff --git a/utils/ipc/generators/libcamera_templates/core_ipa_interface.h.tmpl b/utils/ipc/generators/libcamera_templates/core_ipa_interface.h.tmpl
index a565b59a..2fd55119 100644
--- a/utils/ipc/generators/libcamera_templates/core_ipa_interface.h.tmpl
+++ b/utils/ipc/generators/libcamera_templates/core_ipa_interface.h.tmpl
@@ -30,6 +30,10 @@ static const {{const.kind|name}} {{const.mojom_name}} = {{const.value}};
 {{funcs.define_enum(enum)}}
 {% endfor %}
 
+{% for flag in flags %}
+{{funcs.define_flags(flag)}}
+{% endfor %}
+
 {%- for struct in structs_gen_header %}
 {{funcs.define_struct(struct)}}
 {% endfor %}
diff --git a/utils/ipc/generators/libcamera_templates/definition_functions.tmpl b/utils/ipc/generators/libcamera_templates/definition_functions.tmpl
index 94bb4918..3dbcfca0 100644
--- a/utils/ipc/generators/libcamera_templates/definition_functions.tmpl
+++ b/utils/ipc/generators/libcamera_templates/definition_functions.tmpl
@@ -16,6 +16,19 @@ enum {{enum.mojom_name}} {
 };
 {%- endmacro -%}
 
+{#
+ # \brief Generate Flags definition
+ #
+ # \param flags Enum object from which a Flags definition is to be generated
+ #}
+{%- macro define_flags(flags) -%}
+enum class {{flags|flags_name}} {
+{%- for field in flags.fields %}
+	{{field.mojom_name}} = {{field.numeric_value}},
+{%- endfor %}
+};
+{%- endmacro -%}
+
 {#
  # \brief Generate struct definition
  #
diff --git a/utils/ipc/generators/libcamera_templates/module_ipa_interface.h.tmpl b/utils/ipc/generators/libcamera_templates/module_ipa_interface.h.tmpl
index 415ec283..5e003849 100644
--- a/utils/ipc/generators/libcamera_templates/module_ipa_interface.h.tmpl
+++ b/utils/ipc/generators/libcamera_templates/module_ipa_interface.h.tmpl
@@ -48,6 +48,10 @@ enum class {{cmd_event_enum_name}} {
 {{funcs.define_enum(enum)}}
 {% endfor %}
 
+{% for flag in flags %}
+{{funcs.define_flags(flag)}}
+{% endfor %}
+
 {%- for struct in structs_nonempty %}
 {{funcs.define_struct(struct)}}
 {% endfor %}
diff --git a/utils/ipc/generators/libcamera_templates/proxy_functions.tmpl b/utils/ipc/generators/libcamera_templates/proxy_functions.tmpl
index dc35620f..c5e24323 100644
--- a/utils/ipc/generators/libcamera_templates/proxy_functions.tmpl
+++ b/utils/ipc/generators/libcamera_templates/proxy_functions.tmpl
@@ -59,7 +59,9 @@
 {%- else %}
 	std::tie({{param.mojom_name}}Buf, std::ignore) =
 {%- endif %}
-{%- if param|is_enum %}
+{%- if param|is_flags %}
+		IPADataSerializer<{{param|name_full}}>::serialize({{param.mojom_name}}
+{%- elif param|is_enum %}
 		IPADataSerializer<uint32_t>::serialize(static_cast<uint32_t>({{param.mojom_name}})
 {%- else %}
 		IPADataSerializer<{{param|name}}>::serialize({{param.mojom_name}}
@@ -102,7 +104,9 @@
  #}
 {%- macro deserialize_param(param, pointer, loop, buf, fds, iter, data_size) -%}
 {{"*" if pointer}}{{param.mojom_name}} =
-{%- if param|is_enum %}
+{%- if param|is_flags %}
+IPADataSerializer<{{param|name_full}}>::deserialize(
+{%- elif param|is_enum %}
 static_cast<{{param|name_full}}>(IPADataSerializer<uint32_t>::deserialize(
 {%- else %}
 IPADataSerializer<{{param|name}}>::deserialize(
@@ -130,7 +134,7 @@ IPADataSerializer<{{param|name}}>::deserialize(
 {%- if param|needs_control_serializer %}
 	&controlSerializer_
 {%- endif -%}
-){{")" if param|is_enum}};
+){{")" if param|is_enum and not param|is_flags}};
 {%- endmacro -%}
 
 
diff --git a/utils/ipc/generators/libcamera_templates/serializer.tmpl b/utils/ipc/generators/libcamera_templates/serializer.tmpl
index 77bae36f..eec75211 100644
--- a/utils/ipc/generators/libcamera_templates/serializer.tmpl
+++ b/utils/ipc/generators/libcamera_templates/serializer.tmpl
@@ -34,6 +34,8 @@
 		std::tie({{field.mojom_name}}, std::ignore) =
 	{%- if field|is_pod %}
 			IPADataSerializer<{{field|name}}>::serialize(data.{{field.mojom_name}});
+	{%- elif field|is_flags %}
+			IPADataSerializer<{{field|name_full}}>::serialize(data.{{field.mojom_name}});
 	{%- elif field|is_enum %}
 			IPADataSerializer<uint{{field|bit_width}}_t>::serialize(data.{{field.mojom_name}});
 	{%- endif %}
@@ -96,6 +98,8 @@
 		{{- check_data_size(field_size, 'dataSize', field.mojom_name, 'data')}}
 		{%- if field|is_pod %}
 		ret.{{field.mojom_name}} = IPADataSerializer<{{field|name}}>::deserialize(m, m + {{field_size}});
+		{%- elif field|is_flags %}
+		ret.{{field.mojom_name}} = IPADataSerializer<{{field|name_full}}>::deserialize(m, m + {{field_size}});
 		{%- else %}
 		ret.{{field.mojom_name}} = static_cast<{{field|name_full}}>(IPADataSerializer<uint{{field|bit_width}}_t>::deserialize(m, m + {{field_size}}));
 		{%- endif %}
diff --git a/utils/ipc/generators/mojom_libcamera_generator.py b/utils/ipc/generators/mojom_libcamera_generator.py
index 753bfc73..22de6fdd 100644
--- a/utils/ipc/generators/mojom_libcamera_generator.py
+++ b/utils/ipc/generators/mojom_libcamera_generator.py
@@ -47,6 +47,8 @@ _bit_widths = {
     mojom.DOUBLE: '64',
 }
 
+_flags_re = r'^Flags_(.*)_t$'
+
 def ModuleName(path):
     return path.split('/')[-1].split('.')[0]
 
@@ -74,6 +76,8 @@ def GetDefaultValue(element):
         return element.default
     if type(element.kind) == mojom.Kind:
         return '0'
+    if IsFlags(element):
+        return ''
     if mojom.IsEnumKind(element.kind):
         return f'static_cast<{element.kind.mojom_name}>(0)'
     if isinstance(element.kind, mojom.Struct) and \
@@ -223,6 +227,16 @@ def IsEnum(element):
 def IsFd(element):
     return mojom.IsStructKind(element.kind) and element.kind.mojom_name == "SharedFD"
 
+def IsFlags(element):
+    if not hasattr(element, 'mojom_name'):
+        return False
+    if re.match(_flags_re, element.mojom_name):
+        return True
+    if hasattr(element, 'kind'):
+        if hasattr(element.kind, 'mojom_name'):
+            return True if re.match(_flags_re, element.kind.mojom_name) else False
+    return False
+
 def IsMap(element):
     return mojom.IsMapKind(element.kind)
 
@@ -251,9 +265,20 @@ def ByteWidthFromCppType(t):
         raise Exception('invalid type')
     return str(int(_bit_widths[key]) // 8)
 
+def FlagsName(element):
+    if hasattr(element, 'mojom_name'):
+        if re.match(_flags_re, element.mojom_name):
+            return re.sub(_flags_re, lambda match: match.group(1), element.mojom_name)
+    if hasattr(element, 'kind'):
+        if hasattr(element.kind, 'mojom_name'):
+            return re.sub(_flags_re, lambda match: match.group(1), element.kind.mojom_name)
+    return None
 
 # Get the type name for a given element
 def GetNameForElement(element):
+    # Flags
+    if IsFlags(element):
+        return f'Flags<{FlagsName(element)}>'
     # structs
     if (mojom.IsEnumKind(element) or
         mojom.IsInterfaceKind(element) or
@@ -311,6 +336,11 @@ def GetFullNameForElement(element):
 
     if namespace_str == '':
         return name
+
+    if IsFlags(element):
+        name = re.match(r'^Flags<(.*)>$', name).group(1)
+        return f'Flags<{namespace_str}::{name}>'
+
     return f'{namespace_str}::{name}'
 
 def ValidateZeroLength(l, s, cap=True):
@@ -401,6 +431,7 @@ class Generator(generator.Generator):
             'choose': Choose,
             'comma_sep': CommaSep,
             'default_value': GetDefaultValue,
+            'flags_name': FlagsName,
             'has_default_fields': HasDefaultFields,
             'has_fd': HasFd,
             'is_async': IsAsync,
@@ -408,6 +439,7 @@ class Generator(generator.Generator):
             'is_controls': IsControls,
             'is_enum': IsEnum,
             'is_fd': IsFd,
+            'is_flags': IsFlags,
             'is_map': IsMap,
             'is_plain_struct': IsPlainStruct,
             'is_pod': IsPod,
@@ -433,7 +465,8 @@ class Generator(generator.Generator):
             'cmd_enum_name': '_%sCmd' % self.module_name,
             'cmd_event_enum_name': '_%sEventCmd' % self.module_name,
             'consts': self.module.constants,
-            'enums': self.module.enums,
+            'enums': [enum for enum in self.module.enums if not IsFlags(enum)],
+            'flags': [enum for enum in self.module.enums if IsFlags(enum)],
             'has_array': len([x for x in self.module.kinds.keys() if x[0] == 'a']) > 0,
             'has_map': len([x for x in self.module.kinds.keys() if x[0] == 'm']) > 0,
             'has_namespace': self.module.mojom_namespace != '',
-- 
2.30.2



More information about the libcamera-devel mailing list