1/* ----------------------------------------------------------------------------
2 * Copyright (c) Huawei Technologies Co., Ltd. 2017-2019. All rights reserved.
3 * Description: LiteOS USB Driver Hicamera Control
4 * Author: huangjieliang
5 * Create: 2017-11-25
6 * Redistribution and use in source and binary forms, with or without modification,
7 * are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
14 * to endorse or promote products derived from this software without specific prior written
15 * permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 * --------------------------------------------------------------------------- */
28/* ----------------------------------------------------------------------------
29 * Notice of Export Control Law
30 * ===============================================
31 * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
32 * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
33 * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
34 * applicable export control laws and regulations.
35 * --------------------------------------------------------------------------- */
36
37#include "implementation/global_implementation.h"
38#include "hicamera_control.h"
39#include "gadget/f_uvc.h"
40
41#ifdef __cplusplus
42#if __cplusplus
43extern "C" {
44#endif /* __cplusplus */
45#endif /* __cplusplus */
46
47#define UVC_UNIT_MAP_SIZE 4
48static struct uvc_camera_cmd g_cmd_map[CMD_MAX_NUM] = {0};
49static bool g_uvc_unit_is_register = false;
50static struct uvc_camera_cmd g_uvc_unit_mappings[UVC_UNIT_MAP_SIZE];
51DEFINE_SPINLOCK(g_cmd_spinlock);
52
53static int cmd_check(struct uvc_camera_cmd *cmd)
54{
55  if (cmd->id >= CMD_MAX_NUM)
56    {
57      usb_err("the cmd id is too big, make sure it less than %d\n", CMD_MAX_NUM);
58      return -1;
59    }
60
61  return 0;
62}
63
64void uvc_unit_control_register(void)
65{
66  int ret;
67  uint32_t i;
68
69  if (g_uvc_unit_is_register == false)
70    {
71      hi_camera_cmd_init();
72
73      for (i = 0; i < sizeof(g_uvc_unit_mappings) / sizeof(g_uvc_unit_mappings[0]); i++)
74        {
75          ret = hi_camera_register_cmd(&g_uvc_unit_mappings[i]);
76          if (ret < 0)
77            {
78              usb_err("register cmd failed\n");
79            }
80        }
81    }
82}
83
84int run_cmd_func(void *buf, uint32_t len, uint32_t event_id, uint32_t cmdtype, uint32_t cmd_id)
85{
86  struct uvc_camera_cmd *cmd_cb;
87  uint32_t flags;
88  int ret;
89
90  if (cmd_id >= CMD_MAX_NUM)
91    {
92      return -1;
93    }
94
95  spin_lock_irqsave(&g_cmd_spinlock, flags);
96  cmd_cb = &g_cmd_map[cmd_id];
97
98  ret = cmd_check(cmd_cb);
99  if (ret < 0)
100    {
101      spin_unlock_irqrestore(&g_cmd_spinlock, flags);
102      usb_err("cmd check is invalid\n");
103      return -1;
104    }
105
106  if (cmd_cb->uvc_control_func != NULL)
107    {
108      ret = (int)cmd_cb->uvc_control_func(buf, len, event_id, cmdtype);
109    }
110  spin_unlock_irqrestore(&g_cmd_spinlock, flags);
111
112  return ret;
113}
114
115void hi_camera_cmd_init(void)
116{
117  uint32_t flags;
118
119  spin_lock_irqsave(&g_cmd_spinlock, flags);
120  (void)memset_s(g_cmd_map, (CMD_MAX_NUM * sizeof(struct uvc_camera_cmd)),
121                 0, (CMD_MAX_NUM * sizeof(struct uvc_camera_cmd)));
122  g_uvc_unit_is_register = false;
123  spin_unlock_irqrestore(&g_cmd_spinlock, flags);
124}
125
126static void new_cmd_add(struct uvc_camera_cmd *cmd)
127{
128  uint32_t cmd_id = cmd->id;
129  struct uvc_camera_cmd *cmd_cb = &g_cmd_map[cmd_id];
130
131  cmd_cb->id = cmd_id;
132  (void)memcpy_s(cmd_cb->name, sizeof(cmd_cb->name), cmd->name, sizeof(cmd->name));
133  cmd_cb->uvc_control_func = cmd->uvc_control_func;
134}
135
136int hi_camera_register_cmd(struct uvc_camera_cmd *cmd)
137{
138  uint32_t flags;
139  int ret;
140
141  if (cmd == NULL)
142    {
143      usb_err("the arg is NULL\n");
144      return -1;
145    }
146
147  ret = cmd_check(cmd);
148  if (ret == -1)
149    {
150      usb_err("cmd check is invalid\n");
151      return -1;
152    }
153
154  spin_lock_irqsave(&g_cmd_spinlock, flags);
155  new_cmd_add(cmd);
156  g_uvc_unit_is_register = true;
157  spin_unlock_irqrestore(&g_cmd_spinlock, flags);
158
159  return 0;
160}
161
162void hi_camera_cmd_info_print(void)
163{
164  int i;
165
166  for (i = 0; i < CMD_MAX_NUM; i++)
167    {
168      dprintf("cmd_id=%u, name:%s, func:%x\n", g_cmd_map[i].id, g_cmd_map[i].name, g_cmd_map[i].uvc_control_func);
169    }
170}
171
172static uint32_t camera_unit_control_sample(void *buf, uint32_t len, uint32_t cmdtype)
173{
174  uint8_t *data = (uint8_t *)buf;
175  uint32_t ret  = 0;
176
177  (void)len;
178
179  switch (cmdtype)
180    {
181    case UVC_RC_SETCUR:
182    case UVC_RC_GETCUR:
183    case UVC_RC_GETMIN:
184      ret = 4;
185      break;
186
187    case UVC_RC_GETLEN:
188      data[0] = 0x40;
189      data[1] = 0x00;
190      ret     = 2;
191      break;
192
193    case UVC_RC_GETINFO:
194      data[0] = 0x03;
195      ret     = 1;
196      break;
197
198    default:
199      break;
200    }
201
202  return ret;
203}
204
205static uint32_t hicamera_unit_control(void *buf, uint32_t len, uint32_t event_id, uint32_t cmdtype)
206{
207  uint32_t ret;
208
209  PRINT_INFO("%s %d, event_id=%u, len=%u, cmdtype=%02x\n", __FUNCTION__, __LINE__, event_id, len, cmdtype);
210
211  switch(event_id)
212    {
213    case HICAMERA_GET_VERSION_CONTROL:
214    case HICAMERA_START_UPDATE_CONTROL:
215    case HICAMERA_TRUN_ON_CONTROL:
216    case HICAMERA_RESET_CONTROL:
217    case HICAMERA_TRUN_OFF_CONTROL:
218    case HICAMERA_VIBRATOR_UP_CONTROL:
219    case HICAMERA_VIBRATOR_DOWN_CONTROL:
220    case HICAMERA_VIBRATOR_LEFT_CONTROL:
221    case HICAMERA_VIBRATOR_RIGHT_CONTROL:
222    default:
223      ret = camera_unit_control_sample(buf, len, cmdtype);
224      break;
225    }
226
227  return ret;
228}
229
230static uint32_t h264_unit_control(void *buf, uint32_t len, uint32_t event_id, uint32_t cmdtype)
231{
232  uint32_t ret  = 0;
233  uint8_t *data = (uint8_t *)buf;
234
235  PRINT_INFO("%s %d, event_id=%u, len=%u, cmdtype=%02x\n", __FUNCTION__, __LINE__, event_id, len, cmdtype);
236
237  switch (cmdtype)
238    {
239    case UVC_RC_SETCUR:
240      ret = 4;
241      break;
242
243    case UVC_RC_GETLEN:
244      data[0] = 0x40;
245      data[1] = 0x00;
246      ret     = 0x2;
247      break;
248
249    case UVC_RC_GETINFO:
250      data[0] = 0x3;
251      ret     = 0x1;
252      break;
253
254    case UVC_RC_GETMIN:
255    case UVC_RC_GETMAX:
256    case UVC_RC_GETRES:
257    case UVC_RC_GETDEF:
258      ret = 4;
259      break;
260
261    default:
262      usb_err("Yet to be supported cmdtype: %#x\n", cmdtype);
263      break;
264    }
265
266  return ret;
267}
268
269static void histream_pu_set_brightness(uint16_t val)
270{
271  PRINT_INFO("set brightness val = %u\n", val);
272}
273
274static uint16_t histream_pu_get_brightness(void)
275{
276  const uint16_t cur_val = 30;
277
278  PRINT_INFO("get brightness val = %u\n", cur_val);
279
280  return cur_val;
281}
282
283static uint32_t sample_uvc_pu_brightness_ctrl(void *buf, uint32_t len, uint32_t cmdtype)
284{
285  uint32_t ret  = 0;
286  uint8_t *data = (uint8_t *)buf;
287  uint16_t val;
288
289  (void)len;
290
291  switch (cmdtype)
292    {
293    case UVC_RC_SETCUR:
294      val = data[0] + (data[1] << 8);
295      histream_pu_set_brightness(val);
296      ret = 2;
297      break;
298
299    case UVC_RC_GETCUR:
300      val = histream_pu_get_brightness();
301      data[0] = val & 0xff;
302      data[1] = (val >> 8) & 0xff;
303      ret     = 2;
304      break;
305
306    case UVC_RC_GETRES:
307      data[0] = 0x1;
308      ret     = 2;
309      break;
310
311    case UVC_RC_GETINFO:
312      data[0] = 0x3;
313      ret     = 1;
314      break;
315
316    case UVC_RC_GETMIN:
317      val = 0;
318      data[0] = val & 0xff;
319      data[1] = (val >> 8) & 0xff;
320      ret     = 2;
321      break;
322
323    case UVC_RC_GETMAX:
324      val = 0x64;
325      data[0] = val & 0xff;
326      data[1] = (val >> 8) & 0xff;
327      ret     = 2;
328      break;
329
330    case UVC_RC_GETDEF:
331      val = 0x32;
332      data[0] = val & 0xff;
333      data[1] = (val >> 8) & 0xff;
334      ret     = 2;
335      break;
336
337    default:
338      break;
339    }
340
341  return ret;
342}
343
344static void histream_pu_set_contrast(uint16_t val)
345{
346  PRINT_INFO("set contrast val = %u\n", val);
347}
348
349static uint16_t histream_pu_get_contrast(void)
350{
351  const uint16_t cur_cal = 30;
352
353  PRINT_INFO("get contrast val = %u\n", __FUNCTION__, __LINE__);
354
355  return cur_cal;
356}
357
358static uint32_t sample_uvc_pu_contrast_ctrl(void *buf, uint32_t len, uint32_t cmdtype)
359{
360  uint32_t ret  = 0;
361  uint8_t *data = (uint8_t *)buf;
362  uint16_t val;
363
364  (void)len;
365
366  switch (cmdtype)
367    {
368    case UVC_RC_SETCUR:
369      val = data[0] + (data[1] << 8);
370      histream_pu_set_contrast(val);
371      ret = 2;
372      break;
373
374    case UVC_RC_GETCUR:
375      val = histream_pu_get_contrast();
376      data[0] = val & 0xff;
377      data[1] = (val >> 8) & 0xff;
378      ret     = 2;
379      break;
380
381    case UVC_RC_GETRES:
382      data[0] = 0x1;
383      ret     = 2;
384      break;
385
386    case UVC_RC_GETINFO:
387      data[0] = 0x3;
388      ret     = 1;
389      break;
390
391    case UVC_RC_GETMIN:
392      val = 0;
393      data[0] = val & 0xff;
394      data[1] = (val >> 8) & 0xff;
395      ret     = 2;
396      break;
397
398    case UVC_RC_GETMAX:
399      val = 0x64;
400      data[0] = val & 0xff;
401      data[1] = (val >> 8) & 0xff;
402      ret     = 2;
403      break;
404
405    case UVC_RC_GETDEF:
406      val = 0x32;
407      data[0] = val & 0xff;
408      data[1] = (val >> 8) & 0xff;
409      ret     = 2;
410      break;
411
412    default:
413      break;
414    }
415
416  return ret;
417}
418
419static uint32_t uvc_process_unit_contorl(void *buf, uint32_t len, uint32_t event_id, uint32_t cmdtype)
420{
421  uint32_t ret = 0;
422
423  PRINT_INFO("%s %d, event_id=%u, len=%u, cmdtype=%02x\n", __FUNCTION__, __LINE__, event_id, len, cmdtype);
424
425  switch (event_id)
426    {
427    case USBD_UVC_PU_CONTROL_UNDEFINED:
428      break;
429
430    case USBD_UVC_PU_BACKLIGHT_COMPENSATION_CONTROL:
431      break;
432
433    case USBD_UVC_PU_BRIGHTNESS_CONTROL:
434      ret = sample_uvc_pu_brightness_ctrl(buf, len, cmdtype);
435      break;
436
437    case USBD_UVC_PU_CONTRAST_CONTROL:
438      ret = sample_uvc_pu_contrast_ctrl(buf, len, cmdtype);
439      break;
440
441    case USBD_UVC_PU_GAIN_CONTROL:
442      break;
443
444    case USBD_UVC_PU_POWER_LINE_FREQUENCY_CONTROL:
445      break;
446
447    case USBD_UVC_PU_HUE_CONTROL:
448      break;
449
450    case USBD_UVC_PU_SATURATION_CONTROL:
451      break;
452
453    case USBD_UVC_PU_SHARPNESS_CONTROL:
454      break;
455
456    case USBD_UVC_PU_GAMMA_CONTROL:
457      break;
458
459    case USBD_UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL:
460      break;
461
462    case USBD_UVC_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTORL:
463      break;
464
465    case USBD_UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL:
466      break;
467
468    case USBD_UVC_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL:
469      break;
470
471    case USBD_UVC_PU_DIGITAL_MULTIPLIER_CONTROL:
472      break;
473
474    case USBD_UVC_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL:
475      break;
476
477    case USBD_UVC_PU_HUE_AUTO_CONTROL:
478      break;
479
480    case USBD_UVC_PU_ANALOG_VIDEO_STANDARD_CONTROL:
481      break;
482
483    case USBD_UVC_PU_ANALOG_LOCK_STATUS_CONTROL:
484      break;
485
486    case USBD_UVC_PU_CONTRAST_AUTO_CONTROL:
487      break;
488
489    default:
490      break;
491    }
492
493  return ret;
494}
495
496static uint32_t camera_terminal_unit_contorl(void *buf, uint32_t len, uint32_t event_id, uint32_t cmdtype)
497{
498  (void)buf;
499
500  PRINT_INFO("%s %d, event_id=%u, len=%u, cmdtype=%02x\n", __FUNCTION__, __LINE__, event_id, len, cmdtype);
501
502  switch (event_id)
503    {
504    case USBD_UVC_CT_CONTROL_UNDEFINED:
505      break;
506
507    case USBD_UVC_CT_SCANNING_MODE_CONTROL:
508      break;
509
510    case USBD_UVC_CT_AE_MODE_CONTROL:
511      break;
512
513    case USBD_UVC_CT_AE_PRIORITY_CONTROL:
514      break;
515
516    case USBD_UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL:
517      break;
518
519    case USBD_UVC_CT_EXPOSURE_TIME_RELATIVE_CONTROL:
520      break;
521
522    case USBD_UVC_CT_FOCUS_ABSOLUTE_CONTROL:
523      break;
524
525    case USBD_UVC_CT_FOCUS_RELATIVE_CONTROL:
526      break;
527
528    case USBD_UVC_CT_FOCUS_AUTO_CONTROL:
529      break;
530
531    case USBD_UVC_CT_IRIS_ABSOLUTE_CONTROL:
532      break;
533
534    case USBD_UVC_CT_IRIS_RELATIVE_CONTROL:
535      break;
536
537    case USBD_UVC_CT_ZOOM_ABSOLUTE_CONTROL:
538      break;
539
540    case USBD_UVC_CT_ZOOM_RELATIVE_CONTROL:
541      break;
542
543    case USBD_UVC_CT_PANTILT_ABSOLUTE_CONTROL:
544      break;
545
546    case USBD_UVC_CT_PANTILT_RELATIVE_CONTROL:
547      break;
548
549    case USBD_UVC_CT_ROLL_ABSOLUTE_CONTROL:
550      break;
551
552    case USBD_UVC_CT_ROLL_RELATIVE_CONTROL:
553      break;
554
555    case USBD_UVC_CT_PRIVACY_CONTROL:
556      break;
557
558    case USBD_UVC_CT_FOCUS_SIMPLE_CONTROL:
559      break;
560
561    case USBD_UVC_CT_WINDOW_CONTROL:
562      break;
563
564    case USBD_UVC_CT_REGION_OF_INTEREST_CONTROL:
565      break;
566
567    default:
568      break;
569    }
570
571  return 0;
572}
573
574static struct uvc_camera_cmd g_uvc_unit_mappings[UVC_UNIT_MAP_SIZE] =
575{
576  {
577    .id = CMD_HICAMERA_UNIT_CONTROL,
578    .name = "hicamera_unit_control",
579    .uvc_control_func = hicamera_unit_control,
580  },
581  {
582    .id = CMD_H264_UNIT_CONTROL,
583    .name = "h264_unit_control",
584    .uvc_control_func = h264_unit_control,
585  },
586  {
587    .id = CMD_CAMERA_UNIT_CONTROL,
588    .name = "camera_terminal_unit_contorl",
589    .uvc_control_func = camera_terminal_unit_contorl,
590  },
591  {
592    .id = CMD_PROCESS_UNIT_CONTROL,
593    .name = "uvc_process_unit_contorl",
594    .uvc_control_func = uvc_process_unit_contorl,
595  },
596};
597
598#ifdef __cplusplus
599#if __cplusplus
600}
601#endif /* __cplusplus */
602#endif /* __cplusplus */
603