[RFC 2/3] xfree86: Introduce OutputClass configuration

Aaron Plattner aplattner at nvidia.com
Thu Feb 13 08:50:35 PST 2014


On 02/13/14 05:22, Thierry Reding wrote:
> The OutputClass section provides a way to match output devices to a set
> of given attributes and configure them. For now, only matching by kernel
> driver name is supported. This can be used to determine what DDX module
> to load for non-PCI output devices. DDX modules can ship an xorg.conf.d
> snippet (e.g. in /usr/share/X11/xorg.conf.d) that looks like this:
>
>          Section "OutputClass"
>              Identifer "NVIDIA Tegra open-source driver"
>              MatchDriver "tegra"
>              Driver "opentegra"
>          EndSection
>
> This will cause any device that's driven by the kernel driver named
> "tegra" to use the "opentegra" DDX module.
>
> See the OUTPUTCLASS section in xorg.conf(5) for more details.
>
> Signed-off-by: Thierry Reding <treding at nvidia.com>
> ---
>   hw/xfree86/man/xorg.conf.man    |  74 ++++++++++++++++++
>   hw/xfree86/parser/Makefile.am   |   1 +
>   hw/xfree86/parser/OutputClass.c | 167 ++++++++++++++++++++++++++++++++++++++++
>   hw/xfree86/parser/configProcs.h |   5 ++
>   hw/xfree86/parser/read.c        |   6 ++
>   hw/xfree86/parser/write.c       |   2 +
>   hw/xfree86/parser/xf86Parser.h  |   9 +++
>   7 files changed, 264 insertions(+)
>   create mode 100644 hw/xfree86/parser/OutputClass.c
>
> diff --git a/hw/xfree86/man/xorg.conf.man b/hw/xfree86/man/xorg.conf.man
> index 85f9f2ee1331..0db87bb31404 100644
> --- a/hw/xfree86/man/xorg.conf.man
> +++ b/hw/xfree86/man/xorg.conf.man
> @@ -171,6 +171,7 @@ The section names are:
>   .BR "Extensions     " "Extension enabling"
>   .BR "InputDevice    " "Input device description"
>   .BR "InputClass     " "Input class description"
> +.BR "OutputClass    " "Output class description"
>   .BR "Device         " "Graphics device description"
>   .BR "VideoAdaptor   " "Xv video adaptor description"
>   .BR "Monitor        " "Monitor description"
> @@ -1186,6 +1187,79 @@ entries.
>   This optional entry specifies that the device should be ignored entirely,
>   and not added to the server. This can be useful when the device is handled
>   by another program and no X events should be generated.
> +.SH "OUTPUTCLASS SECTION"
> +The config file may have multiple
> +.B OutputClass
> +sections.
> +These sections are optional and are used to provide configuration for a
> +class of output devices as they are automatically added. An output device can

I think technically, sentences in ROFF syntax should start on their own 
lines.

> +match more than one
> +.B OutputClass
> +section. Each class can override settings from a previous class, so it is
> +best to arrange the sections with the most generic matches first.
> +.PP
> +.B OutputClass
> +sections have the following format:
> +.PP
> +.RS 4
> +.nf
> +.B  "Section \*qOutputClass\*q"
> +.BI "    Identifier  \*q" name \*q
> +.I  "    entries"
> +.I  "    ..."
> +.B  "EndSection"
> +.fi
> +.RE
> +.PP
> +The
> +.B Identifier
> +entry is required in all
> +.B OutputClass
> +sections.
> +All other entries are optional.
> +.PP
> +The
> +.B Identifier
> +entry specifies the unique name for this output class.
> +The
> +.B Driver
> +entry specifies the name of the driver to use for this input device.

s/input/output/ here.

> +After all classes have been examined, the
> +.RI \*q outputdriver \*q
> +module from the first
> +.B Driver
> +entry will be enabled when using the loadable server.
> +.PP
> +When an output device is automatically added, its characteristics are
> +checked against all
> +.B OutputClass
> +sections. Each section can contain optional entries to narrow the match
> +of the class. If none of the optional entries appear, the
> +.B OutputClass
> +section is generic and will match any input device. If more than one of

