1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef V4L2_CAMERA_HAL_METADATA_CONTROL_FACTORY_H_
18#define V4L2_CAMERA_HAL_METADATA_CONTROL_FACTORY_H_
19
20#include "../common.h"
21#include "control.h"
22#include "menu_control_options.h"
23#include "no_effect_control_delegate.h"
24#include "ranged_converter.h"
25#include "slider_control_options.h"
26#include "state.h"
27#include "tagged_control_delegate.h"
28#include "tagged_control_options.h"
29#include "v4l2_control_delegate.h"
30
31namespace v4l2_camera_hal {
32
33enum class ControlType { kMenu, kSlider };
34
35// Static functions to create partial metadata. Nullptr is returned on failures.
36
37// FixedState: A state that doesn't change.
38template <typename T>
39static std::unique_ptr<State<T>> FixedState(int32_t tag, T value);
40
41// NoEffectOptionlessControl: A control that accepts any value,
42// and has no effect. A default value is given.
43template <typename T>
44static std::unique_ptr<Control<T>> NoEffectOptionlessControl(
45    int32_t delegate_tag, T default_value);
46
47// NoEffectMenuControl: Some menu options, but they have no effect.
48template <typename T>
49static std::unique_ptr<Control<T>> NoEffectMenuControl(
50    int32_t delegate_tag,
51    int32_t options_tag,
52    const std::vector<T>& options,
53    std::map<int, T> default_values = {});
54
55// NoEffectSliderControl: A slider of options, but they have no effect.
56template <typename T>
57static std::unique_ptr<Control<T>> NoEffectSliderControl(
58    int32_t delegate_tag,
59    int32_t options_tag,
60    T min,
61    T max,
62    std::map<int, T> default_values = {});
63
64// NoEffectControl: A control with no effect and only a single allowable
65// value. Chooses an appropriate ControlOptionsInterface depending on type.
66template <typename T>
67static std::unique_ptr<Control<T>> NoEffectControl(
68    ControlType type,
69    int32_t delegate_tag,
70    int32_t options_tag,
71    T value,
72    std::map<int, T> default_values = {});
73
74// V4L2Control: A control corresponding to a V4L2 control.
75template <typename T>
76static std::unique_ptr<Control<T>> V4L2Control(
77    ControlType type,
78    int32_t delegate_tag,
79    int32_t options_tag,
80    std::shared_ptr<V4L2Wrapper> device,
81    int control_id,
82    std::shared_ptr<ConverterInterface<T, int32_t>> converter,
83    std::map<int, T> default_values = {});
84
85// V4L2ControlOrDefault: Like V4L2Control, but if the V4L2Control fails to
86// initialize for some reason, this method will fall back to NoEffectControl
87// with an initial value defined by |fallback_default|.
88template <typename T>
89static std::unique_ptr<Control<T>> V4L2ControlOrDefault(
90    ControlType type,
91    int32_t delegate_tag,
92    int32_t options_tag,
93    std::shared_ptr<V4L2Wrapper> device,
94    int control_id,
95    std::shared_ptr<ConverterInterface<T, int32_t>> converter,
96    T fallback_default,
97    std::map<int, T> default_values = {});
98
99// -----------------------------------------------------------------------------
100
101template <typename T>
102std::unique_ptr<State<T>> FixedState(int32_t tag, T value) {
103  HAL_LOG_ENTER();
104
105  // Take advantage of ControlDelegate inheriting from StateDelegate;
106  // This will only expose GetValue, not SetValue, so the default will
107  // always be returned.
108  return std::make_unique<State<T>>(
109      tag, std::make_unique<NoEffectControlDelegate<T>>(value));
110}
111
112template <typename T>
113std::unique_ptr<Control<T>> NoEffectOptionlessControl(int32_t delegate_tag,
114                                                      T default_value) {
115  HAL_LOG_ENTER();
116
117  return std::make_unique<Control<T>>(
118      std::make_unique<TaggedControlDelegate<T>>(
119          delegate_tag,
120          std::make_unique<NoEffectControlDelegate<T>>(default_value)),
121      nullptr);
122}
123
124template <typename T>
125std::unique_ptr<Control<T>> NoEffectMenuControl(
126    int32_t delegate_tag,
127    int32_t options_tag,
128    const std::vector<T>& options,
129    std::map<int, T> default_values) {
130  HAL_LOG_ENTER();
131
132  if (options.empty()) {
133    HAL_LOGE("At least one option must be provided.");
134    return nullptr;
135  }
136
137  return std::make_unique<Control<T>>(
138      std::make_unique<TaggedControlDelegate<T>>(
139          delegate_tag,
140          std::make_unique<NoEffectControlDelegate<T>>(options[0])),
141      std::make_unique<TaggedControlOptions<T>>(
142          options_tag,
143          std::make_unique<MenuControlOptions<T>>(options, default_values)));
144}
145
146template <typename T>
147std::unique_ptr<Control<T>> NoEffectSliderControl(
148    int32_t delegate_tag,
149    int32_t options_tag,
150    T min,
151    T max,
152    std::map<int, T> default_values) {
153  HAL_LOG_ENTER();
154
155  return std::make_unique<Control<T>>(
156      std::make_unique<TaggedControlDelegate<T>>(
157          delegate_tag, std::make_unique<NoEffectControlDelegate<T>>(min)),
158      std::make_unique<TaggedControlOptions<T>>(
159          options_tag,
160          std::make_unique<SliderControlOptions<T>>(min, max, default_values)));
161}
162
163template <typename T>
164std::unique_ptr<Control<T>> NoEffectControl(ControlType type,
165                                            int32_t delegate_tag,
166                                            int32_t options_tag,
167                                            T value,
168                                            std::map<int, T> default_values) {
169  HAL_LOG_ENTER();
170
171  switch (type) {
172    case ControlType::kMenu:
173      return NoEffectMenuControl<T>(
174          delegate_tag, options_tag, {value}, default_values);
175    case ControlType::kSlider:
176      return NoEffectSliderControl(
177          delegate_tag, options_tag, value, value, default_values);
178  }
179}
180
181template <typename T>
182std::unique_ptr<Control<T>> V4L2Control(
183    ControlType type,
184    int32_t delegate_tag,
185    int32_t options_tag,
186    std::shared_ptr<V4L2Wrapper> device,
187    int control_id,
188    std::shared_ptr<ConverterInterface<T, int32_t>> converter,
189    std::map<int, T> default_values) {
190  HAL_LOG_ENTER();
191
192  // Query the device.
193  v4l2_query_ext_ctrl control_query;
194  int res = device->QueryControl(control_id, &control_query);
195  if (res) {
196    HAL_LOGE("Failed to query control %d.", control_id);
197    return nullptr;
198  }
199
200  int32_t control_min = static_cast<int32_t>(control_query.minimum);
201  int32_t control_max = static_cast<int32_t>(control_query.maximum);
202  int32_t control_step = static_cast<int32_t>(control_query.step);
203  if (control_min > control_max) {
204    HAL_LOGE("No acceptable values (min %d is greater than max %d).",
205             control_min,
206             control_max);
207    return nullptr;
208  }
209
210  // Variables needed by the various switch statements.
211  std::vector<T> options;
212  T metadata_val;
213  T metadata_min;
214  T metadata_max;
215  // Set up the result converter and result options based on type.
216  std::shared_ptr<ConverterInterface<T, int32_t>> result_converter(converter);
217  std::unique_ptr<ControlOptionsInterface<T>> result_options;
218  switch (control_query.type) {
219    case V4L2_CTRL_TYPE_BOOLEAN:
220      if (type != ControlType::kMenu) {
221        HAL_LOGE(
222            "V4L2 control %d is of type %d, which isn't compatible with "
223            "desired metadata control type %d",
224            control_id,
225            control_query.type,
226            type);
227        return nullptr;
228      }
229
230      // Convert each available option,
231      // ignoring ones without a known conversion.
232      for (int32_t i = control_min; i <= control_max; i += control_step) {
233        res = converter->V4L2ToMetadata(i, &metadata_val);
234        if (res == -EINVAL) {
235          HAL_LOGV("V4L2 value %d for control %d has no metadata equivalent.",
236                   i,
237                   control_id);
238          continue;
239        } else if (res) {
240          HAL_LOGE("Error converting value %d for control %d.", i, control_id);
241          return nullptr;
242        }
243        options.push_back(metadata_val);
244      }
245      // Check to make sure there's at least one option.
246      if (options.empty()) {
247        HAL_LOGE("No valid options for control %d.", control_id);
248        return nullptr;
249      }
250
251      result_options.reset(new MenuControlOptions<T>(options, default_values));
252      // No converter changes necessary.
253      break;
254    case V4L2_CTRL_TYPE_INTEGER:
255      if (type != ControlType::kSlider) {
256        HAL_LOGE(
257            "V4L2 control %d is of type %d, which isn't compatible with "
258            "desired metadata control type %d",
259            control_id,
260            control_query.type,
261            type);
262        return nullptr;
263      }
264
265      // Upgrade to a range/step-clamping converter.
266      result_converter.reset(new RangedConverter<T, int32_t>(
267          converter, control_min, control_max, control_step));
268
269      // Convert the min and max.
270      res = result_converter->V4L2ToMetadata(control_min, &metadata_min);
271      if (res) {
272        HAL_LOGE(
273            "Failed to convert V4L2 min value %d for control %d to metadata.",
274            control_min,
275            control_id);
276        return nullptr;
277      }
278      res = result_converter->V4L2ToMetadata(control_max, &metadata_max);
279      if (res) {
280        HAL_LOGE(
281            "Failed to convert V4L2 max value %d for control %d to metadata.",
282            control_max,
283            control_id);
284        return nullptr;
285      }
286      result_options.reset(new SliderControlOptions<T>(
287          metadata_min, metadata_max, default_values));
288      break;
289    default:
290      HAL_LOGE("Control %d (%s) is of unsupported type %d",
291               control_id,
292               control_query.name,
293               control_query.type);
294      return nullptr;
295  }
296
297  // Construct the control.
298  return std::make_unique<Control<T>>(
299      std::make_unique<TaggedControlDelegate<T>>(
300          delegate_tag,
301          std::make_unique<V4L2ControlDelegate<T>>(
302              device, control_id, result_converter)),
303      std::make_unique<TaggedControlOptions<T>>(options_tag,
304                                                std::move(result_options)));
305}
306
307template <typename T>
308std::unique_ptr<Control<T>> V4L2ControlOrDefault(
309    ControlType type,
310    int32_t delegate_tag,
311    int32_t options_tag,
312    std::shared_ptr<V4L2Wrapper> device,
313    int control_id,
314    std::shared_ptr<ConverterInterface<T, int32_t>> converter,
315    T fallback_default,
316    std::map<int, T> default_values) {
317  HAL_LOG_ENTER();
318
319  std::unique_ptr<Control<T>> result = V4L2Control(type,
320                                                   delegate_tag,
321                                                   options_tag,
322                                                   device,
323                                                   control_id,
324                                                   converter,
325                                                   default_values);
326  if (!result) {
327    result = NoEffectControl(
328        type, delegate_tag, options_tag, fallback_default, default_values);
329  }
330  return result;
331}
332
333}  // namespace v4l2_camera_hal
334
335#endif  // V4L2_CAMERA_HAL_METADATA_CONTROL_FACTORY_H_
336