fbmem.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,399 行 · 第 1/3 页
C
1,399 行
kfree(palette); if (saved_pseudo_palette != NULL) info->pseudo_palette = saved_pseudo_palette; if (logo_new != NULL) kfree(logo_new); return fb_logo.logo->height;}#elseint fb_prepare_logo(struct fb_info *info) { return 0; }int fb_show_logo(struct fb_info *info) { return 0; }#endif /* CONFIG_LOGO */static int fbmem_read_proc(char *buf, char **start, off_t offset, int len, int *eof, void *private){ struct fb_info **fi; int clen; clen = 0; for (fi = registered_fb; fi < ®istered_fb[FB_MAX] && len < 4000; fi++) if (*fi) clen += sprintf(buf + clen, "%d %s\n", (*fi)->node, (*fi)->fix.id); *start = buf + offset; if (clen > offset) clen -= offset; else clen = 0; return clen < len ? clen : len;}static ssize_tfb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos){ unsigned long p = *ppos; struct inode *inode = file->f_dentry->d_inode; int fbidx = iminor(inode); struct fb_info *info = registered_fb[fbidx]; u32 *buffer, *dst, *src; int c, i, cnt = 0, err = 0; unsigned long total_size; if (!info || ! info->screen_base) return -ENODEV; if (info->state != FBINFO_STATE_RUNNING) return -EPERM; if (info->fbops->fb_read) return info->fbops->fb_read(file, buf, count, ppos); total_size = info->screen_size; if (total_size == 0) total_size = info->fix.smem_len; if (p >= total_size) return 0; if (count >= total_size) count = total_size; if (count + p > total_size) count = total_size - p; cnt = 0; buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL); if (!buffer) return -ENOMEM; src = (u32 *) (info->screen_base + p); if (info->fbops->fb_sync) info->fbops->fb_sync(info); while (count) { c = (count > PAGE_SIZE) ? PAGE_SIZE : count; dst = buffer; for (i = c >> 2; i--; ) *dst++ = fb_readl(src++); if (c & 3) { u8 *dst8 = (u8 *) dst; u8 *src8 = (u8 *) src; for (i = c & 3; i--;) *dst8++ = fb_readb(src8++); src = (u32 *) src8; } if (copy_to_user(buf, buffer, c)) { err = -EFAULT; break; } *ppos += c; buf += c; cnt += c; count -= c; } kfree(buffer); return (err) ? err : cnt;}static ssize_tfb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos){ unsigned long p = *ppos; struct inode *inode = file->f_dentry->d_inode; int fbidx = iminor(inode); struct fb_info *info = registered_fb[fbidx]; u32 *buffer, *dst, *src; int c, i, cnt = 0, err; unsigned long total_size; if (!info || !info->screen_base) return -ENODEV; if (info->state != FBINFO_STATE_RUNNING) return -EPERM; if (info->fbops->fb_write) return info->fbops->fb_write(file, buf, count, ppos); total_size = info->screen_size; if (total_size == 0) total_size = info->fix.smem_len; if (p > total_size) return -ENOSPC; if (count >= total_size) count = total_size; err = 0; if (count + p > total_size) { count = total_size - p; err = -ENOSPC; } cnt = 0; buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL); if (!buffer) return -ENOMEM; dst = (u32 *) (info->screen_base + p); if (info->fbops->fb_sync) info->fbops->fb_sync(info); while (count) { c = (count > PAGE_SIZE) ? PAGE_SIZE : count; src = buffer; if (copy_from_user(src, buf, c)) { err = -EFAULT; break; } for (i = c >> 2; i--; ) fb_writel(*src++, dst++); if (c & 3) { u8 *src8 = (u8 *) src; u8 *dst8 = (u8 *) dst; for (i = c & 3; i--; ) fb_writeb(*src8++, dst8++); dst = (u32 *) dst8; } *ppos += c; buf += c; cnt += c; count -= c; } kfree(buffer); return (err) ? err : cnt;}#ifdef CONFIG_KMODstatic void try_to_load(int fb){ request_module("fb%d", fb);}#endif /* CONFIG_KMOD */voidfb_load_cursor_image(struct fb_info *info){ unsigned int width = (info->cursor.image.width + 7) >> 3; u8 *data = (u8 *) info->cursor.image.data; if (info->sprite.outbuf) info->sprite.outbuf(info, info->sprite.addr, data, width); else memcpy(info->sprite.addr, data, width);}intfb_cursor(struct fb_info *info, struct fb_cursor_user __user *sprite){ struct fb_cursor_user cursor_user; struct fb_cursor cursor; char *data = NULL, *mask = NULL, *info_mask = NULL; u16 *red = NULL, *green = NULL, *blue = NULL, *transp = NULL; int err = -EINVAL; if (copy_from_user(&cursor_user, sprite, sizeof(struct fb_cursor_user))) return -EFAULT; memcpy(&cursor, &cursor_user, sizeof(cursor_user)); cursor.mask = info->cursor.mask; cursor.image.data = info->cursor.image.data; cursor.image.cmap.red = info->cursor.image.cmap.red; cursor.image.cmap.green = info->cursor.image.cmap.green; cursor.image.cmap.blue = info->cursor.image.cmap.blue; cursor.image.cmap.transp = info->cursor.image.cmap.transp; cursor.data = NULL; if (cursor.set & FB_CUR_SETCUR) info->cursor.enable = 1; if (cursor.set & FB_CUR_SETCMAP) { unsigned len = cursor.image.cmap.len; if ((int)len <= 0) goto out; len *= 2; err = -ENOMEM; red = kmalloc(len, GFP_USER); green = kmalloc(len, GFP_USER); blue = kmalloc(len, GFP_USER); if (!red || !green || !blue) goto out; if (cursor_user.image.cmap.transp) { transp = kmalloc(len, GFP_USER); if (!transp) goto out; } err = -EFAULT; if (copy_from_user(red, cursor_user.image.cmap.red, len)) goto out; if (copy_from_user(green, cursor_user.image.cmap.green, len)) goto out; if (copy_from_user(blue, cursor_user.image.cmap.blue, len)) goto out; if (transp) { if (copy_from_user(transp, cursor_user.image.cmap.transp, len)) goto out; } cursor.image.cmap.red = red; cursor.image.cmap.green = green; cursor.image.cmap.blue = blue; cursor.image.cmap.transp = transp; } if (cursor.set & FB_CUR_SETSHAPE) { int size = ((cursor.image.width + 7) >> 3) * cursor.image.height; if ((cursor.image.height != info->cursor.image.height) || (cursor.image.width != info->cursor.image.width)) cursor.set |= FB_CUR_SETSIZE; err = -ENOMEM; data = kmalloc(size, GFP_USER); mask = kmalloc(size, GFP_USER); if (!mask || !data) goto out; err = -EFAULT; if (copy_from_user(data, cursor_user.image.data, size) || copy_from_user(mask, cursor_user.mask, size)) goto out; cursor.image.data = data; cursor.mask = mask; info_mask = (char *) info->cursor.mask; info->cursor.mask = mask; } info->cursor.set = cursor.set; info->cursor.rop = cursor.rop; err = info->fbops->fb_cursor(info, &cursor);out: kfree(data); kfree(mask); kfree(red); kfree(green); kfree(blue); kfree(transp); if (info_mask) info->cursor.mask = info_mask; return err;}intfb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var){ int xoffset = var->xoffset; int yoffset = var->yoffset; int err; if (xoffset < 0 || yoffset < 0 || !info->fbops->fb_pan_display || xoffset + info->var.xres > info->var.xres_virtual || yoffset + info->var.yres > info->var.yres_virtual) return -EINVAL; if ((err = info->fbops->fb_pan_display(var, info))) return err; info->var.xoffset = var->xoffset; info->var.yoffset = var->yoffset; if (var->vmode & FB_VMODE_YWRAP) info->var.vmode |= FB_VMODE_YWRAP; else info->var.vmode &= ~FB_VMODE_YWRAP; return 0;}intfb_set_var(struct fb_info *info, struct fb_var_screeninfo *var){ int err; if (var->activate & FB_ACTIVATE_INV_MODE) { struct fb_videomode mode1, mode2; int ret = 0; fb_var_to_videomode(&mode1, var); fb_var_to_videomode(&mode2, &info->var); /* make sure we don't delete the videomode of current var */ ret = fb_mode_is_equal(&mode1, &mode2); if (!ret) { struct fb_event event; event.info = info; event.data = &mode1; ret = notifier_call_chain(&fb_notifier_list, FB_EVENT_MODE_DELETE, &event); } if (!ret) fb_delete_videomode(&mode1, &info->modelist); return ret; } if ((var->activate & FB_ACTIVATE_FORCE) || memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) { if (!info->fbops->fb_check_var) { *var = info->var; return 0; } if ((err = info->fbops->fb_check_var(var, info))) return err; if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { struct fb_videomode mode; info->var = *var; if (info->fbops->fb_set_par) info->fbops->fb_set_par(info); fb_pan_display(info, &info->var); fb_set_cmap(&info->cmap, info); fb_var_to_videomode(&mode, &info->var); fb_add_videomode(&mode, &info->modelist); if (info->flags & FBINFO_MISC_MODECHANGEUSER) { struct fb_event event; info->flags &= ~FBINFO_MISC_MODECHANGEUSER; event.info = info; notifier_call_chain(&fb_notifier_list, FB_EVENT_MODE_CHANGE, &event); } } } return 0;}intfb_blank(struct fb_info *info, int blank){ /* ??? Variable sized stack allocation. */ u16 black[info->cmap.len]; struct fb_cmap cmap; if (info->fbops->fb_blank && !info->fbops->fb_blank(blank, info)) return 0; if (blank) { memset(black, 0, info->cmap.len * sizeof(u16)); cmap.red = cmap.green = cmap.blue = black; cmap.transp = info->cmap.transp ? black : NULL; cmap.start = info->cmap.start; cmap.len = info->cmap.len; } else cmap = info->cmap; return fb_set_cmap(&cmap, info);}static int fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ int fbidx = iminor(inode); struct fb_info *info = registered_fb[fbidx]; struct fb_ops *fb = info->fbops; struct fb_var_screeninfo var; struct fb_fix_screeninfo fix; struct fb_con2fbmap con2fb; struct fb_cmap_user cmap; struct fb_event event; void __user *argp = (void __user *)arg; int i; if (!fb) return -ENODEV; switch (cmd) { case FBIOGET_VSCREENINFO: return copy_to_user(argp, &info->var, sizeof(var)) ? -EFAULT : 0; case FBIOPUT_VSCREENINFO: if (copy_from_user(&var, argp, sizeof(var))) return -EFAULT; acquire_console_sem(); info->flags |= FBINFO_MISC_MODECHANGEUSER; i = fb_set_var(info, &var); info->flags &= ~FBINFO_MISC_MODECHANGEUSER; release_console_sem(); if (i) return i; if (copy_to_user(argp, &var, sizeof(var))) return -EFAULT; return 0; case FBIOGET_FSCREENINFO: return copy_to_user(argp, &info->fix, sizeof(fix)) ? -EFAULT : 0; case FBIOPUTCMAP: if (copy_from_user(&cmap, argp, sizeof(cmap))) return -EFAULT; return (fb_set_user_cmap(&cmap, info)); case FBIOGETCMAP: if (copy_from_user(&cmap, argp, sizeof(cmap))) return -EFAULT; return fb_cmap_to_user(&info->cmap, &cmap); case FBIOPAN_DISPLAY: if (copy_from_user(&var, argp, sizeof(var))) return -EFAULT; acquire_console_sem(); i = fb_pan_display(info, &var); release_console_sem(); if (i) return i; if (copy_to_user(argp, &var, sizeof(var))) return -EFAULT; return 0; case FBIO_CURSOR: acquire_console_sem(); i = fb_cursor(info, argp); release_console_sem(); return i; case FBIOGET_CON2FBMAP: if (copy_from_user(&con2fb, argp, sizeof(con2fb))) return -EFAULT; if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) return -EINVAL; con2fb.framebuffer = -1; event.info = info; event.data = &con2fb; notifier_call_chain(&fb_notifier_list,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?