also here.

> +these entries appear, they all must match for the configuration to apply.
> +.PP
> +The following list of tokens can be matched against attributes of the device.
> +An entry can be constructed to match attributes from different devices by
> +separating arguments with a '|' character.
> +.PP
> +For example:
> +.PP
> +.RS 4
> +.nf
> +.B  "Section \*qOutputClass\*q"
> +.B  "    Identifier   \*qMy Class\*q"
> +.B  "    # kernel driver must be either foo or bar
> +.B  "    MatchDriver \*qfoo|bar\*q
> +.I  "    ..."
> +.B  "EndSection"
> +.fi
> +.RE
> +.TP 7
> +.BI "MatchDriver \*q" matchdriver \*q
> +Check the case-sensitive string
> +.RI \*q matchdriver \*q
> +against the kernel driver of the device.
>   .SH "DEVICE SECTION"
>   The config file may have multiple
>   .B Device
> diff --git a/hw/xfree86/parser/Makefile.am b/hw/xfree86/parser/Makefile.am
> index 3bf62e8af6a5..4d0bb4fd8e01 100644
> --- a/hw/xfree86/parser/Makefile.am
> +++ b/hw/xfree86/parser/Makefile.am
> @@ -14,6 +14,7 @@ INTERNAL_SOURCES= \
>          Flags.c \
>          Input.c \
>          InputClass.c \
> +       OutputClass.c \
>          Layout.c \
>          Module.c \
>          Video.c \
> diff --git a/hw/xfree86/parser/OutputClass.c b/hw/xfree86/parser/OutputClass.c
> new file mode 100644
> index 000000000000..7e9a8ac1a8c0
> --- /dev/null
> +++ b/hw/xfree86/parser/OutputClass.c
> @@ -0,0 +1,167 @@
> +/*
> + * Copyright (c) 2014 NVIDIA Corporation. All rights reserved.
> + *
> + * Permission is hereby granted, free of charge, to any person
> + * obtaining a copy of this software and associated documentation
> + * files (the "Software"), to deal in the Software without
> + * restriction, including without limitation the rights to use,
> + * copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following
> + * conditions:
> + *
> + * The above copyright notice and this permission notice shall be
> + * included in all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
> + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
> + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
> + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + * OTHER DEALINGS IN THE SOFTWARE.
> + */
> +
> +#ifdef HAVE_XORG_CONFIG_H
> +#include <xorg-config.h>
> +#endif
> +
> +#include "os.h"
> +#include "xf86Parser.h"
> +#include "xf86tokens.h"
> +#include "Configint.h"
> +
> +static
> +xf86ConfigSymTabRec OutputClassTab[] = {
> +    {ENDSECTION, "endsection"},
> +    {IDENTIFIER, "identifier"},
> +    {DRIVER, "driver"},
> +    {MATCH_DRIVER, "matchdriver"},
> +    {-1, ""},
> +};
> +
> +#define CLEANUP xf86freeOutputClassList
> +
> +#define TOKEN_SEP "|"
> +
> +static void
> +add_group_entry(struct xorg_list *head, char **values)
> +{
> +    xf86MatchGroup *group;
> +
> +    group = malloc(sizeof(*group));
> +    if (group) {
> +        group->values = values;
> +        xorg_list_add(&group->entry, head);
> +    }
> +}
> +
> +XF86ConfOutputClassPtr
> +xf86parseOutputClassSection(void)
> +{
> +    int has_ident = FALSE;
> +    int token;
> +
> +    parsePrologue(XF86ConfOutputClassPtr, XF86ConfOutputClassRec)
> +
> +    /* Initialize MatchGroup lists */
> +    xorg_list_init(&ptr->match_driver);
> +
> +    while ((token = xf86getToken(OutputClassTab)) != ENDSECTION) {
> +        switch (token) {
> +        case COMMENT:
> +            ptr->comment = xf86addComment(ptr->comment, xf86_lex_val.str);
> +            break;
> +        case IDENTIFIER:
> +            if (xf86getSubToken(&(ptr->comment)) != STRING)
> +                Error(QUOTE_MSG, "Identifier");
> +            if (has_ident == TRUE)
> +                Error(MULTIPLE_MSG, "Identifier");
> +            ptr->identifier = xf86_lex_val.str;
> +            has_ident = TRUE;
> +            break;
> +        case DRIVER:
> +            if (xf86getSubToken(&(ptr->comment)) != STRING)
> +                Error(QUOTE_MSG, "Driver");
> +            else
> +                ptr->driver = xf86_lex_val.str;
> +            break;
> +        case MATCH_DRIVER:
> +            if (xf86getSubToken(&(ptr->comment)) != STRING)
> +                Error(QUOTE_MSG, "MatchDriver");
> +            add_group_entry(&ptr->match_driver,
> +                            xstrtokenize(xf86_lex_val.str, TOKEN_SEP));
> +            free(xf86_lex_val.str);
> +            break;
> +        case EOF_TOKEN:
> +            Error(UNEXPECTED_EOF_MSG);
> +            break;
> +        default:
> +            Error(INVALID_KEYWORD_MSG, xf86tokenString());
> +            break;
> +        }
> +    }
> +
> +    if (!has_ident)
> +        Error(NO_IDENT_MSG);
> +
> +#ifdef DEBUG
> +    printf("OutputClass section parsed\n");
> +#endif
> +
> +    return ptr;
> +}
> +void
> +xf86printOutputClassSection(FILE * cf, XF86ConfOutputClassPtr ptr)
> +{
> +    const xf86MatchGroup *group;
> +    char *const *cur;
> +
> +    while (ptr) {
> +        fprintf(cf, "Section \"OutputClass\"\n");
> +        if (ptr->comment)
> +            fprintf(cf, "%s", ptr->comment);
> +        if (ptr->identifier)
> +            fprintf(cf, "\tIdentifier      \"%s\"\n", ptr->identifier);
> +        if (ptr->driver)
> +            fprintf(cf, "\tDriver          \"%s\"\n", ptr->driver);
> +
> +        xorg_list_for_each_entry(group, &ptr->match_driver, entry) {
> +            fprintf(cf, "\tMatchDriver     \"");
> +            for (cur = group->values; *cur; cur++)
> +                fprintf(cf, "%s%s", cur == group->values ? "" : TOKEN_SEP,
> +                        *cur);
> +            fprintf(cf, "\"\n");
> +        }
> +
> +        fprintf(cf, "EndSection\n\n");
> +        ptr = ptr->list.next;
> +    }
> +}
> +
> +void
> +xf86freeOutputClassList(XF86ConfOutputClassPtr ptr)
> +{
> +    XF86ConfOutputClassPtr prev;
> +
> +    while (ptr) {
> +        xf86MatchGroup *group, *next;
> +        char **list;
> +
> +        TestFree(ptr->identifier);
> +        TestFree(ptr->comment);
> +        TestFree(ptr->driver);
> +
> +        xorg_list_for_each_entry_safe(group, next, &ptr->match_driver, entry) {
> +            xorg_list_del(&group->entry);
> +            for (list = group->values; *list; list++)
> +                free(*list);
> +            free(group);
> +        }
> +
> +        prev = ptr;
> +        ptr = ptr->list.next;
> +        free(prev);
> +    }
> +}
> diff --git a/hw/xfree86/parser/configProcs.h b/hw/xfree86/parser/configProcs.h
> index 60509dcd8552..774e2a2da0b0 100644
> --- a/hw/xfree86/parser/configProcs.h
> +++ b/hw/xfree86/parser/configProcs.h
> @@ -57,6 +57,11 @@ XF86ConfInputClassPtr xf86parseInputClassSection(void);
>   void xf86printInputClassSection(FILE * f, XF86ConfInputClassPtr ptr);
>   void xf86freeInputClassList(XF86ConfInputClassPtr ptr);
>
> +/* OutputClass.c */
> +XF86ConfOutputClassPtr xf86parseOutputClassSection(void);
> +void xf86printOutputClassSection(FILE * f, XF86ConfOutputClassPtr ptr);
> +void xf86freeOutputClassList(XF86ConfOutputClassPtr ptr);
> +
>   /* Layout.c */
>   XF86ConfLayoutPtr xf86parseLayoutSection(void);
>   void xf86printLayoutSection(FILE * cf, XF86ConfLayoutPtr ptr);
> diff --git a/hw/xfree86/parser/read.c b/hw/xfree86/parser/read.c
> index 2478b074b4ac..22f6e6af4d00 100644
> --- a/hw/xfree86/parser/read.c
> +++ b/hw/xfree86/parser/read.c
> @@ -165,6 +165,12 @@ xf86readConfigFile(void)
>                   HANDLE_LIST(conf_inputclass_lst,
>                               xf86parseInputClassSection, XF86ConfInputClassPtr);
>               }
> +            else if (xf86nameCompare(xf86_lex_val.str, "outputclass") == 0) {
> +                free(xf86_lex_val.str);
> +                xf86_lex_val.str = NULL;
> +                HANDLE_LIST(conf_outputclass_lst, xf86parseOutputClassSection,
> +                            XF86ConfOutputClassPtr);
> +            }
>               else if (xf86nameCompare(xf86_lex_val.str, "module") == 0) {
>                   free(xf86_lex_val.str);
>                   xf86_lex_val.str = NULL;
> diff --git a/hw/xfree86/parser/write.c b/hw/xfree86/parser/write.c
> index 26739b933087..472b27ba1b5b 100644
> --- a/hw/xfree86/parser/write.c
> +++ b/hw/xfree86/parser/write.c
> @@ -114,6 +114,8 @@ doWriteConfigFile(const char *filename, XF86ConfigPtr cptr)
>
>       xf86printInputClassSection(cf, cptr->conf_inputclass_lst);
>
> +    xf86printOutputClassSection(cf, cptr->conf_outputclass_lst);
> +
>       xf86printVideoAdaptorSection(cf, cptr->conf_videoadaptor_lst);
>
>       xf86printModesSection(cf, cptr->conf_modes_lst);
> diff --git a/hw/xfree86/parser/xf86Parser.h b/hw/xfree86/parser/xf86Parser.h
> index 8f855ac098ff..3a425c52bb7a 100644
> --- a/hw/xfree86/parser/xf86Parser.h
> +++ b/hw/xfree86/parser/xf86Parser.h
> @@ -325,6 +325,14 @@ typedef struct {
>       char *comment;
>   } XF86ConfInputClassRec, *XF86ConfInputClassPtr;
>
> +typedef struct {
> +    GenericListRec list;
> +    char *identifier;
> +    char *driver;
> +    struct xorg_list match_driver;
> +    char *comment;
> +} XF86ConfOutputClassRec, *XF86ConfOutputClassPtr;
> +
>   /* Values for adj_where */
>   #define CONF_ADJ_OBSOLETE      -1
>   #define CONF_ADJ_ABSOLUTE      0
> @@ -408,6 +416,7 @@ typedef struct {
>       XF86ConfScreenPtr conf_screen_lst;
>       XF86ConfInputPtr conf_input_lst;
>       XF86ConfInputClassPtr conf_inputclass_lst;
> +    XF86ConfOutputClassPtr conf_outputclass_lst;
>       XF86ConfLayoutPtr conf_layout_lst;
>       XF86ConfVendorPtr conf_vendor_lst;
>       XF86ConfDRIPtr conf_dri;
> --
> 1.8.4.2



More information about the xorg-devel mailing list