static int vloopback_release(struct file *f) #endif { struct video_device *loopdev = video_devdata(f); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) priv_ptr ptr = (priv_ptr)dev_get_drvdata(&loopdev->dev); #else priv_ptr ptr = (priv_ptr)loopdev->vd_private_data; #endif int nr = ptr->pipenr; if (debug > LOG_NODEBUG) info("Video loopback %d", nr); if (ptr->in) { down(&loops[nr]->lock); if (loops[nr]->buffer && !loops[nr]->ropen) { rvfree(loops[nr]->buffer, loops[nr]->buflength * num_buffers); loops[nr]->buffer = NULL; } up(&loops[nr]->lock); loops[nr]->frameswrite++; if (waitqueue_active(&loops[nr]->wait)) wake_up(&loops[nr]->wait); loops[nr]->width = 0; loops[nr]->height = 0; loops[nr]->palette = 0; loops[nr]->wopen = 0; pipesused--; } else { down(&loops[nr]->lock); if (loops[nr]->buffer && !loops[nr]->wopen) { rvfree(loops[nr]->buffer, loops[nr]->buflength * num_buffers); loops[nr]->buffer = NULL; } up(&loops[nr]->lock); loops[nr]->ropen = 0; if (loops[nr]->zerocopy && loops[nr]->buffer) { loops[nr]->ioctlnr = 0; loops[nr]->ioctllength = 0; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) kill_proc(loops[nr]->pid, SIGIO, 1); #else kill_pid(loops[nr]->pid, SIGIO, 1); #endif } } return 0; }
static int vloopback_release(struct inode *inod, struct file *f) #endif { struct video_device *loopdev=video_devdata(f); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) priv_ptr ptr=(priv_ptr)video_get_drvdata(loopdev); #else priv_ptr ptr=(priv_ptr)loopdev->priv; #endif int nr=ptr->pipenr; if (ptr->in) { down(&loops[nr]->lock); if (loops[nr]->buffer && !loops[nr]->ropen) { rvfree(loops[nr]->buffer, loops[nr]->buflength*N_BUFFS); loops[nr]->buffer=NULL; } up(&loops[nr]->lock); if (waitqueue_active(&loops[nr]->wait)) { loops[nr]->frameswrite++; wake_up(&loops[nr]->wait); } loops[nr]->width=0; loops[nr]->height=0; loops[nr]->palette=0; loops[nr]->wopen=0; pipesused--; } else { down(&loops[nr]->lock); if (loops[nr]->buffer && !loops[nr]->wopen) { rvfree(loops[nr]->buffer, loops[nr]->buflength*N_BUFFS); loops[nr]->buffer=NULL; } up(&loops[nr]->lock); if (waitqueue_active(&loops[nr]->wait)) { loops[nr]->pendingread = 1; wake_up(&loops[nr]->wait); } loops[nr]->ropen=0; if (loops[nr]->zerocopy && loops[nr]->buffer) { loops[nr]->ioctlnr=0; loops[nr]->ioctllength=0; kill_proc(loops[nr]->pid, SIGIO, 1); } } return 0; }
static void __exit cleanup_vloopback_module(void) { int i; info("Unregistering video4linux loopback devices"); for (i = 0; i < nr_o_pipes; i++) { if (loops[i]) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) priv_ptr ptr_in = (priv_ptr)dev_get_drvdata(&loops[i]->vloopin->dev); kfree(ptr_in); dev_set_drvdata(&loops[i]->vloopin->dev, NULL); #else kfree(loops[i]->vloopin->vd_private_data); #endif video_unregister_device(loops[i]->vloopin); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) priv_ptr ptr_out = (priv_ptr)dev_get_drvdata(&loops[i]->vloopout->dev); kfree(ptr_out); dev_set_drvdata(&loops[i]->vloopout->dev, NULL); #else kfree(loops[i]->vloopout->vd_private_data); #endif video_unregister_device(loops[i]->vloopout); if (loops[i]->buffer) rvfree(loops[i]->buffer, loops[i]->buflength * num_buffers); kfree(loops[i]->ioctldata); kfree(loops[i]->ioctlretdata); kfree(loops[i]); } } }
static inline void *_rt_shm_alloc(unsigned long name, int size, int suprt) { void *adr; // suprt = USE_GFP_ATOMIC; // to force some testing if (!(adr = rt_get_adr_cnt(name)) && size > 0 && suprt >= 0 && RT_SHM_OP_PERM()) { size = ((size - 1) & PAGE_MASK) + PAGE_SIZE; if ((adr = suprt ? rkmalloc(&size, SUPRT[suprt]) : rvmalloc(size))) { if (!rt_register(name, adr, suprt ? -size : size, 0)) { if (suprt) { rkfree(adr, size); } else { rvfree(adr, size); } return 0; } memset(ALIGN2PAGE(adr), 0, size); } } return ALIGN2PAGE(adr); }
static int dhahelper_free_pa(dhahelper_mem_t *arg) { dhahelper_mem_t mem; if (copy_from_user(&mem, arg, sizeof(dhahelper_mem_t))) { if (dhahelper_verbosity > 0) printk(KERN_ERR "dhahelper: failed copy from userspace\n"); return -EFAULT; } rvfree(mem.addr,mem.length); return 0; }
static int qtft_fb_remove(struct platform_device *dev) { struct fb_info *info = platform_get_drvdata(dev); func_in(); if (info) { lcd_exit(); unregister_framebuffer(info); fb_dealloc_cmap(&info->cmap); framebuffer_release(info); rvfree(videomemory, videomemorysize); } func_out(); return 0; }
static inline int _rt_shm_free(unsigned long name, int size) { void *adr; if (size && (adr = rt_get_adr(name))) { if (RT_SHM_OP_PERM()) { if (!rt_drg_on_name_cnt(name) && name != GLOBAL_HEAP_ID) { if (size < 0) { rkfree(adr, -size); } else { rvfree(adr, size); } } } return abs(size); } return 0; }
static void __exit cleanup_vloopback_module(void) { int i; info("Unregistering video4linux loopback devices"); for (i=0; i<nr_o_pipes; i++) if (loops[i]) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) kfree(((priv_ptr)video_get_drvdata(loops[i]->vloopin))); video_unregister_device(loops[i]->vloopin); kfree(((priv_ptr)video_get_drvdata(loops[i]->vloopout))); #else kfree(loops[i]->vloopin->priv); video_unregister_device(loops[i]->vloopin); kfree(loops[i]->vloopout->priv); #endif video_unregister_device(loops[i]->vloopout); if (loops[i]->buffer) rvfree(loops[i]->buffer, loops[i]->buflength*N_BUFFS); kfree(loops[i]->ioctldata); kfree(loops[i]->ioctlretdata); kfree(loops[i]); } }
void oprof_free_hashmap(void) { kfree(op_dname_stack); rvfree(hash_map, PAGE_ALIGN(OP_HASH_MAP_SIZE)); }
static int vloopback_mmap(struct file *f, struct vm_area_struct *vma) { struct video_device *loopdev=video_devdata(f); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) priv_ptr ptr=(priv_ptr)video_get_drvdata(loopdev); #else priv_ptr ptr=(priv_ptr)loopdev->priv; #endif int nr=ptr->pipenr; unsigned long start = (unsigned long)vma->vm_start; long size = vma->vm_end - vma->vm_start; unsigned long page, pos; down(&loops[nr]->lock); if (ptr->in) { loops[nr]->zerocopy=1; if (loops[nr]->ropen) { info("Can't change size while opened for read"); up(&loops[nr]->lock); return -EINVAL; } if (!size) { up(&loops[nr]->lock); return -EINVAL; } if (loops[nr]->buffer) rvfree(loops[nr]->buffer, loops[nr]->buflength*N_BUFFS); loops[nr]->buflength=size; loops[nr]->buffer=rvmalloc(loops[nr]->buflength*N_BUFFS); } if (loops[nr]->buffer == NULL) { up(&loops[nr]->lock); return -EINVAL; } if (size > (((N_BUFFS * loops[nr]->buflength) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) { up(&loops[nr]->lock); return -EINVAL; } pos = (unsigned long)loops[nr]->buffer; while (size > 0) { #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) page = kvirt_to_pa(pos); if (remap_page_range(vma,start, page, PAGE_SIZE, PAGE_SHARED)) { #else page = vmalloc_to_pfn((void *)pos); if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) { #endif up(&loops[nr]->lock); return -EAGAIN; } start += PAGE_SIZE; pos += PAGE_SIZE; size -= PAGE_SIZE; } up(&loops[nr]->lock); return 0; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) static long vloopback_ioctl(struct file *f, unsigned int cmd, unsigned long arg) #else static int vloopback_ioctl(struct inode *inod, struct file *f, unsigned int cmd, unsigned long arg) #endif { struct video_device *loopdev=video_devdata(f); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) priv_ptr ptr=(priv_ptr)video_get_drvdata(loopdev); #else priv_ptr ptr=(priv_ptr)loopdev->priv; #endif int nr=ptr->pipenr; int i; if (loops[nr]->zerocopy) { if (!ptr->in) { loops[nr]->ioctlnr=cmd; loops[nr]->ioctllength=_IOC_SIZE(cmd); /* info("DEBUG: vl_ioctl: !loop->in"); */ /* info("DEBUG: vl_ioctl: cmd %lu", cmd); */ /* info("DEBUG: vl_ioctl: len %lu", loops[nr]->ioctllength); */ if(copy_from_user(loops[nr]->ioctldata, (void*)arg, _IOC_SIZE(cmd))) return -EFAULT; kill_proc(loops[nr]->pid, SIGIO, 1); #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) wait_event_interruptible(loops[nr]->wait, loops[nr]->ioctlnr==-1); #else interruptible_sleep_on(&loops[nr]->wait); #endif if (loops[nr]->invalid_ioctl) { //info ("DEBUG: There was an invalid ioctl"); loops[nr]->invalid_ioctl = 0; return -ENOTTY; } if (cmd & IOC_IN && !(cmd & IOC_OUT)) { //info("DEBUG: vl_ioctl: cmd & IOC_IN 1"); if (memcmp(loops[nr]->ioctlretdata, loops[nr]->ioctldata, _IOC_SIZE(cmd))) { return -EINVAL; } //info("DEBUG: vl_ioctl: cmd & IOC_IN 2"); return 0; } else { if (copy_to_user((void*)arg, loops[nr]->ioctlretdata, _IOC_SIZE(cmd))) return -EFAULT; //info("DEBUG: vl_ioctl: !(cmd & IOC_IN) 1"); return 0; } } else { if ( (loops[nr]->ioctlnr!=cmd) && (cmd != (VIDIOCSINVALID))) { /* wrong ioctl */ info("DEBUG: vo_ioctl: Wrong IOCTL"); return 0; } if (cmd == VIDIOCSINVALID) { loops[nr]->invalid_ioctl = 1; } else { if (copy_from_user(loops[nr]->ioctlretdata, (void*)arg, loops[nr]->ioctllength)) return -EFAULT; } loops[nr]->ioctlnr=-1; if (waitqueue_active(&loops[nr]->wait)) wake_up(&loops[nr]->wait); return 0; } } switch(cmd) { /* Get capabilities */ case VIDIOCGCAP: { struct video_capability b; if (ptr->in) { sprintf(b.name, "Video loopback %d input", ptr->pipenr); b.type = 0; } else { sprintf(b.name, "Video loopback %d output", ptr->pipenr); b.type = VID_TYPE_CAPTURE; } b.channels=1; b.audios=0; b.maxwidth=loops[nr]->width; b.maxheight=loops[nr]->height; b.minwidth=20; b.minheight=20; if(copy_to_user((void*)arg, &b, sizeof(b))) return -EFAULT; return 0; } /* Get channel info (sources) */ case VIDIOCGCHAN: { struct video_channel v; if(copy_from_user(&v, (void*)arg, sizeof(v))) return -EFAULT; if(v.channel!=0) { info("VIDIOCGCHAN: Invalid Channel, was %d", v.channel); v.channel=0; //return -EINVAL; } v.flags=0; v.tuners=0; v.norm=0; v.type = VIDEO_TYPE_CAMERA; /*strcpy(v.name, "Loopback"); -- tibit */ strcpy(v.name, "Composite1"); if(copy_to_user((void*)arg, &v, sizeof(v))) return -EFAULT; return 0; } /* Set channel */ case VIDIOCSCHAN: { int v; if(copy_from_user(&v, (void*)arg, sizeof(v))) return -EFAULT; if(v!=0) { info("VIDIOCSCHAN: Invalid Channel, was %d", v); return -EINVAL; } return 0; } /* Get tuner abilities */ case VIDIOCGTUNER: { struct video_tuner v; if(copy_from_user(&v, (void*)arg, sizeof(v))!=0) return -EFAULT; if(v.tuner) { info("VIDIOCGTUNER: Invalid Tuner, was %d", v.tuner); return -EINVAL; } strcpy(v.name, "Format"); v.rangelow=0; v.rangehigh=0; v.flags=0; v.mode=VIDEO_MODE_AUTO; if(copy_to_user((void*)arg,&v, sizeof(v))!=0) return -EFAULT; return 0; } /* Get picture properties */ case VIDIOCGPICT: { struct video_picture p; p.colour=0x8000; p.hue=0x8000; p.brightness=0x8000; p.contrast=0x8000; p.whiteness=0x8000; p.depth=0x8000; p.palette=loops[nr]->palette; if(copy_to_user((void*)arg, &p, sizeof(p))) return -EFAULT; return 0; } /* Set picture properties */ case VIDIOCSPICT: { struct video_picture p; if(copy_from_user(&p, (void*)arg, sizeof(p))) return -EFAULT; if (!ptr->in) { if (p.palette!=loops[nr]->palette) return -EINVAL; } else loops[nr]->palette=p.palette; return 0; } /* Get the video overlay window */ case VIDIOCGWIN: { struct video_window vw; vw.x=0; vw.y=0; vw.width=loops[nr]->width; vw.height=loops[nr]->height; vw.chromakey=0; vw.flags=0; vw.clipcount=0; if(copy_to_user((void*)arg, &vw, sizeof(vw))) return -EFAULT; return 0; } /* Set the video overlay window - passes clip list for hardware smarts , chromakey etc */ case VIDIOCSWIN: { struct video_window vw; if(copy_from_user(&vw, (void*)arg, sizeof(vw))) return -EFAULT; if(vw.flags) return -EINVAL; if(vw.clipcount) return -EINVAL; if (loops[nr]->height==vw.height && loops[nr]->width==vw.width) return 0; if(!ptr->in) { return -EINVAL; } else { loops[nr]->height=vw.height; loops[nr]->width=vw.width; /* Make sure nobody is using the buffer while we fool around with it. We are also not allowing changes while somebody using mmap has the output open. */ down(&loops[nr]->lock); if (loops[nr]->ropen) { info("Can't change size while opened for read"); up(&loops[nr]->lock); return -EINVAL; } if (loops[nr]->buffer) rvfree(loops[nr]->buffer, loops[nr]->buflength*N_BUFFS); loops[nr]->buflength=vw.width*vw.height*4; loops[nr]->buffer=rvmalloc(loops[nr]->buflength*N_BUFFS); up(&loops[nr]->lock); } return 0; } /* Memory map buffer info */ case VIDIOCGMBUF: { struct video_mbuf vm; vm.size=loops[nr]->buflength*N_BUFFS; vm.frames=N_BUFFS; for (i=0; i<vm.frames; i++) vm.offsets[i]=i*loops[nr]->buflength; if(copy_to_user((void*)arg, &vm, sizeof(vm))) return -EFAULT; return 0; } /* Grab frames */ case VIDIOCMCAPTURE: { struct video_mmap vm; if (ptr->in) return -EINVAL; if (!loops[nr]->buffer) return -EINVAL; if (copy_from_user(&vm, (void*)arg, sizeof(vm))) return -EFAULT; if (vm.format!=loops[nr]->palette) return -EINVAL; if (vm.frame > N_BUFFS) return -EINVAL; return 0; } /* Sync with mmap grabbing */ case VIDIOCSYNC: { int frame; unsigned long fw; if (copy_from_user((void *)&frame, (void*)arg, sizeof(int))) return -EFAULT; if (ptr->in) return -EINVAL; if (!loops[nr]->buffer) return -EINVAL; /* Ok, everything should be alright since the program should have called VIDIOMCAPTURE and we are ready to do the 'capturing' */ if (frame > 1) return -EINVAL; loops[nr]->frame=frame; #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) fw = loops[nr]->frameswrite; wait_event_interruptible(loops[nr]->wait, fw!=loops[nr]->frameswrite); #else interruptible_sleep_on(&loops[nr]->wait); #endif if (!loops[nr]->buffer) /* possibly released during sleep */ return -EINVAL; loops[nr]->framesread++; return 0; } /* Get attached units */ case VIDIOCGUNIT: { struct video_unit vu; if (ptr->in) vu.video=loops[nr]->vloopout->minor; else vu.video=loops[nr]->vloopin->minor; vu.vbi=VIDEO_NO_UNIT; vu.radio=VIDEO_NO_UNIT; vu.audio=VIDEO_NO_UNIT; vu.teletext=VIDEO_NO_UNIT; if (copy_to_user((void*)arg, &vu, sizeof(vu))) return -EFAULT; return 0; } /* Get frame buffer */ case VIDIOCGFBUF: { struct video_buffer vb; memset(&vb, 0, sizeof(vb)); vb.base=NULL; if(copy_to_user((void *)arg, (void *)&vb, sizeof(vb))) return -EFAULT; return 0; } /* Start, end capture */ case VIDIOCCAPTURE: { int start; if (copy_from_user(&start, (void*)arg, sizeof(int))) return -EFAULT; /* if (start) info ("Capture started"); else info ("Capture stopped"); */ return 0; } case VIDIOCGFREQ: case VIDIOCSFREQ: case VIDIOCGAUDIO: case VIDIOCSAUDIO: return -EINVAL; case VIDIOCKEY: return 0; default: return -ENOTTY; //return -ENOIOCTLCMD; } return 0; } static unsigned int vloopback_poll(struct file *f, struct poll_table_struct *wait) { struct video_device *loopdev=video_devdata(f); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) priv_ptr ptr=(priv_ptr)video_get_drvdata(loopdev); #else priv_ptr ptr=(priv_ptr)loopdev->priv; #endif int nr=ptr->pipenr; if (loopdev==NULL) return -EFAULT; if (!ptr->in) return 0; if (loops[nr]->ioctlnr!=-1) { if (loops[nr]->zerocopy) { return (POLLIN | POLLPRI | POLLOUT | POLLRDNORM); } else { return (POLLOUT); } } return 0; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) static struct v4l2_file_operations fileops_template= #else static struct file_operations fileops_template= #endif { owner: THIS_MODULE, open: vloopback_open, release: vloopback_release, read: vloopback_read, write: vloopback_write, poll: vloopback_poll, ioctl: vloopback_ioctl, #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15) && defined(CONFIG_COMPAT) compat_ioctl: v4l_compat_ioctl32, #endif mmap: vloopback_mmap, };
static int qtft_fb_probe(struct platform_device * dev) { struct fb_info *info; int retval = -ENOMEM; func_in(); // 分配显存 if (!(videomemory = rvmalloc(videomemorysize))) return retval; memset(videomemory, 0, videomemorysize); // 动态分配 fb_info info = framebuffer_alloc((sizeof(u32)*16), &dev->dev); if (!info) goto err0; // 虚拟地址 info->screen_base = (char __iomem *)videomemory; info->screen_size = videomemorysize; // 文件操作符 qtft_fb_ops 在 ops.c 中定义 info->fbops = &qtft_fb_ops; info->var = qtft_fb_var_default; qtft_fb_fix_default.smem_start = (unsigned long) videomemory; qtft_fb_fix_default.smem_len = videomemorysize; info->fix = qtft_fb_fix_default; // 16色伪调色板指针指向了 info->par 的私有空间 info->pseudo_palette = info->par; info->par = NULL; info->flags = FBINFO_DEFAULT; // 为16色伪调色板分配内存 retval = fb_alloc_cmap(&info->cmap, 16, 0); if (retval < 0) goto err1; retval = register_framebuffer(info); if (retval < 0) goto err2; // 初始化 LCD 模块 retval = lcd_init(); if (retval < 0) goto err3; retval = lcd_hard_reset(); if (retval < 0) goto err3; retval = lcd_normal_config(); if (retval < 0) goto err3; lcd_address_set(0,0,(info->var).xres,(info->var).yres); // 将 info 指针存入平台设备私有数据 platform_set_drvdata(dev, info); printk(KERN_INFO "SPI QVGA TFT LCD driver: fb%d, %ldK video memory\n", info->node, videomemorysize >> 10); goto out; err3: unregister_framebuffer(info); err2: fb_dealloc_cmap(&info->cmap); err1: framebuffer_release(info); err0: rvfree(videomemory, videomemorysize); out: func_out(); return retval; }