diff --git a/arch/arm/include/cxd56xx/cisif.h b/arch/arm/include/cxd56xx/cisif.h index 2967fd07269..7ab7ea8d738 100644 --- a/arch/arm/include/cxd56xx/cisif.h +++ b/arch/arm/include/cxd56xx/cisif.h @@ -37,48 +37,10 @@ #define __ARCH_ARM_INCLUDE_CXD56XX_CISIF_H /**************************************************************************** - * Public Types + * Included Files ****************************************************************************/ -typedef void (*notify_callback_t)(uint8_t code, uint32_t size, uint32_t addr); -typedef void (*comp_callback_t)(uint8_t code, uint32_t size, uint32_t addr); - -struct cisif_init_yuv_param_s -{ - uint16_t hsize; - uint16_t vsize; - uint32_t notify_size; - notify_callback_t notify_func; -}; - -typedef struct cisif_init_yuv_param_s cisif_init_yuv_param_t; - -struct cisif_init_jpeg_param_s -{ - uint32_t notify_size; - notify_callback_t notify_func; -}; - -typedef struct cisif_init_jpeg_param_s cisif_init_jpeg_param_t; - -struct cisif_sarea_s -{ - uint8_t *strg_addr; - uint32_t strg_size; -}; - -typedef struct cisif_sarea_s cisif_sarea_t; - -struct cisif_param_s -{ - uint32_t format; - cisif_init_yuv_param_t yuv_param; - cisif_init_jpeg_param_t jpg_param; - cisif_sarea_t sarea; - comp_callback_t comp_func; -}; - -typedef struct cisif_param_s cisif_param_t; +#include #ifndef __ASSEMBLY__ @@ -95,11 +57,7 @@ extern "C" * Public Function Prototypes ****************************************************************************/ -int cxd56_cisifinit(void); -int cxd56_cisiffinalize(void); -int cxd56_cisifstartcapture(cisif_param_t *param, cisif_sarea_t *sarea); -int cxd56_cisifstopcapture(void); -int cxd56_cisifsetdmabuf(cisif_sarea_t *sarea); +const FAR struct video_imgdata_ops_s *cxd56_cisif_initialize(void); #undef EXTERN #if defined(__cplusplus) diff --git a/arch/arm/include/cxd56xx/pm.h b/arch/arm/include/cxd56xx/pm.h index 7c67ac97633..5944b040671 100644 --- a/arch/arm/include/cxd56xx/pm.h +++ b/arch/arm/include/cxd56xx/pm.h @@ -79,6 +79,7 @@ #define PM_CPUFREQLOCK_FLAG_HV (0x0001) /* request HV */ #define PM_CPUFREQLOCK_FLAG_LV (0x4000) /* request LV */ +#define PM_CPUFREQLOCK_FLAG_HOLD (0x8000) /* hold the current frequency */ /* FrequencyLock identifier tag helper macro function */ diff --git a/arch/arm/src/cxd56xx/cxd56_cisif.c b/arch/arm/src/cxd56xx/cxd56_cisif.c index c5bdbbc253b..b89584da8d4 100644 --- a/arch/arm/src/cxd56xx/cxd56_cisif.c +++ b/arch/arm/src/cxd56xx/cxd56_cisif.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/arm/src/cxd56xx/cxd56_cisif.c * - * Copyright 2018 Sony Semiconductor Solutions Corporation + * Copyright 2018, 2020 Sony Semiconductor Solutions Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -51,7 +51,7 @@ #include #include - +#include #include "up_arch.h" #include "cxd56_clock.h" @@ -67,10 +67,19 @@ /* #define CISIF_DBG_CONTI_CAP */ -#define YUV_VSIZE_MIN (64) -#define YUV_HSIZE_MIN (96) -#define YUV_VSIZE_MAX (360) -#define YUV_HSIZE_MAX (480) +#define YUV_VSIZE_STEP (1) +#define YUV_HSIZE_STEP (1) +#define YUV_VSIZE_MIN (64) +#define YUV_HSIZE_MIN (96) +#define YUV_VSIZE_MAX (360) +#define YUV_HSIZE_MAX (480) + +#define JPG_VSIZE_STEP (1) +#define JPG_HSIZE_STEP (1) +#define JPG_VSIZE_MIN (64) +#define JPG_HSIZE_MIN (96) +#define JPG_VSIZE_MAX (1944) +#define JPG_HSIZE_MAX (2592) #define JPG_INT_ALL (JPG_ERR_STATUS_INT | \ JPG_MEM_OVF_INT | \ @@ -123,16 +132,55 @@ typedef enum state_e state_t; typedef void (*intc_func_table)(uint8_t code); +typedef void (*notify_callback_t)(uint8_t code, uint32_t size, uint32_t addr); +typedef void (*comp_callback_t)(uint8_t code, uint32_t size, uint32_t addr); + +struct cisif_init_yuv_param_s +{ + uint16_t hsize; + uint16_t vsize; + uint32_t notify_size; + notify_callback_t notify_func; +}; + +typedef struct cisif_init_yuv_param_s cisif_init_yuv_param_t; + +struct cisif_init_jpeg_param_s +{ + uint32_t notify_size; + notify_callback_t notify_func; +}; + +typedef struct cisif_init_jpeg_param_s cisif_init_jpeg_param_t; + +struct cisif_sarea_s +{ + uint8_t *strg_addr; + uint32_t strg_size; +}; + +typedef struct cisif_sarea_s cisif_sarea_t; + +struct cisif_param_s +{ + uint32_t format; + cisif_init_yuv_param_t yuv_param; + cisif_init_jpeg_param_t jpg_param; + cisif_sarea_t sarea; +}; + +typedef struct cisif_param_s cisif_param_t; + /**************************************************************************** * Private Data ****************************************************************************/ +FAR static void *g_cisif_video_private = NULL; static state_t g_state = STATE_STANDBY; static uint32_t g_storage_addr = 0; -notify_callback_t g_jpg_notify_callback_func; -notify_callback_t g_ycc_notify_callback_func; -comp_callback_t g_comp_callback_func; +static notify_callback_t g_jpg_notify_callback_func; +static notify_callback_t g_ycc_notify_callback_func; static bool g_jpgint_receive; static bool g_errint_receive; @@ -167,8 +215,22 @@ static int cisif_check_sarea(void *s); static int cisif_set_yuv_sarea(void *s); static int cisif_set_jpg_sarea(void *s); static int cisif_set_intlev_sarea(void *s, uint32_t yuv_size); - -int cisif_intc_handler(int irq, FAR void *context, FAR void *arg); +static int cisif_intc_handler(int irq, FAR void *context, FAR void *arg); + +/* video image data operations */ + +static int cxd56_cisif_open(FAR void *video_private); +static int cxd56_cisif_close(void); +static int cxd56_cisif_start_dma(FAR struct v4l2_format *format, + uint32_t bufaddr, + uint32_t bufsize); +static int cxd56_cisif_cancel_dma(void); +static int cxd56_cisif_set_dmabuf(uint32_t bufaddr, uint32_t bufsize); +static int cxd56_cisif_get_range_of_framesize(FAR struct v4l2_frmsizeenum + *frmsize); +static int cxd56_cisif_chk_pixelformat(uint32_t pixelformat, + uint32_t subimg_pixelformat); +static int cxd56_cisif_try_format(FAR struct v4l2_format *format); const intc_func_table g_intcomp_func[] = { @@ -203,6 +265,18 @@ const intc_func_table g_intcomp_func[] = cisif_jpg_err_int, /* JPG_ERR_STATUS_INT */ }; +const struct video_imgdata_ops_s g_cxd56_cisif_ops = + { + .open = cxd56_cisif_open, + .close = cxd56_cisif_close, + .start_dma = cxd56_cisif_start_dma, + .set_dmabuf = cxd56_cisif_set_dmabuf, + .cancel_dma = cxd56_cisif_cancel_dma, + .get_range_of_framesize = cxd56_cisif_get_range_of_framesize, + .try_format = cxd56_cisif_try_format, + .chk_pixelformat = cxd56_cisif_chk_pixelformat, + }; + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -305,7 +379,7 @@ static void cisif_callback_for_intlev(uint8_t code) /* Notify and get next addr */ - g_comp_callback_func(0, size, g_storage_addr); + video_common_notify_dma_done(0, size, g_cisif_video_private); g_jpgint_receive = false; @@ -347,7 +421,7 @@ static void cisif_ycc_axi_trdn_int(uint8_t code) else { size = cisif_reg_read(CISIF_YCC_DSTRG_CONT); - g_comp_callback_func(0, size, g_storage_addr); + video_common_notify_dma_done(0, size, g_cisif_video_private); cisif_reg_write(CISIF_YCC_DREAD_CONT, 0); } } @@ -397,7 +471,7 @@ static void cisif_jpg_axi_trdn_int(uint8_t code) else { size = cisif_reg_read(CISIF_JPG_DSTRG_CONT); - g_comp_callback_func(0, size, g_storage_addr); + video_common_notify_dma_done(0, size, g_cisif_video_private); cisif_reg_write(CISIF_JPG_DREAD_CONT, 0); } } @@ -429,7 +503,7 @@ static void cisif_ycc_err_int(uint8_t code) #endif size = cisif_reg_read(CISIF_YCC_DSTRG_CONT); - g_comp_callback_func(code, size, g_storage_addr); + video_common_notify_dma_done(code, size, g_cisif_video_private); cisif_reg_write(CISIF_YCC_DREAD_CONT, 0); g_errint_receive = true; } @@ -441,16 +515,13 @@ static void cisif_ycc_err_int(uint8_t code) static void cisif_jpg_err_int(uint8_t code) { uint32_t size; - uint32_t addr; #ifdef CISIF_INTR_TRACE cisif_trace_time_stop("cisif_jpg_err_int"); #endif - addr = g_storage_addr; - size = cisif_reg_read(CISIF_JPG_DSTRG_CONT); - g_comp_callback_func(code, size, addr); + video_common_notify_dma_done(code, size, g_cisif_video_private); cisif_reg_write(CISIF_JPG_DREAD_CONT, 0); g_errint_receive = true; } @@ -459,7 +530,7 @@ static void cisif_jpg_err_int(uint8_t code) * cisif_intc_handler ****************************************************************************/ -int cisif_intc_handler(int irq, FAR void *context, FAR void *arg) +static int cisif_intc_handler(int irq, FAR void *context, FAR void *arg) { uint32_t value; uint32_t enable; @@ -514,11 +585,6 @@ static int cisif_check_param(cisif_param_t *p) return -EINVAL; } - if (p->comp_func == NULL) - { - return -EINVAL; - } - switch (p->format) { case V4L2_PIX_FMT_UYVY: @@ -687,14 +753,56 @@ static int cisif_set_intlev_sarea(void *s, uint32_t yuv_size) } /**************************************************************************** - * Public Functions + * cisif_chk_jpgfrmsize + ****************************************************************************/ + +static int cisif_chk_jpgfrmsize(int w, int h) +{ + if ((w < JPG_HSIZE_MIN) || + (w > JPG_HSIZE_MAX)) + { + return -EINVAL; + } + + if ((h < JPG_VSIZE_MIN) || + (h > JPG_VSIZE_MAX)) + { + return -EINVAL; + } + + return OK; +} + +/**************************************************************************** + * cisif_chk_yuvfrmsize + ****************************************************************************/ + +static int cisif_chk_yuvfrmsize(int w, int h) +{ + if ((w < YUV_HSIZE_MIN) || + (w > YUV_HSIZE_MAX)) + { + return -EINVAL; + } + + if ((h < YUV_VSIZE_MIN) || + (h > YUV_VSIZE_MAX)) + { + return -EINVAL; + } + + return OK; +} + +/**************************************************************************** + * Private Functions ****************************************************************************/ /**************************************************************************** - * cxd56_cisifinit + * cxd56_cisif_open ****************************************************************************/ -int cxd56_cisifinit(void) +static int cxd56_cisif_open(FAR void *video_private) { if (g_state != STATE_STANDBY) { @@ -723,15 +831,15 @@ int cxd56_cisifinit(void) #endif g_state = STATE_READY; - + g_cisif_video_private = video_private; return OK; } /**************************************************************************** - * cxd56_cisiffinalize + * cxd56_cisif_close ****************************************************************************/ -int cxd56_cisiffinalize(void) +static int cxd56_cisif_close(void) { if (g_state != STATE_READY) { @@ -756,18 +864,21 @@ int cxd56_cisiffinalize(void) cxd56_img_cisif_clock_disable(); g_state = STATE_STANDBY; + g_cisif_video_private = NULL; return OK; } /**************************************************************************** - * cxd56_cisifstartcapturing + * cxd56_cisif_start_dma ****************************************************************************/ -int cxd56_cisifstartcapture( - cisif_param_t *param, - cisif_sarea_t *sarea) +static int cxd56_cisif_start_dma(FAR struct v4l2_format *format, + uint32_t bufaddr, + uint32_t bufsize) { + cisif_param_t param = {0}; + cisif_sarea_t sarea = {0}; uint32_t cisif_mode; uint32_t interrupts = VS_INT; int ret; @@ -777,7 +888,22 @@ int cxd56_cisifstartcapture( return -EPERM; } - ret = cisif_check_param(param); + param.format = format->fmt.pix.pixelformat; + if (param.format != V4L2_PIX_FMT_JPEG) + { + if (param.format == V4L2_PIX_FMT_UYVY) + { + param.yuv_param.hsize = format->fmt.pix.width; + param.yuv_param.vsize = format->fmt.pix.height; + } + else + { + param.yuv_param.hsize = format->fmt.pix.subimg_width; + param.yuv_param.vsize = format->fmt.pix.subimg_height; + } + } + + ret = cisif_check_param(¶m); if (ret != OK) { return ret; @@ -785,37 +911,39 @@ int cxd56_cisifstartcapture( cisif_reg_write(CISIF_INTR_DISABLE, ALL_CLEAR_INT); - ret = cisif_check_sarea(sarea); + sarea.strg_addr = (uint8_t *)bufaddr; + sarea.strg_size = bufsize; + ret = cisif_check_sarea(&sarea); if (ret != OK) { return ret; } - switch (param->format) + switch (param.format) { case V4L2_PIX_FMT_UYVY: - cisif_set_yuv_param(param); - cisif_set_yuv_sarea(sarea); + cisif_set_yuv_param(¶m); + cisif_set_yuv_sarea(&sarea); cisif_mode = MODE_YUV_TRS_EN; interrupts |= YCC_INT_ALL; break; case V4L2_PIX_FMT_JPEG: - cisif_set_jpg_param(param); - cisif_set_jpg_sarea(sarea); + cisif_set_jpg_param(¶m); + cisif_set_jpg_sarea(&sarea); cisif_mode = MODE_JPG_TRS_EN; interrupts |= JPG_INT_ALL; break; case V4L2_PIX_FMT_JPEG_WITH_SUBIMG: - cisif_set_yuv_param(param); - cisif_set_jpg_param(param); + cisif_set_yuv_param(¶m); + cisif_set_jpg_param(¶m); - cisif_set_intlev_sarea(sarea, - YUV_SIZE(param->yuv_param.vsize, - param->yuv_param.hsize)); + cisif_set_intlev_sarea(&sarea, + YUV_SIZE(param.yuv_param.vsize, + param.yuv_param.hsize)); cisif_mode = MODE_INTLEV_TRS_EN; interrupts |= YCC_INT_ALL | JPG_INT_ALL; @@ -826,8 +954,7 @@ int cxd56_cisifstartcapture( return -EINVAL; } - g_comp_callback_func = param->comp_func; - g_storage_addr = (uint32_t)sarea->strg_addr; + g_storage_addr = (uint32_t)sarea.strg_addr; g_state = STATE_CAPTURE; @@ -851,7 +978,7 @@ int cxd56_cisifstartcapture( return OK; } -int cxd56_cisifstopcapture(void) +static int cxd56_cisif_cancel_dma(void) { g_state = STATE_READY; cisif_reg_write(CISIF_DIN_ENABLE, 0); @@ -861,15 +988,18 @@ int cxd56_cisifstopcapture(void) return OK; } -int cxd56_cisifsetdmabuf(cisif_sarea_t *sarea) +static int cxd56_cisif_set_dmabuf(uint32_t bufaddr, uint32_t bufsize) { int ret; uint32_t cisif_mode; uint32_t yuv_regsize; uint32_t yuv_hsize; uint32_t yuv_vsize; + cisif_sarea_t sarea = {0}; - ret = cisif_check_sarea(sarea); + sarea.strg_addr = (uint8_t *)bufaddr; + sarea.strg_size = bufsize; + ret = cisif_check_sarea(&sarea); if (ret != OK) { return ret; @@ -880,11 +1010,11 @@ int cxd56_cisifsetdmabuf(cisif_sarea_t *sarea) switch (cisif_mode) { case MODE_YUV_TRS_EN: - ret = cisif_set_yuv_sarea(sarea); + ret = cisif_set_yuv_sarea(&sarea); break; case MODE_JPG_TRS_EN: - ret = cisif_set_jpg_sarea(sarea); + ret = cisif_set_jpg_sarea(&sarea); break; default: /* MODE_INTLEV_TRS_EN */ @@ -895,7 +1025,7 @@ int cxd56_cisifsetdmabuf(cisif_sarea_t *sarea) yuv_vsize = (yuv_regsize >> 16) & 0x1ff; yuv_hsize = yuv_regsize & 0x01ff; - ret = cisif_set_intlev_sarea(sarea, + ret = cisif_set_intlev_sarea(&sarea, YUV_SIZE(yuv_vsize, yuv_hsize)); break; } @@ -906,7 +1036,172 @@ int cxd56_cisifsetdmabuf(cisif_sarea_t *sarea) } cisif_reg_write(CISIF_EXE_CMD, 1); - g_storage_addr = (uint32_t)sarea->strg_addr; + g_storage_addr = (uint32_t)sarea.strg_addr; + + return ret; +} + +static int cxd56_cisif_get_range_of_framesize(FAR struct v4l2_frmsizeenum + *frmsize) +{ + int ret = OK; + + if (frmsize == NULL) + { + return -EINVAL; + } + + if (frmsize->index != 0) + { + return -EINVAL; + } + + switch (frmsize->pixel_format) + { + case V4L2_PIX_FMT_UYVY: /* YUV 4:2:2 */ + frmsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; + frmsize->stepwise.min_width = YUV_HSIZE_MIN; + frmsize->stepwise.max_width = YUV_HSIZE_MAX; + frmsize->stepwise.step_width = YUV_HSIZE_STEP; + frmsize->stepwise.min_height = YUV_VSIZE_MIN; + frmsize->stepwise.max_height = YUV_VSIZE_MAX; + frmsize->stepwise.step_height = YUV_VSIZE_STEP; + + break; + + case V4L2_PIX_FMT_JPEG: /* JPEG */ + frmsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; + frmsize->stepwise.min_width = JPG_HSIZE_MIN; + frmsize->stepwise.max_width = JPG_HSIZE_MAX; + frmsize->stepwise.step_width = JPG_HSIZE_STEP; + frmsize->stepwise.min_height = JPG_VSIZE_MIN; + frmsize->stepwise.max_height = JPG_VSIZE_MAX; + frmsize->stepwise.step_height = JPG_VSIZE_STEP; + + break; + + case V4L2_PIX_FMT_JPEG_WITH_SUBIMG: /* JPEG + YUV 4:2:2 */ + if (frmsize->subimg_pixel_format != V4L2_PIX_FMT_UYVY) + { + /* Unsupported pixel format */ + + return -EINVAL; + } + + frmsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; + frmsize->stepwise.min_width = JPG_HSIZE_MIN; + frmsize->stepwise.max_width = JPG_HSIZE_MAX; + frmsize->stepwise.step_width = JPG_HSIZE_STEP; + frmsize->stepwise.min_height = JPG_VSIZE_MIN; + frmsize->stepwise.max_height = JPG_VSIZE_MAX; + frmsize->stepwise.step_height = JPG_VSIZE_STEP; + + frmsize->subimg_type = V4L2_FRMSIZE_TYPE_STEPWISE; + frmsize->subimg.stepwise.min_width = YUV_HSIZE_MIN; + frmsize->subimg.stepwise.max_width = YUV_HSIZE_MAX; + frmsize->subimg.stepwise.step_width = YUV_HSIZE_STEP; + frmsize->subimg.stepwise.min_height = YUV_VSIZE_MIN; + frmsize->subimg.stepwise.max_height = YUV_VSIZE_MAX; + frmsize->subimg.stepwise.step_height = YUV_VSIZE_STEP; + + break; + + default: /* Unsupported pixel format */ + + return -EINVAL; + } return ret; } + +static int cxd56_cisif_chk_pixelformat(uint32_t pixelformat, + uint32_t subimg_pixelformat) +{ + switch (pixelformat) + { + case V4L2_PIX_FMT_UYVY: + + return OK; + + case V4L2_PIX_FMT_JPEG: + + return OK; + + case V4L2_PIX_FMT_JPEG_WITH_SUBIMG: + + if (subimg_pixelformat == V4L2_PIX_FMT_UYVY) + { + return OK; + } + else + { + return -EINVAL; + } + + default : + + return -EINVAL; + } + + return OK; +} + +static int cxd56_cisif_try_format(FAR struct v4l2_format *format) +{ + int ret = OK; + + switch (format->fmt.pix.pixelformat) + { + case V4L2_PIX_FMT_UYVY: /* YUV 4:2:2 */ + + ret = cisif_chk_yuvfrmsize(format->fmt.pix.width, + format->fmt.pix.height); + break; + + case V4L2_PIX_FMT_JPEG: /* JPEG */ + + ret = cisif_chk_jpgfrmsize(format->fmt.pix.width, + format->fmt.pix.height); + break; + + case V4L2_PIX_FMT_JPEG_WITH_SUBIMG: /* JPEG + YUV 4:2:2 */ + + if (format->fmt.pix.subimg_pixelformat != V4L2_PIX_FMT_UYVY) + { + /* Unsupported pixel format */ + + return -EINVAL; + } + + ret = cisif_chk_jpgfrmsize(format->fmt.pix.width, + format->fmt.pix.height); + if (ret != OK) + { + return ret; + } + + ret = cisif_chk_yuvfrmsize(format->fmt.pix.subimg_width, + format->fmt.pix.subimg_height); + break; + + default: /* Unsupported pixel format */ + + return -EINVAL; + } + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * cxd56_cisif_initialize + ****************************************************************************/ + +const FAR struct video_imgdata_ops_s *cxd56_cisif_initialize(void) +{ + return &g_cxd56_cisif_ops; +} + diff --git a/arch/arm/src/cxd56xx/cxd56_dmac.c b/arch/arm/src/cxd56xx/cxd56_dmac.c index 75d74dc65f0..53abb971650 100644 --- a/arch/arm/src/cxd56xx/cxd56_dmac.c +++ b/arch/arm/src/cxd56xx/cxd56_dmac.c @@ -595,8 +595,6 @@ static int dma_setintrcallback(int ch, dma_callback_t func, void *data) g_dmach[ch].callback = func; g_dmach[ch].arg = data; - up_enable_irq(irq_map[ch]); - return 0; } @@ -608,8 +606,6 @@ static int dma_clearintrcallback(int ch) g_dmach[ch].callback = NULL; g_dmach[ch].arg = NULL; - up_disable_irq(irq_map[ch]); - return 0; } @@ -676,6 +672,7 @@ void weak_function up_dma_initialize(void) for (i = 0; i < NCHANNELS; i++) { g_dmach[i].chan = i; + up_enable_irq(irq_map[i]); } nxsem_init(&g_dmaexc, 0, 1); diff --git a/arch/arm/src/cxd56xx/cxd56_farapistub.h b/arch/arm/src/cxd56xx/cxd56_farapistub.h index f411bc26cc1..ef6b755be60 100644 --- a/arch/arm/src/cxd56xx/cxd56_farapistub.h +++ b/arch/arm/src/cxd56xx/cxd56_farapistub.h @@ -36,6 +36,6 @@ #ifndef __ARCH_ARM_SRC_CXD56XX_CXD56_FARAPISTUB_H #define __ARCH_ARM_SRC_CXD56XX_CXD56_FARAPISTUB_H -#define FARAPISTUB_VERSION 20166 +#define FARAPISTUB_VERSION 20175 #endif /* __ARCH_ARM_SRC_CXD56XX_CXD56_FARAPISTUB_H */ diff --git a/arch/arm/src/cxd56xx/cxd56_i2c.c b/arch/arm/src/cxd56xx/cxd56_i2c.c index 4517071a3b8..3b84e644ab9 100644 --- a/arch/arm/src/cxd56xx/cxd56_i2c.c +++ b/arch/arm/src/cxd56xx/cxd56_i2c.c @@ -855,9 +855,6 @@ static int cxd56_i2c_transfer_scu(FAR struct i2c_master_s *dev, cxd56_i2c_clock_gate_disable(priv->port); cxd56_i2c_disable(priv); cxd56_i2c_setfrequency(priv, msgs->frequency); - i2c_reg_rmw(priv, CXD56_IC_CON, IC_RESTART_EN, IC_RESTART_EN); - i2c_reg_write(priv, CXD56_IC_TAR, msgs->addr & 0x7f); - cxd56_i2c_enable(priv); cxd56_i2c_clock_gate_enable(priv->port); priv->frequency = msgs->frequency; @@ -1037,7 +1034,9 @@ struct i2c_master_s *cxd56_i2cbus_initialize(int port) i2c_reg_write(priv, CXD56_IC_SDA_HOLD, 1); i2c_reg_write(priv, CXD56_IC_CON, - (IC_SLAVE_DISABLE | IC_MASTER_MODE | IC_TX_EMPTY_CTRL)); + (IC_RX_FIFO_FULL_HLD_CTRL | IC_RESTART_EN | + IC_SLAVE_DISABLE | IC_MASTER_MODE | IC_TX_EMPTY_CTRL)); + cxd56_i2c_setfrequency(priv, I2C_DEFAULT_FREQUENCY); leave_critical_section(flags); diff --git a/arch/arm/src/cxd56xx/cxd56_powermgr.c b/arch/arm/src/cxd56xx/cxd56_powermgr.c index 34bde395d19..8f65c5a4313 100644 --- a/arch/arm/src/cxd56xx/cxd56_powermgr.c +++ b/arch/arm/src/cxd56xx/cxd56_powermgr.c @@ -575,6 +575,13 @@ void up_pm_acquire_freqlock(struct pm_cpu_freqlock_s *lock) cxd56_pm_semtake(&g_freqlock); + if (lock->flag == PM_CPUFREQLOCK_FLAG_HOLD) + { + /* Return with holding the current frequency */ + + return; + } + for (entry = sq_peek(&g_freqlockqueue); entry; entry = sq_next(entry)) { if (entry == (struct sq_entry_s *)lock) @@ -614,6 +621,13 @@ void up_pm_release_freqlock(struct pm_cpu_freqlock_s *lock) DEBUGASSERT(lock); + if (lock->flag == PM_CPUFREQLOCK_FLAG_HOLD) + { + /* Release holding the current frequency */ + + goto exit; + } + up_pm_acquire_wakelock(&g_wlock); cxd56_pm_semtake(&g_freqlock); @@ -632,6 +646,7 @@ void up_pm_release_freqlock(struct pm_cpu_freqlock_s *lock) } } +exit: nxsem_post(&g_freqlock); up_pm_release_wakelock(&g_wlock); diff --git a/arch/arm/src/cxd56xx/cxd56_rtc.c b/arch/arm/src/cxd56xx/cxd56_rtc.c index c4aa38fbe90..87d8b5717cc 100644 --- a/arch/arm/src/cxd56xx/cxd56_rtc.c +++ b/arch/arm/src/cxd56xx/cxd56_rtc.c @@ -561,6 +561,7 @@ int cxd56_rtc_setalarm(FAR struct alm_setalarm_s *alminfo) int ret = -EBUSY; int id; uint64_t count; + uint32_t mask; ASSERT(alminfo != NULL); DEBUGASSERT(RTC_ALARM_LAST > alminfo->as_id); @@ -584,6 +585,13 @@ int cxd56_rtc_setalarm(FAR struct alm_setalarm_s *alminfo) count -= g_rtc_save->offset; + /* clear previsous setting */ + + mask = RTCREG_ALM0_ERR_FLAG_MASK | RTCREG_ALM0_FLAG_MASK; + mask <<= id; + + putreg32(mask, CXD56_RTC0_ALMCLR); + /* wait until previous alarm request is completed */ while (RTCREG_ASET_BUSY_MASK & getreg32(CXD56_RTC0_SETALMPRECNT(id))); @@ -628,10 +636,11 @@ int cxd56_rtc_cancelalarm(enum alm_id_e alarmid) FAR struct alm_cbinfo_s *cbinfo; irqstate_t flags; int ret = -ENODATA; + uint32_t mask; DEBUGASSERT(RTC_ALARM_LAST > alarmid); - /* Set the alarm in hardware and enable interrupts */ + /* Cancel the alarm in hardware and clear interrupts */ cbinfo = &g_alarmcb[alarmid]; @@ -647,6 +656,29 @@ int cxd56_rtc_cancelalarm(enum alm_id_e alarmid) putreg32(0, CXD56_RTC0_ALMOUTEN(alarmid)); + while (RTCREG_ALM_BUSY_MASK & getreg32(CXD56_RTC0_ALMOUTEN(alarmid))); + + /* wait until previous alarm request is completed */ + + while (RTCREG_ASET_BUSY_MASK & getreg32(CXD56_RTC0_SETALMPRECNT(alarmid))); + + /* clear the alarm counter */ + + putreg32(0, CXD56_RTC0_SETALMPOSTCNT(alarmid)); + putreg32(0, CXD56_RTC0_SETALMPRECNT(alarmid)); + + while (RTCREG_ASET_BUSY_MASK & getreg32(CXD56_RTC0_SETALMPRECNT(alarmid))); + + /* wait until the interrupt flag is clear */ + + mask = RTCREG_ALM0_ERR_FLAG_MASK | RTCREG_ALM0_FLAG_MASK; + mask <<= alarmid; + + while (mask & getreg32(CXD56_RTC0_ALMFLG)) + { + putreg32(mask, CXD56_RTC0_ALMCLR); + } + leave_critical_section(flags); ret = OK; diff --git a/arch/arm/src/cxd56xx/cxd56_scu.c b/arch/arm/src/cxd56xx/cxd56_scu.c index c715a484f8b..e1374767d70 100644 --- a/arch/arm/src/cxd56xx/cxd56_scu.c +++ b/arch/arm/src/cxd56xx/cxd56_scu.c @@ -210,6 +210,7 @@ struct cxd56_scudev_s uint8_t oneshot; /* Bitmap for Oneshots */ sem_t oneshotwait[3]; /* Semaphore for wait oneshot sequence is done */ + int oneshoterr[3]; /* error code for oneshot sequencer */ #ifndef CONFIG_DISABLE_SIGNAL struct ev_notify_s event[3]; /* MATHFUNC event notify */ struct wm_notify_s wm[14]; /* Watermark notify */ @@ -1080,6 +1081,7 @@ static int seq_oneshot(int bustype, int slave, FAR uint16_t *inst, putreg32(1 << (tid + 24), SCU_INT_ENABLE_MAIN); scuinfo("Sequencer start.\n"); + priv->oneshoterr[tid] = 0; /* Start sequencer as one shot mode */ @@ -1096,7 +1098,11 @@ static int seq_oneshot(int bustype, int slave, FAR uint16_t *inst, scuinfo("Sequencer done.\n"); - if (buffer) + if (priv->oneshoterr[tid] < 0) + { + ret = ERROR; + } + else { /* Copy sequencer output results to user buffer. * XXX: Sequencer output RAM offset is differ from document. @@ -1694,6 +1700,8 @@ static int seq_scuirqhandler(int irq, FAR void *context, FAR void *arg) uint32_t ierr0; uint32_t ierr1; uint32_t ierr2; + uint32_t out; + int tid; int i; intr = getreg32(SCU_INT_MASKED_STT_MAIN); @@ -1754,16 +1762,30 @@ static int seq_scuirqhandler(int irq, FAR void *context, FAR void *arg) if (ierr2 != 0) { scuerr("err2: %08x\n", ierr2); - ierr2 &= 0x03ff; + for (i = 0; i < 10; i++) { - if (ierr2 & (1 << i)) + if (ierr2 & (0x00010001 << i)) { seq_stopseq(i); + + /* Get sequencer output selector */ + + out = (getreg32(SCUSEQ_PROPERTY(i)) >> 12) & 0x3; + + if (0 < out) + { + /* Set error code to oneshot sequencer id */ + + tid = out - 1; + + priv->oneshoterr[tid] = -EIO; + seq_semgive(&priv->oneshotwait[tid]); + } } } - putreg32(0x03ff, SCU_INT_CLEAR_ERR_2); + putreg32(ierr2, SCU_INT_CLEAR_ERR_2); } return 0; @@ -3516,7 +3538,11 @@ void scu_initialize(void) /* Enable error interrupt */ putreg32(0x007ffe00, SCU_INT_ENABLE_ERR_0); - putreg32(0x03ff, SCU_INT_ENABLE_ERR_2); + putreg32(0x03ff03ff, SCU_INT_ENABLE_ERR_2); + + /* Set the number of TxAbort repeat times */ + + putreg32(5, SCUSEQ_REPEAT_TXABORT); /* Enable SCU IRQ */ diff --git a/arch/arm/src/cxd56xx/cxd56_spi.c b/arch/arm/src/cxd56xx/cxd56_spi.c index 3ca95cdfce2..d6da40ea8f5 100644 --- a/arch/arm/src/cxd56xx/cxd56_spi.c +++ b/arch/arm/src/cxd56xx/cxd56_spi.c @@ -48,6 +48,7 @@ #include #include +#include #include #include #include @@ -342,6 +343,11 @@ static struct cxd56_spidev_s g_spi3dev = }; #endif +/* Inhibit clock change */ + +static struct pm_cpu_freqlock_s g_hold_lock = + PM_CPUFREQLOCK_INIT(0, PM_CPUFREQLOCK_FLAG_HOLD); + /**************************************************************************** * Public Data ****************************************************************************/ @@ -518,6 +524,7 @@ static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode) { FAR struct cxd56_spidev_s *priv = (FAR struct cxd56_spidev_s *)dev; uint32_t regval; + uint32_t cr1val; /* Has the mode changed? */ @@ -560,8 +567,19 @@ static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode) return; } + /* Disable SSE */ + + cr1val = spi_getreg(priv, CXD56_SPI_CR1_OFFSET); + spi_putreg(priv, CXD56_SPI_CR1_OFFSET, cr1val & ~SPI_CR1_SSE); + spi_putreg(priv, CXD56_SPI_CR0_OFFSET, regval); + /* Enable SSE after a few microseconds delay */ + + up_udelay(3); + + spi_putreg(priv, CXD56_SPI_CR1_OFFSET, cr1val); + /* Enable clock gating (clock disable) */ cxd56_spi_clock_gate_enable(priv->port); @@ -658,6 +676,10 @@ static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd) register uint32_t regval; register uint32_t cr1val = 0; + /* Prohibit the clock change during SPI transfer */ + + up_pm_acquire_freqlock(&g_hold_lock); + /* Disable clock gating (clock enable) */ cxd56_spi_clock_gate_disable(priv->port); @@ -698,6 +720,10 @@ static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd) cxd56_spi_clock_gate_enable(priv->port); + /* Allow the clock change after SPI transfer */ + + up_pm_release_freqlock(&g_hold_lock); + return (uint16_t)regval; } @@ -752,6 +778,10 @@ static void spi_do_exchange(FAR struct spi_dev_s *dev, tx.pv = txbuffer; rx.pv = rxbuffer; + /* Prohibit the clock change during SPI transfer */ + + up_pm_acquire_freqlock(&g_hold_lock); + /* Disable clock gating (clock enable) */ cxd56_spi_clock_gate_disable(priv->port); @@ -826,6 +856,10 @@ static void spi_do_exchange(FAR struct spi_dev_s *dev, /* Enable clock gating (clock disable) */ cxd56_spi_clock_gate_enable(priv->port); + + /* Allow the clock change after SPI transfer */ + + up_pm_release_freqlock(&g_hold_lock); } /**************************************************************************** @@ -1359,6 +1393,10 @@ void spi_flush(FAR struct spi_dev_s *dev) FAR struct cxd56_spidev_s *priv = (FAR struct cxd56_spidev_s *)dev; uint32_t regval = 0; + /* Prohibit the clock change during SPI transfer */ + + up_pm_acquire_freqlock(&g_hold_lock); + /* Disable clock gating (clock enable) */ cxd56_spi_clock_gate_disable(priv->port); @@ -1402,6 +1440,10 @@ void spi_flush(FAR struct spi_dev_s *dev) /* Enable clock gating (clock disable) */ cxd56_spi_clock_gate_enable(priv->port); + + /* Allow the clock change after SPI transfer */ + + up_pm_release_freqlock(&g_hold_lock); } #ifdef CONFIG_CXD56_DMAC @@ -1423,6 +1465,10 @@ static void spi_dmaexchange(FAR struct spi_dev_s *dev, DEBUGASSERT(priv && priv->spibase); + /* Prohibit the clock change during SPI transfer */ + + up_pm_acquire_freqlock(&g_hold_lock); + /* Disable clock gating (clock enable) */ cxd56_spi_clock_gate_disable(priv->port); @@ -1459,6 +1505,10 @@ static void spi_dmaexchange(FAR struct spi_dev_s *dev, /* Enable clock gating (clock disable) */ cxd56_spi_clock_gate_enable(priv->port); + + /* Allow the clock change after SPI transfer */ + + up_pm_release_freqlock(&g_hold_lock); } #ifndef CONFIG_SPI_EXCHANGE diff --git a/arch/arm/src/cxd56xx/cxd56_uart.c b/arch/arm/src/cxd56xx/cxd56_uart.c index 6ad71d781be..cbb0dc9d263 100644 --- a/arch/arm/src/cxd56xx/cxd56_uart.c +++ b/arch/arm/src/cxd56xx/cxd56_uart.c @@ -222,11 +222,15 @@ static void cxd56_uart_pincontrol(int ch, bool on) static void cxd56_uart_start(int ch) { + irqstate_t flags = enter_critical_section(); + cxd56_setbaud(CONSOLE_BASE, CONSOLE_BASEFREQ, CONSOLE_BAUD); putreg32(g_lcr, g_uartdevs[ch].uartbase + CXD56_UART_LCR_H); putreg32(g_cr, g_uartdevs[ch].uartbase + CXD56_UART_CR); + + leave_critical_section(flags); } /**************************************************************************** @@ -242,6 +246,8 @@ static void cxd56_uart_stop(int ch) { uint32_t cr; + irqstate_t flags = enter_critical_section(); + while (UART_FR_BUSY & getreg32(g_uartdevs[ch].uartbase + CXD56_UART_FR)); cr = getreg32(g_uartdevs[ch].uartbase + CXD56_UART_CR); @@ -251,6 +257,8 @@ static void cxd56_uart_stop(int ch) g_lcr = getreg32(g_uartdevs[ch].uartbase + CXD56_UART_LCR_H); putreg32(0, g_uartdevs[ch].uartbase + CXD56_UART_LCR_H); + + leave_critical_section(flags); } /**************************************************************************** diff --git a/arch/arm/src/cxd56xx/hardware/cxd5602_isop.h b/arch/arm/src/cxd56xx/hardware/cxd5602_isop.h index 9132ec3281b..28347203da4 100644 --- a/arch/arm/src/cxd56xx/hardware/cxd5602_isop.h +++ b/arch/arm/src/cxd56xx/hardware/cxd5602_isop.h @@ -1,444 +1,468 @@ -/* This file is generated at May 18 2016 16:19:52 */ +/* This file is generated at Dec 14 2020 13:28:30 */ -const unsigned long scu_isopprog_array[] = { -0xf7f8d600, 0xa2024f86, 0x0001a200, 0x18004081, -0x00008014, 0x00000000, 0x0000a207, 0x00000000, -0x0000a070, 0xac2d4ec6, 0xd000ac27, 0x50a2e444, -0x70111801, 0x50011c01, 0xf34cd000, 0x0004800a, -0x40110114, 0x50031f43, 0x9ff42801, 0x90062911, -0x8fec5043, 0x00140003, 0x40640113, 0x1f344011, -0x9fe42121, 0xd2005001, 0x5203f356, 0x50155004, -0x04150845, 0x90082905, 0x2d444014, 0x00259ff2, -0x40110115, 0x21311f54, 0xd1009fe4, 0x5ff2e824, -0xe808d400, 0x01f8fc43, 0x07fffc33, 0xe804d000, -0xf000d700, 0x1c431c12, 0xe800d100, 0x1c025013, -0x0103fc40, 0x0300fc30, 0xf3d8d200, 0x1c135be4, -0xe418d100, 0x1c105003, 0xf47250a1, 0x1c230300, -0x0004f721, 0xf7235e61, 0xf7230005, 0xf7230016, -0x00250017, 0x4fc10215, 0xf7531d53, 0xf753fffe, -0x2141ffff, 0xd1009fee, 0xd209f33c, 0xd000ec00, -0x5004f4b8, 0x1c125005, 0x0304f470, 0x44020002, -0x0308f472, 0x41a10001, 0x00020053, 0x106350a7, -0x1c240132, 0x0004f727, 0x0005f724, 0x0016f724, -0x0017f724, 0x1d340013, 0xfffef734, 0xfffff734, -0x40434ff7, 0x9ff02907, 0x44014015, 0x9fca2925, -0xd3005001, 0x5004f340, 0xf398d200, 0x01150035, -0x1f544011, 0x9ff62941, 0xd4005fe3, 0x5005f344, -0x00415f67, 0x4fc30231, 0xfffef512, 0x1f154202, -0x9ff02173, 0xf334d200, 0xf000d100, 0xd4005003, -0x5005f538, 0x030cf412, 0xac115001, 0xa819ac19, -0x00470052, 0x00710112, 0x01211032, 0x00201c13, -0x70407052, 0x1f450104, 0x00740070, 0xf34cd700, -0x01200157, 0x1e724015, 0xf7131f02, 0xa8110016, -0x210550a0, 0x9fc44021, 0xf376d000, 0x1000fc11, -0x00345f02, 0x4ff30005, 0x21231014, 0x1d510245, -0x50029ff2, 0xf334d000, 0xf000d700, 0xf458d300, -0x1d025004, 0xf332d000, 0x0310f470, 0x00350041, -0x01151041, 0x0004f452, 0x0008f454, 0xf7524014, -0xf752000c, 0x1c52000d, 0x9fe22964, 0xd2005001, -0x1f21f330, 0x0001f721, 0xf5711d01, 0xf77102fe, -0xfc4102fc, 0xfc312016, 0xd2160518, 0x1c711951, -0x0427fc41, 0x9e21fc31, 0x0004f472, 0xe412d200, -0x0008f471, 0x1f215011, 0x0d86fa00, 0xa82da827, -0x41465000, 0x0000a070, 0xac3d4e46, 0xf601ac37, -0x28010005, 0xf6029178, 0xac200004, 0x10110021, -0xd100ac29, 0xa828f538, 0x10300120, 0x7050ac18, -0x1e150101, 0xfa000050, 0x00501890, 0x29006fb0, -0x0050901a, 0xfa004010, 0x00501880, 0xfa004020, -0x00501878, 0xfa004030, 0xd1001870, 0x5010e000, -0x08501811, 0x28010401, 0xac15906c, 0x0128fa00, -0x5003a822, 0xf6205005, 0xa8110004, 0xfa004062, -0xa8230290, 0xf538d400, 0x91022900, 0x5021a818, -0xf334d700, 0x1c410104, 0xf6305011, 0x1a720004, -0x05120801, 0xf6301d72, 0xf7400005, 0x28000016, -0x500090dc, 0x00320041, 0x01524010, 0xf6220151, -0xf7120006, 0x00050006, 0x0005f632, 0x24256ff5, -0x80ba9fe4, 0xd100a822, 0xf620e404, 0x18110004, -0x28016201, 0xd3009028, 0x6ff0f330, 0x0001f631, -0x90222101, 0x6ff01e30, 0x901a2910, 0x15f0fa00, -0x5030a822, 0xf330d100, 0x800a1f10, 0xf330d000, -0x1f015001, 0x0004f620, 0xf000d100, 0x01011050, -0x0005f620, 0x0024f213, 0xac1b2800, 0x0024f211, -0x905a0050, 0xac100015, 0x0562fa00, 0x0053a814, -0x904a2910, 0x60f31243, 0x61f34013, 0x903e2803, -0x5002a818, 0x60f05001, 0x0030ac18, 0x00470043, -0xf418d400, 0x10234011, 0xf2430134, 0x1a440002, -0x0152a81d, 0x0125a825, 0x0006f652, 0x00741f42, -0x00031f32, 0x6ff20012, 0x9fd02432, 0xa83da837, -0xa07041c6, 0xac454e06, 0xd000ac3f, 0xfc41e400, -0x18000400, 0x28000410, 0x5000915e, 0xfc41ac10, -0xd0000400, 0xac19e804, 0xd1001c01, 0x1810e080, -0xe084d100, 0x00021811, 0xf76260f2, 0x00620014, -0x0014fc02, 0x00040023, 0x13007022, 0x70131284, -0x1f346034, 0xf5611d20, 0x13010018, 0xe088d000, -0xf5615012, 0x1c02001a, 0x0014f265, 0x6ff5ac25, -0xfa000050, 0xa8220498, 0xf418d100, 0x90902910, -0xd0001025, 0x0017f000, 0xfc411282, 0x01500100, -0xf0004012, 0x6ff20280, 0x50010410, 0x903a2900, -0x50000075, 0x28020027, 0xf6629066, 0x00530014, -0x40101011, 0x01231022, 0x0002f232, 0x00641a33, -0x0014fc04, 0xf2410114, 0x1d310002, 0x00011d21, -0x24716ff1, 0x80389fd6, 0x50000075, 0x28020027, -0xf662902e, 0x00530014, 0x40101011, 0x01231022, -0x0002f232, 0x00641a33, 0x0014fc04, 0xf6410114, -0x1f310003, 0x00011f21, 0x24716ff1, 0xd0009fd6, -0x1800e400, 0x0410a819, 0x900c2800, 0x4010a810, -0x2c40ac10, 0xf6619efa, 0x50000014, 0x90142c41, -0x4fc00010, 0x90062e30, 0x80085010, 0x00fafc01, -0xd1000010, 0x1811e404, 0x28016201, 0xd5009022, -0x6ff0f330, 0x0001f651, 0x901c2101, 0x6ff01e50, -0x90142910, 0x13f8fa00, 0x1f505030, 0xd000800a, -0x5001f330, 0xa83f1f01, 0x4206a845, 0x4e06a070, -0xac3fac45, 0xe400d300, 0xfc431834, 0x04340200, -0x90322804, 0xd400ac21, 0x1841e404, 0x28016201, -0xd1009032, 0xf614f330, 0x21040001, 0x1e11902e, -0x29316ff1, 0xd0009026, 0xf001f000, 0x701102c8, -0x02c8f401, 0xe808d000, 0x05311801, 0x50001c01, -0xd1008108, 0x5003f330, 0x10501f13, 0xf000d100, -0xe808d300, 0xfdfffc45, 0xfffffc35, 0x01015007, -0xf210ac19, 0x18340026, 0xfc450454, 0x12c00200, -0xd3001c34, 0x1c35e804, 0x0026f213, 0xf214ac10, -0xf2100026, 0xf2150026, 0x12830026, 0x124512c4, -0x601060f3, 0x01326034, 0x28006075, 0x902a4014, -0x00615003, 0x40131017, 0x0014fc01, 0x01711e20, -0x0001f627, 0x10804022, 0x08500570, 0x00371d10, -0x24476ff7, 0x80289fde, 0x00605003, 0x40131017, -0x0014fc00, 0x01701e21, 0x0001f627, 0x10874022, -0x08570517, 0x00371d07, 0x24476ff7, 0xa8119fde, -0xf262a820, 0xd3000014, 0x1081e004, 0xfc211102, -0x05010300, 0xd2000521, 0x1c31e008, 0xfc000060, -0xf2610014, 0x70200018, 0x11011a00, 0x1c210501, -0xe00cd100, 0xf020a81a, 0x1c100028, 0xe010d100, -0x002cf020, 0xd1001c10, 0xf020e014, 0x1c100030, -0xd1005010, 0x1c10e018, 0xa845a83f, 0xa0704206, -0xac454e06, 0xd500ac3f, 0x5014e000, 0xa84d1857, -0x04470804, 0x901e2807, 0xac21ac32, 0xac1bac28, -0xfd04faff, 0xa828ac0d, 0xa832a821, 0xfa00a81b, -0x80240032, 0x2805ac32, 0x901cac28, 0x1811ac21, -0xa832a828, 0x0286fa00, 0xa828a830, 0x4ff5a821, -0x40412905, 0xa83f9fe8, 0x5010a845, 0xa0704206, -0xac654d06, 0xac22ac5f, 0xd100ac19, 0xfc44e808, -0xfc34fdff, 0x2623ffff, 0x04421812, 0x0200fc44, -0xd2001c12, 0x5001e804, 0xa86c1c24, 0x9014ac2c, -0x90322803, 0x90382913, 0xf000d100, 0x0268f011, -0x28338052, 0x29439038, 0xd200903e, 0xf021f000, -0xa8230274, 0x903c2913, 0x0278f022, 0xe010d300, -0x80301c32, 0xf000d100, 0x0264f011, 0x29238026, -0xd1009022, 0xf011f000, 0x8018026c, 0xf000d100, -0x0270f011, 0x2953800e, 0xd100900a, 0xf011f000, -0xd200027c, 0x1c21e00c, 0x2801a829, 0xa821911a, -0xd4005003, 0x1081e400, 0xac110501, 0xa8190030, -0xe004d500, 0x01011020, 0x00011810, 0x1101a812, -0x1c520512, 0x2911a821, 0x1300900a, 0xe008d100, -0xd0001c10, 0x5011e018, 0x1c01ac33, 0xfc401841, -0x04010400, 0x9ff62801, 0x04011841, 0x28015010, -0xfc4190bc, 0xd2000400, 0xac50e804, 0xe084d000, -0x1c21ac49, 0xe080d100, 0x18155012, 0xe088d100, -0x60f5ac45, 0xac381800, 0x00501c12, 0x00aefa00, -0x90742910, 0x1025a844, 0xf000d100, 0x0100fc42, -0x00400151, 0x0280f011, 0x0300fc20, 0x28010421, -0xd2009016, 0x1384f418, 0xf2230152, 0x1a220002, -0x1f341f24, 0xd2008014, 0x1304f418, 0xf2230152, -0x1a220002, 0x1d341d24, 0x902c2800, 0xf418d000, -0x01502801, 0xf2019016, 0x1a000002, 0xfc22a83a, -0x1282ff00, 0x1f121f02, 0xf201800e, 0x1a000002, -0x1d02a83a, 0xd4001d12, 0x1840e400, 0x0410a849, -0xa8502800, 0x2c409008, 0x9f484010, 0xa828a833, -0x21034013, 0xfc409ef8, 0xd1000200, 0x1c10e804, -0xa85f5010, 0x4306a865, 0xd200a070, 0x0001f000, -0x00231020, 0x50100103, 0x0280f033, 0x28036033, -0x29239078, 0x0014904c, 0xd3001021, 0x0112f376, -0xf0211014, 0x01430280, 0x12415094, 0x40a16031, -0x081460f1, 0xe404d100, 0x04141811, 0x904c2804, -0x50001a31, 0x90422801, 0x1000fc10, 0x90442101, -0x0280f020, 0xfc201280, 0x1d300fff, 0xa0705010, -0x90242913, 0x01121021, 0xf0205091, 0xd2000280, -0x1240e404, 0x40a06030, 0x080160f0, 0x04011820, -0xa3002901, 0x5000a070, 0xfc11a070, 0x1d311000, -0x4ff1a070, 0x1d315010, 0x4ec6a070, 0xac27ac2d, -0xac19ac12, 0xfaff0005, 0x2910ff54, 0x10259024, -0xf418d100, 0xf2100151, 0x1a110002, 0x2802a812, -0xa81a900a, 0x1c021c12, 0xa81a8008, 0x1d021d12, -0xa82da827, 0xa0704146, 0xac3d4e46, 0x0004ac37, -0x29051845, 0xd000901e, 0x2801e404, 0x00171803, -0xe410d000, 0x180290a0, 0x28036043, 0x704290b4, -0x2915809e, 0x00179332, 0x0004f641, 0x00126ff1, -0x10220040, 0xf6020120, 0xf6030019, 0x21230018, -0x10519026, 0xf000d200, 0xf0210112, 0xf0220020, -0x13010020, 0x67f11382, 0xf70161f2, 0x01210018, -0xf7014011, 0xac170019, 0xe444d200, 0x28075041, -0x08711823, 0xf000d700, 0xd1000513, 0x1c23d800, -0xd400d300, 0xa512a432, 0xf6410023, 0x00450004, -0x76c30074, 0x01141051, 0x0020f041, 0x1c345004, -0xfc240014, 0x28040400, 0xfc21902e, 0xfc3103ff, -0x80261000, 0x60231802, 0x91102803, 0x1c027022, -0xe804d000, 0x0400fc11, 0x50001c01, 0x0524f800, -0xac245fb1, 0x67f180fa, 0x1c217042, 0x50015012, -0xd2001c32, 0xf604d410, 0xac250018, 0x0017f754, -0x0005f751, 0xd1000003, 0xac1bd810, 0x2800a810, -0xa5120030, 0x0019f601, 0xac296ff1, 0xa82b0041, -0x25136ff1, 0x4014915a, 0xf7041011, 0x00740018, -0xf2470114, 0xf2450160, 0x12c50160, 0x00516075, -0x0160f243, 0xfc234011, 0x28030100, 0xa8209010, -0x0005f603, 0xf7030113, 0xa8180005, 0x0160fc04, -0x29030e53, 0xfc279008, 0x802607ff, 0x28210073, -0x05fffc23, 0x90161c23, 0x90122815, 0x4ff50071, -0x01fffc21, 0x1c214ff5, 0x9ffa2905, 0x03fffc27, -0xd7001c27, 0x1a41f000, 0x0018f604, 0x0800fc21, -0x9f7a2801, 0x0019f601, 0x90d42541, 0xd2001014, -0x0147c000, 0x0160f271, 0xe000fc21, 0x90ba2121, -0x0160fc07, 0x6ff11a71, 0xf5014011, 0xf601001a, -0x40110018, 0x0018f701, 0xac2480a6, 0x04125fd1, -0xe400d100, 0x50001c02, 0xfc211811, 0x280103ff, -0x0410f900, 0x280750a2, 0xd5005143, 0xa424f000, -0xf053a534, 0x0943000c, 0xf356d400, 0x00310413, -0x61f10045, 0x1e510115, 0x900a2951, 0x01341253, -0x40511e41, 0x903c2021, 0xd4005013, 0x5012e804, -0x1c430813, 0xa8230014, 0x01431024, 0x001af234, -0x90202804, 0xe408d100, 0xa8251814, 0x0004f655, -0x05420852, 0xf2311c12, 0x4ff1001a, 0x001af531, -0x001283a0, 0x6ff250a3, 0x93962032, 0x5010a824, -0x0004f741, 0x8dc61c40, 0xf5015001, 0xa824001a, -0x0005f640, 0x90162800, 0xd200a813, 0xd100d438, -0x4ff0d838, 0xa5122803, 0x80141c20, 0xd100a812, -0xd000d438, 0x2802d838, 0xa50151f2, 0xd0001c12, -0x1800e404, 0x0200fc20, 0x908e2800, 0xe41bd000, -0xd5005011, 0x1f01e408, 0xf6431852, 0x41030004, -0xd3000831, 0x0521e808, 0xfff8fc42, 0xfffffc32, -0xfc411c51, 0xfc31ffff, 0xfc151fff, 0xa8104000, -0xa5212800, 0x28001832, 0x1c320412, 0x2000fc13, -0x0001fc42, 0xd300a431, 0xa521e804, 0x8000d200, -0x1c312800, 0x0004fc41, 0x2800a512, 0x0002fc41, -0xa4521c32, 0xa5125005, 0xf6421c32, 0x00410004, -0x01211022, 0x001af515, 0x0017f642, 0x0018f712, -0x0de0fa00, 0x801ca824, 0xd100a812, 0xfc40e000, -0xd3000007, 0x5025e808, 0xa5012802, 0x05121832, -0x1c451c32, 0x2925a811, 0xd0009294, 0x0047e400, -0x18042801, 0x90220013, 0x0004fc42, 0x28040424, -0x1801902a, 0x0001fc42, 0x29010421, 0x1800901e, -0x0002fc41, 0x81c60410, 0x8000fc24, 0x900c2804, -0xfc211801, 0x28012000, 0x003291ae, 0xfffffc41, -0x1ffffc31, 0xfff8fc40, 0xfffffc30, 0xe808d300, -0x0004fc45, 0xac122802, 0x2802a501, 0x1830ac29, -0xfc110410, 0x1c302000, 0x0001fc40, 0xd300a414, -0xa5048000, 0xe804d000, 0x1c042802, 0x1c03a553, -0xf6150071, 0x28050005, 0xa810902e, 0xd410d500, -0xd810d700, 0xa5752800, 0x00725007, 0x40170010, -0x01206ff2, 0xf7021e52, 0x00700006, 0x0005f612, -0x24206ff0, 0xd0009fe6, 0x0017e404, 0xfc201800, -0x28000200, 0xd0009060, 0x5012e41b, 0xd0001f02, -0x1801e408, 0xac250075, 0x0004f657, 0x08724107, -0x1c020512, 0xe808d200, 0xa8291820, 0xd1000410, -0x1c20e804, 0xfc110017, 0xfc424000, 0x1c740002, -0x50031c73, 0x2800a810, 0x1c71a521, 0x0004f652, -0x10220051, 0xf5130121, 0xf652001a, 0xf7120017, -0x81600018, 0xd100a810, 0xd200d46c, 0x5004d86c, -0xa5212800, 0xd4001c14, 0x1c43e804, 0xe408d400, -0x18415013, 0xf6520075, 0x08230004, 0x05135042, -0x1c430802, 0xe444d400, 0x18420723, 0x1c420432, -0x0c50fa00, 0x50310050, 0xf000d300, 0xf6021c01, -0x00310004, 0x01211052, 0x0020f017, 0x12c10071, -0x28016031, 0x4ff19056, 0x12875012, 0xd1000812, -0x6307e414, 0x0724ac2a, 0x18120137, 0x02bcfc07, -0x60f40424, 0xf6041f14, 0x10540004, 0xf2340143, -0xf2330024, 0x60f40024, 0x01041243, 0x406460f3, -0x1e454013, 0x40144ff3, 0x1f752903, 0x9ff44017, -0x0532a82b, 0x1f1260f2, 0x0005800a, 0xf34cfaff, -0x50050050, 0x180080a6, 0x4000fc20, 0x90aa2800, -0xd46cd100, 0xd0002803, 0x5014d86c, 0x5000a501, -0xd1001c10, 0x0035e408, 0xac271812, 0xf6732805, -0x41030004, 0x05240834, 0xfc441c14, 0xfc34ffff, -0xfc411fff, 0xfc31fff8, 0xa442ffff, 0xe808d400, -0x1843a512, 0xfc412805, 0x04230001, 0xfc131c43, -0xfc142000, 0xa4324000, 0x8000d300, 0xd100a512, -0x2805e804, 0xfc421c12, 0xa5230004, 0xfc422805, -0x1c130002, 0xa523a443, 0xf6711c13, 0x00720004, -0x01121021, 0x001af520, 0x0017f670, 0x0018f720, -0xfa000050, 0xa8200b2e, 0x1c055005, 0xa3002905, -0xa83da837, 0xa07041c6, 0x1c755025, 0x48468ff0, -0xacf7acfd, 0xf000d500, 0xfa008006, 0x50030962, -0xf05180f0, 0x12c10260, 0x211260f1, 0xd00090e4, -0xf600f340, 0x6ff00003, 0x90d62900, 0x0260f050, -0xf80013b0, 0xf537092e, 0x5010001a, 0xd094d100, -0xd004d200, 0x1c105fd7, 0x50120021, 0x04701810, -0xd1001c10, 0x0013e408, 0xf6411830, 0x08120004, -0x1c320502, 0xe444d200, 0x18100021, 0x1c100470, -0x1c415031, 0x0004f640, 0x10500051, 0xf0130101, -0x00310020, 0x603112c1, 0x90102901, 0xfaff0040, -0xd300f1fa, 0x5007f3d8, 0xd7008372, 0x4ff1e414, -0x12835010, 0x63030810, 0x07021871, 0x60f20412, -0x00521f72, 0xf6430132, 0x00470004, 0xfc020054, -0x105302bc, 0xf2450134, 0x00730024, 0x0024f244, -0x60f51244, 0x60f40153, 0x40144063, 0x4ff41e35, -0x29044013, 0x40121f25, 0x05019ff4, 0xe414d000, -0xf000d500, 0xd3005007, 0x60f1f3d8, 0x830c1f01, -0x02fef250, 0xe404d100, 0xf5504010, 0x181002fe, -0x29006200, 0xd000900a, 0x1f03f330, 0xd0008020, -0x1e00f330, 0x90162900, 0xf330d000, 0x00015012, -0xf0501f12, 0x60f002c4, 0x0001f710, 0xe440d000, -0x00015082, 0x1d125000, 0x0836fa00, 0xfa005010, -0x54000830, 0xe440d100, 0xfaff1d10, 0x5010f2ba, -0xe440d100, 0xf3d8d400, 0x18401d10, 0x90802900, -0xe404d000, 0xe410d200, 0x18201801, 0x29016011, -0x5fe19248, 0xd1000410, 0x1c20e400, 0xfc211811, -0x280103ff, 0xf050929a, 0xd200000c, 0x0410f356, -0x61f10001, 0x1e210112, 0x900e2951, 0xd1001250, -0x0101f356, 0x40511e11, 0x200150a0, 0x5010901e, -0xe804d200, 0x1c200810, 0x00400012, 0x01201022, -0x001af202, 0xf9002902, 0x00100746, 0x6ff050a2, -0x924c2020, 0xf7415010, 0x1c400004, 0x2910800a, -0xf641923e, 0x6ff10004, 0x00430010, 0x01031020, -0x0019f630, 0x0018f632, 0x90242102, 0x00501051, -0xf0010110, 0xf0000020, 0x13010020, 0x67f11380, -0xf73161f0, 0x01010018, 0xf7314011, 0xd0000019, -0xd200e444, 0xd700d094, 0x0001d004, 0x70201810, -0xaca31c10, 0x50110023, 0x1c315fd2, 0x04201870, -0xd090d200, 0x1c211c70, 0xf6405002, 0x00510004, -0x01011050, 0x0020f010, 0xd098d100, 0x1c106ff0, -0xa8a31c32, 0x70201870, 0xf7421c70, 0xf6310005, -0xf7410018, 0xf6320017, 0x00100019, 0x25026ff0, -0x10109daa, 0x01054011, 0x0018f731, 0xf253acb5, -0xf2500160, 0xaca80160, 0xf25112c3, 0x00620160, -0x40136073, 0x0060fc02, 0x0100fc21, 0x90142801, -0x0005f641, 0x01320012, 0x0005f742, 0x01120042, -0x00354062, 0x5003acbb, 0xd7005004, 0xa8a8d008, -0x28056ff5, 0x6ff09014, 0x40115001, 0x00141c70, -0x24546ff4, 0x9ff4a8bc, 0xf33cd000, 0x18005007, -0xf9002800, 0xa8b00602, 0x0160fc00, 0x0047acb0, -0x6ff75005, 0x90062907, 0x80265004, 0xd00cd000, -0x60401800, 0x90182800, 0xd008d100, 0x18110020, -0x40150150, 0x00501f01, 0x24706ff0, 0x01529fe0, -0x50076ff4, 0x00400254, 0x28006ff0, 0xd000901e, -0x1800e404, 0x0200fc20, 0x90742900, 0xf33cd000, -0x18004013, 0x9fa82403, 0xd0008008, 0x1800f33c, -0xf9002030, 0xa8b00592, 0xf000d500, 0xf3d8d400, -0xa8a31a00, 0x0018f631, 0x0800fc20, 0x9ef82800, -0x0019f630, 0x9ca42510, 0x00501011, 0xc000d200, -0xf2010110, 0xfc210160, 0x2121e000, 0xfc009c8a, -0x1a000160, 0x40106ff0, 0x001af530, 0x0018f630, -0xf7304010, 0x8c740018, 0x1c207010, 0x50108058, -0xe41bd100, 0xd0001f10, 0xd300e408, 0x5012f3d8, -0xf000d500, 0x18400004, 0x0004f631, 0x08124101, -0x1c420502, 0x0004f630, 0x10200031, 0xf5170101, -0xf630001a, 0xf7100017, 0x1c370018, 0xe404d000, -0x60101800, 0x90182800, 0xe410d000, 0x18100001, -0x1c107010, 0xe804d000, 0x0400fc11, 0xd0001c01, -0x5401e440, 0xfaff1d01, 0x5020efde, 0xe440d100, -0xd0001d10, 0x5001f4b8, 0xf5b0faff, 0xe440d000, -0x1d015401, 0xefc0faff, 0xd1005040, 0x1d10e440, -0xf4b8d000, 0x44005011, 0xf590faff, 0xe440d000, -0x1d015401, 0xefa0faff, 0xd4005007, 0x5080e400, -0xe440d100, 0xf0511d10, 0xd2000260, 0xfc40f340, -0x01720100, 0xac8a0870, 0x1e200401, 0x90302901, -0x6ff10001, 0x90dc2911, 0x18420070, 0x41305011, -0x50000801, 0x28020412, 0x007290ca, 0xfc321022, -0x1823dc00, 0x04131843, 0x9ff82903, 0x007180b6, -0x41315012, 0xacaa0812, 0x6ff10001, 0xa6112801, -0xac81a501, 0xac970070, 0xaca01020, 0xdc00fc30, -0x5000ac98, 0x1840acb8, 0x0410a8a9, 0x90802800, -0x0260f055, 0x0905a8a0, 0x60f00050, 0xfa00acb0, -0x60b50638, 0xa8b52905, 0x0050901a, 0xfa004010, -0x00500628, 0xfa004020, 0x00500620, 0xfa004030, -0xa8980618, 0xe000d200, 0x50101801, 0xace10850, -0x04021822, 0x900e2902, 0x50026ff5, 0xfaff0050, -0x801cf46c, 0xeec0faff, 0x6ff55010, 0xac085002, -0xfc010061, 0x00500070, 0xfaffa893, 0xa8b8f1e6, -0xf000d500, 0xe400d400, 0x2c304010, 0xa8809f78, -0xa889a897, 0x29474017, 0x9efc1f10, 0xe440d000, -0x00055401, 0xfaff1d51, 0x5100ee7e, 0xf334d100, -0x1a101d50, 0x28005001, 0xacb9910a, 0xd3000010, -0x1010f538, 0xa8edace8, 0x01150030, 0x01501035, -0x1800aca8, 0x90922910, 0x01300050, 0x0016f604, -0x00320051, 0x01127051, 0x00511e20, 0x70410032, -0x01122804, 0xd2001e21, 0x1051f000, 0xf2210112, -0xacb10024, 0x0024f221, 0xaca09098, 0xfaffac99, -0xa89af31c, 0x2910a8a4, 0x12429088, 0x401260f2, -0x280261f2, 0xa8b0907c, 0x50017065, 0x015060f0, -0x5000acb0, 0x00420027, 0xf418d300, 0x10224010, -0xf2320123, 0x1a330002, 0xa8b40045, 0xd1000114, -0x0141f538, 0x1e110054, 0x1f211f31, 0x00010072, -0x24216ff1, 0x803a9fd0, 0x904e2920, 0xd1000050, -0x7060f538, 0x01010012, 0x0050acb1, 0x01027050, -0xfaffaca2, 0xa8a0eda2, 0xd2007045, 0x5003f538, -0x1e010152, 0xa8b21e20, 0xef06faff, 0x901a2910, -0xd200a8b9, 0x5010f334, 0x1a210810, 0x04010700, -0x50011d21, 0x1c01a8a8, 0x50a0a8b9, 0x21014011, -0xd0009efa, 0x5401e440, 0x1d510005, 0xed58faff, -0xd1005200, 0x5003f332, 0x1d505004, 0xf458d500, -0x28001a10, 0xacbc905e, 0x0004f050, 0x90122910, -0x000df652, 0xf6501851, 0xfaff000c, 0x8022f2d0, -0x2920a8bc, 0xfaff9036, 0xf053ed1e, 0xf6520008, -0xf650000d, 0x5011000c, 0x0051ac09, 0xf044faff, -0xd100a8bc, 0x5010f332, 0x00125003, 0x08401a21, -0x04010700, 0xf4531d21, 0x40140004, 0x29644105, -0xd0009fa6, 0xfc11e440, 0xd4000080, 0xd500e400, -0x1d01f000, 0x18401d01, 0x0263f651, 0xfc200002, -0x133203ff, 0x63f20412, 0x29020502, 0xd0009042, -0x1800e404, 0x29006100, 0xd0009036, 0x5fe1e444, -0x18500005, 0x1850acb8, 0x1c500410, 0xe8a6faff, -0xd400a8b8, 0x5003e400, 0xe804d200, 0x01f8fc41, -0x07fffc31, 0x1c507010, 0xf000d500, 0xd0001c21, -0x1800e404, 0x28006080, 0xf958f9ff, 0x02c4f051, -0xf34cd000, 0x60f11842, 0x03fffc22, 0x1e000110, -0x0013acb8, 0x10530054, 0x50130134, 0x0020f044, -0x00500813, 0xf0070035, 0xfc25000c, 0xfc2403ff, -0x04573000, 0x90062807, 0x908c2804, 0x000cf007, -0x045712a7, 0x90062807, 0x909a2804, 0x000cf007, -0x04571347, 0x90062807, 0x90ce2804, 0x0260f001, -0x0005a8ba, 0x60f11301, 0x901a2112, 0xf344d000, -0xf6005003, 0x29000002, 0xf8d8f9ff, 0x0260f050, -0x812e13c0, 0x0260f051, 0x13415003, 0x211260f1, -0xd0009018, 0xf600f344, 0x29000006, 0xf8b4f9ff, -0x0260f050, 0x810a13d0, 0x0260f051, 0x211260f1, -0xd0009056, 0x1e00f340, 0xf9ff2900, 0xf050f896, -0x13800260, 0x043280ec, 0x50030005, 0xf9ff2902, -0xd000f882, 0x1800f3d8, 0xf9ff2800, 0xd000f780, -0x801ef3d8, 0x00050432, 0x29025003, 0xf864f9ff, -0xf4b8d000, 0x28001800, 0xf762f9ff, 0xf4b8d000, -0x0004f600, 0xf0518046, 0x12410260, 0x211260f1, -0xd000907e, 0xf600f340, 0x29000001, 0xf834f9ff, -0x0260f050, 0x808a1390, 0x00050432, 0x29025003, -0xf820f9ff, 0xf4b8d000, 0x0040f000, 0xf9ff2800, -0xd000f71c, 0xf600f4b8, 0x20100044, 0xf804f9ff, -0xf70af8ff, 0xd1005010, 0x5fd2d094, 0xd1001c10, -0x1810d004, 0x1c100420, 0xfabef8ff, 0xe408d100, -0x00175013, 0xf6421871, 0x08230004, 0x1c730513, -0x001af201, 0xf5014ff1, 0xf8ff001a, 0xf051faf4, -0x12810260, 0x211260f1, 0xf6caf9ff, 0xf340d000, -0x0002f600, 0xf9ff2900, 0xf050f7aa, 0x13a00260, -0x29006010, 0xf79cf9ff, 0xf6a2f8ff, 0xe414d000, -0x60711801, 0x70820012, 0x1f011f02, 0x4dc6a070, -0xac47ac4d, 0xf000d200, 0x1000fc41, 0xf344d700, -0x0260f024, 0x00420801, 0x00010412, 0x10210073, -0x01132802, 0x0002f633, 0x6ff10031, 0x28019014, -0x00019042, 0x10210072, 0xf6250112, 0x80440003, -0x913e2911, 0x50140001, 0x41715003, 0xd1000814, -0x1812e400, 0x28020442, 0xd2009128, 0x0003dc80, -0x01231023, 0x18131833, 0x29030443, 0x50039ff2, -0x00018110, 0x50050072, 0x10215013, 0xf7250112, -0xac1b0003, 0x00720001, 0x10216ff5, 0x01122f85, -0xac3a1a22, 0x00019040, 0xd7005012, 0xd300dc80, -0x4171e400, 0x00010812, 0x1021ac20, 0x01740014, -0x04271837, 0x90b62807, 0xa8380057, 0x10274015, -0x01702c85, 0x1c071847, 0xd0009fe8, 0xf004f000, -0x80040260, 0x4101ac20, 0xac2c0914, 0x60f00040, -0xfa00ac30, 0xa82800e4, 0x290060b0, 0xa830901a, -0xfa004010, 0xa83000d4, 0xfa004020, 0xa83000cc, -0xfa004030, 0xa82000c4, 0x29005001, 0xd0009008, -0x1801de50, 0x5010ac29, 0xe000d200, 0x0810a831, -0x04011821, 0x90222801, 0xe96cfaff, 0xa830ac0d, -0xa825a82a, 0xa8390053, 0x6ff26ff0, 0xfaff4043, -0x0050ec92, 0x80285005, 0x90202805, 0xac38a838, -0x1801a838, 0xa82aa830, 0x6ff26ff0, 0xeedefaff, -0x4ff5a838, 0x40402905, 0x50059fe6, 0x0002a820, -0xf344d700, 0x00711022, 0xf7150121, 0xa81b0003, -0x01071020, 0x0002f773, 0xa84da847, 0xa0704246, -0xe404d100, 0x18112800, 0x60419012, 0x90262801, -0xe410d000, 0x70411801, 0x60218010, 0x90162801, -0xe410d000, 0x70211801, 0xd0001c01, 0xfc12e804, -0x1c020400, 0xd100a070, 0x0101f000, 0xf6111020, -0x00130314, 0x60130002, 0x2000fc02, 0x900e2803, -0xfc311011, 0xfc212000, 0x800621fc, 0xf338d100, -0xf418d300, 0x1d320103, 0x0002f531, 0x0000a070, +/**************************************************************************** + * Public Data + ****************************************************************************/ + +const unsigned long scu_isopprog_array[] = +{ + 0xf7f8d600, 0xa2024f86, 0x0001a200, 0x18004081, + 0x00008014, 0x00000000, 0x0000a207, 0x00000000, + 0x0000a070, 0xac2d4ec6, 0xd000ac27, 0x50a2e444, + 0x70111801, 0x50011c01, 0xf356d000, 0x0004800a, + 0x40110114, 0x50031f43, 0x9ff42801, 0x90062911, + 0x8fec5043, 0x00140003, 0x40640113, 0x1f344011, + 0x9fe42121, 0xd2005001, 0x5203f360, 0x50155004, + 0x04150845, 0x90082905, 0x2d444014, 0x00259ff2, + 0x40110115, 0x21311f54, 0xd1009fe4, 0x5ff2e824, + 0xe808d400, 0x01f8fc43, 0x07fffc33, 0xe804d000, + 0xf000d700, 0x1c431c12, 0xe800d100, 0x1c025013, + 0x0103fc40, 0x0300fc30, 0xf3e0d200, 0x1c135be4, + 0xe418d100, 0x1c105003, 0xf47250a1, 0x1c230300, + 0x0004f721, 0xf7235e61, 0xf7230005, 0xf7230016, + 0x00250017, 0x4fc10215, 0xf7531d53, 0xf753fffe, + 0x2141ffff, 0xd1009fee, 0xd209f33c, 0xd000ec00, + 0x5004f4c0, 0x1c125005, 0x0304f470, 0x44020002, + 0x0308f472, 0x41a10001, 0x00020053, 0x106350a7, + 0x1c240132, 0x0004f727, 0x0005f724, 0x0016f724, + 0x0017f724, 0x1d340013, 0xfffef734, 0xfffff734, + 0x40434ff7, 0x9ff02907, 0x44014015, 0x9fca2925, + 0xf34cd200, 0xd3005001, 0x5004f340, 0x0002f721, + 0xf3a0d200, 0x01450035, 0x1f514014, 0x9ff62944, + 0xd4005fe3, 0x5005f344, 0x00415f67, 0x4fc30231, + 0xfffef512, 0x1f154202, 0x9ff02173, 0xf334d200, + 0xf000d100, 0xd4005003, 0x5005f540, 0x030cf412, + 0xac115001, 0xa819ac19, 0x00470052, 0x00710112, + 0x01211032, 0x00201c13, 0x70407052, 0x1f450104, + 0x00740070, 0xf356d700, 0x01200157, 0x1e724015, + 0xf7131f02, 0xa8110016, 0x210550a0, 0x9fc44021, + 0xf380d000, 0x1000fc11, 0x00345f02, 0x4ff30005, + 0x21231014, 0x1d510245, 0x50029ff2, 0xf334d000, + 0xf000d700, 0xf460d300, 0x1d025004, 0xf332d000, + 0x0310f470, 0x00350041, 0x01151041, 0x0004f452, + 0x0008f454, 0xf7524014, 0xf752000c, 0x1c52000d, + 0x9fe22964, 0xd2005001, 0x1f21f330, 0x0001f721, + 0xf5711d01, 0xf77102fe, 0xfc4102fc, 0xfc312020, + 0xd2131214, 0x1c712825, 0x01cdfc41, 0x4cf8fc31, + 0x0004f472, 0xe412d200, 0x0008f471, 0x1f215011, + 0x0e98fa00, 0xa82da827, 0x41465000, 0x0000a070, + 0xac3d4e46, 0xf601ac37, 0x28010005, 0xf6029178, + 0xac200004, 0x10110021, 0xd100ac29, 0xa828f540, + 0x10300120, 0x7050ac18, 0x1e150101, 0xfa000050, + 0x005019a2, 0x29006fb0, 0x0050901a, 0xfa004010, + 0x00501992, 0xfa004020, 0x0050198a, 0xfa004030, + 0xd1001982, 0x5010e000, 0x08501811, 0x28010401, + 0xac15906c, 0x0128fa00, 0x5003a822, 0xf6205005, + 0xa8110004, 0xfa004062, 0xa8230290, 0xf540d400, + 0x91022900, 0x5021a818, 0xf334d700, 0x1c410104, + 0xf6305011, 0x1a720004, 0x05120801, 0xf6301d72, + 0xf7400005, 0x28000016, 0x500090dc, 0x00320041, + 0x01524010, 0xf6220151, 0xf7120006, 0x00050006, + 0x0005f632, 0x24256ff5, 0x80ba9fe4, 0xd100a822, + 0xf620e404, 0x18110004, 0x28016201, 0xd3009028, + 0x6ff0f330, 0x0001f631, 0x90222101, 0x6ff01e30, + 0x901a2910, 0x1702fa00, 0x5030a822, 0xf330d100, + 0x800a1f10, 0xf330d000, 0x1f015001, 0x0004f620, + 0xf000d100, 0x01011050, 0x0005f620, 0x0024f213, + 0xac1b2800, 0x0024f211, 0x905a0050, 0xac100015, + 0x0562fa00, 0x0053a814, 0x904a2910, 0x60f31243, + 0x61f34013, 0x903e2803, 0x5002a818, 0x60f05001, + 0x0030ac18, 0x00470043, 0xf420d400, 0x10234011, + 0xf2430134, 0x1a440002, 0x0152a81d, 0x0125a825, + 0x0006f652, 0x00741f42, 0x00031f32, 0x6ff20012, + 0x9fd02432, 0xa83da837, 0xa07041c6, 0xac454e06, + 0xd000ac3f, 0xfc41e400, 0x18000400, 0x28000410, + 0x5000915e, 0xfc41ac10, 0xd0000400, 0xac19e804, + 0xd1001c01, 0x1810e080, 0xe084d100, 0x00021811, + 0xf76260f2, 0x00620014, 0x0014fc02, 0x00040023, + 0x13007022, 0x70131284, 0x1f346034, 0xf5611d20, + 0x13010018, 0xe088d000, 0xf5615012, 0x1c02001a, + 0x0014f265, 0x6ff5ac25, 0xfa000050, 0xa8220498, + 0xf420d100, 0x90902910, 0xd0001025, 0x0017f000, + 0xfc411282, 0x01500100, 0xf0004012, 0x6ff20280, + 0x50010410, 0x903a2900, 0x50000075, 0x28020027, + 0xf6629066, 0x00530014, 0x40101011, 0x01231022, + 0x0002f232, 0x00641a33, 0x0014fc04, 0xf2410114, + 0x1d310002, 0x00011d21, 0x24716ff1, 0x80389fd6, + 0x50000075, 0x28020027, 0xf662902e, 0x00530014, + 0x40101011, 0x01231022, 0x0002f232, 0x00641a33, + 0x0014fc04, 0xf6410114, 0x1f310003, 0x00011f21, + 0x24716ff1, 0xd0009fd6, 0x1800e400, 0x0410a819, + 0x900c2800, 0x4010a810, 0x2c40ac10, 0xf6619efa, + 0x50000014, 0x90142c41, 0x4fc00010, 0x90062e30, + 0x80085010, 0x00fafc01, 0xd1000010, 0x1811e404, + 0x28016201, 0xd5009022, 0x6ff0f330, 0x0001f651, + 0x901c2101, 0x6ff01e50, 0x90142910, 0x150afa00, + 0x1f505030, 0xd000800a, 0x5001f330, 0xa83f1f01, + 0x4206a845, 0x4e06a070, 0xac3fac45, 0xe400d300, + 0xfc431834, 0x04340200, 0x90322804, 0xd400ac21, + 0x1841e404, 0x28016201, 0xd1009032, 0xf614f330, + 0x21040001, 0x1e11902e, 0x29316ff1, 0xd0009026, + 0xf001f000, 0x701102c8, 0x02c8f401, 0xe808d000, + 0x05311801, 0x50001c01, 0xd1008108, 0x5003f330, + 0x10501f13, 0xf000d100, 0xe808d300, 0xfdfffc45, + 0xfffffc35, 0x01015007, 0xf210ac19, 0x18340026, + 0xfc450454, 0x12c00200, 0xd3001c34, 0x1c35e804, + 0x0026f213, 0xf214ac10, 0xf2100026, 0xf2150026, + 0x12830026, 0x124512c4, 0x601060f3, 0x01326034, + 0x28006075, 0x902a4014, 0x00615003, 0x40131017, + 0x0014fc01, 0x01711e20, 0x0001f627, 0x10804022, + 0x08500570, 0x00371d10, 0x24476ff7, 0x80289fde, + 0x00605003, 0x40131017, 0x0014fc00, 0x01701e21, + 0x0001f627, 0x10874022, 0x08570517, 0x00371d07, + 0x24476ff7, 0xa8119fde, 0xf262a820, 0xd3000014, + 0x1081e004, 0xfc211102, 0x05010300, 0xd2000521, + 0x1c31e008, 0xfc000060, 0xf2610014, 0x70200018, + 0x11011a00, 0x1c210501, 0xe00cd100, 0xf020a81a, + 0x1c100028, 0xe010d100, 0x002cf020, 0xd1001c10, + 0xf020e014, 0x1c100030, 0xd1005010, 0x1c10e018, + 0xa845a83f, 0xa0704206, 0xac454e06, 0xd500ac3f, + 0x5014e000, 0xa84d1857, 0x04470804, 0x901e2807, + 0xac21ac32, 0xac1bac28, 0xfd04faff, 0xa828ac0d, + 0xa832a821, 0xfa00a81b, 0x80240032, 0x2805ac32, + 0x901cac28, 0x1811ac21, 0xa832a828, 0x0286fa00, + 0xa828a830, 0x4ff5a821, 0x40412905, 0xa83f9fe8, + 0x5010a845, 0xa0704206, 0xac654d06, 0xac22ac5f, + 0xd100ac19, 0xfc44e808, 0xfc34fdff, 0x2623ffff, + 0x04421812, 0x0200fc44, 0xd2001c12, 0x5001e804, + 0xa86c1c24, 0x9014ac2c, 0x90322803, 0x90382913, + 0xf000d100, 0x0268f011, 0x28338052, 0x29439038, + 0xd200903e, 0xf021f000, 0xa8230274, 0x903c2913, + 0x0278f022, 0xe010d300, 0x80301c32, 0xf000d100, + 0x0264f011, 0x29238026, 0xd1009022, 0xf011f000, + 0x8018026c, 0xf000d100, 0x0270f011, 0x2953800e, + 0xd100900a, 0xf011f000, 0xd200027c, 0x1c21e00c, + 0x2801a829, 0xa821911a, 0xd4005003, 0x1081e400, + 0xac110501, 0xa8190030, 0xe004d500, 0x01011020, + 0x00011810, 0x1101a812, 0x1c520512, 0x2911a821, + 0x1300900a, 0xe008d100, 0xd0001c10, 0x5011e018, + 0x1c01ac33, 0xfc401841, 0x04010400, 0x9ff62801, + 0x04011841, 0x28015010, 0xfc4190bc, 0xd2000400, + 0xac50e804, 0xe084d000, 0x1c21ac49, 0xe080d100, + 0x18155012, 0xe088d100, 0x60f5ac45, 0xac381800, + 0x00501c12, 0x00aefa00, 0x90742910, 0x1025a844, + 0xf000d100, 0x0100fc42, 0x00400151, 0x0280f011, + 0x0300fc20, 0x28010421, 0xd2009016, 0x1384f420, + 0xf2230152, 0x1a220002, 0x1f341f24, 0xd2008014, + 0x1304f420, 0xf2230152, 0x1a220002, 0x1d341d24, + 0x902c2800, 0xf420d000, 0x01502801, 0xf2019016, + 0x1a000002, 0xfc22a83a, 0x1282ff00, 0x1f121f02, + 0xf201800e, 0x1a000002, 0x1d02a83a, 0xd4001d12, + 0x1840e400, 0x0410a849, 0xa8502800, 0x2c409008, + 0x9f484010, 0xa828a833, 0x21034013, 0xfc409ef8, + 0xd1000200, 0x1c10e804, 0xa85f5010, 0x4306a865, + 0xd200a070, 0x0001f000, 0x00231020, 0x50100103, + 0x0280f033, 0x28036033, 0x29239078, 0x0014904c, + 0xd3001021, 0x0112f380, 0xf0211014, 0x01430280, + 0x12415094, 0x40a16031, 0x081460f1, 0xe404d100, + 0x04141811, 0x904c2804, 0x50001a31, 0x90422801, + 0x1000fc10, 0x90442101, 0x0280f020, 0xfc201280, + 0x1d300fff, 0xa0705010, 0x90242913, 0x01121021, + 0xf0205091, 0xd2000280, 0x1240e404, 0x40a06030, + 0x080160f0, 0x04011820, 0xa3002901, 0x5000a070, + 0xfc11a070, 0x1d311000, 0x4ff1a070, 0x1d315010, + 0x4ec6a070, 0xac27ac2d, 0xac19ac12, 0xfaff0005, + 0x2910ff54, 0x10259024, 0xf420d100, 0xf2100151, + 0x1a110002, 0x2802a812, 0xa81a900a, 0x1c021c12, + 0xa81a8008, 0x1d021d12, 0xa82da827, 0xa0704146, + 0xac3d4e46, 0x0004ac37, 0x0004f645, 0x29001840, + 0xd00090e2, 0x2801e404, 0xd0001802, 0x900ee410, + 0x60421803, 0x90222802, 0x800c7043, 0x60221803, + 0x901c2802, 0x1c037023, 0xe804d000, 0x0400fc11, + 0x50001c01, 0x0606f800, 0xac245fb2, 0xac248006, + 0x04235fd2, 0xe400d200, 0xac2d1c03, 0x18225000, + 0x03fffc22, 0xf9002802, 0x50a305e4, 0x51442801, + 0xf000d700, 0xa545a435, 0x000cf074, 0xd5000954, + 0x0424f360, 0x00570042, 0x012761f2, 0x29521e72, + 0x1254900a, 0x1e520145, 0x20324052, 0x5014903e, + 0xe804d500, 0x08245013, 0x00251c54, 0x1025a824, + 0xf2450154, 0x2805001a, 0xd1009022, 0x1812e408, + 0xf655a825, 0x08530004, 0x1c130523, 0x001af241, + 0xf5414ff1, 0xf800001a, 0x00230574, 0x6ff350a4, + 0xf9002043, 0xa8240568, 0xf7425010, 0x1c400004, + 0xac19a82d, 0xe404d000, 0x2000fc42, 0x04201800, + 0x90182800, 0xf000d000, 0x02c4f000, 0x215060f0, + 0x5005900a, 0xf8001c45, 0x18450530, 0x926e2915, + 0x0004f641, 0x00400012, 0x01201022, 0x0019f602, + 0x0018f603, 0x90262123, 0xd2001051, 0x0112f000, + 0x0020f021, 0x0020f022, 0x13821301, 0x61f267f1, + 0x0018f701, 0x40110121, 0x0019f701, 0xa8180007, + 0xe444d200, 0x18235041, 0x28000801, 0xd1000513, + 0x1c23d800, 0xd400d300, 0xa512a432, 0xf6410023, + 0x00450004, 0xf000d400, 0x105176c3, 0xf0410114, + 0x50040020, 0x00141c34, 0x0400fc24, 0x900c2804, + 0x03fffc21, 0x1000fc31, 0x67f18004, 0x50107042, + 0x1c21ac17, 0x50011c30, 0xd410d200, 0x0018f674, + 0xf754ac25, 0xf7510017, 0xd1000005, 0xa818d810, + 0x00702800, 0xf601a512, 0x6ff10019, 0x0041ac29, + 0x6ff1a82b, 0x90c02513, 0x10114014, 0x0018f704, + 0xf000d400, 0xf2470114, 0xf2450160, 0x12c50160, + 0x00516075, 0x0160f243, 0xfc234011, 0x28030100, + 0xa8209010, 0x0005f603, 0xf7030113, 0xa8100005, + 0x0160fc04, 0x29030e53, 0xfc279008, 0x802607ff, + 0x28210073, 0x05fffc23, 0x90161c23, 0x90122815, + 0x4ff50071, 0x01fffc21, 0x1c214ff5, 0x9ffa2905, + 0x03fffc27, 0x1a411c27, 0x0018f604, 0x0800fc21, + 0x9f7c2801, 0x0019f601, 0x903c2541, 0xd1001014, + 0xd200f000, 0x0141c000, 0xf2310013, 0xfc210160, + 0x2121e000, 0xfc03901c, 0x1a310160, 0x40116ff1, + 0x001af501, 0x0018f601, 0xf7014011, 0x80080018, + 0xf5015001, 0xa824001a, 0x0005f640, 0x90162800, + 0xd200a81b, 0xd100d438, 0x4ff0d838, 0xa5122803, + 0x80141c20, 0xd100a81a, 0xd000d438, 0x2802d838, + 0xa50151f2, 0xd0001c12, 0x1800e404, 0x0200fc20, + 0x908e2800, 0xe41bd000, 0xd5005011, 0x1f01e408, + 0xf6431852, 0x41030004, 0xd3000831, 0x0521e808, + 0xfff8fc42, 0xfffffc32, 0xfc411c51, 0xfc31ffff, + 0xfc151fff, 0xa8184000, 0xa5212800, 0x28001832, + 0x1c320412, 0x2000fc13, 0x0001fc42, 0xd300a431, + 0xa521e804, 0x8000d200, 0x1c312800, 0x0004fc41, + 0x2800a512, 0x0002fc41, 0xa4521c32, 0xa5125005, + 0xf6421c32, 0x00410004, 0x01211022, 0x001af515, + 0x0017f642, 0x0018f712, 0x0ec2fa00, 0x801ca824, + 0xd100a81a, 0xfc40e000, 0xd3000007, 0x5025e808, + 0xa5012802, 0x05121832, 0x1c451c32, 0x92b82925, + 0x0004f640, 0xd000ac28, 0x1801e400, 0x2802a81a, + 0xfc429010, 0x04210004, 0x90122801, 0x80321800, + 0x8000fc21, 0x90062801, 0x802e1800, 0xd200a81b, + 0xd100d400, 0x2803d800, 0xa517a427, 0x77810071, + 0xf6421811, 0x25120005, 0x180090b0, 0x900a2803, + 0x0002fc41, 0x80060410, 0x4000fc20, 0x5021a81d, + 0x917a2800, 0xd46cd100, 0xd0002805, 0xa501d86c, + 0x28055000, 0xd1001c10, 0x1812e408, 0x0004f643, + 0x50140047, 0x4103ac27, 0x05240834, 0xfc441c14, + 0xfc34ffff, 0xfc411fff, 0xfc31fff8, 0xa442ffff, + 0xe808d400, 0x1843a512, 0xfc412805, 0x04230001, + 0xfc131c43, 0xfc142000, 0xa4324000, 0x8000d300, + 0xd100a512, 0x2805e804, 0xfc421c12, 0xa5230004, + 0xfc422805, 0x1c130002, 0xa523a443, 0xf6711c13, + 0x00720004, 0x01121021, 0x001af520, 0x0017f670, + 0x0018f720, 0x80dc0050, 0xfffffc41, 0x1ffffc31, + 0xfc402803, 0xfc30fff8, 0xd200ffff, 0xfc15e808, + 0xa5012000, 0xac112803, 0x04101820, 0x00411c20, + 0xfc40a454, 0xd2000001, 0xfc45e804, 0xa5040004, + 0x8000d000, 0x1c242803, 0xa553a403, 0xf6151c23, + 0x28050005, 0x71079022, 0x00525005, 0x40150010, + 0x01206ff2, 0xf7021e72, 0x00500006, 0x0005f612, + 0x24206ff0, 0xd0009fe6, 0x0017e404, 0xfc201800, + 0x28000200, 0xd000914e, 0x5012e41b, 0xd0001f02, + 0x1801e408, 0xac250075, 0x0004f657, 0x08724107, + 0x1c020512, 0xe808d200, 0xa8111820, 0xd1000410, + 0x1c20e804, 0xfc110017, 0xfc424000, 0x1c740002, + 0x50031c73, 0x2800a818, 0x1c71a521, 0x0004f652, + 0x10220051, 0xf5130121, 0xf652001a, 0xf7120017, + 0x00050018, 0x0cc6fa00, 0x5001a824, 0xd1001c41, + 0x2805d400, 0xd0000057, 0xd200d800, 0xa501f000, + 0xf0220010, 0x73400010, 0x50001803, 0x28036403, + 0x001090aa, 0x18007800, 0x1000fc20, 0x90142800, + 0xd000a82b, 0x4012f34c, 0x1e000130, 0x24204010, + 0xd000901c, 0x1802e408, 0x0004f643, 0x50140045, + 0x08344103, 0x1c040524, 0x50000054, 0xfc427541, + 0xfc32ffff, 0x28071fff, 0x4000fc15, 0xfc411811, + 0xfc31fff8, 0xa512ffff, 0xe808d100, 0x18132807, + 0x1c130423, 0x2000fc13, 0x0001fc41, 0xd300a432, + 0xa5128000, 0xe804d100, 0x1c122807, 0x0004fc42, + 0x2807a523, 0x0002fc42, 0xa4531c13, 0xa5235005, + 0xf6411c13, 0x00420004, 0x01121021, 0x001af525, + 0x0017f643, 0x0018f723, 0xa82a1c45, 0xf34cd100, + 0x1f100121, 0x29051845, 0xa837a300, 0x41c6a83d, + 0xa818a070, 0xd46cd100, 0xd86cd200, 0x28005004, + 0x1c14a521, 0xe804d400, 0xd4001c43, 0x5013e408, + 0x00751841, 0x0004f652, 0x50420823, 0x08020513, + 0xd4001c43, 0x0723e444, 0x04321842, 0xfa001c42, + 0x00500b9c, 0xd3005031, 0x1c01f000, 0x0004f602, + 0x10520031, 0xf0170121, 0x00710020, 0x603112c1, + 0x90582801, 0x50124ff1, 0x08121287, 0xe414d100, + 0xac1a6307, 0x01370724, 0xfc071812, 0x042402bc, + 0x1f1460f4, 0x0004f604, 0x01431054, 0x0024f234, + 0x0024f233, 0x124360f4, 0x60f30104, 0x40134064, + 0x4ff31e45, 0x29034014, 0x40171f75, 0xa81b9ff4, + 0x60f20532, 0x00051f12, 0x00058008, 0xf184faff, + 0x1c505000, 0x8f240054, 0xacfd4846, 0xd500acf7, + 0x8006f000, 0x0962fa00, 0x80f05003, 0x0260f051, + 0x60f112c1, 0x90e42112, 0xf340d000, 0x0003f600, + 0x29006ff0, 0xf05090d6, 0x13b00260, 0x092ef800, + 0x001af537, 0xd1005010, 0xd200d094, 0x5fd7d004, + 0x00211c10, 0x18105012, 0x1c100470, 0xe408d100, + 0x18300013, 0x0004f641, 0x05020812, 0xd2001c32, + 0x0021e444, 0x04701810, 0x50311c10, 0xf6401c41, + 0x00510004, 0x01011050, 0x0020f013, 0x12c10031, + 0x29016031, 0x00409010, 0xf0e8faff, 0xf3e0d300, + 0x83725007, 0xe414d700, 0x50104ff1, 0x08101283, + 0x18716303, 0x04120702, 0x1f7260f2, 0x01320052, + 0x0004f643, 0x00540047, 0x02bcfc02, 0x01341053, + 0x0024f245, 0xf2440073, 0x12440024, 0x015360f5, + 0x406360f4, 0x1e354014, 0x40134ff4, 0x1f252904, + 0x9ff44012, 0xd0000501, 0xd500e414, 0x5007f000, + 0xf3e0d300, 0x1f0160f1, 0xf250830c, 0xd10002fe, + 0x4010e404, 0x02fef550, 0x62001810, 0x900a2900, + 0xf330d000, 0x80201f03, 0xf330d000, 0x29001e00, + 0xd0009016, 0x5012f330, 0x1f120001, 0x02c4f050, + 0xf71060f0, 0xd0000001, 0x5082e440, 0x50000001, + 0xfa001d12, 0x50100836, 0x0830fa00, 0xd1005400, + 0x1d10e440, 0xf1a8faff, 0xd1005010, 0xd400e440, + 0x1d10f3e0, 0x29001840, 0xd0009080, 0xd200e404, + 0x1801e410, 0x60111820, 0x92482901, 0x04105fe1, + 0xe400d100, 0x18111c20, 0x03fffc21, 0x929a2801, + 0x000cf050, 0xf360d200, 0x00010410, 0x011261f1, + 0x29511e21, 0x1250900e, 0xf360d100, 0x1e110101, + 0x50a04051, 0x901e2001, 0xd2005010, 0x0810e804, + 0x00121c20, 0x10220040, 0xf2020120, 0x2902001a, + 0x0746f900, 0x50a20010, 0x20206ff0, 0x5010924c, + 0x0004f741, 0x800a1c40, 0x923e2910, 0x0004f641, + 0x00106ff1, 0x10200043, 0xf6300103, 0xf6320019, + 0x21020018, 0x10519024, 0x01100050, 0x0020f001, + 0x0020f000, 0x13801301, 0x61f067f1, 0x0018f731, + 0x40110101, 0x0019f731, 0xe444d000, 0xd094d200, + 0xd004d700, 0x18100001, 0x1c107020, 0x0023aca3, + 0x5fd25011, 0x18701c31, 0xd2000420, 0x1c70d090, + 0x50021c21, 0x0004f640, 0x10500051, 0xf0100101, + 0xd1000020, 0x6ff0d098, 0x1c321c10, 0x1870a8a3, + 0x1c707020, 0x0005f742, 0x0018f631, 0x0017f741, + 0x0019f632, 0x6ff00010, 0x9daa2502, 0x40111010, + 0xf7310105, 0xacb50018, 0x0160f253, 0x0160f250, + 0x12c3aca8, 0x0160f251, 0x60730062, 0xfc024013, + 0xfc210060, 0x28010100, 0xf6419014, 0x00120005, + 0xf7420132, 0x00420005, 0x40620112, 0xacbb0035, + 0x50045003, 0xd008d700, 0x6ff5a8a8, 0x90142805, + 0x50016ff0, 0x1c704011, 0x6ff40014, 0xa8bc2454, + 0xd0009ff4, 0x5007f33c, 0x28001800, 0x0602f900, + 0xfc00a8b0, 0xacb00160, 0x50050047, 0x29076ff7, + 0x50049006, 0xd0008026, 0x1800d00c, 0x28006040, + 0xd1009018, 0x0020d008, 0x01501811, 0x1f014015, + 0x6ff00050, 0x9fe02470, 0x6ff40152, 0x02545007, + 0x6ff00040, 0x901e2800, 0xe404d000, 0xfc201800, + 0x29000200, 0xd0009074, 0x4013f33c, 0x24031800, + 0x80089fa8, 0xf33cd000, 0x20301800, 0x0592f900, + 0xd500a8b0, 0xd400f000, 0x1a00f3e0, 0xf631a8a3, + 0xfc200018, 0x28000800, 0xf6309ef8, 0x25100019, + 0x10119ca4, 0xd2000050, 0x0110c000, 0x0160f201, + 0xe000fc21, 0x9c8a2121, 0x0160fc00, 0x6ff01a00, + 0xf5304010, 0xf630001a, 0x40100018, 0x0018f730, + 0x70108c74, 0x80581c20, 0xd1005010, 0x1f10e41b, + 0xe408d000, 0xf3e0d300, 0xd5005012, 0x0004f000, + 0xf6311840, 0x41010004, 0x05020812, 0xf6301c42, + 0x00310004, 0x01011020, 0x001af517, 0x0017f630, + 0x0018f710, 0xd0001c37, 0x1800e404, 0x28006010, + 0xd0009018, 0x0001e410, 0x70101810, 0xd0001c10, + 0xfc11e804, 0x1c010400, 0xe440d000, 0x1d015401, + 0xeeccfaff, 0xd1005020, 0x1d10e440, 0xf4c0d000, + 0xfaff5001, 0xd000f49e, 0x5401e440, 0xfaff1d01, + 0x5040eeae, 0xe440d100, 0xd0001d10, 0x5011f4c0, + 0xfaff4400, 0xd000f47e, 0x5401e440, 0xfaff1d01, + 0x5007ee8e, 0xe400d400, 0xd1005080, 0x1d10e440, + 0x0260f051, 0xf340d200, 0x0100fc40, 0x08700172, + 0x0401ac8a, 0x29011e20, 0x00019030, 0x29116ff1, + 0x007090dc, 0x50111842, 0x08014130, 0x04125000, + 0x90ca2802, 0x10220072, 0xdc00fc32, 0x18431823, + 0x29030413, 0x80b69ff8, 0x50120071, 0x08124131, + 0x0001acaa, 0x28016ff1, 0xa501a611, 0x0070ac81, + 0x1020ac97, 0xfc30aca0, 0xac98dc00, 0xacb85000, + 0xa8a91840, 0x28000410, 0xf0559080, 0xa8a00260, + 0x00500905, 0xacb060f0, 0x0638fa00, 0x290560b5, + 0x901aa8b5, 0x40100050, 0x0628fa00, 0x40200050, + 0x0620fa00, 0x40300050, 0x0618fa00, 0xd200a898, + 0x1801e000, 0x08505010, 0x1822ace1, 0x29020402, + 0x6ff5900e, 0x00505002, 0xf35afaff, 0xfaff801c, + 0x5010edae, 0x50026ff5, 0x0061ac08, 0x0070fc01, + 0xa8930050, 0xf0d4faff, 0xd500a8b8, 0xd400f000, + 0x4010e400, 0x9f782c30, 0xa897a880, 0x4017a889, + 0x1f102947, 0xd0009efc, 0x5401e440, 0x1d510005, + 0xed6cfaff, 0xd1005100, 0x1d50f334, 0x50011a10, + 0x910a2800, 0x0010acb9, 0xf540d300, 0xace81010, + 0x0030a8ed, 0x10350115, 0xaca80150, 0x29101800, + 0x00509092, 0xf6040130, 0x00510016, 0x70510032, + 0x1e200112, 0x00320051, 0x28047041, 0x1e210112, + 0xf000d200, 0x01121051, 0x0024f221, 0xf221acb1, + 0x90980024, 0xac99aca0, 0xf20afaff, 0xa8a4a89a, + 0x90882910, 0x60f21242, 0x61f24012, 0x907c2802, + 0x7065a8b0, 0x60f05001, 0xacb00150, 0x00275000, + 0xd3000042, 0x4010f420, 0x01231022, 0x0002f232, + 0x00451a33, 0x0114a8b4, 0xf540d100, 0x00540141, + 0x1f311e11, 0x00721f21, 0x6ff10001, 0x9fd02421, + 0x2920803a, 0x0050904e, 0xf540d100, 0x00127060, + 0xacb10101, 0x70500050, 0xaca20102, 0xec90faff, + 0x7045a8a0, 0xf540d200, 0x01525003, 0x1e201e01, + 0xfaffa8b2, 0x2910edf4, 0xa8b9901a, 0xf334d200, + 0x08105010, 0x07001a21, 0x1d210401, 0xa8a85001, + 0xa8b91c01, 0x401150a0, 0x9efa2101, 0xe440d000, + 0x00055401, 0xfaff1d51, 0x5200ec46, 0xf332d100, + 0x50045003, 0xd5001d50, 0x1a10f460, 0x905e2800, + 0xf050acbc, 0x29100004, 0xf6529012, 0x1851000d, + 0x000cf650, 0xf1befaff, 0xa8bc8022, 0x90362920, + 0xec0cfaff, 0x0008f053, 0x000df652, 0x000cf650, + 0xac095011, 0xfaff0051, 0xa8bcef32, 0xf332d100, + 0x50035010, 0x1a210012, 0x07000840, 0x1d210401, + 0x0004f453, 0x41054014, 0x9fa62964, 0xe440d000, + 0x0080fc11, 0xe400d400, 0xf000d500, 0x1d011d01, + 0xf6511840, 0x00020263, 0x03fffc20, 0x04121332, + 0x050263f2, 0x90422902, 0xe404d000, 0x61001800, + 0x90362900, 0xe444d000, 0x00055fe1, 0xacb81850, + 0x04101850, 0xfaff1c50, 0xa8b8e78c, 0xe400d400, + 0xd2005003, 0xfc41e804, 0xfc3101f8, 0x701007ff, + 0xd5001c50, 0x1c21f000, 0xe404d000, 0x60801800, + 0xf9ff2800, 0xf051f958, 0xd00002c4, 0x1842f356, + 0xfc2260f1, 0x011003ff, 0xacb81e00, 0x00540013, + 0x01341053, 0xf0445013, 0x08130020, 0x00350050, + 0x000cf007, 0x03fffc25, 0x3000fc24, 0x28070457, + 0x28049006, 0xf007908c, 0x12a7000c, 0x28070457, + 0x28049006, 0xf007909a, 0x1347000c, 0x28070457, + 0x28049006, 0xf00190ce, 0xa8ba0260, 0x13010005, + 0x211260f1, 0xd000901a, 0x5003f344, 0x0002f600, + 0xf9ff2900, 0xf050f8d8, 0x13c00260, 0xf051812e, + 0x50030260, 0x60f11341, 0x90182112, 0xf344d000, + 0x0006f600, 0xf9ff2900, 0xf050f8b4, 0x13d00260, + 0xf051810a, 0x60f10260, 0x90562112, 0xf340d000, + 0x29001e00, 0xf896f9ff, 0x0260f050, 0x80ec1380, + 0x00050432, 0x29025003, 0xf882f9ff, 0xf3e0d000, + 0x28001800, 0xf780f9ff, 0xf3e0d000, 0x0432801e, + 0x50030005, 0xf9ff2902, 0xd000f864, 0x1800f4c0, + 0xf9ff2800, 0xd000f762, 0xf600f4c0, 0x80460004, + 0x0260f051, 0x60f11241, 0x907e2112, 0xf340d000, + 0x0001f600, 0xf9ff2900, 0xf050f834, 0x13900260, + 0x0432808a, 0x50030005, 0xf9ff2902, 0xd000f820, + 0xf000f4c0, 0x28000040, 0xf71cf9ff, 0xf4c0d000, + 0x0044f600, 0xf9ff2010, 0xf8fff804, 0x5010f70a, + 0xd094d100, 0x1c105fd2, 0xd004d100, 0x04201810, + 0xf8ff1c10, 0xd100fabe, 0x5013e408, 0x18710017, + 0x0004f642, 0x05130823, 0xf2011c73, 0x4ff1001a, + 0x001af501, 0xfaf4f8ff, 0x0260f051, 0x60f11281, + 0xf9ff2112, 0xd000f6ca, 0xf600f340, 0x29000002, + 0xf7aaf9ff, 0x0260f050, 0x601013a0, 0xf9ff2900, + 0xf8fff79c, 0xd000f6a2, 0x1801e414, 0x00126071, + 0x1f027082, 0xa0701f01, 0xac4d4dc6, 0xd200ac47, + 0xfc41f000, 0xd7001000, 0xf024f344, 0x08010260, + 0x04120042, 0x00730001, 0x28021021, 0xf6330113, + 0x00310002, 0x90146ff1, 0x90422801, 0x00720001, + 0x01121021, 0x0003f625, 0x29118044, 0x0001913e, + 0x50035014, 0x08144171, 0xe400d100, 0x04421812, + 0x91282802, 0xdc80d200, 0x10230003, 0x18330123, + 0x04431813, 0x9ff22903, 0x81105003, 0x00720001, + 0x50135005, 0x01121021, 0x0003f725, 0x0001ac1b, + 0x6ff50072, 0x2f851021, 0x1a220112, 0x9040ac3a, + 0x50120001, 0xdc80d700, 0xe400d300, 0x08124171, + 0xac200001, 0x00141021, 0x18370174, 0x28070427, + 0x005790b6, 0x4015a838, 0x2c851027, 0x18470170, + 0x9fe81c07, 0xf000d000, 0x0260f004, 0xac208004, + 0x09144101, 0x0040ac2c, 0xac3060f0, 0x00e4fa00, + 0x60b0a828, 0x901a2900, 0x4010a830, 0x00d4fa00, + 0x4020a830, 0x00ccfa00, 0x4030a830, 0x00c4fa00, + 0x5001a820, 0x90082900, 0xde50d000, 0xac291801, + 0xd2005010, 0xa831e000, 0x18210810, 0x28010401, + 0xfaff9022, 0xac0de85a, 0xa82aa830, 0x0053a825, + 0x6ff0a839, 0x40436ff2, 0xeb80faff, 0x50050050, + 0x28058028, 0xa8389020, 0xa838ac38, 0xa8301801, + 0x6ff0a82a, 0xfaff6ff2, 0xa838edcc, 0x29054ff5, + 0x9fe64040, 0xa8205005, 0xd7000002, 0x1022f344, + 0x01210071, 0x0003f715, 0x1020a81b, 0xf7730107, + 0xa8470002, 0x4246a84d, 0xd100a070, 0x2800e404, + 0x90121811, 0x28016041, 0xd0009026, 0x1801e410, + 0x80107041, 0x28016021, 0xd0009016, 0x1801e410, + 0x1c017021, 0xe804d000, 0x0400fc12, 0xa0701c02, + 0xf000d100, 0x10200101, 0x0314f611, 0x00020013, + 0xfc026013, 0x28032000, 0x1011900e, 0x2000fc31, + 0x21fcfc21, 0xd1008006, 0xd300f338, 0x0103f420, + 0xf5311d32, 0xa0700002, }; -const unsigned long sizeof_scu_isopprog_array = 7024; /* 0x00001b70 */ + +const unsigned long sizeof_scu_isopprog_array = 7304; /* 0x00001c88 */ diff --git a/arch/arm/src/cxd56xx/hardware/cxd56_scu.h b/arch/arm/src/cxd56xx/hardware/cxd56_scu.h index 8372f9dbd2a..56010c34489 100644 --- a/arch/arm/src/cxd56xx/hardware/cxd56_scu.h +++ b/arch/arm/src/cxd56xx/hardware/cxd56_scu.h @@ -36,12 +36,8 @@ #ifndef __ARCH_ARM_SRC_CXD56XX_HARDWARE_CXD56_SCU_H #define __ARCH_ARM_SRC_CXD56XX_HARDWARE_CXD56_SCU_H -#define SCU_PWM0_PARAM (CXD56_SCU_BASE + 0x0000) -#define SCU_PWM0_EN (CXD56_SCU_BASE + 0x0004) -#define SCU_PWM0_UPDATE (CXD56_SCU_BASE + 0x0008) -#define SCU_PWM1_PARAM (CXD56_SCU_BASE + 0x000c) -#define SCU_PWM1_EN (CXD56_SCU_BASE + 0x0010) -#define SCU_PWM1_UPDATE (CXD56_SCU_BASE + 0x0014) +#define SCU_DEBUG_I2C0 (CXD56_SCU_BASE + 0x0018) +#define SCU_DEBUG_I2C1 (CXD56_SCU_BASE + 0x001c) #define SCU_SEQ_ENABLE_ALL (CXD56_SCU_BASE + 0x0020) #define SCU_SEQ_ACCESS_INHIBIT (CXD56_SCU_BASE + 0x0024) #define SCU_START_CTRL_COMMON (CXD56_SCU_BASE + 0x0028) @@ -193,5 +189,12 @@ #define SCU_INT_RAW_STT_ERR_2 (CXD56_SCU_BASE + 0x046c) #define SCU_INT_MASKED_STT_ERR_2 (CXD56_SCU_BASE + 0x0470) #define SCU_RAM_TEST (CXD56_SCU_BASE + 0x0500) +#define SCU_POWER (CXD56_SCU_BASE + 0x0510) +#define SCU_INT_ENABLE_MAIN_AD (CXD56_SCU_BASE + 0x0520) +#define SCU_INT_DISABLE_MAIN_AD (CXD56_SCU_BASE + 0x0524) +#define SCU_INT_CLEAR_MAIN_AD (CXD56_SCU_BASE + 0x0528) +#define SCU_INT_LEVEL_SEL_MAIN_AD (CXD56_SCU_BASE + 0x052c) +#define SCU_INT_RAW_STT_MAIN_AD (CXD56_SCU_BASE + 0x0530) +#define SCU_INT_MASKED_STT_MAIN_AD (CXD56_SCU_BASE + 0x0534) #endif /* __ARCH_ARM_SRC_CXD56XX_HARDWARE_CXD56_SCU_H */ diff --git a/arch/arm/src/cxd56xx/hardware/cxd56_scuseq.h b/arch/arm/src/cxd56xx/hardware/cxd56_scuseq.h index 323f6734c3b..57e5e01448f 100644 --- a/arch/arm/src/cxd56xx/hardware/cxd56_scuseq.h +++ b/arch/arm/src/cxd56xx/hardware/cxd56_scuseq.h @@ -36,7 +36,11 @@ #ifndef __ARCH_ARM_SRC_CXD56XX_HARDWARE_CXD56_SCUSEQ_H #define __ARCH_ARM_SRC_CXD56XX_HARDWARE_CXD56_SCUSEQ_H +#define SCUSEQ_SW_REVISION_DATE (CXD56_SCU_SEQ_DRAM_BASE + 0x000) +#define SCUSEQ_SW_REVISION_TIME (CXD56_SCU_SEQ_DRAM_BASE + 0x004) +#define SCUSEQ_SW_REVISION_GIT_HASH (CXD56_SCU_SEQ_DRAM_BASE + 0x008) #define SCUSEQ_SRC_SEL (CXD56_SCU_SEQ_DRAM_BASE + 0x00c) +#define SCUSEQ_REPEAT_TXABORT (CXD56_SCU_SEQ_DRAM_BASE + 0x010) #define SCUSEQ_PROPERTY(s) (CXD56_SCU_SEQ_DRAM_BASE + 0x020 + ((s) * 0x20)) #define SCUSEQ_OUT_FORMAT(s) (CXD56_SCU_SEQ_DRAM_BASE + 0x024 + ((s) * 0x20)) #define SCUSEQ_MATH_PROC_OFST_GAIN_X(s) (CXD56_SCU_SEQ_DRAM_BASE + 0x028 + ((s) * 0x20)) diff --git a/boards/arm/cxd56xx/common/src/Make.defs b/boards/arm/cxd56xx/common/src/Make.defs index 2e3e0cc56b1..4d518a1e5ed 100644 --- a/boards/arm/cxd56xx/common/src/Make.defs +++ b/boards/arm/cxd56xx/common/src/Make.defs @@ -126,6 +126,10 @@ ifeq ($(CONFIG_WL_GS2200M),y) CSRCS += cxd56_gs2200m.c endif +ifeq ($(CONFIG_NET_WIZNET),y) +CSRCS += cxd56_wiznet.c +endif + ifeq ($(CONFIG_LCD_ILI9340),y) CSRCS += cxd56_ili9340.c endif diff --git a/boards/arm/cxd56xx/common/src/cxd56_altmdm.c b/boards/arm/cxd56xx/common/src/cxd56_altmdm.c index b02c93438aa..79a3560914c 100644 --- a/boards/arm/cxd56xx/common/src/cxd56_altmdm.c +++ b/boards/arm/cxd56xx/common/src/cxd56_altmdm.c @@ -1,7 +1,7 @@ /**************************************************************************** * boards/arm/cxd56xx/common/src/cxd56_altmdm.c * - * Copyright 2018 Sony Semiconductor Solutions Corporation + * Copyright 2018, 2020 Sony Semiconductor Solutions Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -89,6 +90,8 @@ # error "Select LTE SPI 4 or 5" #endif +#define WAIT_READY_TO_GPIO_INTERRUPT 300 /* micro seconds */ + /**************************************************************************** * Private Function Prototypes ****************************************************************************/ @@ -328,6 +331,11 @@ static bool altmdm_sready(void) static void altmdm_master_request(bool request) { + /* If the GPIO falls within 300us after raising + * (or GPIO raises within 300us after falling), the modem may miss the GPIO + * interrupt. So delay by 300us before changing the GPIO. */ + + up_udelay(WAIT_READY_TO_GPIO_INTERRUPT); cxd56_gpio_write(ALTMDM_MASTER_REQ, request); } diff --git a/boards/arm/cxd56xx/common/src/cxd56_wiznet.c b/boards/arm/cxd56xx/common/src/cxd56_wiznet.c new file mode 100644 index 00000000000..e39ae5ed4cc --- /dev/null +++ b/boards/arm/cxd56xx/common/src/cxd56_wiznet.c @@ -0,0 +1,358 @@ +/**************************************************************************** + * boards/arm/cxd56xx/common/src/cxd56_wiznet.c + * + * Copyright 2020 Sony Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of Sony Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#if defined(CONFIG_NET_WIZNET) && \ + defined(CONFIG_CXD56_GPIO_IRQ) && defined(CONFIG_CXD56_SPI) + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "cxd56_spi.h" +#include "cxd56_dmac.h" +#include "cxd56_gpio.h" +#include "cxd56_gpioint.h" +#include "cxd56_pinconfig.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#if !defined(CONFIG_NET_WIZNET_MAX_PACKET_SIZE) +# error CONFIG_NET_WIZNET_MAX_PACKET_SIZE is not set +#endif + +#if defined(CONFIG_CXD56_WIZNET_SPI4) +# define SPI_CH (4) +# if defined(CONFIG_CXD56_WIZNET_SPI4_DMAC) +# define DMA_TXCH (2) +# define DMA_RXCH (3) +# define DMA_TXCHCHG (CXD56_DMA_PERIPHERAL_SPI4_TX) +# define DMA_RXCHCFG (CXD56_DMA_PERIPHERAL_SPI4_RX) +# endif +#elif defined(CONFIG_CXD56_WIZNET_SPI5) +# define SPI_CH (5) +# if defined(CONFIG_CXD56_WIZNET_SPI5_DMAC) +# define DMA_TXCH (4) +# define DMA_RXCH (5) +# define DMA_TXCHCHG (CXD56_DMA_PERIPHERAL_SPI5_TX) +# define DMA_RXCHCFG (CXD56_DMA_PERIPHERAL_SPI5_RX) +# endif +#else +# error "Select CXD56 WIZnet SPI config to 4 or 5" +#endif + +#define WIZNET_DELAY_RST (1 * 1000) /* ms */ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void wiznet_irq_attach(bool attach, xcpt_t handler, FAR void *arg); +static void wiznet_irq_enable(bool enable); +static void wiznet_power_on(bool on); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static void *g_devhandle = NULL; +static const struct wiznet_lower_s g_wiznet_lower = +{ + .attach = wiznet_irq_attach, + .enable = wiznet_irq_enable, + .poweron = wiznet_power_on, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: wiznet_irq_attach + ****************************************************************************/ + +static void wiznet_irq_attach(bool attach, xcpt_t handler, FAR void *arg) +{ + if (attach) + { + cxd56_gpioint_config(WIZNET_PIN_INT, + GPIOINT_LEVEL_LOW|GPIOINT_NOISE_FILTER_DISABLE, + handler, arg); + } + else + { + cxd56_gpioint_config(WIZNET_PIN_INT, 0, NULL, NULL); + } +} + +/**************************************************************************** + * Name: wiznet_irq_enable + ****************************************************************************/ + +static void wiznet_irq_enable(bool enable) +{ + irqstate_t flags = spin_lock_irqsave(); + + if (enable) + { + /* enable interrupt */ + + cxd56_gpioint_enable(WIZNET_PIN_INT); + } + else + { + /* disable interrupt */ + + cxd56_gpioint_disable(WIZNET_PIN_INT); + } + + spin_unlock_irqrestore(flags); +} + +/**************************************************************************** + * Name: spi_pincontrol + * + * Description: + * Configure the SPI pin + * + * Input Parameter: + * bus - SPI bus number to control + * on - true: enable pin, false: disable pin + * + ****************************************************************************/ + +static void spi_pincontrol(int bus, bool on) +{ + switch (bus) + { +#ifdef CONFIG_CXD56_SPI4 + case 4: + if (on) + { + CXD56_PIN_CONFIGS(PINCONFS_SPI4); + } + else + { + CXD56_PIN_CONFIGS(PINCONFS_SPI4_GPIO); + } + break; +#endif /* CONFIG_CXD56_SPI4 */ + +#ifdef CONFIG_CXD56_SPI5 + case 5: +#ifdef CONFIG_CXD56_SPI5_PINMAP_EMMC + if (on) + { + CXD56_PIN_CONFIGS(PINCONFS_EMMCA_SPI5); + } + else + { + CXD56_PIN_CONFIGS(PINCONFS_EMMCA_GPIO); + } +#endif /* CONFIG_CXD56_SPI5_PINMAP_EMMC */ + +#ifdef CONFIG_CXD56_SPI5_PINMAP_SDIO + if (on) + { + CXD56_PIN_CONFIGS(PINCONFS_SDIOA_SPI5); + } + else + { + CXD56_PIN_CONFIGS(PINCONFS_SDIOA_GPIO); + } +#endif /* CONFIG_CXD56_SPI5_PINMAP_SDIO */ + break; +#endif /* CONFIG_CXD56_SPI5 */ + default: + break; + } +} + +/**************************************************************************** + * Name: wiznet_poweron + * + * Description: + * Power on the wiznet device on the board. + * + ****************************************************************************/ + +static void wiznet_power_on(bool on) +{ + if (on) + { + ninfo("Power on wiznet device..\n"); + + /* enable the SPI pin */ + + spi_pincontrol(SPI_CH, true); + + /* power on wiznet device */ + + cxd56_gpio_write(WIZNET_PIN_RST, false); + usleep(WIZNET_DELAY_RST); + cxd56_gpio_write(WIZNET_PIN_RST, true); + } + else + { + ninfo("Power off wiznet device..\n"); + + /* disable the SPI pin */ + + spi_pincontrol(SPI_CH, false); + + /* power off wiznet device */ + + cxd56_gpio_write(WIZNET_PIN_RST, false); + } +} + +#if defined(CONFIG_CXD56_WIZNET_USE_SWCS) +static void sw_spi_cs(FAR struct spi_dev_s *dev, uint32_t devid, + bool selected) +{ + /* Active low */ + + cxd56_gpio_write(WIZNET_PIN_CS, selected); +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_wiznet_initialize + * + * Description: + * Initialize wiznet device + * + ****************************************************************************/ + +int board_wiznet_initialize(FAR const char *devpath) +{ + FAR struct spi_dev_s *spi; +#if defined(CONFIG_CXD56_WIZNET_SPI4_DMAC) || \ + defined(CONFIG_CXD56_WIZNET_SPI5_DMAC) + DMA_HANDLE hdl; + dma_config_t conf; +#endif + +#if defined(CONFIG_CXD56_WIZNET_USE_SWCS) + FAR struct spi_ops_s *non_const_ops; +#endif + + ninfo("Initializing wiznet device..\n"); + + if (!g_devhandle) + { + + /* Initialize GPIO */ + + cxd56_gpio_config(WIZNET_PIN_RST, false); + + /* Initialize spi deivce */ + + spi = cxd56_spibus_initialize(SPI_CH); + if (!spi) + { + nerr("ERROR: Failed to initialize spi%d.\n", SPI_CH); + return -ENODEV; + } + +#if defined(CONFIG_CXD56_WIZNET_SPI4_DMAC) || \ + defined(CONFIG_CXD56_WIZNET_SPI5_DMAC) + hdl = cxd56_dmachannel(DMA_TXCH, + CONFIG_NET_WIZNET_MAX_PACKET_SIZE); + if (hdl) + { + conf.channel_cfg = DMA_TXCHCHG; + conf.dest_width = CXD56_DMAC_WIDTH8; + conf.src_width = CXD56_DMAC_WIDTH8; + cxd56_spi_dmaconfig(SPI_CH, CXD56_SPI_DMAC_CHTYPE_TX, hdl, + &conf); + } + + hdl = cxd56_dmachannel(DMA_RXCH, + CONFIG_NET_WIZNET_MAX_PACKET_SIZE); + if (hdl) + { + conf.channel_cfg = DMA_RXCHCFG; + conf.dest_width = CXD56_DMAC_WIDTH8; + conf.src_width = CXD56_DMAC_WIDTH8; + cxd56_spi_dmaconfig(SPI_CH, CXD56_SPI_DMAC_CHTYPE_RX, hdl, + &conf); + } +#endif + + spi_pincontrol(SPI_CH, true); + +#if defined(CONFIG_CXD56_WIZNET_USE_SWCS) + + /* Set Chip Select PIN as GPIO */ + + cxd56_gpio_config(WIZNET_PIN_CS, false); + + /* Override select method on SPI instance */ + + non_const_ops = (struct spi_ops_s *)spi->ops; + non_const_ops->select = sw_spi_cs; + +#endif + + g_devhandle = wiznet_register(devpath, spi, &g_wiznet_lower); + if (!g_devhandle) + { + nerr("ERROR: Failed to register wiznet driver.\n"); + return -ENODEV; + } + } + + return OK; +} + +#endif diff --git a/boards/arm/cxd56xx/spresense/Kconfig b/boards/arm/cxd56xx/spresense/Kconfig index 68516e6242f..39de402b87e 100644 --- a/boards/arm/cxd56xx/spresense/Kconfig +++ b/boards/arm/cxd56xx/spresense/Kconfig @@ -138,4 +138,74 @@ endif # CXD56_LTE_SPI5 endif # CXD56_LTE +menu "WIZnet Ethernet on CXD5602" + +if NET_WIZNET + +choice + prompt "WIZnet SPI selection" + default CXD56_WIZNET_SPI5 + +config CXD56_WIZNET_SPI4 + bool "Use SPI4" + select CXD56_SPI4 + +config CXD56_WIZNET_SPI5 + bool "Use SPI5" + select CXD56_SPI5 + +endchoice + +if CXD56_WIZNET_SPI4 + +config CXD56_WIZNET_SPI4_DMAC + bool "Use DMAC for SPI4" + default n + select CXD56_DMAC_SPI4_TX + select CXD56_DMAC_SPI4_RX + +endif # CXD56_WIZNET_SPI4 + +if CXD56_WIZNET_SPI5 + +config CXD56_WIZNET_SPI5_DMAC + bool "Use DMAC for SPI5" + default n + select CXD56_DMAC_SPI5_TX + select CXD56_DMAC_SPI5_RX + +endif # CXD56_WIZNET_SPI5 + +choice CXD56_WIZNET_PIN_RST + prompt "WIZnet Reset pin configuration." + default CXD56_WIZNET_RST_EMMC_DATA3 + +config CXD56_WIZNET_RST_EMMC_DATA3 + bool "Use PIN EMMC_DATA3" + +config CXD56_WIZNET_RST_I2S0_BCK + bool "Use PIN I2S0_BCK" + +endchoice + +choice CXD56_WIZNET_PIN_INT + prompt "WIZnet Interrupt pin configuration." + default CXD56_WIZNET_INT_EMMC_DATA2 + +config CXD56_WIZNET_INT_EMMC_DATA2 + bool "Use PIN EMMC_DATA2" + +config CXD56_WIZNET_INT_I2S0_LRCK + bool "Use PIN I2S0_LRCK" + +endchoice + +config CXD56_WIZNET_USE_SWCS + bool "Use GPIO (I2S_DIN) as a Chip Select pin." + default y + +endif # NET_WIZNET + +endmenu # "WIZnet Ethernet on CXD5602" + endif diff --git a/boards/arm/cxd56xx/spresense/include/board.h b/boards/arm/cxd56xx/spresense/include/board.h index 9e8c7efb088..1306605dc51 100644 --- a/boards/arm/cxd56xx/spresense/include/board.h +++ b/boards/arm/cxd56xx/spresense/include/board.h @@ -51,6 +51,7 @@ #include "cxd56_gauge.h" #include "cxd56_charger.h" #include "cxd56_gs2200m.h" +#include "cxd56_wiznet.h" #include "cxd56_i2cdev.h" #include "cxd56_spidev.h" #include "cxd56_sdcard.h" @@ -272,6 +273,25 @@ enum board_power_device #define ALTMDM_SHUTDOWN PIN_SPI2_MISO #define ALTMDM_LTE_POWER_BUTTON PIN_AP_CLK +/* WIZnet ethernet device pin definitions **********************************/ + + +#if defined(CONFIG_CXD56_WIZNET_RST_EMMC_DATA3) +#define WIZNET_PIN_RST PIN_EMMC_DATA3 +#elif defined(CONFIG_CXD56_WIZNET_RST_I2S0_BCK) +#define WIZNET_PIN_RST PIN_I2S0_BCK +#endif + +#if defined(CONFIG_CXD56_WIZNET_INT_EMMC_DATA2) +#define WIZNET_PIN_INT PIN_EMMC_DATA2 +#elif defined(CONFIG_CXD56_WIZNET_INT_I2S0_LRCK) +#define WIZNET_PIN_INT PIN_I2S0_LRCK +#endif + +#ifdef CONFIG_CXD56_WIZNET_USE_SWCS +#define WIZNET_PIN_CS PIN_I2S0_DATA_IN +#endif + /**************************************************************************** * Public Types ****************************************************************************/ diff --git a/boards/arm/cxd56xx/spresense/include/cxd56_wiznet.h b/boards/arm/cxd56xx/spresense/include/cxd56_wiznet.h new file mode 100644 index 00000000000..16996e5d1f1 --- /dev/null +++ b/boards/arm/cxd56xx/spresense/include/cxd56_wiznet.h @@ -0,0 +1,97 @@ +/**************************************************************************** + * boards/arm/cxd56xx/spresense/include/cxd56_wiznet.h + * + * Copyright 2020 Sony Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of Sony Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __BOARDS_ARM_CXD56XX_SPRESENSE_INCLUDE_CXD56_WIZNET_H +#define __BOARDS_ARM_CXD56XX_SPRESENSE_INCLUDE_CXD56_WIZNET_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#if defined(CONFIG_NET_WIZNET) && defined(CONFIG_CXD56_GPIO_IRQ) + +/**************************************************************************** + * Name: board_wiznet_initialize + * + * Description: + * Initialize WIZNET net + * + ****************************************************************************/ + +int board_wiznet_initialize(FAR const char *devpath); + +/**************************************************************************** + * Name: board_wiznet_uninitialize + * + * Description: + * Uninitialize WIZNET net + * + ****************************************************************************/ + +int board_wiznet_uninitialize(void); + +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __BOARDS_ARM_CXD56XX_SPRESENSE_INCLUDE_CXD56_WIZNET_H */ diff --git a/boards/arm/cxd56xx/spresense/src/cxd56_bringup.c b/boards/arm/cxd56xx/spresense/src/cxd56_bringup.c index 4c11a3908e3..1dc9a721950 100644 --- a/boards/arm/cxd56xx/spresense/src/cxd56_bringup.c +++ b/boards/arm/cxd56xx/spresense/src/cxd56_bringup.c @@ -1,7 +1,7 @@ /**************************************************************************** * boards/arm/cxd56xx/spresense/src/cxd56_bringup.c * - * Copyright 2018 Sony Semiconductor Solutions Corporation + * Copyright 2018, 2020 Sony Semiconductor Solutions Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -125,6 +125,14 @@ # include #endif +#ifdef CONFIG_CXD56_CISIF +# ifdef CONFIG_VIDEO_ISX012 +# include +# endif +# include +# include +#endif + #include "spresense.h" /**************************************************************************** @@ -380,14 +388,23 @@ int cxd56_bringup(void) _err("ERROR: Failed to initialize ISX012 board. %d\n", errno); } - g_video_devops = isx012_initialize(); - if (g_video_devops == NULL) + g_video_sensctrl_ops = isx012_initialize(); + if (g_video_sensctrl_ops == NULL) { _err("ERROR: Failed to populate ISX012 devops. %d\n", errno); ret = ERROR; } #endif /* CONFIG_VIDEO_ISX012 */ +#ifdef CONFIG_CXD56_CISIF + g_video_imgdata_ops = cxd56_cisif_initialize(); + if (g_video_imgdata_ops == NULL) + { + _err("ERROR: Failed to populate CISIF operations. %d\n", errno); + ret = ERROR; + } +#endif /* CONFIG_CXD56_CISIF */ + #if defined(CONFIG_CXD56_SDIO) /* In order to prevent Hi-Z from being input to the SD Card controller, * Initialize SDIO pins to GPIO low output with internal pull-down. @@ -446,6 +463,14 @@ int cxd56_bringup(void) } #endif +#ifdef CONFIG_NET_WIZNET + ret = board_wiznet_initialize("/dev/wiznet"); + if (ret < 0) + { + _err("ERROR: Failed to initialize W5x00. \n"); + } +#endif + #ifdef CONFIG_CXD56_GNSS ret = cxd56_gnssinitialize("/dev/gps"); if (ret < 0) diff --git a/boards/arm/cxd56xx/spresense/src/cxd56_power.c b/boards/arm/cxd56xx/spresense/src/cxd56_power.c index 23a08ee2845..408dade8e51 100644 --- a/boards/arm/cxd56xx/spresense/src/cxd56_power.c +++ b/boards/arm/cxd56xx/spresense/src/cxd56_power.c @@ -523,9 +523,12 @@ int board_reset(int status) { /* Restore the original state for bootup after power cycle */ - board_xtal_power_control(true); - board_flash_power_control(true); - up_pm_acquire_freqlock(&g_hv_lock); + if (!up_interrupt_context()) + { + board_xtal_power_control(true); + board_flash_power_control(true); + up_pm_acquire_freqlock(&g_hv_lock); + } /* System reboot */ diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index df323c25a9d..64b3ca49bbe 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -377,6 +377,8 @@ menuconfig NET_LAN91C111 if NET_LAN91C111 endif # NET_LAN91C111 +source "drivers/net/wiznet/Kconfig" + if ARCH_HAVE_PHY comment "External Ethernet PHY Device Support" diff --git a/drivers/net/Make.defs b/drivers/net/Make.defs index 54e5ba81f9c..621ccbc3246 100644 --- a/drivers/net/Make.defs +++ b/drivers/net/Make.defs @@ -83,6 +83,8 @@ ifeq ($(CONFIG_ARCH_PHY_INTERRUPT),y) CSRCS += phy_notify.c endif +include net$(DELIM)wiznet$(DELIM)Make.defs + # Include network build support DEPPATH += --dep-path net diff --git a/drivers/net/wiznet/.gitignore b/drivers/net/wiznet/.gitignore new file mode 100644 index 00000000000..1f53d3e957a --- /dev/null +++ b/drivers/net/wiznet/.gitignore @@ -0,0 +1,11 @@ +ioLibrary_Driver-* +archive.zip + +wiz_socket.h +wiz_socket.c +wizchip_conf.h +wizchip_conf.c +wiz_dhcp.c +wiz_dhcp.h +w5500.h +w5500.c diff --git a/drivers/net/wiznet/Kconfig b/drivers/net/wiznet/Kconfig new file mode 100644 index 00000000000..b9c81530014 --- /dev/null +++ b/drivers/net/wiznet/Kconfig @@ -0,0 +1,46 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +menuconfig NET_WIZNET + bool "WIZnet W5x00 Ethernet Support" + default n + select SPI + ---help--- + Enable driver for WIZnet W5x00 ethernet + +if NET_WIZNET + +choice + prompt "WIZnet W5x00 device selection" + default NET_WIZNET_W5500 + +config NET_WIZNET_W5100 + bool "Use WIZnet W5100 device" + +config NET_WIZNET_W5100S + bool "Use WIZnet W5100S device" + +config NET_WIZNET_W5200 + bool "Use WIZnet W5200 device" + +config NET_WIZNET_W5300 + bool "Use WIZnet W5300 device" + +config NET_WIZNET_W5500 + bool "Use WIZnet W5500 device" +endchoice + +config NET_WIZNET_SPI_FREQUENCY + int "SPI frequency for WIZnet" + default 14000000 + range 4000000 20000000 + +config NET_WIZNET_MAX_PACKET_SIZE + int "Max size to be transfer in bytes" + default 2051 + ---help--- + Maximum send/recv data buffer size + 3 bytes header size + +endif # NET_WIZNET diff --git a/drivers/net/wiznet/Make.defs b/drivers/net/wiznet/Make.defs new file mode 100644 index 00000000000..b2e769dd605 --- /dev/null +++ b/drivers/net/wiznet/Make.defs @@ -0,0 +1,117 @@ +############################################################################ +# drivers/net/wiznet/Make.defs +# +# Copyright 2020 Sony Corporation +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name of Sony Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +ifeq ($(CONFIG_NET_WIZNET),y) + +CSRCS += wiznet.c +CSRCS += wiz_common.c + +WIZNET_CSRCS += wiz_socket.c +WIZNET_CSRCS += wizchip_conf.c +WIZNET_CSRCS += wiz_dhcp.c + +# Now only W5500 is supported +ifeq ($(CONFIG_NET_WIZNET_W5500),y) +WIZNETDEV_DIR = W5500 +WIZNETDEV_SRC = w5500 +endif + +WIZNET_CSRCS += $(WIZNETDEV_SRC).c +CSRCS += $(WIZNET_CSRCS) + +WIZNET_HEADERS = wiz_socket.h wizchip_conf.h wiz_dhcp.h $(WIZNETDEV_SRC).h + +DEPPATH += --dep-path net$(DELIM)wiznet +VPATH += :net$(DELIM)wiznet +CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)drivers$(DELIM)net} + +# Set up build environment + +WGET ?= wget +UNZIP ?= unzip +TARGET_WIZNET_SHA1 = cbf5b6e908cfd3e74e03d1a4c9bddaac68ef77bb + +WIZNET_DIR := net$(DELIM)wiznet$(DELIM) +WIZNET_URL := "https://codeload.github.com/Wiznet/ioLibrary_Driver/zip/$(TARGET_WIZNET_SHA1)" +WIZNET_DL_FNAME := archive.zip + +WIZNETSRC = ioLibrary_Driver-$(TARGET_WIZNET_SHA1) + +WIZNETSRC_PATCH = $(WIZNET_DIR)patch + +WIZNETSRCDIR_ETHERNET = $(WIZNET_DIR)$(WIZNETSRC)$(DELIM)Ethernet$(DELIM) +WIZNETSRCDIR_DHCP = $(WIZNET_DIR)$(WIZNETSRC)$(DELIM)Internet$(DELIM)DHCP$(DELIM) +WIZNETSRCDIR_DEV = $(WIZNETSRCDIR_ETHERNET)$(WIZNETDEV_DIR)$(DELIM) + +# Patch files + +WIZNET_PATCHFILES = $(shell cd $(WIZNET_DIR); find patch -name "*.patch") + +# File list of copied files. + +WIZNET_COPYSRCS = $(addprefix $(WIZNET_DIR),$(WIZNET_CSRCS) $(WIZNET_HEADERS)) + +# Files + +$(WIZNET_DIR)$(WIZNETSRC): + $(Q) echo "Downloading: $(WIZNET_DIR)$(WIZNETSRC)" + $(Q) $(WGET) -O $(WIZNET_DIR)$(DELIM)$(WIZNET_DL_FNAME) $(WIZNET_URL); + $(Q) cd $(WIZNET_DIR); $(UNZIP) $(WIZNET_DL_FNAME) + $(Q) cp $(WIZNETSRCDIR_ETHERNET)socket.h $(WIZNET_DIR)wiz_socket.h + $(Q) cp $(WIZNETSRCDIR_ETHERNET)socket.c $(WIZNET_DIR)wiz_socket.c + $(Q) cp $(WIZNETSRCDIR_ETHERNET)wizchip_conf.h $(WIZNET_DIR)wizchip_conf.h + $(Q) cp $(WIZNETSRCDIR_ETHERNET)wizchip_conf.c $(WIZNET_DIR)wizchip_conf.c + $(Q) cp $(WIZNETSRCDIR_DHCP)dhcp.c $(WIZNET_DIR)wiz_dhcp.c + $(Q) cp $(WIZNETSRCDIR_DHCP)dhcp.h $(WIZNET_DIR)wiz_dhcp.h + $(Q) cp $(WIZNETSRCDIR_DEV)$(WIZNETDEV_SRC).h $(WIZNET_DIR) + $(Q) cp $(WIZNETSRCDIR_DEV)$(WIZNETDEV_SRC).c $(WIZNET_DIR) + $(Q) echo "Patch: $(WIZNET_PATCHFILES)" + $(Q) files="$(WIZNET_PATCHFILES)"; \ + cd $@/..; \ + for ff in $$files; do echo patch $$ff; patch -p0 < $$ff; done; + $(Q) touch $@ + + +wiznet.c: $(WIZNET_DIR)$(WIZNETSRC) +wiz_common.c: $(WIZNET_DIR)$(WIZNETSRC) +wiz_socket.h: $(WIZNET_DIR)$(WIZNETSRC) +wiz_socket.c: $(WIZNET_DIR)$(WIZNETSRC) +wizchip_conf.h: $(WIZNET_DIR)$(WIZNETSRC) +wizchip_conf.c: $(WIZNET_DIR)$(WIZNETSRC) +wiz_dhcp.c: $(WIZNET_DIR)$(WIZNETSRC) +wiz_dhcp.h: $(WIZNET_DIR)$(WIZNETSRC) +$(WIZNETDEV_SRC).h: $(WIZNET_DIR)$(WIZNETSRC) +$(WIZNETDEV_SRC).c: $(WIZNET_DIR)$(WIZNETSRC) + +endif diff --git a/drivers/net/wiznet/cleanup.sh b/drivers/net/wiznet/cleanup.sh new file mode 100755 index 00000000000..ef10579008a --- /dev/null +++ b/drivers/net/wiznet/cleanup.sh @@ -0,0 +1,4 @@ +rm -f archive.zip +rm -rf ioLibrary_Driver-* +rm -f wiz_socket.c wizchip_conf.c wiz_dhcp.c w5500.c +rm -f wiz_socket.h wizchip_conf.h wiz_dhcp.h w5500.h diff --git a/drivers/net/wiznet/patch/w5500.c.patch b/drivers/net/wiznet/patch/w5500.c.patch new file mode 100644 index 00000000000..1c7a65b4a53 --- /dev/null +++ b/drivers/net/wiznet/patch/w5500.c.patch @@ -0,0 +1,165 @@ +--- w5500.c 2020-12-01 17:45:13.474682643 +0900 ++++ w5500.c 2020-11-30 10:43:41.881303174 +0900 +@@ -52,6 +52,8 @@ + // + //***************************************************************************** + //#include ++#include ++#include + #include "w5500.h" + + #define _W5500_SPI_VDM_OP_ 0x00 +@@ -62,30 +64,67 @@ + #if (_WIZCHIP_ == 5500) + //////////////////////////////////////////////////// + ++static uint8_t *spi_data = NULL; ++static uint16_t len_data = 0; ++ ++uint8_t* WIZCHIP_BUFFER(uint16_t size) ++{ ++ /* Free already allocated data */ ++ ++ if (spi_data) ++ { ++ free(spi_data); ++ } ++ ++ /* Allocate mwmory */ ++ ++ if (size == 0) ++ { ++ spi_data = NULL; ++ } ++ else ++ { ++ spi_data = (uint8_t *)malloc(size + 4); ++ } ++ ++ /* Set allocated length */ ++ ++ if (spi_data != NULL) ++ { ++ len_data = size; ++ } ++ else ++ { ++ len_data = 0; ++ } ++ ++ return spi_data; ++} ++ + uint8_t WIZCHIP_READ(uint32_t AddrSel) + { + uint8_t ret; +- uint8_t spi_data[3]; + + WIZCHIP_CRITICAL_ENTER(); + WIZCHIP.CS._select(); + + AddrSel |= (_W5500_SPI_READ_ | _W5500_SPI_VDM_OP_); + +- if(!WIZCHIP.IF.SPI._read_burst || !WIZCHIP.IF.SPI._write_burst) // byte operation ++ if(!WIZCHIP.IF.SPI._read_burst || !spi_data || (len_data < 4)) // byte operation + { +- WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16); ++ WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16); + WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8); + WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0); ++ ret = WIZCHIP.IF.SPI._read_byte(); + } +- else // burst operation ++ else // burst operation + { + spi_data[0] = (AddrSel & 0x00FF0000) >> 16; + spi_data[1] = (AddrSel & 0x0000FF00) >> 8; + spi_data[2] = (AddrSel & 0x000000FF) >> 0; +- WIZCHIP.IF.SPI._write_burst(spi_data, 3); ++ WIZCHIP.IF.SPI._read_burst(spi_data, 4); ++ ret = spi_data[3]; + } +- ret = WIZCHIP.IF.SPI._read_byte(); + + WIZCHIP.CS._deselect(); + WIZCHIP_CRITICAL_EXIT(); +@@ -94,15 +133,12 @@ uint8_t WIZCHIP_READ(uint32_t AddrSel) + + void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb ) + { +- uint8_t spi_data[4]; +- + WIZCHIP_CRITICAL_ENTER(); + WIZCHIP.CS._select(); + + AddrSel |= (_W5500_SPI_WRITE_ | _W5500_SPI_VDM_OP_); + +- //if(!WIZCHIP.IF.SPI._read_burst || !WIZCHIP.IF.SPI._write_burst) // byte operation +- if(!WIZCHIP.IF.SPI._write_burst) // byte operation ++ if(!WIZCHIP.IF.SPI._write_burst || !spi_data || (len_data < 4)) // byte operation + { + WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16); + WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8); +@@ -124,15 +160,15 @@ void WIZCHIP_WRITE(uint32_t AddrSel, + + void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len) + { +- uint8_t spi_data[3]; + uint16_t i; + + WIZCHIP_CRITICAL_ENTER(); + WIZCHIP.CS._select(); + ++ memset(pBuf, 0, len); + AddrSel |= (_W5500_SPI_READ_ | _W5500_SPI_VDM_OP_); + +- if(!WIZCHIP.IF.SPI._read_burst || !WIZCHIP.IF.SPI._write_burst) // byte operation ++ if(!WIZCHIP.IF.SPI._read_burst || !spi_data || (len_data < len)) // byte operation + { + WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16); + WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8); +@@ -140,13 +176,13 @@ void WIZCHIP_READ_BUF (uint32_t Addr + for(i = 0; i < len; i++) + pBuf[i] = WIZCHIP.IF.SPI._read_byte(); + } +- else // burst operation ++ else // burst operation + { + spi_data[0] = (AddrSel & 0x00FF0000) >> 16; + spi_data[1] = (AddrSel & 0x0000FF00) >> 8; + spi_data[2] = (AddrSel & 0x000000FF) >> 0; +- WIZCHIP.IF.SPI._write_burst(spi_data, 3); +- WIZCHIP.IF.SPI._read_burst(pBuf, len); ++ WIZCHIP.IF.SPI._read_burst(spi_data, len+3); ++ memmove(pBuf, spi_data+3, len); + } + + WIZCHIP.CS._deselect(); +@@ -155,7 +191,6 @@ void WIZCHIP_READ_BUF (uint32_t Addr + + void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len) + { +- uint8_t spi_data[3]; + uint16_t i; + + WIZCHIP_CRITICAL_ENTER(); +@@ -163,7 +198,7 @@ void WIZCHIP_WRITE_BUF(uint32_t Addr + + AddrSel |= (_W5500_SPI_WRITE_ | _W5500_SPI_VDM_OP_); + +- if(!WIZCHIP.IF.SPI._write_burst) // byte operation ++ if(!WIZCHIP.IF.SPI._write_burst || !spi_data || (len_data < len)) // byte operation + { + WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16); + WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8); +@@ -176,8 +211,8 @@ void WIZCHIP_WRITE_BUF(uint32_t Addr + spi_data[0] = (AddrSel & 0x00FF0000) >> 16; + spi_data[1] = (AddrSel & 0x0000FF00) >> 8; + spi_data[2] = (AddrSel & 0x000000FF) >> 0; +- WIZCHIP.IF.SPI._write_burst(spi_data, 3); +- WIZCHIP.IF.SPI._write_burst(pBuf, len); ++ memmove(spi_data+3, pBuf, len); ++ WIZCHIP.IF.SPI._write_burst(spi_data, len+3); + } + + WIZCHIP.CS._deselect(); diff --git a/drivers/net/wiznet/patch/w5500.h.patch b/drivers/net/wiznet/patch/w5500.h.patch new file mode 100644 index 00000000000..9e5e0cfecfa --- /dev/null +++ b/drivers/net/wiznet/patch/w5500.h.patch @@ -0,0 +1,32 @@ +--- w5500.h 2020-12-01 17:45:13.474682643 +0900 ++++ w5500.h 2020-11-30 10:43:41.881303174 +0900 +@@ -917,12 +917,12 @@ extern "C" { + /** + * @brief For Berkeley Socket API + */ +-#define SOCK_STREAM Sn_MR_TCP ++//#define SOCK_STREAM Sn_MR_TCP + + /** + * @brief For Berkeley Socket API + */ +-#define SOCK_DGRAM Sn_MR_UDP ++//#define SOCK_DGRAM Sn_MR_UDP + + + /* Sn_CR values */ +@@ -1206,6 +1206,14 @@ extern "C" { + + /** + * @ingroup Basic_IO_function ++ * @brief Set and reset buffer for bulk read and write ++ * @param Buffer address ++ * @return void ++ */ ++uint8_t* WIZCHIP_BUFFER(uint16_t size); ++ ++/** ++ * @ingroup Basic_IO_function + * @brief It reads 1 byte value from a register. + * @param AddrSel Register address + * @return The value of register diff --git a/drivers/net/wiznet/patch/wiz_dhcp.c.patch b/drivers/net/wiznet/patch/wiz_dhcp.c.patch new file mode 100644 index 00000000000..b5d9eab96d5 --- /dev/null +++ b/drivers/net/wiznet/patch/wiz_dhcp.c.patch @@ -0,0 +1,82 @@ +--- wiz_dhcp.c 2020-11-25 10:43:37.336981419 +0900 ++++ wiz_dhcp.c 2020-11-25 14:27:32.496049426 +0900 +@@ -50,8 +50,8 @@ + // + //***************************************************************************** + +-#include "socket.h" +-#include "dhcp.h" ++#include "wiz_socket.h" ++#include "wiz_dhcp.h" + + /* If you want to display debug & processing message, Define _DHCP_DEBUG_ in dhcp.h */ + +@@ -420,7 +420,7 @@ void send_DHCP_DISCOVER(void) + printf("> Send DHCP_DISCOVER\r\n"); + #endif + +- sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT); ++ wiz_sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT); + } + + /* SEND DHCP REQUEST */ +@@ -518,7 +518,7 @@ void send_DHCP_REQUEST(void) + printf("> Send DHCP_REQUEST\r\n"); + #endif + +- sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT); ++ wiz_sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT); + + } + +@@ -579,7 +579,7 @@ void send_DHCP_DECLINE(void) + printf("\r\n> Send DHCP_DECLINE\r\n"); + #endif + +- sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT); ++ wiz_sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT); + } + + /* PARSE REPLY pDHCPMSG */ +@@ -596,12 +596,12 @@ int8_t parseDHCPMSG(void) + + if((len = getSn_RX_RSR(DHCP_SOCKET)) > 0) + { +- len = recvfrom(DHCP_SOCKET, (uint8_t *)pDHCPMSG, len, svr_addr, &svr_port); ++ len = wiz_recvfrom(DHCP_SOCKET, (uint8_t *)pDHCPMSG, len, svr_addr, &svr_port); + #ifdef _DHCP_DEBUG_ + printf("DHCP message : %d.%d.%d.%d(%d) %d received. \r\n",svr_addr[0],svr_addr[1],svr_addr[2], svr_addr[3],svr_port, len); + #endif + } +- else return 0; ++ else { return 0; } + if (svr_port == DHCP_SERVER_PORT) { + // compare mac address + if ( (pDHCPMSG->chaddr[0] != DHCP_CHADDR[0]) || (pDHCPMSG->chaddr[1] != DHCP_CHADDR[1]) || +@@ -711,7 +711,7 @@ uint8_t DHCP_run(void) + if(dhcp_state == STATE_DHCP_STOP) return DHCP_STOPPED; + + if(getSn_SR(DHCP_SOCKET) != SOCK_UDP) +- socket(DHCP_SOCKET, Sn_MR_UDP, DHCP_CLIENT_PORT, 0x00); ++ wiz_socket(DHCP_SOCKET, Sn_MR_UDP, DHCP_CLIENT_PORT, 0x00); + + ret = DHCP_RUNNING; + type = parseDHCPMSG(); +@@ -835,7 +835,7 @@ uint8_t DHCP_run(void) + + void DHCP_stop(void) + { +- close(DHCP_SOCKET); ++ wiz_close(DHCP_SOCKET); + dhcp_state = STATE_DHCP_STOP; + } + +@@ -903,7 +903,7 @@ int8_t check_DHCP_leasedIP(void) + + // IP conflict detection : ARP request - ARP reply + // Broadcasting ARP Request for check the IP conflict using UDP sendto() function +- ret = sendto(DHCP_SOCKET, (uint8_t *)"CHECK_IP_CONFLICT", 17, DHCP_allocated_ip, 5000); ++ ret = wiz_sendto(DHCP_SOCKET, (uint8_t *)"CHECK_IP_CONFLICT", 17, DHCP_allocated_ip, 5000); + + // RCR value restore + setRCR(tmp); diff --git a/drivers/net/wiznet/patch/wiz_socket.c.patch b/drivers/net/wiznet/patch/wiz_socket.c.patch new file mode 100644 index 00000000000..0a2b5a2e38c --- /dev/null +++ b/drivers/net/wiznet/patch/wiz_socket.c.patch @@ -0,0 +1,196 @@ +--- wiz_socket.c 2020-12-01 17:45:13.474682643 +0900 ++++ wiz_socket.c 2020-11-30 10:44:03.145529792 +0900 +@@ -53,7 +53,7 @@ + //! THE POSSIBILITY OF SUCH DAMAGE. + // + //***************************************************************************** +-#include "socket.h" ++#include "wiz_socket.h" + + //M20150401 : Typing Error + //#define SOCK_ANY_PORT_NUM 0xC000; +@@ -102,7 +102,7 @@ uint8_t sock_pack_info[_WIZCHIP_SOCK_NU + + + +-int8_t socket(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag) ++int8_t wiz_socket(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag) + { + CHECK_SOCKNUM(); + switch(protocol) +@@ -166,7 +166,7 @@ int8_t socket(uint8_t sn, uint8_t protoc + break; + } + } +- close(sn); ++ wiz_close(sn); + //M20150601 + #if _WIZCHIP_ == 5300 + setSn_MR(sn, ((uint16_t)(protocol | (flag & 0xF0))) | (((uint16_t)(flag & 0x02)) << 7) ); +@@ -195,7 +195,7 @@ int8_t socket(uint8_t sn, uint8_t protoc + return (int8_t)sn; + } + +-int8_t close(uint8_t sn) ++int8_t wiz_close(uint8_t sn) + { + CHECK_SOCKNUM(); + //A20160426 : Applied the erratum 1 of W5300 +@@ -220,7 +220,7 @@ int8_t close(uint8_t sn) + setSn_CR(sn,Sn_CR_OPEN); + while(getSn_CR(sn) != 0); + while(getSn_SR(sn) != SOCK_UDP); +- sendto(sn,destip,1,destip,0x3000); // send the dummy data to an unknown destination(0.0.0.1). ++ wiz_sendto(sn,destip,1,destip,0x3000); // send the dummy data to an unknown destination(0.0.0.1). + }; + #endif + setSn_CR(sn,Sn_CR_CLOSE); +@@ -238,7 +238,7 @@ int8_t close(uint8_t sn) + return SOCK_OK; + } + +-int8_t listen(uint8_t sn) ++int8_t wiz_listen(uint8_t sn) + { + CHECK_SOCKNUM(); + CHECK_SOCKMODE(Sn_MR_TCP); +@@ -247,14 +247,14 @@ int8_t listen(uint8_t sn) + while(getSn_CR(sn)); + while(getSn_SR(sn) != SOCK_LISTEN) + { +- close(sn); ++ wiz_close(sn); + return SOCKERR_SOCKCLOSED; + } + return SOCK_OK; + } + + +-int8_t connect(uint8_t sn, uint8_t * addr, uint16_t port) ++int8_t wiz_connect(uint8_t sn, uint8_t * addr, uint16_t port) + { + CHECK_SOCKNUM(); + CHECK_SOCKMODE(Sn_MR_TCP); +@@ -294,7 +294,7 @@ int8_t connect(uint8_t sn, uint8_t * add + return SOCK_OK; + } + +-int8_t disconnect(uint8_t sn) ++int8_t wiz_disconnect(uint8_t sn) + { + CHECK_SOCKNUM(); + CHECK_SOCKMODE(Sn_MR_TCP); +@@ -307,14 +307,14 @@ int8_t disconnect(uint8_t sn) + { + if(getSn_IR(sn) & Sn_IR_TIMEOUT) + { +- close(sn); ++ wiz_close(sn); + return SOCKERR_TIMEOUT; + } + } + return SOCK_OK; + } + +-int32_t send(uint8_t sn, uint8_t * buf, uint16_t len) ++int32_t wiz_send(uint8_t sn, uint8_t * buf, uint16_t len) + { + uint8_t tmp=0; + uint16_t freesize=0; +@@ -344,7 +344,7 @@ int32_t send(uint8_t sn, uint8_t * buf, + } + else if(tmp & Sn_IR_TIMEOUT) + { +- close(sn); ++ wiz_close(sn); + return SOCKERR_TIMEOUT; + } + else return SOCK_BUSY; +@@ -357,7 +357,7 @@ int32_t send(uint8_t sn, uint8_t * buf, + tmp = getSn_SR(sn); + if ((tmp != SOCK_ESTABLISHED) && (tmp != SOCK_CLOSE_WAIT)) + { +- close(sn); ++ wiz_close(sn); + return SOCKERR_SOCKSTATUS; + } + if( (sock_io_mode & (1< freesize) ) return SOCK_BUSY; +@@ -382,7 +382,7 @@ int32_t send(uint8_t sn, uint8_t * buf, + } + + +-int32_t recv(uint8_t sn, uint8_t * buf, uint16_t len) ++int32_t wiz_recv(uint8_t sn, uint8_t * buf, uint16_t len) + { + uint8_t tmp = 0; + uint16_t recvsize = 0; +@@ -417,13 +417,13 @@ int32_t recv(uint8_t sn, uint8_t * buf, + if(recvsize != 0) break; + else if(getSn_TX_FSR(sn) == getSn_TxMAX(sn)) + { +- close(sn); ++ wiz_close(sn); + return SOCKERR_SOCKSTATUS; + } + } + else + { +- close(sn); ++ wiz_close(sn); + return SOCKERR_SOCKSTATUS; + } + } +@@ -487,7 +487,7 @@ int32_t recv(uint8_t sn, uint8_t * buf, + return (int32_t)len; + } + +-int32_t sendto(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port) ++int32_t wiz_sendto(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port) + { + uint8_t tmp = 0; + uint16_t freesize = 0; +@@ -591,7 +591,7 @@ int32_t sendto(uint8_t sn, uint8_t * buf + + + +-int32_t recvfrom(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port) ++int32_t wiz_recvfrom(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port) + { + //M20150601 : For W5300 + #if _WIZCHIP_ == 5300 +@@ -710,7 +710,7 @@ int32_t recvfrom(uint8_t sn, uint8_t * b + #endif + if(sock_remained_size[sn] > 1514) + { +- close(sn); ++ wiz_close(sn); + return SOCKFATAL_PACKLEN; + } + sock_pack_info[sn] = PACK_FIRST; +@@ -773,7 +773,7 @@ int32_t recvfrom(uint8_t sn, uint8_t * b + } + + +-int8_t ctlsocket(uint8_t sn, ctlsock_type cstype, void* arg) ++int8_t wiz_ctlsocket(uint8_t sn, ctlsock_type cstype, void* arg) + { + uint8_t tmp = 0; + CHECK_SOCKNUM(); +@@ -819,7 +819,7 @@ int8_t ctlsocket(uint8_t sn, ctlsock_ty + return SOCK_OK; + } + +-int8_t setsockopt(uint8_t sn, sockopt_type sotype, void* arg) ++int8_t wiz_setsockopt(uint8_t sn, sockopt_type sotype, void* arg) + { + // M20131220 : Remove warning + //uint8_t tmp; +@@ -872,7 +872,7 @@ int8_t setsockopt(uint8_t sn, sockopt_t + return SOCK_OK; + } + +-int8_t getsockopt(uint8_t sn, sockopt_type sotype, void* arg) ++int8_t wiz_getsockopt(uint8_t sn, sockopt_type sotype, void* arg) + { + CHECK_SOCKNUM(); + switch(sotype) diff --git a/drivers/net/wiznet/patch/wiz_socket.h.patch b/drivers/net/wiznet/patch/wiz_socket.h.patch new file mode 100644 index 00000000000..d23d6c0d2cb --- /dev/null +++ b/drivers/net/wiznet/patch/wiz_socket.h.patch @@ -0,0 +1,125 @@ +--- wiz_socket.h 2020-12-01 17:45:13.474682643 +0900 ++++ wiz_socket.h 2020-11-30 10:44:03.145529792 +0900 +@@ -82,8 +82,8 @@ + * Following figure shows network flow diagram by WIZnet SOCKET API. + * @image html WIZnet_SOCKET.jpg "" + */ +-#ifndef _SOCKET_H_ +-#define _SOCKET_H_ ++#ifndef _WIZ_SOCKET_H_ ++#define _WIZ_SOCKET_H_ + #ifdef __cplusplus + extern "C" { + #endif +@@ -162,7 +162,7 @@ + * @ref SOCKERR_SOCKMODE - Not support socket mode as TCP, UDP, and so on. \n + * @ref SOCKERR_SOCKFLAG - Invaild socket flag. + */ +-int8_t socket(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag); ++int8_t wiz_socket(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag); + + /** + * @ingroup WIZnet_socket_APIs +@@ -174,7 +174,7 @@ int8_t socket(uint8_t sn, uint8_t proto + * @return @b Success : @ref SOCK_OK \n + * @b Fail : @ref SOCKERR_SOCKNUM - Invalid socket number + */ +-int8_t close(uint8_t sn); ++int8_t wiz_close(uint8_t sn); + + /** + * @ingroup WIZnet_socket_APIs +@@ -187,7 +187,7 @@ int8_t close(uint8_t sn); + * @b Fail :\n @ref SOCKERR_SOCKINIT - Socket is not initialized \n + * @ref SOCKERR_SOCKCLOSED - Socket closed unexpectedly. + */ +-int8_t listen(uint8_t sn); ++int8_t wiz_listen(uint8_t sn); + + /** + * @ingroup WIZnet_socket_APIs +@@ -210,7 +210,7 @@ int8_t listen(uint8_t sn); + * @ref SOCKERR_TIMEOUT - Timeout occurred during request connection\n + * @ref SOCK_BUSY - In non-block io mode, it returned immediately\n + */ +-int8_t connect(uint8_t sn, uint8_t * addr, uint16_t port); ++int8_t wiz_connect(uint8_t sn, uint8_t * addr, uint16_t port); + + /** + * @ingroup WIZnet_socket_APIs +@@ -227,7 +227,7 @@ int8_t connect(uint8_t sn, uint8_t * ad + * @ref SOCKERR_TIMEOUT - Timeout occurred \n + * @ref SOCK_BUSY - Socket is busy. + */ +-int8_t disconnect(uint8_t sn); ++int8_t wiz_disconnect(uint8_t sn); + + /** + * @ingroup WIZnet_socket_APIs +@@ -247,7 +247,7 @@ int8_t disconnect(uint8_t sn); + * @ref SOCKERR_DATALEN - zero data length \n + * @ref SOCK_BUSY - Socket is busy. + */ +-int32_t send(uint8_t sn, uint8_t * buf, uint16_t len); ++int32_t wiz_send(uint8_t sn, uint8_t * buf, uint16_t len); + + /** + * @ingroup WIZnet_socket_APIs +@@ -269,7 +269,7 @@ int32_t send(uint8_t sn, uint8_t * buf, + * @ref SOCKERR_DATALEN - zero data length \n + * @ref SOCK_BUSY - Socket is busy. + */ +-int32_t recv(uint8_t sn, uint8_t * buf, uint16_t len); ++int32_t wiz_recv(uint8_t sn, uint8_t * buf, uint16_t len); + + /** + * @ingroup WIZnet_socket_APIs +@@ -297,7 +297,7 @@ int32_t recv(uint8_t sn, uint8_t * buf, + * @ref SOCKERR_TIMEOUT - Timeout occurred \n + * @ref SOCK_BUSY - Socket is busy. + */ +-int32_t sendto(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port); ++int32_t wiz_sendto(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port); + + /** + * @ingroup WIZnet_socket_APIs +@@ -327,7 +327,7 @@ int32_t sendto(uint8_t sn, uint8_t * buf + * @ref SOCKERR_SOCKNUM - Invalid socket number \n + * @ref SOCKBUSY - Socket is busy. + */ +-int32_t recvfrom(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port); ++int32_t wiz_recvfrom(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port); + + + ///////////////////////////// +@@ -418,7 +418,7 @@ typedef enum + * @return @b Success @ref SOCK_OK \n + * @b fail @ref SOCKERR_ARG - Invalid argument\n + */ +-int8_t ctlsocket(uint8_t sn, ctlsock_type cstype, void* arg); ++int8_t wiz_ctlsocket(uint8_t sn, ctlsock_type cstype, void* arg); + + /** + * @ingroup WIZnet_socket_APIs +@@ -446,7 +446,7 @@ int8_t ctlsocket(uint8_t sn, ctlsock_ty + * - @ref SOCKERR_SOCKOPT - Invalid socket option or its value \n + * - @ref SOCKERR_TIMEOUT - Timeout occurred when sending keep-alive packet \n + */ +-int8_t setsockopt(uint8_t sn, sockopt_type sotype, void* arg); ++int8_t wiz_setsockopt(uint8_t sn, sockopt_type sotype, void* arg); + + /** + * @ingroup WIZnet_socket_APIs +@@ -480,10 +480,10 @@ int8_t setsockopt(uint8_t sn, sockopt_t + * When SO_PACKINFO value is PACK_FIRST and the return value of recvfrom() is zero, + * This means the zero byte UDP data(UDP Header only) received. + */ +-int8_t getsockopt(uint8_t sn, sockopt_type sotype, void* arg); ++int8_t wiz_getsockopt(uint8_t sn, sockopt_type sotype, void* arg); + + #ifdef __cplusplus + } + #endif + +-#endif // _SOCKET_H_ ++#endif // _WIZ_SOCKET_H_ diff --git a/drivers/net/wiznet/patch/wizchip_conf.h.patch b/drivers/net/wiznet/patch/wizchip_conf.h.patch new file mode 100644 index 00000000000..ec1e2f7581a --- /dev/null +++ b/drivers/net/wiznet/patch/wizchip_conf.h.patch @@ -0,0 +1,77 @@ +--- wizchip_conf.h 2020-12-01 17:45:13.474682643 +0900 ++++ wizchip_conf.h 2020-11-30 14:42:22.245797459 +0900 +@@ -58,6 +58,7 @@ + extern "C" { + #endif + ++#include + #include + /** + * @brief Select WIZCHIP. +@@ -72,7 +73,20 @@ extern "C" { + #define W5500 5500 + + #ifndef _WIZCHIP_ +-#define _WIZCHIP_ W5100S // W5100, W5100S, W5200, W5300, W5500 ++//#define _WIZCHIP_ W5100S // W5100, W5100S, W5200, W5300, W5500 ++#if defined(CONFIG_NET_WIZNET_W5100) ++#define _WIZCHIP_ W5100 ++#elif defined(CONFIG_NET_WIZNET_W5100S) ++#define _WIZCHIP_ W5100S ++#elif defined(CONFIG_NET_WIZNET_W5200) ++#define _WIZCHIP_ W5200 ++#elif defined(CONFIG_NET_WIZNET_W5300) ++#define _WIZCHIP_ W5300 ++#elif defined(CONFIG_NET_WIZNET_W5500) ++#define _WIZCHIP_ W5500 ++#else ++#error "CONFIG_NET_WIZNET_W5x00 not defined" ++#endif + #endif + + #define _WIZCHIP_IO_MODE_NONE_ 0x0000 +@@ -103,7 +117,7 @@ extern "C" { + //A20150601 : Define the unit of IO DATA. + typedef uint8_t iodata_t; + //A20150401 : Indclude W5100.h file +- #include "W5100/w5100.h" ++ #include "w5100.h" + + #elif (_WIZCHIP_ == W5100S) + #define _WIZCHIP_ID_ "W5100S\0" +@@ -118,7 +132,7 @@ extern "C" { + //A20150601 : Define the unit of IO DATA. + typedef uint8_t iodata_t; + //A20150401 : Indclude W5100.h file +- #include "W5100S/w5100s.h" ++ #include "w5100s.h" + #elif (_WIZCHIP_ == W5200) + #define _WIZCHIP_ID_ "W5200\0" + /** +@@ -131,7 +145,7 @@ extern "C" { + #endif + //A20150601 : Define the unit of IO DATA. + typedef uint8_t iodata_t; +- #include "W5200/w5200.h" ++ #include "w5200.h" + #elif (_WIZCHIP_ == W5500) + #define _WIZCHIP_ID_ "W5500\0" + +@@ -154,7 +168,7 @@ extern "C" { + #endif + //A20150601 : Define the unit of IO DATA. + typedef uint8_t iodata_t; +- #include "W5500/w5500.h" ++ #include "w5500.h" + #elif ( _WIZCHIP_ == W5300) + #define _WIZCHIP_ID_ "W5300\0" + /** +@@ -182,7 +196,7 @@ extern "C" { + #error "Unknown _WIZCHIP_IO_BUS_WIDTH_. It should be 8 or 16." + #endif + // +- #include "W5300/w5300.h" ++ #include "w5300.h" + #else + #error "Unknown defined _WIZCHIP_. You should define one of 5100, 5200, and 5500 !!!" + #endif diff --git a/drivers/net/wiznet/wiz_common.c b/drivers/net/wiznet/wiz_common.c new file mode 100644 index 00000000000..9df601e0109 --- /dev/null +++ b/drivers/net/wiznet/wiz_common.c @@ -0,0 +1,933 @@ +/**************************************************************************** + * drivers/net/wiznet/wiz_common.c + * + * Copyright 2020 Sony Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of Sony Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "stdio.h" +#include "stdlib.h" +#include "errno.h" +#include "fcntl.h" +#include "string.h" +#include +#include +#include + +#include +#include +#include +#include + +#include "wiz_common.h" +#include "wiz_socket.h" +#include "wizchip_conf.h" +#include "wiz_dhcp.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define WIZNET_INTERNET_SOCKET 0 +#define WIZNET_DHCP_BUFFER_SIZE 548 + +#define WIZNET_REG_RETRY_COUNT 8 +#define WIZNET_REG_RETRY_TIMEOUT 2000 + +/* Avoid mixed case identifier warning */ + +#define wiz_netinfo wiz_NetInfo +#define wiz_nettimeout wiz_NetTimeout + +#define dhcp_time_handler DHCP_time_handler +#define dhcp_init DHCP_init +#define dhcp_run DHCP_run +#define dhcp_stop DHCP_stop +#define get_dns_from_dhcp getDNSfromDHCP + +#define get_sn_sr getSn_SR +#define get_sn_ir getSn_IR +#define set_sn_ir setSn_IR +#define get_sn_rx_rsr getSn_RX_RSR +#define set_sn_port setSn_PORT + +#define SN_IR_CHECK (Sn_IR_RECV|Sn_IR_DISCON|Sn_IR_CON) +#define SN_IR_RESET (Sn_IR_RECV|Sn_IR_CON) + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static FAR struct wiznet_dev_s *g_wizdev; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: wiznet_cris_enter + ****************************************************************************/ + +static void wiznet_cris_enter(void) +{ +} + +/**************************************************************************** + * Name: wiznet_cris_exit + ****************************************************************************/ + +static void wiznet_cris_exit(void) +{ +} + +/**************************************************************************** + * Name: wiznet_cs_select + ****************************************************************************/ + +static void wiznet_cs_select(void) +{ + /* Low active signal */ + + SPI_SELECT(g_wizdev->spi, 0, false); +} + +/**************************************************************************** + * Name: wiznet_cs_deselect + ****************************************************************************/ + +static void wiznet_cs_deselect(void) +{ + /* Low active signal */ + + SPI_SELECT(g_wizdev->spi, 0, true); +} + +/**************************************************************************** + * Name: wiznet_spi_readbyte + ****************************************************************************/ + +static uint8_t wiznet_spi_readbyte(void) +{ + uint8_t rb = 0; + + if (g_wizdev != NULL) + { + SPI_EXCHANGE(g_wizdev->spi, &rb, &rb, 1); + } + + return rb; +} + +/**************************************************************************** + * Name: wiznet_spi_writebyte + ****************************************************************************/ + +static void wiznet_spi_writebyte(uint8_t wb) +{ + if (g_wizdev != NULL) + { + SPI_EXCHANGE(g_wizdev->spi, &wb, NULL, 1); + } +} + +/**************************************************************************** + * Name: wiznet_spi_readburst + ****************************************************************************/ + +static void wiznet_spi_readburst(uint8_t *pbuf, uint16_t len) +{ + if (g_wizdev != NULL) + { + SPI_EXCHANGE(g_wizdev->spi, pbuf, pbuf, len); + } +} + +/**************************************************************************** + * Name: wiznet_spi_writeburst + ****************************************************************************/ + +static void wiznet_spi_writeburst(uint8_t *pbuf, uint16_t len) +{ + if (g_wizdev != NULL) + { + SPI_EXCHANGE(g_wizdev->spi, pbuf, NULL, len); + } +} + +/**************************************************************************** + * Name: wiznet_start_timer + ****************************************************************************/ + +static timer_t wiznet_start_timer(int interval_ms, FAR void *handler) +{ + int ret; + sigset_t mask; + struct sigaction sa; + struct sigevent sev; + struct itimerspec timer; + timer_t timerid; + + sigemptyset(&mask); + sigaddset(&mask, SIGUSR1); + + ret = sigprocmask(SIG_UNBLOCK, &mask, NULL); + if (ret != OK) + { + nerr("sigprocmask() failed:%d\n", ret); + return NULL; + } + + sa.sa_sigaction = handler; + sa.sa_flags = SA_SIGINFO; + sigfillset(&sa.sa_mask); + sigdelset(&sa.sa_mask, SIGUSR1); + + ret = sigaction(SIGUSR1, &sa, NULL); + if (ret != OK) + { + nerr("sigaction() failed:%d\n", ret); + return NULL; + } + + sev.sigev_notify = SIGEV_SIGNAL; + sev.sigev_signo = SIGUSR1; + + ret = timer_create(CLOCK_REALTIME, &sev, &timerid); + if (ret != OK) + { + nerr("timer_create() failed:%d\n", ret); + return NULL; + } + + timer.it_value.tv_sec = interval_ms / 1000; + timer.it_value.tv_nsec = (interval_ms % 1000) * 1000 * 1000; + timer.it_interval.tv_sec = timer.it_value.tv_sec; + timer.it_interval.tv_nsec = timer.it_value.tv_nsec; + + ret = timer_settime(timerid, 0, &timer, NULL); + if (ret != OK) + { + nerr("timer_settime() failed:%d\n", ret); + return NULL; + } + + return timerid; +} + +/**************************************************************************** + * Name: wiznet_stop_timer + ****************************************************************************/ + +static void wiznet_stop_timer(timer_t timerid) +{ + sigset_t mask; + + timer_delete(timerid); + + sigfillset(&mask); + sigprocmask(SIG_SETMASK, &mask, NULL); +} + +/**************************************************************************** + * Name: wiznet_internet_dhcp + ****************************************************************************/ + +static int wiznet_internet_dhcp(FAR struct wiznet_dev_s *dev) +{ + int ret; + timer_t timerid; + uint8_t dhcp_buffer[WIZNET_DHCP_BUFFER_SIZE]; + + ninfo("wiznet_internet_dhcp start\n"); + + timerid = wiznet_start_timer(1000, dhcp_time_handler); + + dhcp_init(WIZNET_INTERNET_SOCKET, dhcp_buffer); + + do + { + ret = dhcp_run(); + nxsig_sleep(1); + } + while (ret == DHCP_RUNNING); + + dhcp_stop(); + + wiznet_stop_timer(timerid); + + if ((ret == DHCP_FAILED) || (ret == DHCP_STOPPED)) + { + nerr("wiznet_internet_dhcp failed : %d\n", ret); + errno = EHOSTDOWN; + return -1; + } + + ninfo("wiznet_internet_dhcp success : %d\n", ret); + return 0; +} + +/**************************************************************************** + * Name: wiznet_check_netinfo + ****************************************************************************/ + +static int wiznet_check_netinfo(wiz_netinfo *netinfo) +{ + int ret = -1; + int cnt; + wiz_netinfo netcheck; + + for (cnt = 0; cnt < WIZNET_SET_NET_WAIT_COUNT; cnt++) + { + wizchip_setnetinfo(netinfo); + wizchip_getnetinfo(&netcheck); + + if (memcmp(netinfo, &netcheck, 6) == 0) + { + ret = 0; + break; + } + + /* Wait before next try */ + + nxsig_usleep(WIZNET_SET_NET_WAIT_US); + } + + return ret; +} + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: wiznet_initialize + * + * Description: + * initialise WIZNET class. + * - open port + * - configure port + * - etc... + * + * Input Parmeters: + * dev : private data for wiznet driver access + * + * Returned Value: + * 0 on success, -1 in case of error. + * + ****************************************************************************/ + +int wiznet_initialize(FAR struct wiznet_dev_s *dev) +{ + int cnt; + netmode_type netmode; + wiz_nettimeout nettime; + uint8_t bufsize[_WIZCHIP_SOCK_NUM_]; + + ninfo("Initializing WIZNET...\n"); + + /* Register private device */ + + g_wizdev = dev; + +#if defined(CONFIG_NET_WIZNET_W5500) + /* Buffer allocation */ + + switch (_WIZCHIP_SOCK_NUM_) + { + case 1: + dev->buffer = WIZCHIP_BUFFER(16384); + break; + case 2: + dev->buffer = WIZCHIP_BUFFER(8192); + break; + case 4: + dev->buffer = WIZCHIP_BUFFER(4096); + break; + default: + dev->buffer = WIZCHIP_BUFFER(2048); + break; + } + + if (dev->buffer == NULL) + { + nerr("WIZNET alloc memory failed\n"); + errno = ENOMEM; + return -1; + } +#endif + + /* Initialize */ + + reg_wizchip_cris_cbfunc(wiznet_cris_enter, wiznet_cris_exit); + reg_wizchip_cs_cbfunc(wiznet_cs_select, wiznet_cs_deselect); + reg_wizchip_spi_cbfunc(wiznet_spi_readbyte, wiznet_spi_writebyte); + reg_wizchip_spiburst_cbfunc(wiznet_spi_readburst, wiznet_spi_writeburst); + + ninfo("WIZNET waiting for initialize\n"); + + for (cnt = 0; cnt < WIZNET_INITIALIZE_WAIT; cnt++) + { + netmode = wizchip_getnetmode(); + if (!(netmode & 0x80)) + { + ninfo("WIZNET waiting skipped\n"); + break; + } + + /* Wait for transmission */ + + nxsig_sleep(1); + } + + for (cnt = 0; cnt < WIZNET_INITIALIZE_WAIT; cnt++) + { + /* Set default timeout */ + + nettime.retry_cnt = WIZNET_REG_RETRY_COUNT; + nettime.time_100us = WIZNET_REG_RETRY_TIMEOUT; + wizchip_settimeout(&nettime); + nxsig_sleep(1); + wizchip_gettimeout(&nettime); + + if ((nettime.retry_cnt == WIZNET_REG_RETRY_COUNT) + && (nettime.time_100us == WIZNET_REG_RETRY_TIMEOUT)) + { + ninfo("WIZNET waiting skipped\n"); + break; + } + } + + switch (_WIZCHIP_SOCK_NUM_) + { + case 1: + memset(bufsize, 16, _WIZCHIP_SOCK_NUM_); + break; + case 2: + memset(bufsize, 8, _WIZCHIP_SOCK_NUM_); + break; + case 4: + memset(bufsize, 4, _WIZCHIP_SOCK_NUM_); + break; + default: + memset(bufsize, 2, _WIZCHIP_SOCK_NUM_); + break; + } + + wizchip_init(bufsize, bufsize); + + /* Setup IRQ */ + + wizchip_setinterruptmask(IK_SOCK_ALL); + wizchip_clrinterrupt(IK_SOCK_ALL); + + ninfo("WIZNET initialized\n"); + memset(dev->dns_server, 0, 4); + + errno = 0; + + return 0; +} + +/**************************************************************************** + * Name: wiznet_finalize + * + * Description: + * finalize WIZNET class. + * - close port + * - etc... + * + * Input Parmeters: + * dev : private data for wiznet driver access + * + * Returned Value: + * 0 on success, -1 in case of error. + * + ****************************************************************************/ + +int wiznet_finalize(FAR struct wiznet_dev_s *dev) +{ + ninfo("Finalizing WIZNET...\n"); + +#if defined(CONFIG_NET_WIZNET_W5100S) || defined(CONFIG_NET_WIZNET_W5500) + wizphy_reset(); +#endif + +#if defined(CONFIG_NET_WIZNET_W5500) + dev->buffer = WIZCHIP_BUFFER(0); +#endif + + /* Unregister private device */ + + g_wizdev = NULL; + + errno = 0; + return 0; +} + +/**************************************************************************** + * Name: wiznet_setup + * + * Description: + * setup wiznet device + * + * Input Parmeters: + * dev : private data for wiznet driver access + * msg : device message + * + * Returned Value: + * 0 on success, -1 in case of error. + * + ****************************************************************************/ + +int wiznet_setup(FAR struct wiznet_dev_s *dev, + FAR struct wiznet_device_msg *msg) +{ + int ret = 0; + wiznet_ipaddr_t ip; + + /* MAC address configuration */ + + ip.mac[0] = (msg->mac >> (8 * 5)) & 0xff; + ip.mac[1] = (msg->mac >> (8 * 4)) & 0xff; + ip.mac[2] = (msg->mac >> (8 * 3)) & 0xff; + ip.mac[3] = (msg->mac >> (8 * 2)) & 0xff; + ip.mac[4] = (msg->mac >> (8 * 1)) & 0xff; + ip.mac[5] = (msg->mac >> (8 * 0)) & 0xff; + + /* IP configuration */ + + ip.dhcp = msg->dhcp; + if (!msg->dhcp) + { + memmove(&ip.ip, &msg->ipaddr, sizeof(in_addr_t)); + memmove(&ip.gw, &msg->draddr, sizeof(in_addr_t)); + memmove(&ip.mask, &msg->netmask, sizeof(in_addr_t)); + memmove(&ip.dns, &msg->dnsaddr, sizeof(in_addr_t)); + } + + /* Update configuration */ + + ret = wiznet_set_net(dev, &ip); + if (ret < 0) + { + return ret; + } + + if (msg->dhcp) + { + memmove(&msg->ipaddr, &ip.ip, sizeof(in_addr_t)); + memmove(&msg->draddr, &ip.gw, sizeof(in_addr_t)); + memmove(&msg->netmask, &ip.mask, sizeof(in_addr_t)); + memmove(&msg->dnsaddr, &ip.dns, sizeof(in_addr_t)); + } + + errno = 0; + return 0; +} + +/**************************************************************************** + * Name: wiznet_convert_error + * + * Description: + * confirm wiznet is connected + * + * Input Parmeters: + * value : value to convert wiznet error code to errno + * + * Returned Value: + * 0 or positive value for success case, negative vale for error case. + * + ****************************************************************************/ + +int wiznet_convert_error(int value) +{ + switch (value) + { + case SOCK_BUSY: + errno = EAGAIN; + break; + case SOCKERR_SOCKNUM: + errno = EBADF; + break; + case SOCKERR_SOCKOPT: + case SOCKERR_SOCKFLAG: + case SOCKERR_ARG: + case SOCKERR_PORTZERO: + case SOCKERR_IPINVALID: + errno = EINVAL; + break; + case SOCKERR_SOCKINIT: + errno = ENOTCONN; + break; + case SOCKERR_SOCKMODE: + errno = EISCONN; + break; + case SOCKERR_SOCKCLOSED: + case SOCKERR_SOCKSTATUS: + errno = ECONNRESET; + return 0; + case SOCKERR_TIMEOUT: + errno = ETIME; + break; + case SOCKERR_DATALEN: + case SOCKERR_BUFFER: + case SOCKFATAL_PACKLEN: + errno = ENOMEM; + break; + default: + errno = 0; + return value; + } + + return -errno; +} + +/**************************************************************************** + * Name: wiznet_lock_access + * + * Description: + * Lock access right to wiznet + * + * Input Parmeters: + * dev : private data for wiznet driver access + * + * Returned Value: + * None + * + ****************************************************************************/ + +void wiznet_lock_access(FAR struct wiznet_dev_s *dev) +{ + nxsem_wait_uninterruptible(&dev->lock_sem); +} + +/**************************************************************************** + * Name: wiznet_unlock_access + * + * Description: + * Unlock access right to wiznet + * + * Input Parmeters: + * dev : private data for wiznet driver access + * + * Returned Value: + * None + * + ****************************************************************************/ + +void wiznet_unlock_access(FAR struct wiznet_dev_s *dev) +{ + nxsem_post(&dev->lock_sem); +} + +/**************************************************************************** + * Name: wiznet_set_net + * + * Description: + * It will set network ip of mode. + * + * Input Parmeters: + * dev : private data for wiznet driver access + * ip : ip address info structure of interface + * + * Returned Value: + * 0 on success, -1 in case of error. + * + ****************************************************************************/ + +int wiznet_set_net(FAR struct wiznet_dev_s *dev, wiznet_ipaddr_t *ip) +{ + wiz_netinfo netinfo; + struct sockaddr_in dnsaddr; + + /* Check parameter */ + + if (ip == NULL) + { + errno = EINVAL; + return -1; + } + + /* Reset internal parameter */ + + dev->net_dev.d_flags |= IFF_DOWN; + + /* Create mac_addr data */ + + memset(&netinfo, 0, sizeof(wiz_netinfo)); + memmove(netinfo.mac, ip->mac, 6); + + if (ip->dhcp) + { + netinfo.dhcp = NETINFO_DHCP; + + /* Setup network parameter */ + + if (wiznet_check_netinfo(&netinfo) < 0) + { + errno = EIO; + return -1; + } + + /* Call DHCP function */ + + if (wiznet_internet_dhcp(dev) < 0) + { + return -1; + } + + /* Backup DNS server information */ + + get_dns_from_dhcp(dev->dns_server); + } + else + { + netinfo.dhcp = NETINFO_STATIC; + + netinfo.ip[0] = *((uint8_t *)&(ip->ip)+0); + netinfo.ip[1] = *((uint8_t *)&(ip->ip)+1); + netinfo.ip[2] = *((uint8_t *)&(ip->ip)+2); + netinfo.ip[3] = *((uint8_t *)&(ip->ip)+3); + netinfo.sn[0] = *((uint8_t *)&(ip->mask)+0); + netinfo.sn[1] = *((uint8_t *)&(ip->mask)+1); + netinfo.sn[2] = *((uint8_t *)&(ip->mask)+2); + netinfo.sn[3] = *((uint8_t *)&(ip->mask)+3); + netinfo.gw[0] = *((uint8_t *)&(ip->gw)+0); + netinfo.gw[1] = *((uint8_t *)&(ip->gw)+1); + netinfo.gw[2] = *((uint8_t *)&(ip->gw)+2); + netinfo.gw[3] = *((uint8_t *)&(ip->gw)+3); + dev->dns_server[0] = *((uint8_t *)&(ip->dns)+0); + dev->dns_server[1] = *((uint8_t *)&(ip->dns)+1); + dev->dns_server[2] = *((uint8_t *)&(ip->dns)+2); + dev->dns_server[3] = *((uint8_t *)&(ip->dns)+3); + + /* Setup network parameter */ + + if (wiznet_check_netinfo(&netinfo) < 0) + { + errno = EIO; + return -1; + } + } + + /* Update internal parameter */ + + wiznet_get_net(dev, ip); + + dev->net_dev.d_flags |= IFF_UP; + memmove(&dev->net_dev.d_mac.ether.ether_addr_octet, &ip->mac, 6); + memmove(&dev->net_dev.d_ipaddr, &ip->ip, sizeof(in_addr_t)); + memmove(&dev->net_dev.d_draddr, &ip->gw, sizeof(in_addr_t)); + memmove(&dev->net_dev.d_netmask, &ip->mask, sizeof(in_addr_t)); + + dnsaddr.sin_family = AF_INET; + memmove(&dnsaddr.sin_addr, &ip->dns, sizeof(in_addr_t)); + dnsaddr.sin_port = htons(DNS_DEFAULT_PORT); + dns_add_nameserver((FAR struct sockaddr *)&dnsaddr, sizeof(dnsaddr)); + + errno = 0; + return 0; +} + +/**************************************************************************** + * Name: wiznet_get_net + * + * Description: + * It will get network ip of mode. + * + * Output Parmeters: + * dev : private data for wiznet driver access + * ip : ip address info structure of interface + * + * Returned Value: + * 0 on success, -1 in case of error. + * + ****************************************************************************/ + +int wiznet_get_net(FAR struct wiznet_dev_s *dev, wiznet_ipaddr_t *ip) +{ + wiz_netinfo netinfo; + + memset(&netinfo, 0, sizeof(wiz_netinfo)); + wizchip_getnetinfo(&netinfo); + + *((uint8_t *)&(ip->ip)+0) = netinfo.ip[0]; + *((uint8_t *)&(ip->ip)+1) = netinfo.ip[1]; + *((uint8_t *)&(ip->ip)+2) = netinfo.ip[2]; + *((uint8_t *)&(ip->ip)+3) = netinfo.ip[3]; + *((uint8_t *)&(ip->mask)+0) = netinfo.sn[0]; + *((uint8_t *)&(ip->mask)+1) = netinfo.sn[1]; + *((uint8_t *)&(ip->mask)+2) = netinfo.sn[2]; + *((uint8_t *)&(ip->mask)+3) = netinfo.sn[3]; + *((uint8_t *)&(ip->gw)+0) = netinfo.gw[0]; + *((uint8_t *)&(ip->gw)+1) = netinfo.gw[1]; + *((uint8_t *)&(ip->gw)+2) = netinfo.gw[2]; + *((uint8_t *)&(ip->gw)+3) = netinfo.gw[3]; + *((uint8_t *)&(ip->dns)+0) = dev->dns_server[0]; + *((uint8_t *)&(ip->dns)+1) = dev->dns_server[1]; + *((uint8_t *)&(ip->dns)+2) = dev->dns_server[2]; + *((uint8_t *)&(ip->dns)+3) = dev->dns_server[3]; + memmove(ip->mac, netinfo.mac, 6); + + errno = 0; + return 0; +} + +/**************************************************************************** + * Name: wiznet_bind + * + * Description: + * Equivalent of POSIX bind for WIZNET. + * + * Input Parameters: + * sockfd Socket descriptor returned by socket() + * addr Socket local address + * addrlen Length of 'addr' + * + * Returned Value: + * A 0 on success; -errno on error. + * + ****************************************************************************/ + +int wiznet_bind(int sockfd, + FAR const struct sockaddr *addr, socklen_t addrlen) +{ + uint16_t port; + + port = ntohs(((struct sockaddr_in *)addr)->sin_port); + set_sn_port(sockfd, port); + + errno = 0; + return 0; +} + +/**************************************************************************** + * Name: wiznet_accept + * + * Description: + * Equivalent of POSIX accept for WIZNET. + * + * Input Parameters: + * sockfd Socket descriptor returned by socket() + * addr Receives the address of the connecting client + * addrlen Input: allocated size of 'addr', + * Return: returned size of 'addr' + * + * Returned Value: + * A 0 on success; -errno on error. + * + ****************************************************************************/ + +int wiznet_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) +{ + uint8_t val; + + while ((val = get_sn_sr(sockfd)) != SOCK_ESTABLISHED) + { + if (val == SOCK_CLOSED) + { + errno = ENETDOWN; + return -1; + } + + wiznet_unlock_access(g_wizdev); + nxsig_usleep(WIZNET_ACCEPT_WAIT_US); + wiznet_lock_access(g_wizdev); + } + + errno = 0; + return 0; +} + +/**************************************************************************** + * Name: wiznet_check_interrupt + * + * Description: + * Check interrupted socket. + * + * Input Parameters: + * dev : private data for wiznet driver access + * + * Returned Value: + * Positive value for success case, negative vale for error case. + * + ****************************************************************************/ + +int wiznet_check_interrupt(FAR struct wiznet_dev_s *dev) +{ + int cnt; + + for (cnt = 1; cnt < _WIZCHIP_SOCK_NUM_; cnt++) + { + if (get_sn_ir(cnt) & SN_IR_CHECK) + { + return cnt; + } + } + + return -1; +} + +/**************************************************************************** + * Name: wiznet_reset_interrupt + * + * Description: + * Check interrupted socket. + * + * Input Parameters: + * dev : private data for wiznet driver access + * sockfd : socket descriptor returned by socket() + * + * Returned Value: + * Positive value for success case, negative vale for error case. + * + ****************************************************************************/ + +void wiznet_reset_interrupt(FAR struct wiznet_dev_s *dev, int sockfd) +{ + if ((sockfd > 0) && (sockfd < _WIZCHIP_SOCK_NUM_)) + { + if (get_sn_rx_rsr(sockfd) == 0) + { + set_sn_ir(sockfd, SN_IR_RESET); + } + } +} + diff --git a/drivers/net/wiznet/wiz_common.h b/drivers/net/wiznet/wiz_common.h new file mode 100644 index 00000000000..02ee4ac3c16 --- /dev/null +++ b/drivers/net/wiznet/wiz_common.h @@ -0,0 +1,179 @@ +/**************************************************************************** + * drivers/net/wiznet/wiz_common.h + * + * Copyright 2020 Sony Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of Sony Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __NET_WIZNET_WIZ_COMMON_H__ +#define __NET_WIZNET_WIZ_COMMON_H__ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#ifdef CONFIG_NET_WIZNET + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define WIZNET_INITIALIZE_WAIT (30) /* Wait for SPI setup done */ +#define WIZNET_SET_NET_WAIT_COUNT (256) /* Wait for setup (US*COUNT) */ +#define WIZNET_SET_NET_WAIT_US (100000) /* Wait for setup (US*COUNT) */ +#define WIZNET_ACCEPT_WAIT_US (500000) /* Wait for accept */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* WIZnet IP information */ + +typedef struct +{ + uint8_t mac[6]; /* MAC address */ + bool dhcp; /* DHCP configuration */ + in_addr_t ip; /* IP address */ + in_addr_t mask; /* Netmask */ + in_addr_t gw; /* Gateway address */ + in_addr_t dns; /* DNS server address */ +} wiznet_ipaddr_t; + +struct wiznet_dev_s +{ + FAR char *path; + FAR struct pollfd *pfd; + FAR struct spi_dev_s *spi; + struct net_driver_s net_dev; + FAR const struct wiznet_lower_s *lower; + + uint8_t *buffer; + sem_t lock_sem; + + uint8_t dns_server[4]; +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: wiznet_lock_access() + ****************************************************************************/ + +void wiznet_lock_access(FAR struct wiznet_dev_s *dev); + +/**************************************************************************** + * Name: wiznet_unlock_access() + ****************************************************************************/ + +void wiznet_unlock_access(FAR struct wiznet_dev_s *dev); + +/**************************************************************************** + * Name: wiznet_initialize() + ****************************************************************************/ + +int wiznet_initialize(FAR struct wiznet_dev_s *priv); + +/**************************************************************************** + * Name: wiznet_finalize() + ****************************************************************************/ + +int wiznet_finalize(FAR struct wiznet_dev_s *dev); + +/**************************************************************************** + * Name: wiznet_setup() + ****************************************************************************/ + +int wiznet_setup(FAR struct wiznet_dev_s *dev, + FAR struct wiznet_device_msg *msg); + +/**************************************************************************** + * Name: wiznet_convert_error() + ****************************************************************************/ + +int wiznet_convert_error(int value); + +/**************************************************************************** + * Name: wiznet_get_net + ****************************************************************************/ + +int wiznet_get_net(FAR struct wiznet_dev_s *dev, wiznet_ipaddr_t *ip); + +/**************************************************************************** + * Name: wiznet_set_net + ****************************************************************************/ + +int wiznet_set_net(FAR struct wiznet_dev_s *dev, wiznet_ipaddr_t *ip); + +/**************************************************************************** + * Name: wiznet_poll + ****************************************************************************/ + +int wiznet_poll(FAR struct wiznet_dev_s *dev); + +/**************************************************************************** + * Name: wiznet_bind() + ****************************************************************************/ + +int wiznet_bind(int sockfd, + FAR const struct sockaddr *addr, socklen_t addrlen); + +/**************************************************************************** + * Name: wiznet_accept() + ****************************************************************************/ + +int wiznet_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); + +/**************************************************************************** + * Name: wiznet_check_interrupt() + ****************************************************************************/ + +int wiznet_check_interrupt(FAR struct wiznet_dev_s *dev); + +/**************************************************************************** + * Name: wiznet_reset_interrupt() + ****************************************************************************/ + +void wiznet_reset_interrupt(FAR struct wiznet_dev_s *dev, int sockfd); + +#endif /* CONFIG_NET_WIZNET */ +#endif /* __NET_WIZNET_WIZ_COMMON_H__ */ diff --git a/drivers/net/wiznet/wiznet.c b/drivers/net/wiznet/wiznet.c new file mode 100644 index 00000000000..7ffa8b67d2c --- /dev/null +++ b/drivers/net/wiznet/wiznet.c @@ -0,0 +1,853 @@ +/**************************************************************************** + * drivers/net/wiznet/wiznet.c + * + * Copyright 2020 Sony Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of Sony Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "wiz_socket.h" +#include "wiz_common.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#if !defined(CONFIG_SCHED_WORKQUEUE) +# error "Worker thread support is required (CONFIG_SCHED_WORKQUEUE)" +#endif + +#define SPI_MAXFREQUENCY CONFIG_NET_WIZNET_SPI_FREQUENCY +#define SPI_USESPIMODE (SPIDEV_MODE3) + +/* Avoid mixed case identifier warning */ + +#define SN_MR_TCP Sn_MR_TCP +#define SN_MR_UDP Sn_MR_UDP +#define SN_MR_MACRAW Sn_MR_MACRAW + +/**************************************************************************** + * Private Data Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Character driver methods */ + +static int wizdev_open(FAR struct file *filep); +static int wizdev_close(FAR struct file *filep); +static ssize_t wizdev_read(FAR struct file *filep, FAR char *buff, + size_t len); +static ssize_t wizdev_write(FAR struct file *filep, FAR const char *buff, + size_t len); +static int wizdev_ioctl(FAR struct file *filep, int cmd, + unsigned long arg); +static int wizdev_poll(FAR struct file *filep, FAR struct pollfd *fds, + bool setup); + +/* Interrupt handler */ + +static int wizdev_irq(int irq, FAR void *context, FAR void *arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* This the vtable that supports the character driver interface. */ + +static const struct file_operations g_wiznet_fops = +{ + wizdev_open, /* open */ + wizdev_close, /* close */ + wizdev_read, /* read */ + wizdev_write, /* write */ + NULL, /* seek */ + wizdev_ioctl, /* ioctl */ + wizdev_poll, /* poll */ + NULL /* unlink */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: wizdev_open + ****************************************************************************/ + +static int wizdev_open(FAR struct file *filep) +{ + return OK; +} + +/**************************************************************************** + * Name: wizdev_close + ****************************************************************************/ + +static int wizdev_close(FAR struct file *filep) +{ + return OK; +} + +/**************************************************************************** + * Name: wizdev_read + ****************************************************************************/ + +static ssize_t wizdev_read(FAR struct file *filep, FAR char *buffer, + size_t len) +{ + FAR struct inode *inode; + FAR struct wiznet_dev_s *dev; + int ret = 0; + + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + dev = (FAR struct wiznet_dev_s *)inode->i_private; + + wiznet_lock_access(dev); + + ret = wiznet_check_interrupt(dev); + if (ret <= 0) + { + ret = 0; + } + + memcpy(buffer, &ret, sizeof(ret)); + ret = sizeof(ret); + + wiznet_unlock_access(dev); + + return ret; +} + +/**************************************************************************** + * Name: wizdev_write + ****************************************************************************/ + +static ssize_t wizdev_write(FAR struct file *filep, FAR const char *buffer, + size_t len) +{ + return 0; +} + +/**************************************************************************** + * Name: wiznet_spi_init + ****************************************************************************/ + +static int wiznet_spi_init(FAR struct wiznet_dev_s *dev) +{ + (void)SPI_LOCK(dev->spi, true); + + SPI_SETMODE(dev->spi, SPI_USESPIMODE); + SPI_SETBITS(dev->spi, 8); + (void)SPI_SETFREQUENCY(dev->spi, SPI_MAXFREQUENCY); + + (void)SPI_LOCK(dev->spi, false); + + dev->lower->poweron(true); + + /* Attach interrupt handler */ + + dev->lower->attach(true, wizdev_irq, dev); + + return 0; +} + +/**************************************************************************** + * Name: wiznet_ioctl_device + ****************************************************************************/ + +static int wiznet_ioctl_device(FAR struct wiznet_dev_s *dev, + FAR struct wiznet_device_msg *msg) +{ + return wiznet_setup(dev, msg); +} + +/**************************************************************************** + * Name: wiznet_ioctl_socket + ****************************************************************************/ + +static int wiznet_ioctl_socket(FAR struct wiznet_dev_s *dev, + FAR struct wiznet_socket_msg *msg) +{ + int ret = OK; + int type = SOCK_STREAM; + + switch (msg->type) + { + case SOCK_STREAM: + type = SN_MR_TCP; + break; + case SOCK_DGRAM: + type = SN_MR_UDP; + break; + case SOCK_RAW: + type = SN_MR_MACRAW; + break; + default: + break; + } + + ret = wiz_socket(msg->sockfd, type, 0, 0); + + if (SOCK_OK == ret) + { + ret = OK; + } + else + { + ret = wiznet_convert_error(ret); + } + + return ret; +} + +/**************************************************************************** + * Name: wiznet_ioctl_connect + ****************************************************************************/ + +static int wiznet_ioctl_connect(FAR struct wiznet_dev_s *dev, + FAR struct wiznet_connect_msg *msg) +{ + int ret = OK; + struct sockaddr_in *addr = (struct sockaddr_in *)&msg->addr; + + ret = wiz_connect(msg->sockfd, + (uint8_t *)&(addr->sin_addr.s_addr), + ntohs(addr->sin_port)); + + if (SOCK_OK == ret) + { + ret = OK; + } + else + { + ret = wiznet_convert_error(ret); + } + + return ret; +} + +/**************************************************************************** + * Name: wiznet_ioctl_send + ****************************************************************************/ + +static int wiznet_ioctl_send(FAR struct wiznet_dev_s *dev, + FAR struct wiznet_send_msg *msg) +{ + int ret = OK; + struct sockaddr_in *addr = (struct sockaddr_in *)&msg->addr; + + do + { + if (SOCK_STREAM == msg->type) + { + ret = wiz_send(msg->sockfd, (void *)msg->buf, msg->len); + } + else + { + ret = wiz_sendto(msg->sockfd, (void *)msg->buf, msg->len, + (uint8_t *)&(addr->sin_addr.s_addr), + ntohs(addr->sin_port)); + } + } + while (SOCK_BUSY == ret); + + if (SOCK_OK <= ret) + { + msg->result = ret; + ret = OK; + } + else + { + msg->result = 0; + ret = wiznet_convert_error(ret); + } + + return ret; +} + +/**************************************************************************** + * Name: wiznet_ioctl_recv + ****************************************************************************/ + +static int wiznet_ioctl_recv(FAR struct wiznet_dev_s *dev, + FAR struct wiznet_recv_msg *msg) +{ + int ret = OK; + struct sockaddr_in *addr = (struct sockaddr_in *)&msg->addr; + + do + { + if (SOCK_STREAM == msg->type) + { + ret = wiz_recv(msg->sockfd, (void *)msg->buf, msg->len); + } + else + { + ret = wiz_recvfrom(msg->sockfd, (void *)msg->buf, msg->len, + (uint8_t *)&(addr->sin_addr.s_addr), + &(addr->sin_port)); + } + } + while (SOCK_BUSY == ret); + + if (SOCK_OK <= ret) + { + msg->result = ret; + ret = OK; + + wiznet_reset_interrupt(dev, msg->sockfd); + } + else + { + msg->result = 0; + ret = wiznet_convert_error(ret); + } + + return ret; +} + +/**************************************************************************** + * Name: wiznet_ioctl_close + ****************************************************************************/ + +static int wiznet_ioctl_close(FAR struct wiznet_dev_s *dev, + FAR struct wiznet_close_msg *msg) +{ + int ret = OK; + uint8_t val; + + wiz_getsockopt(msg->sockfd, SO_STATUS, &val); + + if (SOCK_ESTABLISHED == val) + { + wiz_disconnect(msg->sockfd); + } + + ret = wiz_close(msg->sockfd); + + if (SOCK_OK == ret) + { + ret = 0; + } + else + { + ret = wiznet_convert_error(ret); + } + + return ret; +} + +/**************************************************************************** + * Name: wiznet_ioctl_bind + ****************************************************************************/ + +static int wiznet_ioctl_bind(FAR struct wiznet_dev_s *dev, + FAR struct wiznet_bind_msg *msg) +{ + int ret = OK; + + ret = wiznet_bind(msg->sockfd, + (struct sockaddr *)&(msg->addr), msg->addrlen); + + return ret; +} + +/**************************************************************************** + * Name: wiznet_ioctl_listen + ****************************************************************************/ + +static int wiznet_ioctl_listen(FAR struct wiznet_dev_s *dev, + FAR struct wiznet_listen_msg *msg) +{ + int ret = OK; + + ret = wiz_listen(msg->sockfd); + + if (SOCK_OK == ret) + { + ret = OK; + } + else + { + ret = wiznet_convert_error(ret); + } + + return ret; +} + +/**************************************************************************** + * Name: wiznet_ioctl_accept + ****************************************************************************/ + +static int wiznet_ioctl_accept(FAR struct wiznet_dev_s *dev, + FAR struct wiznet_accept_msg *msg) +{ + int ret = OK; + + ret = wiznet_accept(msg->sockfd, + (struct sockaddr *)&(msg->addr), &(msg->addrlen)); + + return ret; +} + +/**************************************************************************** + * Name: wiznet_ifreq_ifreq + ****************************************************************************/ + +static int wiznet_ioctl_ifreq(FAR struct wiznet_dev_s *dev, + FAR struct wiznet_ifreq_msg *msg) +{ + wiznet_ipaddr_t netinfo; + struct sockaddr_in *addr; + int ret = OK; + + switch (msg->cmd) + { + case SIOCGIFHWADDR: + case SIOCGIFADDR: + case SIOCGIFBRDADDR: + case SIOCGIFNETMASK: + case SIOCSIFHWADDR: + case SIOCSIFADDR: + case SIOCSIFBRDADDR: + case SIOCSIFNETMASK: + wiznet_get_net(dev, &netinfo); + break; + + default: + ret = SOCKERR_SOCKFLAG; + break; + } + + switch (msg->cmd) + { + case SIOCGIFHWADDR: + memmove((uint8_t *)&msg->ifr.ifr_hwaddr.sa_data, + (uint8_t *)&netinfo.mac, 6); + break; + + case SIOCGIFADDR: + addr = (struct sockaddr_in *)&msg->ifr.ifr_addr; + memmove((uint8_t *)&addr->sin_addr.s_addr, + (uint8_t *)&netinfo.ip, 4); + break; + + case SIOCGIFBRDADDR: + addr = (struct sockaddr_in *)&msg->ifr.ifr_broadaddr; + memmove((uint8_t *)&addr->sin_addr.s_addr, + (uint8_t *)&netinfo.gw, 4); + break; + + case SIOCGIFNETMASK: + addr = (struct sockaddr_in *)&msg->ifr.ifr_netmask; + memmove((uint8_t *)&addr->sin_addr.s_addr, + (uint8_t *)&netinfo.mask, 4); + break; + + case SIOCSIFHWADDR: + memmove((uint8_t *)&netinfo.mac, + (uint8_t *)&msg->ifr.ifr_hwaddr.sa_data, 6); + wiznet_set_net(dev, &netinfo); + break; + + case SIOCSIFADDR: + netinfo.dhcp = false; + addr = (struct sockaddr_in *)&msg->ifr.ifr_addr; + memmove((uint8_t *)&netinfo.ip, + (uint8_t *)&addr->sin_addr.s_addr, 4); + wiznet_set_net(dev, &netinfo); + break; + + case SIOCSIFBRDADDR: + netinfo.dhcp = false; + addr = (struct sockaddr_in *)&msg->ifr.ifr_broadaddr; + memmove((uint8_t *)&netinfo.gw, + (uint8_t *)&addr->sin_addr.s_addr, 4); + wiznet_set_net(dev, &netinfo); + break; + + case SIOCSIFNETMASK: + netinfo.dhcp = false; + addr = (struct sockaddr_in *)&msg->ifr.ifr_netmask; + memmove((uint8_t *)&netinfo.mask, + (uint8_t *)&addr->sin_addr.s_addr, 4); + wiznet_set_net(dev, &netinfo); + break; + + default: + ret = SOCKERR_SOCKFLAG; + break; + } + + return ret; +} + +/**************************************************************************** + * Name: wiznet_ioctl_name + ****************************************************************************/ + +static int wiznet_ioctl_name(FAR struct wiznet_dev_s *dev, + FAR struct wiznet_name_msg *msg) +{ + int ret = 0; + wiznet_ipaddr_t netinfo; + struct sockaddr_in *addr = (struct sockaddr_in *)&msg->addr; + + memset(addr, 0, sizeof(struct sockaddr_in)); + + if (msg->local) + { + wiznet_get_net(dev, &netinfo); + memmove((uint8_t *)&(addr->sin_addr.s_addr), + (uint8_t *)&netinfo.ip, sizeof(in_addr_t)); + } + else + { + ret = wiz_getsockopt(msg->sockfd, SO_DESTIP, &netinfo.ip); + + if (SOCK_OK == ret) + { + memmove((uint8_t *)&(addr->sin_addr.s_addr), + (uint8_t *)&netinfo.ip, sizeof(in_addr_t)); + } + else + { + ret = wiznet_convert_error(ret); + } + } + + return ret; +} + +/**************************************************************************** + * Name: wizdev_ioctl + ****************************************************************************/ + +static int wizdev_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct inode *inode; + FAR struct wiznet_dev_s *dev; + int ret = -EINVAL; + + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + dev = (FAR struct wiznet_dev_s *)inode->i_private; + + /* Lock the device */ + + ninfo("== ioctl:%X\n", cmd); + wiznet_lock_access(dev); + + /* Disable wiznet irq to poll dready */ + + DEBUGASSERT(dev); + + switch (cmd) + { + case WIZNET_IOC_DEVICE: + { + struct wiznet_device_msg *msg = + (struct wiznet_device_msg *)arg; + + ret = wiznet_ioctl_device(dev, msg); + } + break; + + case WIZNET_IOC_SOCKET: + { + struct wiznet_socket_msg *msg = + (struct wiznet_socket_msg *)arg; + + ret = wiznet_ioctl_socket(dev, msg); + } + break; + + case WIZNET_IOC_CONNECT: + { + struct wiznet_connect_msg *msg = + (struct wiznet_connect_msg *)arg; + + ret = wiznet_ioctl_connect(dev, msg); + } + break; + + case WIZNET_IOC_SEND: + { + struct wiznet_send_msg *msg = + (struct wiznet_send_msg *)arg; + + ret = wiznet_ioctl_send(dev, msg); + } + break; + + case WIZNET_IOC_RECV: + { + struct wiznet_recv_msg *msg = + (struct wiznet_recv_msg *)arg; + + ret = wiznet_ioctl_recv(dev, msg); + break; + } + + case WIZNET_IOC_CLOSE: + { + struct wiznet_close_msg *msg = + (struct wiznet_close_msg *)arg; + + ret = wiznet_ioctl_close(dev, msg); + break; + } + + case WIZNET_IOC_BIND: + { + struct wiznet_bind_msg *msg = + (struct wiznet_bind_msg *)arg; + + ret = wiznet_ioctl_bind(dev, msg); + break; + } + + case WIZNET_IOC_LISTEN: + { + struct wiznet_listen_msg *msg = + (struct wiznet_listen_msg *)arg; + + ret = wiznet_ioctl_listen(dev, msg); + break; + } + + case WIZNET_IOC_ACCEPT: + { + struct wiznet_accept_msg *msg = + (struct wiznet_accept_msg *)arg; + + ret = wiznet_ioctl_accept(dev, msg); + break; + } + + case WIZNET_IOC_IFREQ: + { + struct wiznet_ifreq_msg *msg = + (struct wiznet_ifreq_msg *)arg; + + ret = wiznet_ioctl_ifreq(dev, msg); + break; + } + + case WIZNET_IOC_NAME: + { + struct wiznet_name_msg *msg = + (struct wiznet_name_msg *)arg; + + ret = wiznet_ioctl_name(dev, msg); + break; + } + + default: + DEBUGPANIC(); + break; + } + + /* Unlock the device */ + + wiznet_unlock_access(dev); + ninfo("== ioctl:%X finished\n", cmd); + + return ret; +} + +/**************************************************************************** + * Name: wizdev_poll + ****************************************************************************/ + +static int wizdev_poll(FAR struct file *filep, FAR struct pollfd *fds, + bool setup) +{ + FAR struct inode *inode; + FAR struct wiznet_dev_s *dev; + int ret = OK; + + ninfo("== setup:%d\n", (int)setup); + DEBUGASSERT(filep && fds); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + dev = (FAR struct wiznet_dev_s *)inode->i_private; + + /* Are we setting up the poll? Or tearing it down? */ + + if (setup) + { + /* Ignore waits that do not include POLLIN */ + + if ((fds->events & POLLIN) == 0) + { + ret = -EDEADLK; + goto errout; + } + + /* NOTE: only one thread can poll the device at any time */ + + if (dev->pfd) + { + ret = -EBUSY; + goto errout; + } + + dev->pfd = fds; + dev->lower->enable(true); + } + else + { + dev->lower->enable(false); + dev->pfd = NULL; + } + +errout: + ninfo("== setup:%d finished\n", (int)setup); + + return ret; +} + +/**************************************************************************** + * Name: wiznet_interrupt + ****************************************************************************/ + +static int wizdev_irq(int irq, FAR void *context, FAR void *arg) +{ + FAR struct wiznet_dev_s *dev; + + DEBUGASSERT(arg != NULL); + dev = (FAR struct wiznet_dev_s *)arg; + + if (dev->pfd) + { + ninfo("== interrupted : post\n"); + dev->pfd->revents |= POLLIN; + nxsem_post(dev->pfd->sem); + } + + dev->lower->enable(false); + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: wiznet_register + ****************************************************************************/ + +FAR void * wiznet_register(FAR const char *devpath, + FAR struct spi_dev_s *spi, + FAR const struct wiznet_lower_s *lower) +{ + struct wiznet_dev_s *priv; + int ret; + int size = sizeof(struct wiznet_dev_s); + + priv = (FAR struct wiznet_dev_s *)kmm_malloc(size); + if (!priv) + { + nerr("Failed to allocate instance.\n"); + return NULL; + } + + memset(priv, 0, size); + + priv->spi = spi; + priv->path = strdup(devpath); + priv->lower = lower; + priv->pfd = NULL; + nxsem_init(&priv->lock_sem, 0, 1); + + ret = wiznet_spi_init(priv); + + if (ret < 0) + { + nerr("Failed to initialize WIZNET driver.\n"); + kmm_free(priv); + return NULL; + } + + ret = wiznet_initialize(priv); + + if (ret < 0) + { + nerr("Failed to initialize WIZNET driver.\n"); + kmm_free(priv); + return NULL; + } + + ret = register_driver(devpath, &g_wiznet_fops, 0666, priv); + + if (ret < 0) + { + nerr("Failed to register driver: %d\n", ret); + kmm_free(priv); + return NULL; + } + + ret = netdev_register(&priv->net_dev, NET_LL_ETHERNET); + + ninfo("Register WIZNET driver.\n"); + return (FAR void *)priv; +} + diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index ce868ca6968..efffc287ca2 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -41,6 +41,60 @@ config VIDEO_ISX012 default n select I2C +if VIDEO_ISX012 +config VIDEO_ISX012_SCENE_BACKLIGHT + bool "ISX012 use backlight scene" + default y + +config VIDEO_ISX012_SCENE_BEACHSNOW + bool "ISX012 use beach snow scene" + default y + +config VIDEO_ISX012_SCENE_CANDLELIGHT + bool "ISX012 use candle light scene" + default y + +config VIDEO_ISX012_SCENE_DAWNDUSK + bool "ISX012 use dawn dusk scene" + default y + +config VIDEO_ISX012_SCENE_FALLCOLORS + bool "ISX012 use fall colors scene" + default y + +config VIDEO_ISX012_SCENE_FIREWORKS + bool "ISX012 use fireworks scene" + default y + +config VIDEO_ISX012_SCENE_LANDSCAPE + bool "ISX012 use landscape scene" + default y + +config VIDEO_ISX012_SCENE_NIGHT + bool "ISX012 use night scene" + default y + +config VIDEO_ISX012_SCENE_PARTYINDOOR + bool "ISX012 use party and indoor scene" + default y + +config VIDEO_ISX012_SCENE_PORTRAIT + bool "ISX012 use portrait scene" + default y + +config VIDEO_ISX012_SCENE_SPORTS + bool "ISX012 use sports scene" + default y + +config VIDEO_ISX012_SCENE_SUNSET + bool "ISX012 use sunset scene" + default y + +config VIDEO_ISX012_SCENE_TEXT + bool "ISX012 use text scene" + default y +endif + config VIDEO_OV2640 bool "OV2640 camera chip" default n diff --git a/drivers/video/isx012.c b/drivers/video/isx012.c index 73a02885514..e592fc4be48 100644 --- a/drivers/video/isx012.c +++ b/drivers/video/isx012.c @@ -1,7 +1,7 @@ /**************************************************************************** * drivers/video/isx012.c * - * Copyright 2018 Sony Semiconductor Solutions Corporation + * Copyright 2018, 2020 Sony Semiconductor Solutions Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -48,12 +48,12 @@ #include #include #include -#include #include #include #include #include +#include #include /**************************************************************************** @@ -93,12 +93,12 @@ #define OUT_YUV_HSIZE_MIN (96) #define OUT_JPG_VSIZE_MIN (64) #define OUT_JPG_HSIZE_MIN (96) -#define OUT_YUV_15FPS_VSIZE_MAX (360) -#define OUT_YUV_15FPS_HSIZE_MAX (480) -#define OUT_YUV_30FPS_VSIZE_MAX (360) -#define OUT_YUV_30FPS_HSIZE_MAX (480) -#define OUT_YUV_60FPS_VSIZE_MAX (360) -#define OUT_YUV_60FPS_HSIZE_MAX (480) +#define OUT_YUV_15FPS_VSIZE_MAX (600) +#define OUT_YUV_15FPS_HSIZE_MAX (800) +#define OUT_YUV_30FPS_VSIZE_MAX (600) +#define OUT_YUV_30FPS_HSIZE_MAX (800) +#define OUT_YUV_60FPS_VSIZE_MAX (480) +#define OUT_YUV_60FPS_HSIZE_MAX (640) #define OUT_YUV_120FPS_VSIZE_MAX (240) #define OUT_YUV_120FPS_HSIZE_MAX (320) #define OUT_JPG_15FPS_VSIZE_MAX (1944) @@ -228,15 +228,38 @@ struct isx012_dev_s uint8_t i2c_addr; /* I2C address */ int i2c_freq; /* Frequency */ isx012_state_t state; /* ISX012 status */ - bool dma_state; /* true means "in DMA" */ uint8_t mode; /* ISX012 mode */ isx012_param_t param; /* ISX012 paramerters */ - void *video_priv; /* pointer to video private data */ }; typedef struct isx012_dev_s isx012_dev_t; -#define ARRAY_NENTRIES(a) (sizeof(a)/sizeof(isx012_reg_t)) +struct isx012_scene_params_s +{ + uint8_t mode; /* enum v4l2_scene_mode */ + + /* Parameters for ctrl_class = V4L2_CTRL_CLASS_USER */ + + int8_t brightness; /* id = V4L2_CID_BRIGHTNESS */ + uint8_t contrast; /* id = V4L2_CID_CONTRAST */ + uint8_t saturation; /* id = V4L2_CID_SATURATION */ + uint8_t hue; /* id = V4L2_CID_HUE */ + uint8_t sharpness; /* id = V4L2_CID_SHARPNESS */ + uint16_t gamma[ISX012_ELEMS_GAMMACURVE]; /* id = V4L2_CID_GAMMA_CURVE */ + + /* Parameters for ctrl_class = V4L2_CTRL_CLASS_CAMERA */ + + uint16_t exptime; /* id = V4L2_CID_EXPOSURE_ABSOLUTE */ + bool exptime_auto; /* id = V4L2_CID_EXPOSURE_AUTO */ + uint8_t iso; /* id = V4L2_CID_ISO_SENSITIVITY */ + bool iso_auto; /* id = V4L2_CID_ISO_SENSITIVITY_AUTO */ + uint8_t expmeter; /* id = V4L2_CID_EXPOSURE_METERING */ + uint8_t wb; /* id = V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE */ +}; + +typedef struct isx012_scene_params_s isx012_scene_params_t; + +#define ARRAY_NENTRIES(a) (sizeof(a)/sizeof(a[0])) /**************************************************************************** * Private Function Prototypes @@ -269,17 +292,20 @@ static int isx012_set_supported_frminterval(uint32_t fps_index, FAR struct v4l2_fract *interval); static int8_t isx012_get_maximum_fps(FAR struct v4l2_frmivalenum *frmival); static int isx012_set_shd(FAR isx012_dev_t *priv); - static bool is_movie_needed(isx012_modeparam_t *param); +static int reflect_scene_parameter(FAR isx012_dev_t *priv, + FAR struct isx012_scene_params_s *params); +static int leave_scene(FAR isx012_dev_t *priv); +static struct isx012_scene_params_s *search_snparam_tbl + (enum v4l2_scene_mode mode); -/* video driver HAL infterface */ +/* image sensor device operations interface */ -static int isx012_open(FAR void *video_private); +static int isx012_open(void); static int isx012_close(void); static int isx012_do_halfpush(bool enable); static int isx012_set_buftype(enum v4l2_buf_type type); -static int isx012_set_buf(uint32_t bufaddr, uint32_t bufsize); -static int isx012_cancel_dma(void); +static enum v4l2_buf_type isx012_get_buftype(void); static int isx012_check_fmt(enum v4l2_buf_type buf_type, uint32_t pixel_format); static int isx012_get_range_of_fmt(FAR struct v4l2_fmtdesc *format); @@ -287,6 +313,7 @@ static int isx012_get_range_of_framesize(FAR struct v4l2_frmsizeenum *frmsize); static int isx012_try_format(FAR struct v4l2_format *format); static int isx012_set_format(FAR struct v4l2_format *format); +static int isx012_get_format(FAR struct v4l2_format *format); static int isx012_get_range_of_frameinterval(FAR struct v4l2_frmivalenum *frmival); static int isx012_set_frameinterval(FAR struct v4l2_streamparm *parm); @@ -294,9 +321,20 @@ static int isx012_get_range_of_ctrlval(FAR struct v4l2_query_ext_ctrl *range); static int isx012_get_menu_of_ctrlval(FAR struct v4l2_querymenu *menu); static int isx012_get_ctrlval(uint16_t ctrl_class, - FAR struct v4l2_ext_control *control); + FAR struct v4l2_ext_control *control); static int isx012_set_ctrlval(uint16_t ctrl_class, - FAR struct v4l2_ext_control *control); + FAR struct v4l2_ext_control *control); +static int isx012_get_range_of_sceneparam(enum v4l2_scene_mode mode, + FAR struct v4l2_query_ext_ctrl + * range); +static int isx012_get_menu_of_sceneparam(enum v4l2_scene_mode mode, + FAR struct v4l2_querymenu *menu); +static int isx012_get_sceneparam(enum v4l2_scene_mode mode, + uint16_t ctrl_class, + FAR struct v4l2_ext_control *control); +static int isx012_set_sceneparam(enum v4l2_scene_mode mode, + uint16_t ctrl_class, + FAR struct v4l2_ext_control *control); static int isx012_refresh(void); /**************************************************************************** @@ -348,6 +386,7 @@ static const isx012_reg_t g_isx012_def_init[] = { {INCK_SET, 0x17, 0x01}, /* INCK_SET */ #endif {FRM_FIX_SN1_2, 0xff, 0x01}, /* Fix framerate */ + {FRM_FIX_SN3_4, 0xff, 0x01}, /* Fix framerate */ {FAST_MODECHG_EN, 0x01, 0x01}, {FAST_SHT_MODE_SEL, 0x01, 0x01}, {CAP_HALF_AE_CTRL, 0x07, 0x01}, /* HAFREL=HIGHSPEED, CAP=Auto */ @@ -356,6 +395,41 @@ static const isx012_reg_t g_isx012_def_init[] = { {FASTMOVE_TIMEOUT, 0x2d, 0x01}, {YGAMMA_MODE, 0x01, 0x01}, {INT_QLTY2, 0x50, 0x01}, + {AE_SN1, 0x00, 0x01}, /* SN1 use TYPE1 */ + {AE_SN2, 0x28, 0x01}, /* SN2 use TYPE2 */ + {AE_SN3, 0x50, 0x01}, /* SN3 use TYPE3 */ + {PICT3_GAMMA_MONI0, 0x39, 0x01}, /* SN1 use GAMMA0 table + * SN2 use GAMMA1 table + * SN3 use GAMMA2 table + */ + {PICT3_GAMMA_CAP0, 0x39, 0x01}, /* SN1 use GAMMA0 table + * SN2 use GAMMA1 table + * SN3 use GAMMA2 table + */ + {PICT3_GAMMA_MOVIE0, 0x39, 0x01},/* SN1 use GAMMA0 table + * SN2 use GAMMA1 table + * SN3 use GAMMA2 table + */ + /* The following settings(prefix = G1_ and G2_) are same as GAMMA0 table */ + + {G1_LOWGM_ON_R, 0x0611, 0x02}, + {G1_0CLIP_R, 0x1e0a, 0x02}, + {G1_LOWGM_ON_G, 0x0611, 0x02}, + {G1_0CLIP_G, 0x1e0a, 0x02}, + {G1_LOWGM_ON_B, 0x0611, 0x02}, + {G1_0CLIP_B, 0x1e0a, 0x02}, + {G2_LOWGM_ON_R, 0x0611, 0x02}, + {G2_0CLIP_R, 0x1e0a, 0x02}, + {G2_LOWGM_ON_G, 0x0611, 0x02}, + {G2_0CLIP_G, 0x1e0a, 0x02}, + {G2_LOWGM_ON_B, 0x0611, 0x02}, + {G2_0CLIP_B, 0x1e0a, 0x02}, + + {PICT1_SN_3, 0xaa, 0x01}, /* SN3 use TYPE3 */ + {AELINE_MONI_SN3_4, 0x00, 0x01}, /* same setting as SN1_2 */ + {AELINE_HALF_SN3_4, 0x11, 0x01}, /* same setting as SN1_2 */ + {AELINE_CAP_SN3_4, 0x00, 0x01}, /* same setting as SN1_2 */ + {AELINE_MOVIE_SN3_4,0x22, 0x01}, /* same setting as SN1_2 */ }; #define ISX012_RESET_NENTRIES ARRAY_NENTRIES(g_isx012_def_init) @@ -616,27 +690,265 @@ static isx012_conv_v4l2_to_regval_t {1600 * 1000, REGVAL_ISO_1600} }; -static struct video_devops_s g_isx012_video_devops = +static struct video_sensctrl_ops_s g_isx012_sensctrl_ops = { .open = isx012_open, .close = isx012_close, .do_halfpush = isx012_do_halfpush, .set_buftype = isx012_set_buftype, - .set_buf = isx012_set_buf, - .cancel_dma = isx012_cancel_dma, + .get_buftype = isx012_get_buftype, .get_range_of_fmt = isx012_get_range_of_fmt, .get_range_of_framesize = isx012_get_range_of_framesize, .try_format = isx012_try_format, .set_format = isx012_set_format, + .get_format = isx012_get_format, .get_range_of_frameinterval = isx012_get_range_of_frameinterval, .set_frameinterval = isx012_set_frameinterval, .get_range_of_ctrlvalue = isx012_get_range_of_ctrlval, .get_menu_of_ctrlvalue = isx012_get_menu_of_ctrlval, .get_ctrlvalue = isx012_get_ctrlval, .set_ctrlvalue = isx012_set_ctrlval, + .get_range_of_sceneparam = isx012_get_range_of_sceneparam, + .get_menu_of_sceneparam = isx012_get_menu_of_sceneparam, + .get_sceneparam = isx012_get_sceneparam, + .set_sceneparam = isx012_set_sceneparam, .refresh = isx012_refresh, }; +/* Scene parameters */ + +static struct isx012_scene_params_s g_isx012_scene_params[] = +{ +#ifdef CONFIG_VIDEO_ISX012_SCENE_BACKLIGHT + {V4L2_SCENE_MODE_BACKLIGHT, /* mode */ + 0, /* brightness */ + 0x80, /* contrast */ + 0x80, /* saturation */ + 0, /* hue */ + 0x20, /* sharpness */ + {0, 7, 29, 47, 61, 74, 81, 90, 97, 106, + 73, 130, 173, 204, 225, 237, 246, 262, 268}, /* gamma */ + 0, /* exptime */ + false, /* exptime_auto */ + 0, /* iso */ + false, /* iso_auto */ + 0x01, /* expmeter */ + 0x20}, /* wb */ +#endif /* CONFIG_VIDEO_ISX012_SCENE_BACKLIGHT */ +#ifdef CONFIG_VIDEO_ISX012_SCENE_BEACHSNOW + {V4L2_SCENE_MODE_BEACH_SNOW, /* mode */ + 0, /* brightness */ + 0x80, /* contrast */ + 0x80, /* saturation */ + 0, /* hue */ + 0x20, /* sharpness */ + {0, 7, 29, 47, 61, 74, 81, 90, 97, 106, + 73, 130, 173, 204, 225, 237, 246, 262, 268}, /* gamma */ + 0, /* exptime */ + false, /* exptime_auto */ + 0, /* iso */ + false, /* iso_auto */ + 0x01, /* expmeter */ + 0x20}, /* wb */ +#endif /* CONFIG_VIDEO_ISX012_SCENE_BEACHSNOW */ +#ifdef CONFIG_VIDEO_ISX012_SCENE_CANDLELIGHT + {V4L2_SCENE_MODE_CANDLE_LIGHT, /* mode */ + 0, /* brightness */ + 0x80, /* contrast */ + 0x80, /* saturation */ + 0, /* hue */ + 0x20, /* sharpness */ + {0, 7, 29, 47, 61, 74, 81, 90, 97, 106, + 73, 130, 173, 204, 225, 237, 246, 262, 268}, /* gamma */ + 0, /* exptime */ + false, /* exptime_auto */ + 0, /* iso */ + false, /* iso_auto */ + 0x01, /* expmeter */ + 0x20}, /* wb */ +#endif /* CONFIG_VIDEO_ISX012_SCENE_CANDLELIGHT */ +#ifdef CONFIG_VIDEO_ISX012_SCENE_DAWNDUSK + {V4L2_SCENE_MODE_DAWN_DUSK, /* mode */ + 0, /* brightness */ + 0x80, /* contrast */ + 0x80, /* saturation */ + 0, /* hue */ + 0x20, /* sharpness */ + {0, 7, 29, 47, 61, 74, 81, 90, 97, 106, + 73, 130, 173, 204, 225, 237, 246, 262, 268}, /* gamma */ + 0, /* exptime */ + false, /* exptime_auto */ + 0, /* iso */ + false, /* iso_auto */ + 0x01, /* expmeter */ + 0x20}, /* wb */ +#endif /* CONFIG_VIDEO_ISX012_SCENE_DAWNDUSK */ +#ifdef CONFIG_VIDEO_ISX012_SCENE_FALLCOLORS + {V4L2_SCENE_MODE_FALL_COLORS, /* mode */ + 0, /* brightness */ + 0x80, /* contrast */ + 0x80, /* saturation */ + 0, /* hue */ + 0x20, /* sharpness */ + {0, 7, 29, 47, 61, 74, 81, 90, 97, 106, + 73, 130, 173, 204, 225, 237, 246, 262, 268}, /* gamma */ + 0, /* exptime */ + false, /* exptime_auto */ + 0, /* iso */ + false, /* iso_auto */ + 0x01, /* expmeter */ + 0x20}, /* wb */ +#endif /* CONFIG_VIDEO_ISX012_SCENE_FALLCOLORS */ +#ifdef CONFIG_VIDEO_ISX012_SCENE_FIREWORKS + {V4L2_SCENE_MODE_FIREWORKS, /* mode */ + 0, /* brightness */ + 0x80, /* contrast */ + 0x80, /* saturation */ + 0, /* hue */ + 0x20, /* sharpness */ + {0, 7, 29, 47, 61, 74, 81, 90, 97, 106, + 73, 130, 173, 204, 225, 237, 246, 262, 268}, /* gamma */ + 0, /* exptime */ + false, /* exptime_auto */ + 0, /* iso */ + false, /* iso_auto */ + 0x01, /* expmeter */ + 0x20}, /* wb */ +#endif /* CONFIG_VIDEO_ISX012_SCENE_FIREWORKS */ +#ifdef CONFIG_VIDEO_ISX012_SCENE_LANDSCAPE + {V4L2_SCENE_MODE_LANDSCAPE, /* mode */ + 0, /* brightness */ + 0x80, /* contrast */ + 0x80, /* saturation */ + 0, /* hue */ + 0x20, /* sharpness */ + {0, 7, 29, 47, 61, 74, 81, 90, 97, 106, + 73, 130, 173, 204, 225, 237, 246, 262, 268}, /* gamma */ + 0, /* exptime */ + false, /* exptime_auto */ + 0, /* iso */ + false, /* iso_auto */ + 0x01, /* expmeter */ + 0x20}, /* wb */ +#endif /* CONFIG_VIDEO_ISX012_SCENE_LANDSCAPE */ +#ifdef CONFIG_VIDEO_ISX012_SCENE_NIGHT + {V4L2_SCENE_MODE_NIGHT, /* mode */ + 0, /* brightness */ + 0x80, /* contrast */ + 0x80, /* saturation */ + 0, /* hue */ + 0x20, /* sharpness */ + {0, 7, 29, 47, 61, 74, 81, 90, 97, 106, + 73, 130, 173, 204, 225, 237, 246, 262, 268}, /* gamma */ + 0, /* exptime */ + false, /* exptime_auto */ + 0, /* iso */ + false, /* iso_auto */ + 0x01, /* expmeter */ + 0x20}, /* wb */ +#endif /* CONFIG_VIDEO_ISX012_SCENE_NIGHT */ +#ifdef CONFIG_VIDEO_ISX012_SCENE_PARTYINDOOR + {V4L2_SCENE_MODE_PARTY_INDOOR, /* mode */ + 0, /* brightness */ + 0x80, /* contrast */ + 0x80, /* saturation */ + 0, /* hue */ + 0x20, /* sharpness */ + {0, 7, 29, 47, 61, 74, 81, 90, 97, 106, + 73, 130, 173, 204, 225, 237, 246, 262, 268}, /* gamma */ + 0, /* exptime */ + false, /* exptime_auto */ + 0, /* iso */ + false, /* iso_auto */ + 0x01, /* expmeter */ + 0x20}, /* wb */ +#endif /* CONFIG_VIDEO_ISX012_SCENE_PARTYINDOOR */ +#ifdef CONFIG_VIDEO_ISX012_SCENE_PORTRAIT + {V4L2_SCENE_MODE_PORTRAIT, /* mode */ + 0, /* brightness */ + 0x80, /* contrast */ + 0x80, /* saturation */ + 0, /* hue */ + 0x20, /* sharpness */ + {0, 7, 29, 47, 61, 74, 81, 90, 97, 106, + 73, 130, 173, 204, 225, 237, 246, 262, 268}, /* gamma */ + 0, /* exptime */ + false, /* exptime_auto */ + 0, /* iso */ + false, /* iso_auto */ + 0x01, /* expmeter */ + 0x20}, /* wb */ +#endif /* CONFIG_VIDEO_ISX012_SCENE_PORTRAIT */ +#ifdef CONFIG_VIDEO_ISX012_SCENE_SPORTS + {V4L2_SCENE_MODE_SPORTS, /* mode */ + 0, /* brightness */ + 0x80, /* contrast */ + 0x80, /* saturation */ + 0, /* hue */ + 0x20, /* sharpness */ + {0, 7, 29, 47, 61, 74, 81, 90, 97, 106, + 73, 130, 173, 204, 225, 237, 246, 262, 268}, /* gamma */ + 0, /* exptime */ + false, /* exptime_auto */ + 0, /* iso */ + false, /* iso_auto */ + 0x01, /* expmeter */ + 0x20}, /* wb */ +#endif /* CONFIG_VIDEO_ISX012_SCENE_SPORTS */ +#ifdef CONFIG_VIDEO_ISX012_SCENE_SUNSET + {V4L2_SCENE_MODE_SUNSET, /* mode */ + 0, /* brightness */ + 0x80, /* contrast */ + 0x80, /* saturation */ + 0, /* hue */ + 0x20, /* sharpness */ + {0, 7, 29, 47, 61, 74, 81, 90, 97, 106, + 73, 130, 173, 204, 225, 237, 246, 262, 268}, /* gamma */ + 0, /* exptime */ + false, /* exptime_auto */ + 0, /* iso */ + false, /* iso_auto */ + 0x01, /* expmeter */ + 0x20}, /* wb */ +#endif /* CONFIG_VIDEO_ISX012_SCENE_SUNSET */ +#ifdef CONFIG_VIDEO_ISX012_SCENE_TEXT + {V4L2_SCENE_MODE_TEXT, /* mode */ + 0, /* brightness */ + 0x80, /* contrast */ + 0x80, /* saturation */ + 0, /* hue */ + 0x20, /* sharpness */ + {0, 7, 29, 47, 61, 74, 81, 90, 97, 106, + 73, 130, 173, 204, 225, 237, 246, 262, 268}, /* gamma */ + 0, /* exptime */ + false, /* exptime_auto */ + 0, /* iso */ + false, /* iso_auto */ + 0x01, /* expmeter */ + 0x20}, /* wb */ +#endif /* CONFIG_VIDEO_ISX012_SCENE_TEXT */ +}; + +static enum v4l2_scene_mode g_isx012_scene = V4L2_SCENE_MODE_NONE; +static uint8_t g_isx012_brightness = 0; +static uint8_t g_isx012_contrast = 0x80; + +/* address list for scene selection */ + +static uint16_t g_isx012_sat_addr[] + = {UISATURATION_TYPE1, UISATURATION_TYPE2, UISATURATION_TYPE3}; +static uint16_t g_isx012_hue_addr[] + = {UIHUE_TYPE1, UIHUE_TYPE2, UIHUE_TYPE3}; +static uint16_t g_isx012_gamma_addr[] + = {GAMMA_BASE, GAMMA1_BASE, GAMMA2_BASE}; +static uint16_t g_isx012_shrp_addr[] + = {UISHARPNESS_POS_TYPE1, UISHARPNESS_POS_TYPE2, UISHARPNESS_POS_TYPE3}; +static uint16_t g_isx012_exptime_addr[] + = {SHT_PREMODE_TYPE1, SHT_PREMODE_TYPE2, SHT_PREMODE_TYPE3}; +static uint16_t g_isx012_wb_addr[] = {AWB_SN1, AWB_SN2, AWB_SN3}; +static uint16_t g_isx012_iso_addr[] = {ISO_TYPE1, ISO_TYPE2, ISO_TYPE3}; +static uint16_t g_isx012_meter_addr[] = {AE_SUB_SN1, AE_SUB_SN2, AE_SUB_SN3}; + /**************************************************************************** * Public Data ****************************************************************************/ @@ -806,6 +1118,180 @@ static bool is_movie_needed(isx012_modeparam_t *param) } +static int reflect_scene_parameter(FAR isx012_dev_t *priv, + FAR struct isx012_scene_params_s *params) +{ + int ret; + int cnt; + uint8_t sn; /* SCENE_SELECT register value */ + uint16_t sat; /* address of SATURATION */ + uint16_t hue; /* address of HUE */ + uint16_t shrp; /* address of SHARPNESS */ + uint16_t gamma; /* address of GAMMA */ + uint16_t expt; /* address of SHT_PREMODE */ + uint16_t iso; /* address of ISO */ + uint16_t meter; /* address of EXPOSURE_METERING */ + uint16_t wb; /* address of AWB */ + + /* toggle control SN2 <-> SN3 */ + + sn = isx012_getreg(priv, SCENE_SELECT, 1); + if (sn == 1) + { + sat = UISATURATION_TYPE3; + hue = UIHUE_TYPE3; + shrp = UISHARPNESS_POS_TYPE3; + gamma = GAMMA2_BASE; + expt = SHT_PREMODE_TYPE3; + iso = ISO_TYPE3; + meter = AE_SUB_SN3; + wb = AWB_SN3; + + sn = 2; + } + else + { + sat = UISATURATION_TYPE2; + hue = UIHUE_TYPE2; + shrp = UISHARPNESS_POS_TYPE2; + gamma = GAMMA1_BASE; + expt = SHT_PREMODE_TYPE2; + iso = ISO_TYPE2; + meter = AE_SUB_SN2; + wb = AWB_SN2; + + sn = 1; + } + + ret = isx012_putreg(priv, sat, params->saturation, 1); + if (ret < 0) + { + return ret; + } + + ret = isx012_putreg(priv, hue, params->hue, 1); + if (ret < 0) + { + return ret; + } + + ret = isx012_putreg(priv, shrp, params->sharpness, 1); + if (ret < 0) + { + return ret; + } + + for (cnt = 0; cnt < ISX012_ELEMS_GAMMACURVE; cnt++) + { + ret = isx012_putreg(priv, + gamma, + params->gamma[cnt], + ISX012_SIZE_GAMMACURVE); + if (ret < 0) + { + return ret; + } + + gamma = gamma + 2; + } + + ret = isx012_putreg(priv, expt, params->exptime_auto ? 0 : params->exptime, 2); + + if (ret < 0) + { + return ret; + } + + ret = isx012_putreg(priv, iso, params->iso_auto ? 0 : params->iso, 1); + + if (ret < 0) + { + return ret; + } + + ret = isx012_putreg(priv, meter, params->expmeter, 1); + if (ret < 0) + { + return ret; + } + + ret = isx012_putreg(priv, wb, params->wb, 1); + if (ret < 0) + { + return ret; + } + + ret = isx012_putreg(priv, SCENE_SELECT, sn, 1); + if (ret < 0) + { + return ret; + } + + ret = isx012_putreg(priv, UIBRIGHTNESS, params->brightness, 1); + if (ret < 0) + { + return ret; + } + + ret = isx012_putreg(priv, UICONTRAST, params->contrast, 1); + if (ret < 0) + { + return ret; + } + + return OK; +} + +static int leave_scene(FAR isx012_dev_t *priv) +{ + int ret; + + ret = isx012_putreg(priv, SCENE_SELECT, 0, 1); + if (ret < 0) + { + return ret; + } + + ret = isx012_putreg(priv, UIBRIGHTNESS, g_isx012_brightness, 1); + if (ret < 0) + { + return ret; + } + + ret = isx012_putreg(priv, UICONTRAST, g_isx012_contrast, 1); + if (ret < 0) + { + return ret; + } + + return OK; +} + +static struct isx012_scene_params_s *search_snparam_tbl + (enum v4l2_scene_mode mode) +{ + int cnt; + struct isx012_scene_params_s *sptbl = g_isx012_scene_params; + int size = ARRAY_NENTRIES(g_isx012_scene_params); + + for (cnt = 0; cnt < size; cnt++) + { + if (mode == sptbl->mode) + { + break; + } + + sptbl++; + } + + if (cnt >= size) + { + return NULL; + } + + return sptbl; +} + static int isx012_set_mode_param(isx012_dev_t *priv, enum v4l2_buf_type type, isx012_modeparam_t *param) @@ -931,28 +1417,6 @@ static int isx012_set_mode_param(isx012_dev_t *priv, return ret; } -void isx012_callback(uint8_t code, uint32_t size, uint32_t addr) -{ - enum v4l2_buf_type type; - FAR struct isx012_dev_s *priv = &g_isx012_private; - - if (priv->mode == REGVAL_MODESEL_CAP) - { - /* ISX012 capture mode => still capture */ - - type = V4L2_BUF_TYPE_STILL_CAPTURE; - } - else - { - /* ISX012 monitor/halfrelease/movie mode => video capture */ - - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - } - - video_common_notify_dma_done(code, type, size, priv->video_priv); - - return; -} /**************************************************************************** * isx012_change_camera_mode @@ -1264,7 +1728,7 @@ int init_isx012(FAR struct isx012_dev_s *priv) return ret; } -static int isx012_open(FAR void *video_private) +static int isx012_open(void) { FAR struct isx012_dev_s *priv = &g_isx012_private; int ret = 0; @@ -1285,17 +1749,6 @@ static int isx012_open(FAR void *video_private) return ret; } - ret = cxd56_cisifinit(); - if (ret < 0) - { - imagererr("Fail cxd56_cisifinit %d\n", ret); - return ret; - } - - /* Save video private information address */ - - g_isx012_private.video_priv = video_private; - return ret; } @@ -1303,8 +1756,6 @@ static int isx012_close(void) { FAR struct isx012_dev_s *priv = &g_isx012_private; - g_isx012_private.video_priv = NULL; - int ret = 0; if (priv->state == STATE_ISX012_ACTIVE) @@ -1321,20 +1772,6 @@ static int isx012_close(void) return ret; } - ret = cxd56_cisifstopcapture(); - if (ret < 0) - { - imagererr("Fail cxd56_cisifstopcapture %d\n", ret); - return ret; - } - - ret = cxd56_cisiffinalize(); - if (ret < 0) - { - imagererr("Fail cxd56_cisiffinalize %d\n", ret); - return ret; - } - priv->i2c_freq = I2CFREQ_STANDARD; priv->state = STATE_ISX012_POWEROFF; @@ -1436,87 +1873,22 @@ static int isx012_set_buftype(enum v4l2_buf_type type) return ret; } -static int isx012_set_buf(uint32_t bufaddr, uint32_t bufsize) +static enum v4l2_buf_type isx012_get_buftype(void) { - int ret; FAR struct isx012_dev_s *priv = &g_isx012_private; - cisif_param_t cis_param = {0}; - cisif_sarea_t sarea = {0}; - isx012_modeparam_t *mode_param = NULL; - sarea.strg_addr = (uint8_t *)bufaddr; - sarea.strg_size = bufsize; - - if (priv->dma_state) + if (priv->mode == REGVAL_MODESEL_CAP) { - ret = cxd56_cisifsetdmabuf(&sarea); + /* ISX012 capture mode => still capture */ + + return V4L2_BUF_TYPE_STILL_CAPTURE; } else { - if (priv->mode == REGVAL_MODESEL_CAP) - { - mode_param = &priv->param.still; - } - else - { - mode_param = &priv->param.video; - } - - switch (mode_param->format) - { - case V4L2_PIX_FMT_UYVY: /* Set YUV 4:2:2 information */ - - cis_param.yuv_param.hsize = mode_param->hsize; - cis_param.yuv_param.vsize = mode_param->vsize; - - break; - - case V4L2_PIX_FMT_JPEG: /* Set JPEG information */ - - /* no setting */ - - break; - - case V4L2_PIX_FMT_JPEG_WITH_SUBIMG: /* Set JPEG + YUV 4:2:2 information */ - - cis_param.yuv_param.hsize = mode_param->int_hsize; - cis_param.yuv_param.vsize = mode_param->int_vsize; - - break; - - default: /* Unsupported format */ - - return -EINVAL; - } - - cis_param.format = mode_param->format; - cis_param.comp_func = isx012_callback; - - ret = cxd56_cisifstartcapture(&cis_param, &sarea); - if (ret != OK) - { - return ret; - } - - priv->dma_state = true; - } - - return ret; -} - -static int isx012_cancel_dma(void) -{ - int ret; - FAR struct isx012_dev_s *priv = &g_isx012_private; + /* ISX012 monitor/halfrelease/movie mode => video capture */ - ret = cxd56_cisifstopcapture(); - if (ret != OK) - { - return ret; + return V4L2_BUF_TYPE_VIDEO_CAPTURE; } - - priv->dma_state = false; - return ret; } static int isx012_check_fmt(enum v4l2_buf_type buf_type, @@ -1793,6 +2165,30 @@ static int isx012_set_format(FAR struct v4l2_format *format) return OK; } +static int isx012_get_format(FAR struct v4l2_format *format) +{ + FAR struct isx012_dev_s *priv = &g_isx012_private; + FAR isx012_modeparam_t *current_param; + + if (format->type == V4L2_BUF_TYPE_STILL_CAPTURE) + { + current_param = &priv->param.still; + } + else + { + current_param = &priv->param.video; + } + + format->fmt.pix.pixelformat = current_param->format; + format->fmt.pix.subimg_pixelformat = V4L2_PIX_FMT_UYVY; + format->fmt.pix.width = current_param->hsize; + format->fmt.pix.height = current_param->vsize; + format->fmt.pix.subimg_width = current_param->int_hsize; + format->fmt.pix.subimg_height = current_param->int_vsize; + + return OK; +} + static int isx012_set_supported_frminterval(uint32_t fps_index, FAR struct v4l2_fract *interval) { @@ -1822,6 +2218,12 @@ static int isx012_set_supported_frminterval(uint32_t fps_index, break; + case REGVAL_FPSTYPE_10FPS: + interval->numerator = 1; + interval->denominator = 10; + + break; + case REGVAL_FPSTYPE_7_5FPS: interval->numerator = 2; interval->denominator = 15; @@ -2011,6 +2413,10 @@ static int isx012_change_fraction_to_fps(FAR struct v4l2_fract *interval) { return REGVAL_FPSTYPE_15FPS; } + else if (interval->denominator == interval->numerator * 10) /* 10FPS */ + { + return REGVAL_FPSTYPE_10FPS; + } else if(interval->denominator * 10 == interval->numerator * 75) /* 7.5FPS */ { return REGVAL_FPSTYPE_7_5FPS; @@ -2416,6 +2822,18 @@ static int isx012_get_range_of_ctrlval(FAR struct v4l2_query_ext_ctrl *range) break; + case V4L2_CID_SCENE_MODE: + range->type = V4L2_CTRL_TYPE_INTEGER_MENU; + range->minimum = 0; + range->maximum = ARRAY_NENTRIES(g_isx012_scene_params); + range->step = 1; + range->default_value = V4L2_SCENE_MODE_NONE; + strncpy(range->name, + "Scene Mode", + sizeof(range->name)); + + break; + default: /* Unsupported control id */ return -EINVAL; @@ -2515,6 +2933,23 @@ static int isx012_get_menu_of_ctrlval(FAR struct v4l2_querymenu *menu) break; + case V4L2_CID_SCENE_MODE: + if (menu->index > ARRAY_NENTRIES(g_isx012_scene_params)) + { + return -EINVAL; + } + + if (menu->index == 0) + { + menu->value = V4L2_SCENE_MODE_NONE; + } + else + { + menu->value = g_isx012_scene_params[menu->index - 1].mode; + } + + break; + default: /* Unsupported control id */ return -EINVAL; @@ -2540,12 +2975,20 @@ static int isx012_get_ctrlval(uint16_t ctrl_class, uint16_t read_src; uint16_t *read_dst; int ret = -EINVAL; + int sn; if (control == NULL) { return -EINVAL; } + /* This driver use only SN1, SN2 and SN3 registers. + * So, sn > 2 is impossible. + */ + + sn = isx012_getreg(priv, SCENE_SELECT, 1); + ASSERT(sn <= 2); + switch (ctrl_class) { case V4L2_CTRL_CLASS_USER: @@ -2565,13 +3008,13 @@ static int isx012_get_ctrlval(uint16_t ctrl_class, case V4L2_CID_SATURATION: control->value = isx012_getreg(priv, - ISX012_REG_SATURATION, + g_isx012_sat_addr[sn], ISX012_SIZE_SATURATION); break; case V4L2_CID_HUE: control->value = isx012_getreg(priv, - ISX012_REG_HUE, + g_isx012_hue_addr[sn], ISX012_SIZE_HUE); break; @@ -2599,7 +3042,7 @@ static int isx012_get_ctrlval(uint16_t ctrl_class, return -EINVAL; } - read_src = ISX012_REG_GAMMACURVE; + read_src = g_isx012_gamma_addr[sn]; read_dst = control->p_u16; for (cnt = 0; cnt < ISX012_ELEMS_GAMMACURVE; cnt++) @@ -2685,7 +3128,7 @@ static int isx012_get_ctrlval(uint16_t ctrl_class, case V4L2_CID_SHARPNESS: control->value = isx012_getreg(priv, - ISX012_REG_SHARPNESS, + g_isx012_shrp_addr[sn], ISX012_SIZE_SHARPNESS); break; @@ -2740,7 +3183,7 @@ static int isx012_get_ctrlval(uint16_t ctrl_class, { case V4L2_CID_EXPOSURE_AUTO: readvalue = isx012_getreg(priv, - ISX012_REG_EXPOSURETIME, + g_isx012_exptime_addr[sn], ISX012_SIZE_EXPOSURETIME); if (readvalue) @@ -2756,14 +3199,19 @@ static int isx012_get_ctrlval(uint16_t ctrl_class, case V4L2_CID_EXPOSURE_ABSOLUTE: control->value = isx012_getreg(priv, - ISX012_REG_EXPOSURETIME, + g_isx012_exptime_addr[sn], ISX012_SIZE_EXPOSURETIME); break; + case V4L2_CID_SCENE_MODE: + control->value = g_isx012_scene; + + break; + case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE: readvalue = isx012_getreg(priv, - ISX012_REG_PRESETWB, + g_isx012_wb_addr[sn], ISX012_SIZE_PRESETWB); for (cnt = 0; cnt <= ISX012_MAX_PRESETWB; cnt++) @@ -2801,7 +3249,7 @@ static int isx012_get_ctrlval(uint16_t ctrl_class, case V4L2_CID_ISO_SENSITIVITY: readvalue = isx012_getreg(priv, - ISX012_REG_ISO, + g_isx012_iso_addr[sn], ISX012_SIZE_ISO); for (cnt = 0; cnt <= ISX012_MAX_ISO; cnt++) @@ -2824,7 +3272,7 @@ static int isx012_get_ctrlval(uint16_t ctrl_class, case V4L2_CID_ISO_SENSITIVITY_AUTO: readvalue = isx012_getreg(priv, - ISX012_REG_ISOAUTO, + g_isx012_iso_addr[sn], ISX012_SIZE_ISOAUTO); if (readvalue == REGVAL_ISO_AUTO) { @@ -2838,7 +3286,7 @@ static int isx012_get_ctrlval(uint16_t ctrl_class, case V4L2_CID_EXPOSURE_METERING: readvalue = isx012_getreg(priv, - ISX012_REG_PHOTOMETRY, + g_isx012_meter_addr[sn], ISX012_SIZE_PHOTOMETRY); for (cnt = 0; cnt <= ISX012_MAX_PHOTOMETRY; cnt++) @@ -2967,12 +3415,21 @@ static int isx012_set_ctrlval(uint16_t ctrl_class, uint16_t regval; uint16_t exposure_time_lsb; uint16_t exposure_time_msb; + struct isx012_scene_params_s *sptbl; + uint8_t sn; if (control == NULL) { return -EINVAL; } + /* This driver use only SN1, SN2 and SN3 registers. + * So, sn > 2 is impossible. + */ + + sn = isx012_getreg(priv, SCENE_SELECT, 1); + ASSERT(sn <= 2); + switch (ctrl_class) { case V4L2_CTRL_CLASS_USER: @@ -2988,6 +3445,20 @@ static int isx012_set_ctrlval(uint16_t ctrl_class, ISX012_REG_BRIGHTNESS, control->value, ISX012_SIZE_BRIGHTNESS); + if (ret < 0) + { + break; + } + + /* This register is updated if scene is selected. + * So, save original value to be able to restore. + */ + + sn = isx012_getreg(priv, SCENE_SELECT, 1); + if (sn == 0) + { + g_isx012_brightness = control->value; + } break; @@ -3001,17 +3472,31 @@ static int isx012_set_ctrlval(uint16_t ctrl_class, ISX012_REG_CONTRAST, control->value, ISX012_SIZE_CONTRAST); + if (ret < 0) + { + break; + } - break; + /* This register is updated if scene is selected. + * So, save original value to be able to restore. + */ - case V4L2_CID_SATURATION: - CHECK_RANGE(control->value, + sn = isx012_getreg(priv, SCENE_SELECT, 1); + if (sn == 0) + { + g_isx012_contrast = control->value; + } + + break; + + case V4L2_CID_SATURATION: + CHECK_RANGE(control->value, ISX012_MIN_SATURATION, ISX012_MAX_SATURATION, ISX012_STEP_SATURATION); ret = isx012_putreg(priv, - ISX012_REG_SATURATION, + g_isx012_sat_addr[sn], control->value, ISX012_SIZE_SATURATION); @@ -3024,7 +3509,7 @@ static int isx012_set_ctrlval(uint16_t ctrl_class, ISX012_STEP_HUE); ret = isx012_putreg(priv, - ISX012_REG_HUE, + g_isx012_hue_addr[sn], control->value, ISX012_SIZE_HUE); @@ -3071,7 +3556,7 @@ static int isx012_set_ctrlval(uint16_t ctrl_class, } write_src = control->p_u16; - write_dst = ISX012_REG_GAMMACURVE; + write_dst = g_isx012_gamma_addr[sn]; for (cnt = 0; cnt < ISX012_ELEMS_GAMMACURVE; cnt++) { @@ -3215,7 +3700,7 @@ static int isx012_set_ctrlval(uint16_t ctrl_class, ISX012_STEP_SHARPNESS); ret = isx012_putreg(priv, - ISX012_REG_SHARPNESS, + g_isx012_shrp_addr[sn], control->value, ISX012_SIZE_SHARPNESS); @@ -3289,7 +3774,7 @@ static int isx012_set_ctrlval(uint16_t ctrl_class, */ ret = isx012_putreg(priv, - ISX012_REG_EXPOSURETIME, + g_isx012_exptime_addr[sn], REGVAL_EXPOSURETIME_AUTO, ISX012_SIZE_EXPOSURETIME); } @@ -3320,7 +3805,7 @@ static int isx012_set_ctrlval(uint16_t ctrl_class, | exposure_time_lsb) / ISX012_UNIT_EXPOSURETIME_US); ret = isx012_putreg(priv, - ISX012_REG_EXPOSURETIME, + g_isx012_exptime_addr[sn], regval, ISX012_SIZE_EXPOSURETIME); } @@ -3334,7 +3819,7 @@ static int isx012_set_ctrlval(uint16_t ctrl_class, ISX012_STEP_EXPOSURETIME); ret = isx012_putreg(priv, - ISX012_REG_EXPOSURETIME, + g_isx012_exptime_addr[sn], control->value, ISX012_SIZE_EXPOSURETIME); break; @@ -3378,7 +3863,7 @@ static int isx012_set_ctrlval(uint16_t ctrl_class, } ret = isx012_putreg(priv, - ISX012_REG_ISO, + g_isx012_iso_addr[sn], g_isx012_supported_iso[cnt].regval, ISX012_SIZE_ISO); @@ -3393,7 +3878,7 @@ static int isx012_set_ctrlval(uint16_t ctrl_class, if (control->value == V4L2_ISO_SENSITIVITY_AUTO) { ret = isx012_putreg(priv, - ISX012_REG_ISOAUTO, + g_isx012_iso_addr[sn], REGVAL_ISO_AUTO, ISX012_SIZE_ISOAUTO); } @@ -3405,7 +3890,7 @@ static int isx012_set_ctrlval(uint16_t ctrl_class, ISX012_REG_ISOAUTOVALUE, ISX012_SIZE_ISOAUTOVALUE); ret = isx012_putreg(priv, - ISX012_REG_ISO, + g_isx012_iso_addr[sn], regval, ISX012_SIZE_ISO); } @@ -3429,12 +3914,33 @@ static int isx012_set_ctrlval(uint16_t ctrl_class, } ret = isx012_putreg(priv, - ISX012_REG_PHOTOMETRY, + g_isx012_meter_addr[sn], g_isx012_supported_photometry[cnt].regval, ISX012_SIZE_PHOTOMETRY); break; + case V4L2_CID_SCENE_MODE: + if (control->value == V4L2_SCENE_MODE_NONE) + { + ret = leave_scene(priv); + } + else + { + sptbl = search_snparam_tbl(control->value); + if (sptbl) + { + ret = reflect_scene_parameter(priv, sptbl); + } + } + + if (ret == OK) + { + g_isx012_scene = control->value; + } + + break; + case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE: for (cnt = 0; cnt <= ISX012_MAX_PRESETWB; cnt++) { @@ -3451,7 +3957,7 @@ static int isx012_set_ctrlval(uint16_t ctrl_class, } ret = isx012_putreg(priv, - ISX012_REG_PRESETWB, + g_isx012_wb_addr[sn], g_isx012_supported_presetwb[cnt].regval, ISX012_SIZE_PRESETWB); @@ -3554,6 +4060,441 @@ static int isx012_set_ctrlval(uint16_t ctrl_class, return ret; } +static int isx012_get_range_of_sceneparam(enum v4l2_scene_mode mode, + FAR struct v4l2_query_ext_ctrl + * range) +{ + struct isx012_scene_params_s *sptbl; + + if (range == NULL) + { + return -EINVAL; + } + + sptbl = search_snparam_tbl(mode); + if (sptbl == NULL) + { + return -EINVAL; + } + + switch (range->ctrl_class) + { + case V4L2_CTRL_CLASS_USER: + switch (range->id) + { + case V4L2_CID_BRIGHTNESS: + case V4L2_CID_CONTRAST: + case V4L2_CID_SATURATION: + case V4L2_CID_HUE: + case V4L2_CID_SHARPNESS: + case V4L2_CID_GAMMA_CURVE: + break; + + default: + return -EINVAL; + } + + break; + + case V4L2_CTRL_CLASS_CAMERA: + switch (range->id) + { + case V4L2_CID_EXPOSURE_ABSOLUTE: + case V4L2_CID_EXPOSURE_AUTO: + case V4L2_CID_ISO_SENSITIVITY: + case V4L2_CID_ISO_SENSITIVITY_AUTO: + case V4L2_CID_EXPOSURE_METERING: + case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE: + break; + + default: + return -EINVAL; + } + + break; + + default: + return -EINVAL; + } + + return isx012_get_range_of_ctrlval(range); +} + +static int isx012_get_menu_of_sceneparam(enum v4l2_scene_mode mode, + FAR struct v4l2_querymenu *menu) +{ + struct isx012_scene_params_s *sptbl; + + if (menu == NULL) + { + return -EINVAL; + } + + sptbl = search_snparam_tbl(mode); + if (sptbl == NULL) + { + return -EINVAL; + } + + switch (menu->ctrl_class) + { + case V4L2_CTRL_CLASS_CAMERA: + switch (menu->id) + { + case V4L2_CID_ISO_SENSITIVITY: + case V4L2_CID_EXPOSURE_METERING: + case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE: + break; + + default: + return -EINVAL; + } + + break; + + default: + return -EINVAL; + } + + return isx012_get_menu_of_ctrlval(menu); +} + +static int isx012_get_sceneparam(enum v4l2_scene_mode mode, + uint16_t ctrl_class, + FAR struct v4l2_ext_control *control) +{ + int ret = -EINVAL; + int cnt; + struct isx012_scene_params_s *sptbl; + + sptbl = search_snparam_tbl(mode); + if (sptbl == NULL) + { + return -EINVAL; + } + + switch (ctrl_class) + { + case V4L2_CTRL_CLASS_USER: + switch (control->id) + { + case V4L2_CID_BRIGHTNESS: + control->value = sptbl->brightness; + break; + + case V4L2_CID_CONTRAST: + control->value = sptbl->contrast; + break; + + case V4L2_CID_SATURATION: + control->value = sptbl->saturation; + break; + + case V4L2_CID_HUE: + control->value = sptbl->hue; + break; + + case V4L2_CID_SHARPNESS: + control->value = sptbl->sharpness; + break; + + case V4L2_CID_GAMMA_CURVE: + memcpy(control->p_u16, sptbl->gamma, ISX012_ELEMS_GAMMACURVE); + break; + + default: + return -EINVAL; + } + + break; + + case V4L2_CTRL_CLASS_CAMERA: + switch (control->id) + { + case V4L2_CID_EXPOSURE_ABSOLUTE: + control->value = sptbl->exptime; + break; + + case V4L2_CID_EXPOSURE_AUTO: + if (sptbl->exptime_auto) + { + control->value = V4L2_EXPOSURE_AUTO; + } + else + { + control->value = V4L2_EXPOSURE_MANUAL; + } + + break; + + case V4L2_CID_ISO_SENSITIVITY: + for (cnt = 0; cnt <= ISX012_MAX_ISO; cnt++) + { + if (g_isx012_supported_iso[cnt].regval + == sptbl->iso) + { + ret = OK; + break; + } + } + + if (ret != OK) + { + return ret; + } + + control->value = g_isx012_supported_iso[cnt].v4l2; + break; + + case V4L2_CID_ISO_SENSITIVITY_AUTO: + control->value = sptbl->iso_auto; + break; + + case V4L2_CID_EXPOSURE_METERING: + for (cnt = 0; cnt <= ISX012_MAX_PHOTOMETRY; cnt++) + { + if (g_isx012_supported_photometry[cnt].regval + == sptbl->expmeter) + { + ret = OK; + break; + } + } + + if (ret != OK) + { + return ret; + } + + control->value = g_isx012_supported_photometry[cnt].v4l2; + break; + + case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE: + for (cnt = 0; cnt <= ISX012_MAX_PRESETWB; cnt++) + { + if (g_isx012_supported_presetwb[cnt].regval == sptbl->wb) + { + ret = OK; + break; + } + } + + if (ret != OK) + { + return ret; + } + + control->value = g_isx012_supported_presetwb[cnt].v4l2; + break; + + default: + return -EINVAL; + } + + break; + + default: + return -EINVAL; + } + + return OK; +} + +static int isx012_set_sceneparam(enum v4l2_scene_mode mode, + uint16_t ctrl_class, + FAR struct v4l2_ext_control *control) +{ + int ret = -EINVAL; + int cnt; + uint16_t *p_val; + struct isx012_scene_params_s *sptbl; + + sptbl = search_snparam_tbl(mode); + if (sptbl == NULL) + { + return -EINVAL; + } + + switch (ctrl_class) + { + case V4L2_CTRL_CLASS_USER: + switch (control->id) + { + case V4L2_CID_BRIGHTNESS: + CHECK_RANGE(control->value, + ISX012_MIN_BRIGHTNESS, + ISX012_MAX_BRIGHTNESS, + ISX012_STEP_BRIGHTNESS); + + sptbl->brightness = control->value; + break; + + case V4L2_CID_CONTRAST: + CHECK_RANGE(control->value, + ISX012_MIN_CONTRAST, + ISX012_MAX_CONTRAST, + ISX012_STEP_CONTRAST); + + sptbl->contrast = control->value; + break; + + case V4L2_CID_SATURATION: + CHECK_RANGE(control->value, + ISX012_MIN_SATURATION, + ISX012_MAX_SATURATION, + ISX012_STEP_SATURATION); + + sptbl->saturation = control->value; + break; + + case V4L2_CID_HUE: + CHECK_RANGE(control->value, + ISX012_MIN_HUE, + ISX012_MAX_HUE, + ISX012_STEP_HUE); + + sptbl->hue = control->value; + break; + + case V4L2_CID_SHARPNESS: + CHECK_RANGE(control->value, + ISX012_MIN_SHARPNESS, + ISX012_MAX_SHARPNESS, + ISX012_STEP_SHARPNESS); + + sptbl->sharpness = control->value; + break; + + case V4L2_CID_GAMMA_CURVE: + p_val = control->p_u16; + for (cnt = 0; cnt < ISX012_ELEMS_GAMMACURVE; cnt++) + { + CHECK_RANGE(*p_val, + ISX012_MIN_GAMMACURVE, + ISX012_MAX_GAMMACURVE, + ISX012_STEP_GAMMACURVE); + p_val++; + } + + memcpy(sptbl->gamma, control->p_u16, ISX012_ELEMS_GAMMACURVE); + break; + + default: + return -EINVAL; + } + + break; + + case V4L2_CTRL_CLASS_CAMERA: + switch (control->id) + { + case V4L2_CID_EXPOSURE_ABSOLUTE: + CHECK_RANGE(control->value, + ISX012_MIN_EXPOSURETIME, + ISX012_MAX_EXPOSURETIME, + ISX012_STEP_EXPOSURETIME); + + sptbl->exptime = control->value; + sptbl->exptime_auto = false; + break; + + case V4L2_CID_EXPOSURE_AUTO: + CHECK_RANGE(control->value, + ISX012_MIN_EXPOSUREAUTO, + ISX012_MAX_EXPOSUREAUTO, + ISX012_STEP_EXPOSUREAUTO); + + if (control->value == V4L2_EXPOSURE_AUTO) + { + sptbl->exptime_auto = true; + } + else + { + sptbl->exptime_auto = false; + } + + break; + + case V4L2_CID_ISO_SENSITIVITY: + for (cnt = 0; cnt <= ISX012_MAX_ISO; cnt++) + { + if (g_isx012_supported_iso[cnt].v4l2 + == control->value) + { + ret = OK; + break; + } + } + + if (ret != OK) + { + return ret; + } + + sptbl->iso = g_isx012_supported_iso[cnt].regval; + sptbl->iso_auto = false; + break; + + case V4L2_CID_ISO_SENSITIVITY_AUTO: + CHECK_RANGE(control->value, + ISX012_MIN_ISOAUTO, + ISX012_MAX_ISOAUTO, + ISX012_STEP_ISOAUTO); + + sptbl->iso_auto = control->value; + break; + + case V4L2_CID_EXPOSURE_METERING: + for (cnt = 0; cnt <= ISX012_MAX_PHOTOMETRY; cnt++) + { + if (g_isx012_supported_photometry[cnt].v4l2 + == control->value) + { + ret = OK; + break; + } + } + + if (ret != OK) + { + return ret; + } + + sptbl->expmeter = g_isx012_supported_photometry[cnt].regval; + + break; + + case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE: + for (cnt = 0; cnt <= ISX012_MAX_PRESETWB; cnt++) + { + if (g_isx012_supported_presetwb[cnt].v4l2 == control->value) + { + ret = OK; + break; + } + } + + if (ret != OK) + { + return ret; + } + + sptbl->wb = g_isx012_supported_presetwb[cnt].regval; + break; + + default: + return -EINVAL; + } + + break; + + default: + return -EINVAL; + } + + return OK; +} + static int isx012_refresh(void) { int ret = 0; @@ -3831,11 +4772,11 @@ int isx012_unregister(void) return OK; } -FAR struct video_devops_s *isx012_initialize(void) +FAR struct video_sensctrl_ops_s *isx012_initialize(void) { - /* return address of video operations variable */ + /* return address of image senser device operations variable */ - return &g_isx012_video_devops; + return &g_isx012_sensctrl_ops; } int isx012_uninitialize(void) diff --git a/drivers/video/video.c b/drivers/video/video.c index d728b59adf7..23fbb34aa6f 100644 --- a/drivers/video/video.c +++ b/drivers/video/video.c @@ -1,7 +1,7 @@ /**************************************************************************** * drivers/video/video.c * - * Copyright 2018 Sony Semiconductor Solutions Corporation + * Copyright 2018, 2020 Sony Semiconductor Solutions Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -90,6 +90,14 @@ #define videoinfo(x...) #endif +#ifndef MIN +# define MIN(a,b) (a < b ? a : b) +#endif + +#ifndef MAX +# define MAX(a,b) (a > b ? a : b) +#endif + /**************************************************************************** * Private Types ****************************************************************************/ @@ -139,6 +147,14 @@ struct video_type_inf_s typedef struct video_type_inf_s video_type_inf_t; +struct video_fmtlist_s +{ + uint16_t num; + struct v4l2_fmtdesc *fmt; +}; + +typedef struct video_fmtlist_s video_fmtlist_t; + struct video_mng_s { FAR char *devpath; /* parameter of video_initialize() */ @@ -147,6 +163,8 @@ struct video_mng_s FAR struct pollfd *poll_wait; /* poll(setup) information */ video_type_inf_t video_inf; video_type_inf_t still_inf; + video_fmtlist_t video_fmtlist; + video_fmtlist_t still_fmtlist; }; typedef struct video_mng_s video_mng_t; @@ -179,6 +197,9 @@ static bool is_taking_still_picture(FAR video_mng_t *vmng); static bool is_bufsize_sufficient(FAR video_mng_t *vmng, uint32_t bufsize); static void cleanup_resources(FAR video_mng_t *vmng); static bool is_sem_waited(FAR sem_t *sem); +static int create_supported_fmtlist(enum v4l2_buf_type type, + video_fmtlist_t *list); +static void destroy_supported_fmtlist(video_fmtlist_t *list); /* internal function for each cmds of ioctl */ @@ -190,7 +211,8 @@ static int video_dqbuf(FAR struct video_mng_s *vmng, FAR struct v4l2_buffer *buf); static int video_cancel_dqbuf(FAR struct video_mng_s *vmng, enum v4l2_buf_type type); -static int video_enum_fmt(FAR struct v4l2_fmtdesc *fmt); +static int video_enum_fmt(FAR struct video_mng_s *vmng, + FAR struct v4l2_fmtdesc *fmt); static int video_enum_framesizes(FAR struct v4l2_frmsizeenum *frmsize); static int video_s_fmt(FAR struct video_mng_s *priv, FAR struct v4l2_format *fmt); @@ -217,6 +239,11 @@ static int video_g_ext_ctrls(FAR struct video_mng_s *priv, FAR struct v4l2_ext_controls *ctrls); static int video_s_ext_ctrls(FAR struct video_mng_s *priv, FAR struct v4l2_ext_controls *ctrls); +static int video_query_ext_ctrl_scene(FAR struct v4s_query_ext_ctrl_scene + *ctrl); +static int video_querymenu_scene(FAR struct v4s_querymenu_scene *menu); +static int video_g_ext_ctrls_scene(FAR struct v4s_ext_controls_scene *ctrls); +static int video_s_ext_ctrls_scene(FAR struct v4s_ext_controls_scene *ctrls); /**************************************************************************** * Private Data @@ -242,7 +269,8 @@ static bool is_initialized = false; * Public Data ****************************************************************************/ -FAR const struct video_devops_s *g_video_devops; +FAR const struct video_sensctrl_ops_s *g_video_sensctrl_ops; +FAR const struct video_imgdata_ops_s *g_video_imgdata_ops; /**************************************************************************** * Private Functions @@ -353,6 +381,7 @@ static void change_video_state(FAR video_mng_t *vmng, enum video_state_e current_state = vmng->video_inf.state; enum video_state_e updated_next_state = next_state; FAR vbuf_container_t *dma_container; + struct v4l2_format format; if ((current_state != VIDEO_STATE_DMA) && (next_state == VIDEO_STATE_DMA)) @@ -361,9 +390,13 @@ static void change_video_state(FAR video_mng_t *vmng, video_framebuff_get_dma_container(&vmng->video_inf.bufinf); if (dma_container) { - g_video_devops->set_buftype(V4L2_BUF_TYPE_VIDEO_CAPTURE); - g_video_devops->set_buf(dma_container->buf.m.userptr, - dma_container->buf.length); + g_video_sensctrl_ops->set_buftype(V4L2_BUF_TYPE_VIDEO_CAPTURE); + + format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + g_video_sensctrl_ops->get_format(&format); + g_video_imgdata_ops->start_dma(&format, + dma_container->buf.m.userptr, + dma_container->buf.length); } else { @@ -375,7 +408,7 @@ static void change_video_state(FAR video_mng_t *vmng, if ((current_state == VIDEO_STATE_DMA) && (next_state != VIDEO_STATE_DMA)) { - g_video_devops->cancel_dma(); + g_video_imgdata_ops->cancel_dma(); } } @@ -436,7 +469,7 @@ static void cleanup_resources(FAR video_mng_t *vmng) { /* If in DMA, stop */ - g_video_devops->cancel_dma(); + g_video_imgdata_ops->cancel_dma(); } cleanup_streamresources(&vmng->video_inf); @@ -461,6 +494,98 @@ static bool is_sem_waited(FAR sem_t *sem) } } +static int create_supported_fmtlist(enum v4l2_buf_type type, + video_fmtlist_t *list) +{ + int ret = -EINVAL; + struct v4l2_fmtdesc capa_sensctrl = {0}; + struct v4l2_fmtdesc *supported_fmt; + + if (list == NULL) + { + ASSERT(false); + return -EINVAL; + } + + if ((g_video_sensctrl_ops == NULL) || + (g_video_imgdata_ops == NULL) || + (g_video_sensctrl_ops->get_range_of_fmt == NULL) || + (g_video_imgdata_ops->chk_pixelformat == NULL)) + { + return -EINVAL; + } + + /* Loop to find formats that is supported by both sensor control operation + * and image data operation. + * Returns the format associated with fmt->index from such formats. + */ + + capa_sensctrl.type = type; + + do + { + if (g_video_sensctrl_ops->get_range_of_fmt(&capa_sensctrl) + != OK) + { + break; + } + + /* Check whether image data operations I/F support the format supported + * by sensor control operations I/F or not. + */ + + if (g_video_imgdata_ops->chk_pixelformat + (capa_sensctrl.pixelformat, + capa_sensctrl.subimg_pixelformat) == OK) + { + if (list->num == 0) + { + list->fmt = (struct v4l2_fmtdesc *)malloc(sizeof(struct v4l2_fmtdesc)); + } + else + { + list->fmt = (struct v4l2_fmtdesc *)realloc + (list->fmt, sizeof(struct v4l2_fmtdesc) * (list->num + 1)); + } + + if (list->fmt == NULL) + { + return -ENOMEM; + } + + supported_fmt = &list->fmt[list->num]; + + supported_fmt->index = list->num; + supported_fmt->type = type; + supported_fmt->flags = capa_sensctrl.flags; + supported_fmt->pixelformat = capa_sensctrl.pixelformat; + supported_fmt->subimg_pixelformat = capa_sensctrl.subimg_pixelformat; + strncpy(supported_fmt->description, + capa_sensctrl.description, + V4L2_FMT_DSC_MAX); + + list->num++; + ret = OK; + } + + /* Increment index to check next format */ + + capa_sensctrl.index++; + } + while (1); + + return ret; +} + +static void destroy_supported_fmtlist(video_fmtlist_t *list) +{ + if (list->fmt != NULL) + { + free(list->fmt); + list->fmt = NULL; + } +} + static int video_open(FAR struct file *filep) { FAR struct inode *inode = filep->f_inode; @@ -472,10 +597,14 @@ static int video_open(FAR struct file *filep) { /* Only in first execution, open device */ - ret = g_video_devops->open(priv); + ret = g_video_sensctrl_ops->open(); if (ret == OK) { - initialize_resources(priv); + ret = g_video_imgdata_ops->open(priv); + if (ret == OK) + { + initialize_resources(priv); + } } } @@ -507,7 +636,8 @@ static int video_close(FAR struct file *filep) if (priv->open_num == 0) { cleanup_resources(priv); - g_video_devops->close(); + g_video_sensctrl_ops->close(); + g_video_imgdata_ops->close(); } video_unlock(&priv->lock_open_num); @@ -558,6 +688,7 @@ static int video_qbuf(FAR struct video_mng_s *vmng, { FAR video_type_inf_t *type_inf; FAR vbuf_container_t *container; + struct v4l2_format format; enum video_state_e next_video_state; irqstate_t flags; @@ -605,9 +736,14 @@ static int video_qbuf(FAR struct video_mng_s *vmng, container = video_framebuff_get_dma_container(&type_inf->bufinf); if (container) { - g_video_devops->set_buftype(buf->type); - g_video_devops->set_buf(container->buf.m.userptr, - container->buf.length); + g_video_sensctrl_ops->set_buftype(buf->type); + + format.type = buf->type; + g_video_sensctrl_ops->get_format(&format); + g_video_imgdata_ops->start_dma(&format, + container->buf.m.userptr, + container->buf.length); + type_inf->state = VIDEO_STATE_DMA; } } @@ -721,46 +857,235 @@ static int video_cancel_dqbuf(FAR struct video_mng_s *vmng, return OK; } -static int video_enum_fmt(FAR struct v4l2_fmtdesc *fmt) +static int video_enum_fmt(FAR struct video_mng_s *vmng, + FAR struct v4l2_fmtdesc *fmt) { - int ret; + video_fmtlist_t *list; - if ((g_video_devops == NULL) || - (g_video_devops->get_range_of_fmt == NULL)) + if (vmng == NULL) { return -EINVAL; } - ret = g_video_devops->get_range_of_fmt(fmt); + switch (fmt->type) + { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + list = &vmng->video_fmtlist; + break; - return ret; + case V4L2_BUF_TYPE_STILL_CAPTURE: + list = &vmng->still_fmtlist; + break; + + default: + return -EINVAL; + } + + if (fmt->index >= list->num) + { + return -EINVAL; + } + + memcpy(fmt, &list->fmt[fmt->index], sizeof(struct v4l2_fmtdesc)); + + return OK; +} + +/* Greatest Common devisor */ + +static uint16_t gcd(uint16_t a, uint16_t b) +{ + uint16_t r; + while ((r = (a % b))) + { + a = b; + b = r; + } + + return b; +} + +/* Least Common Multiple */ + +static uint16_t lcm(uint16_t a, uint16_t b) +{ + return (b ? (a / gcd(a,b)) * b : 0); } static int video_enum_framesizes(FAR struct v4l2_frmsizeenum *frmsize) { - int ret; + int ret = -EINVAL; + int supported_num = 0; + struct v4l2_frmsizeenum capa_imgdata = {0}; + struct v4l2_frmsizeenum capa_sensctrl = {0}; + struct v4l2_format format = {0}; - if ((g_video_devops == NULL) || - (g_video_devops->get_range_of_framesize == NULL)) + if ((g_video_sensctrl_ops == NULL) || + (g_video_imgdata_ops == NULL) || + (g_video_sensctrl_ops->get_range_of_framesize == NULL) || + (g_video_imgdata_ops->get_range_of_framesize == NULL)) { return -EINVAL; } - ret = g_video_devops->get_range_of_framesize(frmsize); + /* Find the range supported by both image data operations I/F + * and sensor control operations I/F. + */ - return ret; + capa_imgdata.buf_type = frmsize->buf_type; + capa_imgdata.pixel_format = frmsize->pixel_format; + capa_imgdata.subimg_pixel_format = frmsize->subimg_pixel_format; + + ret = g_video_imgdata_ops->get_range_of_framesize(&capa_imgdata); + if (ret != OK) + { + return ret; + } + + capa_sensctrl.buf_type = frmsize->buf_type; + capa_sensctrl.pixel_format = frmsize->pixel_format; + capa_sensctrl.subimg_pixel_format = frmsize->subimg_pixel_format; + + do + { + if (g_video_sensctrl_ops->get_range_of_framesize(&capa_sensctrl) + != OK) + { + break; + } + + if (capa_sensctrl.type == V4L2_FRMSIZE_TYPE_DISCRETE) + { + /* In sensor control operations I/F capability has the discrete type, + * query to image data operation's I/F + * whether the discrete value is supported or not. + */ + + format.type = capa_sensctrl.buf_type; + format.fmt.pix.pixelformat = capa_sensctrl.pixel_format; + format.fmt.pix.subimg_pixelformat = capa_sensctrl.subimg_pixel_format; + format.fmt.pix.width = capa_sensctrl.discrete.width; + format.fmt.pix.height = capa_sensctrl.discrete.height; + format.fmt.pix.subimg_width = capa_sensctrl.subimg.discrete.width; + format.fmt.pix.subimg_height = capa_sensctrl.subimg.discrete.height; + + ret = g_video_imgdata_ops->try_format(&format); + if (ret == OK) + { + if (frmsize->index == supported_num) + { + /* Return this discrete value */ + + frmsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; + frmsize->discrete.width = capa_sensctrl.discrete.width; + frmsize->discrete.height = capa_sensctrl.discrete.height; + frmsize->subimg_type = V4L2_FRMSIZE_TYPE_DISCRETE; + frmsize->subimg.discrete.width = capa_sensctrl.subimg.discrete.width; + frmsize->subimg.discrete.height = capa_sensctrl.subimg.discrete.height; + + break; + } + + supported_num++; + } + + /* Increment index to check next discrete value */ + + capa_sensctrl.index++; + } + else + { + /* Merge image data operation's capability + * and sensor control capability. + */ + + /* step_width is LCM(least common multiple). */ + + frmsize->stepwise.step_width = lcm(capa_imgdata.stepwise.step_width, + capa_sensctrl.stepwise.step_width); + + frmsize->subimg.stepwise.step_width = lcm(capa_imgdata.subimg.stepwise.step_width, + capa_sensctrl.subimg.stepwise.step_width); + + /* step_height is LCM(least common multiple). */ + + frmsize->stepwise.step_height = lcm(capa_imgdata.stepwise.step_height, + capa_sensctrl.stepwise.step_height); + + frmsize->subimg.stepwise.step_height = lcm(capa_imgdata.subimg.stepwise.step_height, + capa_sensctrl.subimg.stepwise.step_height); + + /* minimum is the larger. */ + + frmsize->stepwise.min_width + = MAX(capa_sensctrl.stepwise.min_width, + capa_imgdata.stepwise.min_width); + + frmsize->stepwise.min_height + = MAX(capa_sensctrl.stepwise.min_height, + capa_imgdata.stepwise.min_height); + + frmsize->subimg.stepwise.min_width + = MAX(capa_sensctrl.subimg.stepwise.min_width, + capa_imgdata.subimg.stepwise.min_width); + + frmsize->subimg.stepwise.min_height + = MAX(capa_sensctrl.subimg.stepwise.min_height, + capa_imgdata.subimg.stepwise.min_height); + + /* maximum is the smaller. */ + + frmsize->stepwise.max_width + = MIN(capa_sensctrl.stepwise.max_width, + capa_imgdata.stepwise.max_width); + + frmsize->stepwise.max_height + = MIN(capa_sensctrl.stepwise.max_height, + capa_imgdata.stepwise.max_height); + + frmsize->subimg.stepwise.max_width + = MIN(capa_sensctrl.subimg.stepwise.max_width, + capa_imgdata.subimg.stepwise.max_width); + + frmsize->subimg.stepwise.max_height + = MIN(capa_sensctrl.subimg.stepwise.max_height, + capa_imgdata.subimg.stepwise.max_height); + + frmsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; + frmsize->subimg_type = V4L2_FRMSIZE_TYPE_STEPWISE; + + ret = OK; + break; + } + } + while (1); + + return OK; } static int video_try_fmt(FAR struct v4l2_format *fmt) { int ret; - if ((g_video_devops == NULL) || (g_video_devops->try_format == NULL)) + if ((g_video_sensctrl_ops == NULL) || + (g_video_imgdata_ops == NULL) || + (g_video_sensctrl_ops->try_format == NULL) || + (g_video_imgdata_ops->try_format == NULL)) { return -EINVAL; } - ret = g_video_devops->try_format(fmt); + /* Check both image data operations I/F capability and image sensor capability. + * Return OK only in case both checks are OK. + */ + + ret = g_video_imgdata_ops->try_format(fmt); + if (ret != OK) + { + return ret; + } + + ret = g_video_sensctrl_ops->try_format(fmt); return ret; } @@ -770,12 +1095,25 @@ static int video_s_fmt(FAR struct video_mng_s *priv, { int ret; - if ((g_video_devops == NULL) || (g_video_devops->set_format == NULL)) + if ((g_video_sensctrl_ops == NULL) || + (g_video_imgdata_ops == NULL) || + (g_video_sensctrl_ops->set_format == NULL) || + (g_video_imgdata_ops->try_format == NULL)) { return -EINVAL; } - ret = g_video_devops->set_format(fmt); + /* If image data operations I/F do not support the specified format, + * return error without controlling sensor control operations I/F. + */ + + ret = g_video_imgdata_ops->try_format(fmt); + if (ret != 0) + { + return ret; + } + + ret = g_video_sensctrl_ops->set_format(fmt); return ret; } @@ -784,13 +1122,13 @@ static int video_enum_frameintervals(FAR struct v4l2_frmivalenum *frmival) { int ret; - if ((g_video_devops == NULL) || - (g_video_devops->get_range_of_frameinterval == NULL)) + if ((g_video_sensctrl_ops == NULL) || + (g_video_sensctrl_ops->get_range_of_frameinterval == NULL)) { return -EINVAL; } - ret = g_video_devops->get_range_of_frameinterval(frmival); + ret = g_video_sensctrl_ops->get_range_of_frameinterval(frmival); return ret; } @@ -800,13 +1138,13 @@ static int video_s_parm(FAR struct video_mng_s *priv, { int ret; - if ((g_video_devops == NULL) || - (g_video_devops->set_frameinterval == NULL)) + if ((g_video_sensctrl_ops == NULL) || + (g_video_sensctrl_ops->set_frameinterval == NULL)) { return -EINVAL; } - ret = g_video_devops->set_frameinterval(parm); + ret = g_video_sensctrl_ops->set_frameinterval(parm); return ret; } @@ -900,12 +1238,12 @@ static int video_streamoff(FAR struct video_mng_s *vmng, static int video_do_halfpush(bool enable) { - if ((g_video_devops == NULL) || (g_video_devops->do_halfpush == NULL)) + if ((g_video_sensctrl_ops == NULL) || (g_video_sensctrl_ops->do_halfpush == NULL)) { return -EINVAL; } - return g_video_devops->do_halfpush(enable); + return g_video_sensctrl_ops->do_halfpush(enable); } static int video_takepict_start(FAR struct video_mng_s *vmng, @@ -914,6 +1252,7 @@ static int video_takepict_start(FAR struct video_mng_s *vmng, irqstate_t flags; enum video_state_e next_video_state; FAR vbuf_container_t *dma_container; + struct v4l2_format format; int ret = OK; if (vmng == NULL) @@ -925,43 +1264,48 @@ static int video_takepict_start(FAR struct video_mng_s *vmng, if (vmng->still_inf.state != VIDEO_STATE_STREAMOFF) { - ret = -EPERM; + ret = -EPERM; } else { - if (capture_num > 0) + if (capture_num > 0) { - vmng->still_inf.remaining_capnum = capture_num; + vmng->still_inf.remaining_capnum = capture_num; } - else + else { - vmng->still_inf.remaining_capnum = VIDEO_REMAINING_CAPNUM_INFINITY; + vmng->still_inf.remaining_capnum = VIDEO_REMAINING_CAPNUM_INFINITY; } - /* Control video stream prior to still stream */ + /* Control video stream prior to still stream */ - flags = enter_critical_section(); + flags = enter_critical_section(); - next_video_state = estimate_next_video_state(vmng, - CAUSE_STILL_START); - change_video_state(vmng, next_video_state); + next_video_state = estimate_next_video_state(vmng, + CAUSE_STILL_START); + change_video_state(vmng, next_video_state); - leave_critical_section(flags); + leave_critical_section(flags); - dma_container = video_framebuff_get_dma_container + dma_container = video_framebuff_get_dma_container (&vmng->still_inf.bufinf); - if (dma_container) + if (dma_container) { - /* Start video stream DMA */ + /* Start video stream DMA */ + + g_video_sensctrl_ops->set_buftype(V4L2_BUF_TYPE_STILL_CAPTURE); - g_video_devops->set_buftype(V4L2_BUF_TYPE_STILL_CAPTURE); - g_video_devops->set_buf(dma_container->buf.m.userptr, - dma_container->buf.length); - vmng->still_inf.state = VIDEO_STATE_DMA; + format.type = V4L2_BUF_TYPE_STILL_CAPTURE; + g_video_sensctrl_ops->get_format(&format); + g_video_imgdata_ops->start_dma(&format, + dma_container->buf.m.userptr, + dma_container->buf.length); + + vmng->still_inf.state = VIDEO_STATE_DMA; } - else + else { - vmng->still_inf.state = VIDEO_STATE_STREAMON; + vmng->still_inf.state = VIDEO_STATE_STREAMON; } } @@ -993,7 +1337,7 @@ static int video_takepict_stop(FAR struct video_mng_s *vmng, bool halfpush) flags = enter_critical_section(); if (vmng->still_inf.state == VIDEO_STATE_DMA) { - g_video_devops->cancel_dma(); + g_video_imgdata_ops->cancel_dma(); } leave_critical_section(flags); @@ -1063,13 +1407,13 @@ static int video_query_ext_ctrl(FAR struct v4l2_query_ext_ctrl *ctrl) { int ret; - if ((g_video_devops == NULL) || - (g_video_devops->get_range_of_ctrlvalue == NULL)) + if ((g_video_sensctrl_ops == NULL) || + (g_video_sensctrl_ops->get_range_of_ctrlvalue == NULL)) { return -EINVAL; } - ret = g_video_devops->get_range_of_ctrlvalue(ctrl); + ret = g_video_sensctrl_ops->get_range_of_ctrlvalue(ctrl); return ret; } @@ -1078,13 +1422,13 @@ static int video_querymenu(FAR struct v4l2_querymenu *menu) { int ret; - if ((g_video_devops == NULL) || - (g_video_devops->get_menu_of_ctrlvalue == NULL)) + if ((g_video_sensctrl_ops == NULL) || + (g_video_sensctrl_ops->get_menu_of_ctrlvalue == NULL)) { return -EINVAL; } - ret = g_video_devops->get_menu_of_ctrlvalue(menu); + ret = g_video_sensctrl_ops->get_menu_of_ctrlvalue(menu); return ret; } @@ -1167,7 +1511,7 @@ static int video_g_ext_ctrls(FAR struct video_mng_s *priv, cnt < ctrls->count; cnt++, control++) { - ret = g_video_devops->get_ctrlvalue(ctrls->ctrl_class, control); + ret = g_video_sensctrl_ops->get_ctrlvalue(ctrls->ctrl_class, control); if (ret < 0) { @@ -1197,7 +1541,7 @@ static int video_s_ext_ctrls(FAR struct video_mng_s *priv, cnt < ctrls->count; cnt++, control++) { - ret = g_video_devops->set_ctrlvalue(ctrls->ctrl_class, control); + ret = g_video_sensctrl_ops->set_ctrlvalue(ctrls->ctrl_class, control); if (ret < 0) { @@ -1211,6 +1555,104 @@ static int video_s_ext_ctrls(FAR struct video_mng_s *priv, return ret; } +static int video_query_ext_ctrl_scene(FAR struct v4s_query_ext_ctrl_scene *ctrl) +{ + int ret; + + if ((ctrl == NULL) || + (g_video_sensctrl_ops == NULL) || + (g_video_sensctrl_ops->get_range_of_sceneparam == NULL)) + { + return -EINVAL; + } + + ret = g_video_sensctrl_ops->get_range_of_sceneparam(ctrl->mode, + &ctrl->control); + + return ret; +} + +static int video_querymenu_scene(FAR struct v4s_querymenu_scene *menu) +{ + int ret; + + if ((menu == NULL) || + (g_video_sensctrl_ops == NULL) || + (g_video_sensctrl_ops->get_menu_of_sceneparam == NULL)) + { + return -EINVAL; + } + + ret = g_video_sensctrl_ops->get_menu_of_sceneparam(menu->mode, + &menu->menu); + + return ret; +} + +static int video_g_ext_ctrls_scene(FAR struct v4s_ext_controls_scene *ctrls) +{ + int ret = OK; + int cnt; + FAR struct v4l2_ext_control *control; + + if ((ctrls == NULL) || + (g_video_sensctrl_ops == NULL) || + (g_video_sensctrl_ops->get_sceneparam == NULL)) + { + return -EINVAL; + } + + for (cnt = 0, control = ctrls->control.controls; + cnt < ctrls->control.count; + cnt++, control++) + { + ret = g_video_sensctrl_ops->get_sceneparam(ctrls->mode, + ctrls->control.ctrl_class, + control); + if (ret < 0) + { + /* Set cnt in that error occured */ + + ctrls->control.error_idx = cnt; + return ret; + } + } + + return ret; +} + +static int video_s_ext_ctrls_scene(FAR struct v4s_ext_controls_scene *ctrls) +{ + int ret = OK; + int cnt; + FAR struct v4l2_ext_control *control; + + if ((ctrls == NULL) || + (g_video_sensctrl_ops == NULL) || + (g_video_sensctrl_ops->set_sceneparam == NULL)) + { + return -EINVAL; + } + + for (cnt = 0, control = ctrls->control.controls; + cnt < ctrls->control.count; + cnt++, control++) + { + ret = g_video_sensctrl_ops->set_sceneparam(ctrls->mode, + ctrls->control.ctrl_class, + control); + if (ret < 0) + { + /* Set cnt in that error occured */ + + ctrls->control.error_idx = cnt; + return ret; + } + } + + return ret; +} + /**************************************************************************** * Name: video_ioctl * @@ -1273,7 +1715,7 @@ static int video_ioctl(FAR struct file *filep, int cmd, unsigned long arg) break; case VIDIOC_ENUM_FMT: - ret = video_enum_fmt((FAR struct v4l2_fmtdesc *)arg); + ret = video_enum_fmt(priv, (FAR struct v4l2_fmtdesc *)arg); break; @@ -1337,6 +1779,26 @@ static int video_ioctl(FAR struct file *filep, int cmd, unsigned long arg) break; + case V4SIOC_QUERY_EXT_CTRL_SCENE: + ret = video_query_ext_ctrl_scene((FAR struct v4s_query_ext_ctrl_scene *)arg); + + break; + + case V4SIOC_QUERYMENU_SCENE: + ret = video_querymenu_scene((FAR struct v4s_querymenu_scene *)arg); + + break; + + case V4SIOC_G_EXT_CTRLS_SCENE: + ret = video_g_ext_ctrls_scene((FAR struct v4s_ext_controls_scene *)arg); + + break; + + case V4SIOC_S_EXT_CTRLS_SCENE: + ret = video_s_ext_ctrls_scene((FAR struct v4s_ext_controls_scene *)arg); + + break; + default: videoerr("Unrecognized cmd: %d\n", cmd); ret = - ENOTTY; @@ -1483,6 +1945,15 @@ int video_initialize(FAR const char *devpath) video_handler = video_register(devpath); + /* Because supported format lists are not changed dynamically, + * create lists in initialization. + */ + + create_supported_fmtlist(V4L2_BUF_TYPE_VIDEO_CAPTURE, + &((video_mng_t *)video_handler)->video_fmtlist); + create_supported_fmtlist(V4L2_BUF_TYPE_STILL_CAPTURE, + &((video_mng_t *)video_handler)->still_fmtlist); + is_initialized = true; return OK; @@ -1494,6 +1965,10 @@ int video_uninitialize(void) { return OK; } + + destroy_supported_fmtlist(&((video_mng_t *)video_handler)->video_fmtlist); + destroy_supported_fmtlist(&((video_mng_t *)video_handler)->still_fmtlist); + video_unregister(video_handler); is_initialized = false; @@ -1501,14 +1976,19 @@ int video_uninitialize(void) return OK; } +/* Callback function which device driver call when dma has done. + * This function should be called in interrupt handler or + * in critical section. + */ + int video_common_notify_dma_done(uint8_t err_code, - uint32_t buf_type, uint32_t datasize, FAR void *priv) { FAR video_mng_t *vmng = (FAR video_mng_t *)priv; FAR video_type_inf_t *type_inf; FAR vbuf_container_t *container = NULL; + uint32_t buf_type = g_video_sensctrl_ops->get_buftype(); type_inf = get_video_type_inf(vmng, buf_type); if (type_inf == NULL) @@ -1549,7 +2029,7 @@ int video_common_notify_dma_done(uint8_t err_code, if (type_inf->remaining_capnum == 0) { - g_video_devops->cancel_dma(); + g_video_imgdata_ops->cancel_dma(); type_inf->state = VIDEO_STATE_STREAMOFF; /* If stop still stream, notify it to video stream */ @@ -1567,13 +2047,13 @@ int video_common_notify_dma_done(uint8_t err_code, container = video_framebuff_get_dma_container(&type_inf->bufinf); if (!container) { - g_video_devops->cancel_dma(); + g_video_imgdata_ops->cancel_dma(); type_inf->state = VIDEO_STATE_STREAMON; } else { - g_video_devops->set_buf(container->buf.m.userptr, - container->buf.length); + g_video_imgdata_ops->set_dmabuf(container->buf.m.userptr, + container->buf.length); } } diff --git a/include/nuttx/net/wiznet.h b/include/nuttx/net/wiznet.h new file mode 100644 index 00000000000..2e123f80f0f --- /dev/null +++ b/include/nuttx/net/wiznet.h @@ -0,0 +1,195 @@ +/**************************************************************************** + * include/nuttx/net/wiznet.h + * + * Copyright 2020 Sony Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of Sony Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_NET_WIZNET_H +#define __INCLUDE_NUTTX_NET_WIZNET_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/**************************************************************************** + * Public Definitions + ****************************************************************************/ + +#define WIZNET_IOC_DEVICE _SIOC(0x002a) +#define WIZNET_IOC_SOCKET _SIOC(0x002b) +#define WIZNET_IOC_CONNECT _SIOC(0x002c) +#define WIZNET_IOC_SEND _SIOC(0x002d) +#define WIZNET_IOC_RECV _SIOC(0x002e) +#define WIZNET_IOC_CLOSE _SIOC(0x002f) +#define WIZNET_IOC_BIND _SIOC(0x0030) +#define WIZNET_IOC_LISTEN _SIOC(0x0031) +#define WIZNET_IOC_ACCEPT _SIOC(0x0032) +#define WIZNET_IOC_IFREQ _SIOC(0x0033) +#define WIZNET_IOC_NAME _SIOC(0x0034) + +/**************************************************************************** + * Public Data Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +#undef EXTERN +#if defined(__cplusplus) +# define EXTERN extern "C" +extern "C" +{ +#else +# define EXTERN extern +#endif + +/* NOTE: do not forget to update include/nuttx/net/ioctl.h */ + +struct wiznet_device_msg +{ + bool dhcp; + in_addr_t ipaddr; + in_addr_t draddr; + in_addr_t netmask; + in_addr_t dnsaddr; + uint64_t mac; +}; + +struct wiznet_socket_msg +{ + int sockfd; + int domain; + int type; + int protocol; +}; + +struct wiznet_connect_msg +{ + int sockfd; + int type; + struct sockaddr addr; + socklen_t addrlen; +}; + +struct wiznet_bind_msg +{ + int sockfd; + int type; + struct sockaddr addr; + socklen_t addrlen; +}; + +struct wiznet_listen_msg +{ + int sockfd; + int type; + int backlog; +}; + +struct wiznet_accept_msg +{ + int sockfd; + int type; + struct sockaddr addr; + socklen_t addrlen; +}; + +struct wiznet_send_msg +{ + int sockfd; + int type; + FAR uint8_t *buf; + size_t len; + int flags; + struct sockaddr addr; + socklen_t addrlen; + ssize_t result; +}; + +struct wiznet_recv_msg +{ + int sockfd; + int type; + FAR uint8_t *buf; + size_t len; + int flags; + struct sockaddr addr; + socklen_t addrlen; + ssize_t result; +}; + +struct wiznet_close_msg +{ + int sockfd; + int type; +}; + +struct wiznet_ifreq_msg +{ + uint32_t cmd; + struct ifreq ifr; +}; + +struct wiznet_name_msg +{ + int sockfd; + struct sockaddr addr; + socklen_t addrlen; + bool local; +}; + +struct wiznet_lower_s +{ + void (*attach)(bool attach, xcpt_t handler, FAR void *arg); + void (*enable)(bool enable); + void (*poweron)(bool on); +}; + +FAR void * wiznet_register(FAR const char *devpath, + FAR struct spi_dev_s *spi, + FAR const struct wiznet_lower_s *lower); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __INCLUDE_NUTTX_NET_WIZNET_H */ diff --git a/include/nuttx/video/isx012.h b/include/nuttx/video/isx012.h index 84d83b0f0dc..073b8019bd4 100644 --- a/include/nuttx/video/isx012.h +++ b/include/nuttx/video/isx012.h @@ -63,7 +63,7 @@ extern "C" /**************************************************************************** * Public Function Prototypes ****************************************************************************/ -FAR struct video_devops_s *isx012_initialize(void); +FAR struct video_sensctrl_ops_s *isx012_initialize(void); int isx012_uninitialize(void); #undef EXTERN diff --git a/include/nuttx/video/isx012_range.h b/include/nuttx/video/isx012_range.h index bba8607ef58..685e9e7f4a6 100644 --- a/include/nuttx/video/isx012_range.h +++ b/include/nuttx/video/isx012_range.h @@ -235,10 +235,10 @@ /* Definition for control exposure time */ #define ISX012_TYPE_EXPOSURETIME V4L2_CTRL_TYPE_INTEGER -#define ISX012_NAME_EXPOSURETIME "Exposure time(usec)" +#define ISX012_NAME_EXPOSURETIME "Exposure time(100 usec)" #define ISX012_DEF_EXPOSURETIME (0) #define ISX012_MIN_EXPOSURETIME (1) -#define ISX012_MAX_EXPOSURETIME (10000) +#define ISX012_MAX_EXPOSURETIME (21000) #define ISX012_STEP_EXPOSURETIME (1) #define ISX012_REG_EXPOSURETIME SHT_PREMODE_TYPE1 #define ISX012_SIZE_EXPOSURETIME (2) @@ -328,7 +328,7 @@ #define ISX012_TYPE_JPGQUALITY V4L2_CTRL_TYPE_INTEGER #define ISX012_NAME_JPGQUALITY "JPEG compression quality" -#define ISX012_DEF_JPGQUALITY (75) +#define ISX012_DEF_JPGQUALITY (80) #define ISX012_MIN_JPGQUALITY (1) #define ISX012_MAX_JPGQUALITY (100) #define ISX012_STEP_JPGQUALITY (1) diff --git a/include/nuttx/video/isx012_reg.h b/include/nuttx/video/isx012_reg.h index bd211dc5738..885a356a971 100644 --- a/include/nuttx/video/isx012_reg.h +++ b/include/nuttx/video/isx012_reg.h @@ -56,6 +56,8 @@ #define MODE_BASE (0x6A00) #define PICT_BASE (0x6C00) #define GAMMA_BASE (0x7000) +#define GAMMA1_BASE (0x7200) +#define GAMMA2_BASE (0x7400) #define JPEG_BASE (0x7800) #define AUTOCOM_BASE (0x7C00) #define VFRMPARA_BASE (0x8800) @@ -793,6 +795,18 @@ #define G0_0CLIP_B (GAMMA_BASE+0x0044) #define G0_KNOT_GAINCTRL_TH_L (GAMMA_BASE+0x0046) #define G0_KNOT_GAINCTRL_TH_H (GAMMA_BASE+0x0047) +#define G1_LOWGM_ON_R (GAMMA1_BASE+0x003A) +#define G1_0CLIP_R (GAMMA1_BASE+0x003C) +#define G1_LOWGM_ON_G (GAMMA1_BASE+0x003E) +#define G1_0CLIP_G (GAMMA1_BASE+0x0040) +#define G1_LOWGM_ON_B (GAMMA1_BASE+0x0042) +#define G1_0CLIP_B (GAMMA1_BASE+0x0044) +#define G2_LOWGM_ON_R (GAMMA2_BASE+0x003A) +#define G2_0CLIP_R (GAMMA2_BASE+0x003C) +#define G2_LOWGM_ON_G (GAMMA2_BASE+0x003E) +#define G2_0CLIP_G (GAMMA2_BASE+0x0040) +#define G2_LOWGM_ON_B (GAMMA2_BASE+0x0042) +#define G2_0CLIP_B (GAMMA2_BASE+0x0044) /* JPEG OFFSET */ diff --git a/include/nuttx/video/video.h b/include/nuttx/video/video.h index 0c6ab33dde4..adbe1e5b29e 100644 --- a/include/nuttx/video/video.h +++ b/include/nuttx/video/video.h @@ -163,6 +163,30 @@ extern "C" #define VIDIOC_CANCEL_DQBUF _VIDIOC(0x0016) +/* Query control for scene parameter + * Address pointing to struct v4s_query_ext_ctrl_scene + */ + +#define V4SIOC_QUERY_EXT_CTRL_SCENE _VIDIOC(0x0017) + +/* Query menu for scene parameter + * Address pointing to struct v4s_querymenu_scene + */ + +#define V4SIOC_QUERYMENU_SCENE _VIDIOC(0x0018) + +/* Get current control value + * Address pointing to struct v4s_ext_controls_scene + */ + +#define V4SIOC_G_EXT_CTRLS_SCENE _VIDIOC(0x0019) + +/* Set control value + * Address pointing to struct v4s_ext_controls_scene + */ + +#define V4SIOC_S_EXT_CTRLS_SCENE _VIDIOC(0x001a) + #define VIDEO_HSIZE_QVGA (320) /* QVGA horizontal size */ #define VIDEO_VSIZE_QVGA (240) /* QVGA vertical size */ #define VIDEO_HSIZE_VGA (640) /* VGA horizontal size */ @@ -618,7 +642,32 @@ struct v4l2_ext_controls struct v4l2_ext_control *controls; /* each control information */ }; -extern FAR const struct video_devops_s *g_video_devops; +/* Structure for V4SIOC_S_EXT_CTRLS and V4SIOC_G_EXT_CTRLS */ + +struct v4s_ext_controls_scene +{ + enum v4l2_scene_mode mode; /* scene mode to be controled */ + struct v4l2_ext_controls control; /* same as VIDIOC_S_EXT_CTRLS */ +}; + +/* Structure for V4SIOC_QUERY_EXT_CTRL */ + +struct v4s_query_ext_ctrl_scene +{ + enum v4l2_scene_mode mode; /* scene mode to be queried */ + struct v4l2_query_ext_ctrl control; /* same as VIDIOC_QUERY_EXT_CTRL */ +}; + +/* Structure for V4SIOC_QUERYMENU */ + +struct v4s_querymenu_scene +{ + enum v4l2_scene_mode mode; /* scene mode to be queried */ + struct v4l2_querymenu menu; /* same as VIDIOC_QUERYMENU */ +}; + +extern FAR const struct video_sensctrl_ops_s *g_video_sensctrl_ops; +extern FAR const struct video_imgdata_ops_s *g_video_imgdata_ops; /**************************************************************************** * Public Function Prototypes diff --git a/include/nuttx/video/video_halif.h b/include/nuttx/video/video_halif.h index 2518edc1598..78061fd3b4a 100644 --- a/include/nuttx/video/video_halif.h +++ b/include/nuttx/video/video_halif.h @@ -1,7 +1,7 @@ /**************************************************************************** * modules/include/video/video_halif.h * - * Copyright 2018 Sony Semiconductor Solutions Corporation + * Copyright 2018, 2020 Sony Semiconductor Solutions Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -45,19 +45,19 @@ * Public Types ****************************************************************************/ -struct video_devops_s +struct video_sensctrl_ops_s { - CODE int (*open)(FAR void *video_priv); + CODE int (*open)(void); CODE int (*close)(void); CODE int (*do_halfpush)(bool enable); CODE int (*set_buftype)(enum v4l2_buf_type type); - CODE int (*set_buf)(uint32_t bufaddr, uint32_t bufsize); - CODE int (*cancel_dma)(void); + CODE enum v4l2_buf_type (*get_buftype)(void); CODE int (*get_range_of_fmt)(FAR struct v4l2_fmtdesc *format); CODE int (*get_range_of_framesize)(FAR struct v4l2_frmsizeenum *frmsize); CODE int (*try_format)(FAR struct v4l2_format *format); CODE int (*set_format)(FAR struct v4l2_format *format); + CODE int (*get_format)(FAR struct v4l2_format *format); CODE int (*get_range_of_frameinterval) (FAR struct v4l2_frmivalenum *frmival); CODE int (*set_frameinterval)(FAR struct v4l2_streamparm *parm); @@ -67,9 +67,34 @@ struct video_devops_s FAR struct v4l2_ext_control *control); CODE int (*set_ctrlvalue)(uint16_t ctrl_class, FAR struct v4l2_ext_control *control); + CODE int (*get_range_of_sceneparam)(enum v4l2_scene_mode mode, + FAR struct v4l2_query_ext_ctrl *range); + CODE int (*get_menu_of_sceneparam)(enum v4l2_scene_mode mode, + FAR struct v4l2_querymenu *menu); + CODE int (*get_sceneparam)(enum v4l2_scene_mode mode, + uint16_t ctrl_class, + FAR struct v4l2_ext_control *control); + CODE int (*set_sceneparam)(enum v4l2_scene_mode mode, + uint16_t ctrl_class, + FAR struct v4l2_ext_control *control); CODE int (*refresh)(void); }; +struct video_imgdata_ops_s +{ + CODE int (*open)(FAR void *video_private); + CODE int (*close)(void); + CODE int (*start_dma)(FAR struct v4l2_format *format, + uint32_t bufaddr, + uint32_t bufsize); + CODE int (*set_dmabuf)(uint32_t bufaddr, uint32_t bufsize); + CODE int (*cancel_dma)(void); + CODE int (*get_range_of_framesize)(FAR struct v4l2_frmsizeenum *frmsize); + CODE int (*try_format)(FAR struct v4l2_format *format); + CODE int (*chk_pixelformat)(uint32_t pixelformat, + uint32_t subimg_pixelformat); +}; + /**************************************************************************** * Public Data ****************************************************************************/ @@ -86,8 +111,12 @@ extern "C" * Public Functions ****************************************************************************/ +/* Callback function which device driver call when dma has done. + * This function should be called in interrupt handler or + * in critical section. + */ + int video_common_notify_dma_done(uint8_t err_code, - uint32_t buf_type, uint32_t datasize, FAR void *priv); diff --git a/libs/libc/Makefile b/libs/libc/Makefile index d7d9cf68827..755754caf2b 100644 --- a/libs/libc/Makefile +++ b/libs/libc/Makefile @@ -195,10 +195,10 @@ endif .depend: Makefile $(SRCS) $(TOPDIR)$(DELIM).config ifeq ($(CONFIG_BUILD_FLAT),y) - $(Q) $(MKDEP) --obj-suffix $(OBJEXT) $(DEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >bin/Make.dep + $(Q) $(MKDEP) --obj-path bin --obj-suffix $(OBJEXT) $(DEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >bin/Make.dep else - $(Q) $(MKDEP) --obj-suffix $(OBJEXT) $(DEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >ubin/Make.dep - $(Q) $(MKDEP) --obj-suffix $(OBJEXT) $(DEPPATH) "$(CC)" -- $(CFLAGS) $(KDEFINE) -- $(SRCS) >kbin/Make.dep + $(Q) $(MKDEP) --obj-path ubin --obj-suffix $(OBJEXT) $(DEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >ubin/Make.dep + $(Q) $(MKDEP) --obj-path kbin --obj-suffix $(OBJEXT) $(DEPPATH) "$(CC)" -- $(CFLAGS) $(KDEFINE) -- $(SRCS) >kbin/Make.dep endif ifeq ($(CONFIG_LIB_ZONEINFO_ROMFS),y) $(Q) $(MAKE) -C zoneinfo depend TOPDIR=$(TOPDIR) BIN=$(BIN) diff --git a/libs/libnx/Makefile b/libs/libnx/Makefile index 605cd6f0fe3..c6ee3e07c57 100644 --- a/libs/libnx/Makefile +++ b/libs/libnx/Makefile @@ -262,10 +262,10 @@ endif .depend: Makefile gensources $(SRCS) $(TOPDIR)$(DELIM).config ifeq ($(CONFIG_BUILD_FLAT),y) - $(Q) $(MKDEP) --obj-suffix $(OBJEXT) $(DEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >bin/Make.dep + $(Q) $(MKDEP) --obj-path bin --obj-suffix $(OBJEXT) $(DEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >bin/Make.dep else - $(Q) $(MKDEP) --obj-suffix $(OBJEXT) $(DEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >ubin/Make.dep - $(Q) $(MKDEP) --obj-suffix $(OBJEXT) $(DEPPATH) "$(CC)" -- $(CFLAGS) $(KDEFINE) -- $(SRCS) >kbin/Make.dep + $(Q) $(MKDEP) --obj-path ubin --obj-suffix $(OBJEXT) $(DEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >ubin/Make.dep + $(Q) $(MKDEP) --obj-path kbin --obj-suffix $(OBJEXT) $(DEPPATH) "$(CC)" -- $(CFLAGS) $(KDEFINE) -- $(SRCS) >kbin/Make.dep endif $(Q) touch $@ diff --git a/mm/Makefile b/mm/Makefile index a2261ad82d8..171b2f77eea 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -109,10 +109,10 @@ endif .depend: Makefile $(SRCS) $(TOPDIR)$(DELIM).config ifeq ($(CONFIG_BUILD_FLAT),y) - $(Q) $(MKDEP) --obj-suffix $(OBJEXT) $(DEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >bin/Make.dep + $(Q) $(MKDEP) --obj-path bin --obj-suffix $(OBJEXT) $(DEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >bin/Make.dep else - $(Q) $(MKDEP) --obj-suffix $(OBJEXT) $(DEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >ubin/Make.dep - $(Q) $(MKDEP) --obj-suffix $(OBJEXT) $(DEPPATH) "$(CC)" -- $(CFLAGS) $(KDEFINE) -- $(SRCS) >kbin/Make.dep + $(Q) $(MKDEP) --obj-path ubin --obj-suffix $(OBJEXT) $(DEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >ubin/Make.dep + $(Q) $(MKDEP) --obj-path kbin --obj-suffix $(OBJEXT) $(DEPPATH) "$(CC)" -- $(CFLAGS) $(KDEFINE) -- $(SRCS) >kbin/Make.dep endif $(Q) touch $@ diff --git a/tools/checkpatch.sh b/tools/checkpatch.sh new file mode 100755 index 00000000000..5ba15d817f1 --- /dev/null +++ b/tools/checkpatch.sh @@ -0,0 +1,142 @@ +#!/usr/bin/env bash +# tools/checkpatch.sh +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to you under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +TOOLDIR=$(dirname $0) + +check=check_patch +fail=0 +range=0 +spell=0 + +usage() { + echo "USAGE: ${0} [options] [list|-]" + echo "" + echo "Options:" + echo "-h" + echo "-c spell check with codespell(install with: pip install codespell)" + echo "-r range check only (coupled with -p or -g)" + echo "-p (default)" + echo "-g " + echo "-f " + echo "- read standard input mainly used by git pre-commit hook as below:" + echo " git diff --cached | ./tools/checkpatch.sh -" + echo "Where a is any syntax supported by git for specifying git revision, see GITREVISIONS(7)" + echo "Where a is a space separated list of patch file names or wildcard. or *.patch" + + exit $@ +} + +check_file() { + if ! $TOOLDIR/nxstyle $@ 2>&1; then + fail=1 + fi + + if [ $spell != 0 ]; then + if ! codespell -q 7 ${@: -1}; then + fail=1 + fi + fi +} + +check_ranges() { + while read; do + if [[ $REPLY =~ ^(\+\+\+\ (b/)?([^[:blank:]]+).*)$ ]]; then + if [ "$ranges" != "" ]; then + if [ $range != 0 ]; then + check_file $ranges $path + else + check_file $path + fi + fi + path=$(realpath "${BASH_REMATCH[3]}") + ranges="" + elif [[ $REPLY =~ @@\ -[0-9]+(,[0-9]+)?\ \+([0-9]+,[0-9]+)?\ @@.* ]]; then + ranges+="-r ${BASH_REMATCH[2]} " + fi + done + if [ "$ranges" != "" ]; then + if [ $range != 0 ]; then + check_file $ranges $path + else + check_file $path + fi + fi +} + +check_patch() { + if ! git apply --check $1; then + fail=1 + else + git apply $1 + diffs=`cat $1` + check_ranges <<< "$diffs" + git apply -R $1 + fi +} + +check_commit() { + diffs=`git diff $1` + check_ranges <<< "$diffs" +} + +make -C $TOOLDIR -f Makefile.host nxstyle 1>/dev/null + +if [ -z "$1" ]; then + usage + exit 0 +fi + +while [ ! -z "$1" ]; do + case "$1" in + - ) + check_ranges + ;; + -c ) + spell=1 + ;; + -f ) + check=check_file + ;; + -g ) + check=check_commit + ;; + -h ) + usage 0 + ;; + -p ) + check=check_patch + ;; + -r ) + range=1 + ;; + -* ) + usage 1 + ;; + * ) + break + ;; + esac + shift +done + +for arg in $@; do + $check $arg +done + +exit $fail diff --git a/tools/nxstyle.c b/tools/nxstyle.c index 9d5b8575895..6698bdd09da 100644 --- a/tools/nxstyle.c +++ b/tools/nxstyle.c @@ -1,66 +1,317 @@ -/**************************************************************************** +/******************************************************************************** * tools/nxstyle.c * - * Copyright (C) 2015, 2018-2019 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * http://www.apache.org/licenses/LICENSE-2.0 * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name NuttX nor the names of its contributors may be - * used to endorse or promote products derived from this software - * without specific prior written permission. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************/ + ********************************************************************************/ -/**************************************************************************** +/******************************************************************************** * Included Files - ****************************************************************************/ + ********************************************************************************/ #include #include #include +#include #include #include #include +#include +#include +#include -/**************************************************************************** +/******************************************************************************** * Pre-processor Definitions - ****************************************************************************/ + ********************************************************************************/ + +#define NXSTYLE_VERSION "0.01" + +#define LINE_SIZE 512 +#define RANGE_NUMBER 4096 +#define DEFAULT_WIDTH 78 + +#define FIRST_SECTION INCLUDED_FILES +#define LAST_SECTION PUBLIC_FUNCTION_PROTOTYPES + +#define FATAL(m, l, o) message(FATAL, (m), (l), (o)) +#define FATALFL(m, s) message(FATAL, (m), -1, -1) +#define WARN(m, l, o) message(WARN, (m), (l), (o)) +#define ERROR(m, l, o) message(ERROR, (m), (l), (o)) +#define ERRORFL(m, s) message(ERROR, (m), -1, -1) +#define INFO(m, l, o) message(INFO, (m), (l), (o)) +#define INFOFL(m, s) message(INFO, (m), -1, -1) + +/******************************************************************************** + * Private types + ********************************************************************************/ + +enum class_e +{ + INFO, + WARN, + ERROR, + FATAL +}; -#define LINE_SIZE 512 +const char *class_text[] = +{ + "info", + "warning", + "error", + "fatal" +}; + +enum file_e +{ + UNKNOWN = 0x00, + C_HEADER = 0x01, + C_SOURCE = 0x02 +}; -/**************************************************************************** +enum section_s +{ + NO_SECTION = 0, + INCLUDED_FILES, + PRE_PROCESSOR_DEFINITIONS, + PUBLIC_TYPES, + PRIVATE_TYPES, + PRIVATE_DATA, + PUBLIC_DATA, + PRIVATE_FUNCTIONS, + PRIVATE_FUNCTION_PROTOTYPES, + INLINE_FUNCTIONS, + PUBLIC_FUNCTIONS, + PUBLIC_FUNCTION_PROTOTYPES +}; + +enum pptype_e +{ + PPLINE_NONE = 0, + PPLINE_DEFINE, + PPLINE_IF, + PPLINE_ELIF, + PPLINE_ELSE, + PPLINE_ENDIF, + PPLINE_OTHER +}; + +struct file_section_s +{ + const char *name; /* File section name */ + uint8_t ftype; /* File type where section found */ +}; + +/******************************************************************************** + * Private data + ********************************************************************************/ + +static char *g_file_name = ""; +static enum file_e g_file_type = UNKNOWN; +static enum section_s g_section = NO_SECTION; +static int g_maxline = DEFAULT_WIDTH; +static int g_status = 0; +static int g_verbose = 2; +static int g_rangenumber = 0; +static int g_rangestart[RANGE_NUMBER]; +static int g_rangecount[RANGE_NUMBER]; + +static const struct file_section_s g_section_info[] = +{ + { + " *\n", /* Index: NO_SECTION */ + C_SOURCE | C_HEADER + }, + { + " * Included Files\n", /* Index: INCLUDED_FILES */ + C_SOURCE | C_HEADER + }, + { + " * Pre-processor Definitions\n", /* Index: PRE_PROCESSOR_DEFINITIONS */ + C_SOURCE | C_HEADER + }, + { + " * Public Types\n", /* Index: PUBLIC_TYPES */ + C_HEADER + }, + { + " * Private Types\n", /* Index: PRIVATE_TYPES */ + C_SOURCE + }, + { + " * Private Data\n", /* Index: PRIVATE_DATA */ + C_SOURCE + }, + { + " * Public Data\n", /* Index: PUBLIC_DATA */ + C_SOURCE | C_HEADER + }, + { + " * Private Functions\n", /* Index: PRIVATE_FUNCTIONS */ + C_SOURCE + }, + { + " * Private Function Prototypes\n", /* Index: PRIVATE_FUNCTION_PROTOTYPES */ + C_SOURCE + }, + { + " * Inline Functions\n", /* Index: INLINE_FUNCTIONS */ + C_SOURCE | C_HEADER + }, + { + " * Public Functions\n", /* Index: PUBLIC_FUNCTIONS */ + C_SOURCE + }, + { + " * Public Function Prototypes\n", /* Index: PUBLIC_FUNCTION_PROTOTYPES */ + C_SOURCE | C_HEADER + } +}; + +static const char *g_white_prefix[] = +{ + "Elf", /* Ref: include/elf.h, include/elf32.h, include/elf64.h */ + "PRId", /* Ref: inttypes.h */ + "PRIi", /* Ref: inttypes.h */ + "PRIo", /* Ref: inttypes.h */ + "PRIu", /* Ref: inttypes.h */ + "PRIx", /* Ref: inttypes.h */ + "SCNd", /* Ref: inttypes.h */ + "SCNi", /* Ref: inttypes.h */ + "SCNo", /* Ref: inttypes.h */ + "SCNu", /* Ref: inttypes.h */ + "SCNx", /* Ref: inttypes.h */ + "SYS_", /* Ref: include/sys/syscall.h */ + "STUB_", /* Ref: syscall/syscall_lookup.h, syscall/sycall_stublookup.c */ + "b8", /* Ref: include/fixedmath.h */ + "b16", /* Ref: include/fixedmath.h */ + "b32", /* Ref: include/fixedmath.h */ + "ub8", /* Ref: include/fixedmath.h */ + "ub16", /* Ref: include/fixedmath.h */ + "ub32", /* Ref: include/fixedmath.h */ + NULL +}; + +static const char *g_white_list[] = +{ + "__EIT_entry", /* Ref: gnu_unwind_find_exidx.c */ + "__gnu_Unwind_Find_exidx", /* Ref: gnu_unwind_find_exidx.c */ + "_Exit", /* Ref: stdlib.h */ + "_Unwind_Ptr", /* Ref: unwind-arm-common.h */ + NULL +}; + +/******************************************************************************** * Private Functions - ****************************************************************************/ + ********************************************************************************/ + +/******************************************************************************** + * Name: show_usage + * + * Description: + * + ********************************************************************************/ -static void show_usage(char *progname, int exitcode) +static void show_usage(char *progname, int exitcode, char *what) { - fprintf(stderr, "Usage: %s [-m ] \n", progname); - fprintf(stderr, " %s -h\n", progname); + fprintf(stderr, "%s version %s\n\n", basename(progname), NXSTYLE_VERSION); + if (what) + { + fprintf(stderr, "%s\n", what); + } + + fprintf(stderr, "Usage: %s [-m ] [-v ] " + "[-r ] \n", + basename(progname)); + fprintf(stderr, " %s -h this help\n", basename(progname)); + fprintf(stderr, " %s -v where level is\n", + basename(progname)); + fprintf(stderr, " 0 - no output\n"); + fprintf(stderr, " 1 - PASS/FAIL\n"); + fprintf(stderr, " 2 - output each line (default)\n"); exit(exitcode); } +/******************************************************************************** + * Name: skip + * + * Description: + * + ********************************************************************************/ + +static int skip(int lineno) +{ + int i; + + for (i = 0; i < g_rangenumber; i++) + { + if (lineno >= g_rangestart[i] && lineno < g_rangestart[i] + + g_rangecount[i]) + { + return 0; + } + } + + return g_rangenumber != 0; +} + +/******************************************************************************** + * Name: message + * + * Description: + * + ********************************************************************************/ + +static int message(enum class_e class, const char *text, int lineno, int ndx) +{ + FILE *out = stdout; + + if (skip(lineno)) + { + return g_status; + } + + if (class > INFO) + { + out = stderr; + g_status |= 1; + } + + if (g_verbose == 2) + { + if (lineno == -1 && ndx == -1) + { + fprintf(out, "%s: %s: %s\n", g_file_name, class_text[class], text); + } + else + { + fprintf(out, "%s:%d:%d: %s: %s\n", g_file_name, lineno, ndx, + class_text[class], text); + } + } + + return g_status; +} + +/******************************************************************************** + * Name: check_spaces_left + * + * Description: + * + ********************************************************************************/ + static void check_spaces_left(char *line, int lineno, int ndx) { /* Unary operator should generally be preceded by a space but make also @@ -68,40 +319,247 @@ static void check_spaces_left(char *line, int lineno, int ndx) * expression or follow a right parentheses in the case of a cast. */ - if (ndx > 0 && line[ndx - 1] != ' ' && line[ndx - 1] != '(' && line[ndx - 1] != ')') + if (ndx-- > 0 && line[ndx] != ' ' && line[ndx] != '(' && line[ndx] != ')') { - fprintf(stderr, - "Operator/assignment must be preceded with whitespace at line %d:%d\n", - lineno, ndx); + ERROR("Operator/assignment must be preceded with whitespace", + lineno, ndx); } } +/******************************************************************************** + * Name: check_spaces_leftright + * + * Description: + * + ********************************************************************************/ + static void check_spaces_leftright(char *line, int lineno, int ndx1, int ndx2) { if (ndx1 > 0 && line[ndx1 - 1] != ' ') { - fprintf(stderr, - "Operator/assignment must be preceded with whitespace at line %d:%d\n", - lineno, ndx1); + ERROR("Operator/assignment must be preceded with whitespace", + lineno, ndx1); } if (line[ndx2 + 1] != '\0' && line[ndx2 + 1] != '\n' && line[ndx2 + 1] != ' ') { - fprintf(stderr, - "Operator/assignment must be followed with whitespace at line %d:%d\n", - lineno, ndx2); + ERROR("Operator/assignment must be followed with whitespace", + lineno, ndx2); + } +} + +/******************************************************************************** + * Name: block_comment_width + * + * Description: + * Get the width of a block comment + * + ********************************************************************************/ + +static int block_comment_width(char *line) +{ + int b; + int e; + int n; + + /* Skip over any leading whitespace on the line */ + + for (b = 0; isspace(line[b]); b++) + { + } + + /* Skip over any trailing whitespace at the end of the line */ + + for (e = strlen(line) - 1; e >= 0 && isspace(line[e]); e--) + { + } + + /* Number of characters on the line */ + + n = e - b + 1; + if (n < 4) + { + return 0; + } + + /* The first line of a block comment starts with "[slash]***" and ends with + * "***" + */ + + if (strncmp(&line[b], "/***", 4) == 0 && + strncmp(&line[e - 2], "***", 3) == 0) + { + /* Return the the length of the line up to the final '*' */ + + return e + 1; + } + + /* The last line of a block begins with whitespace then "***" and ends + * with "***[slash]" + */ + + if (strncmp(&line[b], "***", 3) == 0 && + strncmp(&line[e - 3], "***/", 4) == 0) + { + /* Return the the length of the line up to the final '*' */ + + return e; } + + /* But there is also a special single line comment that begins with "[slash]* " + * and ends with "***[slash]" + */ + + if (strncmp(&line[b], "/*", 2) == 0 && + strncmp(&line[e - 3], "***/", 4) == 0) + { + /* Return the the length of the line up to the final '*' */ + + return e; + } + + /* Return zero if the line is not the first or last line of a block + * comment. + */ + + return 0; } -/**************************************************************************** +/******************************************************************************** + * Name: get_line_width + * + * Description: + * Get the maximum line width by examining the width of the block comments. + * + ********************************************************************************/ + +static int get_line_width(FILE *instream) +{ + char line[LINE_SIZE]; /* The current line being examined */ + int max = 0; + int min = INT_MAX; + int lineno = 0; + int lineno_max = 0; + int lineno_min = 0; + int len; + + while (fgets(line, LINE_SIZE, instream)) + { + lineno++; + len = block_comment_width(line); + if (len > 0) + { + if (len > max) + { + max = len; + lineno_max = lineno; + } + + if (len < min) + { + min = len; + lineno_min = lineno; + } + } + } + + if (max < min) + { + ERRORFL("No block comments found", g_file_name); + return DEFAULT_WIDTH; + } + else if (max != min) + { + ERROR("Block comments have different lengths", lineno_max, max); + ERROR("Block comments have different lengths", lineno_min, min); + return DEFAULT_WIDTH; + } + + return min; +} + +/******************************************************************************** + * Name: check_section_header + * + * Description: + * Check if the current line holds a section header + * + ********************************************************************************/ + +static bool check_section_header(const char *line, int lineno) +{ + int i; + + /* Search g_section_info[] to find a matching section header line */ + + for (i = FIRST_SECTION; i <= LAST_SECTION; i++) + { + if (strcmp(line, g_section_info[i].name) == 0) + { + g_section = (enum section_s)i; + + /* Verify that this section is appropriate for this file type */ + + if ((g_file_type & g_section_info[i].ftype) == 0) + { + ERROR("Invalid section for this file type", lineno, 3); + } + + return true; + } + } + + return false; +} + +/******************************************************************************** + * Name: white_prefix + * + * Description: + * Return true if the identifier string begins with a white-listed prefix + * + ********************************************************************************/ + +static bool white_list(const char *ident, int lineno) +{ + const char **pptr; + const char *str; + + for (pptr = g_white_prefix; + (str = *pptr) != NULL; + pptr++) + { + if (strncmp(ident, str, strlen(str)) == 0) + { + return true; + } + } + + for (pptr = g_white_list; + (str = *pptr) != NULL; + pptr++) + { + size_t len = strlen(str); + + if (strncmp(ident, str, len) == 0 && + isalnum(ident[len]) == 0) + { + return true; + } + } + + return false; +} + +/******************************************************************************** * Public Functions - ****************************************************************************/ + ********************************************************************************/ int main(int argc, char **argv, char **envp) { FILE *instream; /* File input stream */ char line[LINE_SIZE]; /* The current line being examined */ - char *filename; /* Name of the file to open */ + char buffer[100]; /* Localy format error strings */ char *lptr; /* Temporary pointer into line[] */ char *ext; /* Temporary file extension */ bool btabs; /* True: TAB characters found on the line */ @@ -113,10 +571,13 @@ int main(int argc, char **argv, char **envp) bool bstring; /* True: Within a string */ bool bquote; /* True: Backslash quoted character next */ bool bblank; /* Used to verify block comment terminator */ - bool ppline; /* True: The next line the continuation of a pre-processor command */ - bool hdrfile; /* True: File is a header file */ bool bexternc; /* True: Within 'extern "C"' */ - bool brhcomment; /* True: Comment to the right of code */ + enum pptype_e ppline; /* > 0: The next line the continuation of a + * pre-processor command */ + int rhcomment; /* Indentation of Comment to the right of code + * (-1 -> don't check position) */ + int prevrhcmt; /* Indentation of previous Comment to the right + * of code (-1 -> don't check position) */ int lineno; /* Current line number */ int indent; /* Indentation level */ int ncomment; /* Comment nesting level on this line */ @@ -126,6 +587,8 @@ int main(int argc, char **argv, char **envp) int dnest; /* Data declaration nesting level on this line */ int prevdnest; /* Data declaration nesting level on the previous line */ int pnest; /* Parenthesis nesting level on this line */ + int ppifnest; /* #if nesting level on this line */ + int inasm; /* > 0: Within #ifdef __ASSEMBLY__ */ int comment_lineno; /* Line on which the last comment was closed */ int blank_lineno; /* Line number of the last blank line */ int noblank_lineno; /* A blank line is not needed after this line */ @@ -133,91 +596,124 @@ int main(int argc, char **argv, char **envp) int rbrace_lineno; /* Last line containing a right brace */ int externc_lineno; /* Last line where 'extern "C"' declared */ int linelen; /* Length of the line */ - int maxline; /* Lines longer that this generate warnings */ + int excess; int n; int i; + int c; - maxline = 78; - filename = argv[1]; - - /* Usage: nxstyle [-m ] - * nxstyle -h - */ - - if (argc == 4) + excess = 0; + while ((c = getopt(argc, argv, ":hv:gm:r:")) != -1) { - if (strcmp(argv[1], "-m") != 0) - { - fprintf(stderr, "Unrecognized argument\n"); - show_usage(argv[0], 1); - } - - maxline = atoi(argv[2]); - if (maxline < 1) - { - fprintf(stderr, "Bad value for \n"); - show_usage(argv[0], 1); - } - - filename = argv[3]; - } - else if (argc == 2) - { - if (strcmp(argv[1], "-h") == 0) - { - show_usage(argv[0], 0); - } - } - else + switch (c) + { + case 'm': + excess = atoi(optarg); + if (excess < 1) + { + show_usage(argv[0], 1, "Bad value for ."); + excess = 0; + } + + break; + + case 'v': + g_verbose = atoi(optarg); + if (g_verbose < 0 || g_verbose > 2) + { + show_usage(argv[0], 1, "Bad value for ."); + } + + break; + + case 'r': + g_rangestart[g_rangenumber] = atoi(strtok(optarg, ",")); + g_rangecount[g_rangenumber++] = atoi(strtok(NULL, ",")); + break; + + case 'h': + show_usage(argv[0], 0, NULL); + break; + + case ':': + show_usage(argv[0], 1, "Missing argument."); + break; + + case '?': + show_usage(argv[0], 1, "Unrecognized option."); + break; + + default: + show_usage(argv[0], 0, NULL); + break; + } + } + + if (optind < argc - 1 || argv[optind] == NULL) { - fprintf(stderr, "Invalid number of arguments\n"); - show_usage(argv[0], 1); + show_usage(argv[0], 1, "No file name given."); } - instream = fopen(filename, "r"); - if (!instream) - { - fprintf(stderr, "Failed to open %s\n", argv[1]); - return 1; - } + g_file_name = argv[optind]; /* Are we parsing a header file? */ - hdrfile = false; - ext = strrchr(filename, '.'); + ext = strrchr(g_file_name, '.'); if (ext == 0) { - printf("No file extension\n"); } else if (strcmp(ext, ".h") == 0) { - hdrfile = true; + g_file_type = C_HEADER; + } + else if (strcmp(ext, ".c") == 0) + { + g_file_type = C_SOURCE; } - else if (strcmp(ext, ".c") != 0) + + if (g_file_type == UNKNOWN) { - printf("Unrecognized file extension: \"%s\"\n", ext + 1); + return 0; } - btabs = false; /* True: TAB characters found on the line */ - bcrs = false; /* True: Carriable return found on the line */ - bfunctions = false; /* True: In private or public functions */ - bswitch = false; /* True: Within a switch statement */ - bstring = false; /* True: Within a string */ - ppline = false; /* True: Continuation of a pre-processor line */ - bexternc = false; /* True: Within 'extern "C"' */ - brhcomment = false; /* True: Comment to the right of code */ - lineno = 0; /* Current line number */ - ncomment = 0; /* Comment nesting level on this line */ - bnest = 0; /* Brace nesting level on this line */ - dnest = 0; /* Data declaration nesting level on this line */ - pnest = 0; /* Parenthesis nesting level on this line */ - comment_lineno = -1; /* Line on which the last comment was closed */ - blank_lineno = -1; /* Line number of the last blank line */ - noblank_lineno = -1; /* A blank line is not needed after this line */ - lbrace_lineno = -1; /* Line number of last left brace */ - rbrace_lineno = -1; /* Last line containing a right brace */ - externc_lineno = -1; /* Last line where 'extern "C"' declared */ + instream = fopen(g_file_name, "r"); + + if (!instream) + { + FATALFL("Failed to open", g_file_name); + return 1; + } + + /* Determine the line width */ + + g_maxline = get_line_width(instream) + excess; + rewind(instream); + + btabs = false; /* True: TAB characters found on the line */ + bcrs = false; /* True: Carriage return found on the line */ + bfunctions = false; /* True: In private or public functions */ + bswitch = false; /* True: Within a switch statement */ + bstring = false; /* True: Within a string */ + bexternc = false; /* True: Within 'extern "C"' */ + ppline = PPLINE_NONE; /* > 0: The next line the continuation of a + * pre-processor command */ + rhcomment = 0; /* Indentation of Comment to the right of code + * (-1 -> don't check position) */ + prevrhcmt = 0; /* Indentation of previous Comment to the right + * of code (-1 -> don't check position) */ + lineno = 0; /* Current line number */ + ncomment = 0; /* Comment nesting level on this line */ + bnest = 0; /* Brace nesting level on this line */ + dnest = 0; /* Data declaration nesting level on this line */ + pnest = 0; /* Parenthesis nesting level on this line */ + ppifnest = 0; /* #if nesting level on this line */ + inasm = 0; /* > 0: Within #ifdef __ASSEMBLY__ */ + comment_lineno = -1; /* Line on which the last comment was closed */ + blank_lineno = -1; /* Line number of the last blank line */ + noblank_lineno = -1; /* A blank line is not needed after this line */ + lbrace_lineno = -1; /* Line number of last left brace */ + rbrace_lineno = -1; /* Last line containing a right brace */ + externc_lineno = -1; /* Last line where 'extern "C"' declared */ /* Process each line in the input stream */ @@ -226,16 +722,21 @@ int main(int argc, char **argv, char **envp) lineno++; indent = 0; prevbnest = bnest; /* Brace nesting level on the previous line */ - prevdnest = dnest; /* Data declaration nesting level on the previous line */ + prevdnest = dnest; /* Data declaration nesting level on the + * previous line */ prevncomment = ncomment; /* Comment nesting level on the previous line */ - bstatm = false; /* True: This line is beginning of a statement */ + bstatm = false; /* True: This line is beginning of a + * statement */ bfor = false; /* REVISIT: Implies for() is all on one line */ - /* If we are not in a comment, then this certainly is not a right-hand comment. */ + /* If we are not in a comment, then this certainly is not a right-hand + * comment. + */ + prevrhcmt = rhcomment; if (ncomment <= 0) { - brhcomment = false; + rhcomment = 0; } /* Check for a blank line */ @@ -248,22 +749,20 @@ int main(int argc, char **argv, char **envp) { if (n > 0) { - fprintf(stderr, "Blank line contains whitespace at line %d\n", - lineno); + ERROR("Blank line contains whitespace", lineno, 1); } if (lineno == 1) { - fprintf(stderr, "File begins with a blank line\n"); + ERROR("File begins with a blank line", 1, 1); } else if (lineno == blank_lineno + 1) { - fprintf(stderr, "Too many blank lines at line %d\n", lineno); + ERROR("Too many blank lines", lineno, 1); } else if (lineno == lbrace_lineno + 1) { - fprintf(stderr, "Blank line follows left brace at line %d\n", - lineno); + ERROR("Blank line follows left brace", lineno, 1); } blank_lineno = lineno; @@ -282,13 +781,19 @@ int main(int argc, char **argv, char **envp) * REVISIT: Generates a false alarm if the current line is also * a comment. Generally it is acceptable for one comment to * follow another with no space separation. + * + * REVISIT: prevrhcmt is tested to case the preceding line + * contained comments to the right of the code. In such cases, + * the comments are normally aligned and do not follow normal + * indentation rules. However, this code will generate a false + * alarm if the comments are aligned to the right BUT the + * preceding line has no comment. */ - if (line[n] != '}' /* && line[n] != '#' */) + if (line[n] != '}' && line[n] != '#' && prevrhcmt == 0) { - fprintf(stderr, - "Missing blank line after comment found at line %d\n", - comment_lineno); + ERROR("Missing blank line after comment", comment_lineno, + 1); } } @@ -299,50 +804,49 @@ int main(int argc, char **argv, char **envp) if (lineno == 1 && (line[n] != '/' || line[n + 1] != '*')) { - fprintf(stderr, - "Missing file header comment block at line 1\n"); + ERROR("Missing file header comment block", lineno, 1); } - /* Check for a blank line following a right brace */ + /* Check for a blank line following a right brace */ if (bfunctions && lineno == rbrace_lineno + 1) - { - /* Check if this line contains a right brace. A right brace - * must be followed by 'else', 'while', 'break', a blank line, - * another right brace, or a pre-processor directive like #endif - */ - - if (strchr(line, '}') == NULL && line[n] != '#' && - strncmp(&line[n], "else", 4) != 0 && - strncmp(&line[n], "while", 5) != 0 && - strncmp(&line[n], "break", 5) != 0) - { - fprintf(stderr, - "Right brace must be followed by a blank line at line %d\n", - rbrace_lineno); - } - - /* If the right brace is followed by a pre-proceeor command - * like #endif (but not #else or #elif), then set the right - * brace line number to the line number of the pre-processor - * command (it then must be followed by a blank line) - */ - - if (line[n] == '#') - { - int ii; - - for (ii = n + 1; line[ii] != '\0' && isspace(line[ii]); ii++) - { - } + { + /* Check if this line contains a right brace. A right brace + * must be followed by 'else', 'while', 'break', a blank line, + * another right brace, or a pre-processor directive like #endif + */ - if (strncmp(&line[ii], "else", 4) != 0 && - strncmp(&line[ii], "elif", 4) != 0) - { - rbrace_lineno = lineno; - } - } - } + if (dnest == 0 && + strchr(line, '}') == NULL && line[n] != '#' && + strncmp(&line[n], "else", 4) != 0 && + strncmp(&line[n], "while", 5) != 0 && + strncmp(&line[n], "break", 5) != 0) + { + ERROR("Right brace must be followed by a blank line", + rbrace_lineno, n + 1); + } + + /* If the right brace is followed by a pre-processor command + * like #endif (but not #else or #elif), then set the right + * brace line number to the line number of the pre-processor + * command (it then must be followed by a blank line) + */ + + if (line[n] == '#') + { + int ii; + + for (ii = n + 1; line[ii] != '\0' && isspace(line[ii]); ii++) + { + } + + if (strncmp(&line[ii], "else", 4) != 0 && + strncmp(&line[ii], "elif", 4) != 0) + { + rbrace_lineno = lineno; + } + } + } } /* STEP 1: Find the indentation level and the start of real stuff on @@ -363,8 +867,7 @@ int main(int argc, char **argv, char **envp) { if (!btabs) { - fprintf(stderr, "TABs found. First detected at line %d:%d\n", - lineno, n); + ERROR("TABs found. First detected", lineno, n); btabs = true; } @@ -376,8 +879,8 @@ int main(int argc, char **argv, char **envp) { if (!bcrs) { - fprintf(stderr, "Carriage returns found. " - "First detected at line %d:%d\n", lineno, n); + ERROR("Carriage returns found. " + "First detected", lineno, n); bcrs = true; } } @@ -385,27 +888,177 @@ int main(int argc, char **argv, char **envp) default: { - fprintf(stderr, - "Unexpected white space character %02x found at line %d:%d\n", - line[n], lineno, n); + snprintf(buffer, sizeof(buffer), + "Unexpected white space character %02x found", + line[n]); + ERROR(buffer, lineno, n); } break; } } /* STEP 2: Detect some certain start of line conditions */ + /* Skip over pre-processor lines (or continuations of pre-processor * lines as indicated by ppline) */ - if (line[indent] == '#' || ppline) + if (line[indent] == '#' || ppline != PPLINE_NONE) { int len; + int ii; /* Suppress error for comment following conditional compilation */ noblank_lineno = lineno; + /* Check pre-processor commands if this is not a continuation + * line. + */ + + ii = indent + 1; + + if (ppline == PPLINE_NONE) + { + /* Skip to the pre-processor command following the '#' */ + + while (line[ii] != '\0' && isspace(line[ii])) + { + ii++; + } + + if (line[ii] != '\0') + { + /* Make sure that pre-processor definitions are all in + * the pre-processor definitions section. + */ + + ppline = PPLINE_OTHER; + + if (strncmp(&line[ii], "define", 6) == 0) + { + ppline = PPLINE_DEFINE; + + if (g_section != PRE_PROCESSOR_DEFINITIONS) + { + /* A complication is the header files always have + * the idempotence guard definitions before the + * "Pre-processor Definitions section". + */ + + if (g_section == NO_SECTION && + g_file_type != C_HEADER) + { + /* Only a warning because there is some usage + * of define outside the Pre-processor + * Definitions section which is justifiable. + * Should be manually checked. + */ + + WARN("#define outside of 'Pre-processor " + "Definitions' section", + lineno, ii); + } + } + } + + /* Make sure that files are included only in the Included + * Files section. + */ + + else if (strncmp(&line[ii], "include", 7) == 0) + { + if (g_section != INCLUDED_FILES) + { + /* Only a warning because there is some usage of + * include outside the Included Files section + * which may be is justifiable. Should be + * manually checked. + */ + + WARN("#include outside of 'Included Files' " + "section", + lineno, ii); + } + } + else if (strncmp(&line[ii], "if", 2) == 0) + { + ppifnest++; + + ppline = PPLINE_IF; + ii += 2; + } + else if (strncmp(&line[ii], "elif", 4) == 0) + { + if (ppifnest == inasm) + { + inasm = 0; + } + + ppline = PPLINE_ELIF; + ii += 4; + } + else if (strncmp(&line[ii], "else", 4) == 0) + { + if (ppifnest == inasm) + { + inasm = 0; + } + + ppline = PPLINE_ELSE; + } + else if (strncmp(&line[ii], "endif", 4) == 0) + { + if (ppifnest == inasm) + { + inasm = 0; + } + + ppifnest--; + + ppline = PPLINE_ENDIF; + } + } + } + + if (ppline == PPLINE_IF || ppline == PPLINE_ELIF) + { + int bdef = 0; + + if (strncmp(&line[ii], "def", 3) == 0) + { + bdef = 1; + ii += 3; + } + else + { + while (line[ii] != '\0' && isspace(line[ii])) + { + ii++; + } + + if (strncmp(&line[ii], "defined", 7) == 0) + { + bdef = 1; + ii += 7; + } + } + + if (bdef) + { + while (line[ii] != '\0' && + (isspace(line[ii]) || line[ii] == '(')) + { + ii++; + } + + if (strncmp(&line[ii], "__ASSEMBLY__", 12) == 0) + { + inasm = ppifnest; + } + } + } + /* Check if the next line will be a continuation of the pre- * processor command. */ @@ -416,7 +1069,69 @@ int main(int argc, char **argv, char **envp) len--; } - ppline = (line[len] == '\\'); + /* Propagate rhcomment over preprocessor lines Issue #120 */ + + if (prevrhcmt != 0) + { + /* Don't check position */ + + rhcomment = -1; + } + + lptr = strstr(line, "/*"); + if (lptr != NULL) + { + n = lptr - &line[0]; + if (line[n + 2] == '\n') + { + ERROR("C comment opening on separate line", lineno, n); + } + else if (!isspace((int)line[n + 2]) && line[n + 2] != '*') + { + ERROR("Missing space after opening C comment", lineno, n); + } + + if (strstr(lptr, "*/") == NULL) + { + /* Increment the count of nested comments */ + + ncomment++; + } + + if (ppline == PPLINE_DEFINE) + { + rhcomment = n; + if (prevrhcmt > 0 && n != prevrhcmt) + { + rhcomment = prevrhcmt; + WARN("Wrong column position of comment right of code", + lineno, n); + } + } + else + { + /* Signal rhcomment, but ignore position */ + + rhcomment = -1; + + if (ncomment > 0 && + (ppline == PPLINE_IF || + ppline == PPLINE_ELSE || + ppline == PPLINE_ELIF)) + { + /* in #if... and #el... */ + + ERROR("No multiline comment right of code allowed here", + lineno, n); + } + } + } + + if (line[len] != '\\' || ncomment > 0) + { + ppline = PPLINE_NONE; + } + continue; } @@ -429,18 +1144,27 @@ int main(int argc, char **argv, char **envp) if (line[indent] == '/' && line[indent + 1] == '*' && lptr - line == linelen - 3) { + /* If preceding comments were to the right of code, then we can + * assume that there is a columnar alignment of columns that do + * no follow the usual alignment. So the rhcomment flag + * should propagate. + */ + + rhcomment = prevrhcmt; + /* Check if there should be a blank line before the comment */ if (lineno > 1 && comment_lineno != lineno - 1 && blank_lineno != lineno - 1 && - noblank_lineno != lineno - 1) + noblank_lineno != lineno - 1 && + rhcomment == 0) { - /* TODO: This generates a false alarm if preceded by a label. */ + /* TODO: This generates a false alarm if preceded + * by a label. + */ - fprintf(stderr, - "Missing blank line before comment found at line %d\n", - lineno); + ERROR("Missing blank line before comment found", lineno, 1); } /* 'comment_lineno 'holds the line number of the last closing @@ -449,18 +1173,19 @@ int main(int argc, char **argv, char **envp) */ comment_lineno = lineno; - brhcomment = false; } } - /* Check for the comment block indicating the beginning of functions. */ + /* Check for the comment block indicating the beginning of a new file + * section. + */ - if (!bfunctions && ncomment > 0 && - (strcmp(line, " * Private Functions\n") == 0 || - strcmp(line, " * Public Functions\n") == 0)) + if (check_section_header(line, lineno)) { - //fprintf(stderr, "Functions begin at line %d:%d\n", lineno, n); - bfunctions = true; + if (g_section == PRIVATE_FUNCTIONS || g_section == PUBLIC_FUNCTIONS) + { + bfunctions = true; /* Latched */ + } } /* Check for some kind of declaration. @@ -470,170 +1195,178 @@ int main(int argc, char **argv, char **envp) * example. */ - else if (strncmp(&line[indent], "auto ", 5) == 0 || - strncmp(&line[indent], "bool ", 5) == 0 || - strncmp(&line[indent], "char ", 5) == 0 || - strncmp(&line[indent], "CODE ", 5) == 0 || - strncmp(&line[indent], "const ", 6) == 0 || - strncmp(&line[indent], "double ", 7) == 0 || -// strncmp(&line[indent], "struct ", 7) == 0 || - strncmp(&line[indent], "struct", 6) == 0 || /* May be unnamed */ - strncmp(&line[indent], "enum ", 5) == 0 || - strncmp(&line[indent], "extern ", 7) == 0 || - strncmp(&line[indent], "EXTERN ", 7) == 0 || - strncmp(&line[indent], "FAR ", 4) == 0 || - strncmp(&line[indent], "float ", 6) == 0 || - strncmp(&line[indent], "int ", 4) == 0 || - strncmp(&line[indent], "int16_t ", 8) == 0 || - strncmp(&line[indent], "int32_t ", 8) == 0 || - strncmp(&line[indent], "long ", 5) == 0 || - strncmp(&line[indent], "off_t ", 6) == 0 || - strncmp(&line[indent], "register ", 9) == 0 || - strncmp(&line[indent], "short ", 6) == 0 || - strncmp(&line[indent], "signed ", 7) == 0 || - strncmp(&line[indent], "size_t ", 7) == 0 || - strncmp(&line[indent], "ssize_t ", 8) == 0 || - strncmp(&line[indent], "static ", 7) == 0 || - strncmp(&line[indent], "time_t ", 7) == 0 || - strncmp(&line[indent], "typedef ", 8) == 0 || - strncmp(&line[indent], "uint8_t ", 8) == 0 || - strncmp(&line[indent], "uint16_t ", 9) == 0 || - strncmp(&line[indent], "uint32_t ", 9) == 0 || -// strncmp(&line[indent], "union ", 6) == 0 || - strncmp(&line[indent], "union", 5) == 0 || /* May be unnamed */ - strncmp(&line[indent], "unsigned ", 9) == 0 || - strncmp(&line[indent], "void ", 5) == 0 || - strncmp(&line[indent], "volatile ", 9) == 0) + else if (inasm == 0) { - /* Check if this is extern "C"; We don't typically indent following - * this. - */ - - if (strncmp(&line[indent], "extern \"C\"", 10) == 0) + if (strncmp(&line[indent], "auto ", 5) == 0 || + strncmp(&line[indent], "bool ", 5) == 0 || + strncmp(&line[indent], "char ", 5) == 0 || + strncmp(&line[indent], "CODE ", 5) == 0 || + strncmp(&line[indent], "const ", 6) == 0 || + strncmp(&line[indent], "double ", 7) == 0 || + strncmp(&line[indent], "struct ", 7) == 0 || + strncmp(&line[indent], "struct\n", 7) == 0 || /* May be unnamed */ + strncmp(&line[indent], "enum ", 5) == 0 || + strncmp(&line[indent], "extern ", 7) == 0 || + strncmp(&line[indent], "EXTERN ", 7) == 0 || + strncmp(&line[indent], "FAR ", 4) == 0 || + strncmp(&line[indent], "float ", 6) == 0 || + strncmp(&line[indent], "int ", 4) == 0 || + strncmp(&line[indent], "int16_t ", 8) == 0 || + strncmp(&line[indent], "int32_t ", 8) == 0 || + strncmp(&line[indent], "long ", 5) == 0 || + strncmp(&line[indent], "off_t ", 6) == 0 || + strncmp(&line[indent], "register ", 9) == 0 || + strncmp(&line[indent], "short ", 6) == 0 || + strncmp(&line[indent], "signed ", 7) == 0 || + strncmp(&line[indent], "size_t ", 7) == 0 || + strncmp(&line[indent], "ssize_t ", 8) == 0 || + strncmp(&line[indent], "static ", 7) == 0 || + strncmp(&line[indent], "time_t ", 7) == 0 || + strncmp(&line[indent], "typedef ", 8) == 0 || + strncmp(&line[indent], "uint8_t ", 8) == 0 || + strncmp(&line[indent], "uint16_t ", 9) == 0 || + strncmp(&line[indent], "uint32_t ", 9) == 0 || + strncmp(&line[indent], "union ", 6) == 0 || + strncmp(&line[indent], "union\n", 6) == 0 || /* May be unnamed */ + strncmp(&line[indent], "unsigned ", 9) == 0 || + strncmp(&line[indent], "void ", 5) == 0 || + strncmp(&line[indent], "volatile ", 9) == 0) { - externc_lineno = lineno; - } + /* Check if this is extern "C"; We don't typically indent + * following this. + */ - /* bfunctions: True: Processing private or public functions. - * bnest: Brace nesting level on this line - * dnest: Data declaration nesting level on this line - */ + if (strncmp(&line[indent], "extern \"C\"", 10) == 0) + { + externc_lineno = lineno; + } - /* REVISIT: Also picks up function return types */ - /* REVISIT: Logic problem for nested data/function declarations */ + /* bfunctions: True: Processing private or public functions. + * bnest: Brace nesting level on this line + * dnest: Data declaration nesting level on this line + */ - if ((!bfunctions || bnest > 0) && dnest == 0) - { - dnest = 1; - } + /* REVISIT: Also picks up function return types */ - /* Check for multiple definitions of variables on the line. - * Ignores declarations within parentheses which are probably - * formal parameters. - */ + /* REVISIT: Logic problem for nested data/function declarations */ - if (pnest == 0) - { - int tmppnest; + if ((!bfunctions || bnest > 0) && dnest == 0) + { + dnest = 1; + } - /* Note, we have not yet parsed each character on the line so - * a comma have have been be preceded by '(' on the same line. - * We will have parse up to any comma to see if that is the - * case. + /* Check for multiple definitions of variables on the line. + * Ignores declarations within parentheses which are probably + * formal parameters. */ - for (i = indent, tmppnest = 0; - line[i] != '\n' && line[i] != '\0'; - i++) + if (pnest == 0) { - if (tmppnest == 0 && line[i] == ',') - { - fprintf(stderr, - "Multiple data definitions on line %d\n", - lineno); - break; - } - else if (line[i] == '(') - { - tmppnest++; - } - else if (line[i] == ')') + int tmppnest; + + /* Note, we have not yet parsed each character on the line so + * a comma have have been be preceded by '(' on the same line. + * We will have parse up to any comma to see if that is the + * case. + */ + + for (i = indent, tmppnest = 0; + line[i] != '\n' && line[i] != '\0'; + i++) { - if (tmppnest < 1) + if (tmppnest == 0 && line[i] == ',') { - /* We should catch this later */ - + ERROR("Multiple data definitions", lineno, i + 1); break; } + else if (line[i] == '(') + { + tmppnest++; + } + else if (line[i] == ')') + { + if (tmppnest < 1) + { + /* We should catch this later */ - tmppnest--; - } - else if (line[i] == ';') - { - /* Break out if the semicolon terminates the - * declaration is found. Avoids processing any - * righthand comments in most cases. - */ + break; + } - break; + tmppnest--; + } + else if (line[i] == ';') + { + /* Break out if the semicolon terminates the + * declaration is found. Avoids processing any + * righthand comments in most cases. + */ + + break; + } } } } - } - /* Check for a keyword indicating the beginning of a statement. - * REVISIT: This, obviously, will not detect statements that do not - * begin with a C keyword (such as assignment statements). - */ + /* Check for a keyword indicating the beginning of a statement. + * REVISIT: This, obviously, will not detect statements that do not + * begin with a C keyword (such as assignment statements). + */ - else if (strncmp(&line[indent], "break ", 6) == 0 || - strncmp(&line[indent], "case ", 5) == 0 || -// strncmp(&line[indent], "case ", 5) == 0 || /* Part of switch */ - strncmp(&line[indent], "continue ", 9) == 0 || -// strncmp(&line[indent], "default ", 8) == 0 || /* Part of switch */ - strncmp(&line[indent], "do ", 3) == 0 || - strncmp(&line[indent], "else ", 5) == 0 || - strncmp(&line[indent], "goto ", 5) == 0 || - strncmp(&line[indent], "if ", 3) == 0 || - strncmp(&line[indent], "return ", 7) == 0 || -// strncmp(&line[indent], "switch ", 7) == 0 || /* Doesn't follow pattern */ - strncmp(&line[indent], "while ", 6) == 0) - { - bstatm = true; - } + else if (strncmp(&line[indent], "break ", 6) == 0 || + strncmp(&line[indent], "case ", 5) == 0 || + #if 0 /* Part of switch */ + strncmp(&line[indent], "case ", 5) == 0 || + #endif + strncmp(&line[indent], "continue ", 9) == 0 || + + #if 0 /* Part of switch */ + strncmp(&line[indent], "default ", 8) == 0 || + #endif + strncmp(&line[indent], "do ", 3) == 0 || + strncmp(&line[indent], "else ", 5) == 0 || + strncmp(&line[indent], "goto ", 5) == 0 || + strncmp(&line[indent], "if ", 3) == 0 || + strncmp(&line[indent], "return ", 7) == 0 || + #if 0 /* Doesn't follow pattern */ + strncmp(&line[indent], "switch ", 7) == 0 || + #endif + strncmp(&line[indent], "while ", 6) == 0) + { + bstatm = true; + } - /* Spacing works a little differently for and switch statements */ + /* Spacing works a little differently for and switch statements */ - else if (strncmp(&line[indent], "for ", 4) == 0) - { - bfor = true; - bstatm = true; - } - else if (strncmp(&line[indent], "switch ", 7) == 0) - { - bswitch = true; - } + else if (strncmp(&line[indent], "for ", 4) == 0) + { + bfor = true; + bstatm = true; + } + else if (strncmp(&line[indent], "switch ", 7) == 0) + { + bswitch = true; + } - /* Also check for C keywords with missing white space */ + /* Also check for C keywords with missing white space */ - else if (strncmp(&line[indent], "do(", 3) == 0 || - strncmp(&line[indent], "if(", 3) == 0 || - strncmp(&line[indent], "while(", 6) == 0) - { - fprintf(stderr, "Missing whitespace after keyword at line %d:%d\n", lineno, n); - bstatm = true; - } - else if (strncmp(&line[indent], "for(", 4) == 0) - { - fprintf(stderr, "Missing whitespace after keyword at line %d:%d\n", lineno, n); - bfor = true; - bstatm = true; - } - else if (strncmp(&line[indent], "switch(", 7) == 0) - { - fprintf(stderr, "Missing whitespace after keyword at line %d:%d\n", - lineno, n); - bswitch = true; + else if (strncmp(&line[indent], "do(", 3) == 0 || + strncmp(&line[indent], "if(", 3) == 0 || + strncmp(&line[indent], "while(", 6) == 0) + { + ERROR("Missing whitespace after keyword", lineno, n); + bstatm = true; + } + else if (strncmp(&line[indent], "for(", 4) == 0) + { + ERROR("Missing whitespace after keyword", lineno, n); + bfor = true; + bstatm = true; + } + else if (strncmp(&line[indent], "switch(", 7) == 0) + { + ERROR("Missing whitespace after keyword", lineno, n); + bswitch = true; + } } /* STEP 3: Parse each character on the line */ @@ -651,8 +1384,7 @@ int main(int argc, char **argv, char **envp) { if (!btabs) { - fprintf(stderr, "TABs found. First detected at line %d:%d\n", - lineno, n); + ERROR("TABs found. First detected", lineno, n); btabs = true; } } @@ -660,16 +1392,17 @@ int main(int argc, char **argv, char **envp) { if (!bcrs) { - fprintf(stderr, "Carriage returns found. " - "First detected at line %d:%d\n", lineno, n); + ERROR("Carriage returns found. " + "First detected", lineno, n); bcrs = true; } } else if (line[n] != ' ') { - fprintf(stderr, - "Unexpected white space character %02x found at line %d:%d\n", - line[n], lineno, n); + snprintf(buffer, sizeof(buffer), + "Unexpected white space character %02x found", + line[n]); + ERROR(buffer, lineno, n); } } @@ -697,6 +1430,7 @@ int main(int argc, char **argv, char **envp) * IGMPv2 as an IGMP version number * [0-9]p[0-9] as a decimal point * d[0-9] as a divisor + * Hz for frequencies (including KHz, MHz, etc.) */ if (!have_lower && islower(line[n])) @@ -737,8 +1471,8 @@ int main(int argc, char **argv, char **envp) } break; - /* Sequences containing 'p' or 'd' must have been - * preceded by upper case characters. + /* Sequences containing 'p', 'd', or 'z' must have + * been preceded by upper case characters. */ case 'p': @@ -757,6 +1491,15 @@ int main(int argc, char **argv, char **envp) } break; + case 'z': + if (!have_upper || n < 1 || + line[n - 1] != 'H') + { + have_lower = true; + } + break; + break; + default: have_lower = true; break; @@ -771,24 +1514,30 @@ int main(int argc, char **argv, char **envp) if (have_upper && have_lower) { + /* Ignore symbols that begin with white-listed prefixes */ + + if (white_list(&line[ident_index], lineno)) + { + /* No error */ + } + /* Special case hex constants. These will look like * identifiers starting with 'x' or 'X' but preceded * with '0' */ - if (ident_index < 1 || - (line[ident_index] != 'x' && line[ident_index] != 'X') || - line[ident_index - 1] != '0') + else if (ident_index < 1 || + (line[ident_index] != 'x' && + line[ident_index] != 'X') || + line[ident_index - 1] != '0') { - fprintf(stderr, - "Mixed case identifier found at line %d:%d\n", - lineno, ident_index); + ERROR("Mixed case identifier found", + lineno, ident_index); } else if (have_upper) { - fprintf(stderr, - "Upper case hex constant found at line %d:%d\n", - lineno, ident_index); + ERROR("Upper case hex constant found", + lineno, ident_index); } } @@ -810,18 +1559,51 @@ int main(int argc, char **argv, char **envp) { if (line[n + 2] == '\n') { - fprintf(stderr, "C comment opening on separate line at %d:%d\n", - lineno, n); + ERROR("C comment opening on separate line", lineno, n); } else if (!isspace((int)line[n + 2]) && line[n + 2] != '*') { - fprintf(stderr, - "Missing space after opening C comment at line %d:%d\n", - lineno, n); + ERROR("Missing space after opening C comment", lineno, n); } + /* Increment the count of nested comments */ + ncomment++; - brhcomment = (n != indent); + + /* If there is anything to the left of the left brace, then + * this must be a comment to the right of code. + * Also if preceding comments were to the right of code, then + * we can assume that there is a columnar alignment of columns + * that do no follow the usual alignment. So the rhcomment + * flag should propagate. + */ + + if (prevrhcmt == 0) + { + if (n != indent) + { + rhcomment = n; + } + } + else + { + rhcomment = n; + if (prevrhcmt > 0 && n != prevrhcmt) + { + rhcomment = prevrhcmt; + if (n != indent) + { + WARN("Wrong column position of " + "comment right of code", lineno, n); + } + else + { + ERROR("Wrong column position or missing " + "blank line before comment", lineno, n); + } + } + } + n++; continue; } @@ -832,14 +1614,12 @@ int main(int argc, char **argv, char **envp) { if (n < 2) { - fprintf(stderr, "Closing C comment not indented at line %d:%d\n", - lineno, n); + ERROR("Closing C comment not indented", lineno, n); } - else if (!isspace((int)line[n + 1]) && line[n - 2] != '*') + else if (!isspace((int)line[n - 2]) && line[n - 2] != '*') { - fprintf(stderr, - "Missing space before closing C comment at line %d:%d\n", - lineno, n); + ERROR("Missing space before closing C comment", lineno, + n); } /* Check for block comments that are not on a separate line. @@ -848,11 +1628,10 @@ int main(int argc, char **argv, char **envp) * not blank up to the point where the comment was closed. */ - if (prevncomment > 0 && !bblank && !brhcomment) + if (prevncomment > 0 && !bblank && rhcomment == 0) { - fprintf(stderr, - "Block comment terminator must be on a separate line at line %d:%d\n", - lineno, n); + ERROR("Block comment terminator must be on a " + "separate line", lineno, n); } #if 0 @@ -862,9 +1641,7 @@ int main(int argc, char **argv, char **envp) if (line[n + 1] != '\n') { - fprintf(stderr, - "Garbage on line after C comment at line %d:%d\n", - lineno, n); + ERROR("Garbage on line after C comment", lineno, n); } #endif @@ -881,18 +1658,12 @@ int main(int argc, char **argv, char **envp) /* 'comment_lineno 'holds the line number of the * last closing comment. It is used only to * verify that the comment is followed by a blank - * line. 'comment_lineno' is NOT set here if this - * comment is to the right of the code. In that - * case, no blank link is required following the - * comment + * line. */ - if (!brhcomment) - { - comment_lineno = lineno; - } + comment_lineno = lineno; - /* Note that brhcomment must persist to support a + /* Note that rhcomment must persist to support a * later test for comment alignment. We will fix * that at the top of the loop when ncomment == 0. */ @@ -900,15 +1671,13 @@ int main(int argc, char **argv, char **envp) } else { - /* Note that brhcomment must persist to support a later + /* Note that rhcomment must persist to support a later * test for comment alignment. We will will fix that * at the top of the loop when ncomment == 0. */ ncomment = 0; - fprintf(stderr, - "Closing without opening comment at line %d:%d\n", - lineno, n); + ERROR("Closing without opening comment", lineno, n); } n++; @@ -924,8 +1693,7 @@ int main(int argc, char **argv, char **envp) if ((n < 5 || strncmp(&line[n - 5], "http://", 7) != 0) && (n < 6 || strncmp(&line[n - 6], "https://", 8) != 0)) { - fprintf(stderr, "C++ style comment at %d:%d\n", - lineno, n); + ERROR("C++ style comment", lineno, n); n++; continue; } @@ -966,14 +1734,14 @@ int main(int argc, char **argv, char **envp) bquote = false; } - /* The reset of the line is only examined of we are not in a comment - * or a string. + /* The rest of the line is only examined of we are not in a comment, + * in a string or in assembly. * * REVISIT: Should still check for whitespace at the end of the * line. */ - if (ncomment == 0 && !bstring) + if (ncomment == 0 && !bstring && inasm == 0) { switch (line[n]) { @@ -983,22 +1751,21 @@ int main(int argc, char **argv, char **envp) { if (n > indent) { - /* REVISIT: dnest is always > 0 here if bfunctions == false */ + /* REVISIT: dnest is always > 0 here if bfunctions == + * false. + */ - if (dnest == 0 || !bfunctions) + if (dnest == 0 || !bfunctions || lineno == rbrace_lineno) { - fprintf(stderr, - "Left bracket not on separate line at %d:%d\n", - lineno, n); + ERROR("Left bracket not on separate line", lineno, + n); } } else if (line[n + 1] != '\n') { if (dnest == 0) { - fprintf(stderr, - "Garbage follows left bracket at line %d:%d\n", - lineno, n); + ERROR("Garbage follows left bracket", lineno, n); } } @@ -1032,7 +1799,7 @@ int main(int argc, char **argv, char **envp) if (bnest < 1) { - fprintf(stderr, "Unmatched right brace at line %d:%d\n", lineno, n); + ERROR("Unmatched right brace", lineno, n); } else { @@ -1062,8 +1829,7 @@ int main(int argc, char **argv, char **envp) { if (dnest == 0) { - fprintf(stderr, - "Right bracket not on separate line at %d:%d\n", + ERROR("Right bracket not on separate line", lineno, n); } } @@ -1074,32 +1840,94 @@ int main(int argc, char **argv, char **envp) line[n + 1] != ',' && line[n + 1] != ';') { - /* One case where there may be garbage after the right - * bracket is, for example, when declaring a until or - * structure variable using an un-named union or - * structure. + int sndx = n + 1; + bool whitespace = false; + + /* Skip over spaces */ + + while (line[sndx] == ' ') + { + sndx++; + } + + /* One possibility is that the right bracket is + * followed by an identifier then a semi-colon. + * Comma is possible to but would be a case of + * multiple declaration of multiple instances. */ - if (prevdnest <= 0 || dnest > 0) + if (line[sndx] == '_' || isalpha(line[sndx])) { - /* REVISIT: Generates false alarms on named structures - * that are fields of other structures or unions. + int endx = sndx; + + /* Skip to the end of the identifier. Checking + * for mixed case identifiers will be done + * elsewhere. */ - fprintf(stderr, - "Garbage follows right bracket at line %d:%d\n", - lineno, n); + while (line[endx] == '_' || + isalnum(line[endx])) + { + endx++; + } + + /* Skip over spaces */ + + while (line[endx] == ' ') + { + whitespace = true; + endx++; + } + + /* Handle according to what comes after the + * identifier. + */ + + if (strncmp(&line[sndx], "while", 5) == 0) + { + ERROR("'while' must be on a separate line", + lineno, sndx); + } + else if (line[endx] == ',') + { + ERROR("Multiple data definitions on line", + lineno, endx); + } + else if (line[endx] == ';') + { + if (whitespace) + { + ERROR("Space precedes semi-colon", + lineno, endx); + } + } + else if (line[endx] == '=') + { + /* There's a struct initialization following */ + + check_spaces_leftright(line, lineno, endx, endx); + dnest = 1; + } + else + { + ERROR("Garbage follows right bracket", + lineno, n); + } + } + else + { + ERROR("Garbage follows right bracket", lineno, n); } } - /* The right brace should not be preceded with a a blank line */ - + /* The right brace should not be preceded with a a blank + * line. + */ if (lineno == blank_lineno + 1) { - fprintf(stderr, - "Blank line precedes right brace at line %d\n", - lineno); + ERROR("Blank line precedes right brace at line", + lineno, 1); } rbrace_lineno = lineno; @@ -1116,11 +1944,9 @@ int main(int argc, char **argv, char **envp) /* Check for inappropriate space around parentheses */ - if (line[n + 1] == ' ' /* && !bfor */) + if (line[n + 1] == ' ') /* && !bfor */ { - fprintf(stderr, - "Space follows left parenthesis at line %d:%d\n", - lineno, n); + ERROR("Space follows left parenthesis", lineno, n); } } break; @@ -1131,8 +1957,7 @@ int main(int argc, char **argv, char **envp) if (pnest < 1) { - fprintf(stderr, "Unmatched right parentheses at line %d:%d\n", - lineno, n); + ERROR("Unmatched right parentheses", lineno, n); pnest = 0; } else @@ -1146,9 +1971,7 @@ int main(int argc, char **argv, char **envp) if (n > 0 && n != indent && line[n - 1] == ' ' && !bfor) { - fprintf(stderr, - "Space precedes right parenthesis at line %d:%d\n", - lineno, n); + ERROR("Space precedes right parenthesis", lineno, n); } } break; @@ -1159,9 +1982,7 @@ int main(int argc, char **argv, char **envp) { if (line[n + 1] == ' ') { - fprintf(stderr, - "Space follows left bracket at line %d:%d\n", - lineno, n); + ERROR("Space follows left bracket", lineno, n); } } break; @@ -1170,9 +1991,7 @@ int main(int argc, char **argv, char **envp) { if (n > 0 && line[n - 1] == ' ') { - fprintf(stderr, - "Space precedes right bracket at line %d:%d\n", - lineno, n); + ERROR("Space precedes right bracket", lineno, n); } } break; @@ -1183,8 +2002,7 @@ int main(int argc, char **argv, char **envp) { if (!isspace((int)line[n + 1])) { - fprintf(stderr, "Missing whitespace after semicolon at line %d:%d\n", - lineno, n); + ERROR("Missing whitespace after semicolon", lineno, n); } /* Semicolon terminates a declaration/definition if there @@ -1204,8 +2022,7 @@ int main(int argc, char **argv, char **envp) { if (!isspace((int)line[n + 1])) { - fprintf(stderr, "Missing whitespace after comma at line %d:%d\n", - lineno, n); + ERROR("Missing whitespace after comma", lineno, n); } } break; @@ -1235,6 +2052,7 @@ int main(int argc, char **argv, char **envp) /* Check for space around various operators */ case '-': + /* ->, -- */ if (line[n + 1] == '>' || line[n + 1] == '-') @@ -1249,6 +2067,19 @@ int main(int argc, char **argv, char **envp) check_spaces_leftright(line, lineno, n, n + 1); n++; } + + /* Scientific notation with a negative exponent (eg. 10e-10) + * REVISIT: This fails for cases where the variable name + * ends with 'e' preceded by a digit: + * a = abc1e-10; + * a = ABC1E-10; + */ + + else if ((line[n - 1] == 'e' || line[n - 1] == 'E') && + isdigit(line[n + 1]) && isdigit(line[n - 2])) + { + n++; + } else { /* '-' may function as a unary operator and snuggle @@ -1261,6 +2092,7 @@ int main(int argc, char **argv, char **envp) break; case '+': + /* ++ */ if (line[n + 1] == '+') @@ -1310,7 +2142,8 @@ int main(int argc, char **argv, char **envp) break; case '/': - /* C comment terminator*/ + + /* C comment terminator */ if (line[n - 1] == '*') { @@ -1326,7 +2159,7 @@ int main(int argc, char **argv, char **envp) if ((n < 5 || strncmp(&line[n - 5], "http://", 7) != 0) && (n < 6 || strncmp(&line[n - 6], "https://", 8) != 0)) { - fprintf(stderr, "C++ style comment on at %d:%d\n", + ERROR("C++ style comment on at %d:%d\n", lineno, n); } @@ -1351,6 +2184,7 @@ int main(int argc, char **argv, char **envp) break; case '*': + /* *\/, ** */ if (line[n] == '*' && @@ -1378,9 +2212,8 @@ int main(int argc, char **argv, char **envp) if (line[n - 1] != ' ') { - fprintf(stderr, - "Operator/assignment must be preceded with whitespace at line %d:%d\n", - lineno, n); + ERROR("Operator/assignment must be preceded " + "with whitespace", lineno, n); } break; @@ -1406,6 +2239,7 @@ int main(int argc, char **argv, char **envp) break; case '%': + /* %= */ if (line[n + 1] == '=') @@ -1421,6 +2255,7 @@ int main(int argc, char **argv, char **envp) break; case '<': + /* <=, <<, <<= */ if (line[n + 1] == '=') @@ -1449,6 +2284,7 @@ int main(int argc, char **argv, char **envp) break; case '>': + /* >=, >>, >>= */ if (line[n + 1] == '=') @@ -1477,6 +2313,7 @@ int main(int argc, char **argv, char **envp) break; case '|': + /* |=, || */ if (line[n + 1] == '=') @@ -1497,6 +2334,7 @@ int main(int argc, char **argv, char **envp) break; case '^': + /* ^= */ if (line[n + 1] == '=') @@ -1512,6 +2350,7 @@ int main(int argc, char **argv, char **envp) break; case '=': + /* == */ if (line[n + 1] == '=') @@ -1531,6 +2370,7 @@ int main(int argc, char **argv, char **envp) break; case '!': + /* != */ if (line[n + 1] == '=') @@ -1561,26 +2401,65 @@ int main(int argc, char **argv, char **envp) /* Loop terminates when NUL or newline character found */ - if (line[n] == '\n') + if (line[n] == '\n' || line[n] == '\0') { + /* If the parse terminated on the NULL, then back up to the last + * character (which should be the newline). + */ + + int m = n; + if (line[m] == '\0' && m > 0) + { + m--; + } + /* Check for space at the end of the line. Except for carriage * returns which we have already reported (one time) above. */ - if (n > 1 && isspace((int)line[n - 1]) && line[n - 1] != '\r') + if (m > 1 && isspace((int)line[m - 1]) && + line[m - 1] != '\n' && line[m - 1] != '\r') + { + ERROR("Dangling whitespace at the end of line", lineno, m); + } + + /* The line width is determined by the location of the final + * asterisk in block comments. The closing line of the block + * comment will exceed that by one one character, the '/' + * following the final asterisk. + */ + + else if (m > g_maxline) { - fprintf(stderr, - "Dangling whitespace at the end of line %d:%d\n", - lineno, n); + bool bslash; + int a; + + for (bslash = false, a = m; + a > 2 && strchr("\n\r/", line[a]) != NULL; + a--) + { + if (line[a] == '/') + { + bslash = true; + } + } + + if (bslash && line[a] == '*') + { + m = a + 1; + } } - /* Check for long lines */ + /* Check for long lines + * + * REVISIT: Long line checks suppressed on right hand comments + * for now. This just prevents a large number of difficult-to- + * fix complaints that we would have otherwise. + */ - if (n > maxline) + if (m > g_maxline && !rhcomment) { - fprintf(stderr, - "Long line found at %d:%d\n", - lineno, n); + ERROR("Long line found", lineno, m); } } @@ -1592,10 +2471,19 @@ int main(int argc, char **argv, char **envp) if ((ncomment > 0 || prevncomment > 0) && !bstring) { + /* Nothing should begin in comment zero */ + if (indent == 0 && line[0] != '/' && !bexternc) { - fprintf(stderr, "No indentation line %d:%d\n", - lineno, indent); + /* NOTE: if this line contains a comment to the right of the + * code, then ncomment will be misleading because it was + * already incremented above. + */ + + if (ncomment > 1 || rhcomment == 0) + { + ERROR("No indentation line", lineno, indent); + } } else if (indent == 1 && line[0] == ' ' && line[1] == '*') { @@ -1603,60 +2491,58 @@ int main(int argc, char **argv, char **envp) } else if (indent > 0 && line[indent] == '\n') { - fprintf(stderr, "Whitespace on blank line at line %d:%d\n", - lineno, indent); + ERROR("Whitespace on blank line", lineno, indent); } else if (indent > 0 && indent < 2) { if (bnest > 0) { - fprintf(stderr, "Insufficient indentation line %d:%d\n", - lineno, indent); + ERROR("Insufficient indentation", lineno, indent); } else { - fprintf(stderr, "Expected indentation line %d:%d\n", - lineno, indent); + ERROR("Expected indentation line", lineno, indent); } } else if (indent > 0 && !bswitch) { if (line[indent] == '/') { - if ((indent & 3) != 2) + /* Comments should like at offsets 2, 6, 10, ... + * This rule is not followed, however, if the comments are + * aligned to the right of the code. + */ + + if ((indent & 3) != 2 && rhcomment == 0) { - fprintf(stderr, - "Bad comment alignment at line %d:%d\n", - lineno, indent); + ERROR("Bad comment alignment", lineno, indent); } /* REVISIT: This screws up in cases where there is C code, * followed by a comment that continues on the next line. */ - else if (line[indent+1] != '*') + else if (line[indent + 1] != '*') { - fprintf(stderr, - "Missing asterisk in comment at line %d:%d\n", - lineno, indent); + ERROR("Missing asterisk in comment", lineno, indent); } } else if (line[indent] == '*') { /* REVISIT: Generates false alarms on comments at the end of * the line if there is nothing preceding (such as the aligned - * comments with a structure field definition). So disabled for - * comments before beginning of function definitions. + * comments with a structure field definition). So disabled + * for comments before beginning of function definitions. * - * Suppress this error if this is a comment to the right of code. + * Suppress this error if this is a comment to the right of + * code. * Those may be unaligned. */ - if ((indent & 3) != 3 && bfunctions && dnest == 0 && !brhcomment) + if ((indent & 3) != 3 && bfunctions && dnest == 0 && + rhcomment == 0) { - fprintf(stderr, - "Bad comment block alignment at line %d:%d\n", - lineno, indent); + ERROR("Bad comment block alignment", lineno, indent); } if (line[indent + 1] != ' ' && @@ -1664,9 +2550,8 @@ int main(int argc, char **argv, char **envp) line[indent + 1] != '\n' && line[indent + 1] != '/') { - fprintf(stderr, - "Invalid character after asterisk in comment block at line %d:%d\n", - lineno, indent); + ERROR("Invalid character after asterisk " + "in comment block", lineno, indent); } } @@ -1676,8 +2561,7 @@ int main(int argc, char **argv, char **envp) else if (prevncomment > 0) { - fprintf(stderr, "Missing asterisk in comment block at line %d:%d\n", - lineno, indent); + ERROR("Missing asterisk in comment block", lineno, indent); } } } @@ -1696,14 +2580,14 @@ int main(int argc, char **argv, char **envp) if (isalpha((int)line[indent])) { - for (i = indent + 1; isalnum((int)line[i]) || line[i] == '_'; i++); + for (i = indent + 1; isalnum((int)line[i]) || + line[i] == '_'; i++); blabel = (line[i] == ':'); } if (!blabel && !bexternc) { - fprintf(stderr, "No indentation line %d:%d\n", - lineno, indent); + ERROR("No indentation line", lineno, indent); } } } @@ -1713,30 +2597,36 @@ int main(int argc, char **argv, char **envp) } else if (indent > 0 && line[indent] == '\n') { - fprintf(stderr, "Whitespace on blank line at line %d:%d\n", - lineno, indent); + ERROR("Whitespace on blank line", lineno, indent); } else if (indent > 0 && indent < 2) { - fprintf(stderr, "Insufficient indentation line %d:%d\n", - lineno, indent); + ERROR("Insufficient indentation line", lineno, indent); } else if (line[indent] == '{') { + /* Check for left brace in first column, but preceded by a + * blank line. Should never happen (but could happen with + * internal compound statements). + */ + + if (indent == 0 && lineno == blank_lineno + 1) + { + ERROR("Blank line before opening left brace", lineno, indent); + } + /* REVISIT: Possible false alarms in compound statements * without a preceding conditional. That usage often violates * the coding standard. */ - if (!bfunctions && (indent & 1) != 0) + else if (!bfunctions && (indent & 1) != 0) { - fprintf(stderr, "Bad left brace alignment at line %d:%d\n", - lineno, indent); + ERROR("Bad left brace alignment", lineno, indent); } else if ((indent & 3) != 0 && !bswitch && dnest == 0) { - fprintf(stderr, "Bad left brace alignment at line %d:%d\n", - lineno, indent); + ERROR("Bad left brace alignment", lineno, indent); } } else if (line[indent] == '}') @@ -1748,20 +2638,18 @@ int main(int argc, char **argv, char **envp) if (!bfunctions && (indent & 1) != 0) { - fprintf(stderr, "right left brace alignment at line %d:%d\n", - lineno, indent); + ERROR("right left brace alignment", lineno, indent); } else if ((indent & 3) != 0 && !bswitch && prevdnest == 0) { - fprintf(stderr, "Bad right brace alignment at line %d:%d\n", - lineno, indent); + ERROR("Bad right brace alignment", lineno, indent); } } else if (indent > 0) { /* REVISIT: Generates false alarms when a statement continues on - * the next line. The bstatm check limits to lines beginning with - * C keywords. + * the next line. The bstatm check limits to lines beginning + * with C keywords. * REVISIT: The bstatm check will not detect statements that * do not begin with a C keyword (such as assignment statements). * REVISIT: Generates false alarms on comments at the end of @@ -1777,8 +2665,7 @@ int main(int argc, char **argv, char **envp) { if ((indent & 3) != 2) { - fprintf(stderr, "Bad alignment at line %d:%d\n", - lineno, indent); + ERROR("Bad alignment", lineno, indent); } } @@ -1789,24 +2676,29 @@ int main(int argc, char **argv, char **envp) else if (indent == 1 || indent == 3) { - fprintf(stderr, "Small odd alignment at line %d:%d\n", - lineno, indent); + ERROR("Small odd alignment", lineno, indent); } } } } - if (!bfunctions && !hdrfile) + if (!bfunctions && g_file_type == C_SOURCE) { - fprintf(stderr, "ERROR: \"Private/Public Functions\" not found!\n"); - fprintf(stderr, " File could not be checked.\n"); + ERROR("\"Private/Public Functions\" not found!" + " File was not be checked", lineno, 1); } if (ncomment > 0 || bstring) { - fprintf(stderr, "ERROR: In a comment/string at end of file\n"); + ERROR("Comment or string found at end of file", lineno, 1); } fclose(instream); - return 0; + if (g_verbose == 1) + { + fprintf(stderr, "%s: %s nxstyle check\n", g_file_name, + g_status == 0 ? "PASSED" : "FAILED"); + } + + return g_status; }