📄 ncplus_mjpeg.c
字号:
int ret = 0; int arg_temp; strt_mjpeg_copy *arg_temp_strt; int thread_num; /* * extract the type and number bitfields, and don't decode * wrong cmds: return ENOTTY (inappropriate ioctl) before access_ok() */ if (_IOC_TYPE(cmd) != MJPEG_IOC_MAGIC) return -ENOTTY; if (_IOC_NR(cmd) > MJPEG_IOC_MAXNR) return -ENOTTY; /* * the direction is a bitmask, and VERIFY_WRITE catches R/W * transfers. `Type' is user-oriented, while * access_ok is kernel-oriented, so the concept of "read" and * "write" is reversed */ if (_IOC_DIR(cmd) & _IOC_READ) err = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd)); else if (_IOC_DIR(cmd) & _IOC_WRITE) err = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd)); if (err) return -EFAULT; switch(cmd) {#ifdef MJPEG_DEBUG case MJPEG_IOCHARDRESET: /* * reset the counter to 1, to allow unloading in case * of problems. Use 1, not 0, because the invoking * process has the device open. */ while (MOD_IN_USE) MOD_DEC_USE_COUNT; MOD_INC_USE_COUNT; /* don't break: fall through and reset things */#endif /* MJPEG_DEBUG */ case MJPEG_IOCRESET: if (mjpeg_reset(dev) < 0) printk("mjpeg: reset failed\n"); break; case MJPEG_IOCQFRAMEAVAIL: /* Query: frame available? */ return (dev->rbuf->valid); case MJPEG_IOCQFRAMESIZE: /* Query: return the size of frame available */ return (dev->rbuf->count); case MJPEG_IOCTALPHA: /* Tell: set the alpha coefficient value */ arg_temp = (int)arg; // Dojip if (arg_temp < 0 || arg_temp > 2048) { printk("invalid alpha_coeff value : %d\n", arg_temp); return -ENOTTY; } mjpeg_alphacoeff = arg_temp; mjpeg_reset(dev); break; case MJPEG_IOCQALPHA: // Query: return it return mjpeg_alphacoeff; case MJPEG_IOCTRESOL: /* Tell: set the resolution mode */ arg_temp = (int)arg; if(arg_temp<0 || arg_temp>5) { printk("invalid resol value : %d\n", arg_temp); return -ENOTTY; } mjpeg_default = arg_temp; mjpeg_reset(dev); break; case MJPEG_IOCQRESOL: // Query: return it return mjpeg_default; case MJPEG_IOCGREAD: arg_temp_strt = (strt_mjpeg_copy *)arg; thread_num = arg_temp_strt->thread_no; if (mjpeg_debug_ioctl) printk("ioc_get_read\n"); if(gs_thread_no & (1<<thread_num)) return 0; ret = mjpeg_read(filp, arg_temp_strt->copy2user, 0, NULL); if(ret) gs_thread_no |= (1<<thread_num); return ret; case MJPEG_IOCTROTATE: if (arg >= 4) { printk("mjpeg: invalid rotate value %d\n", (int)arg); return -ENOTTY; } dev->jpg_rotate = (int)arg; break; case MJPEG_IOCQROTATE: return (dev->jpg_rotate); default: /* redundant, as cmd was checked against MAXNR */ if (mjpeg_debug_ioctl) printk("-enotty\n"); return -ENOTTY; } return ret;}// Default Setting!!!/* * setup_mjpeg_default * 160x120, 422, alpha 50%, 10x15 (mcu) */static void setup_mjpeg(struct mjpeg_device *dev){ int i; //mjpeg_buff_init(dev); gs_new_frame = 0; for(i=0; i<QUANTS_COUNT; i++) mjpeg_writel((unsigned long)yquant[i], Y_QUANT_COEFF+(i*4)); for(i=0; i<QUANTS_COUNT; i++) mjpeg_writel((unsigned long)uvquant[i], UV_QUANT_COEFF+(i*4)); setting_by_ioctl(dev); /* common setting */ mjpeg_writel(YSTART_ADD_VAL_140, YSTART_ADD); // always 0x0 at the YSTART_ADD mjpeg_writel(mjpeg_alphacoeff, ALPHA_COEFF); /* * JPEG headeer setting */ mjpeg_hdr_qt(dev); mjpeg_writel(SDRAM_MODE_COM_VAL, SDRAM_MODE_COM); // interrupt mode mjpeg_writel(FIFO_ENABLE|FIFO_SET_HALF, DMA_MODE_COMMAND); // interrupt mode mjpeg_writel(DMA_START_ADD_VAL, DMA_START_ADD); mjpeg_writel(DMA_COUNT_NUM_VAL, DMA_COUNT_NUM); // questionable mjpeg_writel(DMA_DESTINATION_VAL, DMA_DESTINATION); mjpeg_writel(0x2, 0x22c); mjpeg_buff_init(dev);} /* setup_mjpeg() */static void setting_by_ioctl(struct mjpeg_device *dev) { int resolution = mjpeg_default; /* * mjpg header setting */ mjpeg_hdr_res(dev); if(resolution == 0) { /* mjpeg core register setting */ mjpeg_writel(USTART_ADD_VAL_140, USTART_ADD); mjpeg_writel(VSTART_ADD_VAL_140, VSTART_ADD); mjpeg_writel(IMAGE_MCUWIDE_VAL_140, IMAGE_MCUWIDE); mjpeg_writel(IMAGE_MCUHIGH_VAL_140, IMAGE_MCUHIGH); mjpeg_writel(RSTINTERVAL_VAL_140, RSTINTERVAL); /* mjpeg interface register setting */ mjpeg_writel(PREPRO_HLENGTH_VAL_140, PREPRO_HLENGTH); mjpeg_writel(PREPRO_VLENGTH_VAL_140, PREPRO_VLENGTH); mjpeg_writel(PREPRO_FORMAT_VAL_140, PREPRO_FORMAT); mjpeg_writel(mjpeg_perform, 0x23c); } else if(resolution == 1) { /* mjpeg core register setting */ mjpeg_writel(USTART_ADD_VAL_142, USTART_ADD); mjpeg_writel(VSTART_ADD_VAL_142, VSTART_ADD); mjpeg_writel(IMAGE_MCUWIDE_VAL_142, IMAGE_MCUWIDE); mjpeg_writel(IMAGE_MCUHIGH_VAL_142, IMAGE_MCUHIGH); mjpeg_writel(RSTINTERVAL_VAL_142, RSTINTERVAL); /* mjpeg interface register setting */ mjpeg_writel(PREPRO_HLENGTH_VAL_142, PREPRO_HLENGTH); mjpeg_writel(PREPRO_VLENGTH_VAL_142, PREPRO_VLENGTH); mjpeg_writel(PREPRO_FORMAT_VAL_142, PREPRO_FORMAT); mjpeg_writel(mjpeg_perform, 0x23c); } else if(resolution == 2) { /* mjpeg core register setting */ mjpeg_writel(USTART_ADD_VAL_340, USTART_ADD); mjpeg_writel(VSTART_ADD_VAL_340, VSTART_ADD); mjpeg_writel(IMAGE_MCUWIDE_VAL_340, IMAGE_MCUWIDE); mjpeg_writel(IMAGE_MCUHIGH_VAL_340, IMAGE_MCUHIGH); mjpeg_writel(RSTINTERVAL_VAL_340, RSTINTERVAL); /* mjpeg interface register setting */ mjpeg_writel(PREPRO_HLENGTH_VAL_340, PREPRO_HLENGTH); mjpeg_writel(PREPRO_VLENGTH_VAL_340, PREPRO_VLENGTH); mjpeg_writel(PREPRO_FORMAT_VAL_340, PREPRO_FORMAT); mjpeg_writel(mjpeg_perform, 0x23c); } else if(resolution == 3) { /* mjpeg core register setting */ mjpeg_writel(USTART_ADD_VAL_342, USTART_ADD); mjpeg_writel(VSTART_ADD_VAL_342, VSTART_ADD); mjpeg_writel(IMAGE_MCUWIDE_VAL_342, IMAGE_MCUWIDE); mjpeg_writel(IMAGE_MCUHIGH_VAL_342, IMAGE_MCUHIGH); mjpeg_writel(RSTINTERVAL_VAL_342, RSTINTERVAL); /* mjpeg interface register setting */ mjpeg_writel(PREPRO_HLENGTH_VAL_342, PREPRO_HLENGTH); mjpeg_writel(PREPRO_VLENGTH_VAL_342, PREPRO_VLENGTH); mjpeg_writel(PREPRO_FORMAT_VAL_342, PREPRO_FORMAT); mjpeg_writel(mjpeg_perform, 0x23c); //mjpeg_writel(0x2301, 0x23c); // CIF 15 frames/sec } else if(resolution == 4) { /* mjpeg core register setting */ mjpeg_writel(USTART_ADD_VAL_640, USTART_ADD); mjpeg_writel(VSTART_ADD_VAL_640, VSTART_ADD); mjpeg_writel(IMAGE_MCUWIDE_VAL_640, IMAGE_MCUWIDE); mjpeg_writel(IMAGE_MCUHIGH_VAL_640, IMAGE_MCUHIGH); mjpeg_writel(RSTINTERVAL_VAL_640, RSTINTERVAL); /* mjpeg interface register setting */ mjpeg_writel(PREPRO_HLENGTH_VAL_640, PREPRO_HLENGTH); mjpeg_writel(PREPRO_VLENGTH_VAL_640, PREPRO_VLENGTH); mjpeg_writel(PREPRO_FORMAT_VAL_640, PREPRO_FORMAT); mjpeg_writel(mjpeg_perform, 0x23c); } else if(resolution == 5) { /* mjpeg core register setting */ mjpeg_writel(USTART_ADD_VAL_642, USTART_ADD); mjpeg_writel(VSTART_ADD_VAL_642, VSTART_ADD); mjpeg_writel(IMAGE_MCUWIDE_VAL_642, IMAGE_MCUWIDE); mjpeg_writel(IMAGE_MCUHIGH_VAL_642, IMAGE_MCUHIGH); mjpeg_writel(RSTINTERVAL_VAL_642, RSTINTERVAL); /* mjpeg interface register setting */ mjpeg_writel(PREPRO_HLENGTH_VAL_642, PREPRO_HLENGTH); mjpeg_writel(PREPRO_VLENGTH_VAL_642, PREPRO_VLENGTH); mjpeg_writel(PREPRO_FORMAT_VAL_642, PREPRO_FORMAT); mjpeg_writel(mjpeg_perform, 0x23c); }}/* * success: return 0 * fail : return -1 */static int mjpeg_raw_reset(void){ //unsigned long status; unsigned long timeout; mjpeg_writel(MODULE_FUNC_SET_STOP, MODULE_FUNC_SET); // stop operation mjpeg_writel(MODULE_FUNC_SET_STOP|MODULE_FUNC_SET_RESET, MODULE_FUNC_SET); // module reset //status = mjpeg_readl(MODULE_FUNC_SET) & 0x0000000f; timeout = jiffies + (1 * HZ); // 1secs while (mjpeg_readl(MODULE_FUNC_SET) & MODULE_FUNC_SET_RESET) { if (jiffies > timeout) return -1; } return 0;}static int mjpeg_reset(struct mjpeg_device *dev){ disable_irq(IRQ_MJPEG); // disable interrupt if (mjpeg_raw_reset() < 0) { enable_irq(IRQ_MJPEG); return -1; } enable_irq(IRQ_MJPEG); // enable interrupt setup_mjpeg(dev); // set the registers for mjpeg mjpeg_writel(MODULE_FUNC_SET_NORMAL, MODULE_FUNC_SET); // start mjpeg return 0;}/* * mjpeg watchdog timer init */static void mjpeg_watchdog_init(void) { mjpeg_watchdog_timeout = jiffies + (HZ * 2 * MJPEG_WATCHDOG_TIMEOUT); init_timer(&mjpeg_watchdog_timer); mjpeg_watchdog_timer.function = mjpeg_watchdog; mjpeg_watchdog_timer.data = 0; mjpeg_watchdog_timer.expires = mjpeg_watchdog_timeout; add_timer(&mjpeg_watchdog_timer);}static void mjpeg_watchdog(unsigned long data){ mjpeg_reset(mjpeg_dev); mjpeg_watchdog_timeout = jiffies + (HZ * MJPEG_WATCHDOG_TIMEOUT); mod_timer(&mjpeg_watchdog_timer, mjpeg_watchdog_timeout); //printk("mjpeg: watchdog timeout\n");}/* * mjpeg data buffer allocation */static int mjpeg_buff_alloc(struct mjpeg_device *dev){ int i; for (i = 0; i < 2; i++) { dev->buf[i].valid = 0; dev->buf[i].count = 0; dev->buf[i].data = vmalloc(COMPRESSED_SIZE); if (!dev->buf[i].data) { printk("buffer allocation failed (%d)\n", i); mjpeg_buff_free(dev); return -1; } memset(dev->buf[i].data, 0, COMPRESSED_SIZE); } return 0;}/* * mjpeg data buffer free */static void mjpeg_buff_free(struct mjpeg_device *dev){ int i; for (i = 0; i < 2; i++) { if (dev->buf[i].data != NULL) { vfree(dev->buf[i].data); dev->buf[i].data = NULL; } }}/* * mjpeg init_module */int mjpeg_init_module(void){ int result = 0; struct mjpeg_device *dev = NULL; int i; SET_MODULE_OWNER(&mjpeg_fops); printk("%s", version); mjpeg_dev = kmalloc(sizeof(struct mjpeg_device), GFP_KERNEL); if (!mjpeg_dev) { return -ENOMEM; } dev = mjpeg_dev; memset(dev, 0, sizeof(struct mjpeg_device)); // mjpeg data buffer initialization if (mjpeg_buff_alloc(dev) < 0) { kfree(dev); return -ENOMEM; } // mjpeg watchdog init mjpeg_watchdog_init(); dev->wbuf = &(dev->buf[0]); dev->rbuf = &(dev->buf[1]); dev->max_size = -1; dev->jpg_rotate = 0; // Normal // jpeg header copy for (i = 0; i < JPEG_HDR_SIZE; i++) { dev->jpg_hdr[i] = _jpg_hdr[i]; } gs_new_frame = 0; /* spin_lock initailizing */ dev->lock = SPIN_LOCK_UNLOCKED;#ifdef MJPEG_PROC proc_mjpeg = create_proc_entry("mjpeg", S_IFREG | S_IWUSR, &proc_root); proc_mjpeg->read_proc = mjpeg_read_proc;#endif // Installing an interrupt handler result = request_irq(IRQ_MJPEG, ncplus_mjpeg_interrupt, 0, DEVICE_NAME, dev); if (result < 0) { printk("mjpeg: can't install an interrupt handler\n"); result = -EBUSY; goto irq_fail; } /* * Register your major, and accept a dynamic number. * This is the first thing to do, * in order to avoid releasing other module's fops in mjpeg_cleanup_module() */ if ((result = register_chrdev(mjpeg_major, DEVICE_NAME, &mjpeg_fops)) < 0) { printk(KERN_WARNING "mjpeg: can't get major (%d)\n", mjpeg_major); goto dev_fail; //return result; } if (mjpeg_major == 0) mjpeg_major = result; /* dynamic */ printk(DEVICE_NAME " : device registered with major number = %d\n", mjpeg_major);#ifndef MJPEG_DEBUG EXPORT_NO_SYMBOLS; /* otherwise, leave global symbols visible */#endif mjpeg_reset(dev); // start mjpeg return 0;dev_fail:#ifdef MJPEG_PROC remove_proc_entry("mjpeg", &proc_root);#endif free_irq(IRQ_MJPEG, dev);irq_fail: /* * mjpeg buffer free */ mjpeg_buff_free(dev); /* * watchdog timer deletion */ del_timer_sync(&mjpeg_watchdog_timer); /* * mjpeg device structure free */ if (dev != NULL) { kfree(dev); dev = NULL; } return result;}void mjpeg_cleanup_module(void){ int nRetCode; // del watchdog timer del_timer_sync(&mjpeg_watchdog_timer); //if(mjpeg_debug_stop) mjpeg_writel(MODULE_FUNC_SET_RESET, MODULE_FUNC_SET); // stop operation free_irq(IRQ_MJPEG, mjpeg_dev); mjpeg_buff_free(mjpeg_dev); printk("Unloading MJPEG Module\n"); /* cleanup_module is never called if registering failed */ if ((nRetCode = unregister_chrdev(mjpeg_major, DEVICE_NAME)) < 0) printk(DEVICE_NAME " : Device unregistration failed (%d)\n", nRetCode); if (mjpeg_dev != NULL) kfree(mjpeg_dev); mjpeg_dev = NULL; /* pedantic -.-; */#ifdef MJPEG_PROC remove_proc_entry("mjpeg", &proc_root);#endif return;}module_init(mjpeg_init_module);module_exit(mjpeg_cleanup_module);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -