#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/libkern.h>
#include <sys/fbio.h>
#include <dev/vt/colors/vt_termcolors.h>
static struct {
unsigned char r;
unsigned char g;
unsigned char b;
} color_def[NCOLORS] = {
{0, 0, 0},
{50, 0, 0},
{0, 50, 0},
{77, 63, 0},
{20, 40, 64},
{50, 0, 50},
{0, 50, 50},
{75, 75, 75},
{18, 20, 21},
{100, 0, 0},
{0, 100, 0},
{100, 100, 0},
{45, 62, 81},
{100, 0, 100},
{0, 100, 100},
{100, 100, 100},
};
static int
vt_parse_rgb_triplet(const char *rgb, unsigned char *r,
unsigned char *g, unsigned char *b)
{
unsigned long v;
const char *ptr;
char *endptr;
ptr = rgb;
if (*ptr == '#') {
if (strlen(ptr) != 7)
return (-1);
v = strtoul(ptr + 1, &endptr, 16);
if (*endptr != '\0')
return (-1);
*r = (v >> 16) & 0xff;
*g = (v >> 8) & 0xff;
*b = v & 0xff;
return (0);
}
v = strtoul(ptr, &endptr, 10);
if (ptr == endptr)
return (-1);
if (v > 255)
return (-1);
*r = v & 0xff;
ptr = endptr;
while (*ptr == ',' || *ptr == ' ')
ptr++;
v = strtoul(ptr, &endptr, 10);
if (ptr == endptr)
return (-1);
if (v > 255)
return (-1);
*g = v & 0xff;
ptr = endptr;
while (*ptr == ',' || *ptr == ' ')
ptr++;
v = strtoul(ptr, &endptr, 10);
if (ptr == endptr)
return (-1);
if (v > 255)
return (-1);
*b = v & 0xff;
ptr = endptr;
while (*ptr == ' ')
ptr++;
if (*ptr != 0)
return (-1);
return (0);
}
static void
vt_palette_init(void)
{
int i;
char rgb[32];
char tunable[32];
unsigned char r, g, b;
for (i = 0; i < NCOLORS; i++) {
snprintf(tunable, sizeof(tunable),
"kern.vt.color.%d.rgb", i);
if (TUNABLE_STR_FETCH(tunable, rgb, sizeof(rgb))) {
if (vt_parse_rgb_triplet(rgb, &r, &g, &b) == 0) {
color_def[i].r = r*100/255;
color_def[i].g = g*100/255;
color_def[i].b = b*100/255;
}
}
}
}
static int
vt_generate_cons_palette(uint32_t *palette, int format, uint32_t rmax,
int roffset, uint32_t gmax, int goffset, uint32_t bmax, int boffset)
{
int i;
switch (format) {
case COLOR_FORMAT_VGA:
for (i = 0; i < NCOLORS; i++)
palette[i] = cons_to_vga_colors[i];
break;
case COLOR_FORMAT_RGB:
vt_palette_init();
#define CF(_f, _i) ((_f ## max * color_def[(_i)]._f / 100) << _f ## offset)
for (i = 0; i < NCOLORS; i++)
palette[i] = CF(r, i) | CF(g, i) | CF(b, i);
#undef CF
break;
default:
return (ENODEV);
}
return (0);
}
int
vt_config_cons_colors(struct fb_info *info, int format, uint32_t rmax,
int roffset, uint32_t gmax, int goffset, uint32_t bmax, int boffset)
{
if (format == COLOR_FORMAT_RGB) {
info->fb_rgboffs.red = roffset;
info->fb_rgboffs.green = goffset;
info->fb_rgboffs.blue = boffset;
} else
memset(&info->fb_rgboffs, 0, sizeof(info->fb_rgboffs));
return (vt_generate_cons_palette(info->fb_cmap, format, rmax,
roffset, gmax, goffset, bmax, boffset));
}