in graphics/pdcurs34/nuttx/pdcscrn.c [419:687]
int PDC_scr_open(int argc, char **argv)
{
#ifdef CONFIG_PDCURSES_MULTITHREAD
FAR struct pdc_context_s *ctx = PDC_ctx();
#endif
#ifdef CONFIG_SYSTEM_TERMCURSES
FAR char *env_display;
#endif
FAR struct pdc_fbscreen_s *fbscreen;
FAR const struct nx_font_s *fontset;
FAR struct pdc_fbstate_s *fbstate;
struct fb_videoinfo_s vinfo;
struct fb_planeinfo_s pinfo;
int ret;
int i;
PDC_LOG(("PDC_scr_open() - called\n"));
#ifdef CONFIG_SYSTEM_TERMCURSES
/* When termcurses is compiled in, we must allow opening terminal
* type screens also. Check if the DISPLAY environment variable is
* set to ":0" indicating we should open the graphic screen.
*/
env_display = getenv("DISPLAY");
if (!env_display || strcmp(env_display, ":0") != 0)
{
/* Perform terminal open operation */
return PDC_scr_open_term(argc, argv);
}
#endif
/* Allocate the global instance of SP */
fbscreen =
(FAR struct pdc_fbscreen_s *)zalloc(sizeof(struct pdc_fbscreen_s));
if (fbscreen == NULL)
{
PDC_LOG(("ERROR: Failed to allocate SP\n"));
return ERR;
}
SP = &fbscreen->screen;
fbstate = &fbscreen->fbstate;
#ifdef CONFIG_SYSTEM_TERMCURSES
graphic_screen = true;
#endif
/* Number of RGB colors/greyscale levels. This is the same as the
* dimension of rgbcolor[] or greylevel[]).
*/
COLORS = 16;
/* Setup initial RGB colors */
for (i = 0; i < 8; i++)
{
#ifdef PDCURSES_MONOCHROME
uint8_t greylevel;
greylevel = (i & COLOR_RED) ? 0x40 : 0;
greylevel += (i & COLOR_GREEN) ? 0x40 : 0;
greylevel += (i & COLOR_BLUE) ? 0x40 : 0;
fbstate->greylevel[i] = greylevel;
fbstate->greylevel[i + 8] = greylevel | 0x3f;
#else
fbstate->rgbcolor[i].red = (i & COLOR_RED) ? 0xc0 : 0;
fbstate->rgbcolor[i].green = (i & COLOR_GREEN) ? 0xc0 : 0;
fbstate->rgbcolor[i].blue = (i & COLOR_BLUE) ? 0xc0 : 0;
fbstate->rgbcolor[i + 8].red = (i & COLOR_RED) ? 0xff : 0x40;
fbstate->rgbcolor[i + 8].green = (i & COLOR_GREEN) ? 0xff : 0x40;
fbstate->rgbcolor[i + 8].blue = (i & COLOR_BLUE) ? 0xff : 0x40;
#endif
}
/* Open the framebuffer driver */
fbstate->fbfd = open(CONFIG_PDCURSES_FBDEV, O_RDWR);
if (fbstate->fbfd < 0)
{
PDC_LOG(("ERROR: Failed to open %s: %d\n",
CONFIG_PDCURSES_FBDEV, errno));
goto errout_with_sp;
}
/* Get the characteristics of the framebuffer */
ret = ioctl(fbstate->fbfd, FBIOGET_VIDEOINFO,
(unsigned long)((uintptr_t)&vinfo));
if (ret < 0)
{
PDC_LOG(("ERROR: ioctl(FBIOGET_VIDEOINFO) failed: %d\n", errno));
goto errout_with_fbfd;
}
PDC_LOG(("VideoInfo:\n"));
PDC_LOG((" fmt: %u\n", vinfo.fmt));
PDC_LOG((" xres: %u\n", vinfo.xres));
PDC_LOG((" yres: %u\n", vinfo.yres));
PDC_LOG((" nplanes: %u\n", vinfo.nplanes));
fbstate->xres = vinfo.xres; /* Horizontal resolution in pixel columns */
fbstate->yres = vinfo.yres; /* Vertical resolution in pixel rows */
/* Only one color format supported. */
if (vinfo.fmt != PDCURSES_COLORFMT)
{
PDC_LOG(("ERROR: color format=%u not supported\n", vinfo.fmt));
goto errout_with_fbfd;
}
#ifdef PDCURSES_MONOCHROME
/* Remember if we are using a monochrome framebuffer */
SP->mono = true;
#endif
/* Get characteristics of the color plane */
ret = ioctl(fbstate->fbfd, FBIOGET_PLANEINFO,
(unsigned long)((uintptr_t)&pinfo));
if (ret < 0)
{
PDC_LOG(("ERROR: ioctl(FBIOGET_PLANEINFO) failed: %d\n", errno));
goto errout_with_fbfd;
}
PDC_LOG(("PlaneInfo (plane 0):\n"));
PDC_LOG((" fbmem: %p\n", pinfo.fbmem));
PDC_LOG((" fblen: %lu\n", (unsigned long)pinfo.fblen));
PDC_LOG((" stride: %u\n", pinfo.stride));
PDC_LOG((" display: %u\n", pinfo.display));
PDC_LOG((" bpp: %u\n", pinfo.bpp));
fbstate->stride = pinfo.stride; /* Length of a line in bytes */
/* Only one pixel depth is supported. */
if (pinfo.bpp != PDCURSES_BPP)
{
PDC_LOG(("ERROR: bpp=%u not supported\n", pinfo.bpp));
goto errout_with_fbfd;
}
/* mmap() the framebuffer.
*
* NOTE: In the FLAT build the frame buffer address returned by the
* FBIOGET_PLANEINFO IOCTL command will be the same as the framebuffer
* address. mmap(), however, is the preferred way to get the framebuffer
* address because in the KERNEL build, it will perform the necessary
* address mapping to make the memory accessible to the application.
*/
fbstate->fbmem = mmap(NULL, pinfo.fblen, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_FILE, fbstate->fbfd, 0);
if (fbstate->fbmem == MAP_FAILED)
{
PDC_LOG(("ERROR: ioctl(FBIOGET_PLANEINFO) failed: %d\n", errno));
goto errout_with_fbfd;
}
PDC_LOG(("Mapped FB: %p\n", fbstate->fbmem));
/* Get the handle for the selected font */
fbstate->hfont = nxf_getfonthandle(PDCURSES_FONTID);
if (fbstate->hfont == NULL)
{
PDC_LOG(("ERROR: Failed to get font handle: %d\n", errno));
goto errout_with_fbfd;
}
#ifdef HAVE_BOLD_FONT
/* Get the handle for the matching bold font. It is assume that the
* geometry of the bold font is exactly the same as the geometry of
* the "normal" font.
*/
fbstate->hbold = nxf_getfonthandle(PDCURSES_BOLD_FONTID);
if (fbstate->hbold == NULL)
{
PDC_LOG(("ERROR: Failed to get font handle: %d\n", errno));
goto errout_with_font;
}
#endif
/* Get information about the fontset */
fontset = nxf_getfontset(fbstate->hfont);
if (fontset == NULL)
{
PDC_LOG(("ERROR: Failed to get font handle: %d\n", errno));
goto errout_with_boldfont;
}
PDC_LOG(("Fontset (ID=%d):\n", PDCURSES_FONTID));
PDC_LOG((" mxheight: %u\n", fontset->mxheight));
PDC_LOG((" mxwidth: %u\n", fontset->mxwidth));
PDC_LOG((" mxbits: %u\n", fontset->mxbits));
PDC_LOG((" spwidth: %u\n", fontset->spwidth));
fbstate->fheight = fontset->mxheight;
fbstate->fwidth = fontset->mxwidth;
#if PDCURSES_BPP < 8
/* Allocate the font buffer for < 8-bit display */
fbstate->fstride =
(fbstate->fwidth + PDCURSES_PPB_MASK) >> PDCURSES_PPB_SHIFT;
fbstate->fbuffer = (FAR uint8_t *)
malloc(fbstate->fstride * fbstate->fheight);
if (fbstate->fbuffer == NULL)
{
PDC_LOG(("ERROR: Failed to allocate fstride: %d\n", errno));
goto errout_with_boldfont;
}
#endif
/* Calculate the drawable region */
SP->lines = fbstate->yres / fbstate->fheight;
SP->cols = fbstate->xres / fbstate->fwidth;
fbstate->hoffset = (fbstate->xres - fbstate->fwidth * SP->cols) / 2;
fbstate->voffset = (fbstate->yres - fbstate->fheight * SP->lines) / 2;
/* Set the framebuffer to a known state */
PDC_clear_screen(fbstate);
#ifdef CONFIG_PDCURSES_HAVE_INPUT
/* Open and configure any input devices */
ret = PDC_input_open(fbstate);
if (ret == ERR)
{
goto errout_with_fbuffer;
}
#endif
return OK;
#ifdef CONFIG_PDCURSES_HAVE_INPUT
errout_with_fbuffer:
#if PDCURSES_BPP < 8
free(fbstate->fbuffer);
#endif
#endif
errout_with_boldfont:
#ifdef HAVE_BOLD_FONT
errout_with_font:
#endif
errout_with_fbfd:
close(fbstate->fbfd);
fbstate->fbfd = -1;
errout_with_sp:
free(SP);
SP = NULL;
return ERR;
}