* Allocates memory for a colormap @cmap. @len is the
* number of entries in the palette.
*
- * Returns -1 errno on error, or zero on success.
+ * Returns negative errno on error, or zero on success.
*
*/
}
cmap->start = 0;
cmap->len = len;
- fb_copy_cmap(fb_default_cmap(len), cmap, 0);
+ fb_copy_cmap(fb_default_cmap(len), cmap);
return 0;
fail:
fb_dealloc_cmap(cmap);
- return -1;
+ return -ENOMEM;
}
/**
* fb_copy_cmap - copy a colormap
* @from: frame buffer colormap structure
* @to: frame buffer colormap structure
- * @fsfromto: determine copy method
*
* Copy contents of colormap from @from to @to.
- *
- * @fsfromto accepts the following integer parameters:
- * 0: memcpy function
- * 1: copy_from_user() function to copy from userspace
- * 2: copy_to_user() function to copy to userspace
- *
*/
-int fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto)
+int fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to)
{
- int tooff = 0, fromoff = 0;
- int size;
-
- if (to->start > from->start)
- fromoff = to->start-from->start;
- else
- tooff = from->start-to->start;
- size = to->len-tooff;
- if (size > (int) (from->len - fromoff))
- size = from->len-fromoff;
- if (size <= 0)
- return -EINVAL;
- size *= sizeof(u16);
-
- switch (fsfromto) {
- case 0:
+ int tooff = 0, fromoff = 0;
+ int size;
+
+ if (to->start > from->start)
+ fromoff = to->start - from->start;
+ else
+ tooff = from->start - to->start;
+ size = to->len - tooff;
+ if (size > (int) (from->len - fromoff))
+ size = from->len - fromoff;
+ if (size <= 0)
+ return -EINVAL;
+ size *= sizeof(u16);
+
memcpy(to->red+tooff, from->red+fromoff, size);
memcpy(to->green+tooff, from->green+fromoff, size);
memcpy(to->blue+tooff, from->blue+fromoff, size);
if (from->transp && to->transp)
- memcpy(to->transp+tooff, from->transp+fromoff, size);
- break;
- case 1:
- if (copy_from_user(to->red+tooff, from->red+fromoff, size))
- return -EFAULT;
- if (copy_from_user(to->green+tooff, from->green+fromoff, size))
- return -EFAULT;
- if (copy_from_user(to->blue+tooff, from->blue+fromoff, size))
- return -EFAULT;
- if (from->transp && to->transp)
- if (copy_from_user(to->transp+tooff, from->transp+fromoff, size))
- return -EFAULT;
- break;
- case 2:
+ memcpy(to->transp+tooff, from->transp+fromoff, size);
+ return 0;
+}
+
+int fb_cmap_to_user(struct fb_cmap *from, struct fb_cmap_user *to)
+{
+ int tooff = 0, fromoff = 0;
+ int size;
+
+ if (to->start > from->start)
+ fromoff = to->start - from->start;
+ else
+ tooff = from->start - to->start;
+ size = to->len - tooff;
+ if (size > (int) (from->len - fromoff))
+ size = from->len - fromoff;
+ if (size <= 0)
+ return -EINVAL;
+ size *= sizeof(u16);
+
if (copy_to_user(to->red+tooff, from->red+fromoff, size))
return -EFAULT;
if (copy_to_user(to->green+tooff, from->green+fromoff, size))
if (from->transp && to->transp)
if (copy_to_user(to->transp+tooff, from->transp+fromoff, size))
return -EFAULT;
- break;
- }
- return 0;
+ return 0;
}
/**
* fb_set_cmap - set the colormap
* @cmap: frame buffer colormap structure
- * @kspc: boolean, 1 copy local, 0 get_user() function
* @info: frame buffer info structure
*
* Sets the colormap @cmap for a screen of device @info.
*
*/
-int fb_set_cmap(struct fb_cmap *cmap, int kspc, struct fb_info *info)
+int fb_set_cmap(struct fb_cmap *cmap, struct fb_info *info)
{
- int i, start;
- u16 *red, *green, *blue, *transp;
- u_int hred, hgreen, hblue, htransp;
-
- red = cmap->red;
- green = cmap->green;
- blue = cmap->blue;
- transp = cmap->transp;
- start = cmap->start;
-
- if (start < 0 || !info->fbops->fb_setcolreg)
- return -EINVAL;
- for (i = 0; i < cmap->len; i++) {
- if (kspc) {
- hred = *red;
- hgreen = *green;
- hblue = *blue;
- htransp = transp ? *transp : 0xffff;
+ int i, start, rc = 0;
+ u16 *red, *green, *blue, *transp;
+ u_int hred, hgreen, hblue, htransp = 0xffff;
+
+ red = cmap->red;
+ green = cmap->green;
+ blue = cmap->blue;
+ transp = cmap->transp;
+ start = cmap->start;
+
+ if (start < 0 || (!info->fbops->fb_setcolreg &&
+ !info->fbops->fb_setcmap))
+ return -EINVAL;
+ if (info->fbops->fb_setcmap) {
+ rc = info->fbops->fb_setcmap(cmap, info);
} else {
- get_user(hred, red);
- get_user(hgreen, green);
- get_user(hblue, blue);
- if (transp)
- get_user(htransp, transp);
- else
- htransp = 0xffff;
+ for (i = 0; i < cmap->len; i++) {
+ hred = *red++;
+ hgreen = *green++;
+ hblue = *blue++;
+ if (transp)
+ htransp = *transp++;
+ if (info->fbops->fb_setcolreg(start++,
+ hred, hgreen, hblue,
+ htransp, info))
+ break;
+ }
}
- red++;
- green++;
- blue++;
- if (transp)
- transp++;
- if (info->fbops->fb_setcolreg(start++, hred, hgreen, hblue, htransp, info))
- return 0;
- }
- return 0;
+ if (rc == 0)
+ fb_copy_cmap(cmap, &info->cmap);
+
+ return rc;
}
+int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *info)
+{
+ int rc, size = cmap->len * sizeof(u16);
+ struct fb_cmap umap;
+
+ if (cmap->start < 0 || (!info->fbops->fb_setcolreg &&
+ !info->fbops->fb_setcmap))
+ return -EINVAL;
+
+ memset(&umap, 0, sizeof(struct fb_cmap));
+ rc = fb_alloc_cmap(&umap, cmap->len, cmap->transp != NULL);
+ if (rc)
+ return rc;
+ if (copy_from_user(umap.red, cmap->red, size) ||
+ copy_from_user(umap.green, cmap->green, size) ||
+ copy_from_user(umap.blue, cmap->blue, size) ||
+ (cmap->transp && copy_from_user(umap.transp, cmap->transp, size))) {
+ fb_dealloc_cmap(&umap);
+ return -EFAULT;
+ }
+ umap.start = cmap->start;
+ rc = fb_set_cmap(&umap, info);
+ fb_dealloc_cmap(&umap);
+ return rc;
+}
/**
* fb_default_cmap - get default colormap