Hands-on Projects for the Linux Graphics Subsystem
|
The second part of the parsing process cover at the point the first part ended, which is the part of xf86HandleConfigFile() after the comment:
* now we convert part of the information contained in the parser * structures into our own structures. * The important part here is to figure out which Screen Sections * in the XF86Config file are active so that we can piece together * the modes that we need later down the road. * And while we are at it, we'll decode the rest of the stuff as well |
Before this we have to discuss more thoroughly the Serverlayout Section of the xorg.conf.
ServerLayout sectionFrom DESIGN document we read:
From xorg.conf man page we read:
|
The parsing process of the previous section fills the global XF86ConfigRec with the info xorg.conf provides and the Table 1 of the previous section illustrates how some fields of XF86ConfigRec are filled. Before we proceed we focus in the XF86ConfLayoutPtr field that will be used in the current section. As we find in Table 1 function xf86parseLayoutSection() collects info from xorg.conf to a XF86ConfLayoutPtr pointer.
XF86ConfLayoutRec, which points to XF86ConfLayoutRec is defined in xf86Parser.h as:
typedef struct { GenericListRec list; char *lay_identifier; XF86ConfAdjacencyPtr lay_adjacency_lst; XF86ConfInactivePtr lay_inactive_lst; XF86ConfInputrefPtr lay_input_lst; XF86OptionPtr lay_option_lst; char *lay_comment; } XF86ConfLayoutRec, *XF86ConfLayoutPtr; |
xf86parseLayoutSection()In the images below we follow this example. This implies the presence of two screens (XF86ConfScreenRec) and the two corresponding devices (XF86ConfDeviceRec):
|
We continue then at the next step in xf86HandleConfigFile():
/* First check if a layout section is present, and if it is valid. */ if (xf86configptr->conf_layout_lst == NULL || xf86ScreenName != NULL) { if (xf86ScreenName == NULL) { xf86Msg(X_WARNING, "No Layout section. Using the first Screen section.\n"); } if (!configImpliedLayout(&xf86ConfigLayout, xf86configptr->conf_screen_lst)) { xf86Msg(X_ERROR, "Unable to determine the screen layout\n"); return CONFIG_PARSE_ERROR; } |
xf86ConfigLayout defined in xf86Globals.c is the data structure that is used at this point to represent the Layout section information. It collects the information parsed by xorg.conf and stored previously in the XF86ConfLayoutPtr field of the global XF86ConfigRec. This process is done in configLayout() (or in configImpliedLayout()).
serverLayoutRec xf86ConfigLayout = {NULL, }; |
where serverLayoutRec is defined in xf86str.h as:
typedef struct _serverlayoutrec { char * id; screenLayoutPtr screens; GDevPtr inactives; IDevPtr inputs; pointer options; } serverLayoutRec, *serverLayoutPtr; |
xf86ScreenName is initially NULL. The command line option "-screen", if there is one, provides to this variable a value by calling ddxProcessArgument(), which processes command line options. Along with the following variable - command line options it is defined in xf86Globals.c:
char *xf86LayoutName = NULL; char *xf86ScreenName = NULL; char *xf86PointerName = NULL; char *xf86KeyboardName = NULL; |
Those variables represent values for the Layout, Screen, Pointer and Keyboard respectively that were passed to the X Server as command line arguments.
configImpliedLayout()
configImpliedLayout() is used in the case that there is no layout section. It looks first for a "-screen" command line option and in this case xf86findScreen() is used to lookup the screen given from the command line from the conf_screen_lst list of the global XF86ConfigRec. If no command line argument is passed to the X Server configImpliedLayout() tries to find the first Screen section and sets it as the only active screen. This requires that xorg.conf provided a screen section (i.e. conf_screen <> NULL). In this case configImpliedLayout() allocates a struct confScreenRec for the first field of the screenLayoutRec (slp[0].screen) and fills it by calling configScreen() as:
configScreen(slp[0].screen, conf_screen, 0, from)
Next we continue with xf86HandleConfigFile() at the point of the source code where the previous example applies, that is no configImpliedLayout(), since there is a "ServerLayout" section. Therefore configLayout() is called:
} else { if (xf86configptr->conf_flags != NULL) { char *dfltlayout = NULL; pointer optlist = xf86configptr->conf_flags->flg_option_lst; if (optlist && xf86FindOption(optlist, "defaultserverlayout")) dfltlayout = xf86SetStrOption(optlist, "defaultserverlayout", NULL); if (!configLayout(&xf86ConfigLayout, xf86configptr->conf_layout_lst, dfltlayout)) { xf86Msg(X_ERROR, "Unable to determine the screen layout\n"); return CONFIG_PARSE_ERROR; } } else { if (!configLayout(&xf86ConfigLayout, xf86configptr->conf_layout_lst, NULL)) { xf86Msg(X_ERROR, "Unable to determine the screen layout\n"); return CONFIG_PARSE_ERROR; } } } |
configLayout() is implemented as:
configLayout()
configLayout() searches for the active layout section in xorg.conf. From the DESIGN document we read: "A ServerLayout section can be made active by being referenced on the command line. In the absence of this, a default will be chosen (the first one found)." If a layout is passed as command line argument (and therefore variable xf86LayoutName is non-NULL) xf86findLayout() is called to lookup the argument at the conf_layout conf_layout_lst list of the global XF86ConfigRec and conf_layout points to this otherwise it points to the first node of the list. A screenLayoutRec is allocated and is filled with the approptriate number of confScreenRec according to the screen number of the ServerLayout section. Next the conf_layout->lay_adjacency_lst is examined to find the number of screen references in the ServerLayout section. For each reference a confScreenRec is allocated.
|
configLayout() fills the serverLayoutRec that the serverLayoutPtr of its first argument points to. It uses the layout info from the parsed xorg.conf file stored in conf_layout (the second argument of configLayout) which is actually the XF86ConfLayoutPtr field of the global struct XF86ConfigRec.
For each screen found in conf_layout->lay_adjacency_lst function configScreen() is called as:
configScreen(slp[count].screen, adjp->adj_screen, scrnum, X_CONFIG)) |
where slp is allocated by configLayout() and is of type screenLayoutRec:
typedef struct _screenlayoutrec { confScreenPtr screen; char * topname; confScreenPtr top; char * bottomname; confScreenPtr bottom; char * leftname; confScreenPtr left; char * rightname; confScreenPtr right; PositionType where; int x; int y; char * refname; confScreenPtr refscreen; } screenLayoutRec, *screenLayoutPtr; |
Therefore slp[count].screen is of type confScreenPtr, which is defined as:
====================================================================== THIS STRUCT IA PASSED AS ARGUMENT AND IS FILLED IN configScreen() ====================================================================== typedef struct _confscreenrec { char * id; int screennum; int defaultdepth; int defaultbpp; int defaultfbbpp; MonPtr monitor; GDevPtr device; int numdisplays; DispPtr displays; int numxvadaptors; confXvAdaptorPtr xvadaptors; pointer options; } confScreenRec, *confScreenPtr; |
GDevPtr is defined in xf86str.h as:
=============================================================================== THIS STRUCT IS PASSED AS ARGUMENT AND IS FILLED IN configDevice() =============================================================================== typedef struct { char * identifier; char * vendor; char * board; char * chipset; char * ramdac; char * driver; struct _confscreenrec * myScreenSection; Bool claimed; int dacSpeeds[MAXDACSPEEDS]; int numclocks; int clock[MAXCLOCKS]; char * clockchip; char * busID; Bool active; Bool inUse; int videoRam; int textClockFreq; unsigned long BiosBase; /* Base address of video BIOS */ unsigned long MemBase; /* Frame buffer base address */ unsigned long IOBase; int chipID; int chipRev; pointer options; int irq; int screen; /* For multi-CRTC cards */ } GDevRec, *GDevPtr; |
================================================================================ THIS STRUCT IS PASSED AS ARGUMENT AND IS FILLED IN configLayout() ================================================================================ Notice: the previous three yellow boxed structures along with the serverLayoutRec, are the basic structures that are formed in this section from the parsed xorg.conf file, which is represented here by the XF86ConfLayoutRec (see images at the top of page). typedef struct _serverlayoutrec { char * id; screenLayoutPtr screens; GDevPtr inactives; IDevPtr inputs; pointer options; } serverLayoutRec, *serverLayoutPtr; =============================================================================== serverLayoutPtr is filled in the following lines of configLayout(): servlayoutp->id = conf_layout->lay_identifier; servlayoutp->screens = slp; servlayoutp->inactives = gdp; servlayoutp->inputs = indp; servlayoutp->options = conf_layout->lay_option_lst; =============================================================================== |
configScreen()
configScreen() fills the confScreenRec fields with the values taken from all nodes of
conf_layout->lay_adjacency_lst->adj_screen:
static Bool configScreen(confScreenPtr screenp, XF86ConfScreenPtr conf_screen, int scrnum, MessageType from) { int count = 0; XF86ConfDisplayPtr dispptr; XF86ConfAdaptorLinkPtr conf_adaptor; Bool defaultMonitor = FALSE; xf86Msg(from, "|-->Screen \"%s\" (%d)\n", conf_screen->scrn_identifier, scrnum); /* * now we fill in the elements of the screen */ screenp->id = conf_screen->scrn_identifier; screenp->screennum = scrnum; screenp->defaultdepth = conf_screen->scrn_defaultdepth; screenp->defaultbpp = conf_screen->scrn_defaultbpp; screenp->defaultfbbpp = conf_screen->scrn_defaultfbbpp; screenp->monitor = xnfcalloc(1, sizeof(MonRec)); /* If no monitor is specified, create a default one. */ if (!conf_screen->scrn_monitor) { XF86ConfMonitorRec defMon; bzero(&defMon, sizeof(defMon)); defMon.mon_identifier = " |
configDevice() creates a device (pointer GDevPtr) from conf_device, the config info of xorg.conf. As mentioned in the boxed comment previously conf_device is created by xf86parseDeviceSection(). configDevice() is implemented as:
static Bool configDevice(GDevPtr devicep, XF86ConfDevicePtr conf_device, Bool active) { int i; if (active) xf86Msg(X_CONFIG, "| |-->Device \"%s\"\n", conf_device->dev_identifier); else xf86Msg(X_CONFIG, "|-->Inactive Device \"%s\"\n", conf_device->dev_identifier); devicep->identifier = conf_device->dev_identifier; devicep->vendor = conf_device->dev_vendor; devicep->board = conf_device->dev_board; devicep->chipset = conf_device->dev_chipset; devicep->ramdac = conf_device->dev_ramdac; devicep->driver = conf_device->dev_driver; devicep->active = active; devicep->videoRam = conf_device->dev_videoram; devicep->BiosBase = conf_device->dev_bios_base; devicep->MemBase = conf_device->dev_mem_base; devicep->IOBase = conf_device->dev_io_base; devicep->clockchip = conf_device->dev_clockchip; devicep->busID = conf_device->dev_busid; devicep->textClockFreq = conf_device->dev_textclockfreq; devicep->chipID = conf_device->dev_chipid; devicep->chipRev = conf_device->dev_chiprev; devicep->options = conf_device->dev_option_lst; devicep->irq = conf_device->dev_irq; devicep->screen = conf_device->dev_screen; for (i = 0; i < MAXDACSPEEDS; i++) { if (i < CONF_MAXDACSPEEDS) devicep->dacSpeeds[i] = conf_device->dev_dacSpeeds[i]; else devicep->dacSpeeds[i] = 0; } devicep->numclocks = conf_device->dev_clocks; if (devicep->numclocks > MAXCLOCKS) devicep->numclocks = MAXCLOCKS; for (i = 0; i < devicep->numclocks; i++) { devicep->clock[i] = conf_device->dev_clock[i]; } devicep->claimed = FALSE; return TRUE; } |
We make a case study here for the device field of screenp, since this will provide the dev struct for the sections that follow.
Consider the screenp->device field. This is filled by configDevice() using the value of the second argument From Table 1 is indicated also that xf86parseDeviceSection returns info for the device section at a XF86ConfDevicePtr.
|
configLayout() calls configInput() as:
configInput(&indp[count], irp->iref_inputdev, X_CONFIG)) |
configInput() adds a new IDevRec struct in indp[] (the first argument). The second argument is
conf_layout->lay_input_lst->iref_inputdev. Therefore the values are copied from conf_layout to the current IDevRec. conf_layout was filled by xf86parseLayoutSection (see section 3.2.2.1). Since we take as example the mouse input device we examine here the code of this routine for the case INPUTDEVICE:
case INPUTDEVICE: { XF86ConfInputrefPtr iptr; iptr = xf86confcalloc (1, sizeof (XF86ConfInputrefRec)); iptr->list.next = NULL; iptr->iref_option_lst = NULL; if (xf86getSubToken (&(ptr->lay_comment)) != STRING) Error (INPUTDEV_MSG, NULL); iptr->iref_inputdev_str = val.str; while ((token = xf86getSubToken (&(ptr->lay_comment))) == STRING) { iptr->iref_option_lst = xf86addNewOption (iptr->iref_option_lst, val.str, NULL); } xf86unGetToken (token); ptr->lay_input_lst = (XF86ConfInputrefPtr) xf86addListItem ((glp) ptr->lay_input_lst, (glp) iptr); } break; |
configInput() is implemented in xf86Config.c as:
static Bool configInput(IDevPtr inputp, XF86ConfInputPtr conf_input, MessageType from) { xf86Msg(from, "|-->Input Device \"%s\"\n", conf_input->inp_identifier); inputp->identifier = conf_input->inp_identifier; inputp->driver = conf_input->inp_driver; inputp->commonOptions = conf_input->inp_option_lst; inputp->extraOptions = NULL; /* XXX This is required until the keyboard driver is converted */ if (!xf86NameCmp(inputp->driver, "keyboard")) return configInputKbd(inputp); return TRUE; } |
The result of this will be examined latter in section 3.2.3. At this section the following xorg.conf is used:
Section "ServerLayout" Identifier "single head configuration" Screen 0 "Screen0" 0 0 InputDevice "Keyboard0" "CoreKeyboard" InputDevice "Synaptics" "CorePointer" InputDevice "Mouse0" "AlwaysCore" EndSection . . . Section "InputDevice" Identifier "Mouse0" Driver "mouse" Option "Device" "/dev/input/mice" Option "Protocol" "IMPS/2" Option "ZAxisMapping" "4 5" # Scrollwheel support Option "Emulate3Buttons" "yes" # L+R buttons count as middle EndSection |
From the source of xf86parseLayoutSection() we see that the XF86ConfInputrefPtr for the mouse has the fields provided by Inputedevice Mouse0. Therefore the copied values to the IDevPtr at configInput() become:
inputp->identifier: "Mouse0"
inputp->driver: "mouse"
inputp->commonOptions: "Device" "/dev/input/mice"
, "Protocol" "IMPS/2"
, "ZAxisMapping" "4 5", "Emulate3Buttons" "yes